mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 13:23:36 +02:00
Keep on investigating the shading cost per light
This commit is contained in:
parent
2a0e67ee2a
commit
e143c05ef8
9 changed files with 173 additions and 84 deletions
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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@>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue