mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #5962 from samcake/calvin
Rendering the background elements after opaque and only work on the far pixels
This commit is contained in:
commit
4c556dd43a
23 changed files with 435 additions and 120 deletions
|
@ -141,6 +141,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
|
@ -152,6 +153,7 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
|
|||
auto state = gpu::StatePointer(new gpu::State());
|
||||
// enable decal blend
|
||||
state->setDepthTest(gpu::State::DepthTest(false));
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setAntialiasedLineEnable(true); // line smoothing also smooth points
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_starsPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
|
|
28
libraries/gpu/src/gpu/DrawUnitQuadTexcoord.slv
Normal file
28
libraries/gpu/src/gpu/DrawUnitQuadTexcoord.slv
Normal file
|
@ -0,0 +1,28 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// Draw the unit quad [-1,-1 -> 1,1] amd pass along the unit texcoords [0, 0 -> 1, 1]. Not transform used.
|
||||
// Simply draw a Triangle_strip of 2 triangles, no input buffers or index buffer needed
|
||||
//
|
||||
// Created by Sam Gateau on 6/22/2015
|
||||
// Copyright 2015 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
|
||||
//
|
||||
out vec2 varTexCoord0;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_QUAD[4] = vec4[4](
|
||||
vec4(-1.0, -1.0, 0.0, 1.0),
|
||||
vec4(1.0, -1.0, 0.0, 1.0),
|
||||
vec4(-1.0, 1.0, 0.0, 1.0),
|
||||
vec4(1.0, 1.0, 0.0, 1.0)
|
||||
);
|
||||
vec4 pos = UNIT_QUAD[gl_VertexID];
|
||||
|
||||
varTexCoord0 = (pos.xy + 1) * 0.5;
|
||||
|
||||
gl_Position = pos;
|
||||
}
|
|
@ -247,7 +247,13 @@ bool Framebuffer::setDepthStencilBuffer(const TexturePointer& texture, const For
|
|||
|
||||
_bufferMask = ( _bufferMask & ~BUFFER_DEPTHSTENCIL);
|
||||
if (texture) {
|
||||
_bufferMask |= BUFFER_DEPTHSTENCIL;
|
||||
if (format.getSemantic() == gpu::DEPTH) {
|
||||
_bufferMask |= BUFFER_DEPTH;
|
||||
} else if (format.getSemantic() == gpu::STENCIL) {
|
||||
_bufferMask |= BUFFER_STENCIL;
|
||||
} else if (format.getSemantic() == gpu::DEPTH_STENCIL) {
|
||||
_bufferMask |= BUFFER_DEPTHSTENCIL;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -116,6 +116,8 @@ public:
|
|||
bool isEmpty() const { return (_bufferMask == 0); }
|
||||
bool hasColor() const { return (getBufferMask() & BUFFER_COLORS); }
|
||||
bool hasDepthStencil() const { return (getBufferMask() & BUFFER_DEPTHSTENCIL); }
|
||||
bool hasDepth() const { return (getBufferMask() & BUFFER_DEPTH); }
|
||||
bool hasStencil() const { return (getBufferMask() & BUFFER_STENCIL); }
|
||||
|
||||
bool validateTargetCompatibility(const Texture& texture, uint32 subresource = 0) const;
|
||||
|
||||
|
|
|
@ -132,20 +132,26 @@ void GLBackend::renderPassTransfer(Batch& batch) {
|
|||
const size_t numCommands = batch.getCommands().size();
|
||||
const Batch::Commands::value_type* command = batch.getCommands().data();
|
||||
const Batch::CommandOffsets::value_type* offset = batch.getCommandOffsets().data();
|
||||
|
||||
for (auto& cached : batch._buffers._items) {
|
||||
if (cached._data) {
|
||||
syncGPUObject(*cached._data);
|
||||
|
||||
{ // Sync all the buffers
|
||||
PROFILE_RANGE("syncGPUBuffer");
|
||||
|
||||
for (auto& cached : batch._buffers._items) {
|
||||
if (cached._data) {
|
||||
syncGPUObject(*cached._data);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reset the transform buffers
|
||||
_transform._cameras.resize(0);
|
||||
_transform._cameraOffsets.clear();
|
||||
_transform._objects.resize(0);
|
||||
_transform._objectOffsets.clear();
|
||||
|
||||
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
|
||||
switch (*command) {
|
||||
{ // Sync all the buffers
|
||||
PROFILE_RANGE("syncCPUTransform");
|
||||
_transform._cameras.resize(0);
|
||||
_transform._cameraOffsets.clear();
|
||||
_transform._objects.resize(0);
|
||||
_transform._objectOffsets.clear();
|
||||
|
||||
for (_commandIndex = 0; _commandIndex < numCommands; ++_commandIndex) {
|
||||
switch (*command) {
|
||||
case Batch::COMMAND_draw:
|
||||
case Batch::COMMAND_drawIndexed:
|
||||
case Batch::COMMAND_drawInstanced:
|
||||
|
@ -164,11 +170,16 @@ void GLBackend::renderPassTransfer(Batch& batch) {
|
|||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
command++;
|
||||
offset++;
|
||||
}
|
||||
command++;
|
||||
offset++;
|
||||
}
|
||||
_transform.transfer();
|
||||
|
||||
{ // Sync the transform buffers
|
||||
PROFILE_RANGE("syncGPUTransform");
|
||||
_transform.transfer();
|
||||
}
|
||||
}
|
||||
|
||||
void GLBackend::renderPassDraw(Batch& batch) {
|
||||
|
|
|
@ -100,7 +100,18 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
|
|||
if (surface) {
|
||||
auto gltexture = GLBackend::syncGPUObject(*surface);
|
||||
if (gltexture) {
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gltexture->_texture, 0);
|
||||
GLenum attachement = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||
if (!framebuffer.hasStencil()) {
|
||||
attachement = GL_DEPTH_ATTACHMENT;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0);
|
||||
} else if (!framebuffer.hasDepth()) {
|
||||
attachement = GL_STENCIL_ATTACHMENT;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, attachement, GL_TEXTURE_2D, gltexture->_texture, 0);
|
||||
} else {
|
||||
attachement = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachement, GL_RENDERBUFFER, gltexture->_texture);
|
||||
}
|
||||
(void) CHECK_GL_ERROR();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -642,8 +642,13 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S
|
|||
|
||||
if (activation.isEnabled()) {
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront());
|
||||
glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack());
|
||||
|
||||
if (activation.getWriteMaskFront() != activation.getWriteMaskBack()) {
|
||||
glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront());
|
||||
glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack());
|
||||
} else {
|
||||
glStencilMask(activation.getWriteMaskFront());
|
||||
}
|
||||
|
||||
static GLenum STENCIL_OPS[] = {
|
||||
GL_KEEP,
|
||||
|
@ -655,11 +660,16 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S
|
|||
GL_INCR,
|
||||
GL_DECR };
|
||||
|
||||
glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]);
|
||||
glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask());
|
||||
if (frontTest != backTest) {
|
||||
glStencilOpSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]);
|
||||
glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask());
|
||||
|
||||
glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]);
|
||||
glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask());
|
||||
glStencilOpSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]);
|
||||
glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask());
|
||||
} else {
|
||||
glStencilOp(STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]);
|
||||
glStencilFunc(GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask());
|
||||
}
|
||||
} else {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,9 @@ public:
|
|||
texel.internalFormat = GL_RG;
|
||||
break;
|
||||
case gpu::DEPTH_STENCIL:
|
||||
texel.internalFormat = GL_DEPTH_STENCIL;
|
||||
texel.type = GL_UNSIGNED_BYTE;
|
||||
texel.format = GL_DEPTH_STENCIL;
|
||||
texel.internalFormat = GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
default:
|
||||
qCDebug(gpulogging) << "Unknown combination of texel format";
|
||||
|
@ -197,7 +199,9 @@ public:
|
|||
texel.internalFormat = GL_RG;
|
||||
break;
|
||||
case gpu::DEPTH_STENCIL:
|
||||
texel.internalFormat = GL_DEPTH_STENCIL;
|
||||
texel.type = GL_UNSIGNED_BYTE;
|
||||
texel.format = GL_DEPTH_STENCIL;
|
||||
texel.internalFormat = GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
default:
|
||||
qCDebug(gpulogging) << "Unknown combination of texel format";
|
||||
|
@ -334,22 +338,34 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
|
|||
}
|
||||
|
||||
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
||||
texelFormat.format, texelFormat.type, bytes);
|
||||
|
||||
if (bytes && texture.isAutogenerateMips()) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}/* else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}*/
|
||||
|
||||
object->_target = GL_TEXTURE_2D;
|
||||
auto semantic = texture.getTexelFormat().getSemantic();
|
||||
|
||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||
if (semantic == gpu::DEPTH_STENCIL) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDeleteTextures(1, &object->_texture);
|
||||
|
||||
glGenRenderbuffers(1, &object->_texture);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, object->_texture);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, texture.getWidth(), texture.getHeight());
|
||||
// At this point the mip pixels have been loaded, we can notify
|
||||
texture.notifyMipFaceGPULoaded(0, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
|
||||
texelFormat.format, texelFormat.type, bytes);
|
||||
|
||||
if (bytes && texture.isAutogenerateMips()) {
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
|
||||
object->_target = GL_TEXTURE_2D;
|
||||
|
||||
syncSampler(texture.getSampler(), texture.getType(), object);
|
||||
}
|
||||
|
||||
// At this point the mip pixels have been loaded, we can notify
|
||||
texture.notifyMipFaceGPULoaded(0, 0);
|
||||
|
|
|
@ -130,19 +130,27 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
|
|||
|
||||
void GLBackend::TransformStageState::transfer() const {
|
||||
static QByteArray bufferData;
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer);
|
||||
bufferData.resize(_cameraUboSize * _cameras.size());
|
||||
for (size_t i = 0; i < _cameras.size(); ++i) {
|
||||
memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera));
|
||||
if (!_cameras.empty()) {
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _cameraBuffer);
|
||||
bufferData.resize(_cameraUboSize * _cameras.size());
|
||||
for (size_t i = 0; i < _cameras.size(); ++i) {
|
||||
memcpy(bufferData.data() + (_cameraUboSize * i), &_cameras[i], sizeof(TransformCamera));
|
||||
}
|
||||
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _objectBuffer);
|
||||
bufferData.resize(_objectUboSize * _objects.size());
|
||||
for (size_t i = 0; i < _objects.size(); ++i) {
|
||||
memcpy(bufferData.data() + (_objectUboSize * i), &_objects[i], sizeof(TransformObject));
|
||||
|
||||
if (!_objects.empty()) {
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, _objectBuffer);
|
||||
bufferData.resize(_objectUboSize * _objects.size());
|
||||
for (size_t i = 0; i < _objects.size(); ++i) {
|
||||
memcpy(bufferData.data() + (_objectUboSize * i), &_objects[i], sizeof(TransformObject));
|
||||
}
|
||||
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||
}
|
||||
|
||||
if (!_cameras.empty() || !_objects.empty()) {
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
glBufferData(GL_UNIFORM_BUFFER, bufferData.size(), bufferData.data(), GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
CHECK_GL_ERROR();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//
|
||||
#include "StandardShaderLib.h"
|
||||
|
||||
#include "DrawUnitQuadTexcoord_vert.h"
|
||||
#include "DrawTransformUnitQuad_vert.h"
|
||||
#include "DrawTexcoordRectTransformUnitQuad_vert.h"
|
||||
#include "DrawViewportQuadTransformTexcoord_vert.h"
|
||||
|
@ -21,6 +22,7 @@
|
|||
|
||||
using namespace gpu;
|
||||
|
||||
ShaderPointer StandardShaderLib::_drawUnitQuadTexcoordVS;
|
||||
ShaderPointer StandardShaderLib::_drawTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawTexcoordRectTransformUnitQuadVS;
|
||||
ShaderPointer StandardShaderLib::_drawViewportQuadTransformTexcoordVS;
|
||||
|
@ -55,6 +57,12 @@ ShaderPointer StandardShaderLib::getProgram(GetShader getVS, GetShader getPS) {
|
|||
}
|
||||
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawUnitQuadTexcoordVS() {
|
||||
if (!_drawUnitQuadTexcoordVS) {
|
||||
_drawUnitQuadTexcoordVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(DrawUnitQuadTexcoord_vert)));
|
||||
}
|
||||
return _drawUnitQuadTexcoordVS;
|
||||
}
|
||||
|
||||
ShaderPointer StandardShaderLib::getDrawTransformUnitQuadVS() {
|
||||
if (!_drawTransformUnitQuadVS) {
|
||||
|
|
|
@ -23,6 +23,9 @@ namespace gpu {
|
|||
class StandardShaderLib {
|
||||
public:
|
||||
|
||||
// Shader draws the unit quad in the full viewport clipPos = ([(-1,-1),(1,1)]) and the unit texcoord = [(0,0),(1,1)].
|
||||
static ShaderPointer getDrawUnitQuadTexcoordVS();
|
||||
|
||||
// Shader draw the unit quad objectPos = ([(-1,-1),(1,1)]) and transform it by the full model transform stack (Model, View, Proj).
|
||||
// A texcoord attribute is also generated texcoord = [(0,0),(1,1)]
|
||||
static ShaderPointer getDrawTransformUnitQuadVS();
|
||||
|
@ -44,6 +47,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
static ShaderPointer _drawUnitQuadTexcoordVS;
|
||||
static ShaderPointer _drawTransformUnitQuadVS;
|
||||
static ShaderPointer _drawTexcoordRectTransformUnitQuadVS;
|
||||
static ShaderPointer _drawViewportQuadTransformTexcoordVS;
|
||||
|
|
|
@ -143,11 +143,11 @@ public:
|
|||
static const int PASS_OP_OFFSET = 12;
|
||||
|
||||
uint16 _functionAndOperations;
|
||||
uint8 _reference = 0;
|
||||
int8 _reference = 0;
|
||||
uint8 _readMask = 0xff;
|
||||
public:
|
||||
|
||||
StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) :
|
||||
StencilTest(int8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) :
|
||||
_functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)),
|
||||
_reference(reference), _readMask(readMask)
|
||||
{}
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); }
|
||||
StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); }
|
||||
|
||||
uint8 getReference() const { return _reference; }
|
||||
int8 getReference() const { return _reference; }
|
||||
uint8 getReadMask() const { return _readMask; }
|
||||
|
||||
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
using namespace model;
|
||||
|
||||
Skybox::Skybox() {
|
||||
Data data;
|
||||
_dataBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Data), (const gpu::Byte*) &data));
|
||||
|
||||
/* // PLease create a default engineer skybox
|
||||
_cubemap.reset( gpu::Texture::createCube(gpu::Element::COLOR_RGBA_32, 1));
|
||||
|
@ -36,7 +38,7 @@ Skybox::Skybox() {
|
|||
}
|
||||
|
||||
void Skybox::setColor(const Color& color) {
|
||||
_color = color;
|
||||
_dataBuffer.edit<Data>()._color = color;
|
||||
}
|
||||
|
||||
void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
||||
|
@ -44,12 +46,40 @@ void Skybox::setCubemap(const gpu::TexturePointer& cubemap) {
|
|||
}
|
||||
|
||||
|
||||
void Skybox::updateDataBuffer() const {
|
||||
auto blend = 0.0f;
|
||||
if (getCubemap() && getCubemap()->isDefined()) {
|
||||
blend = 1.0f;
|
||||
// If pitch black neutralize the color
|
||||
if (glm::all(glm::equal(getColor(), glm::vec3(0.0f)))) {
|
||||
blend = 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (blend != _dataBuffer.get<Data>()._blend) {
|
||||
_dataBuffer.edit<Data>()._blend = blend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
||||
updateDataBuffer();
|
||||
Skybox::render(batch, frustum, (*this));
|
||||
}
|
||||
|
||||
|
||||
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
|
||||
// Create the static shared elements used to render the skybox
|
||||
static gpu::BufferPointer theBuffer;
|
||||
static gpu::Stream::FormatPointer theFormat;
|
||||
|
||||
if (skybox.getCubemap()) {
|
||||
if (!theBuffer) {
|
||||
static gpu::BufferPointer theConstants;
|
||||
static gpu::PipelinePointer thePipeline;
|
||||
const int SKYBOX_SKYMAP_SLOT = 0;
|
||||
const int SKYBOX_CONSTANTS_SLOT = 0;
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
{
|
||||
const float CLIP = 1.0f;
|
||||
const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } };
|
||||
theBuffer = std::make_shared<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*) vertices);
|
||||
|
@ -57,62 +87,49 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
|
|||
theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ));
|
||||
}
|
||||
|
||||
glm::mat4 projMat;
|
||||
viewFrustum.evalProjectionMatrix(projMat);
|
||||
{
|
||||
auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert)));
|
||||
auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag)));
|
||||
auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS));
|
||||
|
||||
Transform viewTransform;
|
||||
viewFrustum.evalViewTransform(viewTransform);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewTransform);
|
||||
batch.setModelTransform(Transform()); // only for Mac
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
|
||||
batch.setInputFormat(theFormat);
|
||||
gpu::Shader::BindingSet bindings;
|
||||
bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), SKYBOX_SKYMAP_SLOT));
|
||||
bindings.insert(gpu::Shader::Binding(std::string("skyboxBuffer"), SKYBOX_CONSTANTS_SLOT));
|
||||
if (!gpu::Shader::makeProgram(*skyShader, bindings)) {
|
||||
|
||||
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
|
||||
static gpu::BufferPointer theConstants;
|
||||
static gpu::PipelinePointer thePipeline;
|
||||
static int SKYBOX_CONSTANTS_SLOT = 0; // need to be defined by the compilation of the shader
|
||||
if (!thePipeline) {
|
||||
auto skyVS = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(Skybox_vert)));
|
||||
auto skyFS = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(Skybox_frag)));
|
||||
auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyVS, skyFS));
|
||||
|
||||
gpu::Shader::BindingSet bindings;
|
||||
bindings.insert(gpu::Shader::Binding(std::string("cubeMap"), 0));
|
||||
if (!gpu::Shader::makeProgram(*skyShader, bindings)) {
|
||||
|
||||
}
|
||||
|
||||
SKYBOX_CONSTANTS_SLOT = skyShader->getBuffers().findLocation("skyboxBuffer");
|
||||
if (SKYBOX_CONSTANTS_SLOT == gpu::Shader::INVALID_LOCATION) {
|
||||
SKYBOX_CONSTANTS_SLOT = skyShader->getUniforms().findLocation("skyboxBuffer");
|
||||
}
|
||||
|
||||
auto skyState = std::make_shared<gpu::State>();
|
||||
|
||||
thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState));
|
||||
|
||||
auto color = glm::vec4(1.0f);
|
||||
theConstants = std::make_shared<gpu::Buffer>(sizeof(color), (const gpu::Byte*) &color);
|
||||
}
|
||||
|
||||
if (glm::all(glm::equal(skybox.getColor(), glm::vec3(0.0f)))) {
|
||||
auto color = glm::vec4(1.0f);
|
||||
theConstants->setSubData(0, sizeof(color), (const gpu::Byte*) &color);
|
||||
} else {
|
||||
theConstants->setSubData(0, sizeof(Color), (const gpu::Byte*) &skybox.getColor());
|
||||
}
|
||||
auto skyState = std::make_shared<gpu::State>();
|
||||
skyState->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
|
||||
batch.setPipeline(thePipeline);
|
||||
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, theConstants, 0, theConstants->getSize());
|
||||
batch.setResourceTexture(0, skybox.getCubemap());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
thePipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState));
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// skybox has no cubemap, just clear the color buffer
|
||||
auto color = skybox.getColor();
|
||||
batch.clearFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(color, 0.0f), 0.0f, 0, true);
|
||||
// Render
|
||||
glm::mat4 projMat;
|
||||
viewFrustum.evalProjectionMatrix(projMat);
|
||||
|
||||
Transform viewTransform;
|
||||
viewFrustum.evalViewTransform(viewTransform);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewTransform);
|
||||
batch.setModelTransform(Transform()); // only for Mac
|
||||
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
|
||||
batch.setInputFormat(theFormat);
|
||||
|
||||
gpu::TexturePointer skymap;
|
||||
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {
|
||||
skymap = skybox.getCubemap();
|
||||
}
|
||||
|
||||
batch.setPipeline(thePipeline);
|
||||
batch.setUniformBuffer(SKYBOX_CONSTANTS_SLOT, skybox._dataBuffer);
|
||||
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, skymap);
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
|
||||
batch.setResourceTexture(SKYBOX_SKYMAP_SLOT, nullptr);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,20 +30,28 @@ public:
|
|||
virtual ~Skybox() {};
|
||||
|
||||
void setColor(const Color& color);
|
||||
const Color& getColor() const { return _color; }
|
||||
const Color getColor() const { return _dataBuffer.get<Data>()._color; }
|
||||
|
||||
void setCubemap(const gpu::TexturePointer& cubemap);
|
||||
const gpu::TexturePointer& getCubemap() const { return _cubemap; }
|
||||
|
||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const {
|
||||
render(batch, frustum, (*this));
|
||||
}
|
||||
virtual void render(gpu::Batch& batch, const ViewFrustum& frustum) const;
|
||||
|
||||
|
||||
static void render(gpu::Batch& batch, const ViewFrustum& frustum, const Skybox& skybox);
|
||||
|
||||
protected:
|
||||
gpu::TexturePointer _cubemap;
|
||||
Color _color{1.0f, 1.0f, 1.0f};
|
||||
|
||||
class Data {
|
||||
public:
|
||||
glm::vec3 _color{ 1.0f, 1.0f, 1.0f };
|
||||
float _blend = 1.0f;
|
||||
};
|
||||
|
||||
mutable gpu::BufferView _dataBuffer;
|
||||
|
||||
void updateDataBuffer() const;
|
||||
};
|
||||
typedef std::shared_ptr< Skybox > SkyboxPointer;
|
||||
|
||||
|
|
|
@ -40,8 +40,18 @@ void main(void) {
|
|||
#else
|
||||
|
||||
vec3 coord = normalize(_normal);
|
||||
vec3 texel = texture(cubeMap, coord).rgb;
|
||||
vec3 color = texel * _skybox._color.rgb;
|
||||
|
||||
// Skybox color or blend with skymap
|
||||
vec3 color = _skybox._color.rgb;
|
||||
if (_skybox._color.a > 0.0) {
|
||||
vec3 texel = texture(cubeMap, coord).rgb;
|
||||
if (_skybox._color.a < 2.0) {
|
||||
color *= texel;
|
||||
} else {
|
||||
color = texel;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 pixel = pow(color, vec3(1.0/2.2)); // manual Gamma correction
|
||||
_fragColor = vec4(pixel, 0.0);
|
||||
|
||||
|
|
|
@ -32,7 +32,8 @@ void ProceduralSkybox::setProcedural(const ProceduralPointer& procedural) {
|
|||
if (_procedural) {
|
||||
_procedural->_vertexSource = ProceduralSkybox_vert;
|
||||
_procedural->_fragmentSource = ProceduralSkybox_frag;
|
||||
// No pipeline state customization
|
||||
// Adjust the pipeline state for background using the stencil test
|
||||
_procedural->_state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +43,7 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& frustum) con
|
|||
|
||||
void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const ProceduralSkybox& skybox) {
|
||||
if (!(skybox._procedural)) {
|
||||
skybox.updateDataBuffer();
|
||||
Skybox::render(batch, viewFrustum, skybox);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ void Environment::setupAtmosphereProgram(const char* vertSource, const char* fra
|
|||
auto state = std::make_shared<gpu::State>();
|
||||
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
state->setDepthTest(false);
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
|
|
@ -35,7 +35,9 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
|
|||
_frameBufferSize = frameBufferSize;
|
||||
_primaryFramebufferFull.reset();
|
||||
_primaryFramebufferDepthColor.reset();
|
||||
_primaryFramebufferStencilColor.reset();
|
||||
_primaryDepthTexture.reset();
|
||||
_primaryStencilTexture.reset();
|
||||
_primaryColorTexture.reset();
|
||||
_primaryNormalTexture.reset();
|
||||
_primarySpecularTexture.reset();
|
||||
|
@ -47,6 +49,7 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
|
|||
void FramebufferCache::createPrimaryFramebuffer() {
|
||||
_primaryFramebufferFull = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
_primaryFramebufferDepthColor = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
_primaryFramebufferStencilColor = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
|
||||
auto colorFormat = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
||||
auto width = _frameBufferSize.width();
|
||||
|
@ -63,12 +66,19 @@ void FramebufferCache::createPrimaryFramebuffer() {
|
|||
|
||||
_primaryFramebufferDepthColor->setRenderBuffer(0, _primaryColorTexture);
|
||||
|
||||
_primaryFramebufferStencilColor->setRenderBuffer(0, _primaryColorTexture);
|
||||
|
||||
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH);
|
||||
_primaryDepthTexture = gpu::TexturePointer(gpu::Texture::create2D(depthFormat, width, height, defaultSampler));
|
||||
|
||||
auto stencilFormat = gpu::Element(gpu::VEC2, gpu::UINT32, gpu::DEPTH_STENCIL);
|
||||
_primaryStencilTexture = gpu::TexturePointer(gpu::Texture::create2D(stencilFormat, width, height, defaultSampler));
|
||||
|
||||
_primaryFramebufferFull->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||
|
||||
_primaryFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||
|
||||
_primaryFramebufferStencilColor->setDepthStencilBuffer(_primaryStencilTexture, stencilFormat);
|
||||
|
||||
_selfieFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||
auto tex = gpu::TexturePointer(gpu::Texture::create2D(colorFormat, width * 0.5, height * 0.5, defaultSampler));
|
||||
|
@ -89,6 +99,12 @@ gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferDepthColor() {
|
|||
return _primaryFramebufferDepthColor;
|
||||
}
|
||||
|
||||
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebufferStencilColor() {
|
||||
if (!_primaryFramebufferStencilColor) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryFramebufferStencilColor;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() {
|
||||
if (!_primaryDepthTexture) {
|
||||
|
@ -97,6 +113,13 @@ gpu::TexturePointer FramebufferCache::getPrimaryDepthTexture() {
|
|||
return _primaryDepthTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryStencilTexture() {
|
||||
if (!_primaryStencilTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
}
|
||||
return _primaryStencilTexture;
|
||||
}
|
||||
|
||||
gpu::TexturePointer FramebufferCache::getPrimaryColorTexture() {
|
||||
if (!_primaryColorTexture) {
|
||||
createPrimaryFramebuffer();
|
||||
|
|
|
@ -31,8 +31,10 @@ public:
|
|||
/// used for scene rendering.
|
||||
gpu::FramebufferPointer getPrimaryFramebuffer();
|
||||
gpu::FramebufferPointer getPrimaryFramebufferDepthColor();
|
||||
gpu::FramebufferPointer getPrimaryFramebufferStencilColor();
|
||||
|
||||
gpu::TexturePointer getPrimaryDepthTexture();
|
||||
gpu::TexturePointer getPrimaryStencilTexture();
|
||||
gpu::TexturePointer getPrimaryColorTexture();
|
||||
gpu::TexturePointer getPrimaryNormalTexture();
|
||||
gpu::TexturePointer getPrimarySpecularTexture();
|
||||
|
@ -58,7 +60,9 @@ private:
|
|||
|
||||
gpu::FramebufferPointer _primaryFramebufferFull;
|
||||
gpu::FramebufferPointer _primaryFramebufferDepthColor;
|
||||
gpu::FramebufferPointer _primaryFramebufferStencilColor;
|
||||
gpu::TexturePointer _primaryDepthTexture;
|
||||
gpu::TexturePointer _primaryStencilTexture;
|
||||
gpu::TexturePointer _primaryColorTexture;
|
||||
gpu::TexturePointer _primaryNormalTexture;
|
||||
gpu::TexturePointer _primarySpecularTexture;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include <gpu/Context.h>
|
||||
#include <gpu/StandardShaderLib.h>
|
||||
|
||||
#include "FramebufferCache.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
@ -28,21 +29,27 @@
|
|||
#include "overlay3D_vert.h"
|
||||
#include "overlay3D_frag.h"
|
||||
|
||||
#include "drawOpaqueStencil_frag.h"
|
||||
|
||||
using namespace render;
|
||||
|
||||
void SetupDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
RenderArgs* args = renderContext->args;
|
||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||
|
||||
auto primaryFboStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
|
||||
auto primaryFbo = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferDepthColor();
|
||||
|
||||
batch.enableStereo(false);
|
||||
batch.setFramebuffer(nullptr);
|
||||
batch.setFramebuffer(primaryFbo);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setFramebuffer(primaryFboStencil);
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_STENCIL,
|
||||
vec4(vec3(0), 1), 1.0, 0.0, true);
|
||||
|
||||
batch.setFramebuffer(primaryFbo);
|
||||
batch.clearFramebuffer(
|
||||
gpu::Framebuffer::BUFFER_COLOR0 |
|
||||
gpu::Framebuffer::BUFFER_DEPTH,
|
||||
|
@ -65,7 +72,6 @@ void ResolveDeferred::run(const SceneContextPointer& sceneContext, const RenderC
|
|||
|
||||
RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||
_jobs.push_back(Job(new SetupDeferred::JobModel("SetupFramebuffer")));
|
||||
_jobs.push_back(Job(new DrawBackground::JobModel("DrawBackground")));
|
||||
|
||||
_jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred")));
|
||||
_jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque",
|
||||
|
@ -79,7 +85,10 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
|||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput())));
|
||||
auto& renderedOpaques = _jobs.back().getOutput();
|
||||
_jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", _jobs.back().getOutput())));
|
||||
|
||||
|
||||
_jobs.push_back(Job(new DrawStencilDeferred::JobModel("DrawOpaqueStencil")));
|
||||
_jobs.push_back(Job(new DrawBackgroundDeferred::JobModel("DrawBackgroundDeferred")));
|
||||
|
||||
_jobs.push_back(Job(new DrawLight::JobModel("DrawLight")));
|
||||
_jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred")));
|
||||
_jobs.push_back(Job(new ResolveDeferred::JobModel("ResolveDeferred")));
|
||||
|
@ -226,7 +235,9 @@ const gpu::PipelinePointer& DrawOverlay3D::getOpaquePipeline() {
|
|||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setDepthTest(false);
|
||||
// additive blending
|
||||
state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
|
||||
_opaquePipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
|
@ -289,3 +300,95 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
|
|||
args->_whiteTexture.reset();
|
||||
}
|
||||
}
|
||||
|
||||
gpu::PipelinePointer DrawStencilDeferred::_opaquePipeline;
|
||||
const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
|
||||
if (!_opaquePipeline) {
|
||||
const gpu::int8 STENCIL_OPAQUE = 1;
|
||||
auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS();
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawOpaqueStencil_frag)));
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
|
||||
|
||||
gpu::Shader::makeProgram((*program));
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE, gpu::State::STENCIL_OP_REPLACE));
|
||||
state->setColorWriteMask(0);
|
||||
|
||||
_opaquePipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
return _opaquePipeline;
|
||||
}
|
||||
|
||||
void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// from the touched pixel generate the stencil buffer
|
||||
RenderArgs* args = renderContext->args;
|
||||
doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
auto primaryFboColorDepthStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
|
||||
auto primaryDepth = DependencyManager::get<FramebufferCache>()->getPrimaryDepthTexture();
|
||||
|
||||
batch.enableStereo(false);
|
||||
|
||||
batch.setFramebuffer(primaryFboColorDepthStencil);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
batch.setPipeline(getOpaquePipeline());
|
||||
batch.setResourceTexture(0, primaryDepth);
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.setResourceTexture(0, nullptr);
|
||||
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
|
||||
void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
||||
// render backgrounds
|
||||
auto& scene = sceneContext->_scene;
|
||||
auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background());
|
||||
|
||||
|
||||
ItemIDsBounds inItems;
|
||||
inItems.reserve(items.size());
|
||||
for (auto id : items) {
|
||||
inItems.emplace_back(id);
|
||||
}
|
||||
RenderArgs* args = renderContext->args;
|
||||
doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||
args->_batch = &batch;
|
||||
|
||||
auto primaryFboColorStencil = DependencyManager::get<FramebufferCache>()->getPrimaryFramebufferStencilColor();
|
||||
auto primaryFboFull = DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer();
|
||||
|
||||
batch.enableSkybox(true);
|
||||
|
||||
batch.setFramebuffer(primaryFboColorStencil);
|
||||
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
batch.setStateScissorRect(args->_viewport);
|
||||
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
||||
renderItems(sceneContext, renderContext, inItems);
|
||||
|
||||
batch.setFramebuffer(primaryFboFull);
|
||||
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
|
@ -59,6 +59,23 @@ public:
|
|||
typedef render::Job::ModelI<DrawTransparentDeferred, render::ItemIDsBounds> JobModel;
|
||||
};
|
||||
|
||||
class DrawStencilDeferred {
|
||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||
public:
|
||||
static const gpu::PipelinePointer& getOpaquePipeline();
|
||||
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<DrawStencilDeferred> JobModel;
|
||||
};
|
||||
|
||||
class DrawBackgroundDeferred {
|
||||
public:
|
||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||
|
||||
typedef render::Job::Model<DrawBackgroundDeferred> JobModel;
|
||||
};
|
||||
|
||||
class DrawOverlay3D {
|
||||
static gpu::PipelinePointer _opaquePipeline; //lazy evaluation hence mutable
|
||||
public:
|
||||
|
|
24
libraries/render-utils/src/drawOpaqueStencil.slf
Normal file
24
libraries/render-utils/src/drawOpaqueStencil.slf
Normal file
|
@ -0,0 +1,24 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// drawOpaqueStencil.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Sam Gateau on 9/29/15.
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
|
||||
uniform sampler2D depthTexture;
|
||||
|
||||
void main(void) {
|
||||
float depth = texture(depthTexture, varTexCoord0.xy).r;
|
||||
if (depth >= 1.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
|
@ -257,6 +257,7 @@ class DrawBackground {
|
|||
public:
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext);
|
||||
|
||||
|
||||
typedef Job::Model<DrawBackground> JobModel;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue