diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag index 8d5bf0d..6995f34 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag +++ b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag @@ -1,14 +1,93 @@ #version 450 -layout(location = 0) in vec3 fragColor; +layout(location = 0) in vec3 fragWorldPos; layout(location = 1) in vec3 fragNormal; +layout(location = 2) in vec3 fragAlbedo; + layout(location = 0) out vec4 outColor; -void main() { +const vec3 LIGHT_DIR = normalize(vec3(0.5, 0.8, 0.3)); +const vec3 LIGHT_COLOR = vec3(1.0, 0.95, 0.85); +const vec3 AMBIENT = vec3(0.15, 0.18, 0.22); + +const float PI = 3.14159265359; + +float distributionGGX(vec3 N, vec3 H, float roughness) +{ + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; + float num = a2; + float denom = NdotH2 * (a2 - 1.0) + 1.0; + denom = PI * denom * denom; + return num / denom; +} + +float geometrySchlickGGX(float NdotV, float roughness) +{ + float r = roughness + 1.0; + float k = (r * r) / 8.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +float geometrySmith(vec3 N, vec3 V, vec3 L, float roughness) +{ + float NdotV = max(dot(N, V), 0.0); + float NdotL = max(dot(N, L), 0.0); + float ggx2 = geometrySchlickGGX(NdotV, roughness); + float ggx1 = geometrySchlickGGX(NdotL, roughness); + return ggx2 * ggx1; +} + +vec3 fresnelSchlick(float cosTheta, vec3 F0) +{ + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); +} + +vec3 acesTonemap(vec3 color) +{ + float a = 2.51; + float b = 0.03; + float c = 2.43; + float d = 0.59; + float e = 0.14; + return clamp((color * (a * color + b)) / (color * (c * color + d) + e), 0.0, 1.0); +} + +void main() +{ vec3 N = normalize(fragNormal); - vec3 L = normalize(vec3(0.5, 0.8, 0.3)); - float diff = max(dot(N, L), 0.0); - float ambient = 0.25; - vec3 color = fragColor * (ambient + diff * 0.75); + vec3 V = normalize(-fragWorldPos); + + vec3 albedo = fragAlbedo; + float roughness = 0.5; + float metallic = 0.1; + + vec3 F0 = mix(vec3(0.04), albedo, metallic); + + vec3 L = LIGHT_DIR; + vec3 H = normalize(V + L); + + float NDF = distributionGGX(N, H, roughness); + float G = geometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); + + float NdotL = max(dot(N, L), 0.0); + vec3 Lo = (kD * albedo / PI + specular) * LIGHT_COLOR * NdotL; + + vec3 ambient = AMBIENT * albedo; + vec3 color = ambient + Lo; + + color = acesTonemap(color); + color = pow(color, vec3(1.0 / 2.2)); + outColor = vec4(color, 1.0); } diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv index cb92ce1..33d1e5f 100644 Binary files a/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv and b/src/Engine.Graphics.Vulkan/Shaders/triangle.frag.spv differ diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.vert b/src/Engine.Graphics.Vulkan/Shaders/triangle.vert index 736c74d..e19ff90 100644 --- a/src/Engine.Graphics.Vulkan/Shaders/triangle.vert +++ b/src/Engine.Graphics.Vulkan/Shaders/triangle.vert @@ -4,8 +4,9 @@ layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec3 inNormal; -layout(location = 0) out vec3 fragColor; +layout(location = 0) out vec3 fragWorldPos; layout(location = 1) out vec3 fragNormal; +layout(location = 2) out vec3 fragAlbedo; layout(set = 0, binding = 0) uniform CameraUBO { mat4 vp; @@ -16,7 +17,9 @@ layout(push_constant) uniform PC { } pc; void main() { - gl_Position = vp * pc.model * vec4(inPosition, 1.0); - fragColor = inColor; + vec4 worldPos = pc.model * vec4(inPosition, 1.0); + gl_Position = vp * worldPos; + fragWorldPos = worldPos.xyz; fragNormal = mat3(pc.model) * inNormal; + fragAlbedo = inColor; } diff --git a/src/Engine.Graphics.Vulkan/Shaders/triangle.vert.spv b/src/Engine.Graphics.Vulkan/Shaders/triangle.vert.spv index 834e27a..f511e34 100644 Binary files a/src/Engine.Graphics.Vulkan/Shaders/triangle.vert.spv and b/src/Engine.Graphics.Vulkan/Shaders/triangle.vert.spv differ