Guest User

A basic (and crude) glass shader in GLSL

a guest
Nov 23rd, 2024
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.20 KB | None | 0 0
  1. #version 330 core
  2.  
  3. out vec4 FragColor;
  4.  
  5. in vec3 FragPos; // World space position
  6. in vec3 Normal; // Normal in world space
  7.  
  8. uniform sampler2D bgTexture; // Background texture
  9. uniform vec3 cameraPos; // Camera position
  10. uniform vec3 lightPos; // Light position
  11. uniform mat4 view; // View matrix
  12. uniform mat4 projection; // Projection matrix
  13.  
  14. const float blurRadius = 0.002; // Radius for blurring
  15. const int blurSamples = 1; // Number of samples for blur
  16. const vec3 lightColor = vec3(1.0, 1.0, 1.0); // Light color
  17. const vec3 fresnelColour = vec3(1.0, 1.0, 1.0); // Light color
  18. const float refractiveIndex = 1.5; // Refractive index, e.g., 1.5 for glass
  19.  
  20. vec2 getUV(vec3 fragPos);
  21. vec2 applyWarp(vec2 uv, vec3 normal);
  22. vec4 sampleBlurredTexture(sampler2D texture, vec2 uv);
  23. float calculateFresnel(vec3 fragPos, vec3 normal, vec3 cameraPos);
  24. vec4 blendWithFresnel(vec4 color, float fresnel);
  25. vec4 calculateSpecular(vec3 fragPos, vec3 normal, vec3 viewDir);
  26. float phongShading(vec3 FragPos, vec3 Normal, vec3 cameraPos, vec3 lightPos);
  27. vec4 calcRefraction();
  28.  
  29. void main() {
  30. // Step 1: Calculate UV coordinates from fragment position
  31. vec2 uv = getUV(FragPos);
  32.  
  33. // vec4 refraction = calcRefraction() * phongShading(FragPos, Normal, cameraPos, lightPos);
  34. vec4 refraction = calcRefraction();
  35.  
  36. // Step 2: Warp the UV based on the surface normal
  37. // uv = applyWarp(uv, Normal);
  38.  
  39. // Step 3: Calculate the refracted ray direction using Snell's law
  40. vec3 viewDir = normalize(cameraPos - FragPos);
  41.  
  42. // Step 4: Sample the background texture using the refracted direction
  43. // You might need to adjust the UV coordinates here based on your background
  44. // vec4 bgColor = sampleBlurredTexture(bgTexture, uv);
  45.  
  46. // Step 5: Calculate the Fresnel effect
  47. float fresnel = calculateFresnel(FragPos, Normal, cameraPos);
  48.  
  49. // Step 6: Calculate specular
  50. vec4 specular = calculateSpecular(FragPos, Normal, viewDir);
  51.  
  52. // Step 7: Blend specular with Fresnel effect
  53. vec4 finalColor = mix(refraction * 2, specular, 0.5);
  54. FragColor = blendWithFresnel(finalColor, fresnel);
  55. }
  56.  
  57. vec2 getUV(vec3 fragPos) {
  58. vec4 clipSpacePos = projection * view * vec4(fragPos, 1.0);
  59. vec3 ndc = clipSpacePos.xyz / clipSpacePos.w;
  60. return ndc.xy * 0.5 + 0.5;
  61. }
  62.  
  63. vec2 applyWarp(vec2 uv, vec3 normal) {
  64. vec3 norm = normalize(normal);
  65. vec2 warp = norm.xy * 0.05; // Warp strength based on normal
  66. return clamp(uv + warp, 0.0, 1.0);
  67. }
  68.  
  69. vec4 sampleBlurredTexture(sampler2D texture, vec2 uv) {
  70. vec4 color = vec4(0.0);
  71. float totalWeight = 0.0;
  72.  
  73. for (int i = -blurSamples; i <= blurSamples; ++i)
  74. {
  75. for (int j = -blurSamples; j <= blurSamples; ++j)
  76. {
  77. vec2 offset = vec2(float(i), float(j)) * blurRadius;
  78. float weight = exp(-(dot(offset, offset) / (2.0 * blurRadius * blurRadius)));
  79. color += texture2D(texture, uv + offset) * weight;
  80. totalWeight += weight;
  81. }
  82. }
  83.  
  84. return color / totalWeight; // Normalize the result
  85. }
  86.  
  87. float calculateFresnel(vec3 fragPos, vec3 normal, vec3 cameraPos) {
  88. vec3 viewDir = normalize(cameraPos - fragPos);
  89. float cosTheta = dot(viewDir, normalize(normal));
  90. return pow(1.0 - cosTheta, 6.0);
  91. }
  92.  
  93. vec4 blendWithFresnel(vec4 color, float fresnel) {
  94. vec4 fresnelHighlight = vec4(fresnelColour.r, fresnelColour.g, fresnelColour.b, 1.0);
  95. return mix(color, fresnelHighlight, fresnel);
  96. }
  97.  
  98. vec4 calculateSpecular(vec3 fragPos, vec3 normal, vec3 viewDir) {
  99. vec3 norm = normalize(normal);
  100. vec3 lightDir = normalize(lightPos - fragPos);
  101.  
  102. vec3 reflectDir = reflect(-lightDir, norm);
  103. float spec = pow(max(dot(viewDir, reflectDir), 0.0), 50.0);
  104. vec3 specular = spec * lightColor * 2;
  105.  
  106. return vec4(specular, 1.0);
  107. }
  108.  
  109. float phongShading(vec3 FragPos, vec3 Normal, vec3 cameraPos, vec3 lightPos) {
  110. // Light direction
  111. vec3 lightDir = normalize(lightPos - FragPos);
  112.  
  113. // View direction
  114. vec3 viewDir = normalize(cameraPos - FragPos);
  115.  
  116. // Calculate Diffuse: Lambertian reflection with exaggerated intensity
  117. float diffuse = max(dot(Normal, lightDir), 0.0);
  118.  
  119. // Exaggerate the diffuse lighting for more dramatic effect
  120. diffuse = pow(diffuse, 2.0); // Cube the diffuse to enhance the effect (can adjust the exponent)
  121.  
  122. // Return the enhanced diffuse as Phong shading value
  123. return diffuse;
  124. }
  125.  
  126. vec4 calcRefraction() {
  127. // Warps the texture and applies some gaussian blur that tapers off at glancing angles to make the thing look like glass. This is abstract art really, it is not in any way accurate
  128.  
  129. // Calculate normalized view vector (eye direction)
  130. vec3 eyeVector = normalize(FragPos - cameraPos);
  131.  
  132. // Normalize the surface normal
  133. vec3 normal = normalize(Normal);
  134.  
  135. // Calculate refraction vector using Snell's law
  136. float refractiveIndexRatio = 1.0 / 1.5; // Air to glass (or vice versa)
  137.  
  138. vec3 faceNormal = normalize(Normal); // Normal for this face
  139. vec3 refractVec = refract(eyeVector, faceNormal * 10, refractiveIndexRatio);
  140.  
  141. // Step 1: Calculate the direction of the camera to the fragment
  142. vec3 viewDir = normalize(cameraPos - FragPos);
  143.  
  144. // Step 2: Compute the texture coordinates based on world position and camera/projection matrices
  145. vec4 viewPos = view * vec4(FragPos, 1.0); // Transform the world position to view space
  146.  
  147. // Map the view space position to clip space
  148. vec4 clipSpacePos = projection * viewPos;
  149.  
  150. // Convert clip space coordinates to normalized device coordinates (NDC)
  151. vec2 ndc = clipSpacePos.xy / clipSpacePos.w; // NDC in the range [-1, 1]
  152.  
  153. // Map NDC to texture space [0, 1]
  154. vec2 uv = (ndc * 0.5) + 0.5; // Map to [0, 1] range for texture
  155.  
  156. // Transform refract vector to screen UV coordinates (assumes screen space mapping)
  157. vec2 refractedUV = uv + refractVec.xy * 0.1; // Offset UV based on refraction vector
  158.  
  159. // Step 3: Adjust blur size based on the dot product between view direction and surface normal
  160. float dotProduct = max(dot(viewDir, normal), 0.0); // Avoid negative values
  161.  
  162. // Map the dot product (cosine of the angle) to blur strength: closer to 0 (glancing) -> less blur
  163. float blurStrength = -dotProduct * 2 + 1; // Decrease blur for glancing angles
  164. float blurSize = 0.002 * blurStrength; // Adjust blur size based on the angle
  165.  
  166. // Blur kernel size (how many samples around the refraction direction)
  167. int numSamples = 5;
  168. float sigma = 1.0; // Standard deviation for Gaussian
  169. float weightSum = 0.0;
  170. vec4 blurColor = vec4(0.0);
  171.  
  172. for (int i = -numSamples / 2; i <= numSamples / 2; i++) {
  173. for (int j = -numSamples / 2; j <= numSamples / 2; j++) {
  174. float distance = float(i * i + j * j);
  175. float weight = exp(-distance / (2.0 * sigma * sigma)); // Gaussian weight
  176. vec2 offset = vec2(i, j) * blurSize;
  177. blurColor += texture(bgTexture, (refractedUV + offset) * 1.1) * weight;
  178. weightSum += weight;
  179. }
  180. }
  181.  
  182. blurColor /= weightSum; // Normalize by the sum of weights
  183.  
  184. // Step 4: Return the blurred background color
  185. return blurColor;
  186. }
  187.  
Add Comment
Please, Sign In to add comment