mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 00:43:30 +02:00
Blend function applied to reduce one FBO
This commit is contained in:
parent
fc612ab8cd
commit
5dd16d9f80
4 changed files with 8 additions and 241 deletions
|
@ -32,150 +32,8 @@
|
|||
#include "gaussian_blur_vertical_vert.h"
|
||||
#include "gaussian_blur_horizontal_vert.h"
|
||||
#include "gaussian_blur_frag.h"
|
||||
#include "occlusion_blend_vert.h"
|
||||
#include "occlusion_blend_frag.h"
|
||||
//#include "occlusion_result_vert.h"
|
||||
#include "occlusion_result_frag.h"
|
||||
|
||||
/*
|
||||
void AmbientOcclusionEffect::init(AbstractViewStateInterface* viewState) {
|
||||
_viewState = viewState; // we will use this for view state services
|
||||
|
||||
_occlusionProgram = new ProgramObject();
|
||||
_occlusionProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath()
|
||||
+ "shaders/ambient_occlusion.vert");
|
||||
_occlusionProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath()
|
||||
+ "shaders/ambient_occlusion.frag");
|
||||
_occlusionProgram->link();
|
||||
|
||||
// create the sample kernel: an array of hemispherically distributed offset vectors
|
||||
const int SAMPLE_KERNEL_SIZE = 16;
|
||||
QVector3D sampleKernel[SAMPLE_KERNEL_SIZE];
|
||||
for (int i = 0; i < SAMPLE_KERNEL_SIZE; i++) {
|
||||
// square the length in order to increase density towards the center
|
||||
glm::vec3 vector = glm::sphericalRand(1.0f);
|
||||
float scale = randFloat();
|
||||
const float MIN_VECTOR_LENGTH = 0.01f;
|
||||
const float MAX_VECTOR_LENGTH = 1.0f;
|
||||
vector *= glm::mix(MIN_VECTOR_LENGTH, MAX_VECTOR_LENGTH, scale * scale);
|
||||
sampleKernel[i] = QVector3D(vector.x, vector.y, vector.z);
|
||||
}
|
||||
|
||||
_occlusionProgram->bind();
|
||||
_occlusionProgram->setUniformValue("depthTexture", 0);
|
||||
_occlusionProgram->setUniformValue("rotationTexture", 1);
|
||||
_occlusionProgram->setUniformValueArray("sampleKernel", sampleKernel, SAMPLE_KERNEL_SIZE);
|
||||
_occlusionProgram->setUniformValue("radius", 0.1f);
|
||||
_occlusionProgram->release();
|
||||
|
||||
_nearLocation = _occlusionProgram->uniformLocation("near");
|
||||
_farLocation = _occlusionProgram->uniformLocation("far");
|
||||
_leftBottomLocation = _occlusionProgram->uniformLocation("leftBottom");
|
||||
_rightTopLocation = _occlusionProgram->uniformLocation("rightTop");
|
||||
_noiseScaleLocation = _occlusionProgram->uniformLocation("noiseScale");
|
||||
_texCoordOffsetLocation = _occlusionProgram->uniformLocation("texCoordOffset");
|
||||
_texCoordScaleLocation = _occlusionProgram->uniformLocation("texCoordScale");
|
||||
|
||||
// generate the random rotation texture
|
||||
glGenTextures(1, &_rotationTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||
const int ELEMENTS_PER_PIXEL = 3;
|
||||
unsigned char rotationData[ROTATION_WIDTH * ROTATION_HEIGHT * ELEMENTS_PER_PIXEL];
|
||||
unsigned char* rotation = rotationData;
|
||||
for (int i = 0; i < ROTATION_WIDTH * ROTATION_HEIGHT; i++) {
|
||||
glm::vec3 vector = glm::sphericalRand(1.0f);
|
||||
*rotation++ = ((vector.x + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((vector.y + 1.0f) / 2.0f) * 255.0f;
|
||||
*rotation++ = ((vector.z + 1.0f) / 2.0f) * 255.0f;
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, ROTATION_WIDTH, ROTATION_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, rotationData);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
_blurProgram = new ProgramObject();
|
||||
_blurProgram->addShaderFromSourceFile(QGLShader::Vertex, PathUtils::resourcesPath() + "shaders/ambient_occlusion.vert");
|
||||
_blurProgram->addShaderFromSourceFile(QGLShader::Fragment, PathUtils::resourcesPath() + "shaders/occlusion_blur.frag");
|
||||
_blurProgram->link();
|
||||
|
||||
_blurProgram->bind();
|
||||
_blurProgram->setUniformValue("originalTexture", 0);
|
||||
_blurProgram->release();
|
||||
|
||||
_blurScaleLocation = _blurProgram->uniformLocation("blurScale");
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext){
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, DependencyManager::get<TextureCache>()->getPrimaryDepthTextureID());
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _rotationTextureID);
|
||||
|
||||
// render with the occlusion shader to the secondary/tertiary buffer
|
||||
auto freeFramebuffer = nullptr; // DependencyManager::get<GlowEffect>()->getFreeFramebuffer(); // FIXME
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(freeFramebuffer));
|
||||
|
||||
float left, right, bottom, top, nearVal, farVal;
|
||||
glm::vec4 nearClipPlane, farClipPlane;
|
||||
AbstractViewStateInterface::instance()->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
|
||||
|
||||
int viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
const int VIEWPORT_X_INDEX = 0;
|
||||
const int VIEWPORT_WIDTH_INDEX = 2;
|
||||
|
||||
auto framebufferSize = DependencyManager::get<TextureCache>()->getFrameBufferSize();
|
||||
float sMin = viewport[VIEWPORT_X_INDEX] / (float)framebufferSize.width();
|
||||
float sWidth = viewport[VIEWPORT_WIDTH_INDEX] / (float)framebufferSize.width();
|
||||
|
||||
_occlusionProgram->bind();
|
||||
_occlusionProgram->setUniformValue(_nearLocation, nearVal);
|
||||
_occlusionProgram->setUniformValue(_farLocation, farVal);
|
||||
_occlusionProgram->setUniformValue(_leftBottomLocation, left, bottom);
|
||||
_occlusionProgram->setUniformValue(_rightTopLocation, right, top);
|
||||
_occlusionProgram->setUniformValue(_noiseScaleLocation, viewport[VIEWPORT_WIDTH_INDEX] / (float)ROTATION_WIDTH,
|
||||
framebufferSize.height() / (float)ROTATION_HEIGHT);
|
||||
_occlusionProgram->setUniformValue(_texCoordOffsetLocation, sMin, 0.0f);
|
||||
_occlusionProgram->setUniformValue(_texCoordScaleLocation, sWidth, 1.0f);
|
||||
|
||||
renderFullscreenQuad();
|
||||
|
||||
_occlusionProgram->release();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// now render secondary to primary with 4x4 blur
|
||||
auto primaryFramebuffer = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFramebuffer));
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
|
||||
|
||||
auto freeFramebufferTexture = freeFramebuffer->getRenderBuffer(0);
|
||||
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(freeFramebufferTexture));
|
||||
|
||||
_blurProgram->bind();
|
||||
_blurProgram->setUniformValue(_blurScaleLocation, 1.0f / framebufferSize.width(), 1.0f / framebufferSize.height());
|
||||
|
||||
renderFullscreenQuad(sMin, sMin + sWidth);
|
||||
|
||||
_blurProgram->release();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(GL_TRUE)
|
||||
}
|
||||
*/
|
||||
|
||||
AmbientOcclusion::AmbientOcclusion() {
|
||||
}
|
||||
|
@ -297,7 +155,6 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() {
|
|||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("blurredOcclusionTexture"), 0));
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 1));
|
||||
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
|
@ -306,8 +163,8 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() {
|
|||
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);
|
||||
state->setBlendFunction(true,
|
||||
gpu::State::SRC_COLOR, gpu::State::BLEND_OP_ADD, gpu::State::DEST_COLOR);
|
||||
|
||||
// Link the blend FBO to texture
|
||||
_blendBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32,
|
||||
|
@ -324,30 +181,6 @@ const gpu::PipelinePointer& AmbientOcclusion::getBlendPipeline() {
|
|||
return _blendPipeline;
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& AmbientOcclusion::getAOResultPipeline() {
|
||||
if (!_AOResultPipeline) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(ambient_occlusion_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(occlusion_result_frag)));
|
||||
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
//gpu::ShaderPointer program = gpu::StandardShaderLib::getProgram(gpu::StandardShaderLib::getDrawTransformUnitQuadVS(), gpu::StandardShaderLib::getDrawTexturePS());
|
||||
|
||||
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);
|
||||
|
||||
// Good to go add the brand new pipeline
|
||||
_AOResultPipeline.reset(gpu::Pipeline::create(program, state));
|
||||
}
|
||||
return _AOResultPipeline;
|
||||
}
|
||||
|
||||
void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
|
||||
assert(renderContext->args);
|
||||
assert(renderContext->args->_viewFrustum);
|
||||
|
@ -418,30 +251,14 @@ void AmbientOcclusion::run(const render::SceneContextPointer& sceneContext, cons
|
|||
// Blend step
|
||||
getBlendPipeline();
|
||||
batch.setResourceTexture(0, _hBlurTexture);
|
||||
batch.setResourceTexture(1, DependencyManager::get<FramebufferCache>()->getPrimaryColorTexture());
|
||||
batch.setFramebuffer(_blendBuffer);
|
||||
batch.setFramebuffer(DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer());
|
||||
|
||||
// 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);
|
||||
|
||||
// Final AO result step
|
||||
getAOResultPipeline();
|
||||
batch.setResourceTexture(0, _blendTexture);
|
||||
batch.setFramebuffer(DependencyManager::get<FramebufferCache>()->getPrimaryFramebuffer());
|
||||
|
||||
// Bind the fifth gpu::Pipeline we need - for displaying the blended texture
|
||||
batch.setPipeline(getAOResultPipeline());
|
||||
|
||||
glm::vec2 bottomLeftSmall(0.5f, -1.0f);
|
||||
glm::vec2 topRightSmall(1.0f, -0.5f);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color);
|
||||
|
||||
// Ready to render
|
||||
args->_context->syncCache();
|
||||
args->_context->render((batch));
|
||||
|
||||
// need to fetch forom the z buffer and render something in a new render target a result that combine the z and produce a fake AO result
|
||||
|
||||
}
|
||||
|
|
|
@ -17,17 +17,14 @@
|
|||
varying vec2 varTexcoord;
|
||||
|
||||
uniform sampler2D blurredOcclusionTexture;
|
||||
uniform sampler2D colorTexture;
|
||||
|
||||
void main(void) {
|
||||
vec4 occlusionColor = texture2D(blurredOcclusionTexture, varTexcoord);
|
||||
vec4 currentColor = texture2D(colorTexture, varTexcoord);
|
||||
/*
|
||||
if(occlusionColor.r == 1.0) {
|
||||
gl_FragColor = currentColor;
|
||||
|
||||
if(occlusionColor.r > 0.8 && occlusionColor.r <= 1.0) {
|
||||
gl_FragColor = vec4(vec3(0.0), 1.0);
|
||||
}
|
||||
else {
|
||||
gl_FragColor = mix(occlusionColor, currentColor, 0.5);
|
||||
}*/
|
||||
gl_FragColor = currentColor;
|
||||
gl_FragColor = vec4(vec3(0.2), 1.0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// occlusion_blend.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Niraj Venkat on 7/20/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
|
||||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
varying vec2 varTexcoord;
|
||||
|
||||
void main(void) {
|
||||
varTexcoord = gl_MultiTexCoord0.xy;
|
||||
gl_Position = gl_Vertex;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// occlusion_result.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Niraj Venkat on 7/23/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
|
||||
//
|
||||
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
varying vec2 varTexcoord;
|
||||
|
||||
uniform sampler2D resultTexture;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(resultTexture, varTexcoord);
|
||||
}
|
Loading…
Reference in a new issue