mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 20:34:07 +02:00
Still working on solving that underestimated shadow far plane on the first cascade. I have finally understood the problem (see TODO in LightStage)
This commit is contained in:
parent
b246c479e3
commit
d98dfff0a8
8 changed files with 212 additions and 80 deletions
|
@ -116,9 +116,12 @@ void LightStage::Shadow::setKeylightFrustum(unsigned int cascadeIndex, const Vie
|
|||
fitFrustum(farCorners.bottomRight);
|
||||
fitFrustum(farCorners.topLeft);
|
||||
fitFrustum(farCorners.topRight);
|
||||
|
||||
// TODO: Far distance should be extended to the intersection of the exteruded shadow frustum far plane
|
||||
// with the view frustum.
|
||||
|
||||
// Re-adjust near shadow distance
|
||||
auto near = glm::max(max.z, -nearDepth);
|
||||
auto near = glm::min(-max.z, nearDepth);
|
||||
auto far = -min.z;
|
||||
glm::mat4 ortho = glm::ortho<float>(min.x, max.x, min.y, max.y, near, far);
|
||||
cascade._frustum->setProjection(ortho);
|
||||
|
|
|
@ -204,7 +204,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
for (auto i = 0; i < ExtractFrustums::SHADOW_CASCADE_FRUSTUM_COUNT; i++) {
|
||||
const auto shadowFrustum = frustums.getN<ExtractFrustums::Output>(ExtractFrustums::SHADOW_CASCADE0_FRUSTUM+i);
|
||||
float tint = 1.0f - i / float(ExtractFrustums::SHADOW_CASCADE_FRUSTUM_COUNT - 1);
|
||||
task.addJob<DrawFrustum>("DrawShadowFrustum", shadowFrustum, glm::vec3(0.0f, tint, 1.0f));
|
||||
char jobName[64];
|
||||
sprintf(jobName, "DrawShadowFrustum%d", i);
|
||||
task.addJob<DrawFrustum>(jobName, shadowFrustum, glm::vec3(0.0f, tint, 1.0f));
|
||||
}
|
||||
|
||||
// Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
|
||||
|
|
|
@ -112,8 +112,7 @@ static void adjustNearFar(const AABox& inShapeBounds, ViewFrustum& shadowFrustum
|
|||
float far = 0.0f;
|
||||
|
||||
computeNearFar(sceneBoundVertices, shadowClipPlanes, near, far);
|
||||
// Limit the far range to the one used originally. There's no point in rendering objects
|
||||
// that are not in the view frustum.
|
||||
// Limit the far range to the one used originally.
|
||||
far = glm::min(far, shadowFrustum.getFarClip());
|
||||
|
||||
const auto depthEpsilon = 0.1f;
|
||||
|
@ -233,7 +232,6 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
|
||||
// GPU jobs: Render to shadow map
|
||||
task.addJob<RenderShadowMap>("RenderShadowMap", sortedShapesAndBounds, shapePlumber, i);
|
||||
|
||||
task.addJob<RenderShadowTeardown>("ShadowTeardown", setupOutput);
|
||||
}
|
||||
}
|
||||
|
@ -272,12 +270,13 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O
|
|||
minCascadeDistance = maxCascadeDistance / cascadeLevelScale;
|
||||
}
|
||||
|
||||
shadowOverlapDistance = (maxCascadeDistance - minCascadeDistance) / 3.0f;
|
||||
shadowOverlapDistance = (maxCascadeDistance - minCascadeDistance) / 4.0f;
|
||||
maxCascadeDistance += shadowOverlapDistance;
|
||||
if (_cascadeIndex == 0) {
|
||||
minCascadeDistance = nearClip;
|
||||
} else {
|
||||
minCascadeDistance = std::max(minCascadeDistance, nearClip);
|
||||
}
|
||||
minCascadeDistance = std::max(minCascadeDistance, nearClip);
|
||||
maxCascadeDistance = std::min(maxCascadeDistance, farClip);
|
||||
globalShadow->setKeylightFrustum(_cascadeIndex, args->getViewFrustum(), minCascadeDistance, maxCascadeDistance, shadowOverlapDistance, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR);
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ vec4 evalShadowTexcoord(int cascadeIndex, vec4 position) {
|
|||
}
|
||||
|
||||
bool isShadowCascadeProjectedOnPixel(vec4 cascadeTexCoords) {
|
||||
bvec3 greaterThanZero = greaterThanEqual(cascadeTexCoords.xyz, vec3(0));
|
||||
bvec3 lessThanOne = lessThanEqual(cascadeTexCoords.xyz, vec3(1));
|
||||
bvec2 greaterThanZero = greaterThanEqual(cascadeTexCoords.xy, vec2(0));
|
||||
bvec2 lessThanOne = lessThanEqual(cascadeTexCoords.xy, vec2(1));
|
||||
return all(greaterThanZero) && all(lessThanOne);
|
||||
}
|
||||
|
||||
|
|
|
@ -215,79 +215,158 @@ void DrawBounds::run(const RenderContextPointer& renderContext,
|
|||
});
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DrawFrustum::_pipeline;
|
||||
DrawQuadVolume::DrawQuadVolume(const glm::vec3& color) :
|
||||
_color{ color } {
|
||||
_meshVertices = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
|
||||
_meshStream.addBuffer(_meshVertices._buffer, _meshVertices._offset, _meshVertices._stride);
|
||||
}
|
||||
|
||||
void DrawQuadVolume::configure(const Config& configuration) {
|
||||
_isUpdateEnabled = !configuration.isFrozen;
|
||||
}
|
||||
|
||||
void DrawQuadVolume::run(const render::RenderContextPointer& renderContext, const glm::vec3 vertices[8],
|
||||
const gpu::BufferView& indices, int indexCount) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
if (_isUpdateEnabled) {
|
||||
auto& streamVertices = _meshVertices.edit<std::array<glm::vec3, 8U> >();
|
||||
std::copy(vertices, vertices + 8, streamVertices.begin());
|
||||
}
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setPipeline(getPipeline());
|
||||
batch.setIndexBuffer(indices);
|
||||
|
||||
batch._glUniform4f(0, _color.x, _color.y, _color.z, 1.0f);
|
||||
batch.setInputStream(0, _meshStream);
|
||||
batch.drawIndexed(gpu::LINES, indexCount, 0U);
|
||||
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DrawQuadVolume::getPipeline() {
|
||||
static gpu::PipelinePointer pipeline;
|
||||
|
||||
if (!pipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawColorPS();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("color", 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(true, false));
|
||||
pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
gpu::BufferView DrawAABox::_cubeMeshIndices;
|
||||
|
||||
DrawAABox::DrawAABox(const glm::vec3& color) :
|
||||
DrawQuadVolume{ color } {
|
||||
}
|
||||
|
||||
void DrawAABox::run(const render::RenderContextPointer& renderContext, const Inputs& box) {
|
||||
if (!box.isNull()) {
|
||||
static const uint8_t indexData[] = {
|
||||
0, 1,
|
||||
1, 2,
|
||||
2, 3,
|
||||
3, 0,
|
||||
4, 5,
|
||||
5, 6,
|
||||
6, 7,
|
||||
7, 4,
|
||||
0, 4,
|
||||
1, 5,
|
||||
3, 7,
|
||||
2, 6
|
||||
};
|
||||
|
||||
if (!_cubeMeshIndices._buffer) {
|
||||
auto indices = std::make_shared<gpu::Buffer>(sizeof(indexData), indexData);
|
||||
_cubeMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX));
|
||||
}
|
||||
|
||||
glm::vec3 vertices[8];
|
||||
|
||||
getVertices(box, vertices);
|
||||
|
||||
DrawQuadVolume::run(renderContext, vertices, _cubeMeshIndices, sizeof(indexData) / sizeof(indexData[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawAABox::getVertices(const AABox& box, glm::vec3 vertices[8]) {
|
||||
vertices[0] = box.getVertex(TOP_LEFT_NEAR);
|
||||
vertices[1] = box.getVertex(TOP_RIGHT_NEAR);
|
||||
vertices[2] = box.getVertex(BOTTOM_RIGHT_NEAR);
|
||||
vertices[3] = box.getVertex(BOTTOM_LEFT_NEAR);
|
||||
vertices[4] = box.getVertex(TOP_LEFT_FAR);
|
||||
vertices[5] = box.getVertex(TOP_RIGHT_FAR);
|
||||
vertices[6] = box.getVertex(BOTTOM_RIGHT_FAR);
|
||||
vertices[7] = box.getVertex(BOTTOM_LEFT_FAR);
|
||||
}
|
||||
|
||||
gpu::BufferView DrawFrustum::_frustumMeshIndices;
|
||||
|
||||
DrawFrustum::DrawFrustum(const glm::vec3& color) :
|
||||
_color{ color } {
|
||||
_frustumMeshVertices = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ);
|
||||
_frustumMeshStream.addBuffer(_frustumMeshVertices._buffer, _frustumMeshVertices._offset, _frustumMeshVertices._stride);
|
||||
}
|
||||
|
||||
void DrawFrustum::configure(const Config& configuration) {
|
||||
_updateFrustum = !configuration.isFrozen;
|
||||
DrawQuadVolume{ color } {
|
||||
}
|
||||
|
||||
void DrawFrustum::run(const render::RenderContextPointer& renderContext, const Input& input) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_context);
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
if (input) {
|
||||
const auto& frustum = *input;
|
||||
|
||||
static uint8_t indexData[] = { 0, 1, 2, 3, 0, 4, 5, 6, 7, 4, 5, 1, 2, 6, 7, 3 };
|
||||
static const uint8_t indexData[] = {
|
||||
0, 1,
|
||||
1, 2,
|
||||
2, 3,
|
||||
3, 0,
|
||||
0, 2,
|
||||
3, 1,
|
||||
4, 5,
|
||||
5, 6,
|
||||
6, 7,
|
||||
7, 4,
|
||||
4, 6,
|
||||
7, 5,
|
||||
0, 4,
|
||||
1, 5,
|
||||
3, 7,
|
||||
2, 6
|
||||
};
|
||||
|
||||
if (!_frustumMeshIndices._buffer) {
|
||||
auto indices = std::make_shared<gpu::Buffer>(sizeof(indexData), indexData);
|
||||
_frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX));
|
||||
}
|
||||
|
||||
if (!_pipeline) {
|
||||
auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS();
|
||||
auto ps = gpu::StandardShaderLib::getDrawColorPS();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
glm::vec3 vertices[8];
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("color", 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
getVertices(frustum, vertices);
|
||||
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(true, false));
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
if (_updateFrustum) {
|
||||
updateFrustum(frustum);
|
||||
}
|
||||
|
||||
// Render the frustums in wireframe
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setPipeline(_pipeline);
|
||||
batch.setIndexBuffer(_frustumMeshIndices);
|
||||
|
||||
batch._glUniform4f(0, _color.x, _color.y, _color.z, 1.0f);
|
||||
batch.setInputStream(0, _frustumMeshStream);
|
||||
batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U);
|
||||
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
DrawQuadVolume::run(renderContext, vertices, _frustumMeshIndices, sizeof(indexData) / sizeof(indexData[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawFrustum::updateFrustum(const ViewFrustum& frustum) {
|
||||
auto& vertices = _frustumMeshVertices.edit<std::array<glm::vec3, 8U> >();
|
||||
void DrawFrustum::getVertices(const ViewFrustum& frustum, glm::vec3 vertices[8]) {
|
||||
vertices[0] = frustum.getNearTopLeft();
|
||||
vertices[1] = frustum.getNearTopRight();
|
||||
vertices[2] = frustum.getNearBottomRight();
|
||||
|
|
|
@ -70,12 +70,12 @@ private:
|
|||
int _colorLocation { -1 };
|
||||
};
|
||||
|
||||
class DrawFrustumConfig : public render::JobConfig {
|
||||
class DrawQuadVolumeConfig : public render::JobConfig {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isFrozen MEMBER isFrozen NOTIFY dirty)
|
||||
public:
|
||||
|
||||
DrawFrustumConfig(bool enabled = false) : JobConfig(enabled) {}
|
||||
DrawQuadVolumeConfig(bool enabled = false) : JobConfig(enabled) {}
|
||||
|
||||
bool isFrozen{ false };
|
||||
signals:
|
||||
|
@ -83,30 +83,58 @@ signals:
|
|||
|
||||
};
|
||||
|
||||
class DrawFrustum {
|
||||
class DrawQuadVolume {
|
||||
public:
|
||||
|
||||
using Config = DrawQuadVolumeConfig;
|
||||
|
||||
void configure(const Config& configuration);
|
||||
|
||||
protected:
|
||||
DrawQuadVolume(const glm::vec3& color);
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const glm::vec3 vertices[8],
|
||||
const gpu::BufferView& indices, int indexCount);
|
||||
|
||||
gpu::BufferView _meshVertices;
|
||||
gpu::BufferStream _meshStream;
|
||||
glm::vec3 _color;
|
||||
bool _isUpdateEnabled{ true };
|
||||
|
||||
static gpu::PipelinePointer getPipeline();
|
||||
};
|
||||
|
||||
class DrawAABox : public DrawQuadVolume {
|
||||
public:
|
||||
using Inputs = AABox;
|
||||
using JobModel = render::Job::ModelI<DrawAABox, Inputs, Config>;
|
||||
|
||||
DrawAABox(const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& box);
|
||||
|
||||
protected:
|
||||
|
||||
static gpu::BufferView _cubeMeshIndices;
|
||||
|
||||
static void getVertices(const AABox& box, glm::vec3 vertices[8]);
|
||||
};
|
||||
|
||||
class DrawFrustum : public DrawQuadVolume {
|
||||
public:
|
||||
using Config = DrawFrustumConfig;
|
||||
using Input = ViewFrustumPointer;
|
||||
using JobModel = render::Job::ModelI<DrawFrustum, Input, Config>;
|
||||
|
||||
DrawFrustum(const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
void configure(const Config& configuration);
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input);
|
||||
|
||||
private:
|
||||
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
static gpu::BufferView _frustumMeshIndices;
|
||||
|
||||
bool _updateFrustum{ true };
|
||||
gpu::BufferView _frustumMeshVertices;
|
||||
gpu::BufferStream _frustumMeshStream;
|
||||
glm::vec3 _color;
|
||||
|
||||
void updateFrustum(const ViewFrustum& frustum);
|
||||
static void getVertices(const ViewFrustum& frustum, glm::vec3 vertices[8]);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // hifi_render_DrawTask_h
|
||||
|
|
|
@ -422,7 +422,7 @@ int clipTriangleWithPlanes(const Triangle& triangle, const Plane* planes, int pl
|
|||
|
||||
*clippedTriangles = triangle;
|
||||
|
||||
while (planes < planesEnd) {
|
||||
while (planes < planesEnd && triangleCount) {
|
||||
int clippedSubTriangleCount;
|
||||
|
||||
trianglesToTest.clear();
|
||||
|
|
|
@ -15,15 +15,24 @@ Column {
|
|||
id: root
|
||||
spacing: 8
|
||||
property var viewConfig: Render.getConfig("RenderMainView.DrawViewFrustum");
|
||||
property var shadowConfig: Render.getConfig("RenderMainView.DrawShadowFrustum");
|
||||
property var shadow0Config: Render.getConfig("RenderMainView.DrawShadowFrustum0");
|
||||
property var shadow1Config: Render.getConfig("RenderMainView.DrawShadowFrustum1");
|
||||
property var shadow2Config: Render.getConfig("RenderMainView.DrawShadowFrustum2");
|
||||
property var shadow3Config: Render.getConfig("RenderMainView.DrawShadowFrustum3");
|
||||
|
||||
Component.onCompleted: {
|
||||
viewConfig.enabled = true;
|
||||
shadowConfig.enabled = true;
|
||||
shadow0Config.enabled = true;
|
||||
shadow1Config.enabled = true;
|
||||
shadow2Config.enabled = true;
|
||||
shadow3Config.enabled = true;
|
||||
}
|
||||
Component.onDestruction: {
|
||||
viewConfig.enabled = false;
|
||||
shadowConfig.enabled = false;
|
||||
shadow0Config.enabled = false;
|
||||
shadow1Config.enabled = false;
|
||||
shadow2Config.enabled = false;
|
||||
shadow3Config.enabled = false;
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
|
@ -31,7 +40,14 @@ Column {
|
|||
checked: false
|
||||
onCheckedChanged: {
|
||||
viewConfig.isFrozen = checked;
|
||||
shadowConfig.isFrozen = checked;
|
||||
shadow0Config.isFrozen = checked;
|
||||
shadow1Config.isFrozen = checked;
|
||||
shadow2Config.isFrozen = checked;
|
||||
shadow3Config.isFrozen = checked;
|
||||
shadow0BoundConfig.isFrozen = checked;
|
||||
shadow1BoundConfig.isFrozen = checked;
|
||||
shadow2BoundConfig.isFrozen = checked;
|
||||
shadow3BoundConfig.isFrozen = checked;
|
||||
}
|
||||
}
|
||||
Row {
|
||||
|
@ -46,5 +62,10 @@ Column {
|
|||
color: "blue"
|
||||
font.italic: true
|
||||
}
|
||||
Label {
|
||||
text: "Items"
|
||||
color: "magenta"
|
||||
font.italic: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue