Blend function applied to reduce one FBO

This commit is contained in:
Niraj Venkat 2015-07-24 16:07:30 -07:00
parent fc612ab8cd
commit 5dd16d9f80
4 changed files with 8 additions and 241 deletions

View file

@ -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
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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);
}