Merge branch 'DRTVWR-546' of https://bitbucket.org/lindenlab/viewer
# Conflicts: # indra/llrender/llrender.h # indra/newview/lldrawpoolalpha.cpp # indra/newview/lldrawpoolbump.cpp # indra/newview/lldrawpooltree.cpp # indra/newview/llmodelpreview.cpp # indra/newview/llviewertexture.cppmaster
commit
381f8936f0
|
|
@ -88,24 +88,32 @@ void APIENTRY gl_debug_callback(GLenum source,
|
|||
{
|
||||
if (gGLDebugLoggingEnabled)
|
||||
{
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
|
||||
}
|
||||
LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
|
||||
LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
|
||||
LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
|
||||
LL_WARNS() << "Message: " << message << LL_ENDL;
|
||||
LL_WARNS() << "-----------------------" << LL_ENDL;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
LL_ERRS() << "Halting on GL Error" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
|
||||
severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
|
||||
severity != GL_DEBUG_SEVERITY_LOW_ARB)
|
||||
{ //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
|
||||
return;
|
||||
}
|
||||
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
|
||||
}
|
||||
LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
|
||||
LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
|
||||
LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
|
||||
LL_WARNS() << "Message: " << message << LL_ENDL;
|
||||
LL_WARNS() << "-----------------------" << LL_ENDL;
|
||||
if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
|
||||
{
|
||||
LL_ERRS() << "Halting on GL Error" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@
|
|||
#include "llrender.h"
|
||||
#include "llwindow.h"
|
||||
|
||||
#if !LL_IMAGEGL_THREAD_CHECK
|
||||
#define checkActiveThread()
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const F32 MIN_TEXTURE_LIFETIME = 10.f;
|
||||
|
||||
|
|
@ -445,6 +449,10 @@ LLImageGL::~LLImageGL()
|
|||
|
||||
void LLImageGL::init(BOOL usemipmaps)
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
|
||||
// keep these members in the same order as declared in llimagehl.h
|
||||
// so that it is obvious by visual inspection if we forgot to
|
||||
// init a field.
|
||||
|
|
@ -1325,6 +1333,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
BOOL LLImageGL::createGLTexture()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
checkActiveThread();
|
||||
|
||||
if (gGLManager.mIsDisabled)
|
||||
{
|
||||
LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
|
||||
|
|
@ -1357,6 +1367,8 @@ BOOL LLImageGL::createGLTexture()
|
|||
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
checkActiveThread();
|
||||
|
||||
if (gGLManager.mIsDisabled)
|
||||
{
|
||||
LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
|
||||
|
|
@ -1470,6 +1482,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
|
|||
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
checkActiveThread();
|
||||
|
||||
llassert(data_in);
|
||||
stop_glerror();
|
||||
|
||||
|
|
@ -1584,6 +1598,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
|||
// mark this as bound at this point, so we don't throw it out immediately
|
||||
mLastBindTime = sLastFrameTime;
|
||||
|
||||
checkActiveThread();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1698,18 +1713,10 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
|
|||
return TRUE ;
|
||||
}
|
||||
|
||||
void LLImageGL::deleteDeadTextures()
|
||||
{
|
||||
bool reset = false;
|
||||
|
||||
if (reset)
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageGL::destroyGLTexture()
|
||||
{
|
||||
checkActiveThread();
|
||||
|
||||
if (mTexName != 0)
|
||||
{
|
||||
if(mTextureMemory != S32Bytes(0))
|
||||
|
|
@ -1728,6 +1735,7 @@ void LLImageGL::destroyGLTexture()
|
|||
//force to invalidate the gl texture, most likely a sculpty texture
|
||||
void LLImageGL::forceToInvalidateGLTexture()
|
||||
{
|
||||
checkActiveThread();
|
||||
if (mTexName != 0)
|
||||
{
|
||||
destroyGLTexture();
|
||||
|
|
@ -2207,6 +2215,12 @@ void LLImageGL::resetCurTexSizebar()
|
|||
sCurTexPickSize = -1 ;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
void LLImageGL::checkActiveThread()
|
||||
{
|
||||
llassert(mActiveThread == LLThread::currentID());
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@
|
|||
#include "threadpool.h"
|
||||
#include "workqueue.h"
|
||||
|
||||
class LLTextureAtlas ;
|
||||
#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL
|
||||
|
||||
class LLWindow;
|
||||
|
||||
#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
|
||||
|
|
@ -54,7 +55,6 @@ public:
|
|||
// These 2 functions replace glGenTextures() and glDeleteTextures()
|
||||
static void generateTextures(S32 numTextures, U32 *textures);
|
||||
static void deleteTextures(S32 numTextures, const U32 *textures);
|
||||
static void deleteDeadTextures();
|
||||
|
||||
// Size calculation
|
||||
static S32 dataFormatBits(S32 dataformat);
|
||||
|
|
@ -195,6 +195,12 @@ public:
|
|||
BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
|
||||
void postAddToAtlas() ;
|
||||
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
// thread debugging
|
||||
std::thread::id mActiveThread;
|
||||
void checkActiveThread();
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Various GL/Rendering options
|
||||
S32Bytes mTextureMemory;
|
||||
|
|
|
|||
|
|
@ -74,18 +74,6 @@ static const GLint sGLAddressMode[] =
|
|||
GL_CLAMP_TO_EDGE
|
||||
};
|
||||
|
||||
static const GLenum sGLCompareFunc[] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_ALWAYS,
|
||||
GL_LESS,
|
||||
GL_LEQUAL,
|
||||
GL_EQUAL,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_GREATER
|
||||
};
|
||||
|
||||
const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
|
||||
|
||||
static const GLenum sGLBlendFactor[] =
|
||||
|
|
@ -105,10 +93,7 @@ static const GLenum sGLBlendFactor[] =
|
|||
};
|
||||
|
||||
LLTexUnit::LLTexUnit(S32 index)
|
||||
: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT),
|
||||
mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
|
||||
mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
|
||||
mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
|
||||
: mCurrTexType(TT_NONE),
|
||||
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR),
|
||||
mHasMipMaps(false),
|
||||
mIndex(index)
|
||||
|
|
@ -199,7 +184,11 @@ void LLTexUnit::bindFast(LLTexture* texture)
|
|||
mCurrTexture = gl_tex->getTexName();
|
||||
if (!mCurrTexture)
|
||||
{
|
||||
mCurrTexture = LLImageGL::sDefaultGLTexture->getTexName();
|
||||
LL_PROFILE_ZONE_NAMED("MISSING TEXTURE");
|
||||
//if deleted, will re-generate it immediately
|
||||
texture->forceImmediateUpdate();
|
||||
gl_tex->forceUpdateBindStats();
|
||||
texture->bindDefaultImage(mIndex);
|
||||
}
|
||||
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
|
||||
mHasMipMaps = gl_tex->mHasMipMaps;
|
||||
|
|
@ -855,8 +844,6 @@ LLRender::LLRender()
|
|||
mCurrColorMask[i] = true;
|
||||
}
|
||||
|
||||
mCurrAlphaFunc = CF_DEFAULT;
|
||||
mCurrAlphaFuncVal = 0.01f;
|
||||
mCurrBlendColorSFactor = BF_UNDEF;
|
||||
mCurrBlendAlphaSFactor = BF_UNDEF;
|
||||
mCurrBlendColorDFactor = BF_UNDEF;
|
||||
|
|
|
|||
|
|
@ -224,13 +224,6 @@ protected:
|
|||
const S32 mIndex;
|
||||
U32 mCurrTexture;
|
||||
eTextureType mCurrTexType;
|
||||
eTextureBlendType mCurrBlendType;
|
||||
eTextureBlendOp mCurrColorOp;
|
||||
eTextureBlendSrc mCurrColorSrc1;
|
||||
eTextureBlendSrc mCurrColorSrc2;
|
||||
eTextureBlendOp mCurrAlphaOp;
|
||||
eTextureBlendSrc mCurrAlphaSrc1;
|
||||
eTextureBlendSrc mCurrAlphaSrc2;
|
||||
eTextureColorSpace mTexColorSpace;
|
||||
S32 mCurrColorScale;
|
||||
S32 mCurrAlphaScale;
|
||||
|
|
@ -499,8 +492,6 @@ private:
|
|||
U32 mMode;
|
||||
U32 mCurrTextureUnitIndex;
|
||||
bool mCurrColorMask[4];
|
||||
eCompareFunc mCurrAlphaFunc;
|
||||
F32 mCurrAlphaFuncVal;
|
||||
F32 mLineWidth; // <FS> Line width OGL core profile fix by Rye Mutt
|
||||
// <FS:Ansariel> Don't ignore OpenGL max line width
|
||||
F32 mMaxLineWidthSmooth;
|
||||
|
|
|
|||
|
|
@ -705,8 +705,6 @@ set(viewer_SOURCE_FILES
|
|||
llsyswellwindow.cpp
|
||||
llteleporthistory.cpp
|
||||
llteleporthistorystorage.cpp
|
||||
lltextureatlas.cpp
|
||||
lltextureatlasmanager.cpp
|
||||
lltexturecache.cpp
|
||||
lltexturectrl.cpp
|
||||
lltexturefetch.cpp
|
||||
|
|
@ -1474,8 +1472,6 @@ set(viewer_HEADER_FILES
|
|||
lltable.h
|
||||
llteleporthistory.h
|
||||
llteleporthistorystorage.h
|
||||
lltextureatlas.h
|
||||
lltextureatlasmanager.h
|
||||
lltexturecache.h
|
||||
lltexturectrl.h
|
||||
lltexturefetch.h
|
||||
|
|
|
|||
|
|
@ -40,11 +40,11 @@ VARYING vec4 post_pos;
|
|||
VARYING float pos_w;
|
||||
VARYING float target_pos_x;
|
||||
VARYING vec2 vary_texcoord0;
|
||||
VARYING vec4 vertex_color;
|
||||
uniform vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
|
||||
float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * color.a;
|
||||
|
||||
if (alpha < 0.05) // treat as totally transparent
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ uniform float shadow_target_width;
|
|||
mat4 getSkinnedTransform();
|
||||
void passTextureIndex();
|
||||
|
||||
ATTRIBUTE vec4 diffuse_color;
|
||||
ATTRIBUTE vec3 position;
|
||||
ATTRIBUTE vec3 normal;
|
||||
ATTRIBUTE vec2 texcoord0;
|
||||
|
|
@ -41,7 +40,6 @@ VARYING vec4 post_pos;
|
|||
VARYING float pos_w;
|
||||
VARYING float target_pos_x;
|
||||
VARYING vec2 vary_texcoord0;
|
||||
VARYING vec4 vertex_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
@ -68,7 +66,6 @@ void main()
|
|||
|
||||
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
|
||||
|
||||
vertex_color = diffuse_color;
|
||||
#if !DEPTH_CLAMP
|
||||
post_pos = pos;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ class LLDrawable
|
|||
{
|
||||
LL_ALIGN_NEW;
|
||||
public:
|
||||
typedef std::vector<LLFace*> face_list_t;
|
||||
|
||||
LLDrawable(const LLDrawable& rhs)
|
||||
: LLViewerOctreeEntryData(rhs)
|
||||
{
|
||||
|
|
@ -129,6 +131,7 @@ public:
|
|||
|
||||
inline LLFace* getFace(const S32 i) const;
|
||||
inline S32 getNumFaces() const;
|
||||
face_list_t& getFaces() { return mFaces; }
|
||||
|
||||
//void removeFace(const S32 i); // SJB: Avoid using this, it's slow
|
||||
LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep);
|
||||
|
|
@ -297,8 +300,6 @@ public:
|
|||
static F32 sCurPixelAngle; //current pixels per radian
|
||||
|
||||
private:
|
||||
typedef std::vector<LLFace*> face_list_t;
|
||||
|
||||
U32 mState;
|
||||
S32 mRenderType;
|
||||
LLPointer<LLViewerObject> mVObjp;
|
||||
|
|
|
|||
|
|
@ -81,218 +81,162 @@ void LLDrawPoolAlpha::prerender()
|
|||
|
||||
S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
|
||||
{
|
||||
static LLCachedControl<bool> RenderDepthOfField(gSavedSettings, "RenderDepthOfField"); // <FS:PP> Attempt to speed up things a little
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{ //skip depth buffer filling pass when rendering impostors
|
||||
return 1;
|
||||
}
|
||||
// <FS:PP> Attempt to speed up things a little
|
||||
// else if (gSavedSettings.getBOOL("RenderDepthOfField"))
|
||||
else if (RenderDepthOfField)
|
||||
// </FS:PP>
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
// set some common parameters on the given shader to prepare for alpha rendering
|
||||
static void prepare_alpha_shader(LLGLSLShader* shader, bool textureGamma)
|
||||
{
|
||||
static LLCachedControl<F32> displayGamma(gSavedSettings, "RenderDeferredDisplayGamma");
|
||||
F32 gamma = displayGamma;
|
||||
|
||||
//F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
|
||||
static LLCachedControl<F32> gamma(gSavedSettings, "RenderDeferredDisplayGamma");
|
||||
shader->bind();
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
|
||||
shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
|
||||
|
||||
emissive_shader[0] = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
emissive_shader[1] = emissive_shader[0]->mRiggedVariant;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
emissive_shader[i]->bind();
|
||||
emissive_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
|
||||
emissive_shader[i]->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
emissive_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
|
||||
shader->setMinimumAlpha(0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->setMinimumAlpha(0.f);
|
||||
}
|
||||
if (textureGamma)
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
}
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
fullbright_shader[0] = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
|
||||
fullbright_shader[1] = fullbright_shader[0]->mRiggedVariant;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
fullbright_shader[i]->bind();
|
||||
fullbright_shader[i]->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
fullbright_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
|
||||
fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
fullbright_shader[i]->unbind();
|
||||
}
|
||||
|
||||
simple_shader[0] = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
|
||||
simple_shader[1] = simple_shader[0]->mRiggedVariant;
|
||||
|
||||
//prime simple shader (loads shadow relevant uniforms)
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
gPipeline.bindDeferredShader(*simple_shader[i]);
|
||||
simple_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
|
||||
simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
}
|
||||
}
|
||||
else if (!LLPipeline::sImpostorRender)
|
||||
{
|
||||
//update depth buffer sampler
|
||||
gPipeline.mScreen.flush();
|
||||
gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
|
||||
0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
gPipeline.mDeferredDepth.bindTarget();
|
||||
simple_shader[0] = fullbright_shader[0] = &gObjectFullbrightAlphaMaskProgram;
|
||||
simple_shader[1] = fullbright_shader[1] = simple_shader[0]->mRiggedVariant;
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
simple_shader[i]->bind();
|
||||
simple_shader[i]->setMinimumAlpha(0.33f);
|
||||
}
|
||||
}
|
||||
|
||||
deferred_render = TRUE;
|
||||
if (mShaderLevel > 0)
|
||||
{
|
||||
// Start out with no shaders.
|
||||
target_shader = NULL;
|
||||
}
|
||||
gPipeline.enableLightsDynamic();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::endPostDeferredPass(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
if (pass == 1 && !LLPipeline::sImpostorRender)
|
||||
{
|
||||
gPipeline.mDeferredDepth.flush();
|
||||
gPipeline.mScreen.bindTarget();
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
}
|
||||
|
||||
deferred_render = FALSE;
|
||||
endRenderPass(pass);
|
||||
//also prepare rigged variant
|
||||
if (shader->mRiggedVariant && shader->mRiggedVariant != shader)
|
||||
{
|
||||
prepare_alpha_shader(shader->mRiggedVariant, textureGamma);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderPostDeferred(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
render(pass);
|
||||
}
|
||||
deferred_render = TRUE;
|
||||
|
||||
void LLDrawPoolAlpha::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
simple_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram;
|
||||
// first pass, regular forward alpha rendering
|
||||
{
|
||||
emissive_shader = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
prepare_alpha_shader(emissive_shader, true);
|
||||
|
||||
fullbright_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
|
||||
fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
|
||||
prepare_alpha_shader(fullbright_shader, true);
|
||||
|
||||
emissive_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
|
||||
simple_shader[1] = simple_shader[0]->mRiggedVariant;
|
||||
fullbright_shader[1] = fullbright_shader[0]->mRiggedVariant;
|
||||
emissive_shader[1] = emissive_shader[0]->mRiggedVariant;
|
||||
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
fullbright_shader[i]->bind();
|
||||
fullbright_shader[i]->setMinimumAlpha(0.5f);
|
||||
fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
simple_shader[i]->bind();
|
||||
simple_shader[i]->setMinimumAlpha(0.5f);
|
||||
simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
fullbright_shader[i]->bind();
|
||||
fullbright_shader[i]->setMinimumAlpha(0.f);
|
||||
fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
simple_shader[i]->bind();
|
||||
simple_shader[i]->setMinimumAlpha(0.f);
|
||||
simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
}
|
||||
simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
|
||||
prepare_alpha_shader(simple_shader, false);
|
||||
|
||||
forwardRender();
|
||||
}
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
LLGLSLShader::bindNoShader();
|
||||
// second pass, render to depth for depth of field effects
|
||||
if (!LLPipeline::sImpostorRender && gSavedSettings.getBOOL("RenderDepthOfField"))
|
||||
{
|
||||
//update depth buffer sampler
|
||||
gPipeline.mScreen.flush();
|
||||
gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
|
||||
0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
gPipeline.mDeferredDepth.bindTarget();
|
||||
simple_shader = fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
|
||||
|
||||
simple_shader->bind();
|
||||
simple_shader->setMinimumAlpha(0.33f);
|
||||
|
||||
// mask off color buffer writes as we're only writing to depth buffer
|
||||
gGL.setColorMask(false, false);
|
||||
|
||||
// If the face is more than 90% transparent, then don't update the Depth buffer for Dof
|
||||
// We don't want the nearly invisible objects to cause of DoF effects
|
||||
renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2,
|
||||
true); // <--- discard mostly transparent faces
|
||||
|
||||
gPipeline.mDeferredDepth.flush();
|
||||
gPipeline.mScreen.bindTarget();
|
||||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
||||
renderDebugAlpha();
|
||||
|
||||
deferred_render = FALSE;
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::endRenderPass( S32 pass )
|
||||
//set some generic parameters for forward (non-deferred) rendering
|
||||
static void prepare_forward_shader(LLGLSLShader* shader, F32 minimum_alpha)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
shader->bind();
|
||||
shader->setMinimumAlpha(minimum_alpha);
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
|
||||
|
||||
if(gPipeline.canUseWindLightShaders())
|
||||
{
|
||||
LLGLSLShader::bindNoShader();
|
||||
}
|
||||
//also prepare rigged variant
|
||||
if (shader->mRiggedVariant && shader->mRiggedVariant != shader)
|
||||
{
|
||||
prepare_forward_shader(shader->mRiggedVariant, minimum_alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::render(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA);
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA);
|
||||
|
||||
LLGLSPipelineAlpha gls_pipeline_alpha;
|
||||
simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram;
|
||||
|
||||
if (deferred_render && pass == 1)
|
||||
{ //depth only
|
||||
gGL.setColorMask(false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.setColorMask(true, true);
|
||||
}
|
||||
|
||||
bool write_depth = LLDrawPoolWater::sSkipScreenCopy
|
||||
|| (deferred_render && pass == 1)
|
||||
// we want depth written so that rendered alpha will
|
||||
// contribute to the alpha mask used for impostors
|
||||
|| LLPipeline::sImpostorRenderAlphaDepthPass;
|
||||
fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE);
|
||||
emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
|
||||
(LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
|
||||
if (deferred_render && pass == 1)
|
||||
{
|
||||
gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
|
||||
}
|
||||
else
|
||||
{
|
||||
mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend
|
||||
mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression
|
||||
mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
}
|
||||
F32 minimum_alpha = 0.f;
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
minimum_alpha = 0.5f;
|
||||
}
|
||||
prepare_forward_shader(fullbright_shader, minimum_alpha);
|
||||
prepare_forward_shader(simple_shader, minimum_alpha);
|
||||
|
||||
renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass);
|
||||
forwardRender();
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
renderDebugAlpha();
|
||||
}
|
||||
|
||||
if (deferred_render && pass == 1)
|
||||
{
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
void LLDrawPoolAlpha::forwardRender()
|
||||
{
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
LLGLSPipelineAlpha gls_pipeline_alpha;
|
||||
|
||||
//enable writing to alpha for emissive effects
|
||||
gGL.setColorMask(true, true);
|
||||
|
||||
bool write_depth = LLDrawPoolWater::sSkipScreenCopy
|
||||
// we want depth written so that rendered alpha will
|
||||
// contribute to the alpha mask used for impostors
|
||||
|| LLPipeline::sImpostorRenderAlphaDepthPass;
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE, write_depth ? GL_TRUE : GL_FALSE);
|
||||
|
||||
mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend
|
||||
mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression
|
||||
mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
// If the face is more than 90% transparent, then don't update the Depth buffer for Dof
|
||||
// We don't want the nearly invisible objects to cause of DoF effects
|
||||
renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2);
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderDebugAlpha()
|
||||
{
|
||||
if (sShowDebugAlpha)
|
||||
{
|
||||
gHighlightProgram.bind();
|
||||
|
|
@ -421,7 +365,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material)
|
|||
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
|
||||
}
|
||||
}
|
||||
else if (current_shader == simple_shader[0] || current_shader == simple_shader[1])
|
||||
else if (current_shader == simple_shader || current_shader == simple_shader->mRiggedVariant)
|
||||
{
|
||||
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
|
||||
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
|
||||
|
|
@ -488,14 +432,8 @@ void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
|
|||
|
||||
void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
|
||||
{
|
||||
emissive_shader[0]->bind();
|
||||
emissive_shader[0]->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
|
||||
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
// install glow-accumulating blend mode
|
||||
// don't touch color, add to alpha (glow)
|
||||
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
|
||||
emissive_shader->bind();
|
||||
emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
|
||||
|
||||
for (LLDrawInfo* draw : emissives)
|
||||
{
|
||||
|
|
@ -503,24 +441,13 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
|
|||
drawEmissive(mask, draw);
|
||||
RestoreTexSetup(tex_setup);
|
||||
}
|
||||
|
||||
// restore our alpha blend mode
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
emissive_shader[0]->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
|
||||
{
|
||||
emissive_shader[1]->bind();
|
||||
emissive_shader[1]->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
|
||||
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
mask |= LLVertexBuffer::MAP_WEIGHT4;
|
||||
// install glow-accumulating blend mode
|
||||
// don't touch color, add to alpha (glow)
|
||||
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
|
||||
LLGLSLShader* shader = emissive_shader->mRiggedVariant;
|
||||
shader->bind();
|
||||
shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
|
||||
|
||||
LLVOAvatar* lastAvatar = nullptr;
|
||||
U64 lastMeshId = 0;
|
||||
|
|
@ -550,14 +477,9 @@ void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>&
|
|||
drawEmissive(mask, draw);
|
||||
RestoreTexSetup(tex_setup);
|
||||
}
|
||||
|
||||
// restore our alpha blend mode
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
emissive_shader[1]->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
||||
void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
BOOL initialized_lighting = FALSE;
|
||||
|
|
@ -630,17 +552,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
}
|
||||
// </FS:Beq>
|
||||
|
||||
// Fix for bug - NORSPEC-271
|
||||
// If the face is more than 90% transparent, then don't update the Depth buffer for Dof
|
||||
// We don't want the nearly invisible objects to cause of DoF effects
|
||||
if(pass == 1 && !LLPipeline::sImpostorRender)
|
||||
if(depth_only)
|
||||
{
|
||||
// when updating depth buffer, discard faces that are more than 90% transparent
|
||||
LLFace* face = params.mFace;
|
||||
if(face)
|
||||
{
|
||||
const LLTextureEntry* tep = face->getTextureEntry();
|
||||
if(tep)
|
||||
{
|
||||
{ // don't render faces that are more than 90% transparent
|
||||
if(tep->getColor().mV[3] < 0.1f)
|
||||
continue;
|
||||
}
|
||||
|
|
@ -662,7 +582,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
if (light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
target_shader = fullbright_shader[0];
|
||||
target_shader = fullbright_shader;
|
||||
|
||||
light_enabled = FALSE;
|
||||
}
|
||||
|
|
@ -671,7 +591,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
else if (!light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
target_shader = simple_shader[0];
|
||||
target_shader = simple_shader;
|
||||
light_enabled = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -700,11 +620,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
}
|
||||
else if (!params.mFullbright)
|
||||
{
|
||||
target_shader = simple_shader[0];
|
||||
target_shader = simple_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
target_shader = fullbright_shader[0];
|
||||
target_shader = fullbright_shader;
|
||||
}
|
||||
|
||||
if (params.mAvatar != nullptr)
|
||||
|
|
@ -808,7 +728,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
ratPtr.reset(); // force the final batch to terminate to avoid double counting on the subsidiary batches for FB and Emmissives
|
||||
// </FS:Beq>
|
||||
|
||||
// render emissive faces into alpha channel for bloom effects
|
||||
if (!depth_only)
|
||||
{
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
// install glow-accumulating blend mode
|
||||
// don't touch color, add to alpha (glow)
|
||||
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
|
||||
|
||||
bool rebind = false;
|
||||
LLGLSLShader* lastShader = current_shader;
|
||||
if (!emissives.empty())
|
||||
|
|
@ -825,6 +753,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
|
|||
rebind = true;
|
||||
}
|
||||
|
||||
// restore our alpha blend mode
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
if (lastShader && rebind)
|
||||
{
|
||||
lastShader->bind();
|
||||
|
|
|
|||
|
|
@ -51,19 +51,17 @@ public:
|
|||
/*virtual*/ ~LLDrawPoolAlpha();
|
||||
|
||||
/*virtual*/ S32 getNumPostDeferredPasses();
|
||||
/*virtual*/ void beginPostDeferredPass(S32 pass);
|
||||
/*virtual*/ void endPostDeferredPass(S32 pass);
|
||||
/*virtual*/ void renderPostDeferred(S32 pass);
|
||||
|
||||
/*virtual*/ void beginRenderPass(S32 pass = 0);
|
||||
/*virtual*/ void endRenderPass( S32 pass );
|
||||
/*virtual*/ S32 getNumPasses() { return 1; }
|
||||
|
||||
virtual void render(S32 pass = 0);
|
||||
void forwardRender();
|
||||
/*virtual*/ void prerender();
|
||||
|
||||
void renderDebugAlpha();
|
||||
|
||||
void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
|
||||
void renderAlpha(U32 mask, S32 pass);
|
||||
void renderAlpha(U32 mask, bool depth_only = false);
|
||||
void renderAlphaHighlight(U32 mask);
|
||||
bool uploadMatrixPalette(const LLDrawInfo& params);
|
||||
|
||||
|
|
@ -73,9 +71,9 @@ private:
|
|||
LLGLSLShader* target_shader;
|
||||
|
||||
// setup by beginFooPass, [0] is static variant, [1] is rigged variant
|
||||
LLGLSLShader* simple_shader[2] = { nullptr };
|
||||
LLGLSLShader* fullbright_shader[2] = { nullptr };
|
||||
LLGLSLShader* emissive_shader[2] = { nullptr };
|
||||
LLGLSLShader* simple_shader = nullptr;
|
||||
LLGLSLShader* fullbright_shader = nullptr;
|
||||
LLGLSLShader* emissive_shader = nullptr;
|
||||
|
||||
void drawEmissive(U32 mask, LLDrawInfo* draw);
|
||||
void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
|
||||
|
|
|
|||
|
|
@ -204,25 +204,7 @@ void LLDrawPoolBump::prerender()
|
|||
// static
|
||||
S32 LLDrawPoolBump::numBumpPasses()
|
||||
{
|
||||
// <FS:Ansariel> Use faster LLCachedControls for frequently visited locations
|
||||
//if (gSavedSettings.getBOOL("RenderObjectBump"))
|
||||
static LLCachedControl<bool> renderObjectBump(gSavedSettings, "RenderObjectBump");
|
||||
if (renderObjectBump)
|
||||
// </FS:Ansariel>
|
||||
{
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
S32 LLDrawPoolBump::getNumPasses()
|
||||
|
|
@ -230,108 +212,49 @@ S32 LLDrawPoolBump::getNumPasses()
|
|||
return numBumpPasses();
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
mRigged = ((pass % 2) == 1);
|
||||
pass /= 2;
|
||||
switch( pass )
|
||||
{
|
||||
case 0:
|
||||
beginShiny();
|
||||
break;
|
||||
case 1:
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
beginFullbrightShiny();
|
||||
}
|
||||
else
|
||||
{
|
||||
beginBump();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
beginBump();
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::render(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
|
||||
if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
pass /= 2;
|
||||
switch( pass )
|
||||
{
|
||||
case 0:
|
||||
renderShiny();
|
||||
break;
|
||||
case 1:
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
renderFullbrightShiny();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderBump();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
renderBump();
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
|
||||
if (!gPipeline.hasRenderType(LLDrawPool::POOL_SIMPLE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
mRigged = i == 1;
|
||||
|
||||
// first pass -- shiny
|
||||
beginShiny();
|
||||
renderShiny();
|
||||
endShiny();
|
||||
|
||||
//second pass -- fullbright shiny
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
beginFullbrightShiny();
|
||||
renderFullbrightShiny();
|
||||
endFullbrightShiny();
|
||||
}
|
||||
|
||||
//third pass -- bump
|
||||
beginBump();
|
||||
renderBump(LLRenderPass::PASS_BUMP);
|
||||
endBump();
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::endRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
pass /= 2;
|
||||
switch( pass )
|
||||
{
|
||||
case 0:
|
||||
endShiny();
|
||||
break;
|
||||
case 1:
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
endFullbrightShiny();
|
||||
}
|
||||
else
|
||||
{
|
||||
endBump();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
endBump();
|
||||
break;
|
||||
default:
|
||||
llassert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
//to cleanup texture channels
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLDrawPoolBump::beginShiny(bool invisible)
|
||||
void LLDrawPoolBump::beginShiny()
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
|
||||
|
||||
mShiny = TRUE;
|
||||
sVertexMask = VERTEX_MASK_SHINY;
|
||||
// Second pass: environment map
|
||||
if (!invisible && mShaderLevel > 1)
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
|
||||
}
|
||||
|
|
@ -361,7 +284,7 @@ void LLDrawPoolBump::beginShiny(bool invisible)
|
|||
shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
|
||||
bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
|
||||
bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel);
|
||||
|
||||
if (mShaderLevel > 1)
|
||||
{ //indexed texture rendering, channel 0 is always diffuse
|
||||
|
|
@ -370,12 +293,12 @@ void LLDrawPoolBump::beginShiny(bool invisible)
|
|||
}
|
||||
|
||||
//static
|
||||
void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible)
|
||||
void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel)
|
||||
{
|
||||
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
|
||||
if( cube_map )
|
||||
{
|
||||
if (!invisible && shader )
|
||||
if (shader )
|
||||
{
|
||||
LLMatrix4 mat;
|
||||
mat.initRows(LLVector4(gGLModelView+0),
|
||||
|
|
@ -413,14 +336,14 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di
|
|||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::renderShiny(bool invisible)
|
||||
void LLDrawPoolBump::renderShiny()
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
|
||||
|
||||
if( gSky.mVOSkyp->getCubeMap() )
|
||||
{
|
||||
LLGLEnable blend_enable(GL_BLEND);
|
||||
if (!invisible && mShaderLevel > 1)
|
||||
if (mShaderLevel > 1)
|
||||
{
|
||||
if (mRigged)
|
||||
{
|
||||
|
|
@ -431,7 +354,7 @@ void LLDrawPoolBump::renderShiny(bool invisible)
|
|||
LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
else if (!invisible)
|
||||
else
|
||||
{
|
||||
if (mRigged)
|
||||
{
|
||||
|
|
@ -446,12 +369,12 @@ void LLDrawPoolBump::renderShiny(bool invisible)
|
|||
}
|
||||
|
||||
//static
|
||||
void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible)
|
||||
void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel)
|
||||
{
|
||||
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
|
||||
if( cube_map )
|
||||
{
|
||||
if (!invisible && shader_level > 1)
|
||||
if (shader_level > 1)
|
||||
{
|
||||
shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
|
||||
|
|
@ -469,11 +392,11 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
|
|||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::endShiny(bool invisible)
|
||||
void LLDrawPoolBump::endShiny()
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
|
||||
|
||||
unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
|
||||
unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel);
|
||||
if (shader)
|
||||
{
|
||||
shader->unbind();
|
||||
|
|
@ -758,7 +681,7 @@ S32 LLDrawPoolBump::getNumDeferredPasses()
|
|||
if (RenderObjectBump)
|
||||
// </FS:PP>
|
||||
{
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -766,135 +689,94 @@ S32 LLDrawPoolBump::getNumDeferredPasses()
|
|||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::beginDeferredPass(S32 pass)
|
||||
{
|
||||
if (!gPipeline.hasRenderBatches( pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
mShiny = TRUE;
|
||||
gDeferredBumpProgram.bind(pass == 1);
|
||||
diffuse_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
bump_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::endDeferredPass(S32 pass)
|
||||
{
|
||||
if (!gPipeline.hasRenderBatches(pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
mShiny = FALSE;
|
||||
LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
gGL.getTexUnit(0)->activate();
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::renderDeferred(S32 pass)
|
||||
{
|
||||
if (!gPipeline.hasRenderBatches(pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
|
||||
|
||||
bool rigged = pass == 1;
|
||||
U32 type = rigged ? LLRenderPass::PASS_BUMP_RIGGED : LLRenderPass::PASS_BUMP;
|
||||
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
|
||||
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
|
||||
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
LLVOAvatar* avatar = nullptr;
|
||||
U64 skin = 0;
|
||||
|
||||
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
|
||||
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
|
||||
mShiny = TRUE;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
LLDrawInfo& params = **i;
|
||||
bool rigged = i == 1;
|
||||
gDeferredBumpProgram.bind(rigged);
|
||||
diffuse_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
bump_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
// <FS:Beq> Capture render times
|
||||
if(params.mFace)
|
||||
U32 type = rigged ? LLRenderPass::PASS_BUMP_RIGGED : LLRenderPass::PASS_BUMP;
|
||||
LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
|
||||
LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
|
||||
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
LLVOAvatar* avatar = nullptr;
|
||||
U64 skin = 0;
|
||||
|
||||
std::unique_ptr<FSPerfStats::RecordAttachmentTime> ratPtr{}; // <FS:Beq/> render time capture
|
||||
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
|
||||
{
|
||||
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
|
||||
LLDrawInfo& params = **i;
|
||||
|
||||
if(vobj && vobj->isAttachment())
|
||||
// <FS:Beq> Capture render times
|
||||
if(params.mFace)
|
||||
{
|
||||
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
|
||||
LLViewerObject* vobj = (LLViewerObject *)params.mFace->getViewerObject();
|
||||
|
||||
if(vobj && vobj->isAttachment())
|
||||
{
|
||||
trackAttachments( vobj, params.mFace->isState(LLFace::RIGGED), &ratPtr );
|
||||
}
|
||||
}
|
||||
// </FS:Beq>
|
||||
|
||||
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff);
|
||||
LLDrawPoolBump::bindBumpMap(params, bump_channel);
|
||||
|
||||
if (rigged)
|
||||
{
|
||||
if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash)
|
||||
{
|
||||
uploadMatrixPalette(params);
|
||||
avatar = params.mAvatar;
|
||||
skin = params.mSkinInfo->mHash;
|
||||
}
|
||||
pushBatch(params, mask | LLVertexBuffer::MAP_WEIGHT4, TRUE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushBatch(params, mask, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
// </FS:Beq>
|
||||
|
||||
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff);
|
||||
LLDrawPoolBump::bindBumpMap(params, bump_channel);
|
||||
|
||||
if (rigged)
|
||||
{
|
||||
if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash)
|
||||
{
|
||||
uploadMatrixPalette(params);
|
||||
avatar = params.mAvatar;
|
||||
skin = params.mSkinInfo->mHash;
|
||||
}
|
||||
pushBatch(params, mask | LLVertexBuffer::MAP_WEIGHT4, TRUE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushBatch(params, mask, TRUE, FALSE);
|
||||
}
|
||||
LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
gGL.getTexUnit(0)->activate();
|
||||
}
|
||||
|
||||
mShiny = FALSE;
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::beginPostDeferredPass(S32 pass)
|
||||
{
|
||||
mRigged = ((pass % 2) == 1);
|
||||
pass /= 2;
|
||||
switch (pass)
|
||||
{
|
||||
case 0:
|
||||
beginFullbrightShiny();
|
||||
break;
|
||||
case 1:
|
||||
beginBump();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::endPostDeferredPass(S32 pass)
|
||||
{
|
||||
switch (pass)
|
||||
{
|
||||
case 0:
|
||||
endFullbrightShiny();
|
||||
break;
|
||||
case 1:
|
||||
endBump(LLRenderPass::PASS_POST_BUMP);
|
||||
break;
|
||||
}
|
||||
|
||||
//to disable texture channels
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::renderPostDeferred(S32 pass)
|
||||
{
|
||||
pass /= 2;
|
||||
switch (pass)
|
||||
{
|
||||
case 0:
|
||||
renderFullbrightShiny();
|
||||
break;
|
||||
case 1:
|
||||
renderBump(LLRenderPass::PASS_POST_BUMP);
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{ // two passes -- static and rigged
|
||||
mRigged = (i == 1);
|
||||
|
||||
// render shiny
|
||||
beginFullbrightShiny();
|
||||
renderFullbrightShiny();
|
||||
endFullbrightShiny();
|
||||
|
||||
//render bump
|
||||
beginBump();
|
||||
renderBump(LLRenderPass::PASS_POST_BUMP);
|
||||
endBump();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// List of bump-maps created from other textures.
|
||||
|
||||
|
|
@ -1576,44 +1458,4 @@ void LLDrawPoolInvisible::render(S32 pass)
|
|||
{
|
||||
gOcclusionProgram.unbind();
|
||||
}
|
||||
|
||||
if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
|
||||
{
|
||||
beginShiny(true);
|
||||
renderShiny(true);
|
||||
endShiny(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolInvisible::beginDeferredPass(S32 pass)
|
||||
{
|
||||
beginRenderPass(pass);
|
||||
}
|
||||
|
||||
void LLDrawPoolInvisible::endDeferredPass( S32 pass )
|
||||
{
|
||||
endRenderPass(pass);
|
||||
}
|
||||
|
||||
void LLDrawPoolInvisible::renderDeferred( S32 pass )
|
||||
{ //render invisiprims; this doesn't work becaue it also blocks all the post-deferred stuff
|
||||
#if 0
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE);
|
||||
|
||||
U32 invisi_mask = LLVertexBuffer::MAP_VERTEX;
|
||||
glStencilMask(0);
|
||||
glStencilOp(GL_ZERO, GL_KEEP, GL_REPLACE);
|
||||
gGL.setColorMask(false, false);
|
||||
pushBatches(LLRenderPass::PASS_INVISIBLE, invisi_mask, FALSE);
|
||||
gGL.setColorMask(true, true);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
glStencilMask(0xFFFFFFFF);
|
||||
|
||||
if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))
|
||||
{
|
||||
beginShiny(true);
|
||||
renderShiny(true);
|
||||
endShiny(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ public:
|
|||
LLDrawPoolBump();
|
||||
|
||||
virtual void render(S32 pass = 0) override;
|
||||
virtual void beginRenderPass( S32 pass ) override;
|
||||
virtual void endRenderPass( S32 pass ) override;
|
||||
virtual S32 getNumPasses() override;
|
||||
/*virtual*/ void prerender() override;
|
||||
void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE) override;
|
||||
|
|
@ -64,9 +62,9 @@ public:
|
|||
|
||||
S32 numBumpPasses();
|
||||
|
||||
void beginShiny(bool invisible = false);
|
||||
void renderShiny(bool invisible = false);
|
||||
void endShiny(bool invisible = false);
|
||||
void beginShiny();
|
||||
void renderShiny();
|
||||
void endShiny();
|
||||
|
||||
void beginFullbrightShiny();
|
||||
void renderFullbrightShiny();
|
||||
|
|
@ -76,17 +74,13 @@ public:
|
|||
void renderBump(U32 pass = LLRenderPass::PASS_BUMP);
|
||||
void endBump(U32 pass = LLRenderPass::PASS_BUMP);
|
||||
|
||||
static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible);
|
||||
static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible);
|
||||
static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel);
|
||||
static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel);
|
||||
|
||||
virtual S32 getNumDeferredPasses() override;
|
||||
/*virtual*/ void beginDeferredPass(S32 pass) override;
|
||||
/*virtual*/ void endDeferredPass(S32 pass) override;
|
||||
/*virtual*/ void renderDeferred(S32 pass) override;
|
||||
|
||||
virtual S32 getNumPostDeferredPasses() override { return 4; }
|
||||
/*virtual*/ void beginPostDeferredPass(S32 pass) override;
|
||||
/*virtual*/ void endPostDeferredPass(S32 pass) override;
|
||||
virtual S32 getNumPostDeferredPasses() override { return 1; }
|
||||
/*virtual*/ void renderPostDeferred(S32 pass) override;
|
||||
|
||||
static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2);
|
||||
|
|
@ -171,10 +165,10 @@ private:
|
|||
|
||||
extern LLBumpImageList gBumpImageList;
|
||||
|
||||
class LLDrawPoolInvisible : public LLDrawPoolBump
|
||||
class LLDrawPoolInvisible : public LLRenderPass
|
||||
{
|
||||
public:
|
||||
LLDrawPoolInvisible() : LLDrawPoolBump(LLDrawPool::POOL_INVISIBLE) { }
|
||||
LLDrawPoolInvisible() : LLRenderPass(LLDrawPool::POOL_INVISIBLE) { }
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -189,11 +183,6 @@ public:
|
|||
virtual void beginRenderPass( S32 pass ) { }
|
||||
virtual void endRenderPass( S32 pass ) { }
|
||||
virtual S32 getNumPasses() {return 1;}
|
||||
|
||||
virtual S32 getNumDeferredPasses() { return 1; }
|
||||
/*virtual*/ void beginDeferredPass(S32 pass);
|
||||
/*virtual*/ void endDeferredPass(S32 pass);
|
||||
/*virtual*/ void renderDeferred(S32 pass);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,37 +38,54 @@
|
|||
#include "llrender.h"
|
||||
|
||||
static LLGLSLShader* simple_shader = NULL;
|
||||
static LLGLSLShader* fullbright_shader = NULL;
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_SIMPLE_DEFERRED("Deferred Simple");
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS_DEFERRED("Deferred Grass");
|
||||
|
||||
void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
|
||||
|
||||
static void setup_simple_shader(LLGLSLShader* shader)
|
||||
{
|
||||
if (pass == 0)
|
||||
shader->bind();
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
gDeferredEmissiveProgram.bind();
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(gDeferredEmissiveProgram.mRiggedVariant);
|
||||
gDeferredEmissiveProgram.mRiggedVariant->bind();
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_glow_shader(LLGLSLShader* shader)
|
||||
{
|
||||
setup_simple_shader(shader);
|
||||
if (LLPipeline::sRenderDeferred && !LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_fullbright_shader(LLGLSLShader* shader)
|
||||
{
|
||||
setup_glow_shader(shader);
|
||||
shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
|
||||
}
|
||||
|
||||
|
||||
void LLDrawPoolGlow::renderPostDeferred(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW);
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW);
|
||||
render(&gDeferredEmissiveProgram);
|
||||
}
|
||||
|
||||
void LLDrawPoolGlow::render(LLGLSLShader* shader)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW);
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
LLGLDisable test(GL_ALPHA_TEST);
|
||||
gGL.flush();
|
||||
|
|
@ -80,98 +97,29 @@ void LLDrawPoolGlow::renderPostDeferred(S32 pass)
|
|||
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
||||
gGL.setColorMask(false, true);
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
|
||||
void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
//first pass -- static objects
|
||||
setup_glow_shader(shader);
|
||||
pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
// second pass -- rigged objects
|
||||
shader = shader->mRiggedVariant;
|
||||
setup_glow_shader(shader);
|
||||
pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
|
||||
S32 LLDrawPoolGlow::getNumPasses()
|
||||
{
|
||||
if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LLDrawPoolGlow::render(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_GLOW);
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
LLGLDisable test(GL_ALPHA_TEST);
|
||||
gGL.flush();
|
||||
/// Get rid of z-fighting with non-glow pass.
|
||||
LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -1.0f);
|
||||
gGL.setSceneBlendType(LLRender::BT_ADD);
|
||||
|
||||
U32 shader_level = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
|
||||
//should never get here without basic shaders enabled
|
||||
llassert(shader_level > 0);
|
||||
|
||||
LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
if (pass == 1)
|
||||
{
|
||||
llassert(shader->mRiggedVariant);
|
||||
shader = shader->mRiggedVariant;
|
||||
}
|
||||
shader->bind();
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
|
||||
}
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
||||
gGL.setColorMask(false, true);
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
|
||||
if (shader_level > 0 && fullbright_shader)
|
||||
{
|
||||
shader->unbind();
|
||||
}
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
|
||||
render(shader);
|
||||
}
|
||||
|
||||
LLDrawPoolSimple::LLDrawPoolSimple() :
|
||||
|
|
@ -186,65 +134,38 @@ void LLDrawPoolSimple::prerender()
|
|||
|
||||
S32 LLDrawPoolSimple::getNumPasses()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
void LLDrawPoolSimple::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
|
||||
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
simple_shader = &gObjectSimpleImpostorProgram;
|
||||
}
|
||||
else if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
simple_shader = &gObjectSimpleWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
simple_shader = &gObjectSimpleProgram;
|
||||
}
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
llassert(simple_shader->mRiggedVariant);
|
||||
simple_shader = simple_shader->mRiggedVariant;
|
||||
}
|
||||
|
||||
simple_shader->bind();
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolSimple::endRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
|
||||
stop_glerror();
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
stop_glerror();
|
||||
simple_shader->unbind();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LLDrawPoolSimple::render(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
|
||||
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
shader = &gObjectSimpleImpostorProgram;
|
||||
}
|
||||
else if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
shader = &gObjectSimpleWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gObjectSimpleProgram;
|
||||
}
|
||||
|
||||
{ //render simple
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
|
||||
|
||||
gPipeline.enableLightsDynamic();
|
||||
|
||||
U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
|
||||
if (pass == 0)
|
||||
// first pass -- static objects
|
||||
{
|
||||
setup_simple_shader(shader);
|
||||
pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE);
|
||||
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
|
|
@ -257,8 +178,11 @@ void LLDrawPoolSimple::render(S32 pass)
|
|||
pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
//second pass, rigged
|
||||
{
|
||||
shader = shader->mRiggedVariant;
|
||||
setup_simple_shader(shader);
|
||||
pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, mask, TRUE, TRUE);
|
||||
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
|
|
@ -275,9 +199,6 @@ void LLDrawPoolSimple::render(S32 pass)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK("Alpha Mask");
|
||||
|
||||
LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() :
|
||||
|
|
@ -290,84 +211,36 @@ void LLDrawPoolAlphaMask::prerender()
|
|||
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
}
|
||||
|
||||
void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
|
||||
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
simple_shader = &gObjectSimpleWaterAlphaMaskProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
simple_shader = &gObjectSimpleAlphaMaskProgram;
|
||||
}
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
llassert(simple_shader->mRiggedVariant);
|
||||
simple_shader = simple_shader->mRiggedVariant;
|
||||
}
|
||||
|
||||
simple_shader->bind();
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlphaMask::endRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
|
||||
stop_glerror();
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
stop_glerror();
|
||||
if (mShaderLevel > 0)
|
||||
{
|
||||
simple_shader->unbind();
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolAlphaMask::render(S32 pass)
|
||||
{
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
||||
|
||||
|
||||
simple_shader->bind();
|
||||
simple_shader->setMinimumAlpha(0.33f);
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
|
||||
if (pass == 0)
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
shader = &gObjectSimpleWaterAlphaMaskProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gObjectSimpleAlphaMaskProgram;
|
||||
}
|
||||
|
||||
// render static
|
||||
setup_simple_shader(shader);
|
||||
pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_NORMMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
// render rigged
|
||||
setup_simple_shader(shader->mRiggedVariant);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() :
|
||||
|
|
@ -380,61 +253,27 @@ void LLDrawPoolFullbrightAlphaMask::prerender()
|
|||
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
|
||||
|
||||
bool rigged = (pass == 1);
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
gObjectFullbrightWaterAlphaMaskProgram.bind(rigged);
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectFullbrightAlphaMaskProgram.bind(rigged);
|
||||
}
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
|
||||
stop_glerror();
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
stop_glerror();
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
|
||||
|
||||
if (pass == 0)
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
shader = &gObjectFullbrightWaterAlphaMaskProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
shader = &gObjectFullbrightAlphaMaskProgram;
|
||||
}
|
||||
|
||||
|
||||
// render static
|
||||
setup_fullbright_shader(shader);
|
||||
pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
// render rigged
|
||||
setup_fullbright_shader(shader->mRiggedVariant);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
//===============================
|
||||
|
|
@ -443,112 +282,41 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
|
|||
|
||||
S32 LLDrawPoolSimple::getNumDeferredPasses()
|
||||
{
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
void LLDrawPoolSimple::beginDeferredPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
|
||||
|
||||
mShader = &gDeferredDiffuseProgram;
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
llassert(mShader->mRiggedVariant != nullptr);
|
||||
mShader = mShader->mRiggedVariant;
|
||||
}
|
||||
|
||||
|
||||
mShader->bind();
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
mShader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolSimple::endDeferredPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
|
||||
mShader->unbind();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LLDrawPoolSimple::renderDeferred(S32 pass)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
LLGLDisable alpha_test(GL_ALPHA_TEST);
|
||||
|
||||
if (pass == 0)
|
||||
{ //render simple
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
|
||||
pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//render simple rigged
|
||||
pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
//render static
|
||||
setup_simple_shader(&gDeferredDiffuseProgram);
|
||||
pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
//render rigged
|
||||
setup_simple_shader(gDeferredDiffuseProgram.mRiggedVariant);
|
||||
pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask");
|
||||
|
||||
void LLDrawPoolAlphaMask::beginDeferredPass(S32 pass)
|
||||
{
|
||||
if (pass == 0)
|
||||
{
|
||||
gDeferredDiffuseAlphaMaskProgram.bind();
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(gDeferredDiffuseAlphaMaskProgram.mRiggedVariant);
|
||||
gDeferredDiffuseAlphaMaskProgram.mRiggedVariant->bind();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLDrawPoolAlphaMask::endDeferredPass(S32 pass)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
}
|
||||
|
||||
void LLDrawPoolAlphaMask::renderDeferred(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_DEFERRED);
|
||||
LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.33f);
|
||||
LLGLSLShader* shader = &gDeferredDiffuseAlphaMaskProgram;
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
//render static
|
||||
setup_simple_shader(shader);
|
||||
pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
//render rigged
|
||||
setup_simple_shader(shader->mRiggedVariant);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
|
||||
}
|
||||
|
||||
|
||||
// grass drawpool
|
||||
LLDrawPoolGrass::LLDrawPoolGrass() :
|
||||
LLRenderPass(POOL_GRASS)
|
||||
|
|
@ -667,83 +435,31 @@ void LLDrawPoolFullbright::prerender()
|
|||
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
|
||||
{
|
||||
bool rigged = (pass == 1);
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
gDeferredFullbrightWaterProgram.bind(rigged);
|
||||
}
|
||||
else
|
||||
{
|
||||
gDeferredFullbrightProgram.bind(rigged);
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT);
|
||||
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
if (pass == 0)
|
||||
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
|
||||
shader = &gDeferredFullbrightWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
shader = &gDeferredFullbrightProgram;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::endPostDeferredPass(S32 pass)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::beginRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT);
|
||||
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
fullbright_shader = &gObjectFullbrightWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullbright_shader = &gObjectFullbrightProgram;
|
||||
}
|
||||
|
||||
if (pass == 1)
|
||||
{
|
||||
llassert(fullbright_shader->mRiggedVariant);
|
||||
fullbright_shader = fullbright_shader->mRiggedVariant;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::endRenderPass(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT);
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
|
||||
stop_glerror();
|
||||
|
||||
if (mShaderLevel > 0)
|
||||
{
|
||||
fullbright_shader->unbind();
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
|
||||
// render static
|
||||
setup_fullbright_shader(shader);
|
||||
pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
|
||||
|
||||
// render rigged
|
||||
setup_fullbright_shader(shader->mRiggedVariant);
|
||||
pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbright::render(S32 pass)
|
||||
|
|
@ -752,102 +468,75 @@ void LLDrawPoolFullbright::render(S32 pass)
|
|||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
|
||||
stop_glerror();
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
shader = &gObjectFullbrightWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gObjectFullbrightProgram;
|
||||
}
|
||||
|
||||
if (mShaderLevel > 0)
|
||||
{
|
||||
fullbright_shader->bind();
|
||||
fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
|
||||
fullbright_shader->uniform1f(LLViewerShaderMgr::TEXTURE_GAMMA, 1.f);
|
||||
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
|
||||
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
|
||||
if (pass == 0)
|
||||
{
|
||||
pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask, TRUE, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
// render static
|
||||
setup_fullbright_shader(shader);
|
||||
pushBatches(LLRenderPass::PASS_FULLBRIGHT, mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, mask, TRUE, TRUE);
|
||||
pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, mask, TRUE, TRUE);
|
||||
|
||||
// render rigged
|
||||
setup_fullbright_shader(shader->mRiggedVariant);
|
||||
pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, mask, TRUE, TRUE);
|
||||
pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, mask, TRUE, TRUE);
|
||||
}
|
||||
|
||||
S32 LLDrawPoolFullbright::getNumPasses()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass)
|
||||
{
|
||||
bool rigged = (pass == 1);
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
gObjectFullbrightAlphaMaskProgram.bind(rigged);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
gDeferredFullbrightAlphaMaskWaterProgram.bind(rigged);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gDeferredFullbrightAlphaMaskProgram.bind(rigged);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectFullbrightAlphaMaskProgram.bind(rigged);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
|
||||
LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT);
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
if (pass == 0)
|
||||
|
||||
LLGLSLShader* shader = nullptr;
|
||||
if (LLPipeline::sRenderingHUDs)
|
||||
{
|
||||
pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE);
|
||||
shader = &gObjectFullbrightAlphaMaskProgram;
|
||||
}
|
||||
else if (LLPipeline::sRenderDeferred)
|
||||
{
|
||||
if (LLPipeline::sUnderWaterRender)
|
||||
{
|
||||
shader = &gDeferredFullbrightAlphaMaskWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gDeferredFullbrightAlphaMaskProgram;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
shader = &gObjectFullbrightAlphaMaskProgram;
|
||||
}
|
||||
|
||||
LLGLDisable blend(GL_BLEND);
|
||||
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
|
||||
|
||||
// render static
|
||||
setup_fullbright_shader(shader);
|
||||
pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE);
|
||||
|
||||
// render rigged
|
||||
setup_fullbright_shader(shader->mRiggedVariant);
|
||||
pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, fullbright_mask, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void LLDrawPoolFullbrightAlphaMask::endPostDeferredPass(S32 pass)
|
||||
{
|
||||
LLGLSLShader::sCurBoundShaderPtr->unbind();
|
||||
LLRenderPass::endRenderPass(pass);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,18 +46,12 @@ public:
|
|||
LLDrawPoolSimple();
|
||||
|
||||
S32 getNumDeferredPasses() override;
|
||||
void beginDeferredPass(S32 pass) override;
|
||||
void endDeferredPass(S32 pass) override;
|
||||
void renderDeferred(S32 pass) override;
|
||||
|
||||
void beginRenderPass(S32 pass) override;
|
||||
void endRenderPass(S32 pass) override;
|
||||
/// We need two passes so we can handle emissive materials separately.
|
||||
S32 getNumPasses() override;
|
||||
void render(S32 pass = 0) override;
|
||||
void prerender() override;
|
||||
|
||||
LLGLSLShader* mShader = nullptr;
|
||||
};
|
||||
|
||||
class LLDrawPoolGrass : public LLRenderPass
|
||||
|
|
@ -101,14 +95,10 @@ public:
|
|||
|
||||
LLDrawPoolAlphaMask();
|
||||
|
||||
/*virtual*/ S32 getNumDeferredPasses() { return 2; }
|
||||
/*virtual*/ void beginDeferredPass(S32 pass);
|
||||
/*virtual*/ void endDeferredPass(S32 pass);
|
||||
/*virtual*/ S32 getNumDeferredPasses() { return 1; }
|
||||
/*virtual*/ void renderDeferred(S32 pass);
|
||||
|
||||
/*virtual*/ S32 getNumPasses() { return 2; }
|
||||
/*virtual*/ void beginRenderPass(S32 pass);
|
||||
/*virtual*/ void endRenderPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPasses() { return 1; }
|
||||
/*virtual*/ void render(S32 pass = 0);
|
||||
/*virtual*/ void prerender();
|
||||
|
||||
|
|
@ -127,14 +117,10 @@ public:
|
|||
|
||||
LLDrawPoolFullbrightAlphaMask();
|
||||
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
|
||||
/*virtual*/ void beginPostDeferredPass(S32 pass);
|
||||
/*virtual*/ void endPostDeferredPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
|
||||
/*virtual*/ void renderPostDeferred(S32 pass);
|
||||
|
||||
/*virtual*/ S32 getNumPasses() { return 2; }
|
||||
/*virtual*/ void beginRenderPass(S32 pass);
|
||||
/*virtual*/ void endRenderPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPasses() { return 1; }
|
||||
/*virtual*/ void render(S32 pass = 0);
|
||||
/*virtual*/ void prerender();
|
||||
};
|
||||
|
|
@ -153,13 +139,9 @@ public:
|
|||
|
||||
LLDrawPoolFullbright();
|
||||
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
|
||||
/*virtual*/ void beginPostDeferredPass(S32 pass);
|
||||
/*virtual*/ void endPostDeferredPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
|
||||
/*virtual*/ void renderPostDeferred(S32 pass);
|
||||
|
||||
/*virtual*/ void beginRenderPass(S32 pass);
|
||||
/*virtual*/ void endRenderPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPasses();
|
||||
/*virtual*/ void render(S32 pass = 0);
|
||||
/*virtual*/ void prerender();
|
||||
|
|
@ -182,11 +164,11 @@ public:
|
|||
|
||||
virtual void prerender() { }
|
||||
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
|
||||
/*virtual*/ void beginPostDeferredPass(S32 pass);
|
||||
/*virtual*/ void endPostDeferredPass(S32 pass);
|
||||
/*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
|
||||
/*virtual*/ void renderPostDeferred(S32 pass);
|
||||
|
||||
void render(LLGLSLShader* shader);
|
||||
|
||||
/*virtual*/ S32 getNumPasses();
|
||||
|
||||
void render(S32 pass = 0);
|
||||
|
|
|
|||
|
|
@ -94,12 +94,13 @@ void LLDrawPoolTree::render(S32 pass)
|
|||
|
||||
// [SL:KB] - Patch: Render-TextureToggle (Catznip-4.0)
|
||||
if( (LLPipeline::sRenderTextures) )
|
||||
gGL.getTexUnit(sDiffTex)->bind( mTexturep );
|
||||
gGL.getTexUnit(sDiffTex)->bindFast( mTexturep );
|
||||
else
|
||||
gGL.getTexUnit(sDiffTex)->bind( LLViewerFetchedTexture::sDefaultDiffuseImagep );
|
||||
gGL.getTexUnit(sDiffTex)->bindFast( LLViewerFetchedTexture::sDefaultDiffuseImagep );
|
||||
// [/SL:KB]
|
||||
// gGL.getTexUnit(sDiffTex)->bind(mTexturep);
|
||||
|
||||
// gGL.getTexUnit(sDiffTex)->bindFast(mTexturep);
|
||||
gPipeline.touchTexture(mTexturep, 1024.f * 1024.f); // <=== keep Linden tree textures at full res
|
||||
|
||||
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
|
||||
iter != mDrawFace.end(); iter++)
|
||||
{
|
||||
|
|
@ -122,9 +123,8 @@ void LLDrawPoolTree::render(S32 pass)
|
|||
gPipeline.mMatrixOpCount++;
|
||||
}
|
||||
|
||||
buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
|
||||
buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
|
||||
gPipeline.addTrianglesDrawn(buff->getNumIndices());
|
||||
buff->setBufferFast(LLDrawPoolTree::VERTEX_DATA_MASK);
|
||||
buff->drawRangeFast(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ class LLTextureEntry;
|
|||
class LLVertexProgram;
|
||||
class LLViewerTexture;
|
||||
class LLGeometryManager;
|
||||
class LLTextureAtlasSlot;
|
||||
class LLDrawInfo;
|
||||
class LLMeshSkinInfo;
|
||||
|
||||
|
|
|
|||
|
|
@ -1265,6 +1265,14 @@ F32 gpu_benchmark()
|
|||
// ensure matched pair of bind() and unbind() calls
|
||||
ShaderBinder binder(gBenchmarkProgram);
|
||||
|
||||
U32 glarray = 0;
|
||||
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
glGenVertexArrays(1, &glarray);
|
||||
glBindVertexArray(glarray);
|
||||
}
|
||||
|
||||
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||
glFinish();
|
||||
|
||||
|
|
@ -1297,6 +1305,13 @@ F32 gpu_benchmark()
|
|||
}
|
||||
}
|
||||
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
glDeleteVertexArrays(1, &glarray);
|
||||
}
|
||||
|
||||
|
||||
std::sort(results.begin(), results.end());
|
||||
|
||||
F32 gbps = results[results.size()/2];
|
||||
|
|
|
|||
|
|
@ -1861,12 +1861,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
end = which_lod;
|
||||
}
|
||||
|
||||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
if (shader)
|
||||
{
|
||||
shader->unbind();
|
||||
}
|
||||
|
||||
for (S32 lod = start; lod >= end; --lod)
|
||||
{
|
||||
if (which_lod == -1)
|
||||
|
|
@ -2025,12 +2019,6 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d
|
|||
}
|
||||
|
||||
mResourceCost = calcResourceCost();
|
||||
|
||||
LLVertexBuffer::unbind();
|
||||
if (shader)
|
||||
{
|
||||
shader->bind();
|
||||
}
|
||||
refresh(); // <FS:ND/> refresh once to make sure render gets called with the updated vbos
|
||||
}
|
||||
|
||||
|
|
@ -2963,6 +2951,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
|
|||
*(index_strider++) = vf.mIndices[i];
|
||||
}
|
||||
|
||||
vb->flush();
|
||||
|
||||
mVertexBuffer[lod][mdl].push_back(vb);
|
||||
|
||||
vertex_count += num_vertices;
|
||||
|
|
@ -3523,6 +3513,11 @@ BOOL LLModelPreview::render()
|
|||
genBuffers(mPreviewLOD, skin_weight);
|
||||
}
|
||||
|
||||
if (physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty())
|
||||
{
|
||||
genBuffers(LLModel::LOD_PHYSICS, false);
|
||||
}
|
||||
|
||||
if (!skin_weight)
|
||||
{
|
||||
for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter)
|
||||
|
|
@ -3598,6 +3593,7 @@ BOOL LLModelPreview::render()
|
|||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
gGL.setLineWidth(1.f); // <FS> Line width OGL core profile fix by Rye Mutt
|
||||
}
|
||||
buffer->flush();
|
||||
}
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
|
@ -3691,11 +3687,6 @@ BOOL LLModelPreview::render()
|
|||
|
||||
if (render_mesh)
|
||||
{
|
||||
if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
|
||||
{
|
||||
genBuffers(LLModel::LOD_PHYSICS, false);
|
||||
}
|
||||
|
||||
U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
|
||||
if (pass > 0){
|
||||
for (U32 i = 0; i < num_models; ++i)
|
||||
|
|
@ -3718,6 +3709,8 @@ BOOL LLModelPreview::render()
|
|||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
gGL.setLineWidth(1.f); // <FS> Line width OGL core profile fix by Rye Mutt
|
||||
|
||||
buffer->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3768,11 +3761,6 @@ BOOL LLModelPreview::render()
|
|||
|
||||
if (physics.mHull.empty())
|
||||
{
|
||||
if (mVertexBuffer[LLModel::LOD_PHYSICS].empty())
|
||||
{
|
||||
genBuffers(LLModel::LOD_PHYSICS, false);
|
||||
}
|
||||
|
||||
U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size();
|
||||
for (U32 v = 0; v < num_models; ++v)
|
||||
{
|
||||
|
|
@ -3807,6 +3795,8 @@ BOOL LLModelPreview::render()
|
|||
buffer->draw(LLRender::POINTS, 3, i);
|
||||
}
|
||||
}
|
||||
|
||||
buffer->flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "llphysicsshapebuilderutil.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llvolumemgr.h"
|
||||
#include "lltextureatlas.h"
|
||||
#include "llviewershadermgr.h"
|
||||
#include "llcontrolavatar.h"
|
||||
|
||||
|
|
@ -134,129 +133,6 @@ LLSpatialGroup::~LLSpatialGroup()
|
|||
sNodeCount--;
|
||||
|
||||
clearDrawMap();
|
||||
clearAtlasList() ;
|
||||
}
|
||||
|
||||
BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
|
||||
{
|
||||
S8 type = atlasp->getComponents() - 1 ;
|
||||
for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
|
||||
{
|
||||
if(atlasp == *iter)
|
||||
{
|
||||
return TRUE ;
|
||||
}
|
||||
}
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
|
||||
{
|
||||
if(!hasAtlas(atlasp))
|
||||
{
|
||||
mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
|
||||
atlasp->addSpatialGroup(this) ;
|
||||
}
|
||||
|
||||
--recursive_level;
|
||||
if(recursive_level)//levels propagating up.
|
||||
{
|
||||
LLSpatialGroup* parent = getParent() ;
|
||||
if(parent)
|
||||
{
|
||||
parent->addAtlas(atlasp, recursive_level) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
|
||||
{
|
||||
mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
|
||||
if(remove_group)
|
||||
{
|
||||
atlasp->removeSpatialGroup(this) ;
|
||||
}
|
||||
|
||||
--recursive_level;
|
||||
if(recursive_level)//levels propagating up.
|
||||
{
|
||||
LLSpatialGroup* parent = getParent() ;
|
||||
if(parent)
|
||||
{
|
||||
parent->removeAtlas(atlasp, recursive_level) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLSpatialGroup::clearAtlasList()
|
||||
{
|
||||
std::list<LLTextureAtlas*>::iterator iter ;
|
||||
for(S8 i = 0 ; i < 4 ; i++)
|
||||
{
|
||||
if(mAtlasList[i].size() > 0)
|
||||
{
|
||||
for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
|
||||
{
|
||||
((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
|
||||
}
|
||||
mAtlasList[i].clear() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
|
||||
{
|
||||
S8 type = ncomponents - 1 ;
|
||||
if(mAtlasList[type].size() > 0)
|
||||
{
|
||||
for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
|
||||
{
|
||||
if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
|
||||
{
|
||||
return *iter ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
--recursive_level;
|
||||
if(recursive_level)
|
||||
{
|
||||
LLSpatialGroup* parent = getParent() ;
|
||||
if(parent)
|
||||
{
|
||||
return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
|
||||
}
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
|
||||
{
|
||||
mCurUpdatingSlotp = slotp;
|
||||
|
||||
//if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
|
||||
//{
|
||||
// addAtlas(mCurUpdatingSlotp->getAtlas()) ;
|
||||
//}
|
||||
}
|
||||
|
||||
LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
|
||||
{
|
||||
if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
|
||||
{
|
||||
return mCurUpdatingSlotp ;
|
||||
}
|
||||
|
||||
//--recursive_level ;
|
||||
//if(recursive_level)
|
||||
//{
|
||||
// LLSpatialGroup* parent = getParent() ;
|
||||
// if(parent)
|
||||
// {
|
||||
// return parent->getCurUpdatingSlot(imagep, recursive_level) ;
|
||||
// }
|
||||
//}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
void LLSpatialGroup::clearDrawMap()
|
||||
|
|
@ -671,11 +547,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
|
|||
mDistance(0.f),
|
||||
mDepth(0.f),
|
||||
mLastUpdateDistance(-1.f),
|
||||
mLastUpdateTime(gFrameTimeSeconds),
|
||||
mAtlasList(4),
|
||||
mCurUpdatingTime(0),
|
||||
mCurUpdatingSlotp(NULL),
|
||||
mCurUpdatingTexture (NULL)
|
||||
mLastUpdateTime(gFrameTimeSeconds)
|
||||
{
|
||||
ll_assert_aligned(this,16);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ class LLViewerOctreePartition;
|
|||
class LLSpatialPartition;
|
||||
class LLSpatialBridge;
|
||||
class LLSpatialGroup;
|
||||
class LLTextureAtlas;
|
||||
class LLTextureAtlasSlot;
|
||||
class LLViewerRegion;
|
||||
|
||||
void pushVerts(LLFace* face, U32 mask);
|
||||
|
|
@ -102,6 +100,10 @@ public:
|
|||
LLPointer<LLViewerTexture> mTexture;
|
||||
std::vector<LLPointer<LLViewerTexture> > mTextureList;
|
||||
|
||||
// virtual size of mTexture and mTextureList textures
|
||||
// used to update the decode priority of textures in this DrawInfo
|
||||
std::vector<F32> mTextureListVSize;
|
||||
|
||||
S32 mDebugColor;
|
||||
const LLMatrix4* mTextureMatrix;
|
||||
const LLMatrix4* mModelMatrix;
|
||||
|
|
@ -315,49 +317,15 @@ public:
|
|||
virtual void handleDestruction(const TreeNode* node);
|
||||
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
|
||||
|
||||
//-------------------
|
||||
//for atlas use
|
||||
//-------------------
|
||||
//atlas
|
||||
void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;}
|
||||
U32 getCurUpdatingTime() const { return mCurUpdatingTime ;}
|
||||
|
||||
void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ;
|
||||
LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level = 3) ;
|
||||
|
||||
void setCurUpdatingTexture(LLViewerTexture* tex){ mCurUpdatingTexture = tex ;}
|
||||
LLViewerTexture* getCurUpdatingTexture() const { return mCurUpdatingTexture ;}
|
||||
|
||||
BOOL hasAtlas(LLTextureAtlas* atlasp) ;
|
||||
LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ;
|
||||
void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ;
|
||||
void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ;
|
||||
void clearAtlasList() ;
|
||||
|
||||
public:
|
||||
|
||||
LL_ALIGN_16(LLVector4a mViewAngle);
|
||||
LL_ALIGN_16(LLVector4a mLastUpdateViewAngle);
|
||||
|
||||
F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
|
||||
|
||||
private:
|
||||
U32 mCurUpdatingTime ;
|
||||
//do not make the below two to use LLPointer
|
||||
//because mCurUpdatingTime invalidates them automatically.
|
||||
LLTextureAtlasSlot* mCurUpdatingSlotp ;
|
||||
LLViewerTexture* mCurUpdatingTexture ;
|
||||
|
||||
std::vector< std::list<LLTextureAtlas*> > mAtlasList ;
|
||||
//-------------------
|
||||
//end for atlas use
|
||||
//-------------------
|
||||
|
||||
protected:
|
||||
virtual ~LLSpatialGroup();
|
||||
|
||||
static S32 sLODSeed;
|
||||
|
||||
public:
|
||||
bridge_list_t mBridgeList;
|
||||
buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
|
||||
|
|
|
|||
|
|
@ -1,416 +0,0 @@
|
|||
/**
|
||||
* @file lltextureatlas.cpp
|
||||
* @brief LLTextureAtlas class implementation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "linden_common.h"
|
||||
#include "llerror.h"
|
||||
#include "llimage.h"
|
||||
#include "llmath.h"
|
||||
#include "llgl.h"
|
||||
#include "llrender.h"
|
||||
#include "lltextureatlas.h"
|
||||
|
||||
//-------------------
|
||||
S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
|
||||
S16 LLTextureAtlas::sSlotSize = 32 ;
|
||||
|
||||
#ifndef DEBUG_ATLAS
|
||||
#define DEBUG_ATLAS 0
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_USAGE_BITS
|
||||
#define DEBUG_USAGE_BITS 0
|
||||
#endif
|
||||
//**************************************************************************************************************
|
||||
LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) :
|
||||
LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
|
||||
mAtlasDim(atlas_dim),
|
||||
mNumSlotsReserved(0),
|
||||
mMaxSlotsInAtlas(atlas_dim * atlas_dim)
|
||||
{
|
||||
generateEmptyUsageBits() ;
|
||||
|
||||
//generate an empty texture
|
||||
generateGLTexture() ;
|
||||
LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
|
||||
createGLTexture(0, image_raw, 0);
|
||||
image_raw = NULL;
|
||||
}
|
||||
|
||||
LLTextureAtlas::~LLTextureAtlas()
|
||||
{
|
||||
if(mSpatialGroupList.size() > 0)
|
||||
{
|
||||
LL_ERRS() << "Not clean up the spatial groups!" << LL_ENDL ;
|
||||
}
|
||||
releaseUsageBits() ;
|
||||
}
|
||||
|
||||
//virtual
|
||||
S8 LLTextureAtlas::getType() const
|
||||
{
|
||||
return 0; //LLViewerTexture::ATLAS_TEXTURE ;
|
||||
}
|
||||
|
||||
void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
|
||||
{
|
||||
xoffset = (F32)col / mAtlasDim ;
|
||||
yoffset = (F32)row / mAtlasDim ;
|
||||
}
|
||||
|
||||
void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
|
||||
{
|
||||
xscale = (F32)w / (mAtlasDim * sSlotSize) ;
|
||||
yscale = (F32)h / (mAtlasDim * sSlotSize) ;
|
||||
}
|
||||
|
||||
//insert a texture piece into the atlas
|
||||
LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
|
||||
{
|
||||
if(!getTexName())
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
S32 w = raw_image->getWidth() ;
|
||||
S32 h = raw_image->getHeight() ;
|
||||
if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
|
||||
{
|
||||
//size overflow
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
|
||||
if (!res)
|
||||
{
|
||||
LL_ERRS() << "bindTexture failed" << LL_ENDL;
|
||||
}
|
||||
|
||||
GLint xoffset = sSlotSize * slot_col ;
|
||||
GLint yoffset = sSlotSize * slot_row ;
|
||||
|
||||
if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
|
||||
mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
|
||||
|
||||
source_gl_tex->postAddToAtlas() ;
|
||||
return getTexName();
|
||||
}
|
||||
|
||||
//release a sub-texture slot from the atlas
|
||||
void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
|
||||
{
|
||||
unmarkUsageBits(slot_width, slot_col, slot_row) ;
|
||||
mNumSlotsReserved -= slot_width * slot_width ;
|
||||
}
|
||||
|
||||
BOOL LLTextureAtlas::isEmpty() const
|
||||
{
|
||||
return !mNumSlotsReserved ;
|
||||
}
|
||||
|
||||
BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const
|
||||
{
|
||||
return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
|
||||
}
|
||||
F32 LLTextureAtlas::getFullness() const
|
||||
{
|
||||
return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
|
||||
}
|
||||
|
||||
void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp)
|
||||
{
|
||||
if(groupp && !hasSpatialGroup(groupp))
|
||||
{
|
||||
mSpatialGroupList.push_back(groupp);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp)
|
||||
{
|
||||
if(groupp)
|
||||
{
|
||||
mSpatialGroupList.remove(groupp);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTextureAtlas::clearSpatialGroup()
|
||||
{
|
||||
mSpatialGroupList.clear();
|
||||
}
|
||||
void LLTextureAtlas::removeLastSpatialGroup()
|
||||
{
|
||||
mSpatialGroupList.pop_back() ;
|
||||
}
|
||||
|
||||
LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup()
|
||||
{
|
||||
if(mSpatialGroupList.size() > 0)
|
||||
{
|
||||
return mSpatialGroupList.back() ;
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp)
|
||||
{
|
||||
for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
|
||||
{
|
||||
if(*iter == groupp)
|
||||
{
|
||||
return TRUE ;
|
||||
}
|
||||
}
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
//private
|
||||
void LLTextureAtlas::generateEmptyUsageBits()
|
||||
{
|
||||
S32 col_len = (mAtlasDim + 7) >> 3 ;
|
||||
mUsageBits = new U8*[mAtlasDim] ;
|
||||
*mUsageBits = new U8[mAtlasDim * col_len] ;
|
||||
|
||||
mUsageBits[0] = *mUsageBits ;
|
||||
for(S32 i = 1 ; i < mAtlasDim ; i++)
|
||||
{
|
||||
mUsageBits[i] = mUsageBits[i-1] + col_len ;
|
||||
|
||||
for(S32 j = 0 ; j < col_len ; j++)
|
||||
{
|
||||
//init by 0 for all bits.
|
||||
mUsageBits[i][j] = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
//do not forget mUsageBits[0]!
|
||||
for(S32 j = 0 ; j < col_len ; j++)
|
||||
{
|
||||
//init by 0 for all bits.
|
||||
mUsageBits[0][j] = 0 ;
|
||||
}
|
||||
|
||||
mTestBits = NULL ;
|
||||
#if DEBUG_USAGE_BITS
|
||||
//------------
|
||||
//test
|
||||
mTestBits = new U8*[mAtlasDim] ;
|
||||
*mTestBits = new U8[mAtlasDim * mAtlasDim] ;
|
||||
mTestBits[0] = *mTestBits ;
|
||||
for(S32 i = 1 ; i < mAtlasDim ; i++)
|
||||
{
|
||||
mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
|
||||
|
||||
for(S32 j = 0 ; j < mAtlasDim ; j++)
|
||||
{
|
||||
//init by 0 for all bits.
|
||||
mTestBits[i][j] = 0 ;
|
||||
}
|
||||
}
|
||||
|
||||
for(S32 j = 0 ; j < mAtlasDim ; j++)
|
||||
{
|
||||
//init by 0 for all bits.
|
||||
mTestBits[0][j] = 0 ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLTextureAtlas::releaseUsageBits()
|
||||
{
|
||||
if(mUsageBits)
|
||||
{
|
||||
delete[] *mUsageBits ;
|
||||
delete[] mUsageBits ;
|
||||
}
|
||||
mUsageBits = NULL ;
|
||||
|
||||
//test
|
||||
if( mTestBits)
|
||||
{
|
||||
delete[] *mTestBits;
|
||||
delete[] mTestBits;
|
||||
}
|
||||
mTestBits = NULL ;
|
||||
}
|
||||
|
||||
void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
|
||||
{
|
||||
S16 x = col >> 3 ;
|
||||
|
||||
for(S8 i = 0 ; i < bits_len ; i++)
|
||||
{
|
||||
mUsageBits[row + i][x] |= mask ;
|
||||
}
|
||||
|
||||
#if DEBUG_USAGE_BITS
|
||||
//test
|
||||
for(S8 i = row ; i < row + bits_len ; i++)
|
||||
{
|
||||
for(S8 j = col ; j < col + bits_len ; j++)
|
||||
{
|
||||
mTestBits[i][j] = 1 ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
|
||||
{
|
||||
S16 x = col >> 3 ;
|
||||
U8 mask = 1 ;
|
||||
for(S8 i = 1 ; i < bits_len ; i++)
|
||||
{
|
||||
mask |= (1 << i) ;
|
||||
}
|
||||
mask <<= (col & 7) ;
|
||||
mask = ~mask ;
|
||||
|
||||
for(S8 i = 0 ; i < bits_len ; i++)
|
||||
{
|
||||
mUsageBits[row + i][x] &= mask ;
|
||||
}
|
||||
|
||||
#if DEBUG_USAGE_BITS
|
||||
//test
|
||||
for(S8 i = row ; i < row + bits_len ; i++)
|
||||
{
|
||||
for(S8 j = col ; j < col + bits_len ; j++)
|
||||
{
|
||||
mTestBits[i][j] = 0 ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//return true if any of bits in the range marked.
|
||||
BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
|
||||
{
|
||||
BOOL ret = FALSE ;
|
||||
S16 x = col >> 3 ;
|
||||
|
||||
for(S8 i = 0 ; i < bits_len ; i++)
|
||||
{
|
||||
if(mUsageBits[row + i][x] & mask)
|
||||
{
|
||||
ret = TRUE ;
|
||||
break ;
|
||||
//return TRUE ;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_USAGE_BITS
|
||||
//test
|
||||
BOOL ret2 = FALSE ;
|
||||
for(S8 i = row ; i < row + bits_len ; i++)
|
||||
{
|
||||
for(S8 j = col ; j < col + bits_len ; j++)
|
||||
{
|
||||
if(mTestBits[i][j])
|
||||
{
|
||||
ret2 = TRUE ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ret != ret2)
|
||||
{
|
||||
LL_ERRS() << "bits map corrupted." << LL_ENDL ;
|
||||
}
|
||||
#endif
|
||||
return ret ;//FALSE ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
//index order: Z order, i.e.:
|
||||
// |-----|-----|-----|-----|
|
||||
// | 10 | 11 | 14 | 15 |
|
||||
// |-----|-----|-----|-----|
|
||||
// | 8 | 9 | 12 | 13 |
|
||||
// |-----|-----|-----|-----|
|
||||
// | 2 | 3 | 6 | 7 |
|
||||
// |-----|-----|-----|-----|
|
||||
// | 0 | 1 | 4 | 5 |
|
||||
// |-----|-----|-----|-----|
|
||||
void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
|
||||
{
|
||||
col = 0 ;
|
||||
row = 0 ;
|
||||
|
||||
S16 index_copy = index ;
|
||||
for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
|
||||
{
|
||||
col |= ((index & (1 << i)) >> i) << (i >> 1) ;
|
||||
row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
|
||||
index_copy >>= 2 ;
|
||||
}
|
||||
}
|
||||
void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
|
||||
{
|
||||
index = 0 ;
|
||||
S16 col_copy = col ;
|
||||
S16 row_copy = row ;
|
||||
for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
|
||||
{
|
||||
index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
|
||||
col_copy >>= 1 ;
|
||||
row_copy >>= 1 ;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
//return TRUE if succeeds.
|
||||
BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
|
||||
{
|
||||
S16 index_step = bits_len * bits_len ;
|
||||
|
||||
U8 mask = 1 ;
|
||||
for(S8 i = 1 ; i < bits_len ; i++)
|
||||
{
|
||||
mask |= (1 << i) ;
|
||||
}
|
||||
|
||||
U8 cur_mask ;
|
||||
for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
|
||||
{
|
||||
getPositionFromIndex(index, col, row) ;
|
||||
|
||||
cur_mask = mask << (col & 7) ;
|
||||
if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
|
||||
{
|
||||
markUsageBits(bits_len, cur_mask, col, row) ;
|
||||
mNumSlotsReserved += bits_len * bits_len ;
|
||||
|
||||
return TRUE ;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE ;
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
* @file lltextureatlas.h
|
||||
* @brief LLTextureAtlas base class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_TEXTUREATLAS_H
|
||||
#define LL_TEXTUREATLAS_H
|
||||
|
||||
#include "llviewertexture.h"
|
||||
class LLSpatialGroup ;
|
||||
|
||||
class LLTextureAtlas : public LLViewerTexture
|
||||
{
|
||||
protected:
|
||||
/*virtual*/ ~LLTextureAtlas() ;
|
||||
|
||||
public:
|
||||
LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ;
|
||||
|
||||
/*virtual*/ S8 getType() const;
|
||||
|
||||
LLGLuint insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ;
|
||||
void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width);
|
||||
|
||||
BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ;
|
||||
void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ;
|
||||
void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ;
|
||||
|
||||
BOOL isEmpty() const ;
|
||||
BOOL isFull(S8 to_be_reserved = 1) const ;
|
||||
F32 getFullness() const ;
|
||||
|
||||
void addSpatialGroup(LLSpatialGroup* groupp) ;
|
||||
void removeSpatialGroup(LLSpatialGroup* groupp) ;
|
||||
LLSpatialGroup* getLastSpatialGroup() ;
|
||||
void removeLastSpatialGroup() ;
|
||||
BOOL hasSpatialGroup(LLSpatialGroup* groupp) ;
|
||||
void clearSpatialGroup() ;
|
||||
std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;}
|
||||
private:
|
||||
void generateEmptyUsageBits() ;
|
||||
void releaseUsageBits() ;
|
||||
|
||||
void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ;
|
||||
void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ;
|
||||
|
||||
void getPositionFromIndex(S16 index, S16& col, S16& row) ;
|
||||
void getIndexFromPosition(S16 col, S16 row, S16& index) ;
|
||||
BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ;
|
||||
|
||||
private:
|
||||
S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas.
|
||||
S16 mNumSlotsReserved ;
|
||||
S16 mMaxSlotsInAtlas ;
|
||||
U8 **mUsageBits ;
|
||||
std::list<LLSpatialGroup*> mSpatialGroupList ;
|
||||
|
||||
public:
|
||||
//debug use only
|
||||
U8 **mTestBits ;
|
||||
|
||||
public:
|
||||
static S16 sMaxSubTextureSize ;
|
||||
static S16 sSlotSize ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
/**
|
||||
* @file lltextureatlasmanager.cpp
|
||||
* @brief LLTextureAtlasManager class implementation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "linden_common.h"
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "lltextureatlas.h"
|
||||
#include "lltextureatlasmanager.h"
|
||||
#include "llspatialpartition.h"
|
||||
|
||||
const S8 MAX_NUM_EMPTY_ATLAS = 2 ;
|
||||
const F32 MIN_ATLAS_FULLNESS = 0.6f ;
|
||||
|
||||
//*********************************************************************************************
|
||||
//implementation of class LLTextureAtlasInfo
|
||||
//*********************************************************************************************
|
||||
LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) :
|
||||
mAtlasp(atlasp),
|
||||
mGroupp(groupp),
|
||||
mCol(col),
|
||||
mRow(row),
|
||||
mReservedSlotWidth(slot_width),
|
||||
mValid(FALSE),
|
||||
mUpdatedTime(0),
|
||||
mTexCoordOffset(xoffset, yoffset),
|
||||
mTexCoordScale(1.f, 1.f)
|
||||
{
|
||||
llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ;
|
||||
}
|
||||
|
||||
LLTextureAtlasSlot::~LLTextureAtlasSlot()
|
||||
{
|
||||
if(mAtlasp)
|
||||
{
|
||||
mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ;
|
||||
if(mAtlasp->isEmpty())
|
||||
{
|
||||
LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ;
|
||||
}
|
||||
mAtlasp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp)
|
||||
//{
|
||||
// mAtlasp = atlasp ;
|
||||
//}
|
||||
//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row)
|
||||
//{
|
||||
// mCol = col ;
|
||||
// mRow = row ;
|
||||
//}
|
||||
//void LLTextureAtlasSlot::setSlotWidth(S8 width)
|
||||
//{
|
||||
// //slot is a square with each edge length a power-of-two number
|
||||
// mReservedSlotWidth = width ;
|
||||
//}
|
||||
//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset)
|
||||
//{
|
||||
// mTexCoordOffset.mV[0] = xoffset ;
|
||||
// mTexCoordOffset.mV[1] = yoffset ;
|
||||
//}
|
||||
|
||||
void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp)
|
||||
{
|
||||
mGroupp = groupp ;
|
||||
}
|
||||
void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale)
|
||||
{
|
||||
mTexCoordScale.mV[0] = xscale ;
|
||||
mTexCoordScale.mV[1] = yscale ;
|
||||
}
|
||||
//*********************************************************************************************
|
||||
//END of implementation of class LLTextureAtlasInfo
|
||||
//*********************************************************************************************
|
||||
|
||||
//*********************************************************************************************
|
||||
//implementation of class LLTextureAtlasManager
|
||||
//*********************************************************************************************
|
||||
LLTextureAtlasManager::LLTextureAtlasManager() :
|
||||
mAtlasMap(4),
|
||||
mEmptyAtlasMap(4)
|
||||
{
|
||||
}
|
||||
|
||||
LLTextureAtlasManager::~LLTextureAtlasManager()
|
||||
{
|
||||
for(S32 i = 0 ; i < 4 ; i++)
|
||||
{
|
||||
for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j)
|
||||
{
|
||||
*j = NULL ;
|
||||
}
|
||||
for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j)
|
||||
{
|
||||
*j = NULL ;
|
||||
}
|
||||
|
||||
mAtlasMap[i].clear() ;
|
||||
mEmptyAtlasMap[i].clear() ;
|
||||
}
|
||||
mAtlasMap.clear() ;
|
||||
mEmptyAtlasMap.clear() ;
|
||||
}
|
||||
|
||||
//return TRUE if qualified
|
||||
BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target)
|
||||
{
|
||||
if(ncomponents < 1 || ncomponents > 4)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
//only support GL_TEXTURE_2D
|
||||
if(GL_TEXTURE_2D != target)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
//real image size overflows
|
||||
if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
//if non-power-of-two number
|
||||
if((w & (w - 1)) || (h & (h - 1)))
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
|
||||
return TRUE ;
|
||||
}
|
||||
|
||||
void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp)
|
||||
{
|
||||
LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ;
|
||||
while(groupp)
|
||||
{
|
||||
groupp->removeAtlas(atlasp, FALSE) ;
|
||||
atlasp->removeLastSpatialGroup() ;
|
||||
|
||||
groupp = atlasp->getLastSpatialGroup() ;
|
||||
}
|
||||
|
||||
S8 type = atlasp->getComponents() - 1 ;
|
||||
//insert to the empty list
|
||||
if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS)
|
||||
{
|
||||
mEmptyAtlasMap[type].push_back(atlasp) ;
|
||||
}
|
||||
|
||||
//delete the atlasp
|
||||
mAtlasMap[type].remove(atlasp) ;
|
||||
}
|
||||
|
||||
//
|
||||
//this function reserves an appropriate slot from atlas pool for an image.
|
||||
//return non-NULL if succeeds.
|
||||
//Note:
|
||||
//1, this function does not check if the image this slot assigned for qualifies for atlas or not,
|
||||
// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function.
|
||||
//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway.
|
||||
//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching.
|
||||
//
|
||||
LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
|
||||
LLSpatialGroup* groupp, LLViewerTexture* imagep)
|
||||
{
|
||||
if(!groupp)
|
||||
{
|
||||
//do not insert to atlas if does not have a group.
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
//bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8.
|
||||
if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize)
|
||||
{
|
||||
sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ;
|
||||
}
|
||||
S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ;
|
||||
if(bits_len < 1)
|
||||
{
|
||||
bits_len = 1 ;
|
||||
}
|
||||
|
||||
S16 col = -1, row = -1;
|
||||
S8 total_bits = bits_len * bits_len ;
|
||||
|
||||
//insert to the atlas reserved by the same spatial group
|
||||
LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ;
|
||||
if(atlasp.notNull())
|
||||
{
|
||||
if(!atlasp->getNextAvailableSlot(bits_len, col, row))
|
||||
{
|
||||
//failed
|
||||
atlasp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
//search an atlas to fit for 'size'
|
||||
if(!atlasp)
|
||||
{
|
||||
S8 atlas_index = ncomponents - 1 ;
|
||||
ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ;
|
||||
for(; iter != mAtlasMap[atlas_index].end(); ++iter)
|
||||
{
|
||||
LLTextureAtlas* cur = (LLTextureAtlas*)*iter ;
|
||||
if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary.
|
||||
{
|
||||
if(cur->getNextAvailableSlot(bits_len, col, row))
|
||||
{
|
||||
atlasp = cur ;
|
||||
groupp->addAtlas(atlasp) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create a new atlas if necessary
|
||||
if(!atlasp)
|
||||
{
|
||||
if(mEmptyAtlasMap[ncomponents - 1].size() > 0)
|
||||
{
|
||||
//there is an empty one
|
||||
atlasp = mEmptyAtlasMap[ncomponents - 1].back() ;
|
||||
mEmptyAtlasMap[ncomponents - 1].pop_back() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
atlasp = new LLTextureAtlas(ncomponents, 16) ;
|
||||
}
|
||||
mAtlasMap[ncomponents - 1].push_back(atlasp) ;
|
||||
atlasp->getNextAvailableSlot(bits_len, col, row) ;
|
||||
groupp->addAtlas(atlasp) ;
|
||||
}
|
||||
|
||||
F32 xoffset, yoffset ;
|
||||
atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ;
|
||||
LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ;
|
||||
|
||||
return slot_infop ;
|
||||
}
|
||||
|
||||
//*********************************************************************************************
|
||||
//END of implementation of class LLTextureAtlasManager
|
||||
//*********************************************************************************************
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* @file lltextureatlasmanager.h
|
||||
* @brief LLTextureAtlasManager base class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_TEXTUREATLASMANAGER_H
|
||||
#define LL_TEXTUREATLASMANAGER_H
|
||||
|
||||
#include "llmemory.h"
|
||||
|
||||
class LLSpatialGroup ;
|
||||
class LLViewerTexture ;
|
||||
|
||||
//just use it as a structure.
|
||||
class LLTextureAtlasSlot : public LLRefCount
|
||||
{
|
||||
public:
|
||||
LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ;
|
||||
|
||||
protected:
|
||||
virtual ~LLTextureAtlasSlot();
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
//do not allow to change those values
|
||||
//
|
||||
//void setAtlas(LLTextureAtlas* atlasp) ;
|
||||
//void setSlotPos(S16 col, S16 row) ;
|
||||
//void setSlotWidth(S8 width) ;
|
||||
//void setTexCoordOffset(F32 xoffser, F32 yoffset) ;
|
||||
//
|
||||
|
||||
void setSpatialGroup(LLSpatialGroup* groupp) ;
|
||||
void setTexCoordScale(F32 xscale, F32 yscale) ;
|
||||
void setValid() {mValid = TRUE ;}
|
||||
|
||||
LLTextureAtlas* getAtlas()const {return mAtlasp;}
|
||||
LLSpatialGroup* getSpatialGroup() const {return mGroupp ;}
|
||||
S16 getSlotCol()const {return mCol;}
|
||||
S16 getSlotRow()const {return mRow;}
|
||||
S8 getSlotWidth()const{return mReservedSlotWidth;}
|
||||
BOOL isValid()const { return mValid;}
|
||||
const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;}
|
||||
const LLVector2* getTexCoordScale() const {return &mTexCoordScale;}
|
||||
|
||||
void setUpdatedTime(U32 t) {mUpdatedTime = t;}
|
||||
U32 getUpdatedTime()const {return mUpdatedTime;}
|
||||
|
||||
private:
|
||||
LLTextureAtlas* mAtlasp;
|
||||
S16 mCol ;//col of the slot
|
||||
S16 mRow ;//row of the slot
|
||||
S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number
|
||||
LLSpatialGroup* mGroupp ;
|
||||
BOOL mValid ;
|
||||
|
||||
LLVector2 mTexCoordOffset ;
|
||||
LLVector2 mTexCoordScale ;
|
||||
|
||||
U32 mUpdatedTime ;
|
||||
} ;
|
||||
|
||||
class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>
|
||||
{
|
||||
LLSINGLETON(LLTextureAtlasManager);
|
||||
~LLTextureAtlasManager();
|
||||
typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;
|
||||
|
||||
public:
|
||||
|
||||
LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
|
||||
LLSpatialGroup* groupp, LLViewerTexture* imagep) ;
|
||||
void releaseAtlas(LLTextureAtlas* atlasp);
|
||||
|
||||
BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ;
|
||||
|
||||
private:
|
||||
std::vector<ll_texture_atlas_list_t> mAtlasMap ;
|
||||
std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1560,6 +1560,10 @@ void LLViewerFetchedTexture::addToCreateTexture()
|
|||
BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mGLTexturep->checkActiveThread();
|
||||
#endif
|
||||
|
||||
if (!mNeedsCreateTexture)
|
||||
{
|
||||
destroyRawImage();
|
||||
|
|
@ -1720,6 +1724,10 @@ void LLViewerFetchedTexture::postCreateTexture()
|
|||
{
|
||||
return;
|
||||
}
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mGLTexturep->checkActiveThread();
|
||||
#endif
|
||||
|
||||
// <FS:Beq/> FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
|
||||
gTextureList.recalcImageDecodePriority(this);
|
||||
|
||||
|
|
@ -1738,36 +1746,45 @@ void LLViewerFetchedTexture::postCreateTexture()
|
|||
|
||||
void LLViewerFetchedTexture::scheduleCreateTexture()
|
||||
{
|
||||
ref();
|
||||
mNeedsCreateTexture = TRUE;
|
||||
if (preCreateTexture())
|
||||
if (!mNeedsCreateTexture)
|
||||
{
|
||||
ref();
|
||||
mNeedsCreateTexture = TRUE;
|
||||
if (preCreateTexture())
|
||||
{
|
||||
mNeedsCreateTexture = TRUE;
|
||||
#if LL_WINDOWS //flip to 0 to revert to single-threaded OpenGL texture uploads
|
||||
auto mainq = mMainQueue.lock();
|
||||
if (mainq)
|
||||
{
|
||||
mainq->postTo(
|
||||
mImageQueue,
|
||||
// work to be done on LLImageGL worker thread
|
||||
[this]()
|
||||
{
|
||||
//actually create the texture on a background thread
|
||||
createTexture();
|
||||
},
|
||||
// callback to be run on main thread
|
||||
[this]()
|
||||
{
|
||||
//finalize on main thread
|
||||
postCreateTexture();
|
||||
unref();
|
||||
});
|
||||
}
|
||||
else
|
||||
auto mainq = mMainQueue.lock();
|
||||
if (mainq)
|
||||
{
|
||||
mainq->postTo(
|
||||
mImageQueue,
|
||||
// work to be done on LLImageGL worker thread
|
||||
[this]()
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mGLTexturep->mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
{
|
||||
gTextureList.mCreateTextureList.insert(this);
|
||||
unref();
|
||||
//actually create the texture on a background thread
|
||||
createTexture();
|
||||
},
|
||||
// callback to be run on main thread
|
||||
[this]()
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mGLTexturep->mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
//finalize on main thread
|
||||
postCreateTexture();
|
||||
unref();
|
||||
});
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
gTextureList.mCreateTextureList.insert(this);
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3127,7 +3144,8 @@ void LLViewerFetchedTexture::destroyRawImage()
|
|||
void LLViewerFetchedTexture::switchToCachedImage()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
if(mCachedRawImage.notNull())
|
||||
if(mCachedRawImage.notNull() &&
|
||||
!mNeedsCreateTexture) // <--- texture creation is pending, don't step on it
|
||||
{
|
||||
mRawImage = mCachedRawImage;
|
||||
|
||||
|
|
|
|||
|
|
@ -5454,6 +5454,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
|
|||
}
|
||||
}
|
||||
|
||||
F32 vsize = facep->getVirtualSize(); //TODO -- adjust by texture scale?
|
||||
|
||||
if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0)
|
||||
{
|
||||
|
|
@ -5467,10 +5468,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
|
|||
{
|
||||
batchable = true;
|
||||
draw_vec[idx]->mTextureList[index] = tex;
|
||||
draw_vec[idx]->mTextureListVSize[index] = vsize;
|
||||
}
|
||||
else if (draw_vec[idx]->mTextureList[index] == tex)
|
||||
{ //this face's texture index can be used with this batch
|
||||
batchable = true;
|
||||
draw_vec[idx]->mTextureListVSize[index] = llmax(vsize, draw_vec[idx]->mTextureListVSize[index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -5501,12 +5504,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
|
|||
{
|
||||
draw_vec[idx]->mCount += facep->getIndicesCount();
|
||||
draw_vec[idx]->mEnd += facep->getGeomCount();
|
||||
draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
|
||||
draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
|
||||
|
||||
if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= draw_vec[idx]->mTextureList.size())
|
||||
{
|
||||
draw_vec[idx]->mTextureList.resize(index+1);
|
||||
draw_vec[idx]->mTextureList[index] = tex;
|
||||
draw_vec[idx]->mTextureListVSize.resize(index + 1);
|
||||
draw_vec[idx]->mTextureListVSize[index] = vsize;
|
||||
}
|
||||
draw_vec[idx]->validate();
|
||||
update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]);
|
||||
|
|
@ -5521,7 +5526,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
|
|||
LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
|
||||
facep->getVertexBuffer(), selected, fullbright, bump);
|
||||
draw_info->mGroup = group;
|
||||
draw_info->mVSize = facep->getVirtualSize();
|
||||
draw_info->mVSize = vsize;
|
||||
draw_vec.push_back(draw_info);
|
||||
draw_info->mTextureMatrix = tex_mat;
|
||||
draw_info->mModelMatrix = model_mat;
|
||||
|
|
@ -5596,6 +5601,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
|
|||
{ //initialize texture list for texture batching
|
||||
draw_info->mTextureList.resize(index+1);
|
||||
draw_info->mTextureList[index] = tex;
|
||||
draw_info->mTextureListVSize.resize(index + 1);
|
||||
draw_info->mTextureListVSize[index] = vsize;
|
||||
}
|
||||
draw_info->validate();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3902,25 +3902,31 @@ void renderSoundHighlights(LLDrawable* drawablep)
|
|||
}
|
||||
}
|
||||
|
||||
void LLPipeline::touchTextures(LLDrawInfo* info)
|
||||
void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
for (auto& tex : info->mTextureList)
|
||||
if (tex)
|
||||
{
|
||||
if (tex.notNull())
|
||||
LLImageGL* gl_tex = tex->getGLTexture();
|
||||
if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory))
|
||||
{
|
||||
LLImageGL* gl_tex = tex->getGLTexture();
|
||||
if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory))
|
||||
{
|
||||
tex->setActive();
|
||||
}
|
||||
tex->setActive();
|
||||
tex->addTextureStats(vsize);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->mTexture.notNull())
|
||||
|
||||
}
|
||||
void LLPipeline::touchTextures(LLDrawInfo* info)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
for (int i = 0; i < info->mTextureList.size(); ++i)
|
||||
{
|
||||
info->mTexture->addTextureStats(info->mVSize);
|
||||
touchTexture(info->mTextureList[i], info->mTextureListVSize[i]);
|
||||
}
|
||||
|
||||
touchTexture(info->mTexture, info->mVSize);
|
||||
touchTexture(info->mSpecularMap, info->mVSize);
|
||||
touchTexture(info->mNormalMap, info->mVSize);
|
||||
}
|
||||
|
||||
void LLPipeline::postSort(LLCamera& camera)
|
||||
|
|
|
|||
|
|
@ -260,8 +260,11 @@ public:
|
|||
void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE);
|
||||
void stateSort(LLDrawable* drawablep, LLCamera& camera);
|
||||
void postSort(LLCamera& camera);
|
||||
|
||||
//update stats for textures in given DrawInfo
|
||||
void touchTextures(LLDrawInfo* info);
|
||||
void touchTexture(LLViewerTexture* tex, F32 vsize);
|
||||
|
||||
void forAllVisibleDrawables(void (*func)(LLDrawable*));
|
||||
|
||||
void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue