parent
9c4fcac876
commit
77e552f551
@ -0,0 +1,203 @@ |
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib" |
||||||
|
#import "Common/ShaderLib/BlinnPhongLighting.glsllib" |
||||||
|
#import "Common/ShaderLib/Lighting.glsllib" |
||||||
|
#import "Common/ShaderLib/InPassShadows.glsl" |
||||||
|
|
||||||
|
#ifndef NUM_DIR_LIGHTS |
||||||
|
#define NUM_DIR_LIGHTS 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef NUM_POINT_LIGHTS |
||||||
|
#define NUM_POINT_LIGHTS 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef NUM_SPOT_LIGHTS |
||||||
|
#define NUM_SPOT_LIGHTS 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#define DIR_SHADOW_LIGHT_START (0) |
||||||
|
#define DIR_SHADOW_LIGHT_END (NUM_SHADOW_DIR_LIGHTS * 2) |
||||||
|
|
||||||
|
#define DIR_LIGHT_START (DIR_SHADOW_LIGHT_END) |
||||||
|
#define DIR_LIGHT_END (NUM_DIR_LIGHTS * 2) |
||||||
|
|
||||||
|
#define POINT_LIGHT_START (DIR_LIGHT_END) |
||||||
|
#define POINT_LIGHT_END (POINT_LIGHT_START + NUM_POINT_LIGHTS * 2) |
||||||
|
|
||||||
|
#define SPOT_SHADOW_LIGHT_START (POINT_LIGHT_END) |
||||||
|
#define SPOT_SHADOW_LIGHT_END (SPOT_SHADOW_LIGHT_START + NUM_SHADOW_SPOT_LIGHTS * 3) |
||||||
|
|
||||||
|
#define SPOT_LIGHT_START (SPOT_SHADOW_LIGHT_END) |
||||||
|
#define SPOT_LIGHT_END (SPOT_LIGHT_START + NUM_SPOT_LIGHTS * 3) |
||||||
|
|
||||||
|
#define LIGHT_DATA_SIZE (SPOT_LIGHT_END) |
||||||
|
|
||||||
|
uniform sampler2D m_AmbientMap; |
||||||
|
uniform float m_AlphaDiscardThreshold; |
||||||
|
uniform float m_Shininess; |
||||||
|
uniform vec4 g_AmbientLightColor; |
||||||
|
|
||||||
|
#if LIGHT_DATA_SIZE > 0 |
||||||
|
uniform vec4 g_LightData[LIGHT_DATA_SIZE]; |
||||||
|
#else |
||||||
|
const vec4 g_LightData[1] = vec4[]( vec4(1.0) ); |
||||||
|
#endif |
||||||
|
|
||||||
|
varying vec3 vPos; |
||||||
|
varying vec3 vNormal; |
||||||
|
varying vec2 vTexCoord; |
||||||
|
|
||||||
|
struct surface_t { |
||||||
|
vec3 position; |
||||||
|
vec3 normal; |
||||||
|
vec3 viewDir; |
||||||
|
vec3 ambient; |
||||||
|
vec4 diffuse; |
||||||
|
vec4 specular; |
||||||
|
float shininess; |
||||||
|
}; |
||||||
|
|
||||||
|
vec2 Lighting_ProcessLighting(vec3 norm, vec3 viewDir, vec3 lightDir, float attenuation, float shininess) { |
||||||
|
float diffuseFactor = max(0.0, dot(norm, lightDir)); |
||||||
|
vec3 H = normalize(viewDir + lightDir); |
||||||
|
float HdotN = max(0.0, dot(H, norm)); |
||||||
|
float specularFactor = pow(HdotN, shininess); |
||||||
|
return vec2(diffuseFactor, diffuseFactor * specularFactor) * vec2(attenuation); |
||||||
|
} |
||||||
|
|
||||||
|
vec2 Lighting_ProcessDirectional(int lightIndex, surface_t surface) { |
||||||
|
vec3 lightDirection = g_LightData[lightIndex + 1].xyz; |
||||||
|
vec2 light = Lighting_ProcessLighting(surface.normal, surface.viewDir, -lightDirection, 1.0, surface.shininess); |
||||||
|
return light; |
||||||
|
} |
||||||
|
|
||||||
|
float Lighting_ProcessAttenuation(float invRadius, float dist) { |
||||||
|
#ifdef SRGB |
||||||
|
float atten = (1.0 - invRadius * dist) / (1.0 + invRadius * dist * dist); |
||||||
|
return clamp(atten, 0.0, 1.0); |
||||||
|
#else |
||||||
|
return max(0.0, 1.0 - invRadius * dist); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
vec2 Lighting_ProcessPoint(int lightIndex, surface_t surface) { |
||||||
|
vec4 lightPosition = g_LightData[lightIndex + 1]; |
||||||
|
vec3 lightDirection = lightPosition.xyz - surface.position; |
||||||
|
float dist = length(lightDirection); |
||||||
|
lightDirection /= vec3(dist); |
||||||
|
float atten = Lighting_ProcessAttenuation(lightPosition.w, dist); |
||||||
|
return Lighting_ProcessLighting(surface.normal, surface.viewDir, lightDirection, atten, surface.shininess); |
||||||
|
} |
||||||
|
|
||||||
|
vec2 Lighting_ProcessSpot(int lightIndex, surface_t surface) { |
||||||
|
vec4 lightPosition = g_LightData[lightIndex + 1]; |
||||||
|
vec4 lightDirection = g_LightData[lightIndex + 2]; |
||||||
|
vec3 lightVector = lightPosition.xyz - surface.position; |
||||||
|
float dist = length(lightVector); |
||||||
|
lightVector /= vec3(dist); |
||||||
|
float atten = Lighting_ProcessAttenuation(lightPosition.w, dist); |
||||||
|
atten *= computeSpotFalloff(lightDirection, lightVector); |
||||||
|
return Lighting_ProcessLighting(surface.normal, surface.viewDir, lightVector, atten, surface.shininess); |
||||||
|
} |
||||||
|
|
||||||
|
void Lighting_ProcessAll(surface_t surface, out vec3 ambient, out vec3 diffuse, out vec3 specular) { |
||||||
|
|
||||||
|
ambient = g_AmbientLightColor.rgb; |
||||||
|
diffuse = vec3(0.0); |
||||||
|
specular = vec3(0.0); |
||||||
|
|
||||||
|
Shadow_ProcessPssmSlice(); |
||||||
|
|
||||||
|
#if LIGHT_DATA_SIZE > 0 |
||||||
|
int projIndex = 0; |
||||||
|
|
||||||
|
for (int i = DIR_SHADOW_LIGHT_START; i < DIR_SHADOW_LIGHT_END; i += 2) { |
||||||
|
vec4 lightColor = g_LightData[i]; |
||||||
|
vec2 lightDiffSpec = Lighting_ProcessDirectional(i, surface); |
||||||
|
float shadow = Shadow_ProcessDirectional(projIndex, lightColor.w); |
||||||
|
lightDiffSpec *= vec2(shadow); |
||||||
|
diffuse += lightColor.rgb * lightDiffSpec.x; |
||||||
|
specular += lightColor.rgb * lightDiffSpec.y; |
||||||
|
projIndex += NUM_PSSM_SPLITS; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = DIR_LIGHT_START; i < DIR_LIGHT_END; i += 2) { |
||||||
|
vec3 lightColor = g_LightData[i].rgb; |
||||||
|
vec2 lightDiffSpec = Lighting_ProcessDirectional(i, surface); |
||||||
|
diffuse += lightColor.rgb * lightDiffSpec.x; |
||||||
|
specular += lightColor.rgb * lightDiffSpec.y; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = POINT_LIGHT_START; i < POINT_LIGHT_END; i += 2) { |
||||||
|
vec3 lightColor = g_LightData[i].rgb; |
||||||
|
vec2 lightDiffSpec = Lighting_ProcessPoint(i, surface); |
||||||
|
diffuse += lightColor.rgb * lightDiffSpec.x; |
||||||
|
specular += lightColor.rgb * lightDiffSpec.y; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = SPOT_SHADOW_LIGHT_START; i < SPOT_SHADOW_LIGHT_END; i += 3) { |
||||||
|
vec4 lightColor = g_LightData[i]; |
||||||
|
vec2 lightDiffSpec = Lighting_ProcessSpot(i, surface); |
||||||
|
float shadow = Shadow_ProcessSpot(projIndex, lightColor.w); |
||||||
|
lightDiffSpec *= vec2(shadow); |
||||||
|
diffuse += lightColor.rgb * lightDiffSpec.x; |
||||||
|
specular += lightColor.rgb * lightDiffSpec.y; |
||||||
|
projIndex++; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = SPOT_LIGHT_START; i < SPOT_LIGHT_END; i += 3) { |
||||||
|
vec3 lightColor = g_LightData[i].rgb; |
||||||
|
vec2 lightDiffSpec = Lighting_ProcessSpot(i, surface); |
||||||
|
diffuse += lightColor * lightDiffSpec.x; |
||||||
|
specular += lightColor * lightDiffSpec.y; |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
surface_t getSurface() { |
||||||
|
surface_t s; |
||||||
|
s.position = vPos; |
||||||
|
s.normal = normalize(vNormal); |
||||||
|
if (!gl_FrontFacing) { |
||||||
|
s.normal = -s.normal; |
||||||
|
} |
||||||
|
s.viewDir = normalize(-vPos); |
||||||
|
#ifdef AMBIENTMAP |
||||||
|
s.ambient = texture2D(m_AmbientMap, vTexCoord).rgb; |
||||||
|
#else |
||||||
|
s.ambient = vec3(1.0); |
||||||
|
#endif |
||||||
|
s.diffuse = vec4(1.0); |
||||||
|
s.specular = vec4(1.0); |
||||||
|
s.shininess = m_Shininess; |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
void main() { |
||||||
|
vec3 ambient, diffuse, specular; |
||||||
|
|
||||||
|
surface_t surface = getSurface(); |
||||||
|
Lighting_ProcessAll(surface, ambient, diffuse, specular); |
||||||
|
|
||||||
|
vec4 color = vec4(1.0); |
||||||
|
color.rgb = surface.ambient.rgb * ambient + |
||||||
|
surface.diffuse.rgb * diffuse + |
||||||
|
surface.specular.rgb * specular; |
||||||
|
|
||||||
|
#ifdef DISCARD_ALPHA |
||||||
|
if (color.a < m_AlphaDiscardThreshold) { |
||||||
|
discard; |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
gl_FragColor = color; |
||||||
|
|
||||||
|
/* |
||||||
|
vec4 projCoord = vProjCoord[0]; |
||||||
|
projCoord.xyz /= projCoord.w; |
||||||
|
float shad = shadow2D(g_ShadowMapArray, vec4(projCoord.xy, 0.0, projCoord.z)).r; |
||||||
|
vec3 amb = texture2D(m_AmbientMap, vTexCoord).rgb; |
||||||
|
gl_FragColor = vec4(amb * vec3(shad), 1.0); |
||||||
|
*/ |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
#import "Common/ShaderLib/GLSLCompat.glsllib" |
||||||
|
#import "Common/ShaderLib/Skinning.glsllib" |
||||||
|
#import "Common/ShaderLib/Instancing.glsllib" |
||||||
|
#import "Common/ShaderLib/InPassShadows.glsl" |
||||||
|
|
||||||
|
attribute vec3 inPosition; |
||||||
|
attribute vec3 inNormal; |
||||||
|
attribute vec2 inTexCoord; |
||||||
|
attribute vec4 inColor; |
||||||
|
|
||||||
|
varying vec3 vPos; |
||||||
|
varying vec3 vNormal; |
||||||
|
varying vec2 vTexCoord; |
||||||
|
|
||||||
|
void main() { |
||||||
|
vTexCoord = inTexCoord; |
||||||
|
|
||||||
|
vec4 modelSpacePos = vec4(inPosition, 1.0); |
||||||
|
vec3 modelSpaceNorm = inNormal; |
||||||
|
|
||||||
|
#ifdef NUM_BONES |
||||||
|
Skinning_Compute(modelSpacePos, modelSpaceNorm); |
||||||
|
#endif |
||||||
|
|
||||||
|
vPos = TransformWorldView(modelSpacePos).xyz; |
||||||
|
vNormal = TransformNormal(modelSpaceNorm); |
||||||
|
|
||||||
|
vec3 shadowPos = TransformWorld(modelSpacePos).xyz; |
||||||
|
Shadow_ProcessProjCoord(shadowPos); |
||||||
|
|
||||||
|
gl_Position = TransformWorldViewProjection(modelSpacePos); |
||||||
|
} |
@ -0,0 +1,133 @@ |
|||||||
|
#ifndef NUM_SHADOW_DIR_LIGHTS |
||||||
|
#define NUM_SHADOW_DIR_LIGHTS 0 |
||||||
|
#endif |
||||||
|
#ifndef NUM_SHADOW_POINT_LIGHTS |
||||||
|
#define NUM_SHADOW_POINT_LIGHTS 0 |
||||||
|
#endif |
||||||
|
#ifndef NUM_SHADOW_SPOT_LIGHTS |
||||||
|
#define NUM_SHADOW_SPOT_LIGHTS 0 |
||||||
|
#endif |
||||||
|
#ifndef NUM_PSSM_SPLITS |
||||||
|
#define NUM_PSSM_SPLITS 0 |
||||||
|
#endif |
||||||
|
|
||||||
|
#define SHADOW_DATA_SIZE (NUM_SHADOW_DIR_LIGHTS * NUM_PSSM_SPLITS + NUM_SHADOW_POINT_LIGHTS * 6 + NUM_SHADOW_SPOT_LIGHTS) |
||||||
|
|
||||||
|
#if SHADOW_DATA_SIZE > 0 |
||||||
|
|
||||||
|
varying vec4 vProjCoord[SHADOW_DATA_SIZE]; |
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER |
||||||
|
uniform mat4 g_ShadowMatrices[SHADOW_DATA_SIZE]; |
||||||
|
|
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
for (int i = 0; i < SHADOW_DATA_SIZE; i++) { |
||||||
|
vProjCoord[i] = g_ShadowMatrices[i] * vec4(worldPos, 1.0); |
||||||
|
} |
||||||
|
} |
||||||
|
#else |
||||||
|
uniform sampler2DArrayShadow g_ShadowMapArray; |
||||||
|
uniform vec4 g_PssmSplits; |
||||||
|
|
||||||
|
int pssmSliceOffset; |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
#ifdef NUM_PSSM_SPLITS |
||||||
|
float z = gl_FragCoord.z; |
||||||
|
if (z < g_PssmSplits[0]) { |
||||||
|
pssmSliceOffset = 0; |
||||||
|
} else if (z < g_PssmSplits[1]) { |
||||||
|
pssmSliceOffset = 1; |
||||||
|
} else if (z < g_PssmSplits[2]) { |
||||||
|
pssmSliceOffset = 2; |
||||||
|
} else { |
||||||
|
pssmSliceOffset = 3; |
||||||
|
} |
||||||
|
#else |
||||||
|
pssmSliceOffset = 0; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessDirectional(int startProjIndex, float startArrayLayer) { |
||||||
|
float arraySlice = startArrayLayer + float(pssmSliceOffset); |
||||||
|
vec3 projCoord = vProjCoord[startProjIndex + pssmSliceOffset].xyz; |
||||||
|
return texture(g_ShadowMapArray, vec4(projCoord.xy, arraySlice, projCoord.z)); |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessSpot(int startProjIndex, float startArrayLayer) { |
||||||
|
vec4 projCoord = vProjCoord[startProjIndex]; |
||||||
|
projCoord.xyz /= projCoord.w; |
||||||
|
return texture(g_ShadowMapArray, vec4(projCoord.xy, startArrayLayer, projCoord.z)); |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
||||||
|
#elif NUM_PSSM_SPLITS > 0 |
||||||
|
|
||||||
|
// A lightweight version of in-pass lighting that only handles directional lights |
||||||
|
// Control flow and loop iteration count are static |
||||||
|
|
||||||
|
varying vec4 vProjCoord[NUM_PSSM_SPLITS]; |
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER |
||||||
|
uniform mat4 g_DirectionalShadowMatrix[NUM_PSSM_SPLITS]; |
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
for (int i = 0; i < NUM_PSSM_SPLITS; i++) { |
||||||
|
vProjCoord[i] = g_DirectionalShadowMatrix[i] * vec4(worldPos, 1.0); |
||||||
|
} |
||||||
|
} |
||||||
|
#else |
||||||
|
uniform sampler2DShadow g_DirectionalShadowMap[NUM_PSSM_SPLITS]; |
||||||
|
uniform vec4 g_PssmSplits; |
||||||
|
|
||||||
|
const vec2 invTexSize = vec2(1.0 / 1024.0); |
||||||
|
|
||||||
|
float Shadow_SampleOffset(sampler2DShadow shadowMap, vec4 projCoord, vec2 offset) { |
||||||
|
return shadow2D(shadowMap, vec3(projCoord.xy + offset * invTexSize, projCoord.z)).r; |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_Sample(sampler2DShadow shadowMap, vec4 projCoord) { |
||||||
|
return shadow2D(shadowMap, projCoord.xyz).r; |
||||||
|
} |
||||||
|
|
||||||
|
#define GET_SHADOW(i) if (z < g_PssmSplits[i]) return Shadow_Sample(g_DirectionalShadowMap[i], vProjCoord[i]); |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessDirectional() { |
||||||
|
float z = gl_FragCoord.z; |
||||||
|
|
||||||
|
GET_SHADOW(0); |
||||||
|
#if NUM_PSSM_SPLITS > 1 |
||||||
|
GET_SHADOW(1) |
||||||
|
#if NUM_PSSM_SPLITS > 2 |
||||||
|
GET_SHADOW(2) |
||||||
|
#if NUM_PSSM_SPLITS > 3 |
||||||
|
GET_SHADOW(3) |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
return 1.0; |
||||||
|
} |
||||||
|
#endif |
||||||
|
#else |
||||||
|
#define NUM_SHADOW_DIR_LIGHTS 0 |
||||||
|
#define NUM_SHADOW_POINT_LIGHTS 0 |
||||||
|
#define NUM_SHADOW_SPOT_LIGHTS 0 |
||||||
|
#define NUM_PSSM_SPLITS 0 |
||||||
|
|
||||||
|
void Shadow_ProcessProjCoord(vec3 worldPos) { |
||||||
|
} |
||||||
|
|
||||||
|
void Shadow_ProcessPssmSlice() { |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessDirectional(int startLightIndex, float startArrayLayer) { |
||||||
|
return 1.0; |
||||||
|
} |
||||||
|
|
||||||
|
float Shadow_ProcessSpot(int startLightIndex, float startArrayLayer) { |
||||||
|
return 1.0; |
||||||
|
} |
||||||
|
#endif |
Loading…
Reference in new issue