summaryrefslogtreecommitdiff
path: root/indra/newview/pipeline.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/pipeline.cpp')
-rw-r--r--indra/newview/pipeline.cpp2388
1 files changed, 1787 insertions, 601 deletions
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 62e337b2d1..3a5e41e3ca 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -139,21 +139,22 @@ LLPipeline gPipeline;
const LLMatrix4* gGLLastMatrix = NULL;
//----------------------------------------
-
std::string gPoolNames[] =
{
// Correspond to LLDrawpool enum render type
"NONE",
"POOL_SIMPLE",
- "POOL_TERRAIN",
+ "POOL_TERRAIN",
+ "POOL_BUMP",
"POOL_TREE",
"POOL_SKY",
"POOL_WL_SKY",
"POOL_GROUND",
- "POOL_BUMP",
"POOL_INVISIBLE",
"POOL_AVATAR",
"POOL_WATER",
+ "POOL_GRASS",
+ "POOL_FULLBRIGHT",
"POOL_GLOW",
"POOL_ALPHA",
};
@@ -232,10 +233,12 @@ BOOL LLPipeline::sRenderSoundBeacons = FALSE;
BOOL LLPipeline::sRenderBeacons = FALSE;
BOOL LLPipeline::sRenderHighlight = TRUE;
S32 LLPipeline::sUseOcclusion = 0;
+BOOL LLPipeline::sDelayVBUpdate = TRUE;
BOOL LLPipeline::sFastAlpha = TRUE;
BOOL LLPipeline::sDisableShaders = FALSE;
BOOL LLPipeline::sRenderBump = TRUE;
BOOL LLPipeline::sUseFarClip = TRUE;
+BOOL LLPipeline::sShadowRender = FALSE;
BOOL LLPipeline::sSkipUpdate = FALSE;
BOOL LLPipeline::sWaterReflections = FALSE;
BOOL LLPipeline::sRenderGlow = FALSE;
@@ -246,6 +249,8 @@ BOOL LLPipeline::sTextureBindTest = FALSE;
BOOL LLPipeline::sRenderFrameTest = FALSE;
BOOL LLPipeline::sRenderAttachedLights = TRUE;
BOOL LLPipeline::sRenderAttachedParticles = TRUE;
+BOOL LLPipeline::sRenderDeferred = FALSE;
+S32 LLPipeline::sVisibleLightCount = 0;
static LLCullResult* sCull = NULL;
@@ -261,6 +266,13 @@ static const U32 gl_cube_face[] =
void validate_framebuffer_object();
+void addDeferredAttachments(LLRenderTarget& target)
+{
+ target.addColorAttachment(GL_RGBA16F_ARB); //specular
+ target.addColorAttachment(GL_RGBA16F_ARB); //normal+z
+ target.addColorAttachment(GL_RGBA16F_ARB); //position
+}
+
LLPipeline::LLPipeline() :
mBackfaceCull(FALSE),
mBatchCount(0),
@@ -276,9 +288,6 @@ LLPipeline::LLPipeline() :
mGeometryChanges(0),
mNumVisibleFaces(0),
- mCubeBuffer(NULL),
- mCubeFrameBuffer(0),
- mCubeDepth(0),
mInitialized(FALSE),
mVertexShadersEnabled(FALSE),
mVertexShadersLoaded(0),
@@ -293,6 +302,7 @@ LLPipeline::LLPipeline() :
mWaterPool(NULL),
mGroundPool(NULL),
mSimplePool(NULL),
+ mFullbrightPool(NULL),
mInvisiblePool(NULL),
mGlowPool(NULL),
mBumpPool(NULL),
@@ -301,8 +311,7 @@ LLPipeline::LLPipeline() :
mLightMovingMask(0),
mLightingDetail(0)
{
- mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0;
- mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0;
+ mNoiseMap = 0;
}
void LLPipeline::init()
@@ -321,6 +330,8 @@ void LLPipeline::init()
//create render pass pools
getPool(LLDrawPool::POOL_ALPHA);
getPool(LLDrawPool::POOL_SIMPLE);
+ getPool(LLDrawPool::POOL_GRASS);
+ getPool(LLDrawPool::POOL_FULLBRIGHT);
getPool(LLDrawPool::POOL_INVISIBLE);
getPool(LLDrawPool::POOL_BUMP);
getPool(LLDrawPool::POOL_GLOW);
@@ -405,6 +416,8 @@ void LLPipeline::cleanup()
mGroundPool = NULL;
delete mSimplePool;
mSimplePool = NULL;
+ delete mFullbrightPool;
+ mFullbrightPool = NULL;
delete mInvisiblePool;
mInvisiblePool = NULL;
delete mGlowPool;
@@ -456,52 +469,103 @@ void LLPipeline::resizeScreenTexture()
GLuint resY = gViewerWindow->getWindowDisplayHeight();
U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
- if (res_mod > 1)
+ if (res_mod > 1 && res_mod < resX && res_mod < resY)
{
resX /= res_mod;
resY /= res_mod;
}
-
- mScreen.release();
- mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE);
+
+ allocateScreenBuffer(resX,resY);
llinfos << "RESIZED SCREEN TEXTURE: " << resX << "x" << resY << llendl;
}
}
-
-void LLPipeline::releaseGLBuffers()
+void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
{
- assertInitialized();
-
- if (mCubeBuffer)
+ U32 samples = gSavedSettings.getU32("RenderFSAASamples");
+ if (LLPipeline::sRenderDeferred)
{
- mCubeBuffer = NULL;
+ //allocate deferred rendering color buffers
+ mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+ addDeferredAttachments(mDeferredScreen);
+ mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+
+ for (U32 i = 0; i < 2; i++)
+ {
+ mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+ }
}
-
- if (mCubeFrameBuffer)
+ else
{
- glDeleteFramebuffersEXT(1, &mCubeFrameBuffer);
- glDeleteRenderbuffersEXT(1, &mCubeDepth);
- mCubeDepth = mCubeFrameBuffer = 0;
+ mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
}
+
- if (mBlurCubeBuffer[0])
+ if (gGLManager.mHasFramebufferMultisample && samples > 1)
{
- glDeleteFramebuffersEXT(3, mBlurCubeBuffer);
- mBlurCubeBuffer[0] = mBlurCubeBuffer[1] = mBlurCubeBuffer[2] = 0;
+ if (LLPipeline::sRenderDeferred)
+ {
+ mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
+ addDeferredAttachments(mSampleBuffer);
+ mDeferredScreen.setSampleBuffer(&mSampleBuffer);
+ }
+ else
+ {
+ mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples);
+ }
+
+ mScreen.setSampleBuffer(&mSampleBuffer);
+ stop_glerror();
+ }
+ else if (LLPipeline::sRenderDeferred)
+ { //share depth buffer between deferred targets
+ mDeferredScreen.shareDepthBuffer(mScreen);
+ for (U32 i = 0; i < 2; i++)
+ {
+ mDeferredScreen.shareDepthBuffer(mDeferredLight[i]);
+ }
}
- if (mBlurCubeTexture[0])
+ gGL.getTexUnit(0)->disable();
+
+ stop_glerror();
+
+}
+
+//static
+void LLPipeline::updateRenderDeferred()
+{
+ BOOL deferred = (gSavedSettings.getBOOL("RenderDeferred") &&
+ LLRenderTarget::sUseFBO &&
+ gSavedSettings.getBOOL("VertexShaderEnable") &&
+ gSavedSettings.getBOOL("RenderAvatarVP") &&
+ gSavedSettings.getBOOL("WindLightUseAtmosShaders")) ? TRUE : FALSE;
+
+ sRenderDeferred = deferred;
+}
+
+void LLPipeline::releaseGLBuffers()
+{
+ assertInitialized();
+
+ if (mNoiseMap)
{
- glDeleteTextures(3, mBlurCubeTexture);
- mBlurCubeTexture[0] = mBlurCubeTexture[1] = mBlurCubeTexture[2] = 0;
+ LLImageGL::deleteTextures(1, &mNoiseMap);
+ mNoiseMap = 0;
}
mWaterRef.release();
mWaterDis.release();
mScreen.release();
-
+ mSampleBuffer.releaseSampleBuffer();
+ mDeferredScreen.release();
+
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ mSunShadow[i].release();
+ }
for (U32 i = 0; i < 3; i++)
{
mGlow[i].release();
@@ -514,72 +578,17 @@ void LLPipeline::createGLBuffers()
{
assertInitialized();
+ updateRenderDeferred();
+
if (LLPipeline::sWaterReflections)
{ //water reflection texture
U32 res = (U32) gSavedSettings.getS32("RenderWaterRefResolution");
- mWaterRef.allocate(res,res,GL_RGBA,TRUE);
- mWaterDis.allocate(res,res,GL_RGBA,TRUE);
-
-#if 0 //cube map buffers (keep for future work)
- {
- //reflection map generation buffers
- if (mCubeFrameBuffer == 0)
- {
- glGenFramebuffersEXT(1, &mCubeFrameBuffer);
- glGenRenderbuffersEXT(1, &mCubeDepth);
-
- U32 res = REFLECTION_MAP_RES;
-
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mCubeDepth);
-
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT,res,res);
-
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- }
-
- if (mCubeBuffer.isNull())
- {
- res = 128;
- mCubeBuffer = new LLCubeMap();
- mCubeBuffer->initGL();
- mCubeBuffer->setReflection();
-
- for (U32 i = 0; i < 6; i++)
- {
- glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL);
- }
- }
-
- if (mBlurCubeBuffer[0] == 0)
- {
- glGenFramebuffersEXT(3, mBlurCubeBuffer);
- }
-
- if (mBlurCubeTexture[0] == 0)
- {
- glGenTextures(3, mBlurCubeTexture);
- }
-
- res = (U32) gSavedSettings.getS32("RenderReflectionRes");
-
- for (U32 j = 0; j < 3; j++)
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j]);
- glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- for (U32 i = 0; i < 6; i++)
- {
- glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL);
- }
- }
- }
-#endif
+ mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
+ mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE);
}
+
stop_glerror();
if (LLPipeline::sRenderGlow)
@@ -589,14 +598,41 @@ void LLPipeline::createGLBuffers()
for (U32 i = 0; i < 3; i++)
{
- mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE);
+ mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
}
-
+ }
- GLuint resX = gViewerWindow->getWindowDisplayWidth();
- GLuint resY = gViewerWindow->getWindowDisplayHeight();
+ GLuint resX = gViewerWindow->getWindowDisplayWidth();
+ GLuint resY = gViewerWindow->getWindowDisplayHeight();
- mScreen.allocate(resX, resY, GL_RGBA, TRUE, LLTexUnit::TT_RECT_TEXTURE);
+ allocateScreenBuffer(resX,resY);
+
+ if (sRenderDeferred)
+ {
+ mSunShadow[0].allocate(1024,1024, 0, TRUE, FALSE);
+ mSunShadow[1].allocate(1024,1024, 0, TRUE, FALSE);
+ mSunShadow[2].allocate(1024,1024, 0, TRUE, FALSE);
+ mSunShadow[3].allocate(1024,1024, 0, TRUE, FALSE);
+
+ if (!mNoiseMap)
+ {
+ const U32 noiseRes = 128;
+ LLVector3 noise[noiseRes*noiseRes];
+
+ F32 scaler = gSavedSettings.getF32("RenderDeferredNoise")/100.f;
+ for (U32 i = 0; i < noiseRes*noiseRes; ++i)
+ {
+ noise[i] = LLVector3(ll_frand()-0.5f, ll_frand()-0.5f, 0.f);
+ noise[i].normVec();
+ noise[i].mV[2] = ll_frand()*scaler+1.f-scaler/2.f;
+ }
+
+ LLImageGL::generateTextures(1, &mNoiseMap);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
}
}
@@ -627,7 +663,8 @@ void LLPipeline::restoreGL()
BOOL LLPipeline::canUseVertexShaders()
{
- if (!gGLManager.mHasVertexShader ||
+ if (sDisableShaders ||
+ !gGLManager.mHasVertexShader ||
!gGLManager.mHasFragmentShader ||
!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
(assertInitialized() && mVertexShadersLoaded != 1) )
@@ -785,6 +822,14 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0)
poolp = mSimplePool;
break;
+ case LLDrawPool::POOL_GRASS:
+ poolp = mGrassPool;
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ poolp = mFullbrightPool;
+ break;
+
case LLDrawPool::POOL_INVISIBLE:
poolp = mInvisiblePool;
break;
@@ -964,19 +1009,61 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable)
U32 LLPipeline::addObject(LLViewerObject *vobj)
{
- LLMemType mt(LLMemType::MTYPE_DRAWABLE);
if (gNoRender)
{
return 0;
}
+ if (gSavedSettings.getBOOL("RenderDelayCreation"))
+ {
+ mCreateQ.push_back(vobj);
+ }
+ else
+ {
+ createObject(vobj);
+ }
+
+ return 1;
+}
+
+void LLPipeline::createObjects(F32 max_dtime)
+{
+ LLFastTimer ftm(LLFastTimer::FTM_GEO_UPDATE);
+ LLMemType mt(LLMemType::MTYPE_DRAWABLE);
+
+ LLTimer update_timer;
+
+ while (!mCreateQ.empty() && update_timer.getElapsedTimeF32() < max_dtime)
+ {
+ LLViewerObject* vobj = mCreateQ.front();
+ if (!vobj->isDead())
+ {
+ createObject(vobj);
+ }
+ mCreateQ.pop_front();
+ }
+
+ //for (LLViewerObject::vobj_list_t::iterator iter = mCreateQ.begin(); iter != mCreateQ.end(); ++iter)
+ //{
+ // createObject(*iter);
+ //}
+
+ //mCreateQ.clear();
+}
+
+void LLPipeline::createObject(LLViewerObject* vobj)
+{
LLDrawable* drawablep = vobj->mDrawable;
if (!drawablep)
{
drawablep = vobj->createDrawable(this);
}
-
+ else
+ {
+ llerrs << "Redundant drawable creation!" << llendl;
+ }
+
llassert(drawablep);
if (vobj->getParent())
@@ -990,7 +1077,14 @@ U32 LLPipeline::addObject(LLViewerObject *vobj)
markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE);
- return 1;
+ if (drawablep->getVOVolume() && gSavedSettings.getBOOL("RenderAnimateRes"))
+ {
+ // fun animated res
+ drawablep->updateXform(TRUE);
+ drawablep->clearState(LLDrawable::MOVE_UNDAMPED);
+ drawablep->setScale(LLVector3(0,0,0));
+ drawablep->makeActive();
+ }
}
@@ -1195,6 +1289,65 @@ void LLPipeline::grabReferences(LLCullResult& result)
sCull = &result;
}
+BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
+{
+ for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ if (part->visibleObjectsInFrustum(camera))
+ {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max)
+{
+ min = LLVector3(F32_MAX, F32_MAX, F32_MAX);
+ max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX);
+
+
+ BOOL res = TRUE;
+
+ for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+
+ for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(i);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ if (!part->getVisibleExtents(camera, min, max))
+ {
+ res = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+
void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip)
{
LLFastTimer t(LLFastTimer::FTM_CULL);
@@ -1207,6 +1360,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
BOOL to_texture = LLPipeline::sUseOcclusion > 1 &&
!hasRenderType(LLPipeline::RENDER_TYPE_HUD) &&
!sReflectionRender &&
+ !sShadowRender &&
gPipeline.canUseVertexShaders() &&
sRenderGlow;
@@ -1217,6 +1371,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
glPushMatrix();
gGLLastMatrix = NULL;
+ //glLoadMatrixd(gGLModelView);
glLoadMatrixd(gGLLastModelView);
LLVertexBuffer::unbind();
@@ -1224,7 +1379,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
LLGLDisable test(GL_ALPHA_TEST);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.setColorMask(false, false);
+ if (sUseOcclusion > 1)
+ {
+ gGL.setColorMask(false, false);
+ }
+
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin();
@@ -1282,13 +1441,17 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
sCull->pushDrawable(gSky.mVOGroundp->mDrawable);
}
- gGL.setColorMask(true, false);
+
glPopMatrix();
+ if (sUseOcclusion > 1)
+ {
+ gGL.setColorMask(true, false);
+ }
+
if (to_texture)
{
mScreen.flush();
- LLRenderTarget::unbindTarget();
}
else if (LLPipeline::sUseOcclusion > 1)
{
@@ -1357,6 +1520,7 @@ void LLPipeline::markOccluder(LLSpatialGroup* group)
void LLPipeline::doOcclusion(LLCamera& camera)
{
LLVertexBuffer::unbind();
+
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION))
{
gGL.setColorMask(true, false, false, false);
@@ -1525,7 +1689,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion)
if (!drawablep)
{
- llerrs << "Sending null drawable to moved list!" << llendl;
+ //llerrs << "Sending null drawable to moved list!" << llendl;
return;
}
@@ -1595,8 +1759,8 @@ void LLPipeline::shiftObjects(const LLVector3 &offset)
assertInitialized();
glClear(GL_DEPTH_BUFFER_BIT);
- gDepthDirty = FALSE;
-
+ gDepthDirty = TRUE;
+
for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin();
iter != mShiftList.end(); iter++)
{
@@ -1772,6 +1936,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
stateSort(drawablep, camera);
}
}
+
}
void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
@@ -2045,6 +2210,22 @@ void LLPipeline::postSort(LLCamera& camera)
}
LLSpatialGroup::sNoDelete = TRUE;
+
+ const S32 bin_count = 1024*8;
+
+ static LLCullResult::drawinfo_list_t alpha_bins[bin_count];
+ static U32 bin_size[bin_count];
+
+ //clear one bin per frame to avoid memory bloat
+ static S32 clear_idx = 0;
+ clear_idx = (1+clear_idx)%bin_count;
+ alpha_bins[clear_idx].clear();
+
+ for (U32 j = 0; j < bin_count; j++)
+ {
+ bin_size[j] = 0;
+ }
+
//build render map
for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
{
@@ -2064,7 +2245,7 @@ void LLPipeline::postSort(LLCamera& camera)
sCull->pushDrawInfo(j->first, *k);
}
}
-
+
LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA);
if (alpha != group->mDrawMap.end())
@@ -2090,28 +2271,26 @@ void LLPipeline::postSort(LLCamera& camera)
}
}
+ if (!sShadowRender)
{
//sort by texture or bump map
for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i)
{
- //if (!mRenderMap[i].empty())
+ if (i == LLRenderPass::PASS_BUMP)
{
- if (i == LLRenderPass::PASS_BUMP)
- {
- std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
- }
- else
- {
- std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
- }
+ std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareBump());
}
+ else
+ {
+ std::sort(sCull->beginRenderMap(i), sCull->endRenderMap(i), LLDrawInfo::CompareTexturePtrMatrix());
+ }
}
std::sort(sCull->beginAlphaGroups(), sCull->endAlphaGroups(), LLSpatialGroup::CompareDepthGreater());
}
-
+
// only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus
- if (gSavedSettings.getBOOL("BeaconAlwaysOn"))
+ if (gSavedSettings.getBOOL("BeaconAlwaysOn") && !sShadowRender)
{
if (sRenderScriptedTouchBeacons)
{
@@ -2164,23 +2343,26 @@ void LLPipeline::postSort(LLCamera& camera)
LLFloaterTelehub::addBeacons();
}
- mSelectedFaces.clear();
-
- // Draw face highlights for selected faces.
- if (LLSelectMgr::getInstance()->getTEMode())
+ if (!sShadowRender)
{
- struct f : public LLSelectedTEFunctor
+ mSelectedFaces.clear();
+
+ // Draw face highlights for selected faces.
+ if (LLSelectMgr::getInstance()->getTEMode())
{
- virtual bool apply(LLViewerObject* object, S32 te)
+ struct f : public LLSelectedTEFunctor
{
- if (object->mDrawable)
+ virtual bool apply(LLViewerObject* object, S32 te)
{
- gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
+ if (object->mDrawable)
+ {
+ gPipeline.mSelectedFaces.push_back(object->mDrawable->getFace(te));
+ }
+ return true;
}
- return true;
- }
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ } func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ }
}
LLSpatialGroup::sNoDelete = FALSE;
@@ -2328,8 +2510,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
stop_glerror();
gFrameStats.start(LLFrameStats::RENDER_SYNC);
- glEnableClientState(GL_VERTEX_ARRAY);
-
LLVertexBuffer::unbind();
// Do verification of GL state
@@ -2379,7 +2559,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
}
gGL.getTexUnit(0)->bind(LLViewerImage::sDefaultImagep);
- LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE);
+ LLViewerImage::sDefaultImagep->setAddressMode(LLTexUnit::TAM_WRAP);
//////////////////////////////////////////////
//
@@ -2387,37 +2567,39 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
//
//
stop_glerror();
- BOOL occlude = sUseOcclusion > 1;
- U32 cur_type = 0;
-
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPools");
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
- {
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect");
- gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect());
+ LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred");
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (hasRenderType(poolp->getType()))
+ {
+ poolp->prerender();
+ }
}
- else if (gSavedSettings.getBOOL("RenderDeferred"))
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING))
{
- LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDeferred");
- renderGeomDeferred();
+ gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect());
}
else
{
- for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ LLFastTimer t(LLFastTimer::FTM_POOLS);
+
+ // HACK: don't calculate local lights if we're rendering the HUD!
+ // Removing this check will cause bad flickering when there are
+ // HUD elements being rendered AND the user is in flycam mode -nyx
+ if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
{
- LLDrawPool *poolp = *iter;
- if (hasRenderType(poolp->getType()))
- {
- poolp->prerender();
- }
+ calcNearbyLights(camera);
+ setupHWLights(NULL);
}
-
- LLFastTimer t(LLFastTimer::FTM_POOLS);
- calcNearbyLights(camera);
- setupHWLights(NULL);
+ BOOL occlude = sUseOcclusion > 1;
+ U32 cur_type = 0;
pool_set_t::iterator iter1 = mPools.begin();
while ( iter1 != mPools.end() )
@@ -2426,7 +2608,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
cur_type = poolp->getType();
- if (occlude && cur_type > LLDrawPool::POOL_AVATAR)
+ if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
{
occlude = FALSE;
gGLLastMatrix = NULL;
@@ -2444,6 +2626,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
for( S32 i = 0; i < poolp->getNumPasses(); i++ )
{
+ LLVertexBuffer::unbind();
poolp->beginRenderPass(i);
for (iter2 = iter1; iter2 != mPools.end(); iter2++)
{
@@ -2487,25 +2670,29 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
iter1 = iter2;
stop_glerror();
}
- }
LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDrawPoolsEnd");
LLVertexBuffer::unbind();
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ if (occlude)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+ doOcclusion(camera);
+ }
+ }
+
+ LLVertexBuffer::unbind();
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
- gGLLastMatrix = NULL;
- glLoadMatrixd(gGLModelView);
-
- if (occlude)
- {
- occlude = FALSE;
- gGLLastMatrix = NULL;
- glLoadMatrixd(gGLModelView);
- doOcclusion(camera);
- }
+
stop_glerror();
@@ -2530,7 +2717,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
LLVertexBuffer::unbind();
- if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
// Render debugging beacons.
gObjectList.renderObjectBeacons();
@@ -2557,13 +2744,283 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
LLGLState::checkClientArrays();
}
-void LLPipeline::renderGeomDeferred()
+void LLPipeline::renderGeomDeferred(LLCamera& camera)
{
- gDeferredDiffuseProgram.bind();
- gPipeline.renderObjects(LLRenderPass::PASS_SIMPLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_NORMAL, TRUE);
- gDeferredDiffuseProgram.unbind();
+ LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY);
+
+ LLFastTimer t2(LLFastTimer::FTM_POOLS);
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+ stop_glerror();
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ stop_glerror();
+
+ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+ {
+ LLDrawPool *poolp = *iter;
+ if (hasRenderType(poolp->getType()))
+ {
+ poolp->prerender();
+ }
+ }
+
+ LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
+ U32 cur_type = 0;
+
+ gGL.setColorMask(true, true);
+
+ pool_set_t::iterator iter1 = mPools.begin();
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+ {
+ LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginDeferredPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderDeferred(i);
+ }
+ poolp->endDeferredPass(i);
+ LLVertexBuffer::unbind();
+
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ gGL.setColorMask(true, false);
+}
+
+void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
+{
+ LLFastTimer t(LLFastTimer::FTM_POOLS);
+ U32 cur_type = 0;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+ calcNearbyLights(camera);
+ setupHWLights(NULL);
+
+ gGL.setColorMask(true, false);
+
+ pool_set_t::iterator iter1 = mPools.begin();
+ BOOL occlude = LLPipeline::sUseOcclusion > 1;
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+ doOcclusion(camera);
+ gGL.setColorMask(true, false);
+ }
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumPostDeferredPasses() > 0)
+ {
+ LLFastTimer t(LLFastTimer::FTM_POOLRENDER);
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumPostDeferredPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginPostDeferredPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderPostDeferred(i);
+ }
+ poolp->endPostDeferredPass(i);
+ LLVertexBuffer::unbind();
+
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth > 3)
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ renderHighlights();
+ mHighlightFaces.clear();
+
+ renderDebug();
+
+ LLVertexBuffer::unbind();
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ LLHUDObject::renderAll();
+ gObjectList.resetObjectBeacons();
+ }
+
+ if (occlude)
+ {
+ occlude = FALSE;
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+ doOcclusion(camera);
+ }
}
+void LLPipeline::renderGeomShadow(LLCamera& camera)
+{
+ U32 cur_type = 0;
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ LLVertexBuffer::unbind();
+
+ pool_set_t::iterator iter1 = mPools.begin();
+
+ while ( iter1 != mPools.end() )
+ {
+ LLDrawPool *poolp = *iter1;
+
+ cur_type = poolp->getType();
+
+ pool_set_t::iterator iter2 = iter1;
+ if (hasRenderType(poolp->getType()) && poolp->getNumShadowPasses() > 0)
+ {
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+
+ for( S32 i = 0; i < poolp->getNumShadowPasses(); i++ )
+ {
+ LLVertexBuffer::unbind();
+ poolp->beginShadowPass(i);
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+
+ p->renderShadow(i);
+ }
+ poolp->endShadowPass(i);
+ LLVertexBuffer::unbind();
+
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+ }
+ }
+ else
+ {
+ // Skip all pools of this type
+ for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+ {
+ LLDrawPool *p = *iter2;
+ if (p->getType() != cur_type)
+ {
+ break;
+ }
+ }
+ }
+ iter1 = iter2;
+ stop_glerror();
+ }
+
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
+}
+
+
void LLPipeline::addTrianglesDrawn(S32 count)
{
assertInitialized();
@@ -2621,6 +3078,99 @@ void LLPipeline::renderDebug()
}
}
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ gGL.color4f(1,1,1,1);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ F32 col[] =
+ {
+ 1,1,0,
+ 0,1,1,
+ 1,0,1,
+ 1,1,1,
+ 1,0,0,
+ 0,1,0,
+ 0,0,1,
+ 0,0,0
+ };
+
+ for (U32 i = 0; i < 8; i++)
+ {
+ gGL.color3fv(col+i*3);
+
+ gGL.begin(LLRender::LINES);
+
+ LLVector3* frust = mShadowCamera[i].mAgentFrustum;
+
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV);
+
+ gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV);
+ gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV);
+
+ gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV);
+ gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV);
+ gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV);
+ gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV);
+
+ if (i < 4)
+ {
+ LLVector3* ext = mShadowExtents[i];
+
+ LLVector3 box[] =
+ {
+ LLVector3(ext[0][0], ext[0][1], ext[0][2]),
+ LLVector3(ext[1][0], ext[0][1], ext[0][2]),
+ LLVector3(ext[1][0], ext[1][1], ext[0][2]),
+ LLVector3(ext[0][0], ext[1][1], ext[0][2]),
+ LLVector3(ext[0][0], ext[0][1], ext[1][2]),
+ LLVector3(ext[1][0], ext[0][1], ext[1][2]),
+ LLVector3(ext[1][0], ext[1][1], ext[1][2]),
+ LLVector3(ext[0][0], ext[1][1], ext[1][2]),
+ };
+
+ gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV);
+ gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV);
+ gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV);
+ gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV);
+
+ gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV);
+ gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV);
+ gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV);
+ gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV);
+
+ gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV);
+ gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV);
+ gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV);
+ gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV);
+ }
+
+ gGL.end();
+
+ for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin();
+ iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ {
+ LLViewerRegion* region = *iter;
+ for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
+ {
+ LLSpatialPartition* part = region->getSpatialPartition(j);
+ if (part)
+ {
+ if (hasRenderType(part->mDrawableType))
+ {
+ part->renderIntersectingBBoxes(&mShadowCamera[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+
if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION)
{
// Debug composition layers
@@ -2653,6 +3203,7 @@ void LLPipeline::renderDebug()
gGL.end();
}
}
+
gGL.flush();
}
@@ -2735,7 +3286,7 @@ void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render
gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA);
U32 prim_mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD;
+ LLVertexBuffer::MAP_TEXCOORD0;
for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i)
{
@@ -2891,6 +3442,30 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_GRASS:
+ if (mGrassPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate grass pool." << llendl;
+ }
+ else
+ {
+ mGrassPool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ if (mFullbrightPool)
+ {
+ llassert(0);
+ llwarns << "Ignoring duplicate simple pool." << llendl;
+ }
+ else
+ {
+ mFullbrightPool = (LLRenderPass*) new_poolp;
+ }
+ break;
+
case LLDrawPool::POOL_INVISIBLE:
if (mInvisiblePool)
{
@@ -3024,6 +3599,16 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mSimplePool = NULL;
break;
+ case LLDrawPool::POOL_GRASS:
+ llassert(mGrassPool == poolp);
+ mGrassPool = NULL;
+ break;
+
+ case LLDrawPool::POOL_FULLBRIGHT:
+ llassert(mFullbrightPool == poolp);
+ mFullbrightPool = NULL;
+ break;
+
case LLDrawPool::POOL_INVISIBLE:
llassert(mInvisiblePool == poolp);
mInvisiblePool = NULL;
@@ -3117,7 +3702,7 @@ void LLPipeline::setupAvatarLights(BOOL for_edit)
if (for_edit)
{
- LLColor4 diffuse(0.8f, 0.8f, 0.8f, 0.f);
+ LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
LLVector4 light_pos_cam(-8.f, 0.25f, 10.f, 0.f); // w==0 => directional light
LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
LLMatrix4 camera_rot(camera_mat.getMat3());
@@ -3288,6 +3873,10 @@ void LLPipeline::calcNearbyLights(LLCamera& camera)
{
continue;
}
+ if (!sRenderAttachedLights && light && light->isAttachment())
+ {
+ continue;
+ }
new_nearby_lights.insert(Light(drawable, dist, 0.f));
if (new_nearby_lights.size() > (U32)MAX_LOCAL_LIGHTS)
{
@@ -4282,11 +4871,11 @@ void LLPipeline::resetVertexBuffers()
void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture)
{
assertInitialized();
+ glLoadMatrixd(gGLModelView);
gGLLastMatrix = NULL;
- glLoadMatrixd(gGLLastModelView);
- mSimplePool->renderGroups(type, mask, texture);
- gGLLastMatrix = NULL;
- glLoadMatrixd(gGLLastModelView);
+ mSimplePool->pushBatches(type, mask);
+ glLoadMatrixd(gGLModelView);
+ gGLLastMatrix = NULL;
}
void LLPipeline::setUseVBO(BOOL use_vbo)
@@ -4334,191 +4923,6 @@ void apply_cube_face_rotation(U32 face)
break;
}
}
-void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam)
-{
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- assertInitialized();
-
- //render dynamic cube map
- U32 type_mask = gPipeline.getRenderTypeMask();
- S32 use_occlusion = LLPipeline::sUseOcclusion;
- LLPipeline::sUseOcclusion = 0;
- LLPipeline::sSkipUpdate = TRUE;
- U32 res = REFLECTION_MAP_RES;
-
- LLPipeline::sReflectionRender = TRUE;
-
- gGL.getTexUnit(cube_map->getStage())->bind(cube_map);
- gGL.getTexUnit(0)->activate();
- GLint width;
- glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width);
- if (width != res)
- {
- cube_map->setReflection();
-
- for (U32 i = 0; i < 6; i++)
- {
- glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL);
- }
- }
- gGL.getTexUnit(cube_map->getStage())->unbind(LLTexUnit::TT_CUBE_MAP);
- gGL.getTexUnit(cube_map->getStage())->disable();
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-
- BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
- if (toggle_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
-
- U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) |
- (1 << LLPipeline::RENDER_TYPE_WATER) |
- //(1 << LLPipeline::RENDER_TYPE_BUMP) |
- (1 << LLPipeline::RENDER_TYPE_ALPHA) |
- (1 << LLPipeline::RENDER_TYPE_TREE) |
- //(1 << LLPipeline::RENDER_TYPE_PARTICLES) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
- //(1 << LLPipeline::RENDER_TYPE_STARS) |
- //(1 << LLPipeline::RENDER_TYPE_AVATAR) |
- (1 << LLPipeline::RENDER_TYPE_GLOW) |
- (1 << LLPipeline::RENDER_TYPE_GRASS) |
- (1 << LLPipeline::RENDER_TYPE_VOLUME) |
- (1 << LLPipeline::RENDER_TYPE_TERRAIN) |
- (1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_WL_SKY) |
- (1 << LLPipeline::RENDER_TYPE_GROUND);
-
- LLDrawPoolWater::sSkipScreenCopy = TRUE;
- LLPipeline::sSkipUpdate = TRUE;
- cube_mask = cube_mask & type_mask;
- gPipeline.setRenderTypeMask(cube_mask);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- glViewport(0,0,res,res);
-
- glClearColor(0,0,0,0);
-
- LLVector3 origin = cube_cam.getOrigin();
-
- gPipeline.calcNearbyLights(cube_cam);
-
- stop_glerror();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, mCubeDepth);
- stop_glerror();
-
- for (S32 i = 0; i < 6; i++)
- {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mCubeFrameBuffer);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- gl_cube_face[i], cube_map->getGLName(), 0);
- validate_framebuffer_object();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(90.f, 1.f, 0.1f, 1024.f);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- apply_cube_face_rotation(i);
-
- glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]);
- cube_cam.setOrigin(origin);
- LLViewerCamera::updateFrustumPlanes(cube_cam);
- cube_cam.setOrigin(LLViewerCamera::getInstance()->getOrigin());
- static LLCullResult result;
- gPipeline.updateCull(cube_cam, result);
- gPipeline.stateSort(cube_cam, result);
-
- glClearColor(0,0,0,0);
- gGL.setColorMask(true, true);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
- gGL.setColorMask(true, false);
- stop_glerror();
- gPipeline.renderGeom(cube_cam);
- }
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- cube_cam.setOrigin(origin);
- gShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- gViewerWindow->setupViewport();
-
- gPipeline.setRenderTypeMask(type_mask);
- LLPipeline::sUseOcclusion = use_occlusion;
- LLPipeline::sSkipUpdate = FALSE;
-
- if (toggle_ui)
- {
- gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
- LLDrawPoolWater::sSkipScreenCopy = FALSE;
- LLPipeline::sSkipUpdate = FALSE;
- LLPipeline::sReflectionRender = FALSE;
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-}
-
-//send cube map vertices and texture coordinates
-void render_cube_map()
-{
- U16 idx[36];
-
- idx[0] = 1; idx[1] = 0; idx[2] = 2; //front
- idx[3] = 3; idx[4] = 2; idx[5] = 0;
-
- idx[6] = 4; idx[7] = 5; idx[8] = 1; //top
- idx[9] = 0; idx[10] = 1; idx[11] = 5;
-
- idx[12] = 5; idx[13] = 4; idx[14] = 6; //back
- idx[15] = 7; idx[16] = 6; idx[17] = 4;
-
- idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom
- idx[21] = 2; idx[22] = 3; idx[23] = 7;
-
- idx[24] = 0; idx[25] = 5; idx[26] = 3; //left
- idx[27] = 6; idx[28] = 3; idx[29] = 5;
-
- idx[30] = 4; idx[31] = 1; idx[32] = 7; //right
- idx[33] = 2; idx[34] = 7; idx[35] = 1;
-
- LLVector3 vert[8];
- LLVector3 r = LLVector3(1,1,1);
-
- vert[0] = r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front
- vert[1] = r.scaledVec(LLVector3(1,1,1)); // 1 - right top front
- vert[2] = r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front
- vert[3] = r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front
-
- vert[4] = r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back
- vert[5] = r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back
- vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back
- vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back
-
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(3, GL_FLOAT, 0, vert);
- glVertexPointer(3, GL_FLOAT, 0, vert);
-
- glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (GLushort*) idx);
-
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
void validate_framebuffer_object()
{
@@ -4547,132 +4951,12 @@ void validate_framebuffer_object()
}
}
-void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out)
-{
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-
- assertInitialized();
-
- U32 res = (U32) gSavedSettings.getS32("RenderReflectionRes");
- enableLightsFullbright(LLColor4::white);
- LLGLDepthTest depth(GL_FALSE);
- gGL.setColorMask(true, true);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
- cube_out->enableTexture(0);
- gGL.getTexUnit(cube_out->getStage())->bind(cube_out);
- gGL.getTexUnit(0)->activate();
- GLint width;
- glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_TEXTURE_WIDTH, &width);
- if (width != res)
- {
- cube_out->setReflection();
-
- for (U32 i = 0; i < 6; i++)
- {
- glTexImage2D(gl_cube_face[i], 0, GL_RGBA, res, res, 0, GL_RGBA, GL_FLOAT, NULL);
- }
- }
- gGL.getTexUnit(cube_out->getStage())->unbind(LLTexUnit::TT_CUBE_MAP);
- gGL.getTexUnit(0)->activate();
- glViewport(0, 0, res, res);
- LLGLEnable blend(GL_BLEND);
-
- S32 kernel = 2;
- F32 step = 90.f/res;
- F32 alpha = 1.f / ((kernel*2)+1);
-
- gGL.color4f(alpha,alpha,alpha,alpha*1.25f);
-
- LLVector3 axis[] =
- {
- LLVector3(1,0,0),
- LLVector3(0,1,0),
- LLVector3(0,0,1)
- };
-
- stop_glerror();
- glViewport(0,0,res, res);
- gGL.setSceneBlendType(LLRender::BT_ADD);
- cube_in->enableTexture(0);
- //3-axis blur
- for (U32 j = 0; j < 3; j++)
- {
- stop_glerror();
-
- if (j == 0)
- {
- gGL.getTexUnit(cube_in->getStage())->bind(cube_in);
- }
- else
- {
- gGL.getTexUnit(cube_in->getStage())->bindManual(LLTexUnit::TT_CUBE_MAP, mBlurCubeTexture[j-1]);
- }
- gGL.getTexUnit(0)->activate();
-
- stop_glerror();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mBlurCubeBuffer[j]);
- stop_glerror();
-
- for (U32 i = 0; i < 6; i++)
- {
- stop_glerror();
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
- GL_COLOR_ATTACHMENT0_EXT,
- gl_cube_face[i],
- j < 2 ? mBlurCubeTexture[j] : cube_out->getGLName(), 0);
- validate_framebuffer_object();
- gGL.setColorMask(true, true);
- glClear(GL_COLOR_BUFFER_BIT);
- glLoadIdentity();
- apply_cube_face_rotation(i);
- for (S32 x = -kernel; x <= kernel; ++x)
- {
- glPushMatrix();
- glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]);
- render_cube_map();
- glPopMatrix();
- }
- stop_glerror();
- }
- }
-
- stop_glerror();
-
- gGL.getTexUnit(cube_in->getStage())->unbind(LLTexUnit::TT_CUBE_MAP);
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- gGL.setColorMask(true, false);
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
- gGL.getTexUnit(cube_in->getStage())->disable();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- gViewerWindow->setupViewport();
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- LLGLState::checkStates();
- LLGLState::checkTextureChannels();
- LLGLState::checkClientArrays();
-}
-
void LLPipeline::bindScreenToTexture()
{
}
-void LLPipeline::renderBloom(BOOL for_snapshot)
+void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
{
if (!(gPipeline.canUseVertexShaders() &&
sRenderGlow))
@@ -4694,8 +4978,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor");
LLVector2 tc1(0,0);
- LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth(),
- (F32) gViewerWindow->getWindowDisplayHeight());
+ LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth()*2,
+ (F32) gViewerWindow->getWindowDisplayHeight()*2);
if (res_mod > 1)
{
@@ -4732,9 +5016,22 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
//glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
//LLGLDisable blend(GL_BLEND);
+
+ // If the snapshot is constructed from tiles, calculate which
+ // tile we're in.
+ const S32 num_horizontal_tiles = llceil(zoom_factor);
+ const LLVector2 tile(subfield % num_horizontal_tiles,
+ (S32)(subfield / num_horizontal_tiles));
+ llassert(zoom_factor > 0.0); // Non-zero, non-negative.
+ const F32 tile_size = 1.0/zoom_factor;
+
+ tc1 = tile*tile_size; // Top left texture coordinates
+ tc2 = (tile+LLVector2(1,1))*tile_size; // Bottom right texture coordinates
+
LLGLEnable blend(GL_BLEND);
gGL.setSceneBlendType(LLRender::BT_ADD);
- tc2.setVec(1,1);
+
+
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.color4f(1,1,1,1);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
@@ -4748,6 +5045,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
gGL.vertex2f(1,1);
+
gGL.end();
gGL.flush();
@@ -4771,7 +5069,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
}
gGlowExtractProgram.bind();
- F32 minLum = llclamp(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f, 1.0f);
+ F32 minLum = llmax(gSavedSettings.getF32("RenderGlowMinLuminance"), 0.0f);
F32 maxAlpha = gSavedSettings.getF32("RenderGlowMaxExtractAlpha");
F32 warmthAmount = gSavedSettings.getF32("RenderGlowWarmthAmount");
LLVector3 lumWeights = gSavedSettings.getVector3("RenderGlowLumWeights");
@@ -4798,13 +5096,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,1);
+ gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(1,-1);
+ gGL.vertex2f(3,-1);
- gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
- gGL.vertex2f(1,1);
gGL.end();
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
@@ -4813,7 +5109,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
}
tc1.setVec(0,0);
- tc2.setVec(1,1);
+ tc2.setVec(2,2);
@@ -4867,13 +5163,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
gGL.vertex2f(-1,-1);
gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,1);
+ gGL.vertex2f(-1,3);
gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(1,-1);
+ gGL.vertex2f(3,-1);
- gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
- gGL.vertex2f(1,1);
gGL.end();
mGlow[i%2].flush();
@@ -4889,81 +5183,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
gViewerWindow->setupViewport();
- /*mGlow[1].bindTexture();
- {
- LLGLEnable stencil(GL_STENCIL_TEST);
- glStencilFunc(GL_NOTEQUAL, 255, 0xFFFFFFFF);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- LLGLDisable blend(GL_BLEND);
-
- gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
- gGL.color4f(1,1,1,1);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,1);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(1,-1);
-
- gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
- gGL.vertex2f(1,1);
- gGL.end();
-
- gGL.flush();
- }
-
- if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_GLOW))
- {
- tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(),
- (F32) gViewerWindow->getWindowDisplayHeight());
-
- if (res_mod > 1)
- {
- tc2 /= (F32) res_mod;
- }
-
- LLGLEnable blend(GL_BLEND);
- gGL.blendFunc(GL_ONE, GL_ONE);
-
- gGL.getTexUnit(0)->disable();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
- mScreen.bindTexture();
-
- gGL.begin(LLVertexBuffer::TRIANGLE_STRIP);
- gGL.color4f(1,1,1,1);
- gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
- gGL.vertex2f(-1,-1);
-
- gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
- gGL.vertex2f(-1,1);
-
- gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
- gGL.vertex2f(1,-1);
-
- gGL.texCoord2f(tc2.mV[0], tc2.mV[1]);
- gGL.vertex2f(1,1);
- gGL.end();
-
- gGL.flush();
-
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-
- gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }*/
gGL.flush();
{
LLVertexBuffer::unbind();
- F32 uv0[] =
- {
- tc1.mV[0], tc1.mV[1],
- tc1.mV[0], tc2.mV[1],
- tc2.mV[0], tc1.mV[1],
- tc2.mV[0], tc2.mV[1]
- };
+
tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(),
(F32) gViewerWindow->getWindowDisplayHeight());
@@ -4973,55 +5198,56 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
tc2 /= (F32) res_mod;
}
- F32 uv1[] =
- {
- tc1.mV[0], tc1.mV[1],
- tc1.mV[0], tc2.mV[1],
- tc2.mV[0], tc1.mV[1],
- tc2.mV[0], tc2.mV[1]
- };
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+ LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+ buff->allocateBuffer(3,0,TRUE);
- F32 v[] =
- {
- -1,-1,
- -1,1,
- 1,-1,
- 1,1
- };
+ LLStrider<LLVector3> v;
+ LLStrider<LLVector2> uv1;
+ LLStrider<LLVector2> uv2;
+
+ buff->getVertexStrider(v);
+ buff->getTexCoord0Strider(uv1);
+ buff->getTexCoord1Strider(uv2);
+ uv1[0] = LLVector2(0, 0);
+ uv1[1] = LLVector2(0, 2);
+ uv1[2] = LLVector2(2, 0);
+
+ uv2[0] = LLVector2(0, 0);
+ uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
+ uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
+
+ v[0] = LLVector3(-1,-1,0);
+ v[1] = LLVector3(-1,3,0);
+ v[2] = LLVector3(3,-1,0);
+
+ buff->setBuffer(0);
+
LLGLDisable blend(GL_BLEND);
//tex unit 0
gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
gGL.getTexUnit(0)->bind(&mGlow[1]);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 0, uv0);
gGL.getTexUnit(1)->activate();
gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE);
//tex unit 1
gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
- glClientActiveTextureARB(GL_TEXTURE1_ARB);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 0, uv1);
-
- glVertexPointer(2, GL_FLOAT, 0, v);
-
gGL.getTexUnit(1)->bind(&mScreen);
gGL.getTexUnit(1)->activate();
LLGLEnable multisample(GL_MULTISAMPLE_ARB);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ buff->setBuffer(mask);
+ buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
gGL.getTexUnit(1)->disable();
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
- glClientActiveTextureARB(GL_TEXTURE0_ARB);
gGL.getTexUnit(0)->activate();
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
}
@@ -5038,6 +5264,515 @@ void LLPipeline::renderBloom(BOOL for_snapshot)
}
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index)
+{
+ shader.bind();
+ S32 channel = 0;
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(0,channel);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(1, channel);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(2, channel);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredScreen.bindTexture(3, channel);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE);
+ }
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
+ }
+
+ stop_glerror();
+
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ mDeferredLight[light_index].bindTexture(0, channel);
+ }
+
+ stop_glerror();
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i);
+ stop_glerror();
+ if (channel > -1)
+ {
+ stop_glerror();
+ gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ stop_glerror();
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+ stop_glerror();
+ }
+ }
+
+ stop_glerror();
+
+ F32 mat[64];
+ for (U32 i = 0; i < 16; i++)
+ {
+ mat[i] = mSunShadowMatrix[0].m[i];
+ mat[i+16] = mSunShadowMatrix[1].m[i];
+ mat[i+32] = mSunShadowMatrix[2].m[i];
+ mat[i+48] = mSunShadowMatrix[3].m[i];
+ }
+
+ shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat);
+ shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat);
+
+ stop_glerror();
+
+ channel = shader.enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->enable(channel);
+ cube_map->bind();
+ F64* m = gGLModelView;
+
+
+ F32 mat[] = { m[0], m[1], m[2],
+ m[4], m[5], m[6],
+ m[8], m[9], m[10] };
+
+ shader.uniform3fv("env_mat[0]", 3, mat);
+ shader.uniform3fv("env_mat", 3, mat);
+ }
+ }
+
+ shader.uniform4fv("shadow_clip", 1, mSunClipPlanes.mV);
+ shader.uniform1f("sun_wash", gSavedSettings.getF32("RenderDeferredSunWash"));
+ shader.uniform1f("shadow_noise", gSavedSettings.getF32("RenderShadowNoise"));
+ shader.uniform1f("blur_size", gSavedSettings.getF32("RenderShadowBlurSize"));
+
+ shader.uniform1f("ssao_radius", gSavedSettings.getF32("RenderSSAOScale"));
+ shader.uniform1f("ssao_max_radius", gSavedSettings.getU32("RenderSSAOMaxScale"));
+
+ F32 ssao_factor = gSavedSettings.getF32("RenderSSAOFactor");
+ shader.uniform1f("ssao_factor", ssao_factor);
+ shader.uniform1f("ssao_factor_inv", 1.0/ssao_factor);
+
+ LLVector3 ssao_effect = gSavedSettings.getVector3("RenderSSAOEffect");
+ F32 matrix_diag = (ssao_effect[0] + 2.0*ssao_effect[1])/3.0;
+ F32 matrix_nondiag = (ssao_effect[0] - ssao_effect[1])/3.0;
+ // This matrix scales (proj of color onto <1/rt(3),1/rt(3),1/rt(3)>) by
+ // value factor, and scales remainder by saturation factor
+ F32 ssao_effect_mat[] = { matrix_diag, matrix_nondiag, matrix_nondiag,
+ matrix_nondiag, matrix_diag, matrix_nondiag,
+ matrix_nondiag, matrix_nondiag, matrix_diag};
+ shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat);
+
+ shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+ shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f);
+ shader.uniform1f("alpha_soften", gSavedSettings.getF32("RenderDeferredAlphaSoften"));
+}
+
+void LLPipeline::renderDeferredLighting()
+{
+ if (!sCull)
+ {
+ return;
+ }
+
+ LLGLEnable multisample(GL_MULTISAMPLE_ARB);
+
+ if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+ {
+ gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+ }
+
+ //ati doesn't seem to love actually using the stencil buffer on FBO's
+ LLGLEnable stencil(GL_STENCIL_TEST);
+ glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ gGL.setColorMask(true, true);
+
+ mDeferredLight[0].bindTarget();
+
+ //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+ //draw a cube around every light
+ LLVertexBuffer::unbind();
+
+ glBlendFunc(GL_ONE, GL_ONE);
+ LLGLEnable cull(GL_CULL_FACE);
+ LLGLEnable blend(GL_BLEND);
+
+ glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+
+ F32 vert[] =
+ {
+ -1,1,
+ -1,-3,
+ 3,1,
+ };
+
+ bindDeferredShader(gDeferredSunProgram);
+
+ glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+
+ const U32 slice = 32;
+ F32 offset[slice*3];
+ for (U32 i = 0; i < 4; i++)
+ {
+ for (U32 j = 0; j < 8; j++)
+ {
+ glh::vec3f v;
+ v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
+ v.normalize();
+ inv_trans.mult_matrix_vec(v);
+ v.normalize();
+ offset[(i*8+j)*3+0] = v.v[0];
+ offset[(i*8+j)*3+1] = v.v[2];
+ offset[(i*8+j)*3+2] = v.v[1];
+ }
+ }
+
+ gDeferredSunProgram.uniform3fv("offset", slice, offset);
+ gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight());
+
+ setupHWLights(NULL); //to set mSunDir;
+
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ LLVector4 dir(mSunDir, 0.f);
+
+ glh::vec4f tc(dir.mV);
+ mat.mult_matrix_vec(tc);
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0);
+ glColor3f(1,1,1);
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ unbindDeferredShader(gDeferredSunProgram);
+
+ mDeferredLight[0].flush();
+
+ //blur lightmap
+ mDeferredLight[1].bindTarget();
+
+ //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+ bindDeferredShader(gDeferredBlurLightProgram);
+
+ LLVector3 gauss[32]; // xweight, yweight, offset
+
+ LLVector3 go = gSavedSettings.getVector3("RenderShadowGaussian");
+ U32 kern_length = llclamp(gSavedSettings.getU32("RenderShadowBlurSamples"), (U32) 1, (U32) 16)*2 - 1;
+ F32 blur_size = gSavedSettings.getF32("RenderShadowBlurSize");
+
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = -(kern_length/2.0f) + 0.5f;
+
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
+ /* swap the x=0 position to the start of gauss[] so we can
+ treat it specially as an optimization. */
+ LLVector3 swap;
+ swap = gauss[kern_length/2];
+ gauss[kern_length/2] = gauss[0];
+ gauss[0] = swap;
+ llassert(gauss[0].mV[2] == 0.0f);
+
+ gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ mDeferredLight[1].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ bindDeferredShader(gDeferredBlurLightProgram, 1);
+ mDeferredLight[0].bindTarget();
+
+ gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
+ gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1i("kern_length", kern_length);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_FALSE);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ stop_glerror();
+ }
+ mDeferredLight[0].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
+
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+ glMatrixMode(GL_MODELVIEW);
+ stop_glerror();
+ glPopMatrix();
+ stop_glerror();
+
+ //copy depth and stencil from deferred screen
+ //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
+ // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+
+ mScreen.bindTarget();
+ mScreen.clear(GL_COLOR_BUFFER_BIT);
+
+ bindDeferredShader(gDeferredSoftenProgram);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ unbindDeferredShader(gDeferredSoftenProgram);
+
+ bindDeferredShader(gDeferredLightProgram);
+
+ std::list<LLVector4> fullscreen_lights;
+ std::list<LLVector4> light_colors;
+
+ F32 v[24];
+ glVertexPointer(3, GL_FLOAT, 0, v);
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+ {
+ LLDrawable* drawablep = *iter;
+
+ LLVOVolume* volume = drawablep->getVOVolume();
+ if (!volume)
+ {
+ continue;
+ }
+
+ LLVector3 center = drawablep->getPositionAgent();
+ F32* c = center.mV;
+ F32 s = volume->getLightRadius()*1.5f;
+
+ if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0)
+ {
+ continue;
+ }
+
+ sVisibleLightCount++;
+ glh::vec3f tc(c);
+ mat.mult_matrix_vec(tc);
+
+ LLColor3 col = volume->getLightColor();
+ col *= volume->getLightIntensity();
+
+ //vertex positions are encoded so the 3 bits of their vertex index
+ //correspond to their axis facing, with bit position 3,2,1 matching
+ //axis facing x,y,z, bit set meaning positive facing, bit clear
+ //meaning negative facing
+ v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000
+ v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001
+ v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010
+ v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011
+
+ v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100
+ v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101
+ v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110
+ v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111
+
+ if (LLViewerCamera::getInstance()->getOrigin().mV[0] > c[0] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[0] < c[0] - s - 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[1] > c[1] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[1] < c[1] - s - 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[2] > c[2] + s + 0.2f ||
+ LLViewerCamera::getInstance()->getOrigin().mV[2] < c[2] - s - 0.2f)
+ { //draw box if camera is outside box
+ glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
+ glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(LLViewerCamera::getInstance(), center));
+ }
+ else
+ {
+ fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s));
+ light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f));
+ }
+ }
+ }
+
+ unbindDeferredShader(gDeferredLightProgram);
+
+ if (!fullscreen_lights.empty())
+ {
+ bindDeferredShader(gDeferredMultiLightProgram);
+ LLGLDepthTest depth(GL_FALSE);
+
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ U32 count = 0;
+
+ LLVector4 light[16];
+ LLVector4 col[16];
+
+ glVertexPointer(2, GL_FLOAT, 0, vert);
+
+ while (!fullscreen_lights.empty())
+ {
+ light[count] = fullscreen_lights.front();
+ fullscreen_lights.pop_front();
+ col[count] = light_colors.front();
+ light_colors.pop_front();
+
+ count++;
+ if (count == 16 || fullscreen_lights.empty())
+ {
+ gDeferredMultiLightProgram.uniform1i("light_count", count);
+ gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light);
+ gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col);
+ gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col);
+ count = 0;
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ }
+ }
+
+
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ unbindDeferredShader(gDeferredMultiLightProgram);
+ }
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ { //render non-deferred geometry
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable stencil(GL_STENCIL_TEST);
+
+ U32 render_mask = mRenderTypeMask;
+ mRenderTypeMask = mRenderTypeMask &
+ ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_ALPHA) |
+ (1 << LLPipeline::RENDER_TYPE_AVATAR) |
+ (1 << LLPipeline::RENDER_TYPE_WATER) |
+ (1 << LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1 << LLPipeline::RENDER_TYPE_VOLUME) |
+ (1 << LLPipeline::RENDER_TYPE_GLOW) |
+ (1 << LLPipeline::RENDER_TYPE_BUMP));
+
+ renderGeomPostDeferred(*LLViewerCamera::getInstance());
+ mRenderTypeMask = render_mask;
+ }
+
+ mScreen.flush();
+
+}
+
+void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
+{
+ stop_glerror();
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ for (U32 i = 0; i < 4; i++)
+ {
+ if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1)
+ {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
+ }
+ }
+ shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE);
+
+ S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ if (channel > -1)
+ {
+ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
+ if (cube_map)
+ {
+ cube_map->disable();
+ }
+ }
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->activate();
+ shader.unbind();
+}
+
inline float sgn(float a)
{
if (a > 0.0F) return (1.0F);
@@ -5049,6 +5784,16 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
{
+ LLVOAvatar* agent = gAgent.getAvatarObject();
+ if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
+ {
+ agent = NULL;
+ }
+
+ if (agent)
+ {
+ agent->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
+ }
LLVertexBuffer::unbind();
LLGLState::checkStates();
@@ -5060,6 +5805,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLPipeline::sReflectionRender = TRUE;
S32 occlusion = LLPipeline::sUseOcclusion;
LLPipeline::sUseOcclusion = llmin(occlusion, 1);
+
U32 type_mask = gPipeline.mRenderTypeMask;
glh::matrix4f projection = glh_get_current_projection();
@@ -5127,15 +5873,15 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
//initial sky pass (no user clip plane)
{ //mask out everything but the sky
U32 tmp = mRenderTypeMask;
- mRenderTypeMask &= ((1 << LLPipeline::RENDER_TYPE_SKY) |
- (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
(1 << LLPipeline::RENDER_TYPE_WL_SKY));
-
static LLCullResult result;
updateCull(camera, result);
stateSort(camera, result);
+ mRenderTypeMask = tmp & ((1 << LLPipeline::RENDER_TYPE_SKY) |
+ (1 << LLPipeline::RENDER_TYPE_CLOUDS) |
+ (1 << LLPipeline::RENDER_TYPE_WL_SKY));
renderGeom(camera, TRUE);
-
mRenderTypeMask = tmp;
}
@@ -5227,6 +5973,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
LLRenderTarget::unbindTarget();
+
LLPipeline::sReflectionRender = FALSE;
if (!LLRenderTarget::sUseFBO)
@@ -5245,9 +5992,424 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLGLState::checkStates();
LLGLState::checkTextureChannels();
LLGLState::checkClientArrays();
+
+ if (agent)
+ {
+ agent->updateAttachmentVisibility(gAgent.getCameraMode());
+ }
}
}
+glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
+{
+ glh::matrix4f ret;
+
+ LLVector3 dirN;
+ LLVector3 upN;
+ LLVector3 lftN;
+
+ lftN = dir % up;
+ lftN.normVec();
+
+ upN = lftN % dir;
+ upN.normVec();
+
+ dirN = dir;
+ dirN.normVec();
+
+
+ ret.m[ 0] = lftN[0];
+ ret.m[ 1] = upN[0];
+ ret.m[ 2] = -dirN[0];
+ ret.m[ 3] = 0.f;
+
+ ret.m[ 4] = lftN[1];
+ ret.m[ 5] = upN[1];
+ ret.m[ 6] = -dirN[1];
+ ret.m[ 7] = 0.f;
+
+ ret.m[ 8] = lftN[2];
+ ret.m[ 9] = upN[2];
+ ret.m[10] = -dirN[2];
+ ret.m[11] = 0.f;
+
+ ret.m[12] = -(lftN*pos);
+ ret.m[13] = -(upN*pos);
+ ret.m[14] = dirN*pos;
+ ret.m[15] = 1.f;
+
+ return ret;
+}
+
+glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
+{
+ glh::matrix4f ret;
+ ret.m[ 0] = 2/(max[0]-min[0]);
+ ret.m[ 4] = 0;
+ ret.m[ 8] = 0;
+ ret.m[12] = -(max[0]+min[0])/(max[0]-min[0]);
+
+ ret.m[ 1] = 0;
+ ret.m[ 5] = 2/(max[1]-min[1]);
+ ret.m[ 9] = 0;
+ ret.m[13] = -(max[1]+min[1])/(max[1]-min[1]);
+
+ ret.m[ 2] = 0;
+ ret.m[ 6] = 0;
+ ret.m[10] = 2/(max[2]-min[2]);
+ ret.m[14] = -(max[2]+min[2])/(max[2]-min[2]);
+
+ ret.m[ 3] = 0;
+ ret.m[ 7] = 0;
+ ret.m[11] = 0;
+ ret.m[15] = 1;
+
+ return ret;
+}
+
+void LLPipeline::generateSunShadow(LLCamera& camera)
+{
+
+ if (!sRenderDeferred)
+ {
+ return;
+ }
+
+ //temporary hack to disable shadows but keep local lights
+ static BOOL clear = TRUE;
+ BOOL gen_shadow = gSavedSettings.getBOOL("RenderDeferredSunShadow");
+ if (!gen_shadow)
+ {
+ if (clear)
+ {
+ clear = FALSE;
+ for (U32 i = 0; i < 4; i++)
+ {
+ mSunShadow[i].bindTarget();
+ mSunShadow[i].clear();
+ mSunShadow[i].flush();
+ }
+ }
+ return;
+ }
+ clear = TRUE;
+
+ gGL.setColorMask(false, false);
+
+ //get sun view matrix
+
+ F32 range = 128.f;
+
+ //store current projection/modelview matrix
+ glh::matrix4f saved_proj = glh_get_current_projection();
+ glh::matrix4f saved_view = glh_get_current_modelview();
+ glh::matrix4f inv_view = saved_view.inverse();
+
+ glh::matrix4f view[4];
+ glh::matrix4f proj[4];
+ LLVector3 up;
+
+ //clip contains parallel split distances for 3 splits
+ LLVector3 clip = gSavedSettings.getVector3("RenderShadowClipPlanes");
+
+ //far clip on last split is minimum of camera view distance and 128
+ mSunClipPlanes = LLVector4(clip, clip.mV[2] * clip.mV[2]/clip.mV[1]);
+
+ const LLPickInfo& pick_info = gViewerWindow->getLastPick();
+
+ if (!pick_info.mPosGlobal.isExactlyZero())
+ { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object
+ F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec();
+ mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]);
+ }
+
+ // convenience array of 4 near clip plane distances
+ F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] };
+
+ //currently used for amount to extrude frusta corners for constructing shadow frusta
+ LLVector3 n = gSavedSettings.getVector3("RenderShadowNearDist");
+ F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ //restore render matrices
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+
+ //get center of far clip plane (for point of interest later)
+ LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range;
+
+ LLVector3 eye = camera.getOrigin();
+
+ //camera used for shadow cull/render
+ LLCamera shadow_cam;
+
+ // perspective shadow map
+ glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space)
+ glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space)
+
+ LLVector3 lightDir = -mSunDir;
+ glh::vec3f light_dir(lightDir.mV);
+
+ //create light space camera matrix
+ LLVector3 at;
+ F32 dl = camera.getLeftAxis() * lightDir;
+ F32 du = camera.getUpAxis() * lightDir;
+
+ //choose an at axis such that up will be most aligned with lightDir
+ if (dl*dl < du*du)
+ {
+ at = lightDir%camera.getLeftAxis();
+ }
+ else
+ {
+ at = lightDir%camera.getUpAxis();
+ }
+
+ if (at * camera.getAtAxis() < 0)
+ {
+ at = -at;
+ }
+
+ LLVector3 left = lightDir%at;
+ up = left%lightDir;
+ up.normVec();
+
+ //create world space camera frustum for this split
+ shadow_cam = camera;
+ shadow_cam.setFar(16.f);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam);
+
+ LLVector3* frust = shadow_cam.mAgentFrustum;
+
+ LLVector3 pn = shadow_cam.getAtAxis();
+
+ LLVector3 frust_center;
+
+ LLVector3 min, max;
+
+ //construct 8 corners of split frustum section
+ for (U32 i = 0; i < 4; i++)
+ {
+ LLVector3 delta = frust[i+4]-eye;
+ delta.normVec();
+ F32 dp = delta*pn;
+ frust[i] = eye + (delta*dist[j])/dp;
+ frust[i+4] = eye + (delta*dist[j+1])/dp;
+ frust_center += frust[i] + frust[i+4];
+ }
+
+ //get frustum center
+ frust_center /= 8.f;
+
+ shadow_cam.calcAgentFrustumPlanes(frust);
+
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowCamera[j] = shadow_cam;
+ }
+
+ if (gPipeline.getVisibleExtents(shadow_cam, min, max))
+ {
+ //no possible shadow receivers
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowExtents[j][0] = LLVector3();
+ mShadowExtents[j][1] = LLVector3();
+ mShadowCamera[j+4] = shadow_cam;
+ }
+
+ continue;
+ }
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ mShadowExtents[j][0] = min;
+ mShadowExtents[j][1] = max;
+ }
+
+ view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up);
+ F32 shadow_dist = nearDist[j];
+
+ for (U32 i = 0; i < 8; i++)
+ {
+ //points in worldspace (wp) and light camera space (p)
+ //that must be included in shadow generation
+ wp[i] = glh::vec3f(frust[i].mV);
+ wp[i+8] = wp[i] - light_dir*shadow_dist;
+ view[j].mult_matrix_vec(wp[i], p[i]);
+ view[j].mult_matrix_vec(wp[i+8], p[i+8]);
+ }
+
+ min = LLVector3(p[0].v);
+ max = LLVector3(p[0].v);
+
+ LLVector3 fmin = min;
+ LLVector3 fmax = max;
+
+ for (U32 i = 1; i < 16; i++)
+ { //find camera space AABB of frustum in light camera space
+ update_min_max(min, max, LLVector3(p[i].v));
+ if (i < 8)
+ {
+ update_min_max(fmin, fmax, LLVector3(p[i].v));
+ }
+ }
+
+ //generate perspective matrix that contains frustum
+ //proj[j] = matrix_perspective(min, max);
+ proj[j] = gl_ortho(min.mV[0], max.mV[0],
+ min.mV[1], max.mV[1],
+ -max.mV[2], -min.mV[2]);
+
+ shadow_cam.setFar(128.f);
+ shadow_cam.setOriginAndLookAt(eye, up, center);
+
+ glh_set_current_modelview(view[j]);
+ glh_set_current_projection(proj[j]);
+
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+
+ proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0],
+ fmin.mV[1], fmax.mV[1],
+ -fmax.mV[2], -fmin.mV[2]);
+
+ //translate and scale to from [-1, 1] to [0, 1]
+ glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
+ 0.f, 0.5f, 0.f, 0.5f,
+ 0.f, 0.f, 0.5f, 0.5f,
+ 0.f, 0.f, 0.f, 1.f);
+
+ glh_set_current_modelview(view[j]);
+ glh_set_current_projection(proj[j]);
+
+ mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
+
+ U32 type_mask = mRenderTypeMask;
+ mRenderTypeMask = type_mask & ((1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_ALPHA) |
+ (1<<LLPipeline::RENDER_TYPE_GRASS) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
+ (1<<LLPipeline::RENDER_TYPE_BUMP) |
+ (1<<LLPipeline::RENDER_TYPE_VOLUME) |
+ (1<<LLPipeline::RENDER_TYPE_AVATAR) |
+ (1<<LLPipeline::RENDER_TYPE_TREE) |
+ (1<<LLPipeline::RENDER_TYPE_TERRAIN) |
+ 0);
+
+ //clip out geometry on the same side of water as the camera
+ static LLCullResult result;
+ S32 occlude = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 1;
+ LLPipeline::sShadowRender = TRUE;
+ //hack to prevent LOD updates from using sun camera origin
+ shadow_cam.setOrigin(camera.getOrigin());
+ updateCull(shadow_cam, result);
+ stateSort(shadow_cam, result);
+
+ if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ {
+ LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
+ mShadowCamera[j+4] = shadow_cam;
+ }
+
+ LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER);
+
+ stop_glerror();
+
+ mSunShadow[j].bindTarget();
+ mSunShadow[j].getViewport(gGLViewport);
+
+ {
+ LLGLDepthTest depth(GL_TRUE);
+ mSunShadow[j].clear();
+ }
+
+ U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP };
+ LLGLEnable cull(GL_CULL_FACE);
+
+ //generate sun shadow map
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(proj[j].m);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(view[j].m);
+
+ stop_glerror();
+ gGLLastMatrix = NULL;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ glColor4f(1,1,1,1);
+
+ glCullFace(GL_FRONT);
+
+ stop_glerror();
+
+ gGL.setColorMask(false, false);
+
+ gDeferredShadowProgram.bind();
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE);
+ LLGLDisable test(GL_ALPHA_TEST);
+ gGL.getTexUnit(0)->disable();
+ for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
+ {
+ renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE);
+ }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA);
+ LLGLEnable test(GL_ALPHA_TEST);
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
+ renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
+ glColor4f(1,1,1,1);
+ renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ }
+
+ gDeferredShadowProgram.unbind();
+
+ renderGeomShadow(shadow_cam);
+
+ gGL.setColorMask(true, true);
+
+ glCullFace(GL_BACK);
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = FALSE;
+ mRenderTypeMask = type_mask;
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ gGLLastMatrix = NULL;
+
+ mSunShadow[j].flush();
+ }
+
+ if (!gSavedSettings.getBOOL("CameraOffset"))
+ {
+ glh_set_current_modelview(saved_view);
+ glh_set_current_projection(saved_proj);
+ }
+ else
+ {
+ glh_set_current_modelview(view[1]);
+ glh_set_current_projection(proj[1]);
+ glLoadMatrixf(view[1].m);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(proj[1].m);
+ glMatrixMode(GL_MODELVIEW);
+ }
+ gGL.setColorMask(true, false);
+}
+
void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture)
{
for (LLCullResult::sg_list_t::iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
@@ -5265,6 +6427,10 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu
void LLPipeline::generateImpostor(LLVOAvatar* avatar)
{
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
+
static LLCullResult result;
result.clear();
grabReferences(result);
@@ -5290,6 +6456,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
(1<<LLPipeline::RENDER_TYPE_BUMP) |
(1<<LLPipeline::RENDER_TYPE_GRASS) |
(1<<LLPipeline::RENDER_TYPE_SIMPLE) |
+ (1<<LLPipeline::RENDER_TYPE_FULLBRIGHT) |
(1<<LLPipeline::RENDER_TYPE_ALPHA) |
(1<<LLPipeline::RENDER_TYPE_INVISIBLE);
}
@@ -5300,7 +6467,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
S32 occlusion = sUseOcclusion;
sUseOcclusion = 0;
- sReflectionRender = TRUE;
+ sReflectionRender = sRenderDeferred ? FALSE : TRUE;
sImpostorRender = TRUE;
markVisible(avatar->mDrawable, *LLViewerCamera::getInstance());
@@ -5377,10 +6544,17 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() ||
resY != avatar->mImpostor.getHeight())
{
- avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE);
+ if (LLPipeline::sRenderDeferred)
+ {
+ avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE);
+ addDeferredAttachments(avatar->mImpostor);
+ }
+ else
+ {
+ avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE);
+ }
gGL.getTexUnit(0)->bind(&avatar->mImpostor);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
@@ -5388,8 +6562,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
LLGLEnable scissor(GL_SCISSOR_TEST);
glScissor(0, 0, resX, resY);
avatar->mImpostor.bindTarget();
- avatar->mImpostor.getViewport(gGLViewport);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ avatar->mImpostor.clear();
}
LLGLEnable stencil(GL_STENCIL_TEST);
@@ -5397,11 +6570,20 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- renderGeom(camera);
+ if (LLPipeline::sRenderDeferred)
+ {
+ stop_glerror();
+ renderGeomDeferred(camera);
+ }
+ else
+ {
+ renderGeom(camera);
+ }
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_EQUAL, 1, 0xFFFFFF);
+ if (!sRenderDeferred || muted)
{
LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f;
LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f;
@@ -5432,7 +6614,6 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
gGL.end();
gGL.flush();
-
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
@@ -5454,6 +6635,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
avatar->mNeedsImpostorUpdate = FALSE;
avatar->cacheImpostorValues();
+
+ LLVertexBuffer::unbind();
+ LLGLState::checkStates();
+ LLGLState::checkTextureChannels();
+ LLGLState::checkClientArrays();
}
BOOL LLPipeline::hasRenderBatches(const U32 type) const