diff options
Diffstat (limited to 'drivers/gles3/shaders/scene.glsl')
-rw-r--r-- | drivers/gles3/shaders/scene.glsl | 254 |
1 files changed, 167 insertions, 87 deletions
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index de1591e8ff..ceb5a72118 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -68,24 +68,26 @@ layout(std140) uniform SceneData { //ubo:0 uniform highp mat4 world_transform; -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { //ubo:3 +layout(std140) uniform DirectionalLightData { //ubo:3 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, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; #endif + /* Varyings */ out highp vec3 vertex_interp; @@ -343,30 +345,71 @@ layout(std140) uniform SceneData { }; +//directional light data -#ifdef USE_FORWARD_LIGHTING +#ifdef USE_LIGHT_DIRECTIONAL -layout(std140) uniform LightData { +layout(std140) uniform DirectionalLightData { 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, shadow enabled + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, mediump vec4 light_clamp; - mediump vec4 shadow_split_offsets; + mediump vec4 shadow_color; highp mat4 shadow_matrix1; highp mat4 shadow_matrix2; highp mat4 shadow_matrix3; highp mat4 shadow_matrix4; + mediump vec4 shadow_split_offsets; }; + +uniform highp sampler2DShadow directional_shadow; //texunit:-4 + #endif +//omni and spot + +struct LightData { + + highp vec4 light_pos_inv_radius; + mediump vec4 light_direction_attenuation; + mediump vec4 light_color_energy; + mediump vec4 light_params; //cone attenuation, angle, specular, shadow enabled, + mediump vec4 light_clamp; + mediump vec4 shadow_color; + highp mat4 shadow_matrix; + +}; + + +layout(std140) uniform OmniLightData { //ubo:4 + + LightData omni_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + +layout(std140) uniform SpotLightData { //ubo:5 + + LightData spot_lights[MAX_LIGHT_DATA_STRUCTS]; +}; + -uniform highp sampler2DShadow directional_shadow; //texunit:-4 uniform highp sampler2DShadow shadow_atlas; //texunit:-3 +#ifdef USE_FORWARD_LIGHTING + +uniform int omni_light_indices[MAX_FORWARD_LIGHTS]; +uniform int omni_light_count; + +uniform int spot_light_indices[MAX_FORWARD_LIGHTS]; +uniform int spot_light_count; + +#endif + + + #ifdef USE_MULTIPLE_RENDER_TARGETS layout(location=0) out vec4 diffuse_buffer; @@ -415,18 +458,51 @@ float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0) return dotNL * D * F * vis; } -void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 diffuse_color, vec3 specular_color, float roughness, float attenuation, inout vec3 diffuse, inout vec3 specular) { +void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - diffuse += max(0.0,dot(normal,light_vec)) * diffuse_color * attenuation; + diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color; //specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation; float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0; - specular += s * specular_color * attenuation; + specular += s * light_color * specular_color; } float sample_shadow(highp sampler2DShadow shadow, vec2 shadow_pixel_size, vec2 pos, float depth, vec4 clamp_rect) { +#ifdef SHADOW_MODE_PCF_13 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,-shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x*2.0,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y*2.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y*2.0),depth,1.0)); + return avg*(1.0/13.0); + +#endif + +#ifdef SHADOW_MODE_PCF_5 + + float avg=textureProj(shadow,vec4(pos,depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(-shadow_pixel_size.x,0.0),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,shadow_pixel_size.y),depth,1.0)); + avg+=textureProj(shadow,vec4(pos+vec2(0.0,-shadow_pixel_size.y),depth,1.0)); + return avg*(1.0/5.0); +#endif + +#if !defined(SHADOW_MODE_PCF_5) && !defined(SHADOW_MODE_PCF_13) + return textureProj(shadow,vec4(pos,depth,1.0)); +#endif + } #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -435,6 +511,73 @@ in highp float dp_clip; #endif +void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex; + float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), omni_lights[idx].light_direction_attenuation.w )); + + if (omni_lights[idx].light_params.w>0.5) { + //there is a shadowmap + + highp vec3 splane=(omni_lights[idx].shadow_matrix * vec4(vertex,1.0)).xyz; + float shadow_len=length(splane); + splane=normalize(splane); + vec4 clamp_rect=omni_lights[idx].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 * omni_lights[idx].light_pos_inv_radius.w; + + splane.xy = clamp_rect.xy+splane.xy*clamp_rect.zw; + + light_attenuation*=mix(omni_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect)); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); + +} + +void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex; + float normalized_distance = length( light_rel_vec )*spot_lights[idx].light_pos_inv_radius.w; + vec3 light_attenuation = vec3(pow( max(1.0 - normalized_distance, 0.0), spot_lights[idx].light_direction_attenuation.w )); + vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz; + float spot_cutoff=spot_lights[idx].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, spot_lights[idx].light_params.x); + + if (spot_lights[idx].light_params.w>0.5) { + //there is a shadowmap + highp vec4 splane=(spot_lights[idx].shadow_matrix * vec4(vertex,1.0)); + splane.xyz/=splane.w; + light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp)); + } + + light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); + +} + void main() { #ifdef RENDER_SHADOW_DUAL_PARABOLOID @@ -561,9 +704,9 @@ FRAGMENT_SHADER_CODE #endif -#ifdef USE_FORWARD_DIRECTIONAL +#ifdef USE_LIGHT_DIRECTIONAL - float light_attenuation=1.0; + vec3 light_attenuation=vec3(1.0); #ifdef LIGHT_DIRECTIONAL_SHADOW @@ -589,7 +732,6 @@ FRAGMENT_SHADER_CODE 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) @@ -603,7 +745,6 @@ FRAGMENT_SHADER_CODE 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)); @@ -619,7 +760,6 @@ FRAGMENT_SHADER_CODE 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)); @@ -678,12 +818,12 @@ FRAGMENT_SHADER_CODE //one one sample - light_attenuation=sample_shadow(directional_shadow,directional_shadow_pixel_size,pssm_coord.xy,pssm_coord.z,light_clamp); + light_attenuation=mix(shadow_color.rgb,vec3(1.0),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); + vec3 light_attenuation2=mix(shadow_color.rgb,vec3(1.0),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 @@ -692,84 +832,24 @@ FRAGMENT_SHADER_CODE #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 - + light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light); -#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 ); +#endif //#USE_LIGHT_DIRECTIONAL - 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; +#ifdef USE_FORWARD_LIGHTING - light_attenuation*=sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect); + for(int i=0;i<omni_light_count;i++) { + light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light); } - light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); - - -#endif //USE_FORWARD_OMNI - -#ifdef USE_FORWARD_SPOT - - 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); - + for(int i=0;i<spot_light_count;i++) { + light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light); } - light_compute(normal,normalize(light_rel_vec),eye_vec,albedo,specular,roughness,light_attenuation,diffuse_light,specular_light); +#endif -#endif //USE_FORWARD_SPOT |