SL-19203 et al -- Integrate SSR with reflection probes, tweak probe blending. (#63)
* SL-19203 WIP -- Integrate SSR with reflection probes. Decruft LLRenderTarget. * SL-19203 WIP -- Re-integrate SSR. Incidental decruft. * SL-19203 WIP -- SSR frame delta correction (still broken for Z) * SL-19203 WIP -- SSR frame delta Z fix * SL-19203 WIP -- Make SSR toggleable again and disable SSR in cube snapshots. * SL-19203 WIP -- Soften sphere probe transitions and fix reflections on void water (make fallback probe a simple terrain+water+sky probe). Remove parallax correction for automatic probes to reduce artifacts. * SL-19203 Tune probe blending. * SL-19203 Cleanup.master
parent
503e18fc64
commit
3ef31cb9b2
|
|
@ -2270,7 +2270,7 @@ void do_assert_glerror()
|
|||
GLenum error;
|
||||
error = glGetError();
|
||||
BOOL quit = FALSE;
|
||||
while (LL_UNLIKELY(error))
|
||||
if (LL_UNLIKELY(error))
|
||||
{
|
||||
quit = TRUE;
|
||||
GLubyte const * gl_error_msg = gluErrorString(error);
|
||||
|
|
@ -2295,7 +2295,6 @@ void do_assert_glerror()
|
|||
gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
|
||||
}
|
||||
}
|
||||
error = glGetError();
|
||||
}
|
||||
|
||||
if (quit)
|
||||
|
|
|
|||
|
|
@ -55,8 +55,14 @@ F32 gGLModelView[16];
|
|||
F32 gGLLastModelView[16];
|
||||
F32 gGLLastProjection[16];
|
||||
F32 gGLProjection[16];
|
||||
|
||||
// transform from last frame's camera space to this frame's camera space (and inverse)
|
||||
F32 gGLDeltaModelView[16];
|
||||
F32 gGLInverseDeltaModelView[16];
|
||||
|
||||
S32 gGLViewport[4];
|
||||
|
||||
|
||||
U32 LLRender::sUICalls = 0;
|
||||
U32 LLRender::sUIVerts = 0;
|
||||
U32 LLTexUnit::sWhiteTexture = 0;
|
||||
|
|
@ -373,7 +379,6 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
|
|||
if (bindDepth)
|
||||
{
|
||||
llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment
|
||||
llassert(renderTarget->canSampleDepth()); // depth buffer attachment MUST be sampleable
|
||||
|
||||
bindManual(renderTarget->getUsage(), renderTarget->getDepth());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -507,6 +507,8 @@ extern F32 gGLLastModelView[16];
|
|||
extern F32 gGLLastProjection[16];
|
||||
extern F32 gGLProjection[16];
|
||||
extern S32 gGLViewport[4];
|
||||
extern F32 gGLDeltaModelView[16];
|
||||
extern F32 gGLInverseDeltaModelView[16];
|
||||
|
||||
extern thread_local LLRender gGL;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,19 +35,19 @@ U32 LLRenderTarget::sBytesAllocated = 0;
|
|||
|
||||
void check_framebuffer_status()
|
||||
{
|
||||
if (gDebugGL)
|
||||
{
|
||||
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
|
||||
switch (status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
break;
|
||||
default:
|
||||
LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
|
||||
ll_fail("check_framebuffer_status failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gDebugGL)
|
||||
{
|
||||
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
|
||||
switch (status)
|
||||
{
|
||||
case GL_FRAMEBUFFER_COMPLETE:
|
||||
break;
|
||||
default:
|
||||
LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
|
||||
ll_fail("check_framebuffer_status failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LLRenderTarget::sUseFBO = false;
|
||||
|
|
@ -60,112 +60,86 @@ U32 LLRenderTarget::sCurResX = 0;
|
|||
U32 LLRenderTarget::sCurResY = 0;
|
||||
|
||||
LLRenderTarget::LLRenderTarget() :
|
||||
mResX(0),
|
||||
mResY(0),
|
||||
mFBO(0),
|
||||
mPreviousFBO(0),
|
||||
mPreviousResX(0),
|
||||
mPreviousResY(0),
|
||||
mDepth(0),
|
||||
mUseDepth(false),
|
||||
mSampleDepth(false),
|
||||
mUsage(LLTexUnit::TT_TEXTURE)
|
||||
mResX(0),
|
||||
mResY(0),
|
||||
mFBO(0),
|
||||
mDepth(0),
|
||||
mUseDepth(false),
|
||||
mUsage(LLTexUnit::TT_TEXTURE)
|
||||
{
|
||||
}
|
||||
|
||||
LLRenderTarget::~LLRenderTarget()
|
||||
{
|
||||
release();
|
||||
release();
|
||||
}
|
||||
|
||||
void LLRenderTarget::resize(U32 resx, U32 resy)
|
||||
{
|
||||
//for accounting, get the number of pixels added/subtracted
|
||||
S32 pix_diff = (resx*resy)-(mResX*mResY);
|
||||
|
||||
mResX = resx;
|
||||
mResY = resy;
|
||||
//for accounting, get the number of pixels added/subtracted
|
||||
S32 pix_diff = (resx*resy)-(mResX*mResY);
|
||||
|
||||
mResX = resx;
|
||||
mResY = resy;
|
||||
|
||||
llassert(mInternalFormat.size() == mTex.size());
|
||||
llassert(mInternalFormat.size() == mTex.size());
|
||||
|
||||
for (U32 i = 0; i < mTex.size(); ++i)
|
||||
{ //resize color attachments
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
|
||||
sBytesAllocated += pix_diff*4;
|
||||
}
|
||||
for (U32 i = 0; i < mTex.size(); ++i)
|
||||
{ //resize color attachments
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]);
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, mInternalFormat[i], mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
|
||||
sBytesAllocated += pix_diff*4;
|
||||
}
|
||||
|
||||
if (mDepth)
|
||||
{ //resize depth attachment
|
||||
if (!mSampleDepth)
|
||||
{
|
||||
//use render buffers where stencil buffers are in play
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
|
||||
}
|
||||
if (mDepth)
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
|
||||
|
||||
sBytesAllocated += pix_diff*4;
|
||||
}
|
||||
sBytesAllocated += pix_diff*4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
|
||||
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
|
||||
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
|
||||
llassert(usage == LLTexUnit::TT_TEXTURE);
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
stop_glerror();
|
||||
release();
|
||||
stop_glerror();
|
||||
resx = llmin(resx, (U32) gGLManager.mGLMaxTextureSize);
|
||||
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
|
||||
|
||||
mResX = resx;
|
||||
mResY = resy;
|
||||
release();
|
||||
|
||||
mResX = resx;
|
||||
mResY = resy;
|
||||
|
||||
mUsage = usage;
|
||||
mUsage = usage;
|
||||
mUseDepth = depth;
|
||||
mSampleDepth = sample_depth;
|
||||
|
||||
if (depth)
|
||||
{
|
||||
if (!allocateDepth())
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sUseFBO || use_fbo))
|
||||
{
|
||||
if (depth)
|
||||
{
|
||||
if (!allocateDepth())
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate depth buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
glGenFramebuffers(1, (GLuint *) &mFBO);
|
||||
|
||||
glGenFramebuffers(1, (GLuint *) &mFBO);
|
||||
|
||||
if (mDepth)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
if (mDepth)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
|
||||
if (!canSampleDepth())
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
|
||||
stop_glerror();
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
|
||||
|
||||
return addColorAttachment(color_fmt);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
return addColorAttachment(color_fmt);
|
||||
}
|
||||
|
||||
void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
|
||||
|
|
@ -175,6 +149,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
|
|||
llassert(sUseFBO); // FBO support must be enabled
|
||||
llassert(mDepth == 0); // depth buffers not supported with this mode
|
||||
llassert(mTex.empty()); // mTex must be empty with this mode (binding target should be done via LLImageGL)
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
if (mFBO == 0)
|
||||
{
|
||||
|
|
@ -205,6 +180,7 @@ void LLRenderTarget::setColorAttachment(LLImageGL* img, LLGLuint use_name)
|
|||
void LLRenderTarget::releaseColorAttachment()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
llassert(!isBoundInStack());
|
||||
llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
|
||||
llassert(mFBO != 0); // mFBO must be valid
|
||||
|
||||
|
|
@ -218,323 +194,291 @@ void LLRenderTarget::releaseColorAttachment()
|
|||
bool LLRenderTarget::addColorAttachment(U32 color_fmt)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (color_fmt == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
U32 offset = mTex.size();
|
||||
if (color_fmt == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if( offset >= 4 )
|
||||
{
|
||||
LL_WARNS() << "Too many color attachments" << LL_ENDL;
|
||||
llassert( offset < 4 );
|
||||
return false;
|
||||
}
|
||||
if( offset > 0 && (mFBO == 0) )
|
||||
{
|
||||
llassert( mFBO != 0 );
|
||||
return false;
|
||||
}
|
||||
U32 offset = mTex.size();
|
||||
|
||||
U32 tex;
|
||||
LLImageGL::generateTextures(1, &tex);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, tex);
|
||||
if( offset >= 4 )
|
||||
{
|
||||
LL_WARNS() << "Too many color attachments" << LL_ENDL;
|
||||
llassert( offset < 4 );
|
||||
return false;
|
||||
}
|
||||
if( offset > 0 && (mFBO == 0) )
|
||||
{
|
||||
llassert( mFBO != 0 );
|
||||
return false;
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
U32 tex;
|
||||
LLImageGL::generateTextures(1, &tex);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, tex);
|
||||
|
||||
stop_glerror();
|
||||
|
||||
|
||||
{
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sBytesAllocated += mResX*mResY*4;
|
||||
{
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
LL_WARNS() << "Could not allocate color buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sBytesAllocated += mResX*mResY*4;
|
||||
|
||||
stop_glerror();
|
||||
stop_glerror();
|
||||
|
||||
|
||||
if (offset == 0)
|
||||
{ //use bilinear filtering on single texture render targets that aren't multisampled
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{ //don't filter data attachments
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (offset == 0)
|
||||
{ //use bilinear filtering on single texture render targets that aren't multisampled
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{ //don't filter data attachments
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
|
||||
{
|
||||
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ATI doesn't support mirrored repeat for rectangular textures.
|
||||
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (mFBO)
|
||||
{
|
||||
stop_glerror();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
|
||||
LLTexUnit::getInternalType(mUsage), tex, 0);
|
||||
stop_glerror();
|
||||
if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
|
||||
{
|
||||
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{
|
||||
// ATI doesn't support mirrored repeat for rectangular textures.
|
||||
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if (mFBO)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
|
||||
LLTexUnit::getInternalType(mUsage), tex, 0);
|
||||
|
||||
check_framebuffer_status();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
check_framebuffer_status();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
mTex.push_back(tex);
|
||||
mInternalFormat.push_back(color_fmt);
|
||||
|
||||
mTex.push_back(tex);
|
||||
mInternalFormat.push_back(color_fmt);
|
||||
|
||||
if (gDebugGL)
|
||||
{ //bind and unbind to validate target
|
||||
bindTarget();
|
||||
flush();
|
||||
}
|
||||
if (gDebugGL)
|
||||
{ //bind and unbind to validate target
|
||||
bindTarget();
|
||||
flush();
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLRenderTarget::allocateDepth()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (!mSampleDepth)
|
||||
{
|
||||
//use render buffers if depth buffer won't be sampled
|
||||
glGenRenderbuffers(1, (GLuint *) &mDepth);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, mDepth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mResX, mResY);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLImageGL::generateTextures(1, &mDepth);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
|
||||
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
stop_glerror();
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
}
|
||||
LLImageGL::generateTextures(1, &mDepth);
|
||||
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
|
||||
|
||||
U32 internal_type = LLTexUnit::getInternalType(mUsage);
|
||||
stop_glerror();
|
||||
clear_glerror();
|
||||
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
|
||||
sBytesAllocated += mResX*mResY*4;
|
||||
sBytesAllocated += mResX*mResY*4;
|
||||
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
LL_WARNS() << "Unable to allocate depth buffer for render target." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
|
||||
{
|
||||
if (!mFBO || !target.mFBO)
|
||||
{
|
||||
LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
|
||||
}
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
if (target.mDepth)
|
||||
{
|
||||
LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
|
||||
}
|
||||
if (!mFBO || !target.mFBO)
|
||||
{
|
||||
LL_ERRS() << "Cannot share depth buffer between non FBO render targets." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (target.mUseDepth)
|
||||
{
|
||||
LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
|
||||
}
|
||||
if (target.mDepth)
|
||||
{
|
||||
LL_ERRS() << "Attempting to override existing depth buffer. Detach existing buffer first." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (mDepth)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
|
||||
|
||||
if (!mSampleDepth)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
|
||||
}
|
||||
if (target.mUseDepth)
|
||||
{
|
||||
LL_ERRS() << "Attempting to override existing shared depth buffer. Detach existing buffer first." << LL_ENDL;
|
||||
}
|
||||
|
||||
check_framebuffer_status();
|
||||
if (mDepth)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
check_framebuffer_status();
|
||||
|
||||
target.mUseDepth = true;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
|
||||
target.mUseDepth = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LLRenderTarget::release()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
|
||||
if (mDepth)
|
||||
{
|
||||
if (!mSampleDepth)
|
||||
{
|
||||
glDeleteRenderbuffers(1, (GLuint*) &mDepth);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLImageGL::deleteTextures(1, &mDepth);
|
||||
}
|
||||
mDepth = 0;
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
}
|
||||
else if (mFBO)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
if (mDepth)
|
||||
{
|
||||
LLImageGL::deleteTextures(1, &mDepth);
|
||||
|
||||
mDepth = 0;
|
||||
|
||||
if (mUseDepth)
|
||||
{ //detach shared depth buffer
|
||||
if (!mSampleDepth)
|
||||
{ //attached as a renderbuffer
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
|
||||
mSampleDepth = false;
|
||||
}
|
||||
else
|
||||
{ //attached as a texture
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
|
||||
}
|
||||
mUseDepth = false;
|
||||
}
|
||||
}
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
}
|
||||
else if (mFBO)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
|
||||
// Detach any extra color buffers (e.g. SRGB spec buffers)
|
||||
//
|
||||
if (mFBO && (mTex.size() > 1))
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
S32 z;
|
||||
for (z = mTex.size() - 1; z >= 1; z--)
|
||||
{
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0);
|
||||
stop_glerror();
|
||||
LLImageGL::deleteTextures(1, &mTex[z]);
|
||||
}
|
||||
}
|
||||
if (mUseDepth)
|
||||
{ //detach shared depth buffer
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
|
||||
mUseDepth = false;
|
||||
}
|
||||
|
||||
if (mFBO)
|
||||
{
|
||||
glDeleteFramebuffers(1, (GLuint *) &mFBO);
|
||||
stop_glerror();
|
||||
mFBO = 0;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
if (mTex.size() > 0)
|
||||
{
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
LLImageGL::deleteTextures(1, &mTex[0]);
|
||||
}
|
||||
// Detach any extra color buffers (e.g. SRGB spec buffers)
|
||||
//
|
||||
if (mFBO && (mTex.size() > 1))
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
S32 z;
|
||||
for (z = mTex.size() - 1; z >= 1; z--)
|
||||
{
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0);
|
||||
LLImageGL::deleteTextures(1, &mTex[z]);
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
|
||||
}
|
||||
|
||||
mTex.clear();
|
||||
mInternalFormat.clear();
|
||||
|
||||
mResX = mResY = 0;
|
||||
if (mFBO == sCurFBO)
|
||||
{
|
||||
sCurFBO = 0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
sBoundTarget = NULL;
|
||||
if (mFBO)
|
||||
{
|
||||
glDeleteFramebuffers(1, (GLuint *) &mFBO);
|
||||
mFBO = 0;
|
||||
}
|
||||
|
||||
if (mTex.size() > 0)
|
||||
{
|
||||
sBytesAllocated -= mResX*mResY*4;
|
||||
LLImageGL::deleteTextures(1, &mTex[0]);
|
||||
}
|
||||
|
||||
mTex.clear();
|
||||
mInternalFormat.clear();
|
||||
|
||||
mResX = mResY = 0;
|
||||
}
|
||||
|
||||
void LLRenderTarget::bindTarget()
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("bindTarget");
|
||||
llassert(mFBO);
|
||||
llassert(!isBoundInStack());
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
sCurFBO = mFBO;
|
||||
|
||||
if (mFBO)
|
||||
{
|
||||
stop_glerror();
|
||||
|
||||
mPreviousFBO = sCurFBO;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||
sCurFBO = mFBO;
|
||||
|
||||
stop_glerror();
|
||||
//setup multiple render targets
|
||||
GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_COLOR_ATTACHMENT2,
|
||||
GL_COLOR_ATTACHMENT3};
|
||||
glDrawBuffers(mTex.size(), drawbuffers);
|
||||
|
||||
if (mTex.empty())
|
||||
{ //no color buffer to draw to
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
}
|
||||
//setup multiple render targets
|
||||
GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
|
||||
GL_COLOR_ATTACHMENT1,
|
||||
GL_COLOR_ATTACHMENT2,
|
||||
GL_COLOR_ATTACHMENT3};
|
||||
glDrawBuffers(mTex.size(), drawbuffers);
|
||||
|
||||
if (mTex.empty())
|
||||
{ //no color buffer to draw to
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
}
|
||||
|
||||
check_framebuffer_status();
|
||||
check_framebuffer_status();
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
glViewport(0, 0, mResX, mResY);
|
||||
sCurResX = mResX;
|
||||
sCurResY = mResY;
|
||||
|
||||
mPreviousResX = sCurResX;
|
||||
mPreviousResY = sCurResY;
|
||||
glViewport(0, 0, mResX, mResY);
|
||||
sCurResX = mResX;
|
||||
sCurResY = mResY;
|
||||
|
||||
sBoundTarget = this;
|
||||
mPreviousRT = sBoundTarget;
|
||||
sBoundTarget = this;
|
||||
}
|
||||
|
||||
void LLRenderTarget::clear(U32 mask_in)
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("clear");
|
||||
llassert(mFBO);
|
||||
U32 mask = GL_COLOR_BUFFER_BIT;
|
||||
if (mUseDepth)
|
||||
{
|
||||
mask |= GL_DEPTH_BUFFER_BIT; // stencil buffer is deprecated, performance pnealty | GL_STENCIL_BUFFER_BIT;
|
||||
U32 mask = GL_COLOR_BUFFER_BIT;
|
||||
if (mUseDepth)
|
||||
{
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
}
|
||||
if (mFBO)
|
||||
{
|
||||
check_framebuffer_status();
|
||||
stop_glerror();
|
||||
glClear(mask & mask_in);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLEnable scissor(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, mResX, mResY);
|
||||
stop_glerror();
|
||||
glClear(mask & mask_in);
|
||||
}
|
||||
}
|
||||
if (mFBO)
|
||||
{
|
||||
check_framebuffer_status();
|
||||
stop_glerror();
|
||||
glClear(mask & mask_in);
|
||||
stop_glerror();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLEnable scissor(GL_SCISSOR_TEST);
|
||||
glScissor(0, 0, mResX, mResY);
|
||||
stop_glerror();
|
||||
glClear(mask & mask_in);
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLRenderTarget::getTexture(U32 attachment) const
|
||||
{
|
||||
if (attachment > mTex.size()-1)
|
||||
{
|
||||
LL_ERRS() << "Invalid attachment index." << LL_ENDL;
|
||||
}
|
||||
if (mTex.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return mTex[attachment];
|
||||
if (attachment > mTex.size()-1)
|
||||
{
|
||||
LL_ERRS() << "Invalid attachment index." << LL_ENDL;
|
||||
}
|
||||
if (mTex.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return mTex[attachment];
|
||||
}
|
||||
|
||||
U32 LLRenderTarget::getNumTextures() const
|
||||
{
|
||||
return mTex.size();
|
||||
return mTex.size();
|
||||
}
|
||||
|
||||
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
|
||||
|
|
@ -560,64 +504,54 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
|
|||
gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);
|
||||
}
|
||||
|
||||
void LLRenderTarget::flush(bool fetch_depth)
|
||||
void LLRenderTarget::flush()
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("rt flush");
|
||||
gGL.flush();
|
||||
gGL.flush();
|
||||
llassert(mFBO);
|
||||
if (!mFBO)
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(this);
|
||||
glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
|
||||
llassert(sCurFBO == mFBO);
|
||||
llassert(sBoundTarget == this);
|
||||
|
||||
if (fetch_depth)
|
||||
{
|
||||
if (!mDepth)
|
||||
{
|
||||
allocateDepth();
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->bind(this);
|
||||
glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0);
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->disable();
|
||||
}
|
||||
else
|
||||
{
|
||||
stop_glerror();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO);
|
||||
sCurFBO = mPreviousFBO;
|
||||
|
||||
if (mPreviousFBO)
|
||||
{
|
||||
glViewport(0, 0, mPreviousResX, mPreviousResY);
|
||||
sCurResX = mPreviousResX;
|
||||
sCurResY = mPreviousResY;
|
||||
}
|
||||
else
|
||||
{
|
||||
glViewport(gGLViewport[0],gGLViewport[1],gGLViewport[2],gGLViewport[3]);
|
||||
sCurResX = gGLViewport[2];
|
||||
sCurResY = gGLViewport[3];
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
if (mPreviousRT)
|
||||
{
|
||||
// a bit hacky -- pop the RT stack back two frames and push
|
||||
// the previous frame back on to play nice with the GL state machine
|
||||
sBoundTarget = mPreviousRT->mPreviousRT;
|
||||
mPreviousRT->bindTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
sBoundTarget = nullptr;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
sCurFBO = 0;
|
||||
glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
|
||||
sCurResX = gGLViewport[2];
|
||||
sCurResY = gGLViewport[3];
|
||||
}
|
||||
}
|
||||
|
||||
bool LLRenderTarget::isComplete() const
|
||||
{
|
||||
return (!mTex.empty() || mDepth) ? true : false;
|
||||
return (!mTex.empty() || mDepth) ? true : false;
|
||||
}
|
||||
|
||||
void LLRenderTarget::getViewport(S32* viewport)
|
||||
{
|
||||
viewport[0] = 0;
|
||||
viewport[1] = 0;
|
||||
viewport[2] = mResX;
|
||||
viewport[3] = mResY;
|
||||
viewport[0] = 0;
|
||||
viewport[1] = 0;
|
||||
viewport[2] = mResX;
|
||||
viewport[3] = mResY;
|
||||
}
|
||||
|
||||
bool LLRenderTarget::isBoundInStack() const
|
||||
{
|
||||
LLRenderTarget* cur = sBoundTarget;
|
||||
while (cur && cur != this)
|
||||
{
|
||||
cur = cur->mPreviousRT;
|
||||
}
|
||||
|
||||
return cur == this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "llrender.h"
|
||||
|
||||
/*
|
||||
Wrapper around OpenGL framebuffer objects for use in render-to-texture
|
||||
|
||||
SAMPLE USAGE:
|
||||
|
||||
LLRenderTarget target;
|
||||
|
|
@ -73,7 +75,12 @@ public:
|
|||
//allocate resources for rendering
|
||||
//must be called before use
|
||||
//multiple calls will release previously allocated resources
|
||||
bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool sample_depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0);
|
||||
// resX - width
|
||||
// resY - height
|
||||
// color_fmt - GL color format (e.g. GL_RGB)
|
||||
// depth - if true, allocate a depth buffer
|
||||
// usage - deprecated, should always be TT_TEXTURE
|
||||
bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE);
|
||||
|
||||
//resize existing attachments to use new resolution and color format
|
||||
// CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
|
||||
|
|
@ -93,7 +100,7 @@ public:
|
|||
// attachment -- LLImageGL to render into
|
||||
// use_name -- optional texture name to target instead of attachment->getTexName()
|
||||
// NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
|
||||
// addColorAttachment, allocateDepth, resize, etc.
|
||||
// addColorAttachment, allocateDepth, resize, etc.
|
||||
void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
|
||||
|
||||
// detach from current color attachment
|
||||
|
|
@ -111,14 +118,19 @@ public:
|
|||
|
||||
//free any allocated resources
|
||||
//safe to call redundantly
|
||||
// asserts that this target is not currently bound or present in the RT stack
|
||||
void release();
|
||||
|
||||
//bind target for rendering
|
||||
//applies appropriate viewport
|
||||
// If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget
|
||||
// and restores previous binding on flush() (maintains a stack of Render Targets)
|
||||
// Asserts that this target is not currently bound in the stack
|
||||
void bindTarget();
|
||||
|
||||
//clear render targer, clears depth buffer if present,
|
||||
//uses scissor rect if in copy-to-texture mode
|
||||
// asserts that this target is currently bound
|
||||
void clear(U32 mask = 0xFFFFFFFF);
|
||||
|
||||
//get applied viewport
|
||||
|
|
@ -136,7 +148,6 @@ public:
|
|||
U32 getNumTextures() const;
|
||||
|
||||
U32 getDepth(void) const { return mDepth; }
|
||||
bool canSampleDepth() const { return mSampleDepth; }
|
||||
|
||||
void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
|
||||
|
||||
|
|
@ -144,15 +155,18 @@ public:
|
|||
//must be called when rendering is complete
|
||||
//should be used 1:1 with bindTarget
|
||||
// call bindTarget once, do all your rendering, call flush once
|
||||
// if fetch_depth is TRUE, every effort will be made to copy the depth buffer into
|
||||
// the current depth texture. A depth texture will be allocated if needed.
|
||||
void flush(bool fetch_depth = FALSE);
|
||||
// If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack)
|
||||
// asserts that this target is currently bound
|
||||
void flush();
|
||||
|
||||
//Returns TRUE if target is ready to be rendered into.
|
||||
//That is, if the target has been allocated with at least
|
||||
//one renderable attachment (i.e. color buffer, depth buffer).
|
||||
bool isComplete() const;
|
||||
|
||||
// Returns true if this RenderTarget is bound somewhere in the stack
|
||||
bool isBoundInStack() const;
|
||||
|
||||
static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
|
||||
|
||||
protected:
|
||||
|
|
@ -161,13 +175,10 @@ protected:
|
|||
std::vector<U32> mTex;
|
||||
std::vector<U32> mInternalFormat;
|
||||
U32 mFBO;
|
||||
U32 mPreviousFBO;
|
||||
U32 mPreviousResX;
|
||||
U32 mPreviousResY;
|
||||
LLRenderTarget* mPreviousRT = nullptr;
|
||||
|
||||
U32 mDepth;
|
||||
U32 mDepth;
|
||||
bool mUseDepth;
|
||||
bool mSampleDepth;
|
||||
|
||||
LLTexUnit::eTextureType mUsage;
|
||||
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
}
|
||||
}
|
||||
|
||||
if (features->hasScreenSpaceReflections)
|
||||
if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl"))
|
||||
{
|
||||
|
|
@ -1244,6 +1244,8 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("bumpMap");
|
||||
mReservedUniforms.push_back("bumpMap2");
|
||||
mReservedUniforms.push_back("environmentMap");
|
||||
mReservedUniforms.push_back("sceneMap");
|
||||
mReservedUniforms.push_back("sceneDepth");
|
||||
mReservedUniforms.push_back("reflectionProbes");
|
||||
mReservedUniforms.push_back("irradianceProbes");
|
||||
mReservedUniforms.push_back("cloud_noise_texture");
|
||||
|
|
@ -1323,6 +1325,10 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
|
||||
llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH+1);
|
||||
|
||||
mReservedUniforms.push_back("modelview_delta");
|
||||
mReservedUniforms.push_back("inv_modelview_delta");
|
||||
mReservedUniforms.push_back("cube_snapshot");
|
||||
|
||||
mReservedUniforms.push_back("tc_scale");
|
||||
mReservedUniforms.push_back("rcp_screen_res");
|
||||
mReservedUniforms.push_back("rcp_frame_opt");
|
||||
|
|
|
|||
|
|
@ -90,6 +90,8 @@ public:
|
|||
BUMP_MAP, // "bumpMap"
|
||||
BUMP_MAP2, // "bumpMap2"
|
||||
ENVIRONMENT_MAP, // "environmentMap"
|
||||
SCENE_MAP, // "sceneMap"
|
||||
SCENE_DEPTH, // "sceneDepth"
|
||||
REFLECTION_PROBES, // "reflectionProbes"
|
||||
IRRADIANCE_PROBES, // "irradianceProbes"
|
||||
CLOUD_NOISE_MAP, // "cloud_noise_texture"
|
||||
|
|
@ -158,6 +160,10 @@ public:
|
|||
DEFERRED_NORM_CUTOFF, // "norm_cutoff"
|
||||
DEFERRED_SHADOW_TARGET_WIDTH, // "shadow_target_width"
|
||||
|
||||
MODELVIEW_DELTA_MATRIX, // "modelview_delta"
|
||||
INVERSE_MODELVIEW_DELTA_MATRIX, // "inv_modelview_delta"
|
||||
CUBE_SNAPSHOT, // "cube_snapshot"
|
||||
|
||||
FXAA_TC_SCALE, // "tc_scale"
|
||||
FXAA_RCP_SCREEN_RES, // "rcp_screen_res"
|
||||
FXAA_RCP_FRAME_OPT, // "rcp_frame_opt"
|
||||
|
|
|
|||
|
|
@ -744,7 +744,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
|
|||
|
||||
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
|
||||
{
|
||||
drawRange(mode, 0, mNumVerts, count, indices_offset);
|
||||
drawRange(mode, 0, mNumVerts-1, count, indices_offset);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,14 +25,14 @@
|
|||
|
||||
// fallback stub -- will be used if actual reflection probe shader failed to load (output pink so it's obvious)
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
{
|
||||
ambenv = vec3(1,0,1);
|
||||
glossenv = vec3(1,0,1);
|
||||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
sampleReflectionProbes(ambenv, glossenv,
|
||||
pos, norm, glossiness, false);
|
||||
|
|
|
|||
|
|
@ -23,35 +23,11 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
// debug stub
|
||||
|
||||
/*[EXTRA_CODE_HERE]*/
|
||||
|
||||
#ifdef DEFINE_GL_FRAGCOLOR
|
||||
out vec4 frag_color;
|
||||
#else
|
||||
#define frag_color gl_FragColor
|
||||
#endif
|
||||
|
||||
uniform vec2 screen_res;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat4 inv_proj;
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
|
||||
VARYING vec2 vary_fragcoord;
|
||||
|
||||
uniform sampler2D depthMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D sceneMap;
|
||||
uniform sampler2D diffuseRect;
|
||||
|
||||
vec3 getNorm(vec2 screenpos);
|
||||
float getDepth(vec2 pos_screen);
|
||||
float linearDepth(float d, float znear, float zfar);
|
||||
|
||||
void main() {
|
||||
vec2 tc = vary_fragcoord.xy;
|
||||
vec4 pos = getPositionWithDepth(tc, getDepth(tc));
|
||||
frag_color = pos;
|
||||
void main()
|
||||
{
|
||||
frag_color = vec4(0.5, 0.4, 0.1, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,98 +23,15 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform sampler2D depthMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D sceneMap;
|
||||
uniform vec2 screen_res;
|
||||
uniform mat4 projection_matrix;
|
||||
// debug stub
|
||||
|
||||
// Shamelessly taken from http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html
|
||||
// Original paper: https://jcgt.org/published/0003/04/04/
|
||||
// By Morgan McGuire and Michael Mara at Williams College 2014
|
||||
// Released as open source under the BSD 2-Clause License
|
||||
// http://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
float distanceSquared(vec2 a, vec2 b) { a -= b; return dot(a, a); }
|
||||
|
||||
bool traceScreenSpaceRay1(vec3 csOrig, vec3 csDir, mat4 proj, float zThickness,
|
||||
float nearPlaneZ, float stride, float jitter, const float maxSteps, float maxDistance,
|
||||
out vec2 hitPixel, out vec3 hitPoint)
|
||||
float random (vec2 uv)
|
||||
{
|
||||
|
||||
// Clip to the near plane
|
||||
float rayLength = ((csOrig.z + csDir.z * maxDistance) > nearPlaneZ) ?
|
||||
(nearPlaneZ - csOrig.z) / csDir.z : maxDistance;
|
||||
vec3 csEndPoint = csOrig + csDir * rayLength;
|
||||
|
||||
// Project into homogeneous clip space
|
||||
vec4 H0 = proj * vec4(csOrig, 1.0);
|
||||
vec4 H1 = proj * vec4(csEndPoint, 1.0);
|
||||
float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w;
|
||||
|
||||
// The interpolated homogeneous version of the camera-space points
|
||||
vec3 Q0 = csOrig * k0, Q1 = csEndPoint * k1;
|
||||
|
||||
// Screen-space endpoints
|
||||
vec2 P0 = H0.xy * k0, P1 = H1.xy * k1;
|
||||
|
||||
// If the line is degenerate, make it cover at least one pixel
|
||||
// to avoid handling zero-pixel extent as a special case later
|
||||
P1 += vec2((distanceSquared(P0, P1) < 0.0001) ? 0.01 : 0.0);
|
||||
vec2 delta = P1 - P0;
|
||||
|
||||
// Permute so that the primary iteration is in x to collapse
|
||||
// all quadrant-specific DDA cases later
|
||||
bool permute = false;
|
||||
if (abs(delta.x) < abs(delta.y)) {
|
||||
// This is a more-vertical line
|
||||
permute = true; delta = delta.yx; P0 = P0.yx; P1 = P1.yx;
|
||||
}
|
||||
|
||||
float stepDir = sign(delta.x);
|
||||
float invdx = stepDir / delta.x;
|
||||
|
||||
// Track the derivatives of Q and k
|
||||
vec3 dQ = (Q1 - Q0) * invdx;
|
||||
float dk = (k1 - k0) * invdx;
|
||||
vec2 dP = vec2(stepDir, delta.y * invdx);
|
||||
|
||||
// Scale derivatives by the desired pixel stride and then
|
||||
// offset the starting values by the jitter fraction
|
||||
dP *= stride; dQ *= stride; dk *= stride;
|
||||
P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter;
|
||||
|
||||
// Slide P from P0 to P1, (now-homogeneous) Q from Q0 to Q1, k from k0 to k1
|
||||
vec3 Q = Q0;
|
||||
|
||||
// Adjust end condition for iteration direction
|
||||
float end = P1.x * stepDir;
|
||||
|
||||
float k = k0, stepCount = 0.0, prevZMaxEstimate = csOrig.z;
|
||||
float rayZMin = prevZMaxEstimate, rayZMax = prevZMaxEstimate;
|
||||
float sceneZMax = rayZMax + 100;
|
||||
for (vec2 P = P0;
|
||||
((P.x * stepDir) <= end) && (stepCount < maxSteps) &&
|
||||
((rayZMax < sceneZMax - zThickness) || (rayZMin > sceneZMax)) &&
|
||||
(sceneZMax != 0);
|
||||
P += dP, Q.z += dQ.z, k += dk, ++stepCount) {
|
||||
|
||||
rayZMin = prevZMaxEstimate;
|
||||
rayZMax = (dQ.z * 0.5 + Q.z) / (dk * 0.5 + k);
|
||||
prevZMaxEstimate = rayZMax;
|
||||
if (rayZMin > rayZMax) {
|
||||
float t = rayZMin; rayZMin = rayZMax; rayZMax = t;
|
||||
}
|
||||
|
||||
hitPixel = permute ? P.yx : P;
|
||||
hitPixel.y = screen_res.y - hitPixel.y;
|
||||
// You may need hitPixel.y = screen_res.y - hitPixel.y; here if your vertical axis
|
||||
// is different than ours in screen space
|
||||
sceneZMax = texelFetch(depthMap, ivec2(hitPixel)).r;
|
||||
}
|
||||
|
||||
// Advance Q based on the number of steps
|
||||
Q.xy += dQ.xy * stepCount;
|
||||
hitPoint = Q * (1.0 / k);
|
||||
return (rayZMax >= sceneZMax - zThickness) && (rayZMin < sceneZMax);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source)
|
||||
{
|
||||
collectedColor = vec4(0);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -90,8 +90,8 @@ float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
|||
|
||||
float getAmbientClamp();
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
|
||||
vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
|
||||
{
|
||||
|
|
@ -253,7 +253,7 @@ void main()
|
|||
vec3 irradiance;
|
||||
vec3 glossenv;
|
||||
vec3 legacyenv;
|
||||
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, pos.xyz, norm.xyz, 0.0, 0.0);
|
||||
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0);
|
||||
|
||||
|
||||
float da = dot(norm.xyz, light_dir.xyz);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float
|
|||
float calcLegacyDistanceAttenuation(float distance, float falloff);
|
||||
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness);
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness);
|
||||
|
||||
void waterClip(vec3 pos);
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ void main()
|
|||
float gloss = 1.0 - perceptualRoughness;
|
||||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
sampleReflectionProbes(irradiance, radiance, pos.xyz, norm.xyz, gloss);
|
||||
sampleReflectionProbes(irradiance, radiance, vec2(0), pos.xyz, norm.xyz, gloss);
|
||||
// Take maximium of legacy ambient vs irradiance sample as irradiance
|
||||
// NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
|
||||
irradiance = max(amblit,irradiance);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ uniform mat3 env_mat;
|
|||
vec3 srgb_to_linear(vec3 c);
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
{
|
||||
ambenv = vec3(reflection_probe_ambiance * 0.25);
|
||||
|
||||
|
|
@ -44,10 +44,10 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
|||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
sampleReflectionProbes(ambenv, glossenv,
|
||||
pos, norm, glossiness, false);
|
||||
tc, pos, norm, glossiness, false);
|
||||
}
|
||||
|
||||
vec4 sampleReflectionProbesDebug(vec3 pos)
|
||||
|
|
@ -56,8 +56,8 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
|
|||
return vec4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity)
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
|
||||
{
|
||||
ambenv = vec3(reflection_probe_ambiance * 0.25);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,8 +56,9 @@ vec3 linear_to_srgb(vec3 c);
|
|||
vec3 srgb_to_linear(vec3 c);
|
||||
|
||||
// reflection probe interface
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
|
||||
void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
|
||||
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
|
||||
|
||||
|
|
@ -91,7 +92,7 @@ void main()
|
|||
vec3 legacyenv;
|
||||
vec3 norm = normalize(vary_texcoord1.xyz);
|
||||
vec4 spec = vec4(0,0,0,0);
|
||||
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, env_intensity);
|
||||
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, vec2(0), pos.xyz, norm.xyz, spec.a, env_intensity);
|
||||
applyLegacyEnv(color.rgb, legacyenv, spec, pos, norm, env_intensity);
|
||||
|
||||
color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ out vec4 frag_color;
|
|||
float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
|
||||
#endif
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
|
||||
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ void main()
|
|||
vec3 ambenv;
|
||||
vec3 glossenv;
|
||||
vec3 legacyenv;
|
||||
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xyz, norm.xyz, final_specular.a, env_intensity);
|
||||
sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos_screen, pos.xyz, norm.xyz, final_specular.a, env_intensity);
|
||||
|
||||
// use sky settings ambient or irradiance map sample, whichever is brighter
|
||||
color = max(amblit, ambenv);
|
||||
|
|
|
|||
|
|
@ -25,11 +25,17 @@
|
|||
|
||||
#define FLT_MAX 3.402823466e+38
|
||||
|
||||
#if defined(SSR)
|
||||
float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source);
|
||||
#endif
|
||||
|
||||
#define REFMAP_COUNT 256
|
||||
#define REF_SAMPLE_COUNT 64 //maximum number of samples to consider
|
||||
|
||||
uniform samplerCubeArray reflectionProbes;
|
||||
uniform samplerCubeArray irradianceProbes;
|
||||
uniform sampler2D sceneMap;
|
||||
uniform int cube_snapshot;
|
||||
|
||||
layout (std140) uniform ReflectionProbes
|
||||
{
|
||||
|
|
@ -92,14 +98,17 @@ bool shouldSampleProbe(int i, vec3 pos)
|
|||
}
|
||||
else
|
||||
{
|
||||
vec3 delta = pos.xyz - refSphere[i].xyz;
|
||||
float d = dot(delta, delta);
|
||||
float r2 = refSphere[i].w;
|
||||
r2 *= r2;
|
||||
if (refSphere[i].w > 0.0) // zero is special indicator to always sample this probe
|
||||
{
|
||||
vec3 delta = pos.xyz - refSphere[i].xyz;
|
||||
float d = dot(delta, delta);
|
||||
float r2 = refSphere[i].w;
|
||||
r2 *= r2;
|
||||
|
||||
if (d > r2)
|
||||
{ //outside bounding sphere
|
||||
return false;
|
||||
if (d > r2)
|
||||
{ //outside bounding sphere
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
max_priority = max(max_priority, refIndex[i].w);
|
||||
|
|
@ -138,13 +147,13 @@ void preProbeSample(vec3 pos)
|
|||
probeIndex[probeInfluences++] = idx;
|
||||
if (probeInfluences == REF_SAMPLE_COUNT)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (count == neighborCount)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
idx = refNeighbor[neighborIdx].y;
|
||||
|
|
@ -153,13 +162,13 @@ void preProbeSample(vec3 pos)
|
|||
probeIndex[probeInfluences++] = idx;
|
||||
if (probeInfluences == REF_SAMPLE_COUNT)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (count == neighborCount)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
idx = refNeighbor[neighborIdx].z;
|
||||
|
|
@ -168,13 +177,13 @@ void preProbeSample(vec3 pos)
|
|||
probeIndex[probeInfluences++] = idx;
|
||||
if (probeInfluences == REF_SAMPLE_COUNT)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (count == neighborCount)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
idx = refNeighbor[neighborIdx].w;
|
||||
|
|
@ -183,27 +192,26 @@ void preProbeSample(vec3 pos)
|
|||
probeIndex[probeInfluences++] = idx;
|
||||
if (probeInfluences == REF_SAMPLE_COUNT)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (count == neighborCount)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
++neighborIdx;
|
||||
}
|
||||
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (probeInfluences == 0)
|
||||
{ // probe at index 0 is a special fallback probe
|
||||
probeIndex[0] = 0;
|
||||
probeInfluences = 1;
|
||||
if (max_priority <= 1)
|
||||
{ // probe at index 0 is a special probe for smoothing out automatic probes
|
||||
probeIndex[probeInfluences++] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -330,7 +338,8 @@ return texCUBE(envMap, ReflDirectionWS);
|
|||
// origin - ray origin in clip space
|
||||
// dir - ray direction in clip space
|
||||
// i - probe index in refBox/refSphere
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, int i)
|
||||
// d - distance to nearest wall in clip space
|
||||
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d)
|
||||
{
|
||||
// Intersection with OBB convertto unit box space
|
||||
// Transform in local unit parallax cube space (scaled and rotated)
|
||||
|
|
@ -339,6 +348,8 @@ vec3 boxIntersect(vec3 origin, vec3 dir, int i)
|
|||
vec3 RayLS = mat3(clipToLocal) * dir;
|
||||
vec3 PositionLS = (clipToLocal * vec4(origin, 1.0)).xyz;
|
||||
|
||||
d = 1.0-max(max(abs(PositionLS.x), abs(PositionLS.y)), abs(PositionLS.z));
|
||||
|
||||
vec3 Unitary = vec3(1.0f, 1.0f, 1.0f);
|
||||
vec3 FirstPlaneIntersect = (Unitary - PositionLS) / RayLS;
|
||||
vec3 SecondPlaneIntersect = (-Unitary - PositionLS) / RayLS;
|
||||
|
|
@ -413,6 +424,29 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
|
|||
}
|
||||
|
||||
|
||||
// get the weight of a sphere probe
|
||||
// pos - position to be weighted
|
||||
// dir - normal to be weighted
|
||||
// origin - center of sphere probe
|
||||
// r - radius of probe influence volume
|
||||
// min_da - minimum angular attenuation coefficient
|
||||
float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da)
|
||||
{
|
||||
float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
|
||||
vec3 delta = pos.xyz - origin;
|
||||
float d2 = max(length(delta), 0.001);
|
||||
float r2 = r1; //r1 * r1;
|
||||
|
||||
//float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001);
|
||||
float atten = 1.0 - max(d2 - r2, 0.0) / max((r - r2), 0.001);
|
||||
|
||||
atten *= max(dot(normalize(-delta), dir), min_da);
|
||||
float w = 1.0 / d2;
|
||||
w *= atten;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
// Tap a reflection probe
|
||||
// pos - position of pixel
|
||||
// dir - pixel normal
|
||||
|
|
@ -431,27 +465,21 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float
|
|||
|
||||
if (refIndex[i].w < 0)
|
||||
{
|
||||
v = boxIntersect(pos, dir, i);
|
||||
w = 1.0;
|
||||
float d = 0;
|
||||
v = boxIntersect(pos, dir, i, d);
|
||||
|
||||
w = max(d, 0.001);
|
||||
}
|
||||
else
|
||||
{
|
||||
float r = refSphere[i].w; // radius of sphere volume
|
||||
float rr = r * r; // radius squared
|
||||
|
||||
v = sphereIntersect(pos, dir, c, rr);
|
||||
v = sphereIntersect(pos, dir, c,
|
||||
refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
|
||||
rr);
|
||||
|
||||
float p = float(abs(refIndex[i].w)); // priority
|
||||
|
||||
float r1 = r * 0.1; // 90% of radius (outer sphere to start interpolating down)
|
||||
vec3 delta = pos.xyz - refSphere[i].xyz;
|
||||
float d2 = max(dot(delta, delta), 0.001);
|
||||
float r2 = r1 * r1;
|
||||
|
||||
float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001);
|
||||
|
||||
w = 1.0 / d2;
|
||||
w *= atten;
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25);
|
||||
}
|
||||
|
||||
vi = v;
|
||||
|
|
@ -480,8 +508,9 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
|
|||
vec3 v;
|
||||
if (refIndex[i].w < 0)
|
||||
{
|
||||
v = boxIntersect(pos, dir, i);
|
||||
w = 1.0;
|
||||
float d = 0.0;
|
||||
v = boxIntersect(pos, dir, i, d);
|
||||
w = max(d, 0.001);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -489,17 +518,11 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
|
|||
float p = float(abs(refIndex[i].w)); // priority
|
||||
float rr = r * r; // radius squred
|
||||
|
||||
v = sphereIntersect(pos, dir, c, rr);
|
||||
v = sphereIntersect(pos, dir, c,
|
||||
refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
|
||||
rr);
|
||||
|
||||
float r1 = r * 0.1; // 75% of radius (outer sphere to start interpolating down)
|
||||
vec3 delta = pos.xyz - refSphere[i].xyz;
|
||||
float d2 = dot(delta, delta);
|
||||
float r2 = r1 * r1;
|
||||
|
||||
w = 1.0 / d2;
|
||||
|
||||
float atten = 1.0 - max(d2 - r2, 0.0) / (rr - r2);
|
||||
w *= atten;
|
||||
w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001);
|
||||
}
|
||||
|
||||
v -= c;
|
||||
|
|
@ -605,7 +628,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
|
|||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
|
||||
{
|
||||
// TODO - don't hard code lods
|
||||
float reflection_lods = 6;
|
||||
|
|
@ -617,6 +640,17 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
|||
|
||||
float lod = (1.0-glossiness)*reflection_lods;
|
||||
glossenv = sampleProbes(pos, normalize(refnormpersp), lod, errorCorrect);
|
||||
|
||||
#if defined(SSR)
|
||||
if (cube_snapshot != 1)
|
||||
{
|
||||
vec4 ssr = vec4(0);
|
||||
//float w = tapScreenSpaceReflection(errorCorrect ? 1 : 4, tc, pos, norm, ssr, sceneMap);
|
||||
float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap);
|
||||
|
||||
glossenv = mix(glossenv, ssr.rgb, w);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
|
||||
|
|
@ -660,15 +694,15 @@ vec4 sampleReflectionProbesDebug(vec3 pos)
|
|||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness)
|
||||
{
|
||||
sampleReflectionProbes(ambenv, glossenv,
|
||||
pos, norm, glossiness, false);
|
||||
tc, pos, norm, glossiness, false);
|
||||
}
|
||||
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity)
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
|
||||
{
|
||||
// TODO - don't hard code lods
|
||||
float reflection_lods = 7;
|
||||
|
|
@ -676,7 +710,6 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
|
||||
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
|
||||
|
||||
|
||||
ambenv = sampleProbeAmbient(pos, norm);
|
||||
|
||||
if (glossiness > 0.0)
|
||||
|
|
@ -689,6 +722,17 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
|
|||
{
|
||||
legacyenv = sampleProbes(pos, normalize(refnormpersp), 0.0, false);
|
||||
}
|
||||
|
||||
#if defined(SSR)
|
||||
if (cube_snapshot != 1)
|
||||
{
|
||||
vec4 ssr = vec4(0);
|
||||
float w = tapScreenSpaceReflection(1, tc, pos, norm, ssr, sceneMap);
|
||||
|
||||
glossenv = mix(glossenv, ssr.rgb, w);
|
||||
legacyenv = mix(legacyenv, ssr.rgb, w);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm)
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ uniform float zFar;
|
|||
VARYING vec2 vary_fragcoord;
|
||||
VARYING vec3 camera_ray;
|
||||
|
||||
uniform sampler2D depthMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D specularRect;
|
||||
uniform sampler2D sceneMap;
|
||||
uniform sampler2D diffuseRect;
|
||||
uniform sampler2D diffuseMap;
|
||||
|
||||
|
|
@ -57,27 +54,27 @@ float linearDepth01(float d, float znear, float zfar);
|
|||
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
|
||||
vec4 getPosition(vec2 pos_screen);
|
||||
vec4 getNormalEnvIntensityFlags(vec2 screenpos, out vec3 n, out float envIntensity);
|
||||
bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame);
|
||||
|
||||
float random (vec2 uv);
|
||||
|
||||
float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy;
|
||||
float depth = linearDepth01(getDepth(tc), zNear, zFar);
|
||||
vec3 n = vec3(0, 0, 1);
|
||||
float envIntensity;
|
||||
vec3 n;
|
||||
vec4 norm = getNormalEnvIntensityFlags(tc, n, envIntensity); // need `norm.w` for GET_GBUFFER_FLAG()
|
||||
vec3 pos = getPositionWithDepth(tc, getDepth(tc)).xyz;
|
||||
vec4 spec = texture2D(specularRect, tc);
|
||||
vec3 viewPos = camera_ray * depth;
|
||||
vec3 rayDirection = normalize(reflect(normalize(viewPos), n)) * -viewPos.z;
|
||||
vec2 hitpixel;
|
||||
vec4 hitpoint;
|
||||
|
||||
vec4 diffuse = texture2D(diffuseRect, tc);
|
||||
vec3 specCol = spec.rgb;
|
||||
|
||||
frag_color = texture(diffuseMap, tc);
|
||||
|
||||
if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
|
||||
{
|
||||
vec3 orm = specCol.rgb;
|
||||
|
|
@ -85,44 +82,17 @@ void main()
|
|||
float metallic = orm.b;
|
||||
vec3 f0 = vec3(0.04);
|
||||
vec3 baseColor = diffuse.rgb;
|
||||
|
||||
|
||||
vec3 diffuseColor = baseColor.rgb*(vec3(1.0)-f0);
|
||||
|
||||
specCol = mix(f0, baseColor.rgb, metallic);
|
||||
}
|
||||
|
||||
vec2 uv2 = tc * screen_res;
|
||||
float c = (uv2.x + uv2.y) * 0.125;
|
||||
float jitter = mod( c, 1.0);
|
||||
vec4 collectedColor = vec4(0);
|
||||
|
||||
vec3 firstBasis = normalize(cross(vec3(1.f, 1.f, 1.f), rayDirection));
|
||||
vec3 secondBasis = normalize(cross(rayDirection, firstBasis));
|
||||
|
||||
frag_color = texture(diffuseMap, tc);
|
||||
vec4 collectedColor;
|
||||
|
||||
vec2 screenpos = 1 - abs(tc * 2 - 1);
|
||||
float vignette = clamp((screenpos.x * screenpos.y) * 16,0, 1);
|
||||
vignette *= clamp((dot(normalize(viewPos), n) * 0.5 + 0.5 - 0.2) * 8, 0, 1);
|
||||
vignette *= min(linearDepth(getDepth(tc), zNear, zFar) / zFar, 1);
|
||||
float w = tapScreenSpaceReflection(4, tc, pos, n, collectedColor, diffuseMap);
|
||||
|
||||
int totalSamples = 4;
|
||||
collectedColor.rgb *= specCol.rgb;
|
||||
|
||||
for (int i = 0; i < totalSamples; i++)
|
||||
{
|
||||
vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0)));
|
||||
vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y;
|
||||
|
||||
bool hit = traceScreenRay(pos, reflectionDirectionRandomized, hitpoint, depth, depth, diffuseMap);
|
||||
|
||||
if (hit)
|
||||
{
|
||||
collectedColor += hitpoint;
|
||||
collectedColor.rgb *= specCol.rgb;
|
||||
}
|
||||
}
|
||||
|
||||
collectedColor *= vignette;
|
||||
|
||||
frag_color += collectedColor;
|
||||
frag_color += collectedColor * w;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,19 +23,18 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
uniform sampler2D depthMap;
|
||||
uniform sampler2D normalMap;
|
||||
uniform sampler2D sceneMap;
|
||||
uniform sampler2D sceneDepth;
|
||||
|
||||
uniform vec2 screen_res;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform float zNear;
|
||||
uniform float zFar;
|
||||
//uniform float zNear;
|
||||
//uniform float zFar;
|
||||
uniform mat4 inv_proj;
|
||||
uniform mat4 modelview_delta; // should be transform from last camera space to current camera space
|
||||
uniform mat4 inv_modelview_delta;
|
||||
|
||||
vec4 getPositionWithDepth(vec2 pos_screen, float depth);
|
||||
float linearDepth(float depth, float near, float far);
|
||||
float getDepth(vec2 pos_screen);
|
||||
float linearDepth01(float d, float znear, float zfar);
|
||||
|
||||
float random (vec2 uv)
|
||||
{
|
||||
|
|
@ -62,8 +61,25 @@ float distanceBias = 0.02;
|
|||
float depthRejectBias = 0.001;
|
||||
float epsilon = 0.1;
|
||||
|
||||
float getLinearDepth(vec2 tc)
|
||||
{
|
||||
float depth = texture(sceneDepth, tc).r;
|
||||
|
||||
vec4 pos = getPositionWithDepth(tc, depth);
|
||||
|
||||
return -pos.z;
|
||||
}
|
||||
|
||||
bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float hitDepth, float depth, sampler2D textureFrame)
|
||||
{
|
||||
// transform position and reflection into same coordinate frame as the sceneMap and sceneDepth
|
||||
reflection += position;
|
||||
position = (inv_modelview_delta * vec4(position, 1)).xyz;
|
||||
reflection = (inv_modelview_delta * vec4(reflection, 1)).xyz;
|
||||
reflection -= position;
|
||||
|
||||
depth = -position.z;
|
||||
|
||||
vec3 step = rayStep * reflection;
|
||||
vec3 marchingPosition = position + step;
|
||||
float delta;
|
||||
|
|
@ -72,13 +88,14 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float
|
|||
bool hit = false;
|
||||
hitColor = vec4(0);
|
||||
|
||||
|
||||
int i = 0;
|
||||
if (depth > depthRejectBias)
|
||||
{
|
||||
for (; i < iterationCount && !hit; i++)
|
||||
{
|
||||
screenPosition = generateProjectedPosition(marchingPosition);
|
||||
depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar);
|
||||
depthFromScreen = getLinearDepth(screenPosition);
|
||||
delta = abs(marchingPosition.z) - depthFromScreen;
|
||||
|
||||
if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon)
|
||||
|
|
@ -91,7 +108,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float
|
|||
vec4 color = vec4(1);
|
||||
if(debugDraw)
|
||||
color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0);
|
||||
hitColor = texture(textureFrame, screenPosition) * color;
|
||||
hitColor = texture(sceneMap, screenPosition) * color;
|
||||
hitDepth = depthFromScreen;
|
||||
hit = true;
|
||||
break;
|
||||
|
|
@ -126,7 +143,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float
|
|||
marchingPosition = marchingPosition - step * sign(delta);
|
||||
|
||||
screenPosition = generateProjectedPosition(marchingPosition);
|
||||
depthFromScreen = linearDepth(getDepth(screenPosition), zNear, zFar);
|
||||
depthFromScreen = getLinearDepth(screenPosition);
|
||||
delta = abs(marchingPosition.z) - depthFromScreen;
|
||||
|
||||
if (depth < depthFromScreen + epsilon && depth > depthFromScreen - epsilon)
|
||||
|
|
@ -139,7 +156,7 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float
|
|||
vec4 color = vec4(1);
|
||||
if(debugDraw)
|
||||
color = vec4( 0.5+ sign(delta)/2,0.3,0.5- sign(delta)/2, 0);
|
||||
hitColor = texture(textureFrame, screenPosition) * color;
|
||||
hitColor = texture(sceneMap, screenPosition) * color;
|
||||
hitDepth = depthFromScreen;
|
||||
hit = true;
|
||||
break;
|
||||
|
|
@ -150,3 +167,68 @@ bool traceScreenRay(vec3 position, vec3 reflection, out vec4 hitColor, out float
|
|||
|
||||
return hit;
|
||||
}
|
||||
|
||||
float tapScreenSpaceReflection(int totalSamples, vec2 tc, vec3 viewPos, vec3 n, inout vec4 collectedColor, sampler2D source)
|
||||
{
|
||||
collectedColor = vec4(0);
|
||||
int hits = 0;
|
||||
|
||||
float depth = -viewPos.z;
|
||||
|
||||
vec3 rayDirection = normalize(reflect(viewPos, normalize(n)));
|
||||
|
||||
vec2 uv2 = tc * screen_res;
|
||||
float c = (uv2.x + uv2.y) * 0.125;
|
||||
float jitter = mod( c, 1.0);
|
||||
|
||||
vec3 firstBasis = normalize(cross(vec3(1,1,1), rayDirection));
|
||||
vec3 secondBasis = normalize(cross(rayDirection, firstBasis));
|
||||
|
||||
vec2 screenpos = 1 - abs(tc * 2 - 1);
|
||||
float vignette = clamp((screenpos.x * screenpos.y) * 16,0, 1);
|
||||
vignette *= clamp((dot(normalize(viewPos), n) * 0.5 + 0.5 - 0.2) * 8, 0, 1);
|
||||
float zFar = 64.0;
|
||||
vignette *= clamp(1.0+(viewPos.z/zFar), 0.0, 1.0);
|
||||
//vignette *= min(linearDepth(getDepth(tc), zNear, zFar) / zFar, 1);
|
||||
|
||||
vec4 hitpoint;
|
||||
|
||||
if (totalSamples > 1)
|
||||
{
|
||||
for (int i = 0; i < totalSamples; i++)
|
||||
{
|
||||
vec2 coeffs = vec2(random(tc + vec2(0, i)) + random(tc + vec2(i, 0)));
|
||||
vec3 reflectionDirectionRandomized = rayDirection + firstBasis * coeffs.x + secondBasis * coeffs.y;
|
||||
|
||||
//float hitDepth;
|
||||
|
||||
bool hit = traceScreenRay(viewPos, normalize(reflectionDirectionRandomized), hitpoint, depth, depth, source);
|
||||
|
||||
if (hit)
|
||||
{
|
||||
++hits;
|
||||
collectedColor += hitpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hit = traceScreenRay(viewPos, normalize(rayDirection), hitpoint, depth, depth, source);
|
||||
if (hit)
|
||||
{
|
||||
++hits;
|
||||
collectedColor += hitpoint;
|
||||
}
|
||||
}
|
||||
|
||||
if (hits > 0)
|
||||
{
|
||||
collectedColor /= hits;
|
||||
}
|
||||
else
|
||||
{
|
||||
collectedColor = vec4(0);
|
||||
}
|
||||
|
||||
return min(float(hits), 1.0) * vignette;
|
||||
}
|
||||
|
|
@ -75,9 +75,9 @@ vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten);
|
|||
|
||||
// reflection probe interface
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness);
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyEnv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness);
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm);
|
||||
void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity);
|
||||
float getDepth(vec2 pos_screen);
|
||||
|
|
@ -166,7 +166,7 @@ void main()
|
|||
float gloss = 1.0 - perceptualRoughness;
|
||||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
sampleReflectionProbes(irradiance, radiance, pos.xyz, norm.xyz, gloss);
|
||||
sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss);
|
||||
|
||||
// Take maximium of legacy ambient vs irradiance sample as irradiance
|
||||
// NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
|
||||
|
|
@ -196,7 +196,7 @@ void main()
|
|||
vec3 glossenv = vec3(0);
|
||||
vec3 legacyenv = vec3(0);
|
||||
|
||||
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, pos.xyz, norm.xyz, spec.a, envIntensity);
|
||||
sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity);
|
||||
|
||||
// use sky settings ambient or irradiance map sample, whichever is brighter
|
||||
irradiance = max(amblit, irradiance);
|
||||
|
|
|
|||
|
|
@ -95,9 +95,6 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
|
|||
|
||||
vec3 srgb_to_linear(vec3 col);
|
||||
|
||||
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
|
||||
vec3 pos, vec3 norm, float glossiness, float envIntensity);
|
||||
|
||||
vec3 vN, vT, vB;
|
||||
|
||||
vec3 transform_normal(vec3 vNt)
|
||||
|
|
@ -106,7 +103,10 @@ vec3 transform_normal(vec3 vNt)
|
|||
}
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec3 pos, vec3 norm, float glossiness, bool errorCorrect);
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness);
|
||||
|
||||
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
|
||||
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect);
|
||||
|
||||
vec3 getPositionWithNDC(vec3 ndc);
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ void main()
|
|||
|
||||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
sampleReflectionProbes(irradiance, radiance, pos, refnorm, gloss, true);
|
||||
sampleReflectionProbes(irradiance, radiance, distort, pos, refnorm, gloss, true);
|
||||
radiance *= 0.5;
|
||||
irradiance = fb.rgb;
|
||||
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ void LLFastTimerView::exportCharts(const std::string& base, const std::string& t
|
|||
{
|
||||
//allocate render target for drawing charts
|
||||
LLRenderTarget buffer;
|
||||
buffer.allocate(1024,512, GL_RGB, FALSE, FALSE);
|
||||
buffer.allocate(1024,512, GL_RGB);
|
||||
|
||||
|
||||
LLSD cur;
|
||||
|
|
|
|||
|
|
@ -1050,7 +1050,7 @@ F32 gpu_benchmark()
|
|||
for (U32 i = 0; i < count; ++i)
|
||||
{
|
||||
//allocate render targets and textures
|
||||
if (!dest[i].allocate(res, res, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true))
|
||||
if (!dest[i].allocate(res, res, GL_RGBA))
|
||||
{
|
||||
LL_WARNS("Benchmark") << "Failed to allocate render target." << LL_ENDL;
|
||||
// abandon the benchmark test
|
||||
|
|
|
|||
|
|
@ -39,6 +39,14 @@
|
|||
extern BOOL gCubeSnapshot;
|
||||
extern BOOL gTeleportDisplay;
|
||||
|
||||
static void touch_default_probe(LLReflectionMap* probe)
|
||||
{
|
||||
LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
|
||||
origin.mV[2] += 64.f;
|
||||
|
||||
probe->mOrigin.load3(origin.mV);
|
||||
}
|
||||
|
||||
LLReflectionMapManager::LLReflectionMapManager()
|
||||
{
|
||||
initCubeFree();
|
||||
|
|
@ -83,10 +91,8 @@ void LLReflectionMapManager::update()
|
|||
if (!mRenderTarget.isComplete())
|
||||
{
|
||||
U32 color_fmt = GL_RGB16F;
|
||||
const bool use_depth_buffer = true;
|
||||
const bool use_stencil_buffer = false;
|
||||
U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample
|
||||
mRenderTarget.allocate(targetRes, targetRes, color_fmt, use_depth_buffer, use_stencil_buffer, LLTexUnit::TT_TEXTURE);
|
||||
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
|
||||
}
|
||||
|
||||
if (mMipChain.empty())
|
||||
|
|
@ -97,7 +103,7 @@ void LLReflectionMapManager::update()
|
|||
mMipChain.resize(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
mMipChain[i].allocate(res, res, GL_RGBA16F, false, false, LLTexUnit::TT_TEXTURE);
|
||||
mMipChain[i].allocate(res, res, GL_RGBA16F);
|
||||
res /= 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -108,9 +114,8 @@ void LLReflectionMapManager::update()
|
|||
mDefaultProbe = addProbe();
|
||||
mDefaultProbe->mDistance = -4096.f; // hack to make sure the default probe is always first in sort order
|
||||
mDefaultProbe->mRadius = 4096.f;
|
||||
touch_default_probe(mDefaultProbe);
|
||||
}
|
||||
|
||||
mDefaultProbe->mOrigin.load3(LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
LLVector4a camera_pos;
|
||||
camera_pos.load3(LLViewerCamera::instance().getOrigin().mV);
|
||||
|
|
@ -155,6 +160,8 @@ void LLReflectionMapManager::update()
|
|||
doProbeUpdate();
|
||||
}
|
||||
|
||||
//LL_INFOS() << mProbes.size() << LL_ENDL;
|
||||
|
||||
for (int i = 0; i < mProbes.size(); ++i)
|
||||
{
|
||||
LLReflectionMap* probe = mProbes[i];
|
||||
|
|
@ -403,7 +410,26 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
|
|||
{
|
||||
// hacky hot-swap of camera specific render targets
|
||||
gPipeline.mRT = &gPipeline.mAuxillaryRT;
|
||||
probe->update(mRenderTarget.getWidth(), face);
|
||||
|
||||
if (probe == mDefaultProbe)
|
||||
{
|
||||
touch_default_probe(probe);
|
||||
|
||||
gPipeline.pushRenderTypeMask();
|
||||
|
||||
//only render sky, water, terrain, and clouds
|
||||
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY,
|
||||
LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::END_RENDER_TYPES);
|
||||
|
||||
probe->update(mRenderTarget.getWidth(), face);
|
||||
|
||||
gPipeline.popRenderTypeMask();
|
||||
}
|
||||
else
|
||||
{
|
||||
probe->update(mRenderTarget.getWidth(), face);
|
||||
}
|
||||
|
||||
gPipeline.mRT = &gPipeline.mMainRT;
|
||||
|
||||
S32 targetIdx = mReflectionProbeCount;
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ LLRenderTarget& LLSceneMonitor::getCaptureTarget()
|
|||
if(!mFrames[0])
|
||||
{
|
||||
mFrames[0] = new LLRenderTarget();
|
||||
mFrames[0]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true);
|
||||
mFrames[0]->allocate(width, height, GL_RGB);
|
||||
gGL.getTexUnit(0)->bind(mFrames[0]);
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
|
@ -187,7 +187,7 @@ LLRenderTarget& LLSceneMonitor::getCaptureTarget()
|
|||
else if(!mFrames[1])
|
||||
{
|
||||
mFrames[1] = new LLRenderTarget();
|
||||
mFrames[1]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true);
|
||||
mFrames[1]->allocate(width, height, GL_RGB);
|
||||
gGL.getTexUnit(0)->bind(mFrames[1]);
|
||||
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
|
@ -360,7 +360,7 @@ void LLSceneMonitor::compare()
|
|||
if(!mDiff)
|
||||
{
|
||||
mDiff = new LLRenderTarget();
|
||||
mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true);
|
||||
mDiff->allocate(width, height, GL_RGBA);
|
||||
|
||||
generateDitheringTexture(width, height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -682,6 +682,7 @@ void settings_setup_listeners()
|
|||
// DEPRECATED - setting_setup_signal_listener(gSavedSettings, "RenderDeferred", handleRenderDeferredChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderReflectionProbeDetail", handleReflectionProbeDetailChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderReflectionsEnabled", handleReflectionProbeDetailChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderScreenSpaceReflections", handleReflectionProbeDetailChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderShadowDetail", handleSetShaderChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderDeferredSSAO", handleSetShaderChanged);
|
||||
setting_setup_signal_listener(gSavedSettings, "RenderPerformanceTest", handleRenderPerfTestChanged);
|
||||
|
|
|
|||
|
|
@ -918,15 +918,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
|
||||
gGL.setColorMask(true, true);
|
||||
gPipeline.renderGeomDeferred(*LLViewerCamera::getInstance(), true);
|
||||
|
||||
//store this frame's modelview matrix for use
|
||||
//when rendering next frame's occlusion queries
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
{
|
||||
gGLLastModelView[i] = gGLModelView[i];
|
||||
gGLLastProjection[i] = gGLProjection[i];
|
||||
}
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -843,6 +843,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
|
|||
BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable");
|
||||
BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable");
|
||||
BOOL local_light_kill = gSavedSettings.getBOOL("LocalLightDisable");
|
||||
BOOL ssr = gSavedSettings.getBOOL("RenderScreenSpaceReflections");
|
||||
|
||||
if (ambient_kill)
|
||||
{
|
||||
|
|
@ -871,6 +872,11 @@ std::string LLViewerShaderMgr::loadBasicShaders()
|
|||
}
|
||||
}
|
||||
|
||||
if (ssr)
|
||||
{
|
||||
attribs["SSR"] = "1";
|
||||
}
|
||||
|
||||
// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
|
||||
for (U32 i = 0; i < shaders.size(); i++)
|
||||
{
|
||||
|
|
@ -910,7 +916,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
|
|||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", 3) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
|
||||
|
|
|
|||
|
|
@ -4898,7 +4898,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
|
|||
(image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui)
|
||||
{
|
||||
U32 color_fmt = type == LLSnapshotModel::SNAPSHOT_TYPE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGBA;
|
||||
if (scratch_space.allocate(image_width, image_height, color_fmt, true, true))
|
||||
if (scratch_space.allocate(image_width, image_height, color_fmt, true))
|
||||
{
|
||||
original_width = gPipeline.mRT->deferredScreen.getWidth();
|
||||
original_height = gPipeline.mRT->deferredScreen.getHeight();
|
||||
|
|
@ -5162,9 +5162,7 @@ BOOL LLViewerWindow::simpleSnapshot(LLImageRaw* raw, S32 image_width, S32 image_
|
|||
|
||||
LLRenderTarget scratch_space;
|
||||
U32 color_fmt = GL_RGBA;
|
||||
const bool use_depth_buffer = true;
|
||||
const bool use_stencil_buffer = false;
|
||||
if (scratch_space.allocate(image_width, image_height, color_fmt, use_depth_buffer, use_stencil_buffer))
|
||||
if (scratch_space.allocate(image_width, image_height, color_fmt, true))
|
||||
{
|
||||
if (gPipeline.allocateScreenBuffer(image_width, image_height))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -479,14 +479,9 @@ void LLPipeline::init()
|
|||
|
||||
mBackfaceCull = true;
|
||||
|
||||
stop_glerror();
|
||||
|
||||
// Enable features
|
||||
|
||||
LLViewerShaderMgr::instance()->setShaders();
|
||||
|
||||
stop_glerror();
|
||||
|
||||
for (U32 i = 0; i < 2; ++i)
|
||||
{
|
||||
mSpotLightFade[i] = 1.f;
|
||||
|
|
@ -835,7 +830,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
|
||||
if (RenderUIBuffer)
|
||||
{
|
||||
if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE))
|
||||
if (!mRT->uiScreen.allocate(resX,resY, GL_RGBA))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -845,18 +840,18 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
bool ssao = RenderDeferredSSAO;
|
||||
|
||||
//allocate deferred rendering color buffers
|
||||
if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true, true, LLTexUnit::TT_TEXTURE, false, samples)) return false;
|
||||
if (!mRT->deferredScreen.allocate(resX, resY, GL_RGBA, true)) return false;
|
||||
if (!addDeferredAttachments(mRT->deferredScreen)) return false;
|
||||
|
||||
GLuint screenFormat = GL_RGBA16;
|
||||
|
||||
if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, true, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
|
||||
if (!mRT->screen.allocate(resX, resY, screenFormat)) return false;
|
||||
|
||||
mRT->deferredScreen.shareDepthBuffer(mRT->screen);
|
||||
|
||||
if (samples > 0)
|
||||
{
|
||||
if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false;
|
||||
if (!mRT->fxaaBuffer.allocate(resX, resY, GL_RGBA)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -865,7 +860,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
|
||||
if (shadow_detail > 0 || ssao || RenderDepthOfField || samples > 0)
|
||||
{ //only need mRT->deferredLight for shadows OR ssao OR dof OR fxaa
|
||||
if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE)) return false;
|
||||
if (!mRT->deferredLight.allocate(resX, resY, GL_RGBA16)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -874,6 +869,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
|
|||
|
||||
allocateShadowBuffer(resX, resY);
|
||||
|
||||
if (!gCubeSnapshot && RenderScreenSpaceReflections) // hack to not allocate mSceneMap for cube snapshots
|
||||
{
|
||||
mSceneMap.allocate(resX, resY, GL_RGB, true);
|
||||
}
|
||||
|
||||
//HACK make screenbuffer allocations start failing after 30 seconds
|
||||
if (gSavedSettings.getBOOL("SimulateFBOFailure"))
|
||||
{
|
||||
|
|
@ -903,7 +903,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
|
|||
{ //allocate 4 sun shadow maps
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, true, true, LLTexUnit::TT_TEXTURE))
|
||||
if (!mRT->shadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -928,7 +928,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
|
|||
U32 spot_shadow_map_height = height;
|
||||
for (U32 i = 0; i < 2; i++)
|
||||
{
|
||||
if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, true, true))
|
||||
if (!mSpotShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1112,6 +1112,8 @@ void LLPipeline::releaseGLBuffers()
|
|||
mWaterDis.release();
|
||||
mBake.release();
|
||||
|
||||
mSceneMap.release();
|
||||
|
||||
for (U32 i = 0; i < 3; i++)
|
||||
{
|
||||
mGlow[i].release();
|
||||
|
|
@ -1185,11 +1187,11 @@ void LLPipeline::createGLBuffers()
|
|||
if (LLPipeline::sRenderTransparentWater)
|
||||
{ //water reflection texture
|
||||
U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512);
|
||||
mWaterDis.allocate(res,res,GL_RGBA,true,true,LLTexUnit::TT_TEXTURE);
|
||||
mWaterDis.allocate(res,res,GL_RGBA,true);
|
||||
}
|
||||
|
||||
// Use FBO for bake tex
|
||||
mBake.allocate(512, 512, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, true); // SL-12781 Build > Upload > Model; 3D Preview
|
||||
mBake.allocate(512, 512, GL_RGBA, true); // SL-12781 Build > Upload > Model; 3D Preview
|
||||
|
||||
stop_glerror();
|
||||
|
||||
|
|
@ -1200,7 +1202,7 @@ void LLPipeline::createGLBuffers()
|
|||
const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
|
||||
for (U32 i = 0; i < 3; i++)
|
||||
{
|
||||
mGlow[i].allocate(512, glow_res, GL_RGBA, FALSE, FALSE);
|
||||
mGlow[i].allocate(512, glow_res, GL_RGBA);
|
||||
}
|
||||
|
||||
allocateScreenBuffer(resX, resY);
|
||||
|
|
@ -1306,7 +1308,7 @@ void LLPipeline::createLUTBuffers()
|
|||
delete [] ls;
|
||||
}
|
||||
|
||||
mPbrBrdfLut.allocate(512, 512, GL_RG16F, false, false);
|
||||
mPbrBrdfLut.allocate(512, 512, GL_RG16F);
|
||||
mPbrBrdfLut.bindTarget();
|
||||
gDeferredGenBrdfLutProgram.bind();
|
||||
|
||||
|
|
@ -4019,6 +4021,26 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion)
|
|||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
}
|
||||
|
||||
if (&camera == LLViewerCamera::getInstance())
|
||||
{ // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and
|
||||
// current modelview matrix
|
||||
glh::matrix4f last_modelview(gGLLastModelView);
|
||||
glh::matrix4f cur_modelview(gGLModelView);
|
||||
|
||||
// goal is to have a matrix here that goes from the last frame's camera space to the current frame's camera space
|
||||
glh::matrix4f m = last_modelview.inverse(); // last camera space to world space
|
||||
m.mult_left(cur_modelview); // world space to camera space
|
||||
|
||||
glh::matrix4f n = m.inverse();
|
||||
|
||||
for (U32 i = 0; i < 16; ++i)
|
||||
{
|
||||
gGLDeltaModelView[i] = m.m[i];
|
||||
gGLInverseDeltaModelView[i] = n.m[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool occlude = LLPipeline::sUseOcclusion > 1 && do_occlusion;
|
||||
|
||||
setupHWLights(nullptr);
|
||||
|
|
@ -7529,10 +7551,11 @@ void LLPipeline::renderFinalize()
|
|||
|
||||
if (!gCubeSnapshot)
|
||||
{
|
||||
screenTarget()->bindTarget();
|
||||
LLRenderTarget* screen_target = screenTarget();
|
||||
|
||||
if (RenderScreenSpaceReflections)
|
||||
if (RenderScreenSpaceReflections && !gCubeSnapshot)
|
||||
{
|
||||
#if 0
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("renderDeferredLighting - screen space reflections");
|
||||
LL_PROFILE_GPU_ZONE("screen space reflections");
|
||||
|
||||
|
|
@ -7565,8 +7588,33 @@ void LLPipeline::renderFinalize()
|
|||
}
|
||||
|
||||
unbindDeferredShader(gPostScreenSpaceReflectionProgram);
|
||||
#else
|
||||
LL_PROFILE_GPU_ZONE("ssr copy");
|
||||
LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
|
||||
|
||||
LLRenderTarget& src = *screen_target;
|
||||
LLRenderTarget& depth_src = mRT->deferredScreen;
|
||||
LLRenderTarget& dst = mSceneMap;
|
||||
|
||||
dst.bindTarget();
|
||||
dst.clear();
|
||||
gCopyDepthProgram.bind();
|
||||
|
||||
S32 diff_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DIFFUSE_MAP);
|
||||
S32 depth_map = gCopyDepthProgram.getTextureChannel(LLShaderMgr::DEFERRED_DEPTH);
|
||||
|
||||
gGL.getTexUnit(diff_map)->bind(&src);
|
||||
gGL.getTexUnit(depth_map)->bind(&depth_src, true);
|
||||
|
||||
mScreenTriangleVB->setBuffer();
|
||||
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
|
||||
dst.flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
screenTarget()->bindTarget();
|
||||
|
||||
// gamma correct lighting
|
||||
{
|
||||
LL_PROFILE_GPU_ZONE("gamma correct");
|
||||
|
|
@ -7821,56 +7869,6 @@ void LLPipeline::bindDeferredShaderFast(LLGLSLShader& shader)
|
|||
bindLightFunc(shader);
|
||||
bindShadowMaps(shader);
|
||||
bindReflectionProbes(shader);
|
||||
|
||||
#if 0
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_BLUR_SIZE, RenderShadowBlurSize);
|
||||
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_RADIUS, RenderSSAOScale);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_MAX_RADIUS, RenderSSAOMaxScale);
|
||||
|
||||
F32 ssao_factor = RenderSSAOFactor;
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR, ssao_factor);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SSAO_FACTOR_INV, 1.0 / ssao_factor);
|
||||
|
||||
LLVector3 ssao_effect = RenderSSAOEffect;
|
||||
F32 matrix_diag = (ssao_effect[0] + 2.0 * ssao_effect[1]) / 3.0;
|
||||
F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1]) / 3.0;
|
||||
// This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
|
||||
// value factor, and scales remainder by saturation factor
|
||||
F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag,
|
||||
matrix_nondiag, matrix_diag, matrix_nondiag,
|
||||
matrix_nondiag, matrix_nondiag, matrix_diag };
|
||||
shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat);
|
||||
|
||||
//F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
|
||||
F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]) / 3000.f;
|
||||
F32 shadow_bias = RenderShadowBias + shadow_bias_error;
|
||||
|
||||
//shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_target->getWidth(), deferred_target->getHeight());
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear() * 2.f);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, shadow_bias);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);
|
||||
|
||||
shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
|
||||
shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
|
||||
shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mRT->shadow[0].getWidth(), mRT->shadow[0].getHeight());
|
||||
shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mSpotShadow[0].getWidth(), mSpotShadow[0].getHeight());
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
|
||||
|
||||
if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
|
||||
{
|
||||
glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
|
||||
shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
|
||||
}
|
||||
|
||||
shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV);
|
||||
shader.uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
|
||||
|
|
@ -7910,21 +7908,24 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
|
|||
gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
}
|
||||
|
||||
#if 0
|
||||
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
|
||||
if (channel > -1)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bind(deferred_depth_target, TRUE);
|
||||
stop_glerror();
|
||||
}
|
||||
#else
|
||||
channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_target->getUsage());
|
||||
if (channel > -1)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bind(deferred_target, TRUE);
|
||||
stop_glerror();
|
||||
}
|
||||
#endif
|
||||
|
||||
channel = shader.enableTexture(LLShaderMgr::SCENE_MAP);
|
||||
if (channel > -1)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bind(&mSceneMap);
|
||||
}
|
||||
|
||||
channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH);
|
||||
if (channel > -1)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bind(&mSceneMap, true);
|
||||
}
|
||||
|
||||
if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1)
|
||||
{
|
||||
|
|
@ -8090,6 +8091,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
|
|||
shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
|
||||
shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
|
||||
|
||||
shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLDeltaModelView);
|
||||
shader.uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_DELTA_MATRIX, 1, GL_FALSE, gGLInverseDeltaModelView);
|
||||
|
||||
shader.uniform1i(LLShaderMgr::CUBE_SNAPSHOT, gCubeSnapshot ? 1 : 0);
|
||||
|
||||
if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
|
||||
{
|
||||
glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
|
||||
|
|
@ -8584,6 +8590,16 @@ void LLPipeline::renderDeferredLighting()
|
|||
|
||||
screen_target->flush();
|
||||
|
||||
if (!gCubeSnapshot)
|
||||
{
|
||||
// this is the end of the 3D scene render, grab a copy of the modelview and projection
|
||||
// matrix for use in off-by-one-frame effects in the next frame
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
{
|
||||
gGLLastModelView[i] = gGLModelView[i];
|
||||
gGLLastProjection[i] = gGLProjection[i];
|
||||
}
|
||||
}
|
||||
gGL.setColorMask(true, true);
|
||||
}
|
||||
|
||||
|
|
@ -10398,7 +10414,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar, bool preview_avatar)
|
|||
|
||||
if (!avatar->mImpostor.isComplete())
|
||||
{
|
||||
avatar->mImpostor.allocate(resX, resY, GL_RGBA, TRUE, FALSE);
|
||||
avatar->mImpostor.allocate(resX, resY, GL_RGBA, true);
|
||||
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -685,6 +685,10 @@ public:
|
|||
|
||||
LLRenderTarget mPbrBrdfLut;
|
||||
|
||||
// copy of the color/depth buffer just before gamma correction
|
||||
// for use by SSR
|
||||
LLRenderTarget mSceneMap;
|
||||
|
||||
LLCullResult mSky;
|
||||
LLCullResult mReflectedObjects;
|
||||
LLCullResult mRefractedObjects;
|
||||
|
|
|
|||
Loading…
Reference in New Issue