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