diff options
Diffstat (limited to 'drivers/gles2/shaders')
-rw-r--r-- | drivers/gles2/shaders/SCsub | 1 | ||||
-rw-r--r-- | drivers/gles2/shaders/blend_shape.glsl | 43 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 47 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas_shadow.glsl | 23 | ||||
-rw-r--r-- | drivers/gles2/shaders/copy.glsl | 47 | ||||
-rw-r--r-- | drivers/gles2/shaders/cube_to_dp.glsl | 64 | ||||
-rw-r--r-- | drivers/gles2/shaders/cubemap_filter.glsl | 65 | ||||
-rw-r--r-- | drivers/gles2/shaders/effect_blur.glsl | 182 | ||||
-rw-r--r-- | drivers/gles2/shaders/exposure.glsl | 64 | ||||
-rw-r--r-- | drivers/gles2/shaders/lens_distorted.glsl | 62 | ||||
-rw-r--r-- | drivers/gles2/shaders/particles.glsl | 122 | ||||
-rw-r--r-- | drivers/gles2/shaders/resolve.glsl | 20 | ||||
-rw-r--r-- | drivers/gles2/shaders/scene.glsl | 1917 | ||||
-rw-r--r-- | drivers/gles2/shaders/screen_space_reflection.glsl | 199 | ||||
-rw-r--r-- | drivers/gles2/shaders/ssao.glsl | 164 | ||||
-rw-r--r-- | drivers/gles2/shaders/ssao_blur.glsl | 55 | ||||
-rw-r--r-- | drivers/gles2/shaders/ssao_minify.glsl | 21 | ||||
-rw-r--r-- | drivers/gles2/shaders/stdlib.glsl | 26 | ||||
-rw-r--r-- | drivers/gles2/shaders/subsurf_scattering.glsl | 168 | ||||
-rw-r--r-- | drivers/gles2/shaders/tonemap.glsl | 168 |
20 files changed, 2326 insertions, 1132 deletions
diff --git a/drivers/gles2/shaders/SCsub b/drivers/gles2/shaders/SCsub index acb93fff8f..d959d3f740 100644 --- a/drivers/gles2/shaders/SCsub +++ b/drivers/gles2/shaders/SCsub @@ -20,3 +20,4 @@ if 'GLES2_GLSL' in env['BUILDERS']: # env.GLES2_GLSL('exposure.glsl'); # env.GLES2_GLSL('tonemap.glsl'); # env.GLES2_GLSL('particles.glsl'); + env.GLES2_GLSL('lens_distorted.glsl'); diff --git a/drivers/gles2/shaders/blend_shape.glsl b/drivers/gles2/shaders/blend_shape.glsl index 4e0d066823..a1e954e33d 100644 --- a/drivers/gles2/shaders/blend_shape.glsl +++ b/drivers/gles2/shaders/blend_shape.glsl @@ -1,6 +1,6 @@ +/* clang-format off */ [vertex] - /* from VisualServer: @@ -23,56 +23,57 @@ ARRAY_INDEX=8, /* INPUT ATTRIBS */ -layout(location=0) in highp VFORMAT vertex_attrib; -layout(location=1) in vec3 normal_attrib; +layout(location = 0) in highp VFORMAT vertex_attrib; +/* clang-format on */ +layout(location = 1) in vec3 normal_attrib; #ifdef ENABLE_TANGENT -layout(location=2) in vec4 tangent_attrib; +layout(location = 2) in vec4 tangent_attrib; #endif #ifdef ENABLE_COLOR -layout(location=3) in vec4 color_attrib; +layout(location = 3) in vec4 color_attrib; #endif #ifdef ENABLE_UV -layout(location=4) in vec2 uv_attrib; +layout(location = 4) in vec2 uv_attrib; #endif #ifdef ENABLE_UV2 -layout(location=5) in vec2 uv2_attrib; +layout(location = 5) in vec2 uv2_attrib; #endif #ifdef ENABLE_SKELETON -layout(location=6) in ivec4 bone_attrib; -layout(location=7) in vec4 weight_attrib; +layout(location = 6) in ivec4 bone_attrib; +layout(location = 7) in vec4 weight_attrib; #endif /* BLEND ATTRIBS */ #ifdef ENABLE_BLEND -layout(location=8) in highp VFORMAT vertex_attrib_blend; -layout(location=9) in vec3 normal_attrib_blend; +layout(location = 8) in highp VFORMAT vertex_attrib_blend; +layout(location = 9) in vec3 normal_attrib_blend; #ifdef ENABLE_TANGENT -layout(location=10) in vec4 tangent_attrib_blend; +layout(location = 10) in vec4 tangent_attrib_blend; #endif #ifdef ENABLE_COLOR -layout(location=11) in vec4 color_attrib_blend; +layout(location = 11) in vec4 color_attrib_blend; #endif #ifdef ENABLE_UV -layout(location=12) in vec2 uv_attrib_blend; +layout(location = 12) in vec2 uv_attrib_blend; #endif #ifdef ENABLE_UV2 -layout(location=13) in vec2 uv2_attrib_blend; +layout(location = 13) in vec2 uv2_attrib_blend; #endif #ifdef ENABLE_SKELETON -layout(location=14) in ivec4 bone_attrib_blend; -layout(location=15) in vec4 weight_attrib_blend; +layout(location = 14) in ivec4 bone_attrib_blend; +layout(location = 15) in vec4 weight_attrib_blend; #endif #endif @@ -110,7 +111,6 @@ uniform float blend_amount; void main() { - #ifdef ENABLE_BLEND vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount; @@ -140,7 +140,6 @@ void main() { uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount; #endif - #ifdef ENABLE_SKELETON bone_out = bone_attrib_blend; @@ -149,7 +148,6 @@ void main() { #else //ENABLE_BLEND - vertex_out = vertex_attrib * blend_amount; #ifdef ENABLE_NORMAL @@ -177,7 +175,6 @@ void main() { uv2_out = uv2_attrib * blend_amount; #endif - #ifdef ENABLE_SKELETON bone_out = bone_attrib; @@ -188,10 +185,10 @@ void main() { gl_Position = vec4(0.0); } +/* clang-format off */ [fragment] - void main() { } - +/* clang-format on */ diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 29d81bb2c4..79d4eb2243 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -1,3 +1,4 @@ +/* clang-format off */ [vertex] #ifdef USE_GLES_OVER_GL @@ -9,6 +10,7 @@ precision mediump int; #endif uniform highp mat4 projection_matrix; +/* clang-format on */ uniform highp mat4 modelview_matrix; uniform highp mat4 extra_matrix; attribute highp vec2 vertex; // attrib:0 @@ -29,8 +31,12 @@ uniform vec4 src_rect; uniform highp float time; +/* clang-format off */ + VERTEX_SHADER_GLOBALS +/* clang-format on */ + vec2 select(vec2 a, vec2 b, bvec2 c) { vec2 ret; @@ -74,18 +80,30 @@ void main() { #endif -{ - vec2 src_vtx=outvec.xy; + { + vec2 src_vtx = outvec.xy; + /* clang-format off */ + VERTEX_SHADER_CODE -} + /* clang-format on */ + } + +#if !defined(SKIP_TRANSFORM_USED) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif color_interp = color; - gl_Position = projection_matrix * modelview_matrix * outvec; +#ifdef USE_PIXEL_SNAP + outvec.xy = floor(outvec + 0.5).xy; +#endif + gl_Position = projection_matrix * outvec; } +/* clang-format off */ [fragment] #ifdef USE_GLES_OVER_GL @@ -96,9 +114,10 @@ precision mediump float; precision mediump int; #endif -uniform sampler2D color_texture; // texunit:0 +uniform sampler2D color_texture; // texunit:-1 +/* clang-format on */ uniform highp vec2 color_texpixel_size; -uniform mediump sampler2D normal_texture; // texunit:1 +uniform mediump sampler2D normal_texture; // texunit:-2 varying mediump vec2 uv_interp; varying mediump vec4 color_interp; @@ -109,7 +128,7 @@ uniform vec4 final_modulate; #ifdef SCREEN_TEXTURE_USED -uniform sampler2D screen_texture; // texunit:2 +uniform sampler2D screen_texture; // texunit:-3 #endif @@ -119,27 +138,33 @@ uniform vec2 screen_pixel_size; #endif +/* clang-format off */ + FRAGMENT_SHADER_GLOBALS +/* clang-format on */ void main() { vec4 color = color_interp; +#if !defined(COLOR_USED) + //default behavior, texture by color color *= texture2D(color_texture, uv_interp); +#endif #ifdef SCREEN_UV_USED vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; #endif -{ + { + /* clang-format off */ FRAGMENT_SHADER_CODE - -} + /* clang-format on */ + } color *= final_modulate; gl_FragColor = color; - } diff --git a/drivers/gles2/shaders/canvas_shadow.glsl b/drivers/gles2/shaders/canvas_shadow.glsl index c757990de0..e3c8140e31 100644 --- a/drivers/gles2/shaders/canvas_shadow.glsl +++ b/drivers/gles2/shaders/canvas_shadow.glsl @@ -1,49 +1,50 @@ +/* clang-format off */ [vertex] - - uniform highp mat4 projection_matrix; +/* clang-format on */ uniform highp mat4 light_matrix; uniform highp mat4 world_matrix; uniform highp float distance_norm; -layout(location=0) in highp vec3 vertex; +layout(location = 0) in highp vec3 vertex; out highp vec4 position_interp; void main() { - gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex,1.0))); - position_interp=gl_Position; + gl_Position = projection_matrix * (light_matrix * (world_matrix * vec4(vertex, 1.0))); + position_interp = gl_Position; } +/* clang-format off */ [fragment] in highp vec4 position_interp; +/* clang-format on */ #ifdef USE_RGBA_SHADOWS -layout(location=0) out lowp vec4 distance_buf; +layout(location = 0) out lowp vec4 distance_buf; #else -layout(location=0) out highp float distance_buf; +layout(location = 0) out highp float distance_buf; #endif void main() { - highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0;//bias; + highp float depth = ((position_interp.z / position_interp.w) + 1.0) * 0.5 + 0.0; //bias; #ifdef USE_RGBA_SHADOWS highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0)); comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0); - distance_buf=comp; + distance_buf = comp; #else - distance_buf=depth; + distance_buf = depth; #endif } - diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index feaeb2152b..0b8da4f875 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -1,3 +1,4 @@ +/* clang-format off */ [vertex] #ifdef USE_GLES_OVER_GL @@ -9,6 +10,7 @@ precision mediump int; #endif attribute highp vec4 vertex_attrib; // attrib:0 +/* clang-format on */ #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) attribute vec3 cube_in; // attrib:4 @@ -33,6 +35,8 @@ void main() { #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) cube_interp = cube_in; +#elif defined(USE_ASYM_PANO) + uv_interp = vertex_attrib.xy; #else uv_interp = uv_in; #endif @@ -46,6 +50,7 @@ void main() { #endif } +/* clang-format off */ [fragment] #define M_PI 3.14159265359 @@ -63,6 +68,12 @@ varying vec3 cube_interp; #else varying vec2 uv_interp; #endif +/* clang-format on */ + +#ifdef USE_ASYM_PANO +uniform highp mat4 pano_transform; +uniform highp vec4 asym_proj; +#endif #ifdef USE_CUBEMAP uniform samplerCube source_cube; // texunit:0 @@ -85,17 +96,15 @@ uniform float custom_alpha; vec4 texturePanorama(sampler2D pano, vec3 normal) { vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y) - ); + atan(normal.x, normal.z), + acos(normal.y)); - if(st.x < 0.0) - st.x += M_PI*2.0; + if (st.x < 0.0) + st.x += M_PI * 2.0; - st/=vec2(M_PI*2.0,M_PI); - - return texture2D(pano,st); + st /= vec2(M_PI * 2.0, M_PI); + return texture2D(pano, st); } #endif @@ -106,19 +115,33 @@ void main() { vec4 color = texturePanorama(source, normalize(cube_interp)); +#elif defined(USE_ASYM_PANO) + + // When an asymmetrical projection matrix is used (applicable for stereoscopic rendering i.e. VR) we need to do this calculation per fragment to get a perspective correct result. + // Note that we're ignoring the x-offset for IPD, with Z sufficiently in the distance it becomes neglectible, as a result we could probably just set cube_normal.z to -1. + // The Matrix[2][0] (= asym_proj.x) and Matrix[2][1] (= asym_proj.z) values are what provide the right shift in the image. + + vec3 cube_normal; + cube_normal.z = -1000000.0; + cube_normal.x = (cube_normal.z * (-uv_interp.x - asym_proj.x)) / asym_proj.y; + cube_normal.y = (cube_normal.z * (-uv_interp.y - asym_proj.z)) / asym_proj.a; + cube_normal = mat3(pano_transform) * cube_normal; + cube_normal.z = -cube_normal.z; + + vec4 color = texturePanorama(source, normalize(cube_normal.xyz)); + #elif defined(USE_CUBEMAP) vec4 color = textureCube(source_cube, normalize(cube_interp)); #else - vec4 color = texture2D( source, uv_interp ); + vec4 color = texture2D(source, uv_interp); #endif - #ifdef USE_NO_ALPHA - color.a=1.0; + color.a = 1.0; #endif #ifdef USE_CUSTOM_ALPHA - color.a=custom_alpha; + color.a = custom_alpha; #endif #ifdef USE_MULTIPLIER diff --git a/drivers/gles2/shaders/cube_to_dp.glsl b/drivers/gles2/shaders/cube_to_dp.glsl index 0b3f53a870..3d24c36336 100644 --- a/drivers/gles2/shaders/cube_to_dp.glsl +++ b/drivers/gles2/shaders/cube_to_dp.glsl @@ -1,3 +1,4 @@ +/* clang-format off */ [vertex] #ifdef USE_GLES_OVER_GL @@ -9,6 +10,7 @@ precision mediump int; #endif attribute highp vec4 vertex_attrib; // attrib:0 +/* clang-format on */ attribute vec2 uv_in; // attrib:4 varying vec2 uv_interp; @@ -19,6 +21,7 @@ void main() { gl_Position = vertex_attrib; } +/* clang-format off */ [fragment] #ifdef USE_GLES_OVER_GL @@ -30,6 +33,7 @@ precision mediump int; #endif uniform highp samplerCube source_cube; //texunit:0 +/* clang-format on */ varying vec2 uv_interp; uniform bool z_flip; @@ -39,55 +43,53 @@ uniform highp float bias; void main() { - highp vec3 normal = vec3( uv_interp * 2.0 - 1.0, 0.0 ); -/* - if(z_flip) { - normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + highp vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0); + /* + if (z_flip) { + normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); } else { - normal.z = -0.5 + 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + normal.z = -0.5 + 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); } -*/ + */ - //normal.z = sqrt(1.0-dot(normal.xy,normal.xy)); - //normal.xy*=1.0+normal.z; + //normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); + //normal.xy *= 1.0 + normal.z; - normal.z = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y)); + normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); normal = normalize(normal); + /* + normal.z = 0.5; + normal = normalize(normal); + */ -/* - normal.z=0.5; - normal=normalize(normal); -*/ if (!z_flip) { - normal.z=-normal.z; + normal.z = -normal.z; } //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 )); - float depth = textureCube(source_cube,normal).r; + float depth = textureCube(source_cube, normal).r; // absolute values for direction cosines, bigger value equals closer to basis axis vec3 unorm = abs(normal); - if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { - // x code - unorm = normal.x > 0.0 ? vec3( 1.0, 0.0, 0.0 ) : vec3( -1.0, 0.0, 0.0 ) ; - } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { - // y code - unorm = normal.y > 0.0 ? vec3( 0.0, 1.0, 0.0 ) : vec3( 0.0, -1.0, 0.0 ) ; - } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { - // z code - unorm = normal.z > 0.0 ? vec3( 0.0, 0.0, 1.0 ) : vec3( 0.0, 0.0, -1.0 ) ; + if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { + // x code + unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); + } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { + // y code + unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); + } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { + // z code + unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); } else { - // oh-no we messed up code - // has to be - unorm = vec3( 1.0, 0.0, 0.0 ); + // oh-no we messed up code + // has to be + unorm = vec3(1.0, 0.0, 0.0); } - float depth_fix = 1.0 / dot(normal,unorm); - + float depth_fix = 1.0 / dot(normal, unorm); depth = 2.0 * depth - 1.0; float linear_depth = 2.0 * z_near * z_far / (z_far + z_near - depth * (z_far - z_near)); - gl_FragDepth = (linear_depth*depth_fix+bias) / z_far; + gl_FragDepth = (linear_depth * depth_fix + bias) / z_far; } - diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl index 62ecd9471b..b1553c7cd5 100644 --- a/drivers/gles2/shaders/cubemap_filter.glsl +++ b/drivers/gles2/shaders/cubemap_filter.glsl @@ -1,3 +1,4 @@ +/* clang-format off */ [vertex] #ifdef USE_GLES_OVER_GL @@ -9,19 +10,26 @@ precision mediump int; #endif attribute highp vec2 vertex; // attrib:0 +/* clang-format on */ attribute highp vec2 uv; // attrib:4 varying highp vec2 uv_interp; void main() { - uv_interp=uv; - gl_Position=vec4(vertex,0,1); + uv_interp = uv; + gl_Position = vec4(vertex, 0, 1); } +/* clang-format off */ [fragment] -#extension GL_ARB_shader_texture_lod : require +#extension GL_ARB_shader_texture_lod : enable + +#ifndef GL_ARB_shader_texture_lod +#define texture2DLod(img, coord, lod) texture2D(img, coord) +#define textureCubeLod(img, coord, lod) textureCube(img, coord) +#endif #ifdef USE_GLES_OVER_GL #define mediump @@ -36,6 +44,7 @@ uniform sampler2D source_panorama; //texunit:0 #else uniform samplerCube source_cube; //texunit:0 #endif +/* clang-format on */ uniform int face_id; uniform float roughness; @@ -60,17 +69,15 @@ uniform sampler2D radical_inverse_vdc_cache; // texunit:1 vec4 texturePanorama(sampler2D pano, vec3 normal) { vec2 st = vec2( - atan(normal.x, normal.z), - acos(normal.y) - ); - - if(st.x < 0.0) - st.x += M_PI*2.0; + atan(normal.x, normal.z), + acos(normal.y)); - st/=vec2(M_PI*2.0,M_PI); + if (st.x < 0.0) + st.x += M_PI * 2.0; - return texture2DLod(pano,st,0.0); + st /= vec2(M_PI * 2.0, M_PI); + return texture2DLod(pano, st, 0.0); } #endif @@ -79,24 +86,24 @@ vec3 texelCoordToVec(vec2 uv, int faceID) { mat3 faceUvVectors[6]; // -x - faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[0][0] = vec3(0.0, 0.0, 1.0); // u -> +z faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y faceUvVectors[0][2] = vec3(-1.0, 0.0, 0.0); // -x face // +x faceUvVectors[1][0] = vec3(0.0, 0.0, -1.0); // u -> -z faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face + faceUvVectors[1][2] = vec3(1.0, 0.0, 0.0); // +x face // -y - faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[2][1] = vec3(0.0, 0.0, -1.0); // v -> -z faceUvVectors[2][2] = vec3(0.0, -1.0, 0.0); // -y face // +y - faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z - faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[3][2] = vec3(0.0, 1.0, 0.0); // +y face // -z faceUvVectors[4][0] = vec3(-1.0, 0.0, 0.0); // u -> -x @@ -104,9 +111,9 @@ vec3 texelCoordToVec(vec2 uv, int faceID) { faceUvVectors[4][2] = vec3(0.0, 0.0, -1.0); // -z face // +z - faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[5][0] = vec3(1.0, 0.0, 0.0); // u -> +x faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face + faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; @@ -118,7 +125,7 @@ vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { // Compute distribution direction float Phi = 2.0 * M_PI * Xi.x; - float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); + float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); float SinTheta = sqrt(1.0 - CosTheta * CosTheta); // Convert to spherical direction @@ -160,28 +167,30 @@ void main() { vec3 H = ImportanceSampleGGX(xi, roughness, N); vec3 V = N; - vec3 L = normalize(2.0 * dot(V, H) * H - V); + vec3 L = (2.0 * dot(V, H) * H - V); float NdotL = clamp(dot(N, L), 0.0, 1.0); if (NdotL > 0.0) { #ifdef USE_SOURCE_PANORAMA - sum.rgb += texturePanorama(source_panorama, H).rgb * NdotL; + vec3 val = texturePanorama(source_panorama, L).rgb; #else - H.y = -H.y; - sum.rgb += textureCubeLod(source_cube, H, 0.0).rgb * NdotL; + vec3 val = textureCubeLod(source_cube, L, 0.0).rgb; #endif + //mix using Linear, to approximate high end back-end + val = mix(pow((val + vec3(0.055)) * (1.0 / (1.0 + 0.055)), vec3(2.4)), val * (1.0 / 12.92), vec3(lessThan(val, vec3(0.04045)))); - sum.a += NdotL; + sum.rgb += val * NdotL; + sum.a += NdotL; } - } sum /= sum.a; - gl_FragColor = vec4(sum.rgb, 1.0); + vec3 a = vec3(0.055); + sum.rgb = mix((vec3(1.0) + a) * pow(sum.rgb, vec3(1.0 / 2.4)) - a, 12.92 * sum.rgb, vec3(lessThan(sum.rgb, vec3(0.0031308)))); + gl_FragColor = vec4(sum.rgb, 1.0); } - diff --git a/drivers/gles2/shaders/effect_blur.glsl b/drivers/gles2/shaders/effect_blur.glsl index b5f98a1244..a531802c75 100644 --- a/drivers/gles2/shaders/effect_blur.glsl +++ b/drivers/gles2/shaders/effect_blur.glsl @@ -1,8 +1,9 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; out vec2 uv_interp; @@ -23,6 +24,7 @@ void main() { #endif } +/* clang-format off */ [fragment] #if !defined(GLES_OVER_GL) @@ -30,6 +32,7 @@ precision mediump float; #endif in vec2 uv_interp; +/* clang-format on */ uniform sampler2D source_color; //texunit:0 #ifdef SSAO_MERGE @@ -39,7 +42,6 @@ uniform sampler2D source_ssao; //texunit:1 uniform float lod; uniform vec2 pixel_size; - layout(location = 0) out vec4 frag_color; #ifdef SSAO_MERGE @@ -48,31 +50,31 @@ uniform vec4 ssao_color; #endif -#if defined (GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) +#if defined(GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL) uniform float glow_strength; #endif -#if defined(DOF_FAR_BLUR) || defined (DOF_NEAR_BLUR) +#if defined(DOF_FAR_BLUR) || defined(DOF_NEAR_BLUR) #ifdef DOF_QUALITY_LOW -const int dof_kernel_size=5; -const int dof_kernel_from=2; -const float dof_kernel[5] = float[] (0.153388,0.221461,0.250301,0.221461,0.153388); +const int dof_kernel_size = 5; +const int dof_kernel_from = 2; +const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388); #endif #ifdef DOF_QUALITY_MEDIUM -const int dof_kernel_size=11; -const int dof_kernel_from=5; -const float dof_kernel[11] = float[] (0.055037,0.072806,0.090506,0.105726,0.116061,0.119726,0.116061,0.105726,0.090506,0.072806,0.055037); +const int dof_kernel_size = 11; +const int dof_kernel_from = 5; +const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037); #endif #ifdef DOF_QUALITY_HIGH -const int dof_kernel_size=21; -const int dof_kernel_from=10; -const float dof_kernel[21] = float[] (0.028174,0.032676,0.037311,0.041944,0.046421,0.050582,0.054261,0.057307,0.059587,0.060998,0.061476,0.060998,0.059587,0.057307,0.054261,0.050582,0.046421,0.041944,0.037311,0.032676,0.028174); +const int dof_kernel_size = 21; +const int dof_kernel_from = 10; +const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174); #endif uniform sampler2D dof_source_depth; //texunit:1 @@ -88,7 +90,6 @@ uniform sampler2D source_dof_original; //texunit:2 #endif - #ifdef GLOW_FIRST_PASS uniform float exposure; @@ -112,53 +113,51 @@ uniform float camera_z_near; void main() { - - #ifdef GAUSSIAN_HORIZONTAL vec2 pix_size = pixel_size; - pix_size*=0.5; //reading from larger buffer, so use more samples - vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.214607; - color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.189879; - color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.157305; - color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.071303; - color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.189879; - color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.157305; - color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.071303; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.214607; + color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.189879; + color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.157305; + color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.071303; + color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.189879; + color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.157305; + color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.071303; frag_color = color; #endif #ifdef GAUSSIAN_VERTICAL - vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774; - color+=textureLod( source_color, uv_interp+vec2( 0.0, 1.0)*pixel_size,lod )*0.24477; - color+=textureLod( source_color, uv_interp+vec2( 0.0, 2.0)*pixel_size,lod )*0.06136; - color+=textureLod( source_color, uv_interp+vec2( 0.0,-1.0)*pixel_size,lod )*0.24477; - color+=textureLod( source_color, uv_interp+vec2( 0.0,-2.0)*pixel_size,lod )*0.06136; + vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.38774; + color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.24477; + color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.06136; + color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.24477; + color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.06136; frag_color = color; #endif -//glow uses larger sigma for a more rounded blur effect + //glow uses larger sigma for a more rounded blur effect #ifdef GLOW_GAUSSIAN_HORIZONTAL vec2 pix_size = pixel_size; - pix_size*=0.5; //reading from larger buffer, so use more samples - vec4 color =textureLod( source_color, uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.174938; - color+=textureLod( source_color, uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.106595; - color+=textureLod( source_color, uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.165569; - color+=textureLod( source_color, uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.140367; - color+=textureLod( source_color, uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.106595; - color*=glow_strength; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pix_size, lod) * 0.174938; + color += textureLod(source_color, uv_interp + vec2(1.0, 0.0) * pix_size, lod) * 0.165569; + color += textureLod(source_color, uv_interp + vec2(2.0, 0.0) * pix_size, lod) * 0.140367; + color += textureLod(source_color, uv_interp + vec2(3.0, 0.0) * pix_size, lod) * 0.106595; + color += textureLod(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size, lod) * 0.165569; + color += textureLod(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size, lod) * 0.140367; + color += textureLod(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size, lod) * 0.106595; + color *= glow_strength; frag_color = color; #endif #ifdef GLOW_GAUSSIAN_VERTICAL - vec4 color =textureLod( source_color, uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.288713; - color+=textureLod( source_color, uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.233062; - color+=textureLod( source_color, uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.122581; - color+=textureLod( source_color, uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.233062; - color+=textureLod( source_color, uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.122581; - color*=glow_strength; + vec4 color = textureLod(source_color, uv_interp + vec2(0.0, 0.0) * pixel_size, lod) * 0.288713; + color += textureLod(source_color, uv_interp + vec2(0.0, 1.0) * pixel_size, lod) * 0.233062; + color += textureLod(source_color, uv_interp + vec2(0.0, 2.0) * pixel_size, lod) * 0.122581; + color += textureLod(source_color, uv_interp + vec2(0.0, -1.0) * pixel_size, lod) * 0.233062; + color += textureLod(source_color, uv_interp + vec2(0.0, -2.0) * pixel_size, lod) * 0.122581; + color *= glow_strength; frag_color = color; #endif @@ -166,47 +165,45 @@ void main() { vec4 color_accum = vec4(0.0); - float depth = textureLod( dof_source_depth, uv_interp, 0.0).r; + float depth = textureLod(dof_source_depth, uv_interp, 0.0).r; depth = depth * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); #endif - float amount = smoothstep(dof_begin,dof_end,depth); - float k_accum=0.0; + float amount = smoothstep(dof_begin, dof_end, depth); + float k_accum = 0.0; - for(int i=0;i<dof_kernel_size;i++) { + for (int i = 0; i < dof_kernel_size; i++) { - int int_ofs = i-dof_kernel_from; + int int_ofs = i - dof_kernel_from; vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius; float tap_k = dof_kernel[i]; - float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r; + float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; tap_depth = tap_depth * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); #endif - float tap_amount = mix(smoothstep(dof_begin,dof_end,tap_depth),1.0,int_ofs==0); - tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect - - vec4 tap_color = textureLod( source_color, tap_uv, 0.0) * tap_k; - - k_accum+=tap_k*tap_amount; - color_accum+=tap_color*tap_amount; + float tap_amount = mix(smoothstep(dof_begin, dof_end, tap_depth), 1.0, int_ofs == 0); + tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect + vec4 tap_color = textureLod(source_color, tap_uv, 0.0) * tap_k; + k_accum += tap_k * tap_amount; + color_accum += tap_color * tap_amount; } - if (k_accum>0.0) { - color_accum/=k_accum; + if (k_accum > 0.0) { + color_accum /= k_accum; } - frag_color = color_accum;///k_accum; + frag_color = color_accum; ///k_accum; #endif @@ -214,47 +211,45 @@ void main() { vec4 color_accum = vec4(0.0); - float max_accum=0; + float max_accum = 0; - for(int i=0;i<dof_kernel_size;i++) { + for (int i = 0; i < dof_kernel_size; i++) { - int int_ofs = i-dof_kernel_from; + int int_ofs = i - dof_kernel_from; vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius; - float ofs_influence = max(0.0,1.0-float(abs(int_ofs))/float(dof_kernel_from)); + float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from)); float tap_k = dof_kernel[i]; - vec4 tap_color = textureLod( source_color, tap_uv, 0.0); + vec4 tap_color = textureLod(source_color, tap_uv, 0.0); - float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r; + float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; tap_depth = tap_depth * 2.0 - 1.0; -#ifdef USE_ORTHOGONAL_PROJECTION - tap_depth = ((tap_depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; +#ifdef USE_ORTHOGONAL_PROJECTION + tap_depth = ((tap_depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near)); #endif - float tap_amount = 1.0-smoothstep(dof_end,dof_begin,tap_depth); - tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect + float tap_amount = 1.0 - smoothstep(dof_end, dof_begin, tap_depth); + tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect #ifdef DOF_NEAR_FIRST_TAP - tap_color.a= 1.0-smoothstep(dof_end,dof_begin,tap_depth); + tap_color.a = 1.0 - smoothstep(dof_end, dof_begin, tap_depth); #endif - max_accum=max(max_accum,tap_amount*ofs_influence); - - color_accum+=tap_color*tap_k; + max_accum = max(max_accum, tap_amount * ofs_influence); + color_accum += tap_color * tap_k; } - color_accum.a=max(color_accum.a,sqrt(max_accum)); - + color_accum.a = max(color_accum.a, sqrt(max_accum)); #ifdef DOF_NEAR_BLUR_MERGE - vec4 original = textureLod( source_dof_original, uv_interp, 0.0); - color_accum = mix(original,color_accum,color_accum.a); + vec4 original = textureLod(source_dof_original, uv_interp, 0.0); + color_accum = mix(original, color_accum, color_accum.a); #endif @@ -265,37 +260,32 @@ void main() { #endif - - #ifdef GLOW_FIRST_PASS #ifdef GLOW_USE_AUTO_EXPOSURE - frag_color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; + frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey; #endif - frag_color*=exposure; + frag_color *= exposure; - float luminance = max(frag_color.r,max(frag_color.g,frag_color.b)); - float feedback = max( smoothstep(glow_hdr_threshold,glow_hdr_threshold+glow_hdr_scale,luminance), glow_bloom ); + float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); + float feedback = max(smoothstep(glow_hdr_threshold, glow_hdr_threshold + glow_hdr_scale, luminance), glow_bloom); frag_color *= feedback; #endif - #ifdef SIMPLE_COPY - vec4 color =textureLod( source_color, uv_interp,0.0); + vec4 color = textureLod(source_color, uv_interp, 0.0); frag_color = color; #endif #ifdef SSAO_MERGE - vec4 color =textureLod( source_color, uv_interp,0.0); - float ssao =textureLod( source_ssao, uv_interp,0.0).r; + vec4 color = textureLod(source_color, uv_interp, 0.0); + float ssao = textureLod(source_ssao, uv_interp, 0.0).r; - frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 ); + frag_color = vec4(mix(color.rgb, color.rgb * mix(ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0); #endif - - } diff --git a/drivers/gles2/shaders/exposure.glsl b/drivers/gles2/shaders/exposure.glsl index 001b90a0f1..759adcda06 100644 --- a/drivers/gles2/shaders/exposure.glsl +++ b/drivers/gles2/shaders/exposure.glsl @@ -1,19 +1,19 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; - +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ void main() { gl_Position = vertex_attrib; - } +/* clang-format off */ [fragment] - uniform highp sampler2D source_exposure; //texunit:0 +/* clang-format on */ #ifdef EXPOSURE_BEGIN @@ -33,66 +33,56 @@ uniform highp float max_luminance; layout(location = 0) out highp float exposure; - - void main() { - - #ifdef EXPOSURE_BEGIN - - ivec2 src_pos = ivec2(gl_FragCoord.xy)*source_render_size/target_size; + ivec2 src_pos = ivec2(gl_FragCoord.xy) * source_render_size / target_size; #if 1 //more precise and expensive, but less jittery - ivec2 next_pos = ivec2(gl_FragCoord.xy+ivec2(1))*source_render_size/target_size; - next_pos = max(next_pos,src_pos+ivec2(1)); //so it at least reads one pixel - highp vec3 source_color=vec3(0.0); - for(int i=src_pos.x;i<next_pos.x;i++) { - for(int j=src_pos.y;j<next_pos.y;j++) { - source_color += texelFetch(source_exposure,ivec2(i,j),0).rgb; + ivec2 next_pos = ivec2(gl_FragCoord.xy + ivec2(1)) * source_render_size / target_size; + next_pos = max(next_pos, src_pos + ivec2(1)); //so it at least reads one pixel + highp vec3 source_color = vec3(0.0); + for (int i = src_pos.x; i < next_pos.x; i++) { + for (int j = src_pos.y; j < next_pos.y; j++) { + source_color += texelFetch(source_exposure, ivec2(i, j), 0).rgb; } } - source_color/=float( (next_pos.x-src_pos.x)*(next_pos.y-src_pos.y) ); + source_color /= float((next_pos.x - src_pos.x) * (next_pos.y - src_pos.y)); #else - highp vec3 source_color = texelFetch(source_exposure,src_pos,0).rgb; + highp vec3 source_color = texelFetch(source_exposure, src_pos, 0).rgb; #endif - exposure = max(source_color.r,max(source_color.g,source_color.b)); + exposure = max(source_color.r, max(source_color.g, source_color.b)); #else ivec2 coord = ivec2(gl_FragCoord.xy); - exposure = texelFetch(source_exposure,coord*3+ivec2(0,0),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(1,0),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(2,0),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(0,1),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(1,1),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(2,1),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(0,2),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(1,2),0).r; - exposure += texelFetch(source_exposure,coord*3+ivec2(2,2),0).r; - exposure *= (1.0/9.0); + exposure = texelFetch(source_exposure, coord * 3 + ivec2(0, 0), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 0), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 0), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 1), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 1), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 1), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(0, 2), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(1, 2), 0).r; + exposure += texelFetch(source_exposure, coord * 3 + ivec2(2, 2), 0).r; + exposure *= (1.0 / 9.0); #ifdef EXPOSURE_END #ifdef EXPOSURE_FORCE_SET //will stay as is #else - highp float prev_lum = texelFetch(prev_exposure,ivec2(0,0),0).r; //1 pixel previous exposure - exposure = clamp( prev_lum + (exposure-prev_lum)*exposure_adjust,min_luminance,max_luminance); + highp float prev_lum = texelFetch(prev_exposure, ivec2(0, 0), 0).r; //1 pixel previous exposure + exposure = clamp(prev_lum + (exposure - prev_lum) * exposure_adjust, min_luminance, max_luminance); #endif //EXPOSURE_FORCE_SET - #endif //EXPOSURE_END #endif //EXPOSURE_BEGIN - - } - - diff --git a/drivers/gles2/shaders/lens_distorted.glsl b/drivers/gles2/shaders/lens_distorted.glsl new file mode 100644 index 0000000000..d541db9bf9 --- /dev/null +++ b/drivers/gles2/shaders/lens_distorted.glsl @@ -0,0 +1,62 @@ +/* clang-format off */ +[vertex] + +attribute highp vec2 vertex; // attrib:0 +/* clang-format on */ + +uniform vec2 offset; +uniform vec2 scale; + +varying vec2 uv_interp; + +void main() { + + uv_interp = vertex.xy * 2.0 - 1.0; + + vec2 v = vertex.xy * scale + offset; + gl_Position = vec4(v, 0.0, 1.0); +} + +/* clang-format off */ +[fragment] + +uniform sampler2D source; //texunit:0 +/* clang-format on */ + +uniform vec2 eye_center; +uniform float k1; +uniform float k2; +uniform float upscale; +uniform float aspect_ratio; + +varying vec2 uv_interp; + +void main() { + vec2 coords = uv_interp; + vec2 offset = coords - eye_center; + + // take aspect ratio into account + offset.y /= aspect_ratio; + + // distort + vec2 offset_sq = offset * offset; + float radius_sq = offset_sq.x + offset_sq.y; + float radius_s4 = radius_sq * radius_sq; + float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4); + offset *= distortion_scale; + + // reapply aspect ratio + offset.y *= aspect_ratio; + + // add our eye center back in + coords = offset + eye_center; + coords /= upscale; + + // and check our color + if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) { + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); + } else { + coords = (coords + vec2(1.0)) / vec2(2.0); + gl_FragColor = texture2D(source, coords); + } +} diff --git a/drivers/gles2/shaders/particles.glsl b/drivers/gles2/shaders/particles.glsl index a62c124dfe..5974050fc1 100644 --- a/drivers/gles2/shaders/particles.glsl +++ b/drivers/gles2/shaders/particles.glsl @@ -1,14 +1,13 @@ +/* clang-format off */ [vertex] - - -layout(location=0) in highp vec4 color; -layout(location=1) in highp vec4 velocity_active; -layout(location=2) in highp vec4 custom; -layout(location=3) in highp vec4 xform_1; -layout(location=4) in highp vec4 xform_2; -layout(location=5) in highp vec4 xform_3; - +layout(location = 0) in highp vec4 color; +/* clang-format on */ +layout(location = 1) in highp vec4 velocity_active; +layout(location = 2) in highp vec4 custom; +layout(location = 3) in highp vec4 xform_1; +layout(location = 4) in highp vec4 xform_2; +layout(location = 5) in highp vec4 xform_3; struct Attractor { @@ -39,7 +38,6 @@ uniform float lifetime; uniform mat4 emission_transform; uniform uint random_seed; - out highp vec4 out_color; //tfb: out highp vec4 out_velocity_active; //tfb: out highp vec4 out_custom; //tfb: @@ -47,20 +45,24 @@ out highp vec4 out_xform_1; //tfb: out highp vec4 out_xform_2; //tfb: out highp vec4 out_xform_3; //tfb: - #if defined(USE_MATERIAL) +/* clang-format off */ layout(std140) uniform UniformData { //ubo:0 MATERIAL_UNIFORMS }; +/* clang-format on */ #endif +/* clang-format off */ VERTEX_SHADER_GLOBALS +/* clang-format on */ + uint hash(uint x) { x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); @@ -69,13 +71,12 @@ uint hash(uint x) { return x; } - void main() { #ifdef PARTICLES_COPY - out_color=color; - out_velocity_active=velocity_active; + out_color = color; + out_velocity_active = velocity_active; out_custom = custom; out_xform_1 = xform_1; out_xform_2 = xform_2; @@ -83,34 +84,34 @@ void main() { #else - bool apply_forces=true; - bool apply_velocity=true; - float local_delta=delta; + bool apply_forces = true; + bool apply_velocity = true; + float local_delta = delta; float mass = 1.0; - float restart_phase = float(gl_VertexID)/float(total_particles); + float restart_phase = float(gl_VertexID) / float(total_particles); - if (randomness>0.0) { + if (randomness > 0.0) { uint seed = cycle; if (restart_phase >= system_phase) { - seed-=uint(1); + seed -= uint(1); } - seed*=uint(total_particles); - seed+=uint(gl_VertexID); + seed *= uint(total_particles); + seed += uint(gl_VertexID); float random = float(hash(seed) % uint(65536)) / 65536.0; - restart_phase+=randomness * random * 1.0 / float(total_particles); + restart_phase += randomness * random * 1.0 / float(total_particles); } - restart_phase*= (1.0-explosiveness); - bool restart=false; + restart_phase *= (1.0 - explosiveness); + bool restart = false; bool shader_active = velocity_active.a > 0.5; if (system_phase > prev_system_phase) { // restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed - if (restart_phase >= prev_system_phase && restart_phase < system_phase ) { - restart=true; + if (restart_phase >= prev_system_phase && restart_phase < system_phase) { + restart = true; #ifdef USE_FRACTIONAL_DELTA local_delta = (system_phase - restart_phase) * lifetime; #endif @@ -118,12 +119,12 @@ void main() { } else { if (restart_phase >= prev_system_phase) { - restart=true; + restart = true; #ifdef USE_FRACTIONAL_DELTA local_delta = (1.0 - restart_phase + system_phase) * lifetime; #endif - } else if (restart_phase < system_phase ) { - restart=true; + } else if (restart_phase < system_phase) { + restart = true; #ifdef USE_FRACTIONAL_DELTA local_delta = (system_phase - restart_phase) * lifetime; #endif @@ -133,14 +134,14 @@ void main() { uint current_cycle = cycle; if (system_phase < restart_phase) { - current_cycle-=uint(1); + current_cycle -= uint(1); } uint particle_number = current_cycle * uint(total_particles) + uint(gl_VertexID); int index = int(gl_VertexID); if (restart) { - shader_active=emitting; + shader_active = emitting; } mat4 xform; @@ -150,30 +151,33 @@ void main() { #else if (clear || restart) { #endif - out_color=vec4(1.0); - out_velocity_active=vec4(0.0); - out_custom=vec4(0.0); + out_color = vec4(1.0); + out_velocity_active = vec4(0.0); + out_custom = vec4(0.0); if (!restart) - shader_active=false; + shader_active = false; xform = mat4( - vec4(1.0,0.0,0.0,0.0), - vec4(0.0,1.0,0.0,0.0), - vec4(0.0,0.0,1.0,0.0), - vec4(0.0,0.0,0.0,1.0) - ); + vec4(1.0, 0.0, 0.0, 0.0), + vec4(0.0, 1.0, 0.0, 0.0), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); } else { - out_color=color; - out_velocity_active=velocity_active; - out_custom=custom; - xform = transpose(mat4(xform_1,xform_2,xform_3,vec4(vec3(0.0),1.0))); + out_color = color; + out_velocity_active = velocity_active; + out_custom = custom; + xform = transpose(mat4(xform_1, xform_2, xform_3, vec4(vec3(0.0), 1.0))); } if (shader_active) { //execute shader { + /* clang-format off */ + VERTEX_SHADER_CODE + + /* clang-format on */ } #if !defined(DISABLE_FORCE) @@ -181,26 +185,25 @@ VERTEX_SHADER_CODE if (false) { vec3 force = vec3(0.0); - for(int i=0;i<attractor_count;i++) { + for (int i = 0; i < attractor_count; i++) { vec3 rel_vec = xform[3].xyz - attractors[i].pos; float dist = length(rel_vec); if (attractors[i].radius < dist) continue; - if (attractors[i].eat_radius>0.0 && attractors[i].eat_radius > dist) { - out_velocity_active.a=0.0; + if (attractors[i].eat_radius > 0.0 && attractors[i].eat_radius > dist) { + out_velocity_active.a = 0.0; } rel_vec = normalize(rel_vec); - float attenuation = pow(dist / attractors[i].radius,attractors[i].attenuation); + float attenuation = pow(dist / attractors[i].radius, attractors[i].attenuation); - if (attractors[i].dir==vec3(0.0)) { + if (attractors[i].dir == vec3(0.0)) { //towards center - force+=attractors[i].strength * rel_vec * attenuation * mass; + force += attractors[i].strength * rel_vec * attenuation * mass; } else { - force+=attractors[i].strength * attractors[i].dir * attenuation *mass; - + force += attractors[i].strength * attractors[i].dir * attenuation * mass; } } @@ -216,26 +219,25 @@ VERTEX_SHADER_CODE } #endif } else { - xform=mat4(0.0); + xform = mat4(0.0); } xform = transpose(xform); - out_velocity_active.a = mix(0.0,1.0,shader_active); + out_velocity_active.a = mix(0.0, 1.0, shader_active); out_xform_1 = xform[0]; out_xform_2 = xform[1]; out_xform_3 = xform[2]; #endif //PARTICLES_COPY - } +/* clang-format off */ [fragment] //any code here is never executed, stuff is filled just so it works - #if defined(USE_MATERIAL) layout(std140) uniform UniformData { @@ -249,12 +251,16 @@ MATERIAL_UNIFORMS FRAGMENT_SHADER_GLOBALS void main() { - { + LIGHT_SHADER_CODE + } { + FRAGMENT_SHADER_CODE + } } +/* clang-format on */ diff --git a/drivers/gles2/shaders/resolve.glsl b/drivers/gles2/shaders/resolve.glsl index 0b50a9c57b..5c6f5d6561 100644 --- a/drivers/gles2/shaders/resolve.glsl +++ b/drivers/gles2/shaders/resolve.glsl @@ -1,18 +1,19 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; out vec2 uv_interp; - void main() { uv_interp = uv_in; gl_Position = vertex_attrib; } +/* clang-format off */ [fragment] #if !defined(GLES_OVER_GL) @@ -20,6 +21,7 @@ precision mediump float; #endif in vec2 uv_interp; +/* clang-format on */ uniform sampler2D source_specular; //texunit:0 uniform sampler2D source_ssr; //texunit:1 @@ -31,14 +33,12 @@ layout(location = 0) out vec4 frag_color; void main() { - vec4 specular = texture( source_specular, uv_interp ); + vec4 specular = texture(source_specular, uv_interp); #ifdef USE_SSR - - vec4 ssr = textureLod(source_ssr,uv_interp,0.0); - specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a); + vec4 ssr = textureLod(source_ssr, uv_interp, 0.0); + specular.rgb = mix(specular.rgb, ssr.rgb * specular.a, ssr.a); #endif - frag_color = vec4(specular.rgb,1.0); + frag_color = vec4(specular.rgb, 1.0); } - diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index e08e9d1117..15b90a7771 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -1,15 +1,19 @@ +/* clang-format off */ [vertex] #ifdef USE_GLES_OVER_GL #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif #include "stdlib.glsl" +#define SHADER_IS_SRGB true + +#define M_PI 3.14159265359 // @@ -17,21 +21,22 @@ precision mediump int; // attribute highp vec4 vertex_attrib; // attrib:0 +/* clang-format on */ attribute vec3 normal_attrib; // attrib:1 #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) attribute vec4 tangent_attrib; // attrib:2 #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) attribute vec4 color_attrib; // attrib:3 #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) attribute vec2 uv_attrib; // attrib:4 #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) attribute vec2 uv2_attrib; // attrib:5 #endif @@ -39,16 +44,16 @@ attribute vec2 uv2_attrib; // attrib:5 #ifdef USE_SKELETON_SOFTWARE -attribute highp vec4 bone_transform_row_0; // attrib:9 -attribute highp vec4 bone_transform_row_1; // attrib:10 -attribute highp vec4 bone_transform_row_2; // attrib:11 +attribute highp vec4 bone_transform_row_0; // attrib:13 +attribute highp vec4 bone_transform_row_1; // attrib:14 +attribute highp vec4 bone_transform_row_2; // attrib:15 #else attribute vec4 bone_ids; // attrib:6 attribute highp vec4 bone_weights; // attrib:7 -uniform highp sampler2D bone_transforms; // texunit:4 +uniform highp sampler2D bone_transforms; // texunit:-1 uniform ivec2 skeleton_texture_size; #endif @@ -57,38 +62,33 @@ uniform ivec2 skeleton_texture_size; #ifdef USE_INSTANCING -attribute highp vec4 instance_xform_row_0; // attrib:12 -attribute highp vec4 instance_xform_row_1; // attrib:13 -attribute highp vec4 instance_xform_row_2; // attrib:14 +attribute highp vec4 instance_xform_row_0; // attrib:8 +attribute highp vec4 instance_xform_row_1; // attrib:9 +attribute highp vec4 instance_xform_row_2; // attrib:10 -attribute highp vec4 instance_color; // attrib:15 -attribute highp vec4 instance_custom_data; // attrib:8 +attribute highp vec4 instance_color; // attrib:11 +attribute highp vec4 instance_custom_data; // attrib:12 #endif - - // // uniforms // -uniform mat4 camera_matrix; -uniform mat4 camera_inverse_matrix; -uniform mat4 projection_matrix; -uniform mat4 projection_inverse_matrix; +uniform highp mat4 camera_matrix; +uniform highp mat4 camera_inverse_matrix; +uniform highp mat4 projection_matrix; +uniform highp mat4 projection_inverse_matrix; -uniform mat4 world_transform; +uniform highp mat4 world_transform; uniform highp float time; -uniform float normal_mult; - #ifdef RENDER_DEPTH uniform float light_bias; uniform float light_normal_bias; #endif - // // varyings // @@ -101,21 +101,215 @@ varying vec3 tangent_interp; varying vec3 binormal_interp; #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) varying vec4 color_interp; #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) varying vec2 uv_interp; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) varying vec2 uv2_interp; #endif +/* clang-format off */ VERTEX_SHADER_GLOBALS +/* clang-format on */ + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + +varying highp float dp_clip; +uniform highp float shadow_dual_paraboloid_render_zfar; +uniform highp float shadow_dual_paraboloid_render_side; + +#endif + +#if defined(USE_SHADOW) && defined(USE_LIGHTING) + +uniform highp mat4 light_shadow_matrix; +varying highp vec4 shadow_coord; + +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) +uniform highp mat4 light_shadow_matrix2; +varying highp vec4 shadow_coord2; +#endif + +#if defined(LIGHT_USE_PSSM4) + +uniform highp mat4 light_shadow_matrix3; +uniform highp mat4 light_shadow_matrix4; +varying highp vec4 shadow_coord3; +varying highp vec4 shadow_coord4; + +#endif + +#endif + +#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) + +varying highp vec3 diffuse_interp; +varying highp vec3 specular_interp; + +// general for all lights +uniform highp vec4 light_color; +uniform highp float light_specular; + +// directional +uniform highp vec3 light_direction; + +// omni +uniform highp vec3 light_position; + +uniform highp float light_range; +uniform highp float light_attenuation; + +// spot +uniform highp float light_spot_attenuation; +uniform highp float light_spot_range; +uniform highp float light_spot_angle; + +void light_compute( + vec3 N, + vec3 L, + vec3 V, + vec3 light_color, + vec3 attenuation, + float roughness) { + +//this makes lights behave closer to linear, but then addition of lights looks bad +//better left disabled + +//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); +/* +#define SRGB_APPROX(m_var) {\ + float S1 = sqrt(m_var);\ + float S2 = sqrt(S1);\ + float S3 = sqrt(S2);\ + m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ + } +*/ +#define SRGB_APPROX(m_var) + + float NdotL = dot(N, L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); + +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + +#if defined(DIFFUSE_LAMBERT_WRAP) + // energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } +#else + // lambert by default for everything else + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + + SRGB_APPROX(diffuse_brdf_NL) + + diffuse_interp += light_color * diffuse_brdf_NL * attenuation; + + if (roughness > 0.0) { + + // D + float specular_brdf_NL = 0.0; + +#if !defined(SPECULAR_DISABLED) + //normalized blinn always unless disabled + vec3 H = normalize(V + L); + float cNdotH = max(dot(N, H), 0.0); + float cVdotH = max(dot(V, H), 0.0); + float cLdotH = max(dot(L, H), 0.0); + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); +#endif + + SRGB_APPROX(specular_brdf_NL) + specular_interp += specular_brdf_NL * light_color * attenuation; + } +} + +#endif + +#ifdef USE_VERTEX_LIGHTING + +#ifdef USE_REFLECTION_PROBE1 + +uniform highp mat4 refprobe1_local_matrix; +varying mediump vec4 refprobe1_reflection_normal_blend; +uniform highp vec3 refprobe1_box_extents; + +#ifndef USE_LIGHTMAP +varying mediump vec3 refprobe1_ambient_normal; +#endif + +#endif //reflection probe1 + +#ifdef USE_REFLECTION_PROBE2 + +uniform highp mat4 refprobe2_local_matrix; +varying mediump vec4 refprobe2_reflection_normal_blend; +uniform highp vec3 refprobe2_box_extents; + +#ifndef USE_LIGHTMAP +varying mediump vec3 refprobe2_ambient_normal; +#endif + +#endif //reflection probe2 + +#endif //vertex lighting for refprobes + +#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) + +varying vec4 fog_interp; + +uniform mediump vec4 fog_color_base; +#ifdef LIGHT_MODE_DIRECTIONAL +uniform mediump vec4 fog_sun_color_amount; +#endif + +uniform bool fog_transmit_enabled; +uniform mediump float fog_transmit_curve; + +#ifdef FOG_DEPTH_ENABLED +uniform highp float fog_depth_begin; +uniform mediump float fog_depth_curve; +uniform mediump float fog_max_distance; +#endif + +#ifdef FOG_HEIGHT_ENABLED +uniform highp float fog_height_min; +uniform highp float fog_height_max; +uniform mediump float fog_height_curve; +#endif + +#endif //fog + void main() { highp vec4 vertex = vertex_attrib; @@ -124,35 +318,36 @@ void main() { #ifdef USE_INSTANCING { - highp mat4 m = mat4(instance_xform_row_0, - instance_xform_row_1, - instance_xform_row_2, - vec4(0.0, 0.0, 0.0, 1.0)); + highp mat4 m = mat4( + instance_xform_row_0, + instance_xform_row_1, + instance_xform_row_2, + vec4(0.0, 0.0, 0.0, 1.0)); world_matrix = world_matrix * transpose(m); } + #endif - vec3 normal = normal_attrib * normal_mult; + vec3 normal = normal_attrib; #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) vec3 tangent = tangent_attrib.xyz; - tangent *= normal_mult; float binormalf = tangent_attrib.a; vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) color_interp = color_attrib; #ifdef USE_INSTANCING color_interp *= instance_color; #endif #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) uv_interp = uv_attrib; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) uv2_interp = uv2_attrib; #endif @@ -161,14 +356,14 @@ void main() { normal = normalize((world_matrix * vec4(normal, 0.0)).xyz); #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((world_matrix * vec4(tangent, 0.0)),xyz); + tangent = normalize((world_matrix * vec4(tangent, 0.0)).xyz); binormal = normalize((world_matrix * vec4(binormal, 0.0)).xyz); #endif #endif #ifdef USE_SKELETON - highp mat4 bone_transform = mat4(1.0); + highp mat4 bone_transform = mat4(0.0); #ifdef USE_SKELETON_SOFTWARE // passing the transform as attributes @@ -181,14 +376,15 @@ void main() { #else // look up transform from the "pose texture" { - + for (int i = 0; i < 4; i++) { ivec2 tex_ofs = ivec2(int(bone_ids[i]) * 3, 0); - highp mat4 b = mat4(texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(0, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(1, 0)), - texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(2, 0)), - vec4(0.0, 0.0, 0.0, 1.0)); + highp mat4 b = mat4( + texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(0, 0)), + texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(1, 0)), + texel2DFetch(bone_transforms, skeleton_texture_size, tex_ofs + ivec2(2, 0)), + vec4(0.0, 0.0, 0.0, 1.0)); bone_transform += transpose(b) * bone_weights[i]; } @@ -199,7 +395,6 @@ void main() { world_matrix = bone_transform * world_matrix; #endif - #ifdef USE_INSTANCING vec4 instance_custom = instance_custom_data; #else @@ -207,16 +402,18 @@ void main() { #endif - - mat4 modelview = camera_matrix * world_matrix; + mat4 modelview = camera_inverse_matrix * world_matrix; + float roughness = 1.0; #define world_transform world_matrix -{ + { + /* clang-format off */ VERTEX_SHADER_CODE -} + /* clang-format on */ + } vec4 outvec = vertex; @@ -232,11 +429,11 @@ VERTEX_SHADER_CODE #endif #if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - vertex = camera_matrix * vertex; - normal = normalize((camera_matrix * vec4(normal, 0.0)).xyz); + vertex = camera_inverse_matrix * vertex; + normal = normalize((camera_inverse_matrix * vec4(normal, 0.0)).xyz); #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) - tangent = normalize((camera_matrix * vec4(tangent, 0.0)).xyz); - binormal = normalize((camera_matrix * vec4(binormal, 0.0)).xyz); + tangent = normalize((camera_inverse_matrix * vec4(tangent, 0.0)).xyz); + binormal = normalize((camera_inverse_matrix * vec4(binormal, 0.0)).xyz); #endif #endif @@ -250,61 +447,410 @@ VERTEX_SHADER_CODE #ifdef RENDER_DEPTH +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + + vertex_interp.z *= shadow_dual_paraboloid_render_side; + normal_interp.z *= shadow_dual_paraboloid_render_side; + + dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias + + //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges + + highp vec3 vtx = vertex_interp + normalize(vertex_interp) * light_bias; + highp float distance = length(vtx); + vtx = normalize(vtx); + vtx.xy /= 1.0 - vtx.z; + vtx.z = (distance / shadow_dual_paraboloid_render_zfar); + vtx.z = vtx.z * 2.0 - 1.0; + + vertex_interp = vtx; + +#else float z_ofs = light_bias; z_ofs += (1.0 - abs(normal_interp.z)) * light_normal_bias; - + vertex_interp.z -= z_ofs; +#endif //dual parabolloid + +#endif //depth + +//vertex lighting +#if defined(USE_VERTEX_LIGHTING) && defined(USE_LIGHTING) + //vertex shaded version of lighting (more limited) + vec3 L; + vec3 light_att; + +#ifdef LIGHT_MODE_OMNI + vec3 light_vec = light_position - vertex_interp; + float light_length = length(light_vec); + + float normalized_distance = light_length / light_range; + + if (normalized_distance < 1.0) { + + float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); + + vec3 attenuation = vec3(omni_attenuation); + light_att = vec3(omni_attenuation); + } else { + light_att = vec3(0.0); + } + + L = normalize(light_vec); #endif - gl_Position = projection_matrix * vec4(vertex_interp, 1.0); +#ifdef LIGHT_MODE_SPOT + + vec3 light_rel_vec = light_position - vertex_interp; + float light_length = length(light_rel_vec); + float normalized_distance = light_length / light_range; + + if (normalized_distance < 1.0) { + + float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); + vec3 spot_dir = light_direction; + + float spot_cutoff = light_spot_angle; + + float angle = dot(-normalize(light_rel_vec), spot_dir); + + if (angle > spot_cutoff) { + + float scos = max(angle, spot_cutoff); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); + + spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); + + light_att = vec3(spot_attenuation); + } else { + light_att = vec3(0.0); + } + } else { + light_att = vec3(0.0); + } + + L = normalize(light_rel_vec); + +#endif + +#ifdef LIGHT_MODE_DIRECTIONAL + vec3 light_vec = -light_direction; + light_att = vec3(1.0); //no base attenuation + L = normalize(light_vec); +#endif + + diffuse_interp = vec3(0.0); + specular_interp = vec3(0.0); + light_compute(normal_interp, L, -normalize(vertex_interp), light_color.rgb, light_att, roughness); + +#endif + +//shadows (for both vertex and fragment) +#if defined(USE_SHADOW) && defined(USE_LIGHTING) + + vec4 vi4 = vec4(vertex_interp, 1.0); + shadow_coord = light_shadow_matrix * vi4; + +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) + shadow_coord2 = light_shadow_matrix2 * vi4; +#endif + +#if defined(LIGHT_USE_PSSM4) + shadow_coord3 = light_shadow_matrix3 * vi4; + shadow_coord4 = light_shadow_matrix4 * vi4; + +#endif + +#endif //use shadow and use lighting + +#ifdef USE_VERTEX_LIGHTING + +#ifdef USE_REFLECTION_PROBE1 + { + vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); + vec3 local_pos = (refprobe1_local_matrix * vec4(vertex_interp, 1.0)).xyz; + vec3 inner_pos = abs(local_pos / refprobe1_box_extents); + float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + + { + vec3 local_ref_vec = (refprobe1_local_matrix * vec4(ref_normal, 0.0)).xyz; + refprobe1_reflection_normal_blend.xyz = local_ref_vec; + refprobe1_reflection_normal_blend.a = blend; + } +#ifndef USE_LIGHTMAP + + refprobe1_ambient_normal = (refprobe1_local_matrix * vec4(normal_interp, 0.0)).xyz; +#endif + } +#endif //USE_REFLECTION_PROBE1 + +#ifdef USE_REFLECTION_PROBE2 + { + vec3 ref_normal = normalize(reflect(vertex_interp, normal_interp)); + vec3 local_pos = (refprobe2_local_matrix * vec4(vertex_interp, 1.0)).xyz; + vec3 inner_pos = abs(local_pos / refprobe2_box_extents); + float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + + { + vec3 local_ref_vec = (refprobe2_local_matrix * vec4(ref_normal, 0.0)).xyz; + refprobe2_reflection_normal_blend.xyz = local_ref_vec; + refprobe2_reflection_normal_blend.a = blend; + } +#ifndef USE_LIGHTMAP + + refprobe2_ambient_normal = (refprobe2_local_matrix * vec4(normal_interp, 0.0)).xyz; +#endif + } + +#endif //USE_REFLECTION_PROBE2 + +#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) + + float fog_amount = 0.0; + +#ifdef LIGHT_MODE_DIRECTIONAL + + vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(normalize(vertex_interp), light_direction), 0.0), 8.0)); +#else + vec3 fog_color = fog_color_base.rgb; +#endif + +#ifdef FOG_DEPTH_ENABLED + + { + + float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); + + fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; + } +#endif + +#ifdef FOG_HEIGHT_ENABLED + { + float y = (camera_matrix * vec4(vertex_interp, 1.0)).y; + fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); + } +#endif + fog_interp = vec4(fog_color, fog_amount); + +#endif //fog + +#endif //use vertex lighting + gl_Position = projection_matrix * vec4(vertex_interp, 1.0); } +/* clang-format off */ [fragment] -#extension GL_ARB_shader_texture_lod : require +#extension GL_ARB_shader_texture_lod : enable + +#ifndef GL_ARB_shader_texture_lod +#define texture2DLod(img, coord, lod) texture2D(img, coord) +#define textureCubeLod(img, coord, lod) textureCube(img, coord) +#endif #ifdef USE_GLES_OVER_GL #define mediump #define highp #else precision mediump float; -precision mediump int; +precision highp int; #endif #include "stdlib.glsl" #define M_PI 3.14159265359 +#define SHADER_IS_SRGB true // // uniforms // -uniform mat4 camera_matrix; -uniform mat4 camera_inverse_matrix; -uniform mat4 projection_matrix; -uniform mat4 projection_inverse_matrix; +uniform highp mat4 camera_matrix; +/* clang-format on */ +uniform highp mat4 camera_inverse_matrix; +uniform highp mat4 projection_matrix; +uniform highp mat4 projection_inverse_matrix; -uniform mat4 world_transform; +uniform highp mat4 world_transform; uniform highp float time; - -#ifdef SCREEN_UV_USED +#if defined(SCREEN_UV_USED) uniform vec2 screen_pixel_size; #endif -uniform highp sampler2D depth_buffer; //texunit:1 +// I think supporting this in GLES2 is difficult +// uniform highp sampler2D depth_buffer; #if defined(SCREEN_TEXTURE_USED) -uniform highp sampler2D screen_texture; //texunit:2 +uniform highp sampler2D screen_texture; //texunit:-4 #endif -#ifdef USE_RADIANCE_MAP +#ifdef USE_REFLECTION_PROBE1 + +#ifdef USE_VERTEX_LIGHTING + +varying mediump vec4 refprobe1_reflection_normal_blend; +#ifndef USE_LIGHTMAP +varying mediump vec3 refprobe1_ambient_normal; +#endif + +#else + +uniform bool refprobe1_use_box_project; +uniform highp vec3 refprobe1_box_extents; +uniform vec3 refprobe1_box_offset; +uniform highp mat4 refprobe1_local_matrix; + +#endif //use vertex lighting + +uniform bool refprobe1_exterior; + +uniform highp samplerCube reflection_probe1; //texunit:-5 + +uniform float refprobe1_intensity; +uniform vec4 refprobe1_ambient; + +#endif //USE_REFLECTION_PROBE1 + +#ifdef USE_REFLECTION_PROBE2 + +#ifdef USE_VERTEX_LIGHTING + +varying mediump vec4 refprobe2_reflection_normal_blend; +#ifndef USE_LIGHTMAP +varying mediump vec3 refprobe2_ambient_normal; +#endif + +#else + +uniform bool refprobe2_use_box_project; +uniform highp vec3 refprobe2_box_extents; +uniform vec3 refprobe2_box_offset; +uniform highp mat4 refprobe2_local_matrix; + +#endif //use vertex lighting + +uniform bool refprobe2_exterior; + +uniform highp samplerCube reflection_probe2; //texunit:-6 + +uniform float refprobe2_intensity; +uniform vec4 refprobe2_ambient; + +#endif //USE_REFLECTION_PROBE2 #define RADIANCE_MAX_LOD 6.0 -uniform samplerCube radiance_map; // texunit:0 +#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) + +void reflection_process(samplerCube reflection_map, +#ifdef USE_VERTEX_LIGHTING + vec3 ref_normal, +#ifndef USE_LIGHTMAP + vec3 amb_normal, +#endif + float ref_blend, + +#else //no vertex lighting + vec3 normal, vec3 vertex, + mat4 local_matrix, + bool use_box_project, vec3 box_extents, vec3 box_offset, +#endif //vertex lighting + bool exterior, float intensity, vec4 ref_ambient, float roughness, vec3 ambient, vec3 skybox, inout highp vec4 reflection_accum, inout highp vec4 ambient_accum) { + + vec4 reflection; + +#ifdef USE_VERTEX_LIGHTING + + reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; + + float blend = ref_blend; //crappier blend formula for vertex + blend *= blend; + blend = max(0.0, 1.0 - blend); + +#else //fragment lighting + + vec3 local_pos = (local_matrix * vec4(vertex, 1.0)).xyz; + + if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box + return; + } + + vec3 inner_pos = abs(local_pos / box_extents); + float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + blend = mix(length(inner_pos), blend, blend); + blend *= blend; + blend = max(0.0, 1.0 - blend); + + //reflect and make local + vec3 ref_normal = normalize(reflect(vertex, normal)); + ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz; + + if (use_box_project) { //box project + + vec3 nrdir = normalize(ref_normal); + vec3 rbmax = (box_extents - local_pos) / nrdir; + vec3 rbmin = (-box_extents - local_pos) / nrdir; + + vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0)))); + + float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); + vec3 posonbox = local_pos + nrdir * fa; + ref_normal = posonbox - box_offset.xyz; + } + + reflection.rgb = textureCubeLod(reflection_map, ref_normal, roughness * RADIANCE_MAX_LOD).rgb; +#endif + + if (exterior) { + reflection.rgb = mix(skybox, reflection.rgb, blend); + } + reflection.rgb *= intensity; + reflection.a = blend; + reflection.rgb *= blend; + + reflection_accum += reflection; + +#ifndef USE_LIGHTMAP + + vec4 ambient_out; +#ifndef USE_VERTEX_LIGHTING + + vec3 amb_normal = (local_matrix * vec4(normal, 0.0)).xyz; +#endif + + ambient_out.rgb = textureCubeLod(reflection_map, amb_normal, RADIANCE_MAX_LOD).rgb; + ambient_out.rgb = mix(ref_ambient.rgb, ambient_out.rgb, ref_ambient.a); + if (exterior) { + ambient_out.rgb = mix(ambient, ambient_out.rgb, blend); + } + + ambient_out.a = blend; + ambient_out.rgb *= blend; + ambient_accum += ambient_out; + +#endif +} + +#endif //use refprobe 1 or 2 + +#ifdef USE_LIGHTMAP +uniform mediump sampler2D lightmap; //texunit:-4 +uniform mediump float lightmap_energy; +#endif + +#ifdef USE_LIGHTMAP_CAPTURE +uniform mediump vec4[12] lightmap_captures; +uniform bool lightmap_capture_sky; + +#endif + +#ifdef USE_RADIANCE_MAP + +uniform samplerCube radiance_map; // texunit:-2 uniform mat4 radiance_inverse_xform; @@ -316,52 +862,71 @@ uniform float ambient_sky_contribution; uniform vec4 ambient_color; uniform float ambient_energy; -#ifdef LIGHT_PASS +#ifdef USE_LIGHTING -#define LIGHT_TYPE_DIRECTIONAL 0 -#define LIGHT_TYPE_OMNI 1 -#define LIGHT_TYPE_SPOT 2 +#ifdef USE_VERTEX_LIGHTING -// general for all lights -uniform int light_type; +//get from vertex +varying highp vec3 diffuse_interp; +varying highp vec3 specular_interp; -uniform float light_energy; -uniform vec4 light_color; -uniform float light_specular; +uniform highp vec3 light_direction; //may be used by fog, so leave here -// directional -uniform vec3 light_direction; +#else +//done in fragment +// general for all lights +uniform highp vec4 light_color; +uniform highp float light_specular; +// directional +uniform highp vec3 light_direction; // omni -uniform vec3 light_position; +uniform highp vec3 light_position; -uniform float light_range; -uniform vec4 light_attenuation; +uniform highp float light_attenuation; // spot -uniform float light_spot_attenuation; -uniform float light_spot_range; -uniform float light_spot_angle; +uniform highp float light_spot_attenuation; +uniform highp float light_spot_range; +uniform highp float light_spot_angle; +#endif +//this is needed outside above if because dual paraboloid wants it +uniform highp float light_range; -// shadows -uniform highp sampler2D light_shadow_atlas; //texunit:3 -uniform float light_has_shadow; +#ifdef USE_SHADOW -uniform mat4 light_shadow_matrix; -uniform vec4 light_clamp; +uniform highp vec2 shadow_pixel_size; -// directional shadow +#if defined(LIGHT_MODE_OMNI) || defined(LIGHT_MODE_SPOT) +uniform highp sampler2D light_shadow_atlas; //texunit:-3 +#endif -uniform highp sampler2D light_directional_shadow; // texunit:3 -uniform vec4 light_split_offsets; +#ifdef LIGHT_MODE_DIRECTIONAL +uniform highp sampler2D light_directional_shadow; // texunit:-3 +uniform highp vec4 light_split_offsets; +#endif + +varying highp vec4 shadow_coord; -uniform mat4 light_shadow_matrix1; -uniform mat4 light_shadow_matrix2; -uniform mat4 light_shadow_matrix3; -uniform mat4 light_shadow_matrix4; +#if defined(LIGHT_USE_PSSM2) || defined(LIGHT_USE_PSSM4) +varying highp vec4 shadow_coord2; #endif +#if defined(LIGHT_USE_PSSM4) + +varying highp vec4 shadow_coord3; +varying highp vec4 shadow_coord4; + +#endif + +uniform vec4 light_clamp; + +#endif // light shadow + +// directional shadow + +#endif // // varyings @@ -375,126 +940,473 @@ varying vec3 tangent_interp; varying vec3 binormal_interp; #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) varying vec4 color_interp; #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) varying vec2 uv_interp; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) varying vec2 uv2_interp; #endif varying vec3 view_interp; -vec3 metallic_to_specular_color(float metallic, float specular, vec3 albedo) { - float dielectric = (0.034 * 2.0) * specular; - // energy conservation - return mix(vec3(dielectric), albedo, metallic); // TODO: reference? +vec3 F0(float metallic, float specular, vec3 albedo) { + float dielectric = 0.16 * specular * specular; + // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; + // see https://google.github.io/filament/Filament.md.html + return mix(vec3(dielectric), albedo, vec3(metallic)); } +/* clang-format off */ + FRAGMENT_SHADER_GLOBALS +/* clang-format on */ + +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + +varying highp float dp_clip; + +#endif + +#ifdef USE_LIGHTING + +// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. +// We're dividing this factor off because the overall term we'll end up looks like +// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): +// +// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) +// +// We're basically regouping this as +// +// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] +// +// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. +// +// The contents of the D and G (G1) functions (GGX) are taken from +// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). +// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). + +/* +float G_GGX_2cos(float cos_theta_m, float alpha) { + // Schlick's approximation + // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) + // Eq. (19), although see Heitz (2014) the about the problems with his derivation. + // It nevertheless approximates GGX well with k = alpha/2. + float k = 0.5 * alpha; + return 0.5 / (cos_theta_m * (1.0 - k) + k); + + // float cos2 = cos_theta_m * cos_theta_m; + // float sin2 = (1.0 - cos2); + // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); +} +*/ + +// This approximates G_GGX_2cos(cos_theta_l, alpha) * G_GGX_2cos(cos_theta_v, alpha) +// See Filament docs, Specular G section. +float V_GGX(float cos_theta_l, float cos_theta_v, float alpha) { + return 0.5 / mix(2.0 * cos_theta_l * cos_theta_v, cos_theta_l + cos_theta_v, alpha); +} + +float D_GGX(float cos_theta_m, float alpha) { + float alpha2 = alpha * alpha; + float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; + return alpha2 / (M_PI * d * d); +} + +/* +float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0 - cos2); + float s_x = alpha_x * cos_phi; + float s_y = alpha_y * sin_phi; + return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); +} +*/ + +// This approximates G_GGX_anisotropic_2cos(cos_theta_l, ...) * G_GGX_anisotropic_2cos(cos_theta_v, ...) +// See Filament docs, Anisotropic specular BRDF section. +float V_GGX_anisotropic(float alpha_x, float alpha_y, float TdotV, float TdotL, float BdotV, float BdotL, float NdotV, float NdotL) { + float Lambda_V = NdotL * length(vec3(alpha_x * TdotV, alpha_y * BdotV, NdotV)); + float Lambda_L = NdotV * length(vec3(alpha_x * TdotL, alpha_y * BdotL, NdotL)); + return 0.5 / (Lambda_V + Lambda_L); +} + +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi, float NdotH) { + float alpha2 = alpha_x * alpha_y; + highp vec3 v = vec3(alpha_y * cos_phi, alpha_x * sin_phi, alpha2 * NdotH); + highp float v2 = dot(v, v); + float w2 = alpha2 / v2; + float D = alpha2 * w2 * w2 * (1.0 / M_PI); + return D; + + /* float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0 - cos2); + float r_x = cos_phi / alpha_x; + float r_y = sin_phi / alpha_y; + float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); + return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); */ +} + +float SchlickFresnel(float u) { + float m = 1.0 - u; + float m2 = m * m; + return m2 * m2 * m; // pow(m,5) +} + +float GTR1(float NdotH, float a) { + if (a >= 1.0) return 1.0 / M_PI; + float a2 = a * a; + float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; + return (a2 - 1.0) / (M_PI * log(a2) * t); +} + +void light_compute( + vec3 N, + vec3 L, + vec3 V, + vec3 B, + vec3 T, + vec3 light_color, + vec3 attenuation, + vec3 diffuse_color, + vec3 transmission, + float specular_blob_intensity, + float roughness, + float metallic, + float specular, + float rim, + float rim_tint, + float clearcoat, + float clearcoat_gloss, + float anisotropy, + inout vec3 diffuse_light, + inout vec3 specular_light) { + +//this makes lights behave closer to linear, but then addition of lights looks bad +//better left disabled + +//#define SRGB_APPROX(m_var) m_var = pow(m_var,0.4545454545); +/* +#define SRGB_APPROX(m_var) {\ + float S1 = sqrt(m_var);\ + float S2 = sqrt(S1);\ + float S3 = sqrt(S2);\ + m_var = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * m_var;\ + } +*/ +#define SRGB_APPROX(m_var) + +#if defined(USE_LIGHT_SHADER_CODE) + // light is written by the light shader + + vec3 normal = N; + vec3 albedo = diffuse_color; + vec3 light = L; + vec3 view = V; + + /* clang-format off */ -#ifdef LIGHT_PASS -void light_compute(vec3 N, - vec3 L, - vec3 V, - vec3 B, - vec3 T, - vec3 light_color, - vec3 attenuation, - vec3 diffuse_color, - vec3 transmission, - float specular_blob_intensity, - float roughness, - float metallic, - float rim, - float rim_tint, - float clearcoat, - float clearcoat_gloss, - float anisotropy, - inout vec3 diffuse_light, - inout vec3 specular_light) { +LIGHT_SHADER_CODE + /* clang-format on */ + +#else float NdotL = dot(N, L); - float cNdotL = max(NdotL, 0.0); + float cNdotL = max(NdotL, 0.0); // clamped NdotL float NdotV = dot(N, V); - float cNdotV = max(NdotV, 0.0); + float cNdotV = max(abs(NdotV), 1e-6); - { - // calculate diffuse reflection +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + vec3 H = normalize(V + L); +#endif - // TODO hardcode Oren Nayar for now - float diffuse_brdf_NL; +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cNdotH = max(dot(N, H), 0.0); +#endif - diffuse_brdf_NL = max(0.0,(NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - // diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cLdotH = max(dot(L, H), 0.0); +#endif + + if (metallic < 1.0) { +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + +#if defined(DIFFUSE_LAMBERT_WRAP) + // energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } + +#elif defined(DIFFUSE_TOON) + + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + +#elif defined(DIFFUSE_BURLEY) + + { + float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; + float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); + float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); + diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; + /* + float energyBias = mix(roughness, 0.0, 0.5); + float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); + float fd90 = energyBias + 2.0 * VoH * VoH * roughness; + float f0 = 1.0; + float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); + float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); + + diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; + */ + } +#else + // lambert + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + + SRGB_APPROX(diffuse_brdf_NL) diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; + +#if defined(TRANSMISSION_USED) + diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; +#endif + +#if defined(LIGHT_USE_RIM) + float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); + diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; +#endif } - { - // calculate specular reflection + if (roughness > 0.0) { + +#if defined(SPECULAR_SCHLICK_GGX) + vec3 specular_brdf_NL = vec3(0.0); +#else + float specular_brdf_NL = 0.0; +#endif - vec3 R = normalize(-reflect(L,N)); - float cRdotV = max(dot(R, V), 0.0); - float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0); - specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity; +#if defined(SPECULAR_BLINN) + + //normalized blinn + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + +#elif defined(SPECULAR_PHONG) + + vec3 R = normalize(-reflect(L, N)); + float cRdotV = max(0.0, dot(R, V)); + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float phong = pow(cRdotV, shininess); + phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); + +#elif defined(SPECULAR_TOON) + + vec3 R = normalize(-reflect(L, N)); + float RdotV = dot(R, V); + float mid = 1.0 - roughness; + mid *= mid; + specular_brdf_NL = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; + +#elif defined(SPECULAR_DISABLED) + // none.. +#elif defined(SPECULAR_SCHLICK_GGX) + // shlick+ggx as default + +#if defined(LIGHT_USE_ANISOTROPY) + float alpha = roughness * roughness; + float aspect = sqrt(1.0 - anisotropy * 0.9); + float ax = alpha / aspect; + float ay = alpha * aspect; + float XdotH = dot(T, H); + float YdotH = dot(B, H); + float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH, cNdotH); + //float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); + float G = V_GGX_anisotropic(ax, ay, dot(T, V), dot(T, L), dot(B, V), dot(B, L), cNdotV, cNdotL)) +#else + float alpha = roughness * roughness; + float D = D_GGX(cNdotH, alpha); + //float G = G_GGX_2cos(cNdotL, alpha) * G_GGX_2cos(cNdotV, alpha); + float G = V_GGX(cNdotL, cNdotV, alpha); +#endif + // F + vec3 f0 = F0(metallic, specular, diffuse_color); + float cLdotH5 = SchlickFresnel(cLdotH); + vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + + specular_brdf_NL = cNdotL * D * F * G; + +#endif + + SRGB_APPROX(specular_brdf_NL) + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; + +#if defined(LIGHT_USE_CLEARCOAT) + +#if !defined(SPECULAR_SCHLICK_GGX) + float cLdotH5 = SchlickFresnel(cLdotH); +#endif + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + float Gr = V_GGX(cNdotL, cNdotV, 0.25); + + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; +#endif } + +#endif //defined(USE_LIGHT_SHADER_CODE) } +#endif +// shadows +#ifdef USE_SHADOW + +#define SAMPLE_SHADOW_TEXEL(p_shadow, p_pos, p_depth) step(p_depth, texture2D(p_shadow, p_pos).r) +#define SAMPLE_SHADOW_TEXEL_PROJ(p_shadow, p_pos) step(p_pos.z, texture2DProj(p_shadow, p_pos).r) + +float sample_shadow(highp sampler2D shadow, highp vec4 spos) { + +#ifdef SHADOW_MODE_PCF_13 + + spos.xyz /= spos.w; + vec2 pos = spos.xy; + float depth = spos.z; + + float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth); + return avg * (1.0 / 13.0); +#endif +#ifdef SHADOW_MODE_PCF_5 -// shadows + spos.xyz /= spos.w; + vec2 pos = spos.xy; + float depth = spos.z; + + float avg = SAMPLE_SHADOW_TEXEL(shadow, pos, depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(shadow_pixel_size.x, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(-shadow_pixel_size.x, 0.0), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, shadow_pixel_size.y), depth); + avg += SAMPLE_SHADOW_TEXEL(shadow, pos + vec2(0.0, -shadow_pixel_size.y), depth); + return avg * (1.0 / 5.0); + +#endif -float sample_shadow(highp sampler2D shadow, - vec2 shadow_pixel_size, - vec2 pos, - float depth, - vec4 clamp_rect) -{ - // vec4 depth_value = texture2D(shadow, pos); - - // return depth_value.z; - return texture2DProj(shadow, vec4(pos, depth, 1.0)).r; - // return (depth_value.x + depth_value.y + depth_value.z + depth_value.w) / 4.0; +#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) + + return SAMPLE_SHADOW_TEXEL_PROJ(shadow, spos); +#endif } +#endif + +#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) + +#if defined(USE_VERTEX_LIGHTING) + +varying vec4 fog_interp; + +#else +uniform mediump vec4 fog_color_base; +#ifdef LIGHT_MODE_DIRECTIONAL +uniform mediump vec4 fog_sun_color_amount; +#endif + +uniform bool fog_transmit_enabled; +uniform mediump float fog_transmit_curve; + +#ifdef FOG_DEPTH_ENABLED +uniform highp float fog_depth_begin; +uniform mediump float fog_depth_curve; +uniform mediump float fog_max_distance; +#endif +#ifdef FOG_HEIGHT_ENABLED +uniform highp float fog_height_min; +uniform highp float fog_height_max; +uniform mediump float fog_height_curve; #endif -void main() -{ +#endif //vertex lit +#endif //fog + +void main() { +#ifdef RENDER_DEPTH_DUAL_PARABOLOID + + if (dp_clip > 0.0) + discard; +#endif highp vec3 vertex = vertex_interp; - vec3 albedo = vec3(0.8, 0.8, 0.8); + vec3 albedo = vec3(1.0); vec3 transmission = vec3(0.0); float metallic = 0.0; float specular = 0.5; - vec3 emission = vec3(0.0, 0.0, 0.0); + vec3 emission = vec3(0.0); float roughness = 1.0; float rim = 0.0; float rim_tint = 0.0; float clearcoat = 0.0; float clearcoat_gloss = 0.0; - float anisotropy = 1.0; - vec2 anisotropy_flow = vec2(1.0,0.0); + float anisotropy = 0.0; + vec2 anisotropy_flow = vec2(1.0, 0.0); + float sss_strength = 0.0; //unused float alpha = 1.0; float side = 1.0; + float specular_blob_intensity = 1.0; +#if defined(SPECULAR_TOON) + specular_blob_intensity *= specular * 2.0; +#endif + #if defined(ENABLE_AO) float ao = 1.0; float ao_light_affect = 0.0; #endif - #if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) vec3 binormal = normalize(binormal_interp) * side; vec3 tangent = normalize(tangent_interp) * side; @@ -509,179 +1421,403 @@ void main() #endif float normaldepth = 1.0; - -#ifdef ALPHA_SCISSOR_USED +#if defined(ALPHA_SCISSOR_USED) float alpha_scissor = 0.5; #endif -#ifdef SCREEN_UV_USED +#if defined(SCREEN_UV_USED) vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; #endif -{ + { + /* clang-format off */ FRAGMENT_SHADER_CODE - -} + /* clang-format on */ + } #if defined(ENABLE_NORMALMAP) normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(1.0 - dot(normalmap.xy, normalmap.xy)); + normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); - // normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; - normal = normalmap; + normal = normalize(mix(normal_interp, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)) * side; + //normal = normalmap; #endif normal = normalize(normal); vec3 N = normal; - + vec3 specular_light = vec3(0.0, 0.0, 0.0); vec3 diffuse_light = vec3(0.0, 0.0, 0.0); - vec3 ambient_light = vec3(0.0, 0.0, 0.0); - vec3 env_reflection_light = vec3(0.0, 0.0, 0.0); - vec3 eye_position = -normalize(vertex_interp); -#ifdef ALPHA_SCISSOR_USED +#if defined(ALPHA_SCISSOR_USED) if (alpha < alpha_scissor) { discard; } #endif - + +#ifdef BASE_PASS + //none +#ifdef USE_RADIANCE_MAP + + vec3 ref_vec = reflect(-eye_position, N); + ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); + + ref_vec.z *= -1.0; + + specular_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; + + { + vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); + vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy; + + ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); + } + +#else + + ambient_light = ambient_color.rgb; + +#endif + + ambient_light *= ambient_energy; + +#if defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) + + vec4 ambient_accum = vec4(0.0); + vec4 reflection_accum = vec4(0.0); + +#ifdef USE_REFLECTION_PROBE1 + + reflection_process(reflection_probe1, +#ifdef USE_VERTEX_LIGHTING + refprobe1_reflection_normal_blend.rgb, +#ifndef USE_LIGHTMAP + refprobe1_ambient_normal, +#endif + refprobe1_reflection_normal_blend.a, +#else + normal_interp, vertex_interp, refprobe1_local_matrix, + refprobe1_use_box_project, refprobe1_box_extents, refprobe1_box_offset, +#endif + refprobe1_exterior, refprobe1_intensity, refprobe1_ambient, roughness, + ambient_light, specular_light, reflection_accum, ambient_accum); + +#endif // USE_REFLECTION_PROBE1 + +#ifdef USE_REFLECTION_PROBE2 + + reflection_process(reflection_probe2, +#ifdef USE_VERTEX_LIGHTING + refprobe2_reflection_normal_blend.rgb, +#ifndef USE_LIGHTMAP + refprobe2_ambient_normal, +#endif + refprobe2_reflection_normal_blend.a, +#else + normal_interp, vertex_interp, refprobe2_local_matrix, + refprobe2_use_box_project, refprobe2_box_extents, refprobe2_box_offset, +#endif + refprobe2_exterior, refprobe2_intensity, refprobe2_ambient, roughness, + ambient_light, specular_light, reflection_accum, ambient_accum); + +#endif // USE_REFLECTION_PROBE2 + + if (reflection_accum.a > 0.0) { + specular_light = reflection_accum.rgb / reflection_accum.a; + } + +#ifndef USE_LIGHTMAP + if (ambient_accum.a > 0.0) { + ambient_light = ambient_accum.rgb / ambient_accum.a; + } +#endif + +#endif // defined(USE_REFLECTION_PROBE1) || defined(USE_REFLECTION_PROBE2) + +#ifdef USE_LIGHTMAP + //ambient light will come entirely from lightmap is lightmap is used + ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy; +#endif + +#ifdef USE_LIGHTMAP_CAPTURE + { + vec3 cone_dirs[12] = vec3[]( + vec3(0, 0, 1), + vec3(0.866025, 0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5), + vec3(0, 0, -1), + vec3(0.866025, 0, -0.5), + vec3(0.267617, 0.823639, -0.5), + vec3(-0.700629, 0.509037, -0.5), + vec3(-0.700629, -0.509037, -0.5), + vec3(0.267617, -0.823639, -0.5)); + + vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; + vec4 captured = vec4(0.0); + float sum = 0.0; + for (int i = 0; i < 12; i++) { + float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect + captured += lightmap_captures[i] * amount; + sum += amount; + } + + captured /= sum; + + if (lightmap_capture_sky) { + ambient_light = mix(ambient_light, captured.rgb, captured.a); + } else { + ambient_light = captured.rgb; + } + } +#endif + +#endif //BASE PASS + // // Lighting // -#ifdef LIGHT_PASS +#ifdef USE_LIGHTING - if (light_type == LIGHT_TYPE_OMNI) { - vec3 light_vec = light_position - vertex; - float light_length = length(light_vec); +#ifndef USE_VERTEX_LIGHTING + vec3 L; +#endif + vec3 light_att = vec3(1.0); - float normalized_distance = light_length / light_range; +#ifdef LIGHT_MODE_OMNI - float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation.w); +#ifndef USE_VERTEX_LIGHTING + vec3 light_vec = light_position - vertex; + float light_length = length(light_vec); - vec3 attenuation = vec3(omni_attenuation); + float normalized_distance = light_length / light_range; + if (normalized_distance < 1.0) { - if (light_has_shadow > 0.5) { - highp vec3 splane = (light_shadow_matrix * vec4(vertex, 1.0)).xyz; - float shadow_len = length(splane); + float omni_attenuation = pow(1.0 - normalized_distance, light_attenuation); - splane = normalize(splane); + light_att = vec3(omni_attenuation); + } else { + light_att = vec3(0.0); + } + L = normalize(light_vec); - vec4 clamp_rect = light_clamp; +#endif - if (splane.z >= 0.0) { - splane.z += 1.0; +#ifdef USE_SHADOW + { + highp vec4 splane = shadow_coord; + float shadow_len = length(splane.xyz); - clamp_rect.y += clamp_rect.w; + splane.xyz = normalize(splane.xyz); + + vec4 clamp_rect = light_clamp; + + if (splane.z >= 0.0) { + splane.z += 1.0; + + clamp_rect.y += clamp_rect.w; + } else { + splane.z = 1.0 - splane.z; + } + + splane.xy /= splane.z; + splane.xy = splane.xy * 0.5 + 0.5; + splane.z = shadow_len / light_range; + + splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; + splane.w = 1.0; + + float shadow = sample_shadow(light_shadow_atlas, splane); + + light_att *= shadow; + } +#endif + +#endif //type omni + +#ifdef LIGHT_MODE_DIRECTIONAL + +#ifndef USE_VERTEX_LIGHTING + vec3 light_vec = -light_direction; + L = normalize(light_vec); +#endif + float depth_z = -vertex.z; + +#ifdef USE_SHADOW + +#ifdef USE_VERTEX_LIGHTING + //compute shadows in a mobile friendly way + +#ifdef LIGHT_USE_PSSM4 + //take advantage of prefetch + float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); + float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); + float shadow3 = sample_shadow(light_directional_shadow, shadow_coord3); + float shadow4 = sample_shadow(light_directional_shadow, shadow_coord4); + + if (depth_z < light_split_offsets.w) { + float pssm_fade = 0.0; + float shadow_att = 1.0; +#ifdef LIGHT_USE_PSSM_BLEND + float shadow_att2 = 1.0; + float pssm_blend = 0.0; + bool use_blend = true; +#endif + if (depth_z < light_split_offsets.y) { + if (depth_z < light_split_offsets.x) { + shadow_att = shadow1; + +#ifdef LIGHT_USE_PSSM_BLEND + shadow_att2 = shadow2; + + pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#endif } else { - splane.z = 1.0 - splane.z; - } + shadow_att = shadow2; - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len / light_range; +#ifdef LIGHT_USE_PSSM_BLEND + shadow_att2 = shadow3; - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; + pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#endif + } + } else { + if (depth_z < light_split_offsets.z) { - float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), splane.xy, splane.z, clamp_rect); + shadow_att = shadow3; + +#if defined(LIGHT_USE_PSSM_BLEND) + shadow_att2 = shadow4; + pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); +#endif - if (shadow > splane.z) { } else { - attenuation = vec3(0.0); + + shadow_att = shadow4; + pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); + +#if defined(LIGHT_USE_PSSM_BLEND) + use_blend = false; +#endif } } +#if defined(LIGHT_USE_PSSM_BLEND) + if (use_blend) { + shadow_att = mix(shadow_att, shadow_att2, pssm_blend); + } +#endif + light_att *= shadow_att; + } + +#endif //LIGHT_USE_PSSM4 + +#ifdef LIGHT_USE_PSSM2 + + //take advantage of prefetch + float shadow1 = sample_shadow(light_directional_shadow, shadow_coord); + float shadow2 = sample_shadow(light_directional_shadow, shadow_coord2); + + if (depth_z < light_split_offsets.y) { + float shadow_att = 1.0; + float pssm_fade = 0.0; + +#ifdef LIGHT_USE_PSSM_BLEND + float shadow_att2 = 1.0; + float pssm_blend = 0.0; + bool use_blend = true; +#endif + if (depth_z < light_split_offsets.x) { + float pssm_fade = 0.0; + shadow_att = shadow1; + +#ifdef LIGHT_USE_PSSM_BLEND + shadow_att2 = shadow2; + pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); +#endif + } else { + + shadow_att = shadow2; + pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); +#ifdef LIGHT_USE_PSSM_BLEND + use_blend = false; +#endif + } +#ifdef LIGHT_USE_PSSM_BLEND + if (use_blend) { + shadow_att = mix(shadow_att, shadow_att2, pssm_blend); + } +#endif + light_att *= shadow_att; + } - light_compute(normal, - normalize(light_vec), - eye_position, - binormal, - tangent, - light_color.xyz * light_energy, - attenuation, - albedo, - transmission, - specular * light_specular, - roughness, - metallic, - rim, - rim_tint, - clearcoat, - clearcoat_gloss, - anisotropy, - diffuse_light, - specular_light); - - } else if (light_type == LIGHT_TYPE_DIRECTIONAL) { - - vec3 light_vec = -light_direction; - vec3 attenuation = vec3(1.0, 1.0, 1.0); - - float depth_z = -vertex.z; - - if (light_has_shadow > 0.5) { - +#endif //LIGHT_USE_PSSM2 + +#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) + + light_att *= sample_shadow(light_directional_shadow, shadow_coord); +#endif //orthogonal + +#else //fragment version of pssm + + { #ifdef LIGHT_USE_PSSM4 - if (depth_z < light_split_offsets.w) { + if (depth_z < light_split_offsets.w) { #elif defined(LIGHT_USE_PSSM2) - if (depth_z < light_split_offsets.y) { + if (depth_z < light_split_offsets.y) { #else - if (depth_z < light_split_offsets.x) { -#endif - - vec3 pssm_coord; + if (depth_z < light_split_offsets.x) { +#endif //pssm2 + + highp vec4 pssm_coord; float pssm_fade = 0.0; - + #ifdef LIGHT_USE_PSSM_BLEND float pssm_blend; - vec3 pssm_coord2; + highp vec4 pssm_coord2; bool use_blend = true; #endif - + #ifdef LIGHT_USE_PSSM4 + if (depth_z < light_split_offsets.y) { if (depth_z < light_split_offsets.x) { - highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - + pssm_coord = shadow_coord; + #ifdef LIGHT_USE_PSSM_BLEND - splane = (light_shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - + pssm_coord2 = shadow_coord2; + pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); #endif } else { - highp vec4 splane = (light_shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - + pssm_coord = shadow_coord2; + #ifdef LIGHT_USE_PSSM_BLEND - splane = (light_shadow_matrix3 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; - + pssm_coord2 = shadow_coord3; + pssm_blend = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); #endif } } else { if (depth_z < light_split_offsets.z) { - highp vec4 splane = (light_shadow_matrix3 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; + pssm_coord = shadow_coord3; #if defined(LIGHT_USE_PSSM_BLEND) - splane = (light_shadow_matrix4 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; + pssm_coord2 = shadow_coord4; pssm_blend = smoothstep(light_split_offsets.y, light_split_offsets.z, depth_z); #endif } else { - highp vec4 splane = (light_shadow_matrix4 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; + pssm_coord = shadow_coord4; pssm_fade = smoothstep(light_split_offsets.z, light_split_offsets.w, depth_z); #if defined(LIGHT_USE_PSSM_BLEND) @@ -689,157 +1825,140 @@ FRAGMENT_SHADER_CODE #endif } } - + #endif // LIGHT_USE_PSSM4 - + #ifdef LIGHT_USE_PSSM2 if (depth_z < light_split_offsets.x) { - - highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; - + + pssm_coord = shadow_coord; + #ifdef LIGHT_USE_PSSM_BLEND - splane = (light_shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord2 = splane.xyz / splane.w; + pssm_coord2 = shadow_coord2; pssm_blend = smoothstep(0.0, light_split_offsets.x, depth_z); #endif } else { - highp vec4 splane = (light_shadow_matrix2 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; + + pssm_coord = shadow_coord2; pssm_fade = smoothstep(light_split_offsets.x, light_split_offsets.y, depth_z); #ifdef LIGHT_USE_PSSM_BLEND use_blend = false; #endif } - + #endif // LIGHT_USE_PSSM2 - + #if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2) { - highp vec4 splane = (light_shadow_matrix1 * vec4(vertex, 1.0)); - pssm_coord = splane.xyz / splane.w; + pssm_coord = shadow_coord; } #endif - - float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), pssm_coord.xy, pssm_coord.z, light_clamp); - + + float shadow = sample_shadow(light_directional_shadow, pssm_coord); + #ifdef LIGHT_USE_PSSM_BLEND if (use_blend) { - shadow = mix(shadow, sample_shadow(light_shadow_atlas, vec2(0.0), pssm_coord2.xy, pssm_coord2.z, light_clamp), pssm_blend); + shadow = mix(shadow, sample_shadow(light_directional_shadow, pssm_coord2), pssm_blend); } #endif - - attenuation *= shadow; - - - } - - } - light_compute(normal, - normalize(light_vec), - eye_position, - binormal, - tangent, - light_color.xyz * light_energy, - attenuation, - albedo, - transmission, - specular * light_specular, - roughness, - metallic, - rim, - rim_tint, - clearcoat, - clearcoat_gloss, - anisotropy, - diffuse_light, - specular_light); - } else if (light_type == LIGHT_TYPE_SPOT) { - - vec3 light_att = vec3(1.0); - - if (light_has_shadow > 0.5) { - highp vec4 splane = (light_shadow_matrix * vec4(vertex, 1.0)); - splane.xyz /= splane.w; - - float shadow = sample_shadow(light_shadow_atlas, vec2(0.0), splane.xy, splane.z, light_clamp); - - if (shadow > splane.z) { - } else { - light_att = vec3(0.0); - } - - + light_att *= shadow; } + } +#endif //use vertex lighting + +#endif //use shadow + +#endif - vec3 light_rel_vec = light_position - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length / light_range; +#ifdef LIGHT_MODE_SPOT - float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation.w); + light_att = vec3(1.0); + +#ifndef USE_VERTEX_LIGHTING + + vec3 light_rel_vec = light_position - vertex; + float light_length = length(light_rel_vec); + float normalized_distance = light_length / light_range; + + if (normalized_distance < 1.0) { + float spot_attenuation = pow(1.0 - normalized_distance, light_attenuation); vec3 spot_dir = light_direction; float spot_cutoff = light_spot_angle; + float angle = dot(-normalize(light_rel_vec), spot_dir); - float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_cutoff); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); - - spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); - - light_att *= vec3(spot_attenuation); - - light_compute(normal, - normalize(light_rel_vec), - eye_position, - binormal, - tangent, - light_color.xyz * light_energy, - light_att, - albedo, - transmission, - specular * light_specular, - roughness, - metallic, - rim, - rim_tint, - clearcoat, - clearcoat_gloss, - anisotropy, - diffuse_light, - specular_light); + if (angle > spot_cutoff) { + float scos = max(angle, spot_cutoff); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_cutoff)); + spot_attenuation *= 1.0 - pow(spot_rim, light_spot_attenuation); + light_att = vec3(spot_attenuation); + } else { + light_att = vec3(0.0); + } + } else { + light_att = vec3(0.0); } - gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha); -#else - -#ifdef RENDER_DEPTH + L = normalize(light_rel_vec); -#else +#endif -#ifdef USE_RADIANCE_MAP +#ifdef USE_SHADOW + { + highp vec4 splane = shadow_coord; + splane.xyz /= splane.w; + float shadow = sample_shadow(light_shadow_atlas, splane); + light_att *= shadow; + } +#endif - vec3 ref_vec = reflect(-eye_position, N); - ref_vec = normalize((radiance_inverse_xform * vec4(ref_vec, 0.0)).xyz); +#endif // LIGHT_MODE_SPOT - ref_vec.z *= -1.0; +#ifdef USE_VERTEX_LIGHTING + //vertex lighting - env_reflection_light = textureCubeLod(radiance_map, ref_vec, roughness * RADIANCE_MAX_LOD).xyz * bg_energy; + specular_light += specular_interp * specular_blob_intensity * light_att; + diffuse_light += diffuse_interp * albedo * light_att; - { - vec3 ambient_dir = normalize((radiance_inverse_xform * vec4(normal, 0.0)).xyz); - vec3 env_ambient = textureCubeLod(radiance_map, ambient_dir, RADIANCE_MAX_LOD).xyz * bg_energy; - - ambient_light = mix(ambient_color.rgb, env_ambient, ambient_sky_contribution); +#else + //fragment lighting + light_compute( + normal, + L, + eye_position, + binormal, + tangent, + light_color.xyz, + light_att, + albedo, + transmission, + specular_blob_intensity * light_specular, + roughness, + metallic, + specular, + rim, + rim_tint, + clearcoat, + clearcoat_gloss, + anisotropy, + diffuse_light, + specular_light); + +#endif //vertex lighting + +#endif //USE_LIGHTING + //compute and merge + +#ifndef RENDER_DEPTH + +#ifdef SHADELESS - } + gl_FragColor = vec4(albedo, alpha); +#else - ambient_light *= ambient_energy; - - specular_light += env_reflection_light; - ambient_light *= albedo; #if defined(ENABLE_AO) @@ -848,37 +1967,85 @@ FRAGMENT_SHADER_CODE specular_light *= ao_light_affect; diffuse_light *= ao_light_affect; #endif - + diffuse_light *= 1.0 - metallic; ambient_light *= 1.0 - metallic; - + // environment BRDF approximation - - // TODO shadeless + { + +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; +#else + //TODO: this curve is not really designed for gammaspace, should be adjusted const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); vec4 r = roughness * c0 + c1; - float ndotv = clamp(dot(normal,eye_position),0.0,1.0); - float a004 = min( r.x * r.x, exp2( -9.28 * ndotv ) ) * r.x + r.y; - vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; + float ndotv = clamp(dot(normal, eye_position), 0.0, 1.0); + float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; + vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - vec3 specular_color = metallic_to_specular_color(metallic, specular, albedo); - specular_light *= AB.x * specular_color + AB.y; + vec3 f0 = F0(metallic, specular, albedo); + specular_light *= env.x * f0 + env.y; +#endif } - gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha); + + //add emission if in base pass +#ifdef BASE_PASS + gl_FragColor.rgb += emission; +#endif // gl_FragColor = vec4(normal, 1.0); +#endif //unshaded +//apply fog +#if defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) + +#if defined(USE_VERTEX_LIGHTING) + + gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_interp.rgb, fog_interp.a); +#else //pixel based fog + float fog_amount = 0.0; + +#ifdef LIGHT_MODE_DIRECTIONAL + + vec3 fog_color = mix(fog_color_base.rgb, fog_sun_color_amount.rgb, fog_sun_color_amount.a * pow(max(dot(eye_position, light_direction), 0.0), 8.0)); #else - gl_FragColor = vec4(albedo, alpha); + vec3 fog_color = fog_color_base.rgb; +#endif + +#ifdef FOG_DEPTH_ENABLED + + { + + float fog_z = smoothstep(fog_depth_begin, fog_max_distance, length(vertex)); + + fog_amount = pow(fog_z, fog_depth_curve) * fog_color_base.a; + + if (fog_transmit_enabled) { + vec3 total_light = gl_FragColor.rgb; + float transmit = pow(fog_z, fog_transmit_curve); + fog_color = mix(max(total_light, fog_color), fog_color, transmit); + } + } +#endif + +#ifdef FOG_HEIGHT_ENABLED + { + float y = (camera_matrix * vec4(vertex, 1.0)).y; + fog_amount = max(fog_amount, pow(smoothstep(fog_height_min, fog_height_max, y), fog_height_curve)); + } #endif -#endif // RENDER_DEPTH + gl_FragColor.rgb = mix(gl_FragColor.rgb, fog_color, fog_amount); -#endif // lighting +#endif //use vertex lit +#endif // defined(FOG_DEPTH_ENABLED) || defined(FOG_HEIGHT_ENABLED) +#endif // not RENDER_DEPTH } diff --git a/drivers/gles2/shaders/screen_space_reflection.glsl b/drivers/gles2/shaders/screen_space_reflection.glsl index b2e6f7a736..a11da10b61 100644 --- a/drivers/gles2/shaders/screen_space_reflection.glsl +++ b/drivers/gles2/shaders/screen_space_reflection.glsl @@ -1,8 +1,9 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; out vec2 uv_interp; out vec2 pos_interp; @@ -11,13 +12,14 @@ void main() { uv_interp = uv_in; gl_Position = vertex_attrib; - pos_interp.xy=gl_Position.xy; + pos_interp.xy = gl_Position.xy; } +/* clang-format off */ [fragment] - in vec2 uv_interp; +/* clang-format on */ in vec2 pos_interp; uniform sampler2D source_diffuse; //texunit:0 @@ -40,81 +42,70 @@ uniform float depth_tolerance; uniform float distance_fade; uniform float curve_fade_in; - layout(location = 0) out vec4 frag_color; - -vec2 view_to_screen(vec3 view_pos,out float w) { - vec4 projected = projection * vec4(view_pos, 1.0); - projected.xyz /= projected.w; - projected.xy = projected.xy * 0.5 + 0.5; - w=projected.w; - return projected.xy; +vec2 view_to_screen(vec3 view_pos, out float w) { + vec4 projected = projection * vec4(view_pos, 1.0); + projected.xyz /= projected.w; + projected.xy = projected.xy * 0.5 + 0.5; + w = projected.w; + return projected.xy; } - - #define M_PI 3.14159265359 void main() { - - //// - - vec4 diffuse = texture( source_diffuse, uv_interp ); - vec4 normal_roughness = texture( source_normal_roughness, uv_interp); + vec4 diffuse = texture(source_diffuse, uv_interp); + vec4 normal_roughness = texture(source_normal_roughness, uv_interp); vec3 normal; - normal = normal_roughness.xyz*2.0-1.0; + normal = normal_roughness.xyz * 2.0 - 1.0; float roughness = normal_roughness.w; - float depth_tex = texture(source_depth,uv_interp).r; + float depth_tex = texture(source_depth, uv_interp).r; - vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 ); - vec3 vertex = world_pos.xyz/world_pos.w; + vec4 world_pos = inverse_projection * vec4(uv_interp * 2.0 - 1.0, depth_tex * 2.0 - 1.0, 1.0); + vec3 vertex = world_pos.xyz / world_pos.w; vec3 view_dir = normalize(vertex); vec3 ray_dir = normalize(reflect(view_dir, normal)); - if (dot(ray_dir,normal)<0.001) { - frag_color=vec4(0.0); + if (dot(ray_dir, normal) < 0.001) { + frag_color = vec4(0.0); return; } //ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0); //ray_dir = normalize(vec3(1,1,-1)); - //////////////// - //make ray length and clip it against the near plane (don't want to trace beyond visible) float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far; - vec3 ray_end = vertex + ray_dir*ray_len; + vec3 ray_end = vertex + ray_dir * ray_len; float w_begin; - vec2 vp_line_begin = view_to_screen(vertex,w_begin); + vec2 vp_line_begin = view_to_screen(vertex, w_begin); float w_end; - vec2 vp_line_end = view_to_screen( ray_end, w_end); - vec2 vp_line_dir = vp_line_end-vp_line_begin; + vec2 vp_line_end = view_to_screen(ray_end, w_end); + vec2 vp_line_dir = vp_line_end - vp_line_begin; //we need to interpolate w along the ray, to generate perspective correct reflections - w_begin = 1.0/w_begin; - w_end = 1.0/w_end; + w_begin = 1.0 / w_begin; + w_end = 1.0 / w_end; + float z_begin = vertex.z * w_begin; + float z_end = ray_end.z * w_end; - float z_begin = vertex.z*w_begin; - float z_end = ray_end.z*w_end; - - vec2 line_begin = vp_line_begin/pixel_size; - vec2 line_dir = vp_line_dir/pixel_size; + vec2 line_begin = vp_line_begin / pixel_size; + vec2 line_dir = vp_line_dir / pixel_size; float z_dir = z_end - z_begin; float w_dir = w_end - w_begin; - // clip the line to the viewport edges float scale_max_x = min(1.0, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x)); @@ -124,121 +115,109 @@ void main() { float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y); line_dir *= line_clip; z_dir *= line_clip; - w_dir *=line_clip; + w_dir *= line_clip; //clip z and w advance to line advance vec2 line_advance = normalize(line_dir); //down to pixel - float step_size = length(line_advance)/length(line_dir); - float z_advance = z_dir*step_size; // adapt z advance to line advance - float w_advance = w_dir*step_size; // adapt w advance to line advance + float step_size = length(line_advance) / length(line_dir); + float z_advance = z_dir * step_size; // adapt z advance to line advance + float w_advance = w_dir * step_size; // adapt w advance to line advance //make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice) - float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y)); - line_advance*=advance_angle_adj; // adapt z advance to line advance - z_advance*=advance_angle_adj; - w_advance*=advance_angle_adj; + float advance_angle_adj = 1.0 / max(abs(line_advance.x), abs(line_advance.y)); + line_advance *= advance_angle_adj; // adapt z advance to line advance + z_advance *= advance_angle_adj; + w_advance *= advance_angle_adj; vec2 pos = line_begin; float z = z_begin; float w = w_begin; - float z_from=z/w; - float z_to=z_from; + float z_from = z / w; + float z_to = z_from; float depth; - vec2 prev_pos=pos; + vec2 prev_pos = pos; - bool found=false; + bool found = false; - float steps_taken=0.0; + float steps_taken = 0.0; - for(int i=0;i<num_steps;i++) { + for (int i = 0; i < num_steps; i++) { - pos+=line_advance; - z+=z_advance; - w+=w_advance; + pos += line_advance; + z += z_advance; + w += w_advance; //convert to linear depth - depth = texture(source_depth, pos*pixel_size).r * 2.0 - 1.0; + depth = texture(source_depth, pos * pixel_size).r * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); #endif - depth=-depth; + depth = -depth; z_from = z_to; - z_to = z/w; + z_to = z / w; - if (depth>z_to) { + if (depth > z_to) { //if depth was surpassed - if (depth<=max(z_to,z_from)+depth_tolerance) { + if (depth <= max(z_to, z_from) + depth_tolerance) { //check the depth tolerance - found=true; + found = true; } break; } - steps_taken+=1.0; - prev_pos=pos; + steps_taken += 1.0; + prev_pos = pos; } - - - if (found) { - float margin_blend=1.0; - + float margin_blend = 1.0; - vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin - if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) { + vec2 margin = vec2((viewport_size.x + viewport_size.y) * 0.5 * 0.05); //make a uniform margin + if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, viewport_size + margin)))) { //clip outside screen + margin - frag_color=vec4(0.0); + frag_color = vec4(0.0); return; } { //blend fading out towards external margin - vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0))); - margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y)); + vec2 margin_grad = mix(pos - viewport_size, -pos, lessThan(pos, vec2(0.0))); + margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y)); //margin_blend=1.0; - } vec2 final_pos; float grad; - grad=steps_taken/float(num_steps); - float initial_fade = curve_fade_in==0.0 ? 1.0 : pow(clamp(grad,0.0,1.0),curve_fade_in); - float fade = pow(clamp(1.0-grad,0.0,1.0),distance_fade)*initial_fade; - final_pos=pos; - - - - - - + grad = steps_taken / float(num_steps); + float initial_fade = curve_fade_in == 0.0 ? 1.0 : pow(clamp(grad, 0.0, 1.0), curve_fade_in); + float fade = pow(clamp(1.0 - grad, 0.0, 1.0), distance_fade) * initial_fade; + final_pos = pos; #ifdef REFLECT_ROUGHNESS - vec4 final_color; //if roughness is enabled, do screen space cone tracing if (roughness > 0.001) { /////////////////////////////////////////////////////////////////////////////////////// //use a blurred version (in consecutive mipmaps) of the screen to simulate roughness - float gloss = 1.0-roughness; + float gloss = 1.0 - roughness; float cone_angle = roughness * M_PI * 0.5; vec2 cone_dir = final_pos - line_begin; float cone_len = length(cone_dir); cone_dir = normalize(cone_dir); //will be used normalized from now on float max_mipmap = filter_mipmap_levels - 1.0; - float gloss_mult=gloss; + float gloss_mult = gloss; - float rem_alpha=1.0; + float rem_alpha = 1.0; final_color = vec4(0.0); - for(int i=0;i<7;i++) { + for (int i = 0; i < 7; i++) { float op_len = 2.0 * tan(cone_angle) * cone_len; //opposite side of iso triangle float radius; @@ -258,30 +237,30 @@ void main() { } //find the place where screen must be sampled - vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size; + vec2 sample_pos = (line_begin + cone_dir * (cone_len - radius)) * pixel_size; //radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels - float mipmap = clamp( log2( radius ), 0.0, max_mipmap ); + float mipmap = clamp(log2(radius), 0.0, max_mipmap); //mipmap = max(mipmap-1.0,0.0); //do sampling vec4 sample_color; { - sample_color = textureLod(source_diffuse,sample_pos,mipmap); + sample_color = textureLod(source_diffuse, sample_pos, mipmap); } //multiply by gloss - sample_color.rgb*=gloss_mult; - sample_color.a=gloss_mult; + sample_color.rgb *= gloss_mult; + sample_color.a = gloss_mult; rem_alpha -= sample_color.a; - if(rem_alpha < 0.0) { + if (rem_alpha < 0.0) { sample_color.rgb *= (1.0 - abs(rem_alpha)); } - final_color+=sample_color; + final_color += sample_color; - if (final_color.a>=0.95) { + if (final_color.a >= 0.95) { // This code of accumulating gloss and aborting on near one // makes sense when you think of cone tracing. // Think of it as if roughness was 0, then we could abort on the first @@ -290,29 +269,21 @@ void main() { break; } - cone_len-=radius*2.0; //go to next (smaller) circle. - - gloss_mult*=gloss; - + cone_len -= radius * 2.0; //go to next (smaller) circle. + gloss_mult *= gloss; } } else { - final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0); + final_color = textureLod(source_diffuse, final_pos * pixel_size, 0.0); } - frag_color = vec4(final_color.rgb,fade*margin_blend); + frag_color = vec4(final_color.rgb, fade * margin_blend); #else - frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,fade*margin_blend); + frag_color = vec4(textureLod(source_diffuse, final_pos * pixel_size, 0.0).rgb, fade * margin_blend); #endif - - } else { - frag_color = vec4(0.0,0.0,0.0,0.0); + frag_color = vec4(0.0, 0.0, 0.0, 0.0); } - - - } - diff --git a/drivers/gles2/shaders/ssao.glsl b/drivers/gles2/shaders/ssao.glsl index 219f0957e0..82eea8f274 100644 --- a/drivers/gles2/shaders/ssao.glsl +++ b/drivers/gles2/shaders/ssao.glsl @@ -1,14 +1,16 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ void main() { gl_Position = vertex_attrib; - gl_Position.z=1.0; + gl_Position.z = 1.0; } +/* clang-format off */ [fragment] #define TWO_PI 6.283185307179586476925286766559 @@ -43,19 +45,21 @@ void main() { // This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent // taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 -const int ROTATIONS[] = int[]( 1, 1, 2, 3, 2, 5, 2, 3, 2, -3, 3, 5, 5, 3, 4, 7, 5, 5, 7, -9, 8, 5, 5, 7, 7, 7, 8, 5, 8, -11, 12, 7, 10, 13, 8, 11, 8, 7, 14, -11, 11, 13, 12, 13, 19, 17, 13, 11, 18, -19, 11, 11, 14, 17, 21, 15, 16, 17, 18, -13, 17, 11, 17, 19, 18, 25, 18, 19, 19, -29, 21, 19, 27, 31, 29, 21, 18, 17, 29, -31, 31, 23, 18, 25, 26, 25, 23, 19, 34, -19, 27, 21, 25, 39, 29, 17, 21, 27 ); +const int ROTATIONS[] = int[]( + 1, 1, 2, 3, 2, 5, 2, 3, 2, + 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, + 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, + 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, + 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, + 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, + 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, + 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, + 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, + 19, 27, 21, 25, 39, 29, 17, 21, 27); +/* clang-format on */ //#define NUM_SPIRAL_TURNS (7) -const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES-1]; +const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; uniform sampler2D source_depth; //texunit:0 uniform highp usampler2D source_depth_mipmaps; //texunit:1 @@ -90,44 +94,41 @@ vec3 reconstructCSPosition(vec2 S, float z) { } vec3 getPosition(ivec2 ssP) { - vec3 P; - P.z = texelFetch(source_depth, ssP, 0).r; + vec3 P; + P.z = texelFetch(source_depth, ssP, 0).r; - P.z = P.z * 2.0 - 1.0; + P.z = P.z * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else - P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); #endif - P.z = -P.z; + P.z = -P.z; - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - return P; + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; } /** Reconstructs screen-space unit normal from screen-space position */ vec3 reconstructCSFaceNormal(vec3 C) { - return normalize(cross(dFdy(C), dFdx(C))); + return normalize(cross(dFdy(C), dFdx(C))); } - - /** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ -vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){ - // Radius relative to ssR - float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); - float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { + // Radius relative to ssR + float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); + float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; - ssR = alpha; - return vec2(cos(angle), sin(angle)); + ssR = alpha; + return vec2(cos(angle), sin(angle)); } - /** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { - // Derivation: - // mipLevel = floor(log(ssR / MAX_OFFSET)); + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); ivec2 ssP = ivec2(ssR * unitOffset) + ssC; @@ -138,13 +139,12 @@ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { // Manually clamp to the texture size because texelFetch bypasses the texture unit ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1)); - if (mipLevel < 1) { //read from depth buffer P.z = texelFetch(source_depth, mipP, 0).r; P.z = P.z * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - P.z = ((P.z + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + P.z = ((P.z + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); @@ -153,78 +153,74 @@ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { } else { //read from mipmaps - uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r; - P.z = -(float(d)/65535.0)*camera_z_far; + uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; + P.z = -(float(d) / 65535.0) * camera_z_far; } - // Offset to pixel center P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); return P; } - - /** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds - to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius - Note that units of H() in the HPG12 paper are meters, not - unitless. The whole falloff/sampling function is therefore - unitless. In this implementation, we factor out (9 / radius). + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). - Four versions of the falloff function are implemented below + Four versions of the falloff function are implemented below */ -float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { - // Offset on the unit disk, spun for this pixel - float ssR; - vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); - ssR *= ssDiskRadius; +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; - // The occluding point in camera space - vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); - vec3 v = Q - C; + vec3 v = Q - C; - float vv = dot(v, v); - float vn = dot(v, n_C); + float vv = dot(v, v); + float vn = dot(v, n_C); - const float epsilon = 0.01; - float radius2 = p_radius*p_radius; + const float epsilon = 0.01; + float radius2 = p_radius * p_radius; - // A: From the HPG12 paper - // Note large epsilon to avoid overdarkening within cracks - //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; - // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] - float f=max(radius2 - vv, 0.0); - return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f = max(radius2 - vv, 0.0); + return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); - // C: Medium contrast (which looks better at high radii), no division. Note that the - // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // more computationally efficient and happens to be aesthetically pleasing. - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); - // D: Low contrast, no division operation - // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); } - - void main() { - // Pixel being shaded ivec2 ssC = ivec2(gl_FragCoord.xy); // World space point being shaded vec3 C = getPosition(ssC); -/* if (C.z <= -camera_z_far*0.999) { - // We're on the skybox - visibility=1.0; - return; - }*/ + /* + if (C.z <= -camera_z_far*0.999) { + // We're on the skybox + visibility=1.0; + return; + } + */ //visibility=-C.z/camera_z_far; //return; @@ -251,7 +247,7 @@ void main() { #endif float sum = 0.0; for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle); + sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius, i, randomPatternRotationAngle); } float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); @@ -271,10 +267,10 @@ void main() { sum = 0.0; for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle); + sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius2, i, randomPatternRotationAngle); } - A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES)))); + A = min(A, max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / float(NUM_SAMPLES)))); #endif // Bilateral box-filter over a quad for free, respecting depth edges // (the difference that this makes is subtle) @@ -286,8 +282,4 @@ void main() { } visibility = A; - } - - - diff --git a/drivers/gles2/shaders/ssao_blur.glsl b/drivers/gles2/shaders/ssao_blur.glsl index 472dc21acf..e4133ad534 100644 --- a/drivers/gles2/shaders/ssao_blur.glsl +++ b/drivers/gles2/shaders/ssao_blur.glsl @@ -1,26 +1,25 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; - +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ void main() { gl_Position = vertex_attrib; - gl_Position.z=1.0; + gl_Position.z = 1.0; } +/* clang-format off */ [fragment] - uniform sampler2D source_ssao; //texunit:0 +/* clang-format on */ uniform sampler2D source_depth; //texunit:1 uniform sampler2D source_normal; //texunit:3 - layout(location = 0) out float visibility; - ////////////////////////////////////////////////////////////////////////////////////////////// // Tunable Parameters: @@ -28,32 +27,30 @@ layout(location = 0) out float visibility; uniform float edge_sharpness; /** Step in 2-pixel intervals since we already blurred against neighbors in the - first AO pass. This constant can be increased while R decreases to improve - performance at the expense of some dithering artifacts. + first AO pass. This constant can be increased while R decreases to improve + performance at the expense of some dithering artifacts. - Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was - unobjectionable after shading was applied but eliminated most temporal incoherence - from using small numbers of sample taps. - */ + Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was + unobjectionable after shading was applied but eliminated most temporal incoherence + from using small numbers of sample taps. + */ uniform int filter_scale; /** Filter radius in pixels. This will be multiplied by SCALE. */ -#define R (4) - +#define R (4) ////////////////////////////////////////////////////////////////////////////////////////////// - // Gaussian coefficients const float gaussian[R + 1] = -// float[](0.356642, 0.239400, 0.072410, 0.009869); -// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 - float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 -// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + //float[](0.356642, 0.239400, 0.072410, 0.009869); + //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 /** (1, 0) or (0, 1)*/ -uniform ivec2 axis; +uniform ivec2 axis; uniform float camera_z_far; uniform float camera_z_near; @@ -72,11 +69,11 @@ void main() { float depth_divide = 1.0 / camera_z_far; -// depth*=depth_divide; + //depth *= depth_divide; /* - if (depth > camera_z_far*0.999) { - discard;//skybox + if (depth > camera_z_far * 0.999) { + discard; //skybox } */ @@ -96,23 +93,21 @@ void main() { if (r != 0) { ivec2 ppos = ssC + axis * (r * filter_scale); - float value = texelFetch(source_ssao, clamp(ppos,ivec2(0),clamp_limit), 0).r; - ivec2 rpos = clamp(ppos,ivec2(0),clamp_limit); + float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; + ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); float temp_depth = texelFetch(source_depth, rpos, 0).r; //vec3 temp_normal = texelFetch(source_normal, rpos, 0).rgb * 2.0 - 1.0; temp_depth = temp_depth * 2.0 - 1.0; temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near)); -// temp_depth *= depth_divide; + // temp_depth *= depth_divide; // spatial domain: offset gaussian tap float weight = 0.3 + gaussian[abs(r)]; //weight *= max(0.0,dot(temp_normal,normal)); // range domain (the "bilateral" weight). As depth difference increases, decrease weight. - weight *= max(0.0, 1.0 - - edge_sharpness * abs(temp_depth - depth) - ); + weight *= max(0.0, 1.0 - edge_sharpness * abs(temp_depth - depth)); sum += value * weight; totalWeight += weight; diff --git a/drivers/gles2/shaders/ssao_minify.glsl b/drivers/gles2/shaders/ssao_minify.glsl index 647c762438..272f3e236e 100644 --- a/drivers/gles2/shaders/ssao_minify.glsl +++ b/drivers/gles2/shaders/ssao_minify.glsl @@ -1,21 +1,23 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ void main() { gl_Position = vertex_attrib; } +/* clang-format off */ [fragment] - #ifdef MINIFY_START #define SDEPTH_TYPE highp sampler2D uniform float camera_z_far; uniform float camera_z_near; +/* clang-format on */ #else @@ -32,28 +34,23 @@ layout(location = 0) out mediump uint depth; void main() { - ivec2 ssP = ivec2(gl_FragCoord.xy); - // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. - // On DX9, the bit-and can be implemented with floating-point modulo + // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. + // On DX9, the bit-and can be implemented with floating-point modulo #ifdef MINIFY_START float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; fdepth = fdepth * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - fdepth = ((fdepth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + fdepth = ((fdepth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near)); #endif fdepth /= camera_z_far; - depth = uint(clamp(fdepth*65535.0,0.0,65535.0)); + depth = uint(clamp(fdepth * 65535.0, 0.0, 65535.0)); #else depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; #endif - - } - - diff --git a/drivers/gles2/shaders/stdlib.glsl b/drivers/gles2/shaders/stdlib.glsl index ebbdb96311..3674d70c9f 100644 --- a/drivers/gles2/shaders/stdlib.glsl +++ b/drivers/gles2/shaders/stdlib.glsl @@ -1,6 +1,5 @@ -vec2 select2(vec2 a, vec2 b, bvec2 c) -{ +vec2 select2(vec2 a, vec2 b, bvec2 c) { vec2 ret; ret.x = c.x ? b.x : a.x; @@ -9,8 +8,7 @@ vec2 select2(vec2 a, vec2 b, bvec2 c) return ret; } -vec3 select3(vec3 a, vec3 b, bvec3 c) -{ +vec3 select3(vec3 a, vec3 b, bvec3 c) { vec3 ret; ret.x = c.x ? b.x : a.x; @@ -20,8 +18,7 @@ vec3 select3(vec3 a, vec3 b, bvec3 c) return ret; } -vec4 select4(vec4 a, vec4 b, bvec4 c) -{ +vec4 select4(vec4 a, vec4 b, bvec4 c) { vec4 ret; ret.x = c.x ? b.x : a.x; @@ -32,14 +29,19 @@ vec4 select4(vec4 a, vec4 b, bvec4 c) return ret; } - -highp vec4 texel2DFetch(highp sampler2D tex, ivec2 size, ivec2 coord) -{ +highp vec4 texel2DFetch(highp sampler2D tex, ivec2 size, ivec2 coord) { float x_coord = float(2 * coord.x + 1) / float(size.x * 2); float y_coord = float(2 * coord.y + 1) / float(size.y * 2); - x_coord = float(coord.x) / float(size.x); - y_coord = float(coord.y) / float(size.y); - return texture2DLod(tex, vec2(x_coord, y_coord), 0.0); } + +#ifndef USE_GLES_OVER_GL +highp mat4 transpose(highp mat4 src) { + return mat4( + vec4(src[0].x, src[1].x, src[2].x, src[3].x), + vec4(src[0].y, src[1].y, src[2].y, src[3].y), + vec4(src[0].z, src[1].z, src[2].z, src[3].z), + vec4(src[0].w, src[1].w, src[2].w, src[3].w)); +} +#endif diff --git a/drivers/gles2/shaders/subsurf_scattering.glsl b/drivers/gles2/shaders/subsurf_scattering.glsl index fc66d66198..f40fb3a244 100644 --- a/drivers/gles2/shaders/subsurf_scattering.glsl +++ b/drivers/gles2/shaders/subsurf_scattering.glsl @@ -1,105 +1,93 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; out vec2 uv_interp; - void main() { uv_interp = uv_in; gl_Position = vertex_attrib; } +/* clang-format off */ [fragment] //#define QUALIFIER uniform // some guy on the interweb says it may be faster with this #define QUALIFIER const #ifdef USE_25_SAMPLES - -const int kernel_size=25; -QUALIFIER vec2 kernel[25] = vec2[] ( - vec2(0.530605, 0.0), - vec2(0.000973794, -3.0), - vec2(0.00333804, -2.52083), - vec2(0.00500364, -2.08333), - vec2(0.00700976, -1.6875), - vec2(0.0094389, -1.33333), - vec2(0.0128496, -1.02083), - vec2(0.017924, -0.75), - vec2(0.0263642, -0.520833), - vec2(0.0410172, -0.333333), - vec2(0.0493588, -0.1875), - vec2(0.0402784, -0.0833333), - vec2(0.0211412, -0.0208333), - vec2(0.0211412, 0.0208333), - vec2(0.0402784, 0.0833333), - vec2(0.0493588, 0.1875), - vec2(0.0410172, 0.333333), - vec2(0.0263642, 0.520833), - vec2(0.017924, 0.75), - vec2(0.0128496, 1.02083), - vec2(0.0094389, 1.33333), - vec2(0.00700976, 1.6875), - vec2(0.00500364, 2.08333), - vec2(0.00333804, 2.52083), - vec2(0.000973794, 3.0) -); - +const int kernel_size = 25; +/* clang-format on */ +QUALIFIER vec2 kernel[25] = vec2[]( + vec2(0.530605, 0.0), + vec2(0.000973794, -3.0), + vec2(0.00333804, -2.52083), + vec2(0.00500364, -2.08333), + vec2(0.00700976, -1.6875), + vec2(0.0094389, -1.33333), + vec2(0.0128496, -1.02083), + vec2(0.017924, -0.75), + vec2(0.0263642, -0.520833), + vec2(0.0410172, -0.333333), + vec2(0.0493588, -0.1875), + vec2(0.0402784, -0.0833333), + vec2(0.0211412, -0.0208333), + vec2(0.0211412, 0.0208333), + vec2(0.0402784, 0.0833333), + vec2(0.0493588, 0.1875), + vec2(0.0410172, 0.333333), + vec2(0.0263642, 0.520833), + vec2(0.017924, 0.75), + vec2(0.0128496, 1.02083), + vec2(0.0094389, 1.33333), + vec2(0.00700976, 1.6875), + vec2(0.00500364, 2.08333), + vec2(0.00333804, 2.52083), + vec2(0.000973794, 3.0)); #endif //USE_25_SAMPLES #ifdef USE_17_SAMPLES - -const int kernel_size=17; - +const int kernel_size = 17; QUALIFIER vec2 kernel[17] = vec2[]( - vec2(0.536343, 0.0), - vec2(0.00317394, -2.0), - vec2(0.0100386, -1.53125), - vec2(0.0144609, -1.125), - vec2(0.0216301, -0.78125), - vec2(0.0347317, -0.5), - vec2(0.0571056, -0.28125), - vec2(0.0582416, -0.125), - vec2(0.0324462, -0.03125), - vec2(0.0324462, 0.03125), - vec2(0.0582416, 0.125), - vec2(0.0571056, 0.28125), - vec2(0.0347317, 0.5), - vec2(0.0216301, 0.78125), - vec2(0.0144609, 1.125), - vec2(0.0100386, 1.53125), - vec2(0.00317394,2.0) -); - + vec2(0.536343, 0.0), + vec2(0.00317394, -2.0), + vec2(0.0100386, -1.53125), + vec2(0.0144609, -1.125), + vec2(0.0216301, -0.78125), + vec2(0.0347317, -0.5), + vec2(0.0571056, -0.28125), + vec2(0.0582416, -0.125), + vec2(0.0324462, -0.03125), + vec2(0.0324462, 0.03125), + vec2(0.0582416, 0.125), + vec2(0.0571056, 0.28125), + vec2(0.0347317, 0.5), + vec2(0.0216301, 0.78125), + vec2(0.0144609, 1.125), + vec2(0.0100386, 1.53125), + vec2(0.00317394, 2.0)); #endif //USE_17_SAMPLES - #ifdef USE_11_SAMPLES - -const int kernel_size=11; - +const int kernel_size = 11; QUALIFIER vec2 kernel[11] = vec2[]( - vec2(0.560479, 0.0), - vec2(0.00471691, -2.0), - vec2(0.0192831, -1.28), - vec2(0.03639, -0.72), - vec2(0.0821904, -0.32), - vec2(0.0771802, -0.08), - vec2(0.0771802, 0.08), - vec2(0.0821904, 0.32), - vec2(0.03639, 0.72), - vec2(0.0192831, 1.28), - vec2(0.00471691,2.0) -); - + vec2(0.560479, 0.0), + vec2(0.00471691, -2.0), + vec2(0.0192831, -1.28), + vec2(0.03639, -0.72), + vec2(0.0821904, -0.32), + vec2(0.0771802, -0.08), + vec2(0.0771802, 0.08), + vec2(0.0821904, 0.32), + vec2(0.03639, 0.72), + vec2(0.0192831, 1.28), + vec2(0.00471691, 2.0)); #endif //USE_11_SAMPLES - - uniform float max_radius; uniform float camera_z_far; uniform float camera_z_near; @@ -115,28 +103,24 @@ layout(location = 0) out vec4 frag_color; void main() { - float strength = texture(source_sss,uv_interp).r; - strength*=strength; //stored as sqrt + float strength = texture(source_sss, uv_interp).r; + strength *= strength; //stored as sqrt // Fetch color of current pixel: vec4 base_color = texture(source_diffuse, uv_interp); - - if (strength>0.0) { - + if (strength > 0.0) { // Fetch linear depth of current pixel: float depth = texture(source_depth, uv_interp).r * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - depth = ((depth + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + depth = ((depth + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; float scale = unit_size; //remember depth is negative by default in OpenGL #else depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near)); float scale = unit_size / depth; //remember depth is negative by default in OpenGL #endif - - // Calculate the final step to fetch the surrounding pixels: vec2 step = max_radius * scale * dir; step *= strength; // Modulate it using the alpha channel. @@ -157,35 +141,33 @@ void main() { #ifdef ENABLE_FOLLOW_SURFACE // If the difference in depth is huge, we lerp color back to "colorM": - float depth_cmp = texture(source_depth, offset).r *2.0 - 1.0; + float depth_cmp = texture(source_depth, offset).r * 2.0 - 1.0; #ifdef USE_ORTHOGONAL_PROJECTION - depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near)/(camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near))/2.0; + depth_cmp = ((depth_cmp + (camera_z_far + camera_z_near) / (camera_z_far - camera_z_near)) * (camera_z_far - camera_z_near)) / 2.0; #else depth_cmp = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth_cmp * (camera_z_far - camera_z_near)); #endif - float s = clamp(300.0f * scale * - max_radius * abs(depth - depth_cmp),0.0,1.0); + float s = clamp(300.0f * scale * max_radius * abs(depth - depth_cmp), 0.0, 1.0); color = mix(color, base_color.rgb, s); #endif // Accumulate: - color*=kernel[i].x; + color *= kernel[i].x; #ifdef ENABLE_STRENGTH_WEIGHTING float color_s = texture(source_sss, offset).r; - color_weight+=color_s * kernel[i].x; - color*=color_s; + color_weight += color_s * kernel[i].x; + color *= color_s; #endif color_accum += color; - } #ifdef ENABLE_STRENGTH_WEIGHTING - color_accum/=color_weight; + color_accum /= color_weight; #endif - frag_color = vec4(color_accum,base_color.a); //keep alpha (used for SSAO) + frag_color = vec4(color_accum, base_color.a); //keep alpha (used for SSAO) } else { frag_color = base_color; } diff --git a/drivers/gles2/shaders/tonemap.glsl b/drivers/gles2/shaders/tonemap.glsl index 2f671158b2..eae3b5a1ca 100644 --- a/drivers/gles2/shaders/tonemap.glsl +++ b/drivers/gles2/shaders/tonemap.glsl @@ -1,8 +1,9 @@ +/* clang-format off */ [vertex] - -layout(location=0) in highp vec4 vertex_attrib; -layout(location=4) in vec2 uv_in; +layout(location = 0) in highp vec4 vertex_attrib; +/* clang-format on */ +layout(location = 4) in vec2 uv_in; out vec2 uv_interp; @@ -11,19 +12,19 @@ void main() { gl_Position = vertex_attrib; uv_interp = uv_in; #ifdef V_FLIP - uv_interp.y = 1.0-uv_interp.y; + uv_interp.y = 1.0 - uv_interp.y; #endif - } +/* clang-format off */ [fragment] #if !defined(GLES_OVER_GL) precision mediump float; #endif - in vec2 uv_interp; +/* clang-format on */ uniform highp sampler2D source; //texunit:0 @@ -56,64 +57,54 @@ uniform sampler2D color_correction; //texunit:3 #endif - layout(location = 0) out vec4 frag_color; #ifdef USE_GLOW_FILTER_BICUBIC // w0, w1, w2, and w3 are the four cubic B-spline basis functions -float w0(float a) -{ - return (1.0/6.0)*(a*(a*(-a + 3.0) - 3.0) + 1.0); +float w0(float a) { + return (1.0 / 6.0) * (a * (a * (-a + 3.0) - 3.0) + 1.0); } -float w1(float a) -{ - return (1.0/6.0)*(a*a*(3.0*a - 6.0) + 4.0); +float w1(float a) { + return (1.0 / 6.0) * (a * a * (3.0 * a - 6.0) + 4.0); } -float w2(float a) -{ - return (1.0/6.0)*(a*(a*(-3.0*a + 3.0) + 3.0) + 1.0); +float w2(float a) { + return (1.0 / 6.0) * (a * (a * (-3.0 * a + 3.0) + 3.0) + 1.0); } -float w3(float a) -{ - return (1.0/6.0)*(a*a*a); +float w3(float a) { + return (1.0 / 6.0) * (a * a * a); } // g0 and g1 are the two amplitude functions -float g0(float a) -{ - return w0(a) + w1(a); +float g0(float a) { + return w0(a) + w1(a); } -float g1(float a) -{ - return w2(a) + w3(a); +float g1(float a) { + return w2(a) + w3(a); } // h0 and h1 are the two offset functions -float h0(float a) -{ - return -1.0 + w1(a) / (w0(a) + w1(a)); +float h0(float a) { + return -1.0 + w1(a) / (w0(a) + w1(a)); } -float h1(float a) -{ - return 1.0 + w3(a) / (w2(a) + w3(a)); +float h1(float a) { + return 1.0 + w3(a) / (w2(a) + w3(a)); } uniform ivec2 glow_texture_size; -vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod) -{ - float lod=float(p_lod); +vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { + float lod = float(p_lod); vec2 tex_size = vec2(glow_texture_size >> p_lod); - vec2 pixel_size =1.0/tex_size; - uv = uv*tex_size + 0.5; - vec2 iuv = floor( uv ); - vec2 fuv = fract( uv ); + vec2 pixel_size = 1.0 / tex_size; + uv = uv * tex_size + 0.5; + vec2 iuv = floor(uv); + vec2 fuv = fract(uv); float g0x = g0(fuv.x); float g1x = g1(fuv.x); @@ -127,24 +118,19 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod) vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size; vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size; - return g0(fuv.y) * (g0x * textureLod(tex, p0,lod) + - g1x * textureLod(tex, p1,lod)) + - g1(fuv.y) * (g0x * textureLod(tex, p2,lod) + - g1x * textureLod(tex, p3,lod)); + return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + + (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); } - - -#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod) +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) #else -#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod)) +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) #endif - -vec3 tonemap_filmic(vec3 color,float white) { +vec3 tonemap_filmic(vec3 color, float white) { float A = 0.15; float B = 0.50; @@ -154,11 +140,10 @@ vec3 tonemap_filmic(vec3 color,float white) { float F = 0.30; float W = 11.2; - vec3 coltn = ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; - float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F; - - return coltn/whitetn; + vec3 coltn = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; + float whitetn = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; + return coltn / whitetn; } vec3 tonemap_aces(vec3 color) { @@ -167,12 +152,12 @@ vec3 tonemap_aces(vec3 color) { float c = 2.43f; float d = 0.59f; float e = 0.14f; - return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0)); + return color = clamp((color * (a * color + b)) / (color * (c * color + d) + e), vec3(0.0), vec3(1.0)); } -vec3 tonemap_reindhart(vec3 color,float white) { +vec3 tonemap_reindhart(vec3 color, float white) { - return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color ); + return (color * (1.0 + (color / (white)))) / (1.0 + color); } void main() { @@ -181,10 +166,10 @@ void main() { #ifdef USE_AUTO_EXPOSURE - color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; + color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / auto_exposure_grey; #endif - color*=exposure; + color *= exposure; #if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) #define USING_GLOW @@ -195,56 +180,54 @@ void main() { #ifdef USE_GLOW_LEVEL1 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 1).rgb; #endif #ifdef USE_GLOW_LEVEL2 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 2).rgb; #endif #ifdef USE_GLOW_LEVEL3 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 3).rgb; #endif #ifdef USE_GLOW_LEVEL4 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 4).rgb; #endif #ifdef USE_GLOW_LEVEL5 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 5).rgb; #endif #ifdef USE_GLOW_LEVEL6 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 6).rgb; #endif #ifdef USE_GLOW_LEVEL7 - glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb; + glow += GLOW_TEXTURE_SAMPLE(source_glow, uv_interp, 7).rgb; #endif - glow *= glow_intensity; #endif - #ifdef USE_REINDHART_TONEMAPPER - color.rgb = tonemap_reindhart(color.rgb,white); + color.rgb = tonemap_reindhart(color.rgb, white); -# if defined(USING_GLOW) - glow = tonemap_reindhart(glow,white); -# endif +#if defined(USING_GLOW) + glow = tonemap_reindhart(glow, white); +#endif #endif #ifdef USE_FILMIC_TONEMAPPER - color.rgb = tonemap_filmic(color.rgb,white); + color.rgb = tonemap_filmic(color.rgb, white); -# if defined(USING_GLOW) - glow = tonemap_filmic(glow,white); -# endif +#if defined(USING_GLOW) + glow = tonemap_filmic(glow, white); +#endif #endif @@ -252,26 +235,26 @@ void main() { color.rgb = tonemap_aces(color.rgb); -# if defined(USING_GLOW) +#if defined(USING_GLOW) glow = tonemap_aces(glow); -# endif +#endif #endif //regular Linear -> SRGB conversion vec3 a = vec3(0.055); - color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); + color.rgb = mix((vec3(1.0) + a) * pow(color.rgb, vec3(1.0 / 2.4)) - a, 12.92 * color.rgb, lessThan(color.rgb, vec3(0.0031308))); #if defined(USING_GLOW) - glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308))); + glow = mix((vec3(1.0) + a) * pow(glow, vec3(1.0 / 2.4)) - a, 12.92 * glow, lessThan(glow, vec3(0.0031308))); #endif -//glow needs to be added in SRGB space (together with image space effects) + //glow needs to be added in SRGB space (together with image space effects) - color.rgb = clamp(color.rgb,0.0,1.0); + color.rgb = clamp(color.rgb, 0.0, 1.0); #if defined(USING_GLOW) - glow = clamp(glow,0.0,1.0); + glow = clamp(glow, 0.0, 1.0); #endif #ifdef USE_GLOW_REPLACE @@ -291,33 +274,32 @@ void main() { { glow = (glow * 0.5) + 0.5; - color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); - color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); - color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); + color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); } #endif #if defined(USING_GLOW) && !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) //additive - color.rgb+=glow; + color.rgb += glow; #endif #ifdef USE_BCS - color.rgb = mix(vec3(0.0),color.rgb,bcs.x); - color.rgb = mix(vec3(0.5),color.rgb,bcs.y); - color.rgb = mix(vec3(dot(vec3(1.0),color.rgb)*0.33333),color.rgb,bcs.z); + color.rgb = mix(vec3(0.0), color.rgb, bcs.x); + color.rgb = mix(vec3(0.5), color.rgb, bcs.y); + color.rgb = mix(vec3(dot(vec3(1.0), color.rgb) * 0.33333), color.rgb, bcs.z); #endif #ifdef USE_COLOR_CORRECTION - color.r = texture(color_correction,vec2(color.r,0.0)).r; - color.g = texture(color_correction,vec2(color.g,0.0)).g; - color.b = texture(color_correction,vec2(color.b,0.0)).b; + color.r = texture(color_correction, vec2(color.r, 0.0)).r; + color.g = texture(color_correction, vec2(color.g, 0.0)).g; + color.b = texture(color_correction, vec2(color.b, 0.0)).b; #endif - - frag_color=vec4(color.rgb,1.0); + frag_color = vec4(color.rgb, 1.0); } |