phoenix-firestorm/indra/newview/exopostprocess.cpp

204 lines
5.2 KiB
C++

/**
* @file exopostprocess.cpp
*
* @brief This implements the Exodus post processing chain.
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Copyright (C) 2011 Geenz Spad
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "exopostprocess.h"
#include "llviewershadermgr.h"
#include "pipeline.h"
#include "llviewercontrol.h"
static LLStaticHashedString sScreen_Res("screen_res");
LLVector3 exoPostProcess::sExodusRenderVignette;
exoPostProcess::exoPostProcess()
{
initVB();
sExodusRenderVignette = LLVector3(0.f, 0.f, 0.f);
}
exoPostProcess::~exoPostProcess()
{
destroyVB();
}
void exoPostProcess::ExodusRenderPostStack(LLRenderTarget *src, LLRenderTarget *dst)
{
if (mShaderLevel > 0)
{
if (sExodusRenderVignette.mV[0] > 0.f && LLPipeline::sRenderDeferred)
ExodusRenderVignette(src, dst); // Don't render vignette here in non-deferred. Do it in the glow combine shader.
}
}
void exoPostProcess::ExodusRenderPostSettingsUpdate()
{
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
sExodusRenderVignette = gSavedSettings.getVector3("FSRenderVignette");
}
void exoPostProcess::ExodusRenderPostUpdate()
{
if (!gPipeline.mRT)
return;
etc1.setVec(0.f, 0.f);
etc2.setVec((F32) gPipeline.mRT->screen.getWidth(), (F32) gPipeline.mRT->screen.getHeight());
initVB();
}
void exoPostProcess::initVB()
{
destroyVB();
mExoPostBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1, 0);
if (!gPipeline.sRenderDeferred)
{
if (mExoPostBuffer->allocateBuffer(3, 0, true))
{
LLStrider<LLVector3> v;
LLStrider<LLVector2> uv1;
LLStrider<LLVector2> uv2;
mExoPostBuffer->getVertexStrider(v);
mExoPostBuffer->getTexCoord0Strider(uv1);
mExoPostBuffer->getTexCoord1Strider(uv2);
uv1[0] = LLVector2(0.f, 0.f);
uv1[1] = LLVector2(0.f, 2.f);
uv1[2] = LLVector2(2.f, 0.f);
uv2[0] = LLVector2(0.f, 0.f);
uv2[1] = LLVector2(0.f, etc2.mV[1] * 2.f);
uv2[2] = LLVector2(etc2.mV[0] * 2.f, 0.f);
v[0] = LLVector3(-1.f, -1.f, 0.f);
v[1] = LLVector3(-1.f, 3.f, 0.f);
v[2] = LLVector3(3.f, -1.f, 0.f);
mExoPostBuffer->flush();
}
else
{
LL_WARNS() << "Failed to allocate Vertex Buffer for exoPostProcessing" << LL_ENDL;
destroyVB();
}
}
else
{
if (mExoPostBuffer->allocateBuffer(8, 0, true))
{
LLStrider<LLVector3> vert;
mExoPostBuffer->getVertexStrider(vert);
LLStrider<LLVector2> tc0;
LLStrider<LLVector2> tc1;
mExoPostBuffer->getTexCoord0Strider(tc0);
mExoPostBuffer->getTexCoord1Strider(tc1);
vert[0].set(-1.f, 1.f, 0.f);
vert[1].set(-1.f, -3.f, 0.f);
vert[2].set(3.f, 1.f, 0.f);
}
else
{
LL_WARNS() << "Failed to allocate Vertex Buffer for exoPostProcessing" << LL_ENDL;
destroyVB();
}
}
}
void exoPostProcess::destroyVB()
{
mExoPostBuffer = NULL;
}
void exoPostProcess::ExodusRenderPost(LLRenderTarget* src, LLRenderTarget* dst, S32 type)
{
if (type == EXODUS_RENDER_VIGNETTE_POST)
{
ExodusRenderVignette(src, dst);
}
}
void exoPostProcess::ExodusRenderVignette(LLRenderTarget* src, LLRenderTarget* dst)
{
if (mExoPostBuffer)
{
dst->bindTarget();
LLGLSLShader *shader = &gPostVignetteProgram;
shader->bind();
mExoPostBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX);
exoShader::BindRenderTarget(dst, shader, LLShaderMgr::EXO_RENDER_SCREEN);
shader->uniform3fv(LLShaderMgr::EXO_RENDER_VIGNETTE, 1, sExodusRenderVignette.mV);
mExoPostBuffer->drawArrays(LLRender::TRIANGLES, 0, 3);
stop_glerror();
shader->unbind();
dst->flush();
}
}
void exoShader::BindTex2D(LLTexture *tex2D, LLGLSLShader *shader, S32 uniform, S32 unit, LLTexUnit::eTextureType mode, LLTexUnit::eTextureAddressMode addressMode, LLTexUnit::eTextureFilterOptions filterMode)
{
if (gPipeline.sRenderDeferred)
{
S32 channel = 0;
channel = shader->enableTexture(uniform);
if (channel > -1)
{
gGL.getTexUnit(channel)->bind(tex2D);
gGL.getTexUnit(channel)->setTextureFilteringOption(filterMode);
gGL.getTexUnit(channel)->setTextureAddressMode(addressMode);
}
}
else
{
gGL.getTexUnit(unit)->bind(tex2D);
}
}
void exoShader::BindRenderTarget(LLRenderTarget* tgt, LLGLSLShader* shader, S32 uniform, S32 unit, LLTexUnit::eTextureType mode)
{
if (gPipeline.sRenderDeferred)
{
S32 channel = 0;
channel = shader->enableTexture(uniform, tgt->getUsage());
if (channel > -1)
{
tgt->bindTexture(0,channel);
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
}
}
else
{
S32 reftex = shader->enableTexture(uniform, tgt->getUsage());
if (reftex > -1)
{
gGL.getTexUnit(reftex)->activate();
gGL.getTexUnit(reftex)->bind(tgt);
gGL.getTexUnit(0)->activate();
}
}
shader->uniform2f(sScreen_Res, tgt->getWidth(), tgt->getHeight());
}