diff --git a/shader/DirectionLight.frag b/shader/DirectionLight.frag index b8afdf4..5485e9d 100644 --- a/shader/DirectionLight.frag +++ b/shader/DirectionLight.frag @@ -27,7 +27,6 @@ layout(binding=1) uniform ColorMaterial vec4 ambient; } color_material; - layout(binding=2) uniform Sun { vec3 direction; diff --git a/shader/pbr_DirectionLight.frag b/shader/pbr_DirectionLight.frag new file mode 100644 index 0000000..5383734 --- /dev/null +++ b/shader/pbr_DirectionLight.frag @@ -0,0 +1,117 @@ +#version 450 core + +layout(location=0) in vec3 FragmentWorldPos; +layout(location=1) in vec3 FragmentWorldNormal; + +layout(location=0) out vec4 FragColor; + +layout(binding=10) uniform WorldMatrix // hgl/math/Math.h +{ + mat4 ortho; + + mat4 projection; + mat4 inverse_projection; + + mat4 modelview; + mat4 inverse_modelview; + + mat4 mvp; + mat4 inverse_mvp; + + vec4 camera_pos; + vec2 canvas_resolution; + vec2 viewport_resolution; +}fs_world; + +layout(binding=1) uniform PBRMaterial +{ + vec4 color; + float metallic; + float roughness; +} pbr_material; + +layout(binding=2) uniform Sun +{ + vec3 direction; +}sun; + +const float PI = 3.14159265359; + +// Normal Distribution function -------------------------------------- +float D_GGX(float dotNH, float roughness) +{ + float alpha = roughness * roughness; + float alpha2 = alpha * alpha; + float denom = dotNH * dotNH * (alpha2 - 1.0) + 1.0; + return (alpha2)/(PI * denom*denom); +} + +// Geometric Shadowing function -------------------------------------- +float G_SchlicksmithGGX(float dotNL, float dotNV, float roughness) +{ + float r = (roughness + 1.0); + float k = (r*r) / 8.0; + float GL = dotNL / (dotNL * (1.0 - k) + k); + float GV = dotNV / (dotNV * (1.0 - k) + k); + return GL * GV; +} + +// Fresnel function ---------------------------------------------------- +vec3 F_Schlick(float cosTheta, float metallic) +{ + vec3 F0 = mix(vec3(0.04), pbr_material.color.rgb, metallic); // * material.specular + vec3 F = F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0); + return F; +} + +// Specular BRDF composition -------------------------------------------- + +vec3 BRDF(vec3 L, vec3 V, vec3 N, float metallic, float roughness) +{ + // Precalculate vectors and dot products + vec3 H = normalize (V + L); + float dotNV = clamp(dot(N, V), 0.0, 1.0); + float dotNL = clamp(dot(N, L), 0.0, 1.0); + float dotLH = clamp(dot(L, H), 0.0, 1.0); + float dotNH = clamp(dot(N, H), 0.0, 1.0); + + // Light color fixed + vec3 lightColor = vec3(1.0); + + vec3 color = vec3(0.0); + + if (dotNL > 0.0) + { + float rroughness = max(0.05, roughness); + // D = Normal distribution (Distribution of the microfacets) + float D = D_GGX(dotNH, roughness); + // G = Geometric shadowing term (Microfacets shadowing) + float G = G_SchlicksmithGGX(dotNL, dotNV, roughness); + // F = Fresnel factor (Reflectance depending on angle of incidence) + vec3 F = F_Schlick(dotNV, metallic); + + vec3 spec = D * F * G / (4.0 * dotNL * dotNV); + + color += spec * dotNL * lightColor; + } + + return color; +} + +// ---------------------------------------------------------------------------- +void main() +{ + vec3 N = normalize(FragmentWorldNormal); + vec3 V = normalize(fs_world.camera_pos.xyz - FragmentWorldPos); + + // Specular contribution + vec3 Lo = BRDF(sun.direction, V, N, pbr_material.metallic, pbr_material.roughness); + + // Combine with ambient + vec3 color = (pbr_material.color.rgb * 0.02)+Lo; + + // Gamma correct + color = pow(color, vec3(0.4545)); + + FragColor = vec4(color, 1.0); +} diff --git a/shader/pbr_Light.vert b/shader/pbr_Light.vert new file mode 100644 index 0000000..15964fc --- /dev/null +++ b/shader/pbr_Light.vert @@ -0,0 +1,37 @@ +#version 450 + +layout(location = 0) in vec3 Vertex; +layout(location = 1) in vec3 Normal; + +layout(binding=0) uniform WorldMatrix // hgl/math/Math.h +{ + mat4 ortho; + + mat4 projection; + mat4 inverse_projection; + + mat4 modelview; + mat4 inverse_modelview; + + mat4 mvp; + mat4 inverse_mvp; + + vec4 view_pos; + vec2 canvas_resolution; + vec2 viewport_resolution; +}world; + +layout(push_constant) uniform Consts { + mat4 local_to_world; +}pc; + +layout(location=0) out vec3 FragmentWorldPos; +layout(location=1) out vec3 FragmentWorldNormal; + +void main() +{ + FragmentWorldPos = Vertex*mat3(pc.local_to_world); + FragmentWorldNormal = Normal*mat3(pc.local_to_world); + + gl_Position = vec4(FragmentWorldPos,1.0)*world.mvp; +}