From 158ebb9c704662f3e4613651a676497eec24e5f5 Mon Sep 17 00:00:00 2001 From: stele Date: Thu, 2 May 2019 22:24:44 +0200 Subject: [PATCH 1/3] Parallax occlusion shader --- shaders/mat_parallax.frag | 142 ++++++++++++++++++++++++++++++++++++++ shaders/vertex.vert | 4 +- 2 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 shaders/mat_parallax.frag diff --git a/shaders/mat_parallax.frag b/shaders/mat_parallax.frag new file mode 100644 index 00000000..2f248f22 --- /dev/null +++ b/shaders/mat_parallax.frag @@ -0,0 +1,142 @@ +in vec3 f_normal; +in vec2 f_coord; +in vec4 f_pos; +in mat3 f_tbn; //tangent matrix nietransponowany; mnożyć przez f_tbn dla TangentLightPos; TangentViewPos; TangentFragPos; +in vec4 f_light_pos; +in vec4 f_clip_pos; +in vec4 f_clip_future_pos; +in vec3 TangentFragPos; + +#include + +layout(location = 0) out vec4 out_color; +#if MOTIONBLUR_ENABLED +layout(location = 1) out vec4 out_motion; +#endif + +#param (color, 0, 0, 4, diffuse) +#param (diffuse, 1, 0, 1, diffuse) +#param (specular, 1, 1, 1, specular) +#param (reflection, 1, 2, 1, zero) +#param (height_scale, 2, 1, 1, zero) +#param (height_offset, 2, 2, 1, zero) + +#texture (diffuse, 0, sRGB_A) +uniform sampler2D diffuse; + +#texture (normalmap, 1, RGBA) +uniform sampler2D normalmap; + +#if SHADOWMAP_ENABLED +uniform sampler2DShadow shadowmap; +#endif + +#if ENVMAP_ENABLED +uniform samplerCube envmap; +#endif + +#define NORMALMAP +#include +#include + +vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir); + +void main() +{ +//parallex mapping + vec3 viewDir = normalize(vec3(0.0f, 0.0f, 0.0f) - TangentFragPos); //tangent view pos - tangent frag pos + vec2 f_coord_p = ParallaxMapping(f_coord, viewDir); + + vec4 tex_color = texture(diffuse, f_coord_p); + + if (tex_color.a < opacity) + discard; + vec3 normal = normalize(f_tbn * normalize(texture(normalmap, f_coord_p).rgb * 2.0 - 1.0)); + vec3 refvec = reflect(f_pos.xyz, normal); +#if ENVMAP_ENABLED + vec3 envcolor = texture(envmap, refvec).rgb; +#else + vec3 envcolor = vec3(0.5); +#endif + + vec3 result = ambient * 0.5 + param[0].rgb * emission; + + if (lights_count > 0U) + { + vec2 part = calc_dir_light(lights[0]); + vec3 c = (part.x * param[1].x + part.y * param[1].y) * calc_shadow() * lights[0].color; + result += mix(c, envcolor, param[1].z * texture(normalmap, f_coord_p).a); + } + + for (uint i = 1U; i < lights_count; i++) + { + light_s light = lights[i]; + vec2 part = vec2(0.0); + + if (light.type == LIGHT_SPOT) + part = calc_spot_light(light); + else if (light.type == LIGHT_POINT) + part = calc_point_light(light); + else if (light.type == LIGHT_DIR) + part = calc_dir_light(light); + + result += light.color * (part.x * param[1].x + part.y * param[1].y); + } + + vec4 color = vec4(apply_fog(result * tex_color.rgb), tex_color.a * alpha_mult); +#if POSTFX_ENABLED + out_color = color; +#else + out_color = tonemap(color); +#endif +#if MOTIONBLUR_ENABLED + { + vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;; + vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;; + + out_motion = vec4(a - b, 0.0f, 0.0f); + } +#endif +} +vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir) +{ +#if ENVMAP_ENABLED + const float minLayers = 8.0; + const float maxLayers = 32.0; + float LayersWeight = 1; + if (length(f_pos.xyz) > 20) + LayersWeight = 1; + else + LayersWeight = (length(f_pos.xyz) / 20); + vec2 currentTexCoords = f_coord; + float currentDepthMapValue = texture(normalmap, currentTexCoords).b; + LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewDir)),LayersWeight); + float numLayers = mix(maxLayers, minLayers, LayersWeight); // number of depth layers + float layerDepth = 1.0 / numLayers; // calculate the size of each layer + float currentLayerDepth = 0.0; // depth of current layer + vec2 P = viewDir.xy * param[2].y; // the amount to shift the texture coordinates per layer (from vector P) + vec2 deltaTexCoords = P / numLayers; + + + while(currentLayerDepth < currentDepthMapValue) + { + currentTexCoords -= deltaTexCoords; // shift texture coordinates along direction of P + currentDepthMapValue = texture(normalmap, currentTexCoords).b; // get depthmap value at current texture coordinates + currentLayerDepth += layerDepth; // get depth of next layer + } + + vec2 prevTexCoords = currentTexCoords + deltaTexCoords; // get texture coordinates before collision (reverse operations) + + float afterDepth = currentDepthMapValue - currentLayerDepth; // get depth after and before collision for linear interpolation + float beforeDepth = texture(normalmap, currentTexCoords).b - currentLayerDepth + layerDepth; + + float weight = afterDepth / (afterDepth - beforeDepth); // interpolation of texture coordinates + vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight); + + return finalTexCoords; +#else + float height = texture(normalmap, f_coord).b; + vec2 p = viewDir.xy / viewDir.z * (height * param[2].y - param[2].z); + return f_coord - p; +#endif +} \ No newline at end of file diff --git a/shaders/vertex.vert b/shaders/vertex.vert index b13031d5..7e4ea253 100644 --- a/shaders/vertex.vert +++ b/shaders/vertex.vert @@ -10,7 +10,7 @@ out vec4 f_pos; out mat3 f_tbn; out vec4 f_tangent; out vec4 f_light_pos; - +out vec3 TangentFragPos; out vec4 f_clip_pos; out vec4 f_clip_future_pos; @@ -35,4 +35,6 @@ void main() vec3 B = normalize(modelviewnormal * cross(v_normal, v_tangent.xyz) * v_tangent.w); vec3 N = normalize(modelviewnormal * v_normal); f_tbn = mat3(T, B, N); + mat3 TBN = transpose(mat3(T, B, N)); + TangentFragPos = TBN * f_pos.xyz; } From 410e1452f6bf82bc244142096cd0b06de15787fe Mon Sep 17 00:00:00 2001 From: stele Date: Fri, 3 May 2019 17:32:46 +0200 Subject: [PATCH 2/3] Cleanup of vertex shader by @tmj. 2-channel normalmaps with Z-component reconstruction. Normal vectors passed from fragment shaders to lightning calculations. --- shaders/light_common.glsl | 4 +++- shaders/mat_normalmap.frag | 7 ++++++- shaders/mat_parallax.frag | 10 +++++++--- shaders/vertex.vert | 21 ++++++++++++++------- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/shaders/light_common.glsl b/shaders/light_common.glsl index aed7d107..8fc8216f 100644 --- a/shaders/light_common.glsl +++ b/shaders/light_common.glsl @@ -30,9 +30,11 @@ float calc_shadow() vec2 calc_light(vec3 light_dir) { #ifdef NORMALMAP - vec3 normal = normalize(f_tbn * normalize(texture(normalmap, f_coord).rgb * 2.0 - 1.0)); + vec3 normal = normal; #elif defined(WATER) vec3 normal = normal_d; +#elif defined(PARALLAX) + vec3 normal = normal_p; #else vec3 normal = normalize(f_normal); #endif diff --git a/shaders/mat_normalmap.frag b/shaders/mat_normalmap.frag index c4b7a4fa..cae429aa 100644 --- a/shaders/mat_normalmap.frag +++ b/shaders/mat_normalmap.frag @@ -33,6 +33,8 @@ uniform sampler2DShadow shadowmap; uniform samplerCube envmap; #endif +vec3 normal; + #define NORMALMAP #include #include @@ -44,7 +46,10 @@ void main() if (tex_color.a < opacity) discard; - vec3 normal = normalize(f_tbn * normalize(texture(normalmap, f_coord).rgb * 2.0 - 1.0)); + normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0); + normal.z = sqrt(1 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0)); + normal = normalize(f_tbn * normalize(normal.xyz)); + //vec3 normal = normalize(f_tbn * normalize(texture(normalmap, f_coord).rgb * 2.0 - 1.0)); vec3 refvec = reflect(f_pos.xyz, normal); #if ENVMAP_ENABLED vec3 envcolor = texture(envmap, refvec).rgb; diff --git a/shaders/mat_parallax.frag b/shaders/mat_parallax.frag index 2f248f22..1cca810a 100644 --- a/shaders/mat_parallax.frag +++ b/shaders/mat_parallax.frag @@ -35,7 +35,8 @@ uniform sampler2DShadow shadowmap; uniform samplerCube envmap; #endif -#define NORMALMAP +vec3 normal_p; +#define PARALLAX #include #include @@ -51,8 +52,11 @@ void main() if (tex_color.a < opacity) discard; - vec3 normal = normalize(f_tbn * normalize(texture(normalmap, f_coord_p).rgb * 2.0 - 1.0)); - vec3 refvec = reflect(f_pos.xyz, normal); + vec3 normal = f_normal; + normal.xy = (texture(normalmap, f_coord_p).rg * 2.0 - 1.0); + normal.z = sqrt(1 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0)); + normal_p = normalize(f_tbn * normalize(normal.xyz)); + vec3 refvec = reflect(f_pos.xyz, normal_p); #if ENVMAP_ENABLED vec3 envcolor = texture(envmap, refvec).rgb; #else diff --git a/shaders/vertex.vert b/shaders/vertex.vert index 7e4ea253..76a4f93b 100644 --- a/shaders/vertex.vert +++ b/shaders/vertex.vert @@ -8,20 +8,24 @@ flat out vec3 f_normal_raw; out vec2 f_coord; out vec4 f_pos; out mat3 f_tbn; -out vec4 f_tangent; +//out vec4 f_tangent; out vec4 f_light_pos; -out vec3 TangentFragPos; + out vec4 f_clip_pos; out vec4 f_clip_future_pos; +//out vec3 TangentLightPos; +//out vec3 TangentViewPos; +out vec3 TangentFragPos; + #include void main() { - f_normal = modelviewnormal * v_normal; + f_normal = normalize(modelviewnormal * v_normal); f_normal_raw = v_normal; f_coord = v_coord; - f_tangent = v_tangent; +// f_tangent = v_tangent; f_pos = modelview * vec4(v_vert, 1.0f); f_light_pos = lightview * f_pos; @@ -32,9 +36,12 @@ void main() gl_PointSize = param[1].x; vec3 T = normalize(modelviewnormal * v_tangent.xyz); - vec3 B = normalize(modelviewnormal * cross(v_normal, v_tangent.xyz) * v_tangent.w); - vec3 N = normalize(modelviewnormal * v_normal); + vec3 N = f_normal; + vec3 B = normalize(cross(N, T)); f_tbn = mat3(T, B, N); - mat3 TBN = transpose(mat3(T, B, N)); + + mat3 TBN = transpose(f_tbn); +// TangentLightPos = TBN * f_light_pos.xyz; +// TangentViewPos = TBN * vec3(0.0f, 0.0f, 0.0f); TangentFragPos = TBN * f_pos.xyz; } From 934044e0a99bb7689258967e0e3a6f23a57aa0a4 Mon Sep 17 00:00:00 2001 From: stele Date: Fri, 3 May 2019 17:48:42 +0200 Subject: [PATCH 3/3] Z-normal reconstruction for water shader. --- shaders/mat_parallax.frag | 2 +- shaders/mat_water.frag | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/shaders/mat_parallax.frag b/shaders/mat_parallax.frag index 1cca810a..41b11a63 100644 --- a/shaders/mat_parallax.frag +++ b/shaders/mat_parallax.frag @@ -52,7 +52,7 @@ void main() if (tex_color.a < opacity) discard; - vec3 normal = f_normal; + vec3 normal; normal.xy = (texture(normalmap, f_coord_p).rg * 2.0 - 1.0); normal.z = sqrt(1 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0)); normal_p = normalize(f_tbn * normalize(normal.xyz)); diff --git a/shaders/mat_water.frag b/shaders/mat_water.frag index 2b0649bf..3eba83ea 100644 --- a/shaders/mat_water.frag +++ b/shaders/mat_water.frag @@ -56,7 +56,10 @@ void main() vec2 total_distorted_tex_coord = (texture(dudvmap, distorted_tex_coord).rg * 2.0 - 1.0 ) * param[2].y; texture_coords += total_distorted_tex_coord; - normal_d = f_tbn * normalize(texture(normalmap, texture_coords).rgb * 2.0 - 1.0); + vec3 normal; + normal.xy = (texture(normalmap, texture_coords).rg * 2.0 - 1.0); + normal.z = sqrt(1 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0)); + normal_d = normalize(f_tbn * normalize(normal.xyz)); vec3 refvec = reflect(f_pos.xyz, normal_d); #if ENVMAP_ENABLED vec3 envcolor = texture(envmap, refvec).rgb;