1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 15:29:55 +00:00

Dynamically adjust shaders to have the required number of shadow maps.

This commit is contained in:
AnyOldName3 2017-11-07 20:22:45 +00:00
parent 56fa33af66
commit 715f29165b
8 changed files with 105 additions and 50 deletions

View file

@ -99,10 +99,39 @@ namespace Shader
return true;
}
osg::ref_ptr<osg::Shader> ShaderManager::getShader(const std::string &shaderTemplate, const ShaderManager::DefineMap &defines, osg::Shader::Type shaderType)
osg::ref_ptr<osg::Shader> ShaderManager::getShader(const std::string &shaderTemplate, const ShaderManager::DefineMap &defines, osg::Shader::Type shaderType, bool disableShadows)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
// set up shadows in the shader
// get these values from settings manager
bool shadows = true & !disableShadows;
int numShadowMaps = 2;
DefineMap definesWithShadows;
if (shadows)
{
definesWithShadows.insert(std::make_pair(std::string("shadows_enabled"), std::string("1")));
/*definesWithShadows.insert(std::string("shadow_texture_unit_declarations"), std::string(""));
definesWithShadows.insert(std::string("shadow_space_coordinate_declarations"), std::string(""));
definesWithShadows.insert(std::string("shadow_space_coordinate_calculations"), std::string(""));
definesWithShadows.insert(std::string("shadow_texture_sampler_declarations"), std::string(""));
definesWithShadows.insert(std::string("shadow_texture_lookup_calculations"), std::string(""));*/
for (int i = 0; i < numShadowMaps; ++i)
{
definesWithShadows["shadow_texture_unit_declarations"] += "uniform int shadowTextureUnit" + std::to_string(i) + ";\n";
definesWithShadows["shadow_space_coordinate_declarations"] += "varying vec4 shadowSpaceCoords" + std::to_string(i) + ";\n";
definesWithShadows["shadow_space_coordinate_calculations"] += "eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit" + std::to_string(i) + "], gl_EyePlaneT[shadowTextureUnit" + std::to_string(i) + "], gl_EyePlaneR[shadowTextureUnit" + std::to_string(i) + "], gl_EyePlaneQ[shadowTextureUnit" + std::to_string(i) + "]);\n"
+ "shadowSpaceCoords" + std::to_string(i) + " = viewPos * eyePlaneMat;\n";
definesWithShadows["shadow_texture_sampler_declarations"] += "uniform sampler2DShadow shadowTexture" + std::to_string(i) + ";\n";
definesWithShadows["shadow_texture_lookup_calculations"] += "shadowing *= shadow2DProj(shadowTexture" + std::to_string(i) + ", shadowSpaceCoords" + std::to_string(i) + ").r;\n";
}
}
definesWithShadows.insert(defines.begin(), defines.end());
// read the template if we haven't already
TemplateMap::iterator templateIt = mShaderTemplates.find(shaderTemplate);
if (templateIt == mShaderTemplates.end())
@ -126,11 +155,11 @@ namespace Shader
templateIt = mShaderTemplates.insert(std::make_pair(shaderTemplate, source)).first;
}
ShaderMap::iterator shaderIt = mShaders.find(std::make_pair(shaderTemplate, defines));
ShaderMap::iterator shaderIt = mShaders.find(std::make_pair(shaderTemplate, definesWithShadows));
if (shaderIt == mShaders.end())
{
std::string shaderSource = templateIt->second;
if (!parseDefines(shaderSource, defines))
if (!parseDefines(shaderSource, definesWithShadows))
return NULL;
osg::ref_ptr<osg::Shader> shader (new osg::Shader(shaderType));
@ -139,7 +168,7 @@ namespace Shader
static unsigned int counter = 0;
shader->setName(std::to_string(counter++));
shaderIt = mShaders.insert(std::make_pair(std::make_pair(shaderTemplate, defines), shader)).first;
shaderIt = mShaders.insert(std::make_pair(std::make_pair(shaderTemplate, definesWithShadows), shader)).first;
}
return shaderIt->second;
}

