summaryrefslogtreecommitdiff
path: root/drivers/gles3/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gles3/shaders')
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/cube_to_dp.glsl79
-rw-r--r--drivers/gles3/shaders/scene.glsl341
3 files changed, 366 insertions, 55 deletions
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index afffe10316..44d325b091 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -6,4 +6,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('canvas_shadow.glsl');
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
+ env.GLES3_GLSL('cube_to_dp.glsl');
diff --git a/drivers/gles3/shaders/cube_to_dp.glsl b/drivers/gles3/shaders/cube_to_dp.glsl
new file mode 100644
index 0000000000..5ffc78c0b9
--- /dev/null
+++ b/drivers/gles3/shaders/cube_to_dp.glsl
@@ -0,0 +1,79 @@
+[vertex]
+
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+out vec2 uv_interp;
+
+void main() {
+
+ uv_interp = uv_in;
+ gl_Position = vertex_attrib;
+}
+
+[fragment]
+
+
+uniform highp samplerCube source_cube; //texunit:0
+in vec2 uv_interp;
+
+uniform bool z_flip;
+uniform highp float z_far;
+uniform highp float z_near;
+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));
+ } else {
+ 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 = 0.5 - 0.5*((normal.x * normal.x) + (normal.y * normal.y));
+ normal = normalize(normal);
+
+/*
+ normal.z=0.5;
+ normal=normalize(normal);
+*/
+ if (!z_flip) {
+ normal.z=-normal.z;
+ }
+
+ //normal = normalize(vec3( uv_interp * 2.0 - 1.0, 1.0 ));
+ float depth = texture(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 ) ;
+ } else {
+ // 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);
+
+
+ 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;
+}
+
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 60ac015a17..de1591e8ff 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1,7 +1,6 @@
[vertex]
-#define ENABLE_UV_INTERP
/*
from VisualServer:
@@ -56,6 +55,15 @@ layout(std140) uniform SceneData { //ubo:0
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
+
+ float shadow_z_offset;
+ float shadow_z_slope_scale;
+ float shadow_dual_paraboloid_render_zfar;
+ float shadow_dual_paraboloid_render_side;
+
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
};
uniform highp mat4 world_transform;
@@ -68,6 +76,7 @@ layout(std140) uniform LightData { //ubo:3
mediump vec4 light_direction_attenuation;
mediump vec4 light_color_energy;
mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
+ mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@@ -75,19 +84,6 @@ layout(std140) uniform LightData { //ubo:3
highp mat4 shadow_matrix4;
};
-#ifdef USE_FORWARD_1_SHADOW_MAP
-out mediump vec4 forward_shadow_pos1;
-#endif
-
-#ifdef USE_FORWARD_2_SHADOW_MAP
-out mediump vec4 forward_shadow_pos2;
-#endif
-
-#ifdef USE_FORWARD_4_SHADOW_MAP
-out mediump vec4 forward_shadow_pos3;
-out mediump vec4 forward_shadow_pos4;
-#endif
-
#endif
/* Varyings */
@@ -120,13 +116,6 @@ varying vec4 position_interp;
#endif
-#ifdef USE_SHADOW_PASS
-
-uniform highp float shadow_z_offset;
-uniform highp float shadow_z_slope_scale;
-
-#endif
-
VERTEX_SHADER_GLOBALS
@@ -141,6 +130,11 @@ MATERIAL_UNIFORMS
#endif
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+out highp float dp_clip;
+
+#endif
void main() {
@@ -206,24 +200,49 @@ VERTEX_SHADER_CODE
}
+ vertex_interp = vertex.xyz;
+ normal_interp = normal;
+
+#if defined(ENABLE_TANGENT_INTERP)
+ tangent_interp = tangent;
+ binormal_interp = binormal;
+#endif
+
+#ifdef RENDER_SHADOW
+
+
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+ vertex_interp.z*= shadow_dual_paraboloid_render_side;
+ normal_interp.z*= shadow_dual_paraboloid_render_side;
-#ifdef USE_SHADOW_PASS
+ 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)*shadow_z_offset;
+ 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.xyz=vtx;
+ vertex.w=1.0;
+
+
+#else
float z_ofs = shadow_z_offset;
z_ofs += (1.0-abs(normal_interp.z))*shadow_z_slope_scale;
vertex_interp.z-=z_ofs;
-#endif
+#endif //RENDER_SHADOW_DUAL_PARABOLOID
- vertex_interp = vertex.xyz;
- normal_interp = normal;
+#endif //RENDER_SHADOW
-#if defined(ENABLE_TANGENT_INTERP)
- tangent_interp = tangent;
- binormal_interp = binormal;
-#endif
-#if !defined(SKIP_TRANSFORM_USED)
+#if !defined(SKIP_TRANSFORM_USED) && !defined(RENDER_SHADOW_DUAL_PARABOLOID)
gl_Position = projection_matrix * vec4(vertex_interp,1.0);
#else
gl_Position = vertex;
@@ -239,11 +258,6 @@ VERTEX_SHADER_CODE
#define M_PI 3.14159265359
-
-#define ENABLE_UV_INTERP
-//hack to use uv if no uv present so it works with lightmap
-
-
/* Varyings */
#if defined(ENABLE_COLOR_INTERP)
@@ -318,6 +332,15 @@ layout(std140) uniform SceneData {
highp vec4 bg_color;
float ambient_energy;
float bg_energy;
+
+ float shadow_z_offset;
+ float shadow_z_slope_scale;
+ float shadow_dual_paraboloid_render_zfar;
+ float shadow_dual_paraboloid_render_side;
+
+ vec2 shadow_atlas_pixel_size;
+ vec2 directional_shadow_pixel_size;
+
};
@@ -328,7 +351,8 @@ layout(std140) uniform LightData {
highp vec4 light_pos_inv_radius;
mediump vec4 light_direction_attenuation;
mediump vec4 light_color_energy;
- mediump vec4 light_params; //cone attenuation, specular, shadow darkening,
+ mediump vec4 light_params; //cone attenuation, specular, shadow darkening, shadow enabled
+ mediump vec4 light_clamp;
mediump vec4 shadow_split_offsets;
highp mat4 shadow_matrix1;
highp mat4 shadow_matrix2;
@@ -336,20 +360,12 @@ layout(std140) uniform LightData {
highp mat4 shadow_matrix4;
};
-#ifdef USE_FORWARD_1_SHADOW_MAP
-in mediump vec4 forward_shadow_pos1;
#endif
-#ifdef USE_FORWARD_2_SHADOW_MAP
-in mediump vec4 forward_shadow_pos2;
-#endif
-#ifdef USE_FORWARD_4_SHADOW_MAP
-in mediump vec4 forward_shadow_pos3;
-in mediump vec4 forward_shadow_pos4;
-#endif
+uniform highp sampler2DShadow directional_shadow; //texunit:-4
+uniform highp sampler2DShadow shadow_atlas; //texunit:-3
-#endif
#ifdef USE_MULTIPLE_RENDER_TARGETS
@@ -408,10 +424,27 @@ void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color,
}
+float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) {
+
+ return textureProj(shadow,vec4(pos,depth,1.0));
+}
+
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+in highp float dp_clip;
+
+#endif
+
void main() {
+#ifdef RENDER_SHADOW_DUAL_PARABOLOID
+
+ if (dp_clip>0.0)
+ discard;
+#endif
+
//lay out everything, whathever is unused is optimized away anyway
- vec3 vertex = vertex_interp;
+ highp vec3 vertex = vertex_interp;
vec3 albedo = vec3(0.8,0.8,0.8);
vec3 specular = vec3(0.2,0.2,0.2);
float roughness = 1.0;
@@ -528,27 +561,216 @@ FRAGMENT_SHADER_CODE
#endif
-#ifdef USE_FORWARD_LIGHTING
-
#ifdef USE_FORWARD_DIRECTIONAL
- light_compute(normal,light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,1.0,diffuse_light,specular_light);
+ float light_attenuation=1.0;
+
+#ifdef LIGHT_DIRECTIONAL_SHADOW
+
+ if (gl_FragCoord.w > shadow_split_offsets.w) {
+
+ vec3 pssm_coord;
+
+#ifdef LIGHT_USE_PSSM_BLEND
+ float pssm_blend;
+ vec3 pssm_coord2;
+ bool use_blend=true;
+ vec3 light_pssm_split_inv = 1.0/shadow_split_offsets.xyz;
+ float w_inv = 1.0/gl_FragCoord.w;
#endif
+
+#ifdef LIGHT_USE_PSSM4
+
+
+ if (gl_FragCoord.w > shadow_split_offsets.y) {
+
+ if (gl_FragCoord.w > shadow_split_offsets.x) {
+
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ ambient_light=vec3(1.0,0.4,0.4);
+
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+ splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
+
+ } else {
+
+ highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ ambient_light=vec3(0.4,1.0,0.4);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ splane=(shadow_matrix3 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv);
+#endif
+
+ }
+ } else {
+
+
+ if (gl_FragCoord.w > shadow_split_offsets.z) {
+
+ highp vec4 splane=(shadow_matrix3 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ ambient_light=vec3(0.4,0.4,1.0);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ splane=(shadow_matrix4 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv);
+#endif
+
+ } else {
+ highp vec4 splane=(shadow_matrix4 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ diffuse_light*=vec3(1.0,0.4,1.0);
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ use_blend=false;
+
+#endif
+
+ }
+ }
+
+#endif //LIGHT_USE_PSSM4
+
+#ifdef LIGHT_USE_PSSM2
+
+ if (gl_FragCoord.w > shadow_split_offsets.x) {
+
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+
+ splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord2=splane.xyz/splane.w;
+ pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
+
+ } else {
+ highp vec4 splane=(shadow_matrix2 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+#if defined(LIGHT_USE_PSSM_BLEND)
+ use_blend=false;
+
+#endif
+
+ }
+
+#endif //LIGHT_USE_PSSM2
+
+#if !defined(LIGHT_USE_PSSM4) && !defined(LIGHT_USE_PSSM2)
+ { //regular orthogonal
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ pssm_coord=splane.xyz/splane.w;
+ }
+#endif
+
+
+ //one one sample
+ light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp);
+
+
+#if defined(LIGHT_USE_PSSM_BLEND)
+ if (use_blend) {
+ float light_attenuation2=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord2.xy,pssm_coord2.z,light_clamp);
+ light_attenuation=mix(light_attenuation,light_attenuation2,pssm_blend);
+ }
+#endif
+
+ }
+
+#endif //LIGHT_DIRECTIONAL_SHADOW
+
+ light_compute(normal,-light_direction_attenuation.xyz,eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
+
+
+#endif //USE_FORWARD_DIRECTIONAL
+
+
#ifdef USE_FORWARD_OMNI
vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex;
float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w;
float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w );
+
+ if (light_params.w>0.5) {
+ //there is a shadowmap
+
+ highp vec3 splane=(shadow_matrix1 * vec4(vertex,1.0)).xyz;
+ float shadow_len=length(splane);
+ splane=normalize(splane);
+ 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;
+
+ //if (clamp_rect.z<clamp_rect.w) {
+ // clamp_rect.x+=clamp_rect.z;
+ //} else {
+ // clamp_rect.y+=clamp_rect.w;
+ //}
+
+ }
+
+ splane.xy/=splane.z;
+ splane.xy=splane.xy * 0.5 + 0.5;
+ splane.z = shadow_len * light_pos_inv_radius.w;
+
+ splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw;
+
+ light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect);
+ }
+
light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
-#endif
+
+#endif //USE_FORWARD_OMNI
#ifdef USE_FORWARD_SPOT
-#endif
+ vec3 light_rel_vec = light_pos_inv_radius.xyz-vertex;
+ float normalized_distance = length( light_rel_vec )*light_pos_inv_radius.w;
+ float light_attenuation = pow( max(1.0 - normalized_distance, 0.0), light_direction_attenuation.w );
+ vec3 spot_dir = light_direction_attenuation.xyz;
+ float spot_cutoff=light_params.y;
+ float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff);
+ float rim = (1.0 - scos) / (1.0 - spot_cutoff);
+ light_attenuation *= 1.0 - pow( rim, light_params.x);
+
+ if (light_params.w>0.5) {
+ //there is a shadowmap
+
+ highp vec4 splane=(shadow_matrix1 * vec4(vertex,1.0));
+ splane.xyz/=splane.w;
+ // splane.xy=splane.xy*0.5+0.5;
+
+ //splane.xy=light_clamp.xy+splane.xy*light_clamp.zw;
+ light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,light_clamp);
+
+ }
+
+ light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light);
+
+#endif //USE_FORWARD_SPOT
-#endif
#if defined(USE_LIGHT_SHADER_CODE)
@@ -560,6 +782,11 @@ LIGHT_SHADER_CODE
}
#endif
+#ifdef RENDER_SHADOW
+//nothing happens, so a tree-ssa optimizer will result in no fragment shader :)
+#else
+
+
#ifdef USE_MULTIPLE_RENDER_TARGETS
//approximate ambient scale for SSAO, since we will lack full ambient
@@ -574,13 +801,17 @@ LIGHT_SHADER_CODE
#else
+
#ifdef SHADELESS
frag_color=vec4(albedo,alpha);
#else
frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
-#endif
+#endif //SHADELESS
+
+#endif //USE_MULTIPLE_RENDER_TARGETS
+
+#endif //RENDER_SHADOW
-#endif
}