mirror of
https://github.com/JulianGro/overte.git
synced 2025-06-02 11:20:21 +02:00
Working on AO
This commit is contained in:
parent
ee6d720f2b
commit
dbc4506cee
11 changed files with 409 additions and 359 deletions
|
@ -12,7 +12,7 @@
|
||||||
Script.include("cookies.js");
|
Script.include("cookies.js");
|
||||||
|
|
||||||
var MENU = "Developer>Render>Debug Deferred Buffer";
|
var MENU = "Developer>Render>Debug Deferred Buffer";
|
||||||
var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "Custom"];
|
var ACTIONS = ["Off", "Diffuse", "Alpha", "Specular", "Roughness", "Normal", "Depth", "Lighting", "AmbientOcclusion", "Custom"];
|
||||||
var SETTINGS_KEY = "EngineDebugScript.DebugMode";
|
var SETTINGS_KEY = "EngineDebugScript.DebugMode";
|
||||||
|
|
||||||
Number.prototype.clamp = function(min, max) {
|
Number.prototype.clamp = function(min, max) {
|
||||||
|
|
|
@ -146,6 +146,68 @@ public:
|
||||||
case gpu::RGB:
|
case gpu::RGB:
|
||||||
case gpu::RGBA:
|
case gpu::RGBA:
|
||||||
texel.internalFormat = GL_RED;
|
texel.internalFormat = GL_RED;
|
||||||
|
switch (dstFormat.getType()) {
|
||||||
|
case gpu::UINT32: {
|
||||||
|
texel.internalFormat = GL_R32UI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::INT32: {
|
||||||
|
texel.internalFormat = GL_R32I;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NUINT32: {
|
||||||
|
texel.internalFormat = GL_RED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NINT32: {
|
||||||
|
texel.internalFormat = GL_RED_SNORM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::FLOAT: {
|
||||||
|
texel.internalFormat = GL_R32F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::UINT16: {
|
||||||
|
texel.internalFormat = GL_R16UI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::INT16: {
|
||||||
|
texel.internalFormat = GL_R16I;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NUINT16: {
|
||||||
|
texel.internalFormat = GL_R16;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NINT16: {
|
||||||
|
texel.internalFormat = GL_R16_SNORM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::HALF: {
|
||||||
|
texel.internalFormat = GL_R16F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::UINT8: {
|
||||||
|
texel.internalFormat = GL_R8UI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::INT8: {
|
||||||
|
texel.internalFormat = GL_R8I;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NUINT8: {
|
||||||
|
texel.internalFormat = GL_R8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NINT8: {
|
||||||
|
texel.internalFormat = GL_R8_SNORM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gpu::NUM_TYPES: { // quiet compiler
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case gpu::DEPTH:
|
case gpu::DEPTH:
|
||||||
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
|
texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it
|
||||||
|
|
|
@ -32,298 +32,140 @@
|
||||||
#include "occlusion_blend_frag.h"
|
#include "occlusion_blend_frag.h"
|
||||||
|
|
||||||
|
|
||||||
AmbientOcclusion::AmbientOcclusion() {
|
|
||||||
}
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& AmbientOcclusion::getOcclusionPipeline() {
|
|
||||||
if (!_occlusionPipeline) {
|
|
||||||
auto vs = gpu::Shader::createVertex(std::string(ambient_occlusion_vert));
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(ambient_occlusion_frag));
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("depthTexture"), 0));
|
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("normalTexture"), 1));
|
|
||||||
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
|
||||||
|
|
||||||
_gScaleLoc = program->getUniforms().findLocation("g_scale");
|
|
||||||
_gBiasLoc = program->getUniforms().findLocation("g_bias");
|
|
||||||
_gSampleRadiusLoc = program->getUniforms().findLocation("g_sample_rad");
|
|
||||||
_gIntensityLoc = program->getUniforms().findLocation("g_intensity");
|
|
||||||
|
|
||||||
_nearLoc = program->getUniforms().findLocation("near");
|
|
||||||
_depthScaleLoc = program->getUniforms().findLocation("depthScale");
|
|
||||||
_depthTexCoordOffsetLoc = program->getUniforms().findLocation("depthTexCoordOffset");
|
|
||||||
_depthTexCoordScaleLoc = program->getUniforms().findLocation("depthTexCoordScale");
|
|
||||||
_renderTargetResLoc = program->getUniforms().findLocation("renderTargetRes");
|
|
||||||
_renderTargetResInvLoc = program->getUniforms().findLocation("renderTargetResInv");
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
|
||||||
|
|
||||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend on transparent
|
|
||||||
state->setBlendFunction(false,
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Link the occlusion FBO to texture
|
|
||||||
_occlusionBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32,
|
|
||||||
DependencyManager::get<FramebufferCache>()->getFrameBufferSize().width(), DependencyManager::get<FramebufferCache>()->getFrameBufferSize().height()));
|
|
||||||
auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
auto width = _occlusionBuffer->getWidth();
|
|
||||||
auto height = _occlusionBuffer->getHeight();
|
|
||||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
|
||||||
_occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler));
|
|
||||||
|
|
||||||
// Good to go add the brand new pipeline
|
|
||||||
_occlusionPipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
return _occlusionPipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& AmbientOcclusion::getVBlurPipeline() {
|
|
||||||
if (!_vBlurPipeline) {
|
|
||||||
auto vs = gpu::Shader::createVertex(std::string(gaussian_blur_vertical_vert));
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(gaussian_blur_frag));
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
|
||||||
|
|
||||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend on transparent
|
|
||||||
state->setBlendFunction(false,
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Link the horizontal blur FBO to texture
|
|
||||||
_vBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32,
|
|
||||||
DependencyManager::get<FramebufferCache>()->getFrameBufferSize().width(), DependencyManager::get<FramebufferCache>()->getFrameBufferSize().height()));
|
|
||||||
auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
auto width = _vBlurBuffer->getWidth();
|
|
||||||
auto height = _vBlurBuffer->getHeight();
|
|
||||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
|
||||||
_vBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler));
|
|
||||||
|
|
||||||
// Good to go add the brand new pipeline
|
|
||||||
_vBlurPipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
return _vBlurPipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& AmbientOcclusion::getHBlurPipeline() {
|
|
||||||
if (!_hBlurPipeline) {
|
|
||||||
auto vs = gpu::Shader::createVertex(std::string(gaussian_blur_horizontal_vert));
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(gaussian_blur_frag));
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
|
||||||
|
|
||||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend on transparent
|
|
||||||
state->setBlendFunction(false,
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Link the horizontal blur FBO to texture
|
|
||||||
_hBlurBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32,
|
|
||||||
DependencyManager::get<FramebufferCache>()->getFrameBufferSize().width(), DependencyManager::get<FramebufferCache>()->getFrameBufferSize().height()));
|
|
||||||
auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
auto width = _hBlurBuffer->getWidth();
|
|
||||||
auto height = _hBlurBuffer->getHeight();
|
|
||||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
|
||||||
_hBlurTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler));
|
|
||||||
|
|
||||||
// Good to go add the brand new pipeline
|
|
||||||
_hBlurPipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
return _hBlurPipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() {
|
|
||||||
if (!_blendPipeline) {
|
|
||||||
auto vs = gpu::Shader::createVertex(std::string(ambient_occlusion_vert));
|
|
||||||
auto ps = gpu::Shader::createPixel(std::string(occlusion_blend_frag));
|
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("blurredOcclusionTexture"), 0));
|
|
||||||
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
|
||||||
|
|
||||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
|
||||||
|
|
||||||
// Blend on transparent
|
|
||||||
state->setBlendFunction(true,
|
|
||||||
gpu::State::INV_SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::SRC_ALPHA);
|
|
||||||
|
|
||||||
// Good to go add the brand new pipeline
|
|
||||||
_blendPipeline = gpu::Pipeline::create(program, state);
|
|
||||||
}
|
|
||||||
return _blendPipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
|
||||||
assert(renderContext->getArgs());
|
|
||||||
assert(renderContext->getArgs()->_viewFrustum);
|
|
||||||
|
|
||||||
RenderArgs* args = renderContext->getArgs();
|
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
|
||||||
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
|
||||||
float fbWidth = framebufferSize.width();
|
|
||||||
float fbHeight = framebufferSize.height();
|
|
||||||
float sMin = args->_viewport.x / fbWidth;
|
|
||||||
float sWidth = args->_viewport.z / fbWidth;
|
|
||||||
float tMin = args->_viewport.y / fbHeight;
|
|
||||||
float tHeight = args->_viewport.w / fbHeight;
|
|
||||||
|
|
||||||
|
|
||||||
glm::mat4 projMat;
|
|
||||||
Transform viewMat;
|
|
||||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
|
||||||
args->_viewFrustum->evalViewTransform(viewMat);
|
|
||||||
batch.setProjectionTransform(projMat);
|
|
||||||
batch.setViewTransform(viewMat);
|
|
||||||
batch.setModelTransform(Transform());
|
|
||||||
|
|
||||||
// Occlusion step
|
|
||||||
getOcclusionPipeline();
|
|
||||||
batch.setResourceTexture(0, framebufferCache->getPrimaryDepthTexture());
|
|
||||||
batch.setResourceTexture(1, framebufferCache->getDeferredNormalTexture());
|
|
||||||
_occlusionBuffer->setRenderBuffer(0, _occlusionTexture);
|
|
||||||
batch.setFramebuffer(_occlusionBuffer);
|
|
||||||
|
|
||||||
// Occlusion uniforms
|
|
||||||
g_scale = 1.0f;
|
|
||||||
g_bias = 1.0f;
|
|
||||||
g_sample_rad = 1.0f;
|
|
||||||
g_intensity = 1.0f;
|
|
||||||
|
|
||||||
// Bind the first gpu::Pipeline we need - for calculating occlusion buffer
|
|
||||||
batch.setPipeline(getOcclusionPipeline());
|
|
||||||
batch._glUniform1f(_gScaleLoc, g_scale);
|
|
||||||
batch._glUniform1f(_gBiasLoc, g_bias);
|
|
||||||
batch._glUniform1f(_gSampleRadiusLoc, g_sample_rad);
|
|
||||||
batch._glUniform1f(_gIntensityLoc, g_intensity);
|
|
||||||
|
|
||||||
// setup uniforms for unpacking a view-space position from the depth buffer
|
|
||||||
// This is code taken from DeferredLightEffect.render() method in DeferredLightingEffect.cpp.
|
|
||||||
// DeferredBuffer.slh shows how the unpacking is done and what variables are needed.
|
|
||||||
|
|
||||||
// initialize the view-space unpacking uniforms using frustum data
|
|
||||||
float left, right, bottom, top, nearVal, farVal;
|
|
||||||
glm::vec4 nearClipPlane, farClipPlane;
|
|
||||||
|
|
||||||
args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
|
||||||
|
|
||||||
float depthScale = (farVal - nearVal) / farVal;
|
|
||||||
float nearScale = -1.0f / nearVal;
|
|
||||||
float depthTexCoordScaleS = (right - left) * nearScale / sWidth;
|
|
||||||
float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight;
|
|
||||||
float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS;
|
|
||||||
float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT;
|
|
||||||
|
|
||||||
// now set the position-unpacking unforms
|
|
||||||
batch._glUniform1f(_nearLoc, nearVal);
|
|
||||||
batch._glUniform1f(_depthScaleLoc, depthScale);
|
|
||||||
batch._glUniform2f(_depthTexCoordOffsetLoc, depthTexCoordOffsetS, depthTexCoordOffsetT);
|
|
||||||
batch._glUniform2f(_depthTexCoordScaleLoc, depthTexCoordScaleS, depthTexCoordScaleT);
|
|
||||||
|
|
||||||
batch._glUniform2f(_renderTargetResLoc, fbWidth, fbHeight);
|
|
||||||
batch._glUniform2f(_renderTargetResInvLoc, 1.0f / fbWidth, 1.0f / fbHeight);
|
|
||||||
|
|
||||||
glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
glm::vec2 bottomLeft(-1.0f, -1.0f);
|
|
||||||
glm::vec2 topRight(1.0f, 1.0f);
|
|
||||||
glm::vec2 texCoordTopLeft(0.0f, 0.0f);
|
|
||||||
glm::vec2 texCoordBottomRight(1.0f, 1.0f);
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color);
|
|
||||||
|
|
||||||
// Vertical blur step
|
|
||||||
getVBlurPipeline();
|
|
||||||
batch.setResourceTexture(0, _occlusionTexture);
|
|
||||||
_vBlurBuffer->setRenderBuffer(0, _vBlurTexture);
|
|
||||||
batch.setFramebuffer(_vBlurBuffer);
|
|
||||||
|
|
||||||
// Bind the second gpu::Pipeline we need - for calculating blur buffer
|
|
||||||
batch.setPipeline(getVBlurPipeline());
|
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color);
|
|
||||||
|
|
||||||
// Horizontal blur step
|
|
||||||
getHBlurPipeline();
|
|
||||||
batch.setResourceTexture(0, _vBlurTexture);
|
|
||||||
_hBlurBuffer->setRenderBuffer(0, _hBlurTexture);
|
|
||||||
batch.setFramebuffer(_hBlurBuffer);
|
|
||||||
|
|
||||||
// Bind the third gpu::Pipeline we need - for calculating blur buffer
|
|
||||||
batch.setPipeline(getHBlurPipeline());
|
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color);
|
|
||||||
|
|
||||||
// Blend step
|
|
||||||
getBlendPipeline();
|
|
||||||
batch.setResourceTexture(0, _hBlurTexture);
|
|
||||||
batch.setFramebuffer(framebufferCache->getDeferredFramebuffer());
|
|
||||||
|
|
||||||
// Bind the fourth gpu::Pipeline we need - for blending the primary color buffer with blurred occlusion texture
|
|
||||||
batch.setPipeline(getBlendPipeline());
|
|
||||||
|
|
||||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const int AmbientOcclusionEffect_ParamsSlot = 0;
|
||||||
|
const int AmbientOcclusionEffect_DeferredTransformSlot = 1;
|
||||||
|
const int AmbientOcclusionEffect_DepthMapSlot = 0;
|
||||||
|
const int AmbientOcclusionEffect_PyramidMapSlot = 0;
|
||||||
|
|
||||||
AmbientOcclusionEffect::AmbientOcclusionEffect() {
|
AmbientOcclusionEffect::AmbientOcclusionEffect() {
|
||||||
Parameters parameters;
|
Parameters parameters;
|
||||||
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) ¶meters));
|
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) ¶meters));
|
||||||
}
|
}
|
||||||
|
|
||||||
const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
|
const gpu::PipelinePointer& AmbientOcclusionEffect::getPyramidPipeline() {
|
||||||
if (!_occlusionPipeline) {
|
if (!_pyramidPipeline) {
|
||||||
|
const char AO_frag[] = R"SCRIBE(#version 410 core
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 12/23/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
|
||||||
|
//
|
||||||
|
|
||||||
|
struct AmbientOcclusionParams {
|
||||||
|
vec4 _clipInfo;
|
||||||
|
mat4 _projection;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform ambientOcclusionParamsBuffer {
|
||||||
|
AmbientOcclusionParams params;
|
||||||
|
};
|
||||||
|
|
||||||
|
float evalZeyeFromZdb(float depth) {
|
||||||
|
return params._clipInfo.x / (depth * params._clipInfo.y + params._clipInfo.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the depth texture
|
||||||
|
uniform sampler2D depthMap;
|
||||||
|
|
||||||
|
in vec2 varTexCoord0;
|
||||||
|
out vec4 outFragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
float Zdb = texture(depthMap, varTexCoord0).x;
|
||||||
|
float Zeye = -evalZeyeFromZdb(Zdb);
|
||||||
|
outFragColor = vec4(Zeye, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
)SCRIBE";
|
||||||
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
|
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
|
||||||
auto ps = gpu::Shader::createPixel(std::string(ambient_occlusion_frag));
|
auto ps = gpu::Shader::createPixel(std::string(AO_frag));
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("depthTexture"), 0));
|
slotBindings.insert(gpu::Shader::Binding(std::string("ambientOcclusionParamsBuffer"), AmbientOcclusionEffect_ParamsSlot));
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("normalTexture"), 1));
|
slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), AmbientOcclusionEffect_DeferredTransformSlot));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), AmbientOcclusionEffect_DepthMapSlot));
|
||||||
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
state->setDepthTest(false, false, gpu::LESS_EQUAL);
|
// Stencil test all the ao passes for objects pixels only, not the background
|
||||||
|
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||||
|
|
||||||
// Blend on transparent
|
state->setColorWriteMask(true, false, false, false);
|
||||||
state->setBlendFunction(false,
|
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
// Good to go add the brand new pipeline
|
||||||
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);
|
_pyramidPipeline = gpu::Pipeline::create(program, state);
|
||||||
|
}
|
||||||
|
return _pyramidPipeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gpu::PipelinePointer& AmbientOcclusionEffect::getOcclusionPipeline() {
|
||||||
|
if (!_occlusionPipeline) {
|
||||||
|
const char AO_frag[] = R"SCRIBE(#version 410 core
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 12/23/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
|
||||||
|
//
|
||||||
|
|
||||||
|
struct AmbientOcclusionParams {
|
||||||
|
vec4 _clipInfo;
|
||||||
|
mat4 _projection;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform ambientOcclusionParamsBuffer {
|
||||||
|
AmbientOcclusionParams params;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3 evalEyePositionFromZeye(float Zeye, vec2 texcoord, mat4 projection) {
|
||||||
|
// compute the view space position using the depth
|
||||||
|
// basically manually pick the proj matrix components to do the inverse
|
||||||
|
float Xe = (-Zeye * (texcoord.x * 2.0 - 1.0) - Zeye * projection[2][0] - projection[3][0]) / projection[0][0];
|
||||||
|
float Ye = (-Zeye * (texcoord.y * 2.0 - 1.0) - Zeye * projection[2][1] - projection[3][1]) / projection[1][1];
|
||||||
|
return vec3(Xe, Ye, Zeye);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the depth texture
|
||||||
|
uniform sampler2D pyramidMap;
|
||||||
|
|
||||||
|
in vec2 varTexCoord0;
|
||||||
|
out vec4 outFragColor;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
float Zeye = textureLod(pyramidMap, varTexCoord0, 0).x;
|
||||||
|
vec3 P = evalEyePositionFromZeye(-Zeye, varTexCoord0, params._projection);
|
||||||
|
|
||||||
|
outFragColor = vec4(1.0, 0.0, 0.0, P.x / 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
)SCRIBE";
|
||||||
|
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
|
||||||
|
auto ps = gpu::Shader::createPixel(std::string(AO_frag));
|
||||||
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
|
gpu::Shader::BindingSet slotBindings;
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("ambientOcclusionParamsBuffer"), AmbientOcclusionEffect_ParamsSlot));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), AmbientOcclusionEffect_DeferredTransformSlot));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("pyramidMap"), AmbientOcclusionEffect_PyramidMapSlot));
|
||||||
|
|
||||||
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
|
|
||||||
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
|
|
||||||
|
// Stencil test all the ao passes for objects pixels only, not the background
|
||||||
|
state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::NOT_EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP));
|
||||||
|
|
||||||
|
state->setColorWriteMask(false, false, false, true);
|
||||||
|
|
||||||
// Link the occlusion FBO to texture
|
|
||||||
/* _occlusionBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32,
|
|
||||||
DependencyManager::get<FramebufferCache>()->getFrameBufferSize().width(), DependencyManager::get<FramebufferCache>()->getFrameBufferSize().height()));
|
|
||||||
auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA);
|
|
||||||
auto width = _occlusionBuffer->getWidth();
|
|
||||||
auto height = _occlusionBuffer->getHeight();
|
|
||||||
auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT);
|
|
||||||
_occlusionTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler));
|
|
||||||
*/
|
|
||||||
// Good to go add the brand new pipeline
|
// Good to go add the brand new pipeline
|
||||||
_occlusionPipeline = gpu::Pipeline::create(program, state);
|
_occlusionPipeline = gpu::Pipeline::create(program, state);
|
||||||
}
|
}
|
||||||
|
@ -396,40 +238,173 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getHBlurPipeline() {
|
||||||
return _hBlurPipeline;
|
return _hBlurPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AmbientOcclusionEffect::setClipInfo(float nearZ, float farZ) {
|
||||||
|
_parametersBuffer.edit<Parameters>()._clipInfo = glm::vec4(nearZ*farZ, farZ -nearZ, -farZ, 0.0f);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmbientOcclusionEffect::updateDeferredTransformBuffer(const render::RenderContextPointer& renderContext) {
|
||||||
|
// Allocate the parameters buffer used by all the deferred shaders
|
||||||
|
if (!_deferredTransformBuffer[0]._buffer) {
|
||||||
|
DeferredTransform parameters;
|
||||||
|
_deferredTransformBuffer[0] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters));
|
||||||
|
_deferredTransformBuffer[1] = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(DeferredTransform), (const gpu::Byte*) ¶meters));
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderArgs* args = renderContext->getArgs();
|
||||||
|
|
||||||
|
// THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport)
|
||||||
|
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||||
|
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
||||||
|
auto monoViewport = args->_viewport;
|
||||||
|
float sMin = args->_viewport.x / (float)framebufferSize.width();
|
||||||
|
float sWidth = args->_viewport.z / (float)framebufferSize.width();
|
||||||
|
float tMin = args->_viewport.y / (float)framebufferSize.height();
|
||||||
|
float tHeight = args->_viewport.w / (float)framebufferSize.height();
|
||||||
|
|
||||||
|
// The view frustum is the mono frustum base
|
||||||
|
auto viewFrustum = args->_viewFrustum;
|
||||||
|
|
||||||
|
// Eval the mono projection
|
||||||
|
mat4 monoProjMat;
|
||||||
|
viewFrustum->evalProjectionMatrix(monoProjMat);
|
||||||
|
|
||||||
|
// The mono view transform
|
||||||
|
Transform monoViewTransform;
|
||||||
|
viewFrustum->evalViewTransform(monoViewTransform);
|
||||||
|
|
||||||
|
// THe mono view matrix coming from the mono view transform
|
||||||
|
glm::mat4 monoViewMat;
|
||||||
|
monoViewTransform.getMatrix(monoViewMat);
|
||||||
|
|
||||||
|
// Running in stero ?
|
||||||
|
bool isStereo = args->_context->isStereo();
|
||||||
|
int numPasses = 1;
|
||||||
|
|
||||||
|
mat4 projMats[2];
|
||||||
|
Transform viewTransforms[2];
|
||||||
|
ivec4 viewports[2];
|
||||||
|
vec4 clipQuad[2];
|
||||||
|
vec2 screenBottomLeftCorners[2];
|
||||||
|
vec2 screenTopRightCorners[2];
|
||||||
|
vec4 fetchTexcoordRects[2];
|
||||||
|
|
||||||
|
DeferredTransform deferredTransforms[2];
|
||||||
|
|
||||||
|
if (isStereo) {
|
||||||
|
numPasses = 2;
|
||||||
|
|
||||||
|
mat4 eyeViews[2];
|
||||||
|
args->_context->getStereoProjections(projMats);
|
||||||
|
args->_context->getStereoViews(eyeViews);
|
||||||
|
|
||||||
|
float halfWidth = 0.5f * sWidth;
|
||||||
|
|
||||||
|
for (int i = 0; i < numPasses; i++) {
|
||||||
|
// In stereo, the 2 sides are layout side by side in the mono viewport and their width is half
|
||||||
|
int sideWidth = monoViewport.z >> 1;
|
||||||
|
viewports[i] = ivec4(monoViewport.x + (i * sideWidth), monoViewport.y, sideWidth, monoViewport.w);
|
||||||
|
|
||||||
|
deferredTransforms[i].projection = projMats[i];
|
||||||
|
|
||||||
|
auto sideViewMat = monoViewMat * glm::inverse(eyeViews[i]);
|
||||||
|
viewTransforms[i].evalFromRawMatrix(sideViewMat);
|
||||||
|
deferredTransforms[i].viewInverse = sideViewMat;
|
||||||
|
|
||||||
|
deferredTransforms[i].stereoSide = (i == 0 ? -1.0f : 1.0f);
|
||||||
|
|
||||||
|
clipQuad[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);
|
||||||
|
screenBottomLeftCorners[i] = glm::vec2(-1.0f + i * 1.0f, -1.0f);
|
||||||
|
screenTopRightCorners[i] = glm::vec2(i * 1.0f, 1.0f);
|
||||||
|
|
||||||
|
fetchTexcoordRects[i] = glm::vec4(sMin + i * halfWidth, tMin, halfWidth, tHeight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
viewports[0] = monoViewport;
|
||||||
|
projMats[0] = monoProjMat;
|
||||||
|
|
||||||
|
deferredTransforms[0].projection = monoProjMat;
|
||||||
|
|
||||||
|
deferredTransforms[0].viewInverse = monoViewMat;
|
||||||
|
viewTransforms[0] = monoViewTransform;
|
||||||
|
|
||||||
|
deferredTransforms[0].stereoSide = 0.0f;
|
||||||
|
|
||||||
|
clipQuad[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
|
||||||
|
screenBottomLeftCorners[0] = glm::vec2(-1.0f, -1.0f);
|
||||||
|
screenTopRightCorners[0] = glm::vec2(1.0f, 1.0f);
|
||||||
|
|
||||||
|
fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
_deferredTransformBuffer[0]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[0]);
|
||||||
|
_deferredTransformBuffer[1]._buffer->setSubData(0, sizeof(DeferredTransform), (const gpu::Byte*) &deferredTransforms[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
||||||
assert(renderContext->getArgs());
|
assert(renderContext->getArgs());
|
||||||
assert(renderContext->getArgs()->_viewFrustum);
|
assert(renderContext->getArgs()->_viewFrustum);
|
||||||
|
|
||||||
RenderArgs* args = renderContext->getArgs();
|
RenderArgs* args = renderContext->getArgs();
|
||||||
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
|
||||||
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
auto framebufferCache = DependencyManager::get<FramebufferCache>();
|
||||||
|
auto depthBuffer = framebufferCache->getPrimaryDepthTexture();
|
||||||
|
auto pyramidFBO = framebufferCache->getDepthPyramidFramebuffer();
|
||||||
|
auto occlusionFBO = framebufferCache->getDeferredFramebufferDepthColor();
|
||||||
|
|
||||||
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
QSize framebufferSize = framebufferCache->getFrameBufferSize();
|
||||||
float fbWidth = framebufferSize.width();
|
float sMin = args->_viewport.x / (float)framebufferSize.width();
|
||||||
float fbHeight = framebufferSize.height();
|
float sWidth = args->_viewport.z / (float)framebufferSize.width();
|
||||||
float sMin = args->_viewport.x / fbWidth;
|
float tMin = args->_viewport.y / (float)framebufferSize.height();
|
||||||
float sWidth = args->_viewport.z / fbWidth;
|
float tHeight = args->_viewport.w / (float)framebufferSize.height();
|
||||||
float tMin = args->_viewport.y / fbHeight;
|
|
||||||
float tHeight = args->_viewport.w / fbHeight;
|
|
||||||
|
|
||||||
|
|
||||||
glm::mat4 projMat;
|
updateDeferredTransformBuffer(renderContext);
|
||||||
Transform viewMat;
|
|
||||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
|
||||||
args->_viewFrustum->evalViewTransform(viewMat);
|
|
||||||
batch.setProjectionTransform(projMat);
|
|
||||||
batch.setViewTransform(viewMat);
|
|
||||||
batch.setModelTransform(Transform());
|
|
||||||
|
|
||||||
// Occlusion step
|
// Eval the mono projection
|
||||||
getOcclusionPipeline();
|
mat4 monoProjMat;
|
||||||
batch.setResourceTexture(0, framebufferCache->getPrimaryDepthTexture());
|
args->_viewFrustum->evalProjectionMatrix(monoProjMat);
|
||||||
batch.setResourceTexture(1, framebufferCache->getDeferredNormalTexture());
|
|
||||||
/*_occlusionBuffer->setRenderBuffer(0, _occlusionTexture);
|
setClipInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
|
||||||
batch.setFramebuffer(_occlusionBuffer);
|
_parametersBuffer.edit<Parameters>()._projection = monoProjMat;
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
auto pyramidPipeline = getPyramidPipeline();
|
||||||
|
auto occlusionPipeline = getOcclusionPipeline();
|
||||||
|
|
||||||
|
gpu::doInBatch(args->_context, [=](gpu::Batch& batch) {
|
||||||
|
batch.enableStereo(false);
|
||||||
|
|
||||||
|
batch.setUniformBuffer(AmbientOcclusionEffect_DeferredTransformSlot, _deferredTransformBuffer[0]);
|
||||||
|
|
||||||
|
|
||||||
|
batch.setViewportTransform(args->_viewport);
|
||||||
|
batch.setProjectionTransform(glm::mat4());
|
||||||
|
batch.setViewTransform(Transform());
|
||||||
|
|
||||||
|
Transform model;
|
||||||
|
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
|
||||||
|
model.setScale(glm::vec3(sWidth, tHeight, 1.0));
|
||||||
|
batch.setModelTransform(model);
|
||||||
|
|
||||||
|
batch.setUniformBuffer(AmbientOcclusionEffect_ParamsSlot, _parametersBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
// Pyramid pass
|
||||||
|
batch.setFramebuffer(pyramidFBO);
|
||||||
|
batch.setPipeline(pyramidPipeline);
|
||||||
|
batch.setResourceTexture(AmbientOcclusionEffect_DepthMapSlot, depthBuffer);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
|
//
|
||||||
|
batch.setFramebuffer(occlusionFBO);
|
||||||
|
batch.generateTextureMips(pyramidFBO->getRenderBuffer(0));
|
||||||
|
|
||||||
|
// Occlusion pass
|
||||||
|
batch.setPipeline(occlusionPipeline);
|
||||||
|
batch.setResourceTexture(AmbientOcclusionEffect_PyramidMapSlot, pyramidFBO->getRenderBuffer(0));
|
||||||
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,56 +16,6 @@
|
||||||
|
|
||||||
#include "render/DrawTask.h"
|
#include "render/DrawTask.h"
|
||||||
|
|
||||||
class AmbientOcclusion {
|
|
||||||
public:
|
|
||||||
|
|
||||||
AmbientOcclusion();
|
|
||||||
|
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
|
||||||
typedef render::Job::Model<AmbientOcclusion> JobModel;
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& getOcclusionPipeline();
|
|
||||||
const gpu::PipelinePointer& getHBlurPipeline();
|
|
||||||
const gpu::PipelinePointer& getVBlurPipeline();
|
|
||||||
const gpu::PipelinePointer& getBlendPipeline();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Uniforms for AO
|
|
||||||
gpu::int32 _gScaleLoc;
|
|
||||||
gpu::int32 _gBiasLoc;
|
|
||||||
gpu::int32 _gSampleRadiusLoc;
|
|
||||||
gpu::int32 _gIntensityLoc;
|
|
||||||
|
|
||||||
gpu::int32 _nearLoc;
|
|
||||||
gpu::int32 _depthScaleLoc;
|
|
||||||
gpu::int32 _depthTexCoordOffsetLoc;
|
|
||||||
gpu::int32 _depthTexCoordScaleLoc;
|
|
||||||
gpu::int32 _renderTargetResLoc;
|
|
||||||
gpu::int32 _renderTargetResInvLoc;
|
|
||||||
|
|
||||||
|
|
||||||
float g_scale;
|
|
||||||
float g_bias;
|
|
||||||
float g_sample_rad;
|
|
||||||
float g_intensity;
|
|
||||||
|
|
||||||
gpu::PipelinePointer _occlusionPipeline;
|
|
||||||
gpu::PipelinePointer _hBlurPipeline;
|
|
||||||
gpu::PipelinePointer _vBlurPipeline;
|
|
||||||
gpu::PipelinePointer _blendPipeline;
|
|
||||||
|
|
||||||
gpu::FramebufferPointer _occlusionBuffer;
|
|
||||||
gpu::FramebufferPointer _hBlurBuffer;
|
|
||||||
gpu::FramebufferPointer _vBlurBuffer;
|
|
||||||
|
|
||||||
gpu::TexturePointer _occlusionTexture;
|
|
||||||
gpu::TexturePointer _hBlurTexture;
|
|
||||||
gpu::TexturePointer _vBlurTexture;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class AmbientOcclusionEffect {
|
class AmbientOcclusionEffect {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -74,24 +24,41 @@ public:
|
||||||
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
|
||||||
typedef render::Job::Model<AmbientOcclusionEffect> JobModel;
|
typedef render::Job::Model<AmbientOcclusionEffect> JobModel;
|
||||||
|
|
||||||
const gpu::PipelinePointer& getGenerateDepthPipeline();
|
|
||||||
const gpu::PipelinePointer& getOcclusionPipeline();
|
|
||||||
const gpu::PipelinePointer& getHBlurPipeline();
|
|
||||||
const gpu::PipelinePointer& getVBlurPipeline();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void setClipInfo(float nearZ, float farZ);
|
||||||
|
|
||||||
// Class describing the uniform buffer with all the parameters common to the AO shaders
|
// Class describing the uniform buffer with all the parameters common to the AO shaders
|
||||||
class Parameters {
|
class Parameters {
|
||||||
public:
|
public:
|
||||||
glm::vec4 spareB;
|
glm::vec4 _clipInfo;
|
||||||
|
glm::mat4 _projection;
|
||||||
|
|
||||||
Parameters() {}
|
Parameters() {}
|
||||||
};
|
};
|
||||||
typedef gpu::BufferView UniformBufferView;
|
typedef gpu::BufferView UniformBufferView;
|
||||||
gpu::BufferView _parametersBuffer;
|
gpu::BufferView _parametersBuffer;
|
||||||
|
|
||||||
gpu::PipelinePointer _generateDepthPipeline;
|
// Class describing the uniform buffer with all the parameters common to the deferred shaders
|
||||||
|
class DeferredTransform {
|
||||||
|
public:
|
||||||
|
glm::mat4 projection;
|
||||||
|
glm::mat4 viewInverse;
|
||||||
|
float stereoSide{ 0.f };
|
||||||
|
float spareA, spareB, spareC;
|
||||||
|
|
||||||
|
DeferredTransform() {}
|
||||||
|
};
|
||||||
|
UniformBufferView _deferredTransformBuffer[2];
|
||||||
|
void updateDeferredTransformBuffer(const render::RenderContextPointer& renderContext);
|
||||||
|
|
||||||
|
|
||||||
|
const gpu::PipelinePointer& getPyramidPipeline();
|
||||||
|
const gpu::PipelinePointer& getOcclusionPipeline();
|
||||||
|
const gpu::PipelinePointer& getHBlurPipeline();
|
||||||
|
const gpu::PipelinePointer& getVBlurPipeline();
|
||||||
|
|
||||||
|
gpu::PipelinePointer _pyramidPipeline;
|
||||||
gpu::PipelinePointer _occlusionPipeline;
|
gpu::PipelinePointer _occlusionPipeline;
|
||||||
gpu::PipelinePointer _hBlurPipeline;
|
gpu::PipelinePointer _hBlurPipeline;
|
||||||
gpu::PipelinePointer _vBlurPipeline;
|
gpu::PipelinePointer _vBlurPipeline;
|
||||||
|
|
|
@ -31,7 +31,8 @@ enum Slots {
|
||||||
Normal,
|
Normal,
|
||||||
Specular,
|
Specular,
|
||||||
Depth,
|
Depth,
|
||||||
Lighting
|
Lighting,
|
||||||
|
Pyramid
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string DEEFAULT_DIFFUSE_SHADER {
|
static const std::string DEEFAULT_DIFFUSE_SHADER {
|
||||||
|
@ -69,6 +70,12 @@ static const std::string DEEFAULT_LIGHTING_SHADER {
|
||||||
" return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
|
" return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);"
|
||||||
" }"
|
" }"
|
||||||
};
|
};
|
||||||
|
static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER {
|
||||||
|
"vec4 getFragmentColor() {"
|
||||||
|
" return vec4(vec3(1.0 - texture(pyramidMap, uv).x * 0.01), 1.0);"
|
||||||
|
//" return vec4(vec3(1.0 - textureLod(pyramidMap, uv, 3).x * 0.01), 1.0);"
|
||||||
|
" }"
|
||||||
|
};
|
||||||
static const std::string DEEFAULT_CUSTOM_SHADER {
|
static const std::string DEEFAULT_CUSTOM_SHADER {
|
||||||
"vec4 getFragmentColor() {"
|
"vec4 getFragmentColor() {"
|
||||||
" return vec4(1.0, 0.0, 0.0, 1.0);"
|
" return vec4(1.0, 0.0, 0.0, 1.0);"
|
||||||
|
@ -111,6 +118,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string cus
|
||||||
return DEEFAULT_DEPTH_SHADER;
|
return DEEFAULT_DEPTH_SHADER;
|
||||||
case LightingMode:
|
case LightingMode:
|
||||||
return DEEFAULT_LIGHTING_SHADER;
|
return DEEFAULT_LIGHTING_SHADER;
|
||||||
|
case AmbientOcclusionMode:
|
||||||
|
return DEFAULT_AMBIENT_OCCLUSION_SHADER;
|
||||||
case CustomMode:
|
case CustomMode:
|
||||||
return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER);
|
return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER);
|
||||||
}
|
}
|
||||||
|
@ -158,6 +167,7 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::st
|
||||||
slotBindings.insert(gpu::Shader::Binding("specularMap", Specular));
|
slotBindings.insert(gpu::Shader::Binding("specularMap", Specular));
|
||||||
slotBindings.insert(gpu::Shader::Binding("depthMap", Depth));
|
slotBindings.insert(gpu::Shader::Binding("depthMap", Depth));
|
||||||
slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting));
|
slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding("pyramidMap", Pyramid));
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
auto pipeline = gpu::Pipeline::create(program, std::make_shared<gpu::State>());
|
auto pipeline = gpu::Pipeline::create(program, std::make_shared<gpu::State>());
|
||||||
|
@ -205,6 +215,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
|
||||||
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
|
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());
|
||||||
batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture());
|
batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture());
|
||||||
batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture());
|
batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture());
|
||||||
|
batch.setResourceTexture(Pyramid, framebufferCache->getDepthPyramidTexture());
|
||||||
|
|
||||||
const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
|
const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y);
|
const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y);
|
||||||
|
|
|
@ -33,6 +33,7 @@ private:
|
||||||
NormalMode,
|
NormalMode,
|
||||||
DepthMode,
|
DepthMode,
|
||||||
LightingMode,
|
LightingMode,
|
||||||
|
AmbientOcclusionMode,
|
||||||
|
|
||||||
CustomMode // Needs to stay last
|
CustomMode // Needs to stay last
|
||||||
};
|
};
|
||||||
|
|
|
@ -92,7 +92,7 @@ DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec
|
||||||
frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0));
|
frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0));
|
||||||
|
|
||||||
frag.diffuse = frag.diffuseVal.xyz;
|
frag.diffuse = frag.diffuseVal.xyz;
|
||||||
frag.opacity = frag.diffuseVal.w;
|
frag.opacity = frag.normalVal.w;
|
||||||
frag.specular = frag.specularVal.xyz;
|
frag.specular = frag.specularVal.xyz;
|
||||||
frag.gloss = frag.specularVal.w;
|
frag.gloss = frag.specularVal.w;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,8 @@ void FramebufferCache::setFrameBufferSize(QSize frameBufferSize) {
|
||||||
_cachedFramebuffers.clear();
|
_cachedFramebuffers.clear();
|
||||||
_lightingTexture.reset();
|
_lightingTexture.reset();
|
||||||
_lightingFramebuffer.reset();
|
_lightingFramebuffer.reset();
|
||||||
|
_depthPyramidFramebuffer.reset();
|
||||||
|
_depthPyramidTexture.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +98,14 @@ void FramebufferCache::createPrimaryFramebuffer() {
|
||||||
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
_lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
|
_lightingFramebuffer->setRenderBuffer(0, _lightingTexture);
|
||||||
_lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
_lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||||
|
|
||||||
|
|
||||||
|
// For AO:
|
||||||
|
_depthPyramidTexture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element(gpu::SCALAR, gpu::HALF, gpu::RGB), width, height, smoothSampler));
|
||||||
|
_depthPyramidFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create());
|
||||||
|
_depthPyramidFramebuffer->setRenderBuffer(0, _depthPyramidTexture);
|
||||||
|
_depthPyramidFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() {
|
gpu::FramebufferPointer FramebufferCache::getPrimaryFramebuffer() {
|
||||||
|
@ -197,3 +207,17 @@ gpu::FramebufferPointer FramebufferCache::getSelfieFramebuffer() {
|
||||||
}
|
}
|
||||||
return _selfieFramebuffer;
|
return _selfieFramebuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpu::FramebufferPointer FramebufferCache::getDepthPyramidFramebuffer() {
|
||||||
|
if (!_depthPyramidFramebuffer) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _depthPyramidFramebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu::TexturePointer FramebufferCache::getDepthPyramidTexture() {
|
||||||
|
if (!_depthPyramidTexture) {
|
||||||
|
createPrimaryFramebuffer();
|
||||||
|
}
|
||||||
|
return _depthPyramidTexture;
|
||||||
|
}
|
|
@ -41,6 +41,8 @@ public:
|
||||||
gpu::TexturePointer getDeferredNormalTexture();
|
gpu::TexturePointer getDeferredNormalTexture();
|
||||||
gpu::TexturePointer getDeferredSpecularTexture();
|
gpu::TexturePointer getDeferredSpecularTexture();
|
||||||
|
|
||||||
|
gpu::FramebufferPointer getDepthPyramidFramebuffer();
|
||||||
|
gpu::TexturePointer getDepthPyramidTexture();
|
||||||
|
|
||||||
gpu::TexturePointer getLightingTexture();
|
gpu::TexturePointer getLightingTexture();
|
||||||
gpu::FramebufferPointer getLightingFramebuffer();
|
gpu::FramebufferPointer getLightingFramebuffer();
|
||||||
|
@ -83,6 +85,9 @@ private:
|
||||||
|
|
||||||
gpu::FramebufferPointer _selfieFramebuffer;
|
gpu::FramebufferPointer _selfieFramebuffer;
|
||||||
|
|
||||||
|
gpu::FramebufferPointer _depthPyramidFramebuffer;
|
||||||
|
gpu::TexturePointer _depthPyramidTexture;
|
||||||
|
|
||||||
QSize _frameBufferSize{ 100, 100 };
|
QSize _frameBufferSize{ 100, 100 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
#include "FramebufferCache.h"
|
#include "FramebufferCache.h"
|
||||||
|
|
||||||
|
const int ToneMappingEffect_ParamsSlot = 0;
|
||||||
|
const int ToneMappingEffect_LightingMapSlot = 0;
|
||||||
|
|
||||||
ToneMappingEffect::ToneMappingEffect() {
|
ToneMappingEffect::ToneMappingEffect() {
|
||||||
Parameters parameters;
|
Parameters parameters;
|
||||||
|
@ -91,7 +93,8 @@ void ToneMappingEffect::init() {
|
||||||
auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS));
|
auto blitProgram = gpu::ShaderPointer(gpu::Shader::createProgram(blitVS, blitPS));
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), 3));
|
slotBindings.insert(gpu::Shader::Binding(std::string("toneMappingParamsBuffer"), ToneMappingEffect_ParamsSlot));
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), ToneMappingEffect_LightingMapSlot));
|
||||||
gpu::Shader::makeProgram(*blitProgram, slotBindings);
|
gpu::Shader::makeProgram(*blitProgram, slotBindings);
|
||||||
auto blitState = std::make_shared<gpu::State>();
|
auto blitState = std::make_shared<gpu::State>();
|
||||||
blitState->setColorWriteMask(true, true, true, true);
|
blitState->setColorWriteMask(true, true, true, true);
|
||||||
|
@ -138,8 +141,8 @@ void ToneMappingEffect::render(RenderArgs* args) {
|
||||||
batch.setModelTransform(model);
|
batch.setModelTransform(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.setUniformBuffer(3, _parametersBuffer);
|
batch.setUniformBuffer(ToneMappingEffect_ParamsSlot, _parametersBuffer);
|
||||||
batch.setResourceTexture(0, lightingBuffer);
|
batch.setResourceTexture(ToneMappingEffect_LightingMapSlot, lightingBuffer);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -14,6 +14,8 @@
|
||||||
|
|
||||||
<@include DeferredBuffer.slh@>
|
<@include DeferredBuffer.slh@>
|
||||||
|
|
||||||
|
uniform sampler2D pyramidMap;
|
||||||
|
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
out vec4 outFragColor;
|
out vec4 outFragColor;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue