best state for now

This commit is contained in:
samcake 2016-09-13 14:59:23 -07:00
parent e9bf19840c
commit e8c2dc10f1
11 changed files with 180 additions and 39 deletions

View file

@ -24,7 +24,7 @@ using namespace gpu;
using namespace gpu::gl;
using namespace gpu::gl45;
#define SPARSE_TEXTURES 1
#define SPARSE_TEXTURES 0
// Allocate 1 MB of buffer space for paged transfers
#define DEFAULT_PAGE_BUFFER_SIZE (1024*1024)

View file

@ -32,11 +32,11 @@ namespace gpu {
enum ReservedSlot {
#ifdef GPU_SSBO_DRAW_CALL_INFO
TRANSFORM_OBJECT_SLOT = 6,
TRANSFORM_OBJECT_SLOT = 14,
#else
TRANSFORM_OBJECT_SLOT = 31,
#endif
TRANSFORM_CAMERA_SLOT = 7,
TRANSFORM_CAMERA_SLOT = 15,
};
// The named batch data provides a mechanism for accumulating data into buffers over the course

View file

@ -73,6 +73,10 @@ enum DeferredShader_BufferSlot {
LIGHTING_MODEL_BUFFER_SLOT = render::ShapePipeline::Slot::LIGHTING_MODEL,
LIGHT_GPU_SLOT = render::ShapePipeline::Slot::LIGHT,
LIGHT_INDEX_GPU_SLOT,
LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT,
LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT,
LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT,
};
static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations);
@ -218,7 +222,11 @@ static gpu::ShaderPointer makeLightProgram(const char* vertSource, const char* f
slotBindings.insert(gpu::Shader::Binding(std::string("subsurfaceScatteringParametersBuffer"), SCATTERING_PARAMETERS_BUFFER_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("lightIndexBuffer"), LIGHT_INDEX_GPU_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT));
gpu::Shader::makeProgram(*program, slotBindings);
@ -716,6 +724,11 @@ void RenderDeferredLocals::run(const render::SceneContextPointer& sceneContext,
batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightIndexBufferUnit, lightClusters->_lightIndicesBuffer);
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);
// before we get to the real lighting, let s try to cull down the number of pixels
if (false) {/*
if (numPointLights > 0) {

View file

@ -47,12 +47,30 @@ float projection_getFar(mat4 projection) {
// end of hybrid include
layout (std140) uniform clusterGridBuffer {
uniform clusterGridBuffer {
int _clusterGridTable[4096];
};
layout (std140) uniform clusterContentBuffer {
int _clusterGridContent[4096];
uniform clusterContentBuffer {
int _clusterGridContent[10000];
};
int clusterGrid_clusterToIndex(ivec3 pos) {
return pos.x + (pos.y + pos.z * frustumGrid.dims.y) * frustumGrid.dims.x;
}
ivec3 clusterGrid_indexToCluster(int index) {
ivec3 summedDims = ivec3(frustumGrid.dims.x * frustumGrid.dims.y, frustumGrid.dims.x, 1);
int layer = index / summedDims.x;
int offsetInLayer = index % summedDims.x;
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
return clusterPos;
}
ivec2 clusterGrid_getCluster(int index) {
int clusterDesc = _clusterGridTable[index];
int numLights = 0xFFFF & (clusterDesc >> 16);
int contentOffset = 0xFFFF & (clusterDesc);
return ivec2(numLights, contentOffset);
}
<@endif@>

View file

@ -1,5 +1,4 @@
// glsl / C++ compatible source as interface for FrustrumGrid
float frustumGrid_depthRamp(float linear) {
// return linear;
return linear * linear;
@ -132,6 +131,8 @@ vec4 frustumGrid_worldToEye(vec4 worldPos) {
return frustumGrid.worldToEyeMat * worldPos;
}
// <@if 1@>
// Trigger Scribe include
// <@endif@> <!def that !> End C++ compatible

View file

@ -194,10 +194,27 @@ void LightClusters::updateClusters() {
// rotate the eyeToOriDir (H & V) in both directions
glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
glm::vec3 leftDir(eyeOriDirH.x * eyeToTangentCircleCosH + eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * -eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
glm::vec3 rightDir(eyeOriDirH.x * eyeToTangentCircleCosH - eyeOriDirH.z * eyeToTangentCircleSinH, 0.0f, eyeOriDirH.x * eyeToTangentCircleSinH + eyeOriDirH.z * eyeToTangentCircleCosH);
glm::vec3 bottomDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV + eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * -eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
glm::vec3 topDir(0.0f, eyeOriDirV.y * eyeToTangentCircleCosV - eyeOriDirV.z * eyeToTangentCircleSinV, eyeOriDirV.y * eyeToTangentCircleSinV + eyeOriDirV.z * eyeToTangentCircleCosV);
glm::vec3 leftPosAtNear = leftDir * theFrustumGrid.rangeNear * 2.0f;
glm::vec3 rightPosAtNear = rightDir * theFrustumGrid.rangeNear * 2.0f;
glm::vec3 bottomPosAtNear = bottomDir * theFrustumGrid.rangeNear * 2.0f;
glm::vec3 topPosAtNear = topDir * theFrustumGrid.rangeNear * 2.0f;
auto lc = theFrustumGrid.frustumGrid_eyeToClusterPos(leftPosAtNear);
auto rc = theFrustumGrid.frustumGrid_eyeToClusterPos(rightPosAtNear);
auto bc = theFrustumGrid.frustumGrid_eyeToClusterPos(bottomPosAtNear);
auto tc = theFrustumGrid.frustumGrid_eyeToClusterPos(topPosAtNear);
xMin = std::max(0, lc.x);
xMax = std::max(0, std::min(rc.x, xMax));
yMin = std::max(0, bc.y);
yMax = std::max(0, std::min(tc.y, yMax));
}
@ -249,6 +266,16 @@ void LightClusteringPass::configure(const Config& config) {
if (_lightClusters->_frustumGridBuffer->rangeFar != config.rangeFar) {
_lightClusters->_frustumGridBuffer.edit().rangeFar = config.rangeFar;
}
ivec3 configDimensions;
configDimensions.x = std::max(0, std::min(16, config.dimX));
configDimensions.y = std::max(0, std::min(16, config.dimY));
configDimensions.z = std::max(0, std::min(15, config.dimZ));
auto& dims = _lightClusters->_frustumGridBuffer->dims;
if ((dims.x != configDimensions.x) || (dims.y != configDimensions.y) || (dims.z != configDimensions.z)) {
_lightClusters->setDimensions(configDimensions, 10000);
}
}
_freeze = config.freeze;
@ -290,6 +317,7 @@ DebugLightClusters::DebugLightClusters() {
void DebugLightClusters::configure(const Config& config) {
doDrawGrid = config.doDrawGrid;
doDrawClusterFromDepth = config.doDrawClusterFromDepth;
doDrawContent = config.doDrawContent;
}
@ -301,6 +329,9 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterGridPipeline() {
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT));
gpu::Shader::makeProgram(*program, slotBindings);
@ -327,6 +358,8 @@ const gpu::PipelinePointer DebugLightClusters::getDrawClusterFromDepthPipeline()
gpu::Shader::BindingSet slotBindings;
slotBindings.insert(gpu::Shader::Binding(std::string("frustumGridBuffer"), LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterGridBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("clusterContentBuffer"), LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("linearZeyeMap"), DEFERRED_BUFFER_LINEAR_DEPTH_UNIT));
slotBindings.insert(gpu::Shader::Binding(std::string("cameraCorrectionBuffer"), CAMERA_CORRECTION_BUFFER_SLOT));
slotBindings.insert(gpu::Shader::Binding(std::string("deferredFrameTransformBuffer"), DEFERRED_FRAME_TRANSFORM_BUFFER_SLOT));
@ -401,6 +434,9 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co
batch.setModelTransform(Transform());
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);
if (doDrawClusterFromDepth) {
@ -422,8 +458,6 @@ void DebugLightClusters::run(const render::SceneContextPointer& sceneContext, co
if (doDrawContent) {
// bind the one gpu::Pipeline we need
batch.setPipeline(getDrawClusterContentPipeline());
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer);
batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer);
auto dims = lightClusters->_frustumGridBuffer->dims;
glm::ivec3 summedDims(dims.x*dims.y * dims.z, dims.x*dims.y, dims.x);

View file

@ -24,7 +24,7 @@ public:
float rangeFar { 100.0f };
float frustumFar { 10000.0f };
glm::ivec3 dims { 8, 8, 8 };
glm::ivec3 dims { 8, 8, 12 };
float spare;
glm::mat4 eyeToGridProj;
@ -97,12 +97,21 @@ class LightClusteringPassConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(float rangeNear MEMBER rangeNear NOTIFY dirty)
Q_PROPERTY(float rangeFar MEMBER rangeFar NOTIFY dirty)
Q_PROPERTY(int dimX MEMBER dimX NOTIFY dirty)
Q_PROPERTY(int dimY MEMBER dimY NOTIFY dirty)
Q_PROPERTY(int dimZ MEMBER dimZ NOTIFY dirty)
Q_PROPERTY(bool freeze MEMBER freeze NOTIFY dirty)
public:
LightClusteringPassConfig() : render::Job::Config(true){}
float rangeNear{ 1.0f };
float rangeFar{ 512.0f };
int dimX { 8 };
int dimY { 8 };
int dimZ { 12 };
bool freeze{ false };
signals:
@ -143,12 +152,14 @@ class DebugLightClustersConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool doDrawGrid MEMBER doDrawGrid NOTIFY dirty)
Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty)
Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty)
public:
DebugLightClustersConfig() : render::Job::Config(true){}
bool doDrawGrid{ false };
bool doDrawClusterFromDepth{ false };
bool doDrawClusterFromDepth { false };
bool doDrawContent { false };
signals:
void dirty();
@ -179,9 +190,9 @@ protected:
const gpu::PipelinePointer getDrawClusterGridPipeline();
const gpu::PipelinePointer getDrawClusterFromDepthPipeline();
const gpu::PipelinePointer getDrawClusterContentPipeline();
bool doDrawGrid{ false };
bool doDrawGrid { false };
bool doDrawClusterFromDepth { false };
bool doDrawContent { true };
bool doDrawContent { false };
};
#endif

View file

@ -53,22 +53,16 @@ void main(void) {
);
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
int clusterDesc = _clusterGridTable[gl_InstanceID];
int numLights = 0xFFFF & (clusterDesc >> 16);
if (numLights <= 0) {
return;
}
ivec3 dims = frustumGrid.dims.xyz;
ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1);
ivec2 cluster = clusterGrid_getCluster(gl_InstanceID);
int numLights = cluster.x;
float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0);
int layer = gl_InstanceID / summedDims.x;
int offsetInLayer = gl_InstanceID % summedDims.x;
ivec3 clusterPos = ivec3(offsetInLayer % summedDims.y, offsetInLayer / summedDims.y, layer);
ivec3 clusterPos = clusterGrid_indexToCluster(gl_InstanceID);
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
float boxScale = 0.99;
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz);
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));

View file

@ -36,6 +36,12 @@ void main(void) {
vec4 clusterEyePos = frustumGrid_worldToEye(fragWorldPos);
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos));
int numLights = cluster.x;
float numLightsScale = clamp(numLights * 0.1, 0.01, 1.0);
ivec3 dims = frustumGrid.dims.xyz;
dims.z +=1;
ivec3 summedDims = ivec3(dims.x * dims.y, dims.x, 1);
@ -59,9 +65,9 @@ void main(void) {
if (relClusterId < 0.0) {
_fragColor = vec4(0.0);
} else if (relClusterId >= 1.0) {
_fragColor = vec4(vec3(1.0), 0.5);
_fragColor = vec4(vec3(1.0), 0.2);
} else {
_fragColor = vec4(colorWheel(fract(relClusterId)), 0.9);
_fragColor = vec4(colorWheel(fract(relClusterId)), 0.05 + 0.95 * numLightsScale);
}
}

View file

@ -25,11 +25,15 @@ uniform lightIndexBuffer {
};
<@include LightingModel.slh@>
<@include LightPoint.slh@>
<$declareLightingPoint(supportScattering)$>
<@include LightSpot.slh@>
<$declareLightingSpot(supportScattering)$>
<@include LightClusterGrid.slh@>
in vec2 _texCoord0;
out vec4 _fragColor;
@ -47,24 +51,54 @@ void main(void) {
frag.position = fragPosition;
// Frag pos in world
mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition;
// From frag world pos find the cluster
vec4 clusterEyePos = frustumGrid_worldToEye(fragPos);
ivec3 clusterPos = frustumGrid_eyeToClusterPos(clusterEyePos.xyz);
ivec2 cluster = clusterGrid_getCluster(clusterGrid_clusterToIndex(clusterPos));
int numLights = cluster.x;
if (numLights <= 0) {
discard;
}
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;
}
int lightClusterOffset = cluster.y;
vec4 midNormalCurvature;
vec4 lowNormalCurvature;
if (frag.mode == FRAG_MODE_SCATTERING) {
unpackMidLowNormalCurvature(texCoord, midNormalCurvature, lowNormalCurvature);
}
// Frag pos in world
mat4 invViewMat = getViewInverse();
vec4 fragPos = invViewMat * fragPosition;
// Frag to eye vec
vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0);
vec3 fragEyeDir = normalize(fragEyeVector.xyz);
int numLights = lightIndex[0];
// int numLights = lightIndex[0];
for (int i = 0; i < numLights; i++) {
// Need the light now
Light light = getLight(lightIndex[i + 1]);
int theLightIndex = _clusterGridContent[lightClusterOffset + i];
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;
@ -98,5 +132,7 @@ void main(void) {
_fragColor.rgb += diffuse;
_fragColor.rgb += specular;
}
// _fragColor.rgb += vec3(0.05, 0.0, 0.0);
}

View file

@ -34,7 +34,30 @@ Column {
max: 500.0
min: 100.0
}
ConfigSlider {
label: qsTr("Grid X")
integral: true
config: Render.getConfig("LightClustering")
property: "dimX"
max: 16
min: 1
}
ConfigSlider {
label: qsTr("Grid Y")
integral: true
config: Render.getConfig("LightClustering")
property: "dimY"
max: 16
min: 1
}
ConfigSlider {
label: qsTr("Grid Z")
integral: true
config: Render.getConfig("LightClustering")
property: "dimZ"
max: 15
min: 1
}
CheckBox {
text: "Freeze"
checked: Render.getConfig("LightClustering")["freeze"]
@ -50,6 +73,11 @@ Column {
checked: Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"]
onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawClusterFromDepth"] = checked }
}
CheckBox {
text: "Draw Content"
checked: Render.getConfig("DebugLightClusters")["doDrawContent"]
onCheckedChanged: { Render.getConfig("DebugLightClusters")["doDrawContent"] = checked }
}
}
}
}