From c1673e5bc73734d7b8ba6f5fa69b48015c8eccec Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Sun, 20 Jun 2021 16:52:15 +0200 Subject: [PATCH] [#82] Add specular cook-torrance --- .../resources/shaders/shader.frag | 63 +++++++++++++++++-- projects/voxelization/src/main.cpp | 9 ++- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/projects/voxelization/resources/shaders/shader.frag b/projects/voxelization/resources/shaders/shader.frag index 24f4673b..445caea8 100644 --- a/projects/voxelization/resources/shaders/shader.frag +++ b/projects/voxelization/resources/shaders/shader.frag @@ -19,13 +19,50 @@ layout(set=0, binding=0) uniform sunBuffer { layout(set=0, binding=1) uniform texture2D shadowMap; layout(set=0, binding=2) uniform sampler shadowMapSampler; +layout(set=0, binding=3) uniform cameraBuffer { + vec3 cameraPos; +}; + +const float pi = 3.1415; + +vec3 lambertBRDF(vec3 albedo){ + return albedo / pi; +} + +vec3 fresnelSchlick(float cosTheta, vec3 f0){ + return f0 + (vec3(1) - f0) * pow(1 - cosTheta, 5); +} + +float GGXDistribution(float r, float NoH){ + float r2 = r * r; + float denom = pi * pow(NoH * NoH * (r2 - 1) + 1, 2); + return r2 / max(denom, 0.000001); +} + +float GGXSmithShadowingPart(float r, float cosTheta){ + float nom = cosTheta * 2; + float r2 = r * r; + float denom = cosTheta + sqrt(r2 + (1 - r2) * cosTheta * cosTheta); + return nom / max(denom, 0.000001); +} + +float GGXSmithShadowing(float r, float NoV, float NoL){ + return GGXSmithShadowingPart(r, NoV) * GGXSmithShadowingPart(r, NoL); +} + void main() { vec3 albedoTexel = texture(sampler2D(albedoTexture, textureSampler), passUV).rgb; vec3 normalTexel = texture(sampler2D(normalTexture, textureSampler), passUV).rgb; vec3 specularTexel = texture(sampler2D(specularTexture, textureSampler), passUV).rgb; - vec3 albedo = albedoTexel; + float r = specularTexel.g; + r *= r; // remapping roughness for perceptual linearity + + float metal = specularTexel.b; + vec3 albedo = mix(albedoTexel, vec3(0), metal); + vec3 f0_dielectric = vec3(0.04f); + vec3 f0 = mix(f0_dielectric, albedo, metal); vec3 T = normalize(passTangent.xyz); vec3 N_geo = normalize(passNormal); @@ -33,9 +70,27 @@ void main() { mat3 TBN = mat3(T, B, N_geo); normalTexel = normalTexel * 2 - 1; - vec3 N = TBN * normalTexel; - vec3 sun = lightInfo.sunStrength * lightInfo.sunColor * clamp(dot(N, lightInfo.L), 0, 1); + vec3 N = TBN * normalTexel; + vec3 L = lightInfo.L; + vec3 V = normalize(cameraPos - passPos); + vec3 H = normalize(L + V); + + float NoH = clamp(dot(N, H), 0, 1); + float NoL = clamp(dot(N, L), 0, 1); + float NoV = clamp(dot(N, V), 0, 1); + + vec3 F = fresnelSchlick(NoH, f0); + float D = GGXDistribution(r, NoH); + float G = GGXSmithShadowing(r, NoV, NoL); + vec3 specular = (F * D * G) / max(4 * NoV * NoL, 0.000001); + + vec3 sun = lightInfo.sunStrength * lightInfo.sunColor * NoL; sun *= shadowTest(passPos, lightInfo, shadowMap, shadowMapSampler); vec3 ambient = vec3(0.05); - outColor = albedo * (sun + ambient); + + vec3 F_in = fresnelSchlick(NoL, f0); + vec3 F_out = fresnelSchlick(NoV, f0); + vec3 diffuse = lambertBRDF(albedo) * (1 - F_in) * (1 - F_out); + + outColor = (diffuse + specular) * sun + lambertBRDF(albedo) * ambient; } \ No newline at end of file diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index 33b6cc20..281faaf1 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -159,7 +159,7 @@ int main(int argc, const char** argv) { glm::vec3 direction; float padding; glm::vec3 sunColor = glm::vec3(1.f); - float sunStrength = 8.f; + float sunStrength = 15.f; glm::mat4 lightMatrix; }; LightInfo lightInfo; @@ -168,8 +168,12 @@ int main(int argc, const char** argv) { vkcv::DescriptorSetHandle forwardShadingDescriptorSet = core.createDescriptorSet({ forwardProgram.getReflectedDescriptors()[0] }); + vkcv::Buffer<glm::vec3> cameraPosBuffer = core.createBuffer<glm::vec3>(vkcv::BufferType::UNIFORM, 1); + vkcv::DescriptorWrites forwardDescriptorWrites; - forwardDescriptorWrites.uniformBufferWrites = { vkcv::UniformBufferDescriptorWrite(0, lightBuffer.getHandle()) }; + forwardDescriptorWrites.uniformBufferWrites = { + vkcv::UniformBufferDescriptorWrite(0, lightBuffer.getHandle()), + vkcv::UniformBufferDescriptorWrite(3, cameraPosBuffer.getHandle()) }; forwardDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(1, shadowMap.getHandle()) }; forwardDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(2, shadowSampler) }; core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites); @@ -393,6 +397,7 @@ int main(int argc, const char** argv) { start = end; cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); + cameraPosBuffer.fill({ cameraManager.getActiveCamera().getPosition() }); glm::vec2 lightAngleRadian = glm::radians(lightAngles); lightInfo.direction = glm::normalize(glm::vec3( -- GitLab