use PBR + support point light shadows in shader
This commit is contained in:
parent
ec0fcd24d2
commit
c136a4212e
@ -2,6 +2,7 @@
|
||||
#import "Common/ShaderLib/BlinnPhongLighting.glsllib"
|
||||
#import "Common/ShaderLib/Lighting.glsllib"
|
||||
#import "Common/ShaderLib/InPassShadows.glsl"
|
||||
#import "Common/ShaderLib/PBR.glsllib"
|
||||
|
||||
#ifndef NUM_DIR_LIGHTS
|
||||
#define NUM_DIR_LIGHTS 0
|
||||
@ -59,50 +60,76 @@ struct surface_t {
|
||||
vec3 ambient;
|
||||
vec4 diffuse;
|
||||
vec4 specular;
|
||||
float shininess;
|
||||
float roughness;
|
||||
float ndotv;
|
||||
};
|
||||
|
||||
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);
|
||||
float invRadTimesDist = invRadius * dist;
|
||||
float atten = (1.0 - invRadTimesDist) / (1.0 + invRadTimesDist * 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) {
|
||||
void Lighting_ProcessDirectional(int lightIndex, surface_t surface, out vec3 outDiffuse, out vec3 outSpecular) {
|
||||
vec4 lightColor = g_LightData[lightIndex];
|
||||
vec3 lightDirection = g_LightData[lightIndex + 1].xyz;
|
||||
|
||||
PBR_ComputeDirectLightSpecWF(surface.normal, -lightDirection, surface.viewDir,
|
||||
lightColor.rgb, surface.specular.rgb, surface.roughness, surface.ndotv,
|
||||
outDiffuse, outSpecular);
|
||||
}
|
||||
|
||||
vec3 Lighting_ProcessPoint(in int lightIndex, in surface_t surface, out vec3 outDiffuse, out vec3 outSpecular) {
|
||||
vec4 lightColor = g_LightData[lightIndex];
|
||||
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);
|
||||
if (atten == 0.0) {
|
||||
outDiffuse = vec3(0.0);
|
||||
outSpecular = vec3(0.0);
|
||||
return lightDirection;
|
||||
}
|
||||
PBR_ComputeDirectLightSpecWF(surface.normal, lightDirection, surface.viewDir,
|
||||
lightColor.rgb, surface.specular.rgb, surface.roughness, surface.ndotv,
|
||||
outDiffuse, outSpecular);
|
||||
|
||||
outDiffuse *= atten;
|
||||
outSpecular *= atten;
|
||||
|
||||
return lightDirection;
|
||||
}
|
||||
|
||||
vec2 Lighting_ProcessSpot(int lightIndex, surface_t surface) {
|
||||
void Lighting_ProcessSpot(in int lightIndex, in surface_t surface, out vec3 outDiffuse, out vec3 outSpecular) {
|
||||
vec4 lightColor = g_LightData[lightIndex];
|
||||
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);
|
||||
float atten = computeSpotFalloff(lightDirection, lightVector);
|
||||
if (atten == 0.0) {
|
||||
outDiffuse = vec3(0.0);
|
||||
outSpecular = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
atten *= Lighting_ProcessAttenuation(lightPosition.w, dist);
|
||||
if (atten == 0.0) {
|
||||
outDiffuse = vec3(0.0);
|
||||
outSpecular = vec3(0.0);
|
||||
return;
|
||||
}
|
||||
PBR_ComputeDirectLightSpecWF(surface.normal, lightVector, surface.viewDir,
|
||||
lightColor.rgb, surface.specular.rgb, surface.roughness, surface.ndotv,
|
||||
outDiffuse, outSpecular);
|
||||
|
||||
outDiffuse *= atten;
|
||||
outSpecular *= atten;
|
||||
}
|
||||
|
||||
void Lighting_ProcessAll(surface_t surface, out vec3 ambient, out vec3 diffuse, out vec3 specular) {
|
||||
@ -117,44 +144,59 @@ void Lighting_ProcessAll(surface_t surface, out vec3 ambient, out vec3 diffuse,
|
||||
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;
|
||||
vec3 outDiffuse, outSpecular;
|
||||
Lighting_ProcessDirectional(i, surface, outDiffuse, outSpecular);
|
||||
|
||||
float shadow = Shadow_Process(0, vec3(0.0), g_LightData[i].w, projIndex);
|
||||
outDiffuse *= shadow;
|
||||
outSpecular *= shadow;
|
||||
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
|
||||
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;
|
||||
vec3 outDiffuse, outSpecular;
|
||||
Lighting_ProcessDirectional(i, surface, outDiffuse, outSpecular);
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
|
||||
for (int i = POINT_SHADOW_LIGHT_START; i < POINT_SHADOW_LIGHT_END; i += 2) {
|
||||
vec3 outDiffuse, outSpecular;
|
||||
vec3 lightDir = Lighting_ProcessPoint(i, surface, outDiffuse, outSpecular);
|
||||
|
||||
float shadow = Shadow_Process(1, lightDir, g_LightData[i].w, projIndex);
|
||||
outDiffuse *= shadow;
|
||||
outSpecular *= shadow;
|
||||
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
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;
|
||||
vec3 outDiffuse, outSpecular;
|
||||
Lighting_ProcessPoint(i, surface, outDiffuse, outSpecular);
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
|
||||
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++;
|
||||
vec3 outDiffuse, outSpecular;
|
||||
Lighting_ProcessSpot(i, surface, outDiffuse, outSpecular);
|
||||
|
||||
float shadow = Shadow_Process(2, vec3(0.0), g_LightData[i].w, projIndex);
|
||||
outDiffuse *= shadow;
|
||||
outSpecular *= shadow;
|
||||
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
|
||||
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;
|
||||
vec3 outDiffuse, outSpecular;
|
||||
Lighting_ProcessSpot(i, surface, outDiffuse, outSpecular);
|
||||
diffuse += outDiffuse;
|
||||
specular += outSpecular;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -174,8 +216,9 @@ surface_t getSurface() {
|
||||
s.ambient = vec3(1.0);
|
||||
#endif
|
||||
s.diffuse = vec4(1.0);
|
||||
s.specular = vec4(1.0);
|
||||
s.shininess = m_Shininess;
|
||||
s.specular = vec4(0.04, 0.04, 0.04, 1.0);
|
||||
s.roughness = 0.1;
|
||||
s.ndotv = max(0.0, dot(s.viewDir, s.normal));
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -186,9 +229,9 @@ void main() {
|
||||
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;
|
||||
color.rgb = ambient * surface.ambient.rgb +
|
||||
diffuse * surface.diffuse.rgb +
|
||||
specular;
|
||||
|
||||
#ifdef DISCARD_ALPHA
|
||||
if (color.a < m_AlphaDiscardThreshold) {
|
||||
|
@ -39,17 +39,63 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
float Shadow_ProcessDirectional(int startProjIndex, float startArrayLayer) {
|
||||
/**
|
||||
* Returns a float from 0.0 - 5.0 containing the index
|
||||
* of the cubemap face to fetch for the given direction
|
||||
*/
|
||||
float Shadow_GetCubeMapFace(in vec3 direction) {
|
||||
vec3 mag = abs(direction);
|
||||
|
||||
// Compare each component against the other two
|
||||
// Largest component is set to 1.0, the rest are 0.0
|
||||
vec3 largestComp = step(mag.yzx, mag) * step(mag.zxy, mag);
|
||||
|
||||
// Negative components are set to 1.0, the positive are 0.0
|
||||
vec3 negComp = step(direction, vec3(0.0));
|
||||
|
||||
// Each component contains the face index to use
|
||||
vec3 faceIndices = vec3(0.0, 2.0, 4.0) + negComp;
|
||||
|
||||
// Pick the face index with the largest component
|
||||
return dot(largestComp, faceIndices);
|
||||
}
|
||||
|
||||
float Shadow_ProcessDirectional(in int lightType, in vec3 lightDir, in float startArrayLayer, inout int startProjIndex) {
|
||||
float arraySlice = startArrayLayer + float(pssmSliceOffset);
|
||||
vec3 projCoord = vProjCoord[startProjIndex + pssmSliceOffset].xyz;
|
||||
startProjIndex += NUM_PSSM_SPLITS;
|
||||
return texture(g_ShadowMapArray, vec4(projCoord.xy, arraySlice, projCoord.z));
|
||||
}
|
||||
|
||||
float Shadow_ProcessSpot(int startProjIndex, float startArrayLayer) {
|
||||
float Shadow_ProcessSpot(in int lightType, in vec3 lightDir, in float startArrayLayer, inout int startProjIndex) {
|
||||
vec4 projCoord = vProjCoord[startProjIndex];
|
||||
projCoord.xyz /= projCoord.w;
|
||||
startProjIndex ++;
|
||||
return texture(g_ShadowMapArray, vec4(projCoord.xy, startArrayLayer, projCoord.z));
|
||||
}
|
||||
|
||||
float Shadow_Process(in int lightType, in vec3 lightDir, in float startArrayLayer, inout int startProjIndex) {
|
||||
float arraySlice = startArrayLayer;
|
||||
vec4 projCoord;
|
||||
|
||||
if (lightType == 0) {
|
||||
arraySlice += float(pssmSliceOffset);
|
||||
projCoord = vProjCoord[startProjIndex + pssmSliceOffset];
|
||||
startProjIndex += NUM_PSSM_SPLITS;
|
||||
} else if (lightType == 1) {
|
||||
float face = Shadow_GetCubeMapFace(lightDir);
|
||||
arraySlice += face;
|
||||
projCoord = vProjCoord[startProjIndex + int(face)];
|
||||
projCoord.xyz /= projCoord.w;
|
||||
startProjIndex += 6;
|
||||
} else {
|
||||
projCoord = vProjCoord[startProjIndex];
|
||||
projCoord.xyz /= projCoord.w;
|
||||
startProjIndex += 1;
|
||||
}
|
||||
|
||||
return texture(g_ShadowMapArray, vec4(projCoord.xy, arraySlice, projCoord.z));
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif NUM_PSSM_SPLITS > 0
|
||||
@ -121,4 +167,8 @@
|
||||
float Shadow_ProcessSpot(int startLightIndex, float startArrayLayer) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
float Shadow_Process(in int lightType, in vec3 lightDir, in float startArrayLayer, inout int startProjIndex) {
|
||||
return 1.0;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user