mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 22:55:06 +02:00
261 lines
8.7 KiB
C++
261 lines
8.7 KiB
C++
//
|
|
// GameWorkloadRender.cpp
|
|
//
|
|
// Created by Sam Gateau on 2/20/2018.
|
|
// 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 "GameWorkloadRenderer.h"
|
|
|
|
#include <cstring>
|
|
#include <gpu/Context.h>
|
|
|
|
#include <StencilMaskPass.h>
|
|
#include <GeometryCache.h>
|
|
|
|
#include <gpu/DrawWhite_frag.h>
|
|
#include "render-utils/drawWorkloadProxy_vert.h"
|
|
#include "render-utils/drawWorkloadView_vert.h"
|
|
#include "render-utils/drawWorkloadProxy_frag.h"
|
|
#include "render-utils/drawWorkloadView_frag.h"
|
|
|
|
|
|
void GameSpaceToRender::configure(const Config& config) {
|
|
_freezeViews = config.freezeViews;
|
|
_showAllProxies = config.showProxies;
|
|
_showAllViews = config.showViews;
|
|
}
|
|
|
|
void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) {
|
|
auto gameWorkloadContext = std::dynamic_pointer_cast<GameWorkloadContext>(runContext);
|
|
if (!gameWorkloadContext) {
|
|
return;
|
|
}
|
|
auto space = gameWorkloadContext->_space;
|
|
if (!space) {
|
|
return;
|
|
}
|
|
|
|
auto visible = _showAllProxies || _showAllViews;
|
|
auto showProxies = _showAllProxies;
|
|
auto showViews = _showAllViews;
|
|
auto freezeViews = _freezeViews;
|
|
|
|
render::Transaction transaction;
|
|
auto scene = gameWorkloadContext->_scene;
|
|
|
|
// Nothing really needed, early exit
|
|
if (!visible) {
|
|
if (render::Item::isValidID(_spaceRenderItemID)) {
|
|
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [](GameWorkloadRenderItem& item) {
|
|
item.setVisible(false);
|
|
});
|
|
scene->enqueueTransaction(transaction);
|
|
}
|
|
return;
|
|
}
|
|
|
|
std::vector<workload::Space::Proxy> proxies(space->getNumAllocatedProxies());
|
|
space->copyProxyValues(proxies.data(), (uint32_t)proxies.size());
|
|
|
|
workload::Views views(space->getNumViews());
|
|
space->copyViews(views);
|
|
|
|
// Valid space, let's display its content
|
|
if (!render::Item::isValidID(_spaceRenderItemID)) {
|
|
_spaceRenderItemID = scene->allocateID();
|
|
auto renderItem = std::make_shared<GameWorkloadRenderItem>();
|
|
renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f);
|
|
renderItem->setAllProxies(proxies);
|
|
transaction.resetItem(_spaceRenderItemID, std::make_shared<GameWorkloadRenderItem::Payload>(renderItem));
|
|
}
|
|
|
|
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [visible, showProxies, proxies, freezeViews, showViews, views](GameWorkloadRenderItem& item) {
|
|
item.setVisible(visible);
|
|
item.showProxies(showProxies);
|
|
item.setAllProxies(proxies);
|
|
item.showViews(showViews);
|
|
item.setAllViews(views);
|
|
});
|
|
|
|
scene->enqueueTransaction(transaction);
|
|
}
|
|
|
|
namespace render {
|
|
template <> const ItemKey payloadGetKey(const GameWorkloadRenderItem::Pointer& payload) {
|
|
return payload->getKey();
|
|
}
|
|
template <> const Item::Bound payloadGetBound(const GameWorkloadRenderItem::Pointer& payload) {
|
|
if (payload) {
|
|
return payload->getBound();
|
|
}
|
|
return Item::Bound();
|
|
}
|
|
template <> void payloadRender(const GameWorkloadRenderItem::Pointer& payload, RenderArgs* args) {
|
|
if (payload) {
|
|
payload->render(args);
|
|
}
|
|
}
|
|
template <> const ShapeKey shapeGetShapeKey(const GameWorkloadRenderItem::Pointer& payload) {
|
|
return ShapeKey::Builder::ownPipeline();
|
|
}
|
|
template <> int payloadGetLayer(const GameWorkloadRenderItem::Pointer& payloadData) {
|
|
return render::Item::LAYER_3D_FRONT;
|
|
}
|
|
|
|
}
|
|
|
|
GameWorkloadRenderItem::GameWorkloadRenderItem() : _key(render::ItemKey::Builder::opaqueShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1)) {
|
|
}
|
|
|
|
render::ItemKey GameWorkloadRenderItem::getKey() const {
|
|
return _key;
|
|
}
|
|
|
|
void GameWorkloadRenderItem::setVisible(bool isVisible) {
|
|
if (isVisible) {
|
|
_key = render::ItemKey::Builder(_key).withVisible();
|
|
} else {
|
|
_key = render::ItemKey::Builder(_key).withInvisible();
|
|
}
|
|
}
|
|
|
|
void GameWorkloadRenderItem::showProxies(bool show) {
|
|
_showProxies = show;
|
|
}
|
|
|
|
void GameWorkloadRenderItem::showViews(bool show) {
|
|
_showViews = show;
|
|
}
|
|
|
|
|
|
void GameWorkloadRenderItem::setAllProxies(const std::vector<workload::Space::Proxy>& proxies) {
|
|
_myOwnProxies = proxies;
|
|
static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy);
|
|
if (!_allProxiesBuffer) {
|
|
_allProxiesBuffer = std::make_shared<gpu::Buffer>(sizeOfProxy);
|
|
}
|
|
|
|
_allProxiesBuffer->setData(proxies.size() * sizeOfProxy, (const gpu::Byte*) proxies.data());
|
|
_numAllProxies = (uint32_t) proxies.size();
|
|
}
|
|
|
|
void GameWorkloadRenderItem::setAllViews(const workload::Views& views) {
|
|
_myOwnViews = views;
|
|
static const uint32_t sizeOfView = sizeof(workload::View);
|
|
if (!_allViewsBuffer) {
|
|
_allViewsBuffer = std::make_shared<gpu::Buffer>(sizeOfView);
|
|
}
|
|
|
|
_allViewsBuffer->setData(views.size() * sizeOfView, (const gpu::Byte*) views.data());
|
|
_numAllViews = (uint32_t)views.size();
|
|
}
|
|
|
|
const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
|
if (!_drawAllProxiesPipeline) {
|
|
auto vs = drawWorkloadProxy_vert::getShader();
|
|
auto ps = drawWorkloadProxy_frag::getShader();
|
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
|
|
gpu::Shader::BindingSet slotBindings;
|
|
slotBindings.insert(gpu::Shader::Binding("workloadProxiesBuffer", 0));
|
|
gpu::Shader::makeProgram(*program, slotBindings);
|
|
|
|
auto state = std::make_shared<gpu::State>();
|
|
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
|
/* state->setBlendFunction(true,
|
|
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
|
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/
|
|
|
|
PrepareStencil::testMaskDrawShape(*state);
|
|
state->setCullMode(gpu::State::CULL_NONE);
|
|
_drawAllProxiesPipeline = gpu::Pipeline::create(program, state);
|
|
}
|
|
return _drawAllProxiesPipeline;
|
|
}
|
|
|
|
|
|
const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
|
|
if (!_drawAllViewsPipeline) {
|
|
auto vs = drawWorkloadView_vert::getShader();
|
|
auto ps = drawWorkloadView_frag::getShader();
|
|
// auto ps = DrawWhite_frag::getShader();
|
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
|
|
gpu::Shader::BindingSet slotBindings;
|
|
slotBindings.insert(gpu::Shader::Binding("workloadViewsBuffer", 1));
|
|
slotBindings.insert(gpu::Shader::Binding("drawMeshBuffer", 0));
|
|
gpu::Shader::makeProgram(*program, slotBindings);
|
|
|
|
auto state = std::make_shared<gpu::State>();
|
|
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
|
/* state->setBlendFunction(true,
|
|
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
|
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/
|
|
|
|
PrepareStencil::testMaskDrawShape(*state);
|
|
state->setCullMode(gpu::State::CULL_NONE);
|
|
_drawAllViewsPipeline = gpu::Pipeline::create(program, state);
|
|
}
|
|
return _drawAllViewsPipeline;
|
|
}
|
|
|
|
const gpu::BufferPointer GameWorkloadRenderItem::getDrawViewBuffer() {
|
|
if (!_drawViewBuffer) {
|
|
int numSegments = 64;
|
|
float angleStep = M_PI * 2.0 / (float)numSegments;
|
|
|
|
struct Vert {
|
|
glm::vec4 p;
|
|
};
|
|
std::vector<Vert> verts(numSegments + 1);
|
|
for (int i = 0; i < numSegments; i++) {
|
|
float angle = (float)i * angleStep;
|
|
verts[i].p.x = cos(angle);
|
|
verts[i].p.y = sin(angle);
|
|
verts[i].p.z = angle;
|
|
verts[i].p.w = 1.0;
|
|
}
|
|
verts[numSegments] = verts[0];
|
|
verts[numSegments].p.w = 0.0;
|
|
|
|
_drawViewBuffer = std::make_shared<gpu::Buffer>(verts.size() * sizeof(Vert), (const gpu::Byte*) verts.data());
|
|
_numDrawViewVerts = numSegments + 1;
|
|
}
|
|
return _drawViewBuffer;
|
|
}
|
|
|
|
void GameWorkloadRenderItem::render(RenderArgs* args) {
|
|
gpu::Batch& batch = *(args->_batch);
|
|
|
|
batch.setModelTransform(Transform());
|
|
|
|
batch.setResourceBuffer(0, _allProxiesBuffer);
|
|
batch.setResourceBuffer(1, _allViewsBuffer);
|
|
|
|
// Show Proxies
|
|
if (_showProxies) {
|
|
batch.setPipeline(getProxiesPipeline());
|
|
|
|
static const int NUM_VERTICES_PER_PROXY = 3;
|
|
batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_PROXY * _numAllProxies, 0);
|
|
}
|
|
|
|
// Show Views
|
|
if (_showViews) {
|
|
batch.setPipeline(getViewsPipeline());
|
|
|
|
batch.setUniformBuffer(0, getDrawViewBuffer());
|
|
batch.draw(gpu::TRIANGLE_STRIP, _numDrawViewVerts * 3 * 2, 0);
|
|
|
|
}
|
|
|
|
batch.setResourceBuffer(0, nullptr);
|
|
batch.setResourceBuffer(1, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|