Merge pull request #12180 from Zvork/locallights

Local lights on translucent objects
This commit is contained in:
John Conklin II 2018-01-25 09:36:58 -08:00 committed by GitHub
commit 1865432b47
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 465 additions and 218 deletions

View file

@ -56,10 +56,10 @@ Light getLight(int index) {
} }
<@else@> <@else@>
uniform lightBuffer { uniform keyLightBuffer {
Light light; Light light;
}; };
Light getLight() { Light getKeyLight() {
return light; return light;
} }

View file

@ -21,21 +21,25 @@
<@include LightDirectional.slh@> <@include LightDirectional.slh@>
<@func prepareGlobalLight(isScattering)@> <@func fetchGlobalLight()@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormal = vec3((normal));
vec3 fragEyeVector = vec3(invViewMat * vec4(-1.0*position, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
// Get light // Get light
Light light = getLight(); Light light = getKeyLight();
LightAmbient lightAmbient = getLightAmbient(); LightAmbient lightAmbient = getLightAmbient();
vec3 lightDirection = getLightDirection(light); vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light); vec3 lightIrradiance = getLightIrradiance(light);
vec3 color = vec3(0.0); vec3 color = vec3(0.0);
<@endfunc@>
<@func prepareGlobalLight(isScattering)@>
// prepareGlobalLight
// Transform directions to worldspace
vec3 fragNormal = vec3((normal));
vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
<$fetchGlobalLight()$>
<@endfunc@> <@endfunc@>
@ -147,7 +151,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
<@func declareEvalLightmappedColor()@> <@func declareEvalLightmappedColor()@>
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {
Light light = getLight(); Light light = getKeyLight();
LightAmbient ambient = getLightAmbient(); LightAmbient ambient = getLightAmbient();
// Catch normals perpendicular to the projection plane, hence the magic number for the threshold // Catch normals perpendicular to the projection plane, hence the magic number for the threshold
@ -175,11 +179,12 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur
<$declareLightingAmbient(1, 1, 1)$> <$declareLightingAmbient(1, 1, 1)$>
<$declareLightingDirectional()$> <$declareLightingDirectional()$>
vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) {
<$prepareGlobalLight()$> <$prepareGlobalLight()$>
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
color = prevLighting;
color += emissive * isEmissiveEnabled(); color += emissive * isEmissiveEnabled();
// Ambient // Ambient
@ -238,6 +243,44 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
return color; return color;
} }
vec3 evalGlobalLightingAlphaBlendedWithHaze(
mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position,
vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, SurfaceData surface, float opacity, vec3 prevLighting)
{
<$fetchGlobalLight()$>
color = prevLighting;
color += emissive * isEmissiveEnabled();
// Ambient
vec3 ambientDiffuse;
vec3 ambientSpecular;
evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance);
// Directional
vec3 directionalDiffuse;
vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += ambientDiffuse + directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity;
// Haze
if ((hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
vec4 colorV4 = computeHazeColor(
vec4(color, 1.0), // fragment original color
position, // fragment position in eye coordinates
surface.eyeDir, // fragment eye vector in world coordinates
invViewMat[3].y, // eye height in world coordinates
lightDirection // keylight direction vector
);
color = colorV4.rgb;
}
return color;
}
<@endfunc@> <@endfunc@>

View file

