mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Add RenderShadowTask
This commit is contained in:
parent
7744b89ba5
commit
c704a8d8c5
3 changed files with 170 additions and 0 deletions
128
libraries/render-utils/src/RenderShadowTask.cpp
Normal file
128
libraries/render-utils/src/RenderShadowTask.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
//
|
||||
// RenderShadowTask.cpp
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Zach Pomerantz on 1/7/2016.
|
||||
// Copyright 2016 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/Context.h>
|
||||
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
#include "DeferredLightingEffect.h"
|
||||
#include "FramebufferCache.h"
|
||||
|
||||
#include "RenderShadowTask.h"
|
||||
|
||||
#include "model_shadow_vert.h"
|
||||
#include "skin_model_shadow_vert.h"
|
||||
|
||||
#include "model_shadow_frag.h"
|
||||
#include "skin_model_shadow_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
|
||||
const render::ItemIDsBounds& inItems) {
|
||||
assert(renderContext->getArgs());
|
||||
assert(renderContext->getArgs()->_viewFrustum);
|
||||
|
||||
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
const auto globalLight = lightStage.lights[0];
|
||||
const auto& shadow = globalLight->shadow;
|
||||
const auto& fbo = shadow.framebuffer;
|
||||
|
||||
RenderArgs* args = renderContext->getArgs();
|
||||
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
glm::ivec4 viewport{0, 0, fbo->getWidth(), fbo->getHeight()};
|
||||
batch.setViewportTransform(viewport);
|
||||
batch.setStateScissorRect(viewport);
|
||||
|
||||
batch.setFramebuffer(fbo);
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH,
|
||||
vec4(vec3(1.0, 1.0, 1.0), 1.0), 1.0, 0, true);
|
||||
|
||||
batch.setProjectionTransform(shadow.getProjection());
|
||||
batch.setViewTransform(shadow.getView());
|
||||
|
||||
renderShapes(sceneContext, renderContext, _shapePlumber, inItems);
|
||||
args->_batch = nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
RenderShadowTask::RenderShadowTask() : Task() {
|
||||
// Prepare the ShapePipeline
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
{
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
||||
auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert));
|
||||
auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag));
|
||||
gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withoutSkinned(),
|
||||
modelProgram, state);
|
||||
|
||||
auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert));
|
||||
auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag));
|
||||
gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel);
|
||||
shapePlumber->addPipeline(
|
||||
ShapeKey::Filter::Builder().withSkinned(),
|
||||
skinProgram, state);
|
||||
}
|
||||
|
||||
// CPU: Fetch shadow-casting opaques
|
||||
addJob<FetchItems>("FetchShadowMap");
|
||||
|
||||
// CPU: Cull against KeyLight frustum (nearby viewing camera)
|
||||
addJob<CullItems<RenderDetails::SHADOW_ITEM>>("CullShadowMap", _jobs.back().getOutput());
|
||||
|
||||
// CPU: Sort front to back
|
||||
addJob<DepthSortItems>("DepthSortShadowMap", _jobs.back().getOutput());
|
||||
|
||||
// GPU: Render to shadow map
|
||||
addJob<RenderShadowMap>("RenderShadowMap", _jobs.back().getOutput(), shapePlumber);
|
||||
}
|
||||
|
||||
void RenderShadowTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(sceneContext);
|
||||
RenderArgs* args = renderContext->getArgs();
|
||||
|
||||
// sanity checks
|
||||
if (!sceneContext->_scene || !args) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: If we're not using the global keylight, bail
|
||||
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
|
||||
const auto globalLight = lightStage.lights[0];
|
||||
|
||||
// If the global light is not set, bail
|
||||
if (!globalLight) {
|
||||
return;
|
||||
}
|
||||
|
||||
ViewFrustum* viewFrustum = args->_viewFrustum;
|
||||
|
||||
const auto nearClip = viewFrustum->getNearClip();
|
||||
globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip - 1, nearClip + 20);
|
||||
|
||||
// Set the keylight frustum
|
||||
args->_viewFrustum = globalLight->shadow.getFrustum().get();
|
||||
|
||||
for (auto job : _jobs) {
|
||||
job.run(sceneContext, renderContext);
|
||||
}
|
||||
|
||||
// Reset the view frustum
|
||||
args->_viewFrustum = viewFrustum;
|
||||
};
|
41
libraries/render-utils/src/RenderShadowTask.h
Normal file
41
libraries/render-utils/src/RenderShadowTask.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// RenderShadowTask.h
|
||||
// render-utils/src/
|
||||
//
|
||||
// Created by Zach Pomerantz on 1/7/2016.
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderShadowTask_h
|
||||
#define hifi_RenderShadowTask_h
|
||||
|
||||
#include <gpu/Framebuffer.h>
|
||||
#include <gpu/Pipeline.h>
|
||||
|
||||
#include <render/Scene.h>
|
||||
#include <render/DrawTask.h>
|
||||
|
||||
class ViewFrustum;
|
||||
|
||||
class RenderShadowMap {
|
||||
public:
|
||||
RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {}
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
|
||||
const render::ItemIDsBounds& inItems);
|
||||
|
||||
using JobModel = render::Task::Job::ModelI<RenderShadowMap, render::ItemIDsBounds>;
|
||||
protected:
|
||||
render::ShapePlumberPointer _shapePlumber;
|
||||
};
|
||||
|
||||
class RenderShadowTask : public render::Task {
|
||||
public:
|
||||
RenderShadowTask();
|
||||
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderShadowTask_h
|
|
@ -28,6 +28,7 @@ void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPo
|
|||
class FetchItems {
|
||||
public:
|
||||
typedef std::function<void (const RenderContextPointer& context, int count)> ProbeNumItems;
|
||||
FetchItems() {}
|
||||
FetchItems(const ProbeNumItems& probe): _probeNumItems(probe) {}
|
||||
FetchItems(const ItemFilter& filter, const ProbeNumItems& probe): _filter(filter), _probeNumItems(probe) {}
|
||||
|
||||
|
|
Loading…
Reference in a new issue