TrianglePixelShader.frag 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #version 450
  2. layout(binding = 1) uniform PixelShaderConstantBuffer
  3. {
  4. vec3 CameraPos;
  5. vec3 LightPos;
  6. } c;
  7. layout(location = 0) in vec3 iNormal;
  8. layout(location = 1) in vec3 iWorldPos;
  9. layout(location = 2) in vec2 iTex;
  10. layout(location = 3) in vec4 iPositionL;
  11. layout(location = 4) in vec4 iColor;
  12. layout(location = 0) out vec4 oColor;
  13. layout(set = 1, binding = 0) uniform sampler2D LightDepthSampler;
  14. void main()
  15. {
  16. // Constants
  17. float AmbientFactor = 0.3;
  18. vec3 DiffuseColor = vec3(iColor.r, iColor.g, iColor.b);
  19. vec3 SpecularColor = vec3(1, 1, 1);
  20. float SpecularPower = 100.0;
  21. float bias = 1.0e-7;
  22. // Homogenize position in light space
  23. vec3 position_l = iPositionL.xyz / iPositionL.w;
  24. // Calculate dot product between direction to light and surface normal and clamp between [0, 1]
  25. vec3 view_dir = normalize(c.CameraPos - iWorldPos);
  26. vec3 world_to_light = c.LightPos - iWorldPos;
  27. vec3 light_dir = normalize(world_to_light);
  28. vec3 normal = normalize(iNormal);
  29. if (dot(view_dir, normal) < 0) // If we're viewing the triangle from the back side, flip the normal to get the correct lighting
  30. normal = -normal;
  31. float normal_dot_light_dir = clamp(dot(normal, light_dir), 0, 1);
  32. // Calculate texture coordinates in light depth texture
  33. vec2 tex_coord;
  34. tex_coord.x = position_l.x / 2.0 + 0.5;
  35. tex_coord.y = position_l.y / 2.0 + 0.5;
  36. // Check that the texture coordinate is inside the depth texture, if not we don't know if it is lit or not so we assume lit
  37. float shadow_factor = 1.0;
  38. if (iColor.a > 0 // Alpha = 0 means don't receive shadows
  39. && tex_coord.x == clamp(tex_coord.x, 0, 1) && tex_coord.y == clamp(tex_coord.y, 0, 1))
  40. {
  41. // Modify shadow bias according to the angle between the normal and the light dir
  42. float modified_bias = bias * tan(acos(normal_dot_light_dir));
  43. modified_bias = min(modified_bias, 10.0 * bias);
  44. // Get texture size
  45. float width = 1.0 / 4096;
  46. float height = 1.0 / 4096;
  47. // Samples to take
  48. uint num_samples = 16;
  49. vec2 offsets[] = {
  50. vec2(-1.5 * width, -1.5 * height),
  51. vec2(-0.5 * width, -1.5 * height),
  52. vec2(0.5 * width, -1.5 * height),
  53. vec2(1.5 * width, -1.5 * height),
  54. vec2(-1.5 * width, -0.5 * height),
  55. vec2(-0.5 * width, -0.5 * height),
  56. vec2(0.5 * width, -0.5 * height),
  57. vec2(1.5 * width, -0.5 * height),
  58. vec2(-1.5 * width, 0.5 * height),
  59. vec2(-0.5 * width, 0.5 * height),
  60. vec2(0.5 * width, 0.5 * height),
  61. vec2(1.5 * width, 0.5 * height),
  62. vec2(-1.5 * width, 1.5 * height),
  63. vec2(-0.5 * width, 1.5 * height),
  64. vec2(0.5 * width, 1.5 * height),
  65. vec2(1.5 * width, 1.5 * height),
  66. };
  67. // Calculate depth of this pixel relative to the light
  68. float light_depth = position_l.z + modified_bias;
  69. // Sample shadow factor
  70. shadow_factor = 0.0;
  71. for (uint i = 0; i < num_samples; ++i)
  72. shadow_factor += texture(LightDepthSampler, tex_coord + offsets[i]).x <= light_depth? 1.0 : 0.0;
  73. shadow_factor /= num_samples;
  74. }
  75. // Calculate diffuse and specular
  76. float diffuse = normal_dot_light_dir;
  77. float specular = diffuse > 0.0? pow(clamp(-dot(reflect(light_dir, normal), view_dir), 0, 1), SpecularPower) : 0.0;
  78. // Apply procedural pattern based on the uv coordinates
  79. bvec2 less_half = lessThan(iTex - floor(iTex), vec2(0.5, 0.5));
  80. float darken_factor = less_half.r ^^ less_half.g? 0.5 : 1.0;
  81. // Fade out checkerboard pattern when it tiles too often
  82. vec2 dx = dFdx(iTex), dy = dFdy(iTex);
  83. float texel_distance = sqrt(dot(dx, dx) + dot(dy, dy));
  84. darken_factor = mix(darken_factor, 0.75, clamp(5.0 * texel_distance - 1.5, 0.0, 1.0));
  85. // Calculate color
  86. oColor = vec4(clamp((AmbientFactor + diffuse * shadow_factor) * darken_factor * DiffuseColor + SpecularColor * specular * shadow_factor, 0, 1), 1);
  87. }