@ -45,6 +45,7 @@ using namespace render;
struct LightLocations { struct LightLocations {
int radius{ -1 }; int radius{ -1 };
int keyLightBufferUnit{ -1 };
int lightBufferUnit{ -1 }; int lightBufferUnit{ -1 };
int ambientBufferUnit { -1 }; int ambientBufferUnit { -1 };
int lightIndexBufferUnit { -1 }; int lightIndexBufferUnit { -1 };
@ -147,6 +148,29 @@ void DeferredLightingEffect::unsetKeyLightBatch(gpu::Batch& batch, int lightBuff
} }
} }
void DeferredLightingEffect::setupLocalLightsBatch(gpu::Batch& batch,
int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit,
const LightClustersPointer& lightClusters) {
// Bind the global list of lights and the visible lights this frame
batch.setUniformBuffer(_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer());
batch.setUniformBuffer(frustumGridBufferUnit, lightClusters->_frustumGridBuffer);
batch.setUniformBuffer(clusterGridBufferUnit, lightClusters->_clusterGridBuffer);
batch.setUniformBuffer(clusterContentBufferUnit, lightClusters->_clusterContentBuffer);
}
void DeferredLightingEffect::unsetLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit) {
if (clusterGridBufferUnit >= 0) {
batch.setUniformBuffer(clusterGridBufferUnit, nullptr);
}
if (clusterContentBufferUnit >= 0) {
batch.setUniformBuffer(clusterContentBufferUnit, nullptr);
}
if (frustumGridBufferUnit >= 0) {
batch.setUniformBuffer(frustumGridBufferUnit, nullptr);
}
}
static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* fragSource, LightLocationsPtr& locations) { static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* fragSource, LightLocationsPtr& locations) {
auto VS = gpu::Shader::createVertex(std::string(vertSource)); auto VS = gpu::Shader::createVertex(std::string(vertSource));
auto PS = gpu::Shader::createPixel(std::string(fragSource)); auto PS = gpu::Shader::createPixel(std::string(fragSource));
@ -189,6 +213,7 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f
locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform"); locations->texcoordFrameTransform = program->getUniforms().findLocation("texcoordFrameTransform");
locations->keyLightBufferUnit = program->getUniformBuffers().findLocation("keyLightBuffer");
locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer");
locations->ambientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->ambientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer");
locations->lightIndexBufferUnit = program->getUniformBuffers().findLocation("lightIndexBuffer"); locations->lightIndexBufferUnit = program->getUniformBuffers().findLocation("lightIndexBuffer");
@ -561,7 +586,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform));
// Setup the global lighting // Setup the global lighting
deferredLightingEffect->setupKeyLightBatch(args, batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); deferredLightingEffect->setupKeyLightBatch(args, batch, locations->keyLightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT);
// Haze // Haze
if (haze) { if (haze) {
@ -570,7 +595,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
deferredLightingEffect->unsetKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); deferredLightingEffect->unsetKeyLightBatch(batch, locations->keyLightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT);
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
batch.setResourceTexture(SHADOW_MAP_UNIT+i, nullptr); batch.setResourceTexture(SHADOW_MAP_UNIT+i, nullptr);
@ -625,12 +650,8 @@ void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext
auto& lightIndices = lightClusters->_visibleLightIndices; auto& lightIndices = lightClusters->_visibleLightIndices;
if (!lightIndices.empty() && lightIndices[0] > 0) { if (!lightIndices.empty() && lightIndices[0] > 0) {
// Bind the global list of lights and the visible lights this frame deferredLightingEffect->setupLocalLightsBatch(batch, LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT,
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer()); lightClusters);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer);
// Local light pipeline // Local light pipeline
batch.setPipeline(deferredLightingEffect->_localLight); batch.setPipeline(deferredLightingEffect->_localLight);

View file

@ -51,6 +51,9 @@ public:
void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit);
void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit);
void setupLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit, const LightClustersPointer& lightClusters);
void unsetLocalLightsBatch(gpu::Batch& batch, int clusterGridBufferUnit, int clusterContentBufferUnit, int frustumGridBufferUnit);
void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; };
void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; }
bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; }

View file

@ -147,7 +147,7 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), HazeEffect_TransformBufferSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), HazeEffect_ColorMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("linearDepthMap"), HazeEffect_LinearDepthMapSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), HazeEffect_LightingMapSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), HazeEffect_LightingMapSlot));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
_hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); _hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));

View file

@ -29,7 +29,7 @@
vec3 fragEyeDir = normalize(fragEyeVector); vec3 fragEyeDir = normalize(fragEyeVector);
// Get light // Get light
Light light = getLight(); Light light = getKeyLight();
LightAmbient lightAmbient = getLightAmbient(); LightAmbient lightAmbient = getLightAmbient();
vec3 lightDirection = getLightDirection(light); vec3 lightDirection = getLightDirection(light);
@ -143,7 +143,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu
<@func declareEvalLightmappedColor()@> <@func declareEvalLightmappedColor()@>
vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) {
Light light = getLight(); Light light = getKeyLight();
LightAmbient ambient = getLightAmbient(); LightAmbient ambient = getLightAmbient();
// Catch normals perpendicular to the projection plane, hence the magic number for the threshold // Catch normals perpendicular to the projection plane, hence the magic number for the threshold

View file

@ -53,7 +53,7 @@ void main(void) {
vec4 worldFragPos = viewInverse * eyeFragPos; vec4 worldFragPos = viewInverse * eyeFragPos;
vec4 worldEyePos = viewInverse[3]; vec4 worldEyePos = viewInverse[3];
Light light = getLight(); Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light); vec3 lightDirection = getLightDirection(light);
outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y, lightDirection); outFragColor = computeHazeColor(fragColor, eyeFragPos.xyz, worldFragPos.xyz, worldEyePos.y, lightDirection);

View file

@ -86,4 +86,24 @@ int clusterGrid_getClusterLightId(int index, int offset) {
return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF; return (((elementIndex & 0x00000001) == 1) ? (element >> 16) : element) & 0x0000FFFF;
} }
<@func fetchClusterInfo(fragWorldPos)@>
// From frag world pos find the cluster
vec4 clusterEyePos = frustumGrid_worldToEye(<$fragWorldPos$>);
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
ivec3 dims = frustumGrid.dims.xyz;
<@endfunc@>
bool hasLocalLights(int numLights, ivec3 clusterPos, ivec3 dims) {
return numLights>0
&& all(greaterThanEqual(clusterPos, ivec3(0)))
&& all(lessThan(clusterPos.xy, dims.xy))
&& clusterPos.z <= dims.z;
}
<@endif@> <@endif@>

View file

@ -0,0 +1,148 @@
// Generated on <$_SCRIBE_DATE$>
//
// Created by Olivier Prat on 15/01/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Everything about light
<@include graphics/Light.slh@>
<$declareLightBuffer(256)$>
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
<@include LightSpot.slh@>
<$declareLightingSpot(supportScattering)$>
<@include LightClusterGrid.slh@>
vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface,
float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering,
vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) {
vec4 fragColor = vec4(0.0);
vec3 fragSpecular = vec3(0.0);
vec3 fragDiffuse = vec3(0.0);
int lightClusterOffset = cluster.z;
// Compute the rougness into gloss2 once:
bool withScattering = (fragScattering * isScatteringEnabled() > 0.0);
int numLightTouching = 0;
for (int i = 0; i < cluster.x; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
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;
if (!lightVolume_clipFragToLightVolumePoint(light.volume, fragWorldPos.xyz, fragLightVecLen2)) {
continue;
}
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) {
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;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,
fragScattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);
}
diffuse *= lightEnergy;
specular *= lightEnergy;
fragDiffuse.rgb += diffuse;
fragSpecular.rgb += specular;
}
for (int i = cluster.x; i < numLights; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
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, fragWorldPos.xyz, fragLightVecLen2)) {
continue;
}
// Allright we re in the light sphere volume
fragLightDirLen.w = length(fragLightVecLen2.xyz);
fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w;
if (dot(surface.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;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);
vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo,
fragScattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo);
}
diffuse *= lightEnergy;
specular *= lightEnergy;
fragDiffuse.rgb += diffuse;
fragSpecular.rgb += specular;
}
fragDiffuse *= isDiffuseEnabled();
fragSpecular *= isSpecularEnabled();
fragColor.rgb += fragDiffuse;
fragColor.rgb += fragSpecular / opacity;
return fragColor;
}

View file

@ -289,9 +289,8 @@ void evalFragShading(out vec3 diffuse, out vec3 specular,
void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, void evalFragShadingScattering(out vec3 diffuse, out vec3 specular,
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo,
,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) {
) {
vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w);
float NdotL = surface.ndotl; float NdotL = surface.ndotl;
diffuse = mix(vec3(NdotL), brdf, scattering); diffuse = mix(vec3(NdotL), brdf, scattering);
@ -305,8 +304,7 @@ void evalFragShadingScattering(out vec3 diffuse, out vec3 specular,
} }
void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, void evalFragShadingGloss(out vec3 diffuse, out vec3 specular,
float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) {
) {
vec4 shading = evalPBRShading(metallic, fresnel, surface); vec4 shading = evalPBRShading(metallic, fresnel, surface);
diffuse = vec3(shading.w); diffuse = vec3(shading.w);
diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled());

View file

@ -12,6 +12,8 @@
#include "RenderDeferredTask.h" #include "RenderDeferredTask.h"
#include <DependencyManager.h>
#include <PerfStat.h> #include <PerfStat.h>
#include <PathUtils.h> #include <PathUtils.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
@ -168,7 +170,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<DrawHaze>("DrawHazeDeferred", drawHazeInputs); task.addJob<DrawHaze>("DrawHazeDeferred", drawHazeInputs);
// Render transparent objects forward in LightingBuffer // Render transparent objects forward in LightingBuffer
const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel, lightClusters).asVarying();
task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber); task.addJob<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
// Light Cluster Grid Debuging job // Light Cluster Grid Debuging job
@ -298,6 +300,8 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
const auto& inItems = inputs.get0(); const auto& inItems = inputs.get0();
const auto& lightingModel = inputs.get1(); const auto& lightingModel = inputs.get1();
const auto& lightClusters = inputs.get2();
auto deferredLightingEffect = DependencyManager::get<DeferredLightingEffect>();
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
@ -319,7 +323,13 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
// Setup lighting model for all items; // Setup lighting model for all items;
batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer()); batch.setUniformBuffer(render::ShapePipeline::Slot::LIGHTING_MODEL, lightingModel->getParametersBuffer());
// Setup haze iff current zone has haze deferredLightingEffect->setupLocalLightsBatch(batch,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT,
lightClusters);
// Setup haze if current zone has haze
auto hazeStage = args->_scene->getStage<HazeStage>(); auto hazeStage = args->_scene->getStage<HazeStage>();
if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) { if (hazeStage && hazeStage->_currentFrame._hazes.size() > 0) {
graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front()); graphics::HazePointer hazePointer = hazeStage->getHaze(hazeStage->_currentFrame._hazes.front());
@ -341,6 +351,11 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs&
args->_batch = nullptr; args->_batch = nullptr;
args->_globalShapeKey = 0; args->_globalShapeKey = 0;
deferredLightingEffect->unsetLocalLightsBatch(batch,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
render::ShapePipeline::Slot::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT);
}); });
config->setNumDrawn((int)inItems.size()); config->setNumDrawn((int)inItems.size());

View file

@ -15,6 +15,7 @@
#include <gpu/Pipeline.h> #include <gpu/Pipeline.h>
#include <render/RenderFetchCullSortTask.h> #include <render/RenderFetchCullSortTask.h>
#include "LightingModel.h" #include "LightingModel.h"
#include "LightClusters.h"
class DrawDeferredConfig : public render::Job::Config { class DrawDeferredConfig : public render::Job::Config {
Q_OBJECT Q_OBJECT
@ -40,7 +41,7 @@ protected:
class DrawDeferred { class DrawDeferred {
public: public:
using Inputs = render::VaryingSet2<render::ItemBounds, LightingModelPointer>; using Inputs = render::VaryingSet3 <render::ItemBounds, LightingModelPointer, LightClustersPointer>;
using Config = DrawDeferredConfig; using Config = DrawDeferredConfig;
using JobModel = render::Job::ModelI<DrawDeferred, Inputs, Config>; using JobModel = render::Job::ModelI<DrawDeferred, Inputs, Config>;

View file

@ -29,6 +29,8 @@
#include "model_lightmap_fade_vert.h" #include "model_lightmap_fade_vert.h"
#include "model_lightmap_normal_map_fade_vert.h" #include "model_lightmap_normal_map_fade_vert.h"
#include "model_translucent_vert.h"
#include "model_translucent_fade_vert.h"
#include "skin_model_fade_vert.h" #include "skin_model_fade_vert.h"
#include "skin_model_normal_map_fade_vert.h" #include "skin_model_normal_map_fade_vert.h"
@ -188,6 +190,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert));
auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert)); auto modelLightmapVertex = gpu::Shader::createVertex(std::string(model_lightmap_vert));
auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert)); auto modelLightmapNormalMapVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_vert));
auto modelTranslucentVertex = gpu::Shader::createVertex(std::string(model_translucent_vert));
auto modelTranslucentFadeVertex = gpu::Shader::createVertex(std::string(model_translucent_fade_vert));
auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); auto modelShadowVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert));
auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert));
@ -196,6 +200,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
auto modelLightmapNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_fade_vert)); auto modelLightmapNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_lightmap_normal_map_fade_vert));
auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert)); auto skinModelFadeVertex = gpu::Shader::createVertex(std::string(skin_model_fade_vert));
auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert)); auto skinModelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_fade_vert));
auto skinModelTranslucentVertex = skinModelFadeVertex; // We use the same because it ouputs world position per vertex
auto skinModelNormalMapTranslucentVertex = skinModelNormalMapFadeVertex; // We use the same because it ouputs world position per vertex
auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert)); auto modelFadeVertex = gpu::Shader::createVertex(std::string(model_fade_vert));
auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert)); auto modelNormalMapFadeVertex = gpu::Shader::createVertex(std::string(model_normal_map_fade_vert));
@ -289,7 +295,7 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Translucents // Translucents
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent(), Key::Builder().withMaterial().withTranslucent(),
modelVertex, modelTranslucentPixel, nullptr, nullptr); modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withTranslucent(), Key::Builder().withTranslucent(),
simpleVertex, simpleTranslucentPixel, nullptr, nullptr); simpleVertex, simpleTranslucentPixel, nullptr, nullptr);
@ -301,21 +307,21 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr); simpleVertex, simpleTranslucentUnlitPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents(), Key::Builder().withMaterial().withTranslucent().withTangents(),
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withSpecular(), Key::Builder().withMaterial().withTranslucent().withSpecular(),
modelVertex, modelTranslucentPixel, nullptr, nullptr); modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(), Key::Builder().withMaterial().withTranslucent().withTangents().withSpecular(),
modelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
// FIXME: Ignore lightmap for translucents meshpart // FIXME: Ignore lightmap for translucents meshpart
Key::Builder().withMaterial().withTranslucent().withLightmap(), Key::Builder().withMaterial().withTranslucent().withLightmap(),
modelVertex, modelTranslucentPixel, nullptr, nullptr); modelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withTranslucent().withFade(), Key::Builder().withMaterial().withTranslucent().withFade(),
modelFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter); modelTranslucentFadeVertex, modelTranslucentFadePixel, batchSetter, itemSetter);
addPipeline( addPipeline(
Key::Builder().withTranslucent().withFade(), Key::Builder().withTranslucent().withFade(),
simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter); simpleFadeVertex, simpleTranslucentFadePixel, batchSetter, itemSetter);
@ -396,16 +402,16 @@ void initDeferredPipelines(render::ShapePlumber& plumber, const render::ShapePip
// Skinned and Translucent // Skinned and Translucent
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent(), Key::Builder().withMaterial().withSkinned().withTranslucent(),
skinModelVertex, modelTranslucentPixel, nullptr, nullptr); skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(), Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents(),
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(), Key::Builder().withMaterial().withSkinned().withTranslucent().withSpecular(),
skinModelVertex, modelTranslucentPixel, nullptr, nullptr); skinModelTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(), Key::Builder().withMaterial().withSkinned().withTranslucent().withTangents().withSpecular(),
skinModelNormalMapVertex, modelTranslucentPixel, nullptr, nullptr); skinModelNormalMapTranslucentVertex, modelTranslucentPixel, nullptr, nullptr);
// Same thing but with Fade on // Same thing but with Fade on
addPipeline( addPipeline(
Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(), Key::Builder().withMaterial().withSkinned().withTranslucent().withFade(),
@ -571,9 +577,9 @@ void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderAr
batchSetter(pipeline, batch, args); batchSetter(pipeline, batch, args);
// Set the light // Set the light
if (pipeline.locations->lightBufferUnit >= 0) { if (pipeline.locations->keyLightBufferUnit >= 0) {
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch, DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch,
pipeline.locations->lightBufferUnit, pipeline.locations->keyLightBufferUnit,
pipeline.locations->lightAmbientBufferUnit, pipeline.locations->lightAmbientBufferUnit,
pipeline.locations->lightAmbientMapUnit); pipeline.locations->lightAmbientMapUnit);
} }

View file

@ -463,7 +463,7 @@ gpu::PipelinePointer DebugSubsurfaceScattering::getScatteringPipeline() {
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ScatteringTask_FrameTransformSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ScatteringTask_FrameTransformSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringParamsBuffer"), ScatteringTask_ParamSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringParamsBuffer"), ScatteringTask_ParamSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ScatteringTask_LightSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), ScatteringTask_LightSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), ScatteringTask_ScatteringTableSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringLUT"), ScatteringTask_ScatteringTableSlot));
slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), ScatteringTask_CurvatureMapSlot)); slotBindings.insert(gpu::Shader::Binding(std::string("curvatureMap"), ScatteringTask_CurvatureMapSlot));

View file

@ -83,7 +83,7 @@ const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ZONE_DEFERRED_TRANSFORM_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), ZONE_DEFERRED_TRANSFORM_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), ZONE_KEYLIGHT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), ZONE_KEYLIGHT_BUFFER));
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);

View file

@ -54,26 +54,8 @@ void main(void) {
mat4 invViewMat = getViewInverse(); mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition; vec4 fragPos = invViewMat * fragPosition;
// From frag world pos find the cluster <$fetchClusterInfo(fragPos)$>;
vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); if (!hasLocalLights(numLights, clusterPos, dims)) {
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
if (numLights <= 0) {
discard;
}
int lightClusterOffset = cluster.z;
ivec3 dims = frustumGrid.dims.xyz;
if (clusterPos.x < 0 || clusterPos.x >= dims.x) {
discard;
}
if (clusterPos.y < 0 || clusterPos.y >= dims.y) {
discard;
}
if (clusterPos.z < 0 || clusterPos.z > dims.z) {
discard; discard;
} }
@ -82,6 +64,7 @@ void main(void) {
vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec3 fragEyeDir = normalize(fragEyeVector.xyz);
int numLightTouching = 0; int numLightTouching = 0;
int lightClusterOffset = cluster.z;
for (int i = 0; i < cluster.x; i++) { for (int i = 0; i < cluster.x; i++) {
// Need the light now // Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset); int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);

View file

@ -17,18 +17,7 @@
<$declareDeferredCurvature()$> <$declareDeferredCurvature()$>
// Everything about light <@include LightLocal.slh@>
<@include graphics/Light.slh@>
<$declareLightBuffer(256)$>
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
<@include LightSpot.slh@>
<$declareLightingSpot(supportScattering)$>
<@include LightClusterGrid.slh@>
in vec2 _texCoord0; in vec2 _texCoord0;
out vec4 _fragColor; out vec4 _fragColor;
@ -49,28 +38,10 @@ void main(void) {
// Frag pos in world // Frag pos in world
mat4 invViewMat = getViewInverse(); mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition; vec4 fragWorldPos = invViewMat * fragPosition;
// From frag world pos find the cluster <$fetchClusterInfo(fragWorldPos)$>;
vec4 clusterEyePos = frustumGrid_worldToEye(fragPos); if (!hasLocalLights(numLights, clusterPos, dims)) {
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec3 cluster = clusterGrid_getCluster(frustumGrid_clusterToIndex(clusterPos));
int numLights = cluster.x + cluster.y;
if (numLights <= 0) {
discard;
}
int lightClusterOffset = cluster.z;
ivec3 dims = frustumGrid.dims.xyz;
if (clusterPos.x < 0 || clusterPos.x >= dims.x) {
discard;
}
if (clusterPos.y < 0 || clusterPos.y >= dims.y) {
discard;
}
if (clusterPos.z < 0 || clusterPos.z > dims.z) {
discard; discard;
} }
@ -84,117 +55,11 @@ void main(void) {
// Frag to eye vec // Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz); vec3 fragEyeDir = normalize(fragEyeVector.xyz);
SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir); SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir);
bool withScattering = (frag.scattering * isScatteringEnabled() > 0.0);
int numLightTouching = 0; _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface,
for (int i = 0; i < cluster.x; i++) { frag.metallic, frag.fresnel, frag.albedo, frag.scattering,
// Need the light now midNormalCurvature, lowNormalCurvature, 1.0);
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
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;
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;
}
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;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
vec3 lightEnergy = radialAttenuation * getLightIrradiance(light);
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo);
}
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
}
for (int i = cluster.x; i < numLights; i++) {
// Need the light now
int theLightIndex = clusterGrid_getClusterLightId(i, lightClusterOffset);
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;
updateSurfaceDataWithLight(surface, fragLightDir);
// Eval attenuation
float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance);
float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle);
vec3 lightEnergy = radialAttenuation * angularAttenuation * getLightIrradiance(light);
// Eval shading
if (withScattering) {
evalFragShadingScattering(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo
,frag.scattering, midNormalCurvature, lowNormalCurvature );
} else {
evalFragShadingGloss(diffuse, specular, frag.metallic, frag.fresnel, surface, frag.albedo);
}
diffuse *= lightEnergy * isDiffuseEnabled();
specular *= lightEnergy * isSpecularEnabled();
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
}
} }

