Keep on investigating the shading cost per light

This commit is contained in:
sam 2016-09-30 02:41:21 -07:00
parent 2a0e67ee2a
commit e143c05ef8
9 changed files with 173 additions and 84 deletions

View file

@ -40,39 +40,24 @@ bool lightVolume_clipFragToLightVolumePoint(LightVolume lv, vec3 fragPos, out ve
return (fragLightVecLen2.w <= lightVolume_getRadiusSquare(lv));
}
bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {
fragLightVecLen2.xyz = lightVolume_getPosition(lv) - fragPos.xyz;
fragLightVecLen2.w = dot(fragLightVecLen2.xyz, fragLightVecLen2.xyz);
// Kill if too far from the light center
if (fragLightVecLen2.w > lightVolume_getRadiusSquare(lv)) {
return false;
}
// Allright we re valid in the volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
// Kill if not in the spot light (ah ah !)
cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);
if (cosSpotAngle < lightVolume_getSpotAngleCos(lv)) {
return false;
}
return true;
}
bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {
// Allright we re valid in the volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
bool lightVolume_clipFragToLightVolumeSpotSide(LightVolume lv, vec4 fragLightDirLen, out float cosSpotAngle) {
// Kill if not in the spot light (ah ah !)
cosSpotAngle = max(-dot(fragLightDirLen.xyz, lightVolume_getDirection(lv)), 0.0);
return (cosSpotAngle >= lightVolume_getSpotAngleCos(lv));
}
bool lightVolume_clipFragToLightVolumeSpot(LightVolume lv, vec3 fragPos, out vec4 fragLightVecLen2, out vec4 fragLightDirLen, out float cosSpotAngle) {
if (!lightVolume_clipFragToLightVolumePoint(lv, fragPos, fragLightVecLen2)) {
return false;
}
// Allright we re valid in the volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
return lightVolume_clipFragToLightVolumeSpotSide(lv, fragLightDirLen, cosSpotAngle);
}
#endif

View file

@ -55,11 +55,12 @@ uniform clusterContentBuffer {
int _clusterGridContent[16384];
};
ivec2 clusterGrid_getCluster(int index) {
ivec3 clusterGrid_getCluster(int index) {
int clusterDesc = _clusterGridTable[index];
int numLights = 0xFFFF & (clusterDesc >> 16);
int numPointLights = 0xFF & (clusterDesc >> 16);
int numSpotLights = 0xFF & (clusterDesc >> 24);
int contentOffset = 0xFFFF & (clusterDesc);
return ivec2(numLights, contentOffset);
return ivec3(numPointLights, numSpotLights, contentOffset);
}
int clusterGrid_getClusterLightId(int index, ivec2 cluster) {

View file

@ -270,7 +270,8 @@ uint32_t scanLightVolumeSphere(FrustumGrid& grid, const FrustumGrid::Planes plan
void LightClusters::updateClusters() {
// Clean up last info
std::vector< std::vector< LightIndex > > clusterGrid(_numClusters);
std::vector< std::vector< LightIndex > > clusterGridPoint(_numClusters);
std::vector< std::vector< LightIndex > > clusterGridSpot(_numClusters);
_clusterGrid.resize(_numClusters, EMPTY_CLUSTER);
uint32_t maxNumIndices = (uint32_t) _clusterContent.size();
@ -289,6 +290,7 @@ void LightClusters::updateClusters() {
auto worldOri = light->getPosition();
auto radius = light->getMaximumRadius();
bool isSpot = light->isSpot();
// Bring into frustum eye space
auto eyeOri = theFrustumGrid.frustumGrid_worldToEye(glm::vec4(worldOri, 1.0f));
@ -395,6 +397,7 @@ void LightClusters::updateClusters() {
}
// now voxelize
auto& clusterGrid = (isSpot ? clusterGridSpot : clusterGridPoint);
numClusterTouched += scanLightVolumeSphere(theFrustumGrid, _gridPlanes, zMin, zMax, yMin, yMax, xMin, xMax, lightId, glm::vec4(glm::vec3(eyeOri), radius), clusterGrid);
}
@ -405,9 +408,13 @@ void LightClusters::updateClusters() {
checkBudget = true;
}
uint16_t indexOffset = 0;
for (int i = 0; i < clusterGrid.size(); i++) {
auto& cluster = clusterGrid[i];
uint16_t numLights = ((uint16_t)cluster.size());
for (int i = 0; i < clusterGridPoint.size(); i++) {
auto& clusterPoint = clusterGridPoint[i];
auto& clusterSpot = clusterGridSpot[i];
uint8_t numLightsPoint = ((uint8_t)clusterPoint.size());
uint8_t numLightsSpot = ((uint8_t)clusterSpot.size());
uint16_t numLights = numLightsPoint + numLightsSpot;
uint16_t offset = indexOffset;
// Check for overflow
@ -417,14 +424,18 @@ void LightClusters::updateClusters() {
}
}
_clusterGrid[i] = (uint32_t)((numLights << 16) | offset);
// _clusterGrid[i] = (uint32_t)((numLights << 16) | offset);
_clusterGrid[i] = (uint32_t)((numLightsSpot << 24) | (numLightsPoint << 16) | offset);
if (numLights) {
memcpy(_clusterContent.data() + indexOffset, cluster.data(), numLights * sizeof(LightIndex));
if (numLightsPoint) {
memcpy(_clusterContent.data() + indexOffset, clusterPoint.data(), numLightsPoint * sizeof(LightIndex));
indexOffset += numLightsPoint;
}
if (numLightsSpot) {
memcpy(_clusterContent.data() + indexOffset, clusterSpot.data(), numLightsSpot * sizeof(LightIndex));
indexOffset += numLightsSpot;
}
indexOffset += numLights;
}
// update the buffers

View file

@ -12,16 +12,16 @@
<@func declareLightingPoint(supportScattering)@>
void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light,
vec3 fragLightVec, vec3 fragEyeDir, vec3 normal, float roughness,
vec4 fragLightDirLen, vec3 fragEyeDir, vec3 normal, float roughness,
float metallic, vec3 fresnel, vec3 albedo, float shadow
<@if supportScattering@>
, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
<@endif@>
) {
// Allright we re valid in the volume
float fragLightDistance = length(fragLightVec);
vec3 fragLightDir = fragLightVec / fragLightDistance;
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);

View file

@ -82,12 +82,6 @@ float fetchSpecularBeckmann(float ndoth, float roughness) {
return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0);
}
float fresnelSchlickScalar(float fresnelColor, vec3 lightDir, vec3 halfDir) {
float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0);
float exponential = pow(base, 5.0);
return (exponential)+fresnelColor * (1.0 - exponential);
}
vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) {
vec2 result = vec2(0.0, 1.0);
float ndotl = dot(N, L);
@ -114,6 +108,11 @@ vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) {
return vec3(exponential) + fresnelColor * (1.0 - exponential);
}
float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) {
float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0);
float exponential = pow(base, 5.0);
return (exponential) + fresnelScalar * (1.0 - exponential);
}
float specularDistribution(float roughness, vec3 normal, vec3 halfDir) {
@ -144,6 +143,21 @@ vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float m
return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x));
}
// Frag Shading returns the diffuse amount as W and the specular rgb as xyz
vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness) {
// Diffuse Lighting
float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0);
// Specular Lighting
vec3 halfDir = normalize(fragEyeDir + fragLightDir);
float fresnelScalar = fresnelSchlickScalar(0.03, fragLightDir, halfDir);
float power = specularDistribution(roughness, fragNormal, halfDir);
float specular = power * fresnelScalar * diffuse;
return vec4(vec3(specular), diffuse * (1 - fresnelScalar));
}
<@endfunc@>
@ -196,5 +210,18 @@ void evalFragShading(out vec3 diffuse, out vec3 specular,
}
}
void evalFragShadingSimpler(out vec3 diffuse, out vec3 specular,
vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir,
float metallic, vec3 fresnel, float roughness, vec3 albedo
/*
,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature
*/
) {
vec4 shading = evalPBRShadingDielectric(fragNormal, fragLightDir, fragEyeDir, roughness);
// vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness);
diffuse = vec3(shading.w);
diffuse *= albedo;
specular = shading.xyz;
}
<@endif@>

