mirror of
https://github.com/overte-org/overte.git
synced 2025-08-17 16:47:17 +02:00
Added project rect and scissor test. Need to increase bounds to take into account blur width
This commit is contained in:
parent
f63b4a64b0
commit
f890c5bb8c
4 changed files with 112 additions and 35 deletions
|
@ -11,6 +11,9 @@
|
|||
#include "OutlineEffect.h"
|
||||
|
||||
#include "GeometryCache.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
|
||||
#include "CubeProjectedPolygon.h"
|
||||
|
||||
#include <render/FilterTask.h>
|
||||
#include <render/SortTask.h>
|
||||
|
@ -99,8 +102,13 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con
|
|||
|
||||
RenderArgs* args = renderContext->args;
|
||||
ShapeKey::Builder defaultKeyBuilder;
|
||||
auto framebufferSize = ressources->getSourceFrameSize();
|
||||
|
||||
outputs = args->_viewport;
|
||||
// First thing we do is determine the projected bounding rect of all the outlined items
|
||||
auto outlinedRect = computeOutlineRect(inShapes, args->getViewFrustum(), framebufferSize);
|
||||
qCDebug(renderutils) << "Outline rect is " << outlinedRect.x << ' ' << outlinedRect.y << ' ' << outlinedRect.z << ' ' << outlinedRect.w;
|
||||
|
||||
outputs = outlinedRect;
|
||||
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
@ -108,18 +116,17 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con
|
|||
auto maskPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder);
|
||||
auto maskSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned());
|
||||
|
||||
batch.setFramebuffer(ressources->getDepthFramebuffer());
|
||||
batch.clearDepthFramebuffer(1.0f);
|
||||
|
||||
// Setup camera, projection and viewport for all items
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
|
||||
batch.setStateScissorRect(outlinedRect);
|
||||
batch.setFramebuffer(ressources->getDepthFramebuffer());
|
||||
batch.clearDepthFramebuffer(1.0f, true);
|
||||
|
||||
// Setup camera, projection and viewport for all items
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
|
@ -152,6 +159,49 @@ void DrawOutlineMask::run(const render::RenderContextPointer& renderContext, con
|
|||
}
|
||||
}
|
||||
|
||||
glm::ivec4 DrawOutlineMask::computeOutlineRect(const render::ShapeBounds& shapes,
|
||||
const ViewFrustum& viewFrustum, glm::ivec2 frameSize) {
|
||||
glm::vec4 minMaxBounds{
|
||||
std::numeric_limits<float>::max(),
|
||||
std::numeric_limits<float>::max(),
|
||||
-std::numeric_limits<float>::max(),
|
||||
-std::numeric_limits<float>::max(),
|
||||
};
|
||||
|
||||
for (const auto& keyShapes : shapes) {
|
||||
const auto& items = keyShapes.second;
|
||||
|
||||
for (const auto& item : items) {
|
||||
const auto& aabb = item.bound;
|
||||
const auto projectedCube = viewFrustum.getProjectedPolygon(aabb);
|
||||
|
||||
if (projectedCube.getAnyInView()) {
|
||||
minMaxBounds.x = std::min(minMaxBounds.x, projectedCube.getMinX());
|
||||
minMaxBounds.y = std::min(minMaxBounds.y, projectedCube.getMinY());
|
||||
minMaxBounds.z = std::max(minMaxBounds.z, projectedCube.getMaxX());
|
||||
minMaxBounds.w = std::max(minMaxBounds.w, projectedCube.getMaxY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minMaxBounds.x != std::numeric_limits<float>::max()) {
|
||||
const glm::vec2 halfFrameSize{ frameSize.x*0.5f, frameSize.y*0.5f };
|
||||
glm::ivec4 rect;
|
||||
|
||||
minMaxBounds += 1.0f;
|
||||
rect.x = glm::clamp((int)floorf(minMaxBounds.x * halfFrameSize.x), 0, frameSize.x);
|
||||
rect.y = glm::clamp((int)floorf(minMaxBounds.y * halfFrameSize.y), 0, frameSize.y);
|
||||
rect.z = glm::clamp((int)ceilf(minMaxBounds.z * halfFrameSize.x), 0, frameSize.x);
|
||||
rect.w = glm::clamp((int)ceilf(minMaxBounds.w * halfFrameSize.y), 0, frameSize.y);
|
||||
|
||||
rect.z -= rect.x;
|
||||
rect.w -= rect.y;
|
||||
return rect;
|
||||
} else {
|
||||
return glm::ivec4(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DrawOutline::_pipeline;
|
||||
gpu::PipelinePointer DrawOutline::_pipelineFilled;
|
||||
|
||||
|
@ -203,6 +253,7 @@ void DrawOutline::run(const render::RenderContextPointer& renderContext, const I
|
|||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(destinationFrameBuffer);
|
||||
|
||||
batch.setStateScissorRect(outlineRect);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.resetViewTransform();
|
||||
|
@ -235,6 +286,7 @@ const gpu::PipelinePointer& DrawOutline::getPipeline() {
|
|||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(gpu::State::DepthTest(false, false));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
state->setScissorEnable(true);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
ps = gpu::Shader::createPixel(std::string(Outline_filled_frag));
|
||||
|
@ -261,7 +313,8 @@ void DebugOutline::configure(const Config& config) {
|
|||
}
|
||||
|
||||
void DebugOutline::run(const render::RenderContextPointer& renderContext, const Inputs& input) {
|
||||
const auto outlineRessources = input;
|
||||
const auto outlineRessources = input.get0();
|
||||
const auto outlineRect = input.get1();
|
||||
|
||||
if (_isDisplayEnabled && outlineRessources) {
|
||||
assert(renderContext->args);
|
||||
|
@ -271,6 +324,7 @@ void DebugOutline::run(const render::RenderContextPointer& renderContext, const
|
|||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(outlineRect);
|
||||
|
||||
const auto geometryBuffer = DependencyManager::get<GeometryCache>();
|
||||
|
||||
|
@ -305,6 +359,7 @@ void DebugOutline::initializePipelines() {
|
|||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setScissorEnable(true);
|
||||
|
||||
const auto vs = gpu::Shader::createVertex(VERTEX_SHADER);
|
||||
|
||||
|
@ -360,16 +415,18 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
|
|||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS);
|
||||
state->setColorWriteMask(false, false, false, false);
|
||||
state->setScissorEnable(true);
|
||||
initMaskPipelines(*shapePlumber, state);
|
||||
}
|
||||
|
||||
// Prepare for outline group rendering.
|
||||
const auto outlineRessources = task.addJob<PrepareDrawOutline>("PrepareOutline", primaryFramebuffer);
|
||||
render::Varying outline0Rect;
|
||||
|
||||
for (auto i = 0; i < render::Scene::MAX_OUTLINE_COUNT; i++) {
|
||||
const auto groupItems = groups[i];
|
||||
const auto outlinedItemIDs = task.addJob<render::MetaToSubItems>("OutlineMetaToSubItemIDs", groupItems);
|
||||
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs, true);
|
||||
const auto outlinedItems = task.addJob<render::IDsToBounds>("OutlineMetaToSubItems", outlinedItemIDs);
|
||||
|
||||
// Sort
|
||||
const auto sortedPipelines = task.addJob<render::PipelineSortShapes>("OutlinePipelineSort", outlinedItems);
|
||||
|
@ -384,6 +441,9 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
|
|||
}
|
||||
const auto drawMaskInputs = DrawOutlineMask::Inputs(sortedBounds, outlineRessources).asVarying();
|
||||
const auto outlinedRect = task.addJob<DrawOutlineMask>(name, drawMaskInputs, shapePlumber);
|
||||
if (i == 0) {
|
||||
outline0Rect = outlinedRect;
|
||||
}
|
||||
|
||||
// Draw outline
|
||||
{
|
||||
|
@ -396,7 +456,8 @@ void DrawOutlineTask::build(JobModel& task, const render::Varying& inputs, rende
|
|||
}
|
||||
|
||||
// Debug outline
|
||||
task.addJob<DebugOutline>("OutlineDebug", outlineRessources);
|
||||
const auto debugInputs = DebugOutline::Inputs(outlineRessources, const_cast<const render::Varying&>(outline0Rect)).asVarying();
|
||||
task.addJob<DebugOutline>("OutlineDebug", debugInputs);
|
||||
}
|
||||
|
||||
#include "model_shadow_vert.h"
|
||||
|
|
|
@ -72,6 +72,8 @@ public:
|
|||
protected:
|
||||
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
|
||||
static glm::ivec4 computeOutlineRect(const render::ShapeBounds& shapes, const ViewFrustum& viewFrustum, glm::ivec2 frameSize);
|
||||
};
|
||||
|
||||
class DrawOutlineConfig : public render::Job::Config {
|
||||
|
@ -158,7 +160,7 @@ signals:
|
|||
|
||||
class DebugOutline {
|
||||
public:
|
||||
using Inputs = OutlineRessourcesPointer;
|
||||
using Inputs = render::VaryingSet2<OutlineRessourcesPointer, glm::ivec4>;
|
||||
using Config = DebugOutlineConfig;
|
||||
using JobModel = render::Job::ModelI<DebugOutline, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -504,16 +504,17 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT
|
|||
{6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left
|
||||
};
|
||||
|
||||
CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
||||
template <typename TBOX>
|
||||
CubeProjectedPolygon ViewFrustum::computeProjectedPolygon(const TBOX& box) const {
|
||||
const glm::vec3& bottomNearRight = box.getCorner();
|
||||
glm::vec3 topFarLeft = box.calcTopFarLeft();
|
||||
|
||||
int lookUp = ((_position.x < bottomNearRight.x) ) // 1 = right | compute 6-bit
|
||||
+ ((_position.x > topFarLeft.x ) << 1) // 2 = left | code to
|
||||
+ ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera
|
||||
+ ((_position.y > topFarLeft.y ) << 3) // 8 = top | with respect to
|
||||
+ ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining
|
||||
+ ((_position.z > topFarLeft.z ) << 5); // 32 = back/far | planes
|
||||
int lookUp = ((_position.x < bottomNearRight.x)) // 1 = right | compute 6-bit
|
||||
+ ((_position.x > topFarLeft.x) << 1) // 2 = left | code to
|
||||
+ ((_position.y < bottomNearRight.y) << 2) // 4 = bottom | classify camera
|
||||
+ ((_position.y > topFarLeft.y) << 3) // 8 = top | with respect to
|
||||
+ ((_position.z < bottomNearRight.z) << 4) // 16 = front/near | the 6 defining
|
||||
+ ((_position.z > topFarLeft.z) << 5); // 32 = back/far | planes
|
||||
|
||||
int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
|
||||
|
||||
|
@ -524,8 +525,8 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
|||
bool anyPointsInView = false; // assume the worst!
|
||||
if (vertexCount) {
|
||||
allPointsInView = true; // assume the best!
|
||||
for(int i = 0; i < vertexCount; i++) {
|
||||
int vertexNum = hullVertexLookup[lookUp][i+1];
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
int vertexNum = hullVertexLookup[lookUp][i + 1];
|
||||
glm::vec3 point = box.getVertex((BoxVertex)vertexNum);
|
||||
glm::vec2 projectedPoint = projectPoint(point, pointInView);
|
||||
allPointsInView = allPointsInView && pointInView;
|
||||
|
@ -538,24 +539,24 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
|||
// NOTE: This clipping does not improve our overall performance. It basically causes more polygons to
|
||||
// end up in the same quad/half and so the polygon lists get longer, and that's more calls to polygon.occludes()
|
||||
if ( (projectedPolygon.getMaxX() > PolygonClip::RIGHT_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) {
|
||||
(projectedPolygon.getMaxY() > PolygonClip::TOP_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxX() < PolygonClip::LEFT_OF_CLIPPING_WINDOW ) ||
|
||||
(projectedPolygon.getMaxY() < PolygonClip::BOTTOM_OF_CLIPPING_WINDOW) ) {
|
||||
|
||||
CoverageRegion::_clippedPolygons++;
|
||||
CoverageRegion::_clippedPolygons++;
|
||||
|
||||
glm::vec2* clippedVertices;
|
||||
int clippedVertexCount;
|
||||
PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount);
|
||||
glm::vec2* clippedVertices;
|
||||
int clippedVertexCount;
|
||||
PolygonClip::clipToScreen(projectedPolygon.getVertices(), vertexCount, clippedVertices, clippedVertexCount);
|
||||
|
||||
// Now reset the vertices of our projectedPolygon object
|
||||
projectedPolygon.setVertexCount(clippedVertexCount);
|
||||
for(int i = 0; i < clippedVertexCount; i++) {
|
||||
projectedPolygon.setVertex(i, clippedVertices[i]);
|
||||
}
|
||||
delete[] clippedVertices;
|
||||
// Now reset the vertices of our projectedPolygon object
|
||||
projectedPolygon.setVertexCount(clippedVertexCount);
|
||||
for(int i = 0; i < clippedVertexCount; i++) {
|
||||
projectedPolygon.setVertex(i, clippedVertices[i]);
|
||||
}
|
||||
delete[] clippedVertices;
|
||||
|
||||
lookUp += PROJECTION_CLIPPED;
|
||||
lookUp += PROJECTION_CLIPPED;
|
||||
}
|
||||
***/
|
||||
}
|
||||
|
@ -568,6 +569,14 @@ CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
|||
return projectedPolygon;
|
||||
}
|
||||
|
||||
CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
|
||||
return computeProjectedPolygon(box);
|
||||
}
|
||||
|
||||
CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AABox& box) const {
|
||||
return computeProjectedPolygon(box);
|
||||
}
|
||||
|
||||
// Similar strategy to getProjectedPolygon() we use the knowledge of camera position relative to the
|
||||
// axis-aligned voxels to determine which of the voxels vertices must be the furthest. No need for
|
||||
// squares and square-roots. Just compares.
|
||||
|
|
|
@ -119,6 +119,7 @@ public:
|
|||
|
||||
glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
|
||||
CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
|
||||
CubeProjectedPolygon getProjectedPolygon(const AABox& box) const;
|
||||
void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
|
||||
|
||||
float distanceToCamera(const glm::vec3& point) const;
|
||||
|
@ -169,6 +170,10 @@ private:
|
|||
|
||||
// Used to project points
|
||||
glm::mat4 _ourModelViewProjectionMatrix;
|
||||
|
||||
template <typename TBOX>
|
||||
CubeProjectedPolygon computeProjectedPolygon(const TBOX& box) const;
|
||||
|
||||
};
|
||||
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
|
||||
|
||||
|
|
Loading…
Reference in a new issue