View file

@ -18,6 +18,8 @@
<$declareEvalGlobalLightingAlphaBlended()$> <$declareEvalGlobalLightingAlphaBlended()$>
<@include LightLocal.slh@>
<@include gpu/Transform.slh@> <@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$> <$declareStandardCameraTransform()$>
@ -27,6 +29,7 @@
in vec2 _texCoord0; in vec2 _texCoord0;
in vec2 _texCoord1; in vec2 _texCoord1;
in vec4 _position; in vec4 _position;
in vec4 _worldPosition;
in vec3 _normal; in vec3 _normal;
in vec3 _color; in vec3 _color;
in float _alpha; in float _alpha;
@ -56,20 +59,32 @@ void main(void) {
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz; vec3 fragPosition = _position.xyz;
// Lighting is done in world space
vec3 fragNormal = normalize(_normal); vec3 fragNormal = normalize(_normal);
TransformCamera cam = getTransformCamera(); TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
_fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse, cam._viewInverse,
1.0, 1.0,
occlusionTex, occlusionTex,
fragPosition, fragPosition,
fragNormal,
albedo, albedo,
fresnel, fresnel,
metallic, metallic,
emissive, emissive,
roughness, opacity), surface, opacity, localLighting.rgb),
opacity); opacity);
} }

View file

@ -0,0 +1,44 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// model_translucent.slv
// vertex shader
//
// Created by Olivier Prat on 15/01/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Inputs.slh@>
<@include gpu/Color.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec3 _color;
void main(void) {
_color = colorToLinearRGB(inColor.xyz);
_alpha = inColor.w;
TexMapArray texMapArray = getTexMapArray();
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -18,6 +18,8 @@
<$declareEvalGlobalLightingAlphaBlended()$> <$declareEvalGlobalLightingAlphaBlended()$>
<@include LightLocal.slh@>
<@include gpu/Transform.slh@> <@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$> <$declareStandardCameraTransform()$>
@ -66,20 +68,32 @@ void main(void) {
<$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>;
vec3 fragPosition = _position.xyz; vec3 fragPosition = _position.xyz;
// Lighting is done in world space
vec3 fragNormal = normalize(_normal); vec3 fragNormal = normalize(_normal);
TransformCamera cam = getTransformCamera(); TransformCamera cam = getTransformCamera();
vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0));
vec3 fragEyeDir = normalize(fragEyeVector);
SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir);
vec4 localLighting = vec4(0.0);
<$fetchClusterInfo(_worldPosition)$>;
if (hasLocalLights(numLights, clusterPos, dims)) {
localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface,
metallic, fresnel, albedo, 0.0,
vec4(0), vec4(0), opacity);
}
_fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse, cam._viewInverse,
1.0, 1.0,
occlusionTex, occlusionTex,
fragPosition, fragPosition,
fragNormal,
albedo, albedo,
fresnel, fresnel,
metallic, metallic,
emissive+fadeEmissive, emissive+fadeEmissive,
roughness, opacity), surface, opacity, localLighting.rgb),
opacity); opacity);
} }

View file

@ -0,0 +1,44 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// model_translucent_fade.slv
// vertex shader
//
// Created by Olivier Prat on 15/01/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Inputs.slh@>
<@include gpu/Color.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include MaterialTextures.slh@>
<$declareMaterialTexMapArrayBuffer()$>
out float _alpha;
out vec2 _texCoord0;
out vec2 _texCoord1;
out vec4 _position;
out vec4 _worldPosition;
out vec3 _normal;
out vec3 _color;
void main(void) {
_color = colorToLinearRGB(inColor.xyz);
_alpha = inColor.w;
TexMapArray texMapArray = getTexMapArray();
<$evalTexMapArrayTexcoord0(texMapArray, inTexCoord0, _texCoord0)$>
<$evalTexMapArrayTexcoord1(texMapArray, inTexCoord0, _texCoord1)$>
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToEyeAndClipPos(cam, obj, inPosition, _position, gl_Position)$>
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
<$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$>
}

View file

@ -27,7 +27,7 @@
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {
// Need the light now // Need the light now
Light light = getLight(); Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light); vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light); vec3 lightIrradiance = getLightIrradiance(light);

View file

@ -27,7 +27,7 @@
vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) { vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 fresnel, float roughness, float opacity) {
// Need the light now // Need the light now
Light light = getLight(); Light light = getKeyLight();
vec3 lightDirection = getLightDirection(light); vec3 lightDirection = getLightDirection(light);
vec3 lightIrradiance = getLightIrradiance(light); vec3 lightIrradiance = getLightIrradiance(light);

View file

@ -42,7 +42,7 @@ vec3 evalScatteringBRDF(vec2 texcoord) {
vec3 fragNormal = vec3((normal)); vec3 fragNormal = vec3((normal));
// Get light // Get light
Light light = getLight(); Light light = getKeyLight();
vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin
float metallic = 0.0; float metallic = 0.0;
@ -65,7 +65,7 @@ vec3 drawScatteringTableUV(vec2 cursor, vec2 texcoord) {
float curvature = unpackCurvature(diffusedCurvature.w); float curvature = unpackCurvature(diffusedCurvature.w);
// Get light // Get light
Light light = getLight(); Light light = getKeyLight();
vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin vec3 fresnel = vec3(0.028); // Default Di-electric fresnel value for skin
vec3 fragLightDir = -normalize(getLightDirection(light)); vec3 fragLightDir = -normalize(getLightDirection(light));

View file

@ -25,7 +25,7 @@ void main(void) {
<$evalGlobeWidget()$> <$evalGlobeWidget()$>
Light light = getLight(); Light light = getKeyLight();
vec3 lightDirection = normalize(getLightDirection(light)); vec3 lightDirection = normalize(getLightDirection(light));
vec3 lightIrradiance = getLightIrradiance(light); vec3 lightIrradiance = getLightIrradiance(light);
vec3 color = vec3(0.0); vec3 color = vec3(0.0);

View file

@ -70,6 +70,8 @@ void ShapePlumber::addPipeline(const Key& key, const gpu::ShaderPointer& program
void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state, void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& program, const gpu::StatePointer& state,
BatchSetter batchSetter, ItemSetter itemSetter) { BatchSetter batchSetter, ItemSetter itemSetter) {
ShapeKey key{ filter._flags };
gpu::Shader::BindingSet slotBindings; gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL)); slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), Slot::BUFFER::LIGHTING_MODEL));
slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING)); slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::BUFFER::SKINNING));
@ -82,6 +84,7 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::MAP::EMISSIVE_LIGHTMAP)); slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::MAP::EMISSIVE_LIGHTMAP));
slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION)); slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::MAP::OCCLUSION));
slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING)); slotBindings.insert(gpu::Shader::Binding(std::string("scatteringMap"), Slot::MAP::SCATTERING));
slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), Slot::BUFFER::KEY_LIGHT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::BUFFER::LIGHT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), Slot::BUFFER::LIGHT_AMBIENT_BUFFER));
slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), Slot::MAP::LIGHT_AMBIENT));
@ -89,6 +92,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeParametersBuffer"), Slot::BUFFER::FADE_PARAMETERS));
slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL)); slotBindings.insert(gpu::Shader::Binding(std::string("hazeBuffer"), Slot::BUFFER::HAZE_MODEL));
if (key.isTranslucent()) {
slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), Slot::BUFFER::LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
}
gpu::Shader::makeProgram(*program, slotBindings); gpu::Shader::makeProgram(*program, slotBindings);
auto locations = std::make_shared<Locations>(); auto locations = std::make_shared<Locations>();
@ -103,14 +112,23 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p
locations->skinClusterBufferUnit = program->getUniformBuffers().findLocation("skinClusterBuffer"); locations->skinClusterBufferUnit = program->getUniformBuffers().findLocation("skinClusterBuffer");
locations->materialBufferUnit = program->getUniformBuffers().findLocation("materialBuffer"); locations->materialBufferUnit = program->getUniformBuffers().findLocation("materialBuffer");
locations->texMapArrayBufferUnit = program->getUniformBuffers().findLocation("texMapArrayBuffer"); locations->texMapArrayBufferUnit = program->getUniformBuffers().findLocation("texMapArrayBuffer");
locations->keyLightBufferUnit = program->getUniformBuffers().findLocation("keyLightBuffer");
locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer"); locations->lightBufferUnit = program->getUniformBuffers().findLocation("lightBuffer");
locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer"); locations->lightAmbientBufferUnit = program->getUniformBuffers().findLocation("lightAmbientBuffer");
locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap"); locations->lightAmbientMapUnit = program->getTextures().findLocation("skyboxMap");
locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap"); locations->fadeMaskTextureUnit = program->getTextures().findLocation("fadeMaskMap");
locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer"); locations->fadeParameterBufferUnit = program->getUniformBuffers().findLocation("fadeParametersBuffer");
locations->hazeParameterBufferUnit = program->getUniformBuffers().findLocation("hazeParametersBuffer"); locations->hazeParameterBufferUnit = program->getUniformBuffers().findLocation("hazeParametersBuffer");
if (key.isTranslucent()) {
locations->lightClusterGridBufferUnit = program->getUniformBuffers().findLocation("clusterGridBuffer");
locations->lightClusterContentBufferUnit = program->getUniformBuffers().findLocation("clusterContentBuffer");
locations->lightClusterFrustumBufferUnit = program->getUniformBuffers().findLocation("frustumGridBuffer");
} else {
locations->lightClusterGridBufferUnit = -1;
locations->lightClusterContentBufferUnit = -1;
locations->lightClusterFrustumBufferUnit = -1;
}
ShapeKey key{filter._flags};
auto gpuPipeline = gpu::Pipeline::create(program, state); auto gpuPipeline = gpu::Pipeline::create(program, state);
auto shapePipeline = std::make_shared<Pipeline>(gpuPipeline, locations, batchSetter, itemSetter); auto shapePipeline = std::make_shared<Pipeline>(gpuPipeline, locations, batchSetter, itemSetter);
addPipelineHelper(filter, key, 0, shapePipeline); addPipelineHelper(filter, key, 0, shapePipeline);

View file

@ -235,10 +235,15 @@ public:
MATERIAL, MATERIAL,
TEXMAPARRAY, TEXMAPARRAY,
LIGHTING_MODEL, LIGHTING_MODEL,
KEY_LIGHT,
LIGHT, LIGHT,
LIGHT_AMBIENT_BUFFER, LIGHT_AMBIENT_BUFFER,
HAZE_MODEL, HAZE_MODEL,
FADE_PARAMETERS, FADE_PARAMETERS,
LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT,
LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
}; };
enum MAP { enum MAP {
@ -266,12 +271,16 @@ public:
int skinClusterBufferUnit; int skinClusterBufferUnit;
int materialBufferUnit; int materialBufferUnit;
int texMapArrayBufferUnit; int texMapArrayBufferUnit;
int keyLightBufferUnit;
int lightBufferUnit; int lightBufferUnit;
int lightAmbientBufferUnit; int lightAmbientBufferUnit;
int lightAmbientMapUnit; int lightAmbientMapUnit;
int fadeMaskTextureUnit; int fadeMaskTextureUnit;
int fadeParameterBufferUnit; int fadeParameterBufferUnit;
int hazeParameterBufferUnit; int hazeParameterBufferUnit;
int lightClusterGridBufferUnit;
int lightClusterContentBufferUnit;
int lightClusterFrustumBufferUnit;
}; };
using LocationsPointer = std::shared_ptr<Locations>; using LocationsPointer = std::shared_ptr<Locations>;