View file

@ -26,9 +26,10 @@ namespace Shader
/// @param shaderTemplate The filename of the shader template.
/// @param defines Define values that can be retrieved by the shader template.
/// @param shaderType The type of shader (usually vertex or fragment shader).
/// @param disableShadows Whether to disable shadows in the shader regardless of the overall setting. False by default.
/// @note May return NULL on failure.
/// @note Thread safe.
osg::ref_ptr<osg::Shader> getShader(const std::string& shaderTemplate, const DefineMap& defines, osg::Shader::Type shaderType);
osg::ref_ptr<osg::Shader> getShader(const std::string& shaderTemplate, const DefineMap& defines, osg::Shader::Type shaderType, bool disableShadows = false);
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader, osg::ref_ptr<osg::Shader> fragmentShader);

View file

@ -1,5 +1,7 @@
#version 120
#define SHADOWS @shadows_enabled
#if @diffuseMap
uniform sampler2D diffuseMap;
varying vec2 diffuseMapUV;
@ -55,10 +57,10 @@ varying vec4 passColor;
varying vec3 passViewPos;
varying vec3 passNormal;
uniform sampler2DShadow shadowTexture0;
uniform sampler2DShadow shadowTexture1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#if SHADOWS
@shadow_texture_sampler_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
#include "lighting.glsl"
#include "parallax.glsl"
@ -118,8 +120,10 @@ void main()
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, decalTex.xyz, decalTex.a);
#endif
float shadowing = shadow2DProj(shadowTexture0, shadowSpaceCoords0).r;
shadowing *= shadow2DProj(shadowTexture1, shadowSpaceCoords1).r;
float shadowing = 1.0;
#if SHADOWS
@shadow_texture_lookup_calculations
#endif // SHADOWS
#if !PER_PIXEL_LIGHTING
gl_FragData[0] *= lighting + vec4(shadowDiffuseLighting * shadowing, 0);

View file

@ -1,5 +1,7 @@
#version 120
#define SHADOWS @shadows_enabled
#if @diffuseMap
varying vec2 diffuseMapUV;
#endif
@ -46,10 +48,10 @@ varying vec4 passColor;
varying vec3 passViewPos;
varying vec3 passNormal;
uniform int shadowTextureUnit0;
uniform int shadowTextureUnit1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#if SHADOWS
@shadow_texture_unit_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
#include "lighting.glsl"
@ -106,9 +108,9 @@ 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 = mat4(gl_EyePlaneS[shadowTextureUnit0], gl_EyePlaneT[shadowTextureUnit0], gl_EyePlaneR[shadowTextureUnit0], gl_EyePlaneQ[shadowTextureUnit0]);
shadowSpaceCoords0 = viewPos * eyePlaneMat;
eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit1], gl_EyePlaneT[shadowTextureUnit1], gl_EyePlaneR[shadowTextureUnit1], gl_EyePlaneQ[shadowTextureUnit1]);
shadowSpaceCoords1 = viewPos * eyePlaneMat;
mat4 eyePlaneMat;
@shadow_space_coordinate_calculations
#endif // SHADOWS
}

View file

@ -1,5 +1,7 @@
#version 120
#define SHADOWS @shadows_enabled
varying vec2 uv;
uniform sampler2D diffuseMap;
@ -25,10 +27,10 @@ varying vec4 passColor;
varying vec3 passViewPos;
varying vec3 passNormal;
uniform sampler2DShadow shadowTexture0;
uniform sampler2DShadow shadowTexture1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#if SHADOWS
@shadow_texture_sampler_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
#include "lighting.glsl"
#include "parallax.glsl"
@ -70,8 +72,10 @@ void main()
gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a;
#endif
float shadowing = shadow2DProj(shadowTexture0, shadowSpaceCoords0).r;
shadowing *= shadow2DProj(shadowTexture1, shadowSpaceCoords1).r;
float shadowing = 1.0;
#if SHADOWS
@shadow_texture_lookup_calculations
#endif // SHADOWS
#if !PER_PIXEL_LIGHTING
gl_FragData[0] *= lighting + vec4(shadowDiffuseLighting * shadowing, 0);

View file

@ -1,5 +1,7 @@
#version 120
#define SHADOWS @shadows_enabled
varying vec2 uv;
varying float depth;
@ -14,10 +16,10 @@ varying vec4 passColor;
varying vec3 passViewPos;
varying vec3 passNormal;
uniform int shadowTextureUnit0;
uniform int shadowTextureUnit1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#if SHADOWS
@shadow_texture_unit_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
#include "lighting.glsl"
@ -40,9 +42,9 @@ void main(void)
uv = gl_MultiTexCoord0.xy;
// 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 = mat4(gl_EyePlaneS[shadowTextureUnit0], gl_EyePlaneT[shadowTextureUnit0], gl_EyePlaneR[shadowTextureUnit0], gl_EyePlaneQ[shadowTextureUnit0]);
shadowSpaceCoords0 = viewPos * eyePlaneMat;
eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit1], gl_EyePlaneT[shadowTextureUnit1], gl_EyePlaneR[shadowTextureUnit1], gl_EyePlaneQ[shadowTextureUnit1]);
shadowSpaceCoords1 = viewPos * eyePlaneMat;
#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;
@shadow_space_coordinate_calculations
#endif // SHADOWS
}

View file

@ -1,6 +1,7 @@
#version 120
#define REFRACTION @refraction_enabled
#define SHADOWS @shadows_enabled
// Inspired by Blender GLSL Water by martinsh ( http://devlog-martinsh.blogspot.de/2012/07/waterundewater-shader-wip.html )
@ -142,10 +143,11 @@ uniform vec3 nodePosition;
uniform float rainIntensity;
uniform sampler2DShadow shadowTexture0;
uniform sampler2DShadow shadowTexture1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#if SHADOWS
@shadow_texture_sampler_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
float frustumDepth;
@ -163,8 +165,15 @@ void main(void)
vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0;
float shadow = shadow2DProj(shadowTexture0, shadowSpaceCoords0).r;
shadow *= shadow2DProj(shadowTexture1, shadowSpaceCoords1).r;
#if SHADOWS
float shadowing = 1.0;
@shadow_texture_lookup_calculations
float shadow = shadowing;
#else // NOT SHADOWS
float shadow = 1.0;
#endif // SHADOWS
vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
screenCoords.y = (1.0-screenCoords.y);

View file

@ -4,10 +4,13 @@ varying vec3 screenCoordsPassthrough;
varying vec4 position;
varying float depthPassthrough;
uniform int shadowTextureUnit0;
uniform int shadowTextureUnit1;
varying vec4 shadowSpaceCoords0;
varying vec4 shadowSpaceCoords1;
#define SHADOWS @shadows_enabled
#if SHADOWS
@shadow_texture_unit_declarations
@shadow_space_coordinate_declarations
#endif // SHADOWS
void main(void)
{
@ -25,10 +28,11 @@ void main(void)
depthPassthrough = gl_Position.z;
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 = mat4(gl_EyePlaneS[shadowTextureUnit0], gl_EyePlaneT[shadowTextureUnit0], gl_EyePlaneR[shadowTextureUnit0], gl_EyePlaneQ[shadowTextureUnit0]);
shadowSpaceCoords0 = viewPos * eyePlaneMat;
eyePlaneMat = mat4(gl_EyePlaneS[shadowTextureUnit1], gl_EyePlaneT[shadowTextureUnit1], gl_EyePlaneR[shadowTextureUnit1], gl_EyePlaneQ[shadowTextureUnit1]);
shadowSpaceCoords1 = viewPos * eyePlaneMat;
#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;
@shadow_space_coordinate_calculations
#endif // SHADOWS
}