diff --git a/files/shaders/CMakeLists.txt b/files/shaders/CMakeLists.txt index 7baca78ef..41763f3e1 100644 --- a/files/shaders/CMakeLists.txt +++ b/files/shaders/CMakeLists.txt @@ -18,6 +18,8 @@ set(SHADER_FILES parallax.glsl s360_fragment.glsl s360_vertex.glsl + shadows_vertex.glsl + shadows_fragment.glsl ) copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}") diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index 407541634..fffb9c83b 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -1,7 +1,5 @@ #version 120 -#define SHADOWS @shadows_enabled - #if @diffuseMap uniform sampler2D diffuseMap; varying vec2 diffuseMapUV; @@ -57,13 +55,7 @@ centroid varying vec4 passColor; varying vec3 passViewPos; varying vec3 passNormal; -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform sampler2DShadow shadowTexture@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS - +#include "shadows_fragment.glsl" #include "lighting.glsl" #include "parallax.glsl" @@ -122,29 +114,7 @@ void main() gl_FragData[0].xyz = mix(gl_FragData[0].xyz, decalTex.xyz, decalTex.a); #endif - float shadowing = 1.0; -#if SHADOWS - #if @shadowMapsOverlap - bool doneShadows = false; - @foreach shadow_texture_unit_index @shadow_texture_unit_list - if (!doneShadows) - { - vec2 shadowXY = shadowSpaceCoords@shadow_texture_unit_index.xy / shadowSpaceCoords@shadow_texture_unit_index.w; - if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) - { - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - - if (all(lessThan(shadowXY, vec2(0.95, 0.95))) && all(greaterThan(shadowXY, vec2(0.05, 0.05)))) - doneShadows = true; - } - } - @endforeach - #else - @foreach shadow_texture_unit_index @shadow_texture_unit_list - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - @endforeach - #endif -#endif // SHADOWS + float shadowing = unshadowedLightRatio(); #if !PER_PIXEL_LIGHTING gl_FragData[0] *= lighting + vec4(shadowDiffuseLighting * shadowing, 0); diff --git a/files/shaders/objects_vertex.glsl b/files/shaders/objects_vertex.glsl index 02960e5b4..3d7f49eee 100644 --- a/files/shaders/objects_vertex.glsl +++ b/files/shaders/objects_vertex.glsl @@ -1,7 +1,5 @@ #version 120 -#define SHADOWS @shadows_enabled - #if @diffuseMap varying vec2 diffuseMapUV; #endif @@ -48,12 +46,7 @@ centroid varying vec4 passColor; varying vec3 passViewPos; varying vec3 passNormal; -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform int shadowTextureUnit@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS +#include "shadows_vertex.glsl" #include "lighting.glsl" @@ -110,12 +103,5 @@ void main(void) passViewPos = viewPos.xyz; passNormal = gl_Normal.xyz; -#if SHADOWS - // This matrix has the opposite handedness to the others used here, so multiplication must have the vector to the left. Alternatively it could be transposed after construction, but that's extra work for the GPU just to make the code look a tiny bit cleaner. - mat4 eyePlaneMat; - @foreach shadow_texture_unit_index @shadow_texture_unit_list - eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]); - shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat; - @endforeach -#endif // SHADOWS + setupShadowCoords(viewPos); } diff --git a/files/shaders/shadows_fragment.glsl b/files/shaders/shadows_fragment.glsl new file mode 100644 index 000000000..cc1b38b59 --- /dev/null +++ b/files/shaders/shadows_fragment.glsl @@ -0,0 +1,36 @@ +#define SHADOWS @shadows_enabled + +#if SHADOWS + @foreach shadow_texture_unit_index @shadow_texture_unit_list + uniform sampler2DShadow shadowTexture@shadow_texture_unit_index; + varying vec4 shadowSpaceCoords@shadow_texture_unit_index; + @endforeach +#endif // SHADOWS + +float unshadowedLightRatio() +{ + float shadowing = 1.0; +#if SHADOWS + #if @shadowMapsOverlap + bool doneShadows = false; + @foreach shadow_texture_unit_index @shadow_texture_unit_list + if (!doneShadows) + { + vec2 shadowXY = shadowSpaceCoords@shadow_texture_unit_index.xy / shadowSpaceCoords@shadow_texture_unit_index.w; + if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) + { + shadowing = min(shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r, shadowing); + + if (all(lessThan(shadowXY, vec2(0.95, 0.95))) && all(greaterThan(shadowXY, vec2(0.05, 0.05)))) + doneShadows = true; + } + } + @endforeach + #else + @foreach shadow_texture_unit_index @shadow_texture_unit_list + shadowing = min(shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r, shadowing); + @endforeach + #endif +#endif // SHADOWS + return shadowing; +} \ No newline at end of file diff --git a/files/shaders/shadows_vertex.glsl b/files/shaders/shadows_vertex.glsl new file mode 100644 index 000000000..bbc1a4036 --- /dev/null +++ b/files/shaders/shadows_vertex.glsl @@ -0,0 +1,20 @@ +#define SHADOWS @shadows_enabled + +#if SHADOWS + @foreach shadow_texture_unit_index @shadow_texture_unit_list + uniform int shadowTextureUnit@shadow_texture_unit_index; + varying vec4 shadowSpaceCoords@shadow_texture_unit_index; + @endforeach +#endif // SHADOWS + +void setupShadowCoords(vec4 viewPos) +{ +#if SHADOWS + // This matrix has the opposite handedness to the others used here, so multiplication must have the vector to the left. Alternatively it could be transposed after construction, but that's extra work for the GPU just to make the code look a tiny bit cleaner. + mat4 eyePlaneMat; + @foreach shadow_texture_unit_index @shadow_texture_unit_list + eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]); + shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat; + @endforeach +#endif // SHADOWS +} \ No newline at end of file diff --git a/files/shaders/terrain_fragment.glsl b/files/shaders/terrain_fragment.glsl index 57403f1a4..219b92c99 100644 --- a/files/shaders/terrain_fragment.glsl +++ b/files/shaders/terrain_fragment.glsl @@ -1,7 +1,5 @@ #version 120 -#define SHADOWS @shadows_enabled - varying vec2 uv; uniform sampler2D diffuseMap; @@ -27,13 +25,7 @@ centroid varying vec4 passColor; varying vec3 passViewPos; varying vec3 passNormal; -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform sampler2DShadow shadowTexture@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS - +#include "shadows_fragment.glsl" #include "lighting.glsl" #include "parallax.glsl" @@ -74,29 +66,7 @@ void main() gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a; #endif - float shadowing = 1.0; -#if SHADOWS - #if @shadowMapsOverlap - bool doneShadows = false; - @foreach shadow_texture_unit_index @shadow_texture_unit_list - if (!doneShadows) - { - vec2 shadowXY = shadowSpaceCoords@shadow_texture_unit_index.xy / shadowSpaceCoords@shadow_texture_unit_index.w; - if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) - { - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - - if (all(lessThan(shadowXY, vec2(0.95, 0.95))) && all(greaterThan(shadowXY, vec2(0.05, 0.05)))) - doneShadows = true; - } - } - @endforeach - #else - @foreach shadow_texture_unit_index @shadow_texture_unit_list - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - @endforeach - #endif -#endif // SHADOWS + float shadowing = unshadowedLightRatio(); #if !PER_PIXEL_LIGHTING gl_FragData[0] *= lighting + vec4(shadowDiffuseLighting * shadowing, 0); diff --git a/files/shaders/terrain_vertex.glsl b/files/shaders/terrain_vertex.glsl index 57af0575c..669eac012 100644 --- a/files/shaders/terrain_vertex.glsl +++ b/files/shaders/terrain_vertex.glsl @@ -1,7 +1,5 @@ #version 120 -#define SHADOWS @shadows_enabled - varying vec2 uv; varying float depth; @@ -16,12 +14,7 @@ centroid varying vec4 passColor; varying vec3 passViewPos; varying vec3 passNormal; -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform int shadowTextureUnit@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS +#include "shadows_vertex.glsl" #include "lighting.glsl" @@ -44,12 +37,5 @@ void main(void) uv = gl_MultiTexCoord0.xy; -#if SHADOWS - // This matrix has the opposite handedness to the others used here, so multiplication must have the vector to the left. Alternatively it could be transposed after construction, but that's extra work for the GPU just to make the code look a tiny bit cleaner. - mat4 eyePlaneMat; - @foreach shadow_texture_unit_index @shadow_texture_unit_list - eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]); - shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat; - @endforeach -#endif // SHADOWS + setupShadowCoords(viewPos); } diff --git a/files/shaders/water_fragment.glsl b/files/shaders/water_fragment.glsl index c2628eb7f..a227e1e68 100644 --- a/files/shaders/water_fragment.glsl +++ b/files/shaders/water_fragment.glsl @@ -1,7 +1,6 @@ #version 120 #define REFRACTION @refraction_enabled -#define SHADOWS @shadows_enabled // Inspired by Blender GLSL Water by martinsh ( https://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html ) @@ -143,12 +142,7 @@ uniform vec3 nodePosition; uniform float rainIntensity; -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform sampler2DShadow shadowTexture@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS +#include "shadows_fragment.glsl" float frustumDepth; @@ -166,33 +160,7 @@ void main(void) vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0; UV.y *= -1.0; -#if SHADOWS - float shadowing = 1.0; - #if @shadowMapsOverlap - bool doneShadows = false; - @foreach shadow_texture_unit_index @shadow_texture_unit_list - if (!doneShadows) - { - vec2 shadowXY = shadowSpaceCoords@shadow_texture_unit_index.xy / shadowSpaceCoords@shadow_texture_unit_index.w; - if (all(lessThan(shadowXY, vec2(1.0, 1.0))) && all(greaterThan(shadowXY, vec2(0.0, 0.0)))) - { - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - - if (all(lessThan(shadowXY, vec2(0.95, 0.95))) && all(greaterThan(shadowXY, vec2(0.05, 0.05)))) - doneShadows = true; - } - } - @endforeach - #else - @foreach shadow_texture_unit_index @shadow_texture_unit_list - shadowing *= shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r; - @endforeach - #endif - - float shadow = shadowing; -#else // NOT SHADOWS - float shadow = 1.0; -#endif // SHADOWS + float shadow = unshadowedLightRatio(); vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; screenCoords.y = (1.0-screenCoords.y); diff --git a/files/shaders/water_vertex.glsl b/files/shaders/water_vertex.glsl index f51baf932..b028d90d2 100644 --- a/files/shaders/water_vertex.glsl +++ b/files/shaders/water_vertex.glsl @@ -4,14 +4,7 @@ varying vec3 screenCoordsPassthrough; varying vec4 position; varying float depthPassthrough; -#define SHADOWS @shadows_enabled - -#if SHADOWS - @foreach shadow_texture_unit_index @shadow_texture_unit_list - uniform int shadowTextureUnit@shadow_texture_unit_index; - varying vec4 shadowSpaceCoords@shadow_texture_unit_index; - @endforeach -#endif // SHADOWS +#include "shadows_vertex.glsl" void main(void) { @@ -29,14 +22,5 @@ void main(void) depthPassthrough = gl_Position.z; - #if SHADOWS - vec4 viewPos = gl_ModelViewMatrix * gl_Vertex; - // This matrix has the opposite handedness to the others used here, so multiplication must have the vector to the left. Alternatively it could be transposed after construction, but that's extra work for the GPU just to make the code look a tiny bit cleaner. - mat4 eyePlaneMat; - - @foreach shadow_texture_unit_index @shadow_texture_unit_list - eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneT[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneR[shadowTextureUnit@shadow_texture_unit_index], gl_EyePlaneQ[shadowTextureUnit@shadow_texture_unit_index]); - shadowSpaceCoords@shadow_texture_unit_index = viewPos * eyePlaneMat; - @endforeach - #endif // SHADOWS + setupShadowCoords(gl_ModelViewMatrix * gl_Vertex); }