View file

@ -53,8 +53,8 @@ void main(void) {
ivec2 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x;
ivec3 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x + cluster.y;
float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0);

View file

@ -37,8 +37,8 @@ void main(void) {
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x;
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0);

View file

@ -54,8 +54,8 @@ void main(void) {
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
ivec2 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x;
ivec3 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x + cluster.y;
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);

View file

@ -58,11 +58,13 @@ void main(void) {
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec2 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x;
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
if (numLights <= 0) {
discard;
}
int lightClusterOffset = cluster.z;
ivec2 clusterAddress = ivec2(numLights, lightClusterOffset);
ivec3 dims = frustumGrid.dims.xyz;
if (clusterPos.x < 0 || clusterPos.x >= dims.x) {
@ -76,7 +78,6 @@ void main(void) {
discard;
}
int lightClusterOffset = cluster.y;
@ -92,48 +93,112 @@ void main(void) {
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
int numLightTouching = 0;
for (int i = 0; i < numLights && numLightTouching < 16; i++) {
for (int i = 0; i < cluster.x; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, cluster);
int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress);
Light light = getLight(theLightIndex);
bool isSpot = light_isSpot(light);
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
vec4 fragLightDirLen;
float cosSpotAngle;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
continue;
}
if (isSpot && !lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightVecLen2, fragLightDirLen, cosSpotAngle)) {
continue;
}
if (dot(frag.normal, normalize(fragLightVecLen2.xyz)) < 0.0) {
//_fragColor.rgb += vec3(0.0, 0.0, 1.0 / 16.0);
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {
continue;
}
numLightTouching++;
/*
vec3 diffuse;
vec3 specular;
if (isSpot) {
evalLightingSpot(diffuse, specular, light,
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
} else {
evalLightingPoint(diffuse, specular, light,
fragLightVecLen2.xyz, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
}
vec3 diffuse = vec3(1.0);
vec3 specular = vec3(0.1);
// Allright we re valid in the volume
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);
// Eval shading
evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature
);
/*
evalLightingPoint(diffuse, specular, light,
fragLightDirLen.xyzw, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
*/
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
*/
_fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0);
}
for (int i = cluster.x; i < numLights; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, clusterAddress);
Light light = getLight(theLightIndex);
// Clip againgst the light volume and Make the Light vector going from fragment to light center in world space
vec4 fragLightVecLen2;
vec4 fragLightDirLen;
float cosSpotAngle;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragPos.xyz, fragLightVecLen2)) {
continue;
}
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(frag.normal, fragLightDirLen.xyz) < 0.0) {
continue;
}
// Check spot
if (!lightVolume_clipFragToLightVolumeSpotSide(light.volume, fragLightDirLen, cosSpotAngle)) {
continue;
}
numLightTouching++;
vec3 diffuse = vec3(1.0);
vec3 specular = vec3(0.1);
// Allright we re valid in the volume
float fragLightDistance = fragLightDirLen.w;
vec3 fragLightDir = fragLightDirLen.xyz;
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);
vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);
// Eval shading
evalFragShading(diffuse, specular, frag.normal, fragLightDir, fragEyeDir, frag.metallic, frag.fresnel, frag.roughness, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature
);
/* evalLightingSpot(diffuse, specular, light,
fragLightDirLen.xyzw, cosSpotAngle, fragEyeDir, frag.normal, frag.roughness,
frag.metallic, frag.fresnel, frag.albedo, 1.0,
frag.scattering, midNormalCurvature, lowNormalCurvature);
*/
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
// _fragColor.rgb += vec3(1.0/16.0, 0.0, 0.0);
}
}