#version 460 #extension GL_GOOGLE_include_directive : require #include "bindless.glsl" #include "scene_data.glsl" #include "mesh_pcs.glsl" #include "lighting.glsl" layout (location = 0) in vec3 inPos; layout (location = 1) in vec2 inUV; layout (location = 2) in vec3 inNormal; layout (location = 3) in vec4 inTangent; layout (location = 4) in mat3 inTBN; layout (location = 0) out vec4 outFragColor; void main() { MaterialData material = pcs.sceneData.materials.data[pcs.materialID]; uint samplerID = pcs.sceneData.materials.data[pcs.materialID].textureFilteringMode; vec4 diffuse = sampleTexture2D(material.diffuseTex, samplerID, inUV) * material.baseColor; vec3 baseColor = diffuse.rgb; // if (diffuse.a < 0.1) { // discard; // } vec3 normal = normalize(inNormal); // if (inTangent != vec4(0.0)) { // // FIXME: sometimes Blender doesn't export tangents for some objects // // for some reason. When we will start computing tangents manually, // // this check can be removed // normal = sampleTexture2DLinear(material.normalTex, inUV).rgb; // // normal.y = 1 - normal.y; // flip to make OpenGL normal maps work // normal = inTBN * normalize(normal * 2.0 - 1.0); // normal = normalize(normal); // } float metallicF = material.metallicRoughnessEmissive.r; float roughnessF = material.metallicRoughnessEmissive.g; vec4 metallicRoughness = sampleTexture2DLinear(material.metallicRoughnessTex, inUV); float roughness = roughnessF * metallicRoughness.g; // roughness *= roughness; // from perceptual to linear roughness = max(roughness, 1e-2); // 0.0 roughness leads to NaNs float metallic = metallicF * metallicRoughness.b; vec3 dielectricSpecular = vec3(0.04); vec3 black = vec3(0.0); vec3 diffuseColor = mix(baseColor * (1.0 - dielectricSpecular.r), black, metallic); vec3 f0 = mix(dielectricSpecular, baseColor, metallic); vec3 cameraPos = pcs.sceneData.cameraPos.xyz; vec3 fragPos = inPos.xyz; vec3 n = normal; vec3 v = normalize(cameraPos - fragPos); // forward+: only loop over the lights the culling pass put in this pixel's tile uvec2 tileID = uvec2(gl_FragCoord.xy) / LIGHT_TILE_SIZE; uint tileOffset = (tileID.y * pcs.sceneData.tileCountX + tileID.x) * LIGHT_TILE_STRIDE; uint tileLightCount = pcs.sceneData.tileLightIndices.data[tileOffset]; vec3 fragColor = vec3(0.0); for (uint i = 0; i < tileLightCount; i++) { uint lightIndex = pcs.sceneData.tileLightIndices.data[tileOffset + 1 + i]; Light light = pcs.sceneData.lights.data[lightIndex]; fragColor += calculateLight(light, fragPos, n, v, diffuseColor, roughness, metallic, f0); } // emissive float emissiveF = material.metallicRoughnessEmissive.b; vec3 emissiveColor = emissiveF * sampleTexture2DLinear(material.emissiveTex, inUV).rgb; fragColor += emissiveColor; // ambient fragColor += baseColor * pcs.sceneData.ambientColor * pcs.sceneData.ambientIntensity; if (pcs.sceneData.debugLightHeatmap != 0) { fragColor = mix(fragColor, lightHeatmapColor(tileLightCount), 0.5); } #if 0 // TANGENT DEBUG if (inTangent == vec4(0.0)) { fragColor = vec3(1.0f, 0.0f, 0.0f); } #endif #if 0 // NORMAL DEBUG fragColor = normal; #endif outFragColor = vec4(fragColor, diffuse.a); }