359 lines
8.9 KiB
C++
359 lines
8.9 KiB
C++
/**
|
|
* @file lldrawpoolalpha.cpp
|
|
* @brief LLDrawPoolAlpha class implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2002-2007, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlife.com/developers/opensource/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at http://secondlife.com/developers/opensource/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "lldrawpoolalpha.h"
|
|
|
|
#include "llglheaders.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llcriticaldamp.h"
|
|
#include "llfasttimer.h"
|
|
|
|
#include "llcubemap.h"
|
|
#include "llsky.h"
|
|
#include "llagent.h"
|
|
#include "lldrawable.h"
|
|
#include "llface.h"
|
|
#include "llviewercamera.h"
|
|
#include "llviewerimagelist.h" // For debugging
|
|
#include "llviewerobjectlist.h" // For debugging
|
|
#include "llviewerwindow.h"
|
|
#include "pipeline.h"
|
|
#include "llviewerregion.h"
|
|
#include "llglslshader.h"
|
|
|
|
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
|
|
|
|
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
|
|
LLRenderPass(type)
|
|
{
|
|
|
|
}
|
|
|
|
LLDrawPoolAlphaPostWater::LLDrawPoolAlphaPostWater()
|
|
: LLDrawPoolAlpha(POOL_ALPHA_POST_WATER)
|
|
{
|
|
}
|
|
|
|
LLDrawPoolAlpha::~LLDrawPoolAlpha()
|
|
{
|
|
}
|
|
|
|
|
|
void LLDrawPoolAlpha::prerender()
|
|
{
|
|
mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
|
|
}
|
|
|
|
void LLDrawPoolAlpha::beginRenderPass(S32 pass)
|
|
{
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
}
|
|
|
|
void setup_clip_plane(BOOL pre_water)
|
|
{
|
|
F32 height = gAgent.getRegion()->getWaterHeight();
|
|
BOOL above = gCamera->getOrigin().mV[2] > height ? TRUE : FALSE;
|
|
|
|
F64 plane[4];
|
|
|
|
plane[0] = 0;
|
|
plane[1] = 0;
|
|
plane[2] = above == pre_water ? -1.0 : 1.0;
|
|
plane[3] = -plane[2] * height;
|
|
|
|
glClipPlane(GL_CLIP_PLANE0, plane);
|
|
}
|
|
|
|
void LLDrawPoolAlphaPostWater::render(S32 pass)
|
|
{
|
|
LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
|
|
|
|
if (gPipeline.hasRenderType(LLDrawPool::POOL_ALPHA))
|
|
{
|
|
LLGLEnable clip(GL_CLIP_PLANE0);
|
|
setup_clip_plane(FALSE);
|
|
LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater);
|
|
}
|
|
else
|
|
{
|
|
LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater);
|
|
}
|
|
}
|
|
|
|
void LLDrawPoolAlpha::render(S32 pass)
|
|
{
|
|
LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA);
|
|
|
|
LLGLEnable clip(GL_CLIP_PLANE0);
|
|
setup_clip_plane(TRUE);
|
|
render(gPipeline.mAlphaGroups);
|
|
}
|
|
|
|
void LLDrawPoolAlpha::render(std::vector<LLSpatialGroup*>& groups)
|
|
{
|
|
LLGLDepthTest gls_depth(GL_TRUE);
|
|
LLGLSPipelineAlpha gls_pipeline_alpha;
|
|
|
|
gPipeline.enableLightsDynamic(1.f);
|
|
renderAlpha(getVertexDataMask(), groups);
|
|
|
|
if (sShowDebugAlpha)
|
|
{
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
|
|
glColor4f(1,0,0,1);
|
|
LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f);
|
|
LLViewerImage::sSmokeImagep->bind();
|
|
renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX |
|
|
LLVertexBuffer::MAP_TEXCOORD, groups);
|
|
}
|
|
}
|
|
|
|
void LLDrawPoolAlpha::renderAlpha(U32 mask, std::vector<LLSpatialGroup*>& groups)
|
|
{
|
|
#if !LL_RELEASE_FOR_DOWNLOAD
|
|
LLGLState::checkClientArrays(mask);
|
|
#endif
|
|
|
|
LLSpatialBridge* last_bridge = NULL;
|
|
LLSpatialPartition* last_part = NULL;
|
|
glPushMatrix();
|
|
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
|
|
|
|
for (std::vector<LLSpatialGroup*>::iterator i = groups.begin(); i != groups.end(); ++i)
|
|
{
|
|
LLSpatialGroup* group = *i;
|
|
if (group->mSpatialPartition->mRenderByGroup &&
|
|
!group->isDead())
|
|
{
|
|
LLSpatialPartition* part = group->mSpatialPartition;
|
|
if (part != last_part)
|
|
{
|
|
LLSpatialBridge* bridge = part->asBridge();
|
|
if (bridge != last_bridge)
|
|
{
|
|
glPopMatrix();
|
|
glPushMatrix();
|
|
if (bridge)
|
|
{
|
|
glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
|
|
}
|
|
last_bridge = bridge;
|
|
}
|
|
|
|
// if (!last_part || part->mDepthMask != last_part->mDepthMask)
|
|
// {
|
|
// glDepthMask(part->mDepthMask);
|
|
// }
|
|
last_part = part;
|
|
}
|
|
|
|
renderGroupAlpha(group,LLRenderPass::PASS_ALPHA,mask,TRUE);
|
|
}
|
|
}
|
|
|
|
glPopMatrix();
|
|
}
|
|
|
|
void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask, std::vector<LLSpatialGroup*>& groups)
|
|
{
|
|
#if !LL_RELEASE_FOR_DOWNLOAD
|
|
LLGLState::checkClientArrays(mask);
|
|
#endif
|
|
|
|
LLSpatialBridge* last_bridge = NULL;
|
|
LLSpatialPartition* last_part = NULL;
|
|
glPushMatrix();
|
|
|
|
for (std::vector<LLSpatialGroup*>::iterator i = groups.begin(); i != groups.end(); ++i)
|
|
{
|
|
LLSpatialGroup* group = *i;
|
|
if (group->mSpatialPartition->mRenderByGroup &&
|
|
!group->isDead())
|
|
{
|
|
LLSpatialPartition* part = group->mSpatialPartition;
|
|
if (part != last_part)
|
|
{
|
|
LLSpatialBridge* bridge = part->asBridge();
|
|
if (bridge != last_bridge)
|
|
{
|
|
glPopMatrix();
|
|
glPushMatrix();
|
|
if (bridge)
|
|
{
|
|
glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix);
|
|
}
|
|
last_bridge = bridge;
|
|
}
|
|
|
|
last_part = part;
|
|
}
|
|
|
|
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
|
|
|
|
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
|
|
{
|
|
LLDrawInfo& params = **k;
|
|
|
|
if (params.mParticle)
|
|
{
|
|
continue;
|
|
}
|
|
params.mVertexBuffer->setBuffer(mask);
|
|
U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
|
|
glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount,
|
|
GL_UNSIGNED_INT, indices_pointer+params.mOffset);
|
|
|
|
addIndicesDrawn(params.mCount);
|
|
}
|
|
}
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
|
|
void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
|
|
{
|
|
BOOL light_enabled = TRUE;
|
|
|
|
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
|
|
|
|
U32 prim_type = GL_TRIANGLES;
|
|
|
|
//F32 width = (F32) gViewerWindow->getWindowDisplayWidth();
|
|
|
|
//F32 view = gCamera->getView();
|
|
|
|
if (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CLOUDS)
|
|
{
|
|
glAlphaFunc(GL_GREATER, 0.f);
|
|
}
|
|
else
|
|
{
|
|
glAlphaFunc(GL_GREATER, 0.01f);
|
|
}
|
|
|
|
/*LLGLEnable point_sprite(GL_POINT_SPRITE_ARB);
|
|
|
|
if (gGLManager.mHasPointParameters)
|
|
{
|
|
glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
|
|
glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 0.f);
|
|
glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, width*16.f);
|
|
glPointSize(width/(view*view));
|
|
}*/
|
|
|
|
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
|
|
{
|
|
LLDrawInfo& params = **k;
|
|
if (texture && params.mTexture.notNull())
|
|
{
|
|
params.mTexture->bind();
|
|
params.mTexture->addTextureStats(params.mVSize);
|
|
if (params.mTextureMatrix)
|
|
{
|
|
glMatrixMode(GL_TEXTURE);
|
|
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
|
}
|
|
}
|
|
|
|
if (params.mFullbright)
|
|
{
|
|
if (light_enabled)
|
|
{
|
|
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
|
|
light_enabled = FALSE;
|
|
if (LLPipeline::sRenderGlow)
|
|
{
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
}
|
|
}
|
|
}
|
|
else if (!light_enabled)
|
|
{
|
|
gPipeline.enableLightsDynamic(1.f);
|
|
light_enabled = TRUE;
|
|
if (LLPipeline::sRenderGlow)
|
|
{
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
|
}
|
|
}
|
|
|
|
/*if (params.mParticle)
|
|
{
|
|
F32 size = params.mPartSize;
|
|
size *= size;
|
|
float param[] = { 0, 0, 0.01f/size*view*view };
|
|
prim_type = GL_POINTS;
|
|
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param);
|
|
}
|
|
else*/
|
|
{
|
|
prim_type = GL_TRIANGLES;
|
|
}
|
|
|
|
params.mVertexBuffer->setBuffer(mask);
|
|
U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer();
|
|
glDrawRangeElements(prim_type, params.mStart, params.mEnd, params.mCount,
|
|
GL_UNSIGNED_INT, indices_pointer+params.mOffset);
|
|
|
|
addIndicesDrawn(params.mCount);
|
|
|
|
if (params.mTextureMatrix && texture && params.mTexture.notNull())
|
|
{
|
|
glLoadIdentity();
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
if (!light_enabled)
|
|
{
|
|
gPipeline.enableLightsDynamic(1.f);
|
|
|
|
if (LLPipeline::sRenderGlow)
|
|
{
|
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
|
|
}
|
|
}
|
|
|
|
/*glPointSize(1.f);
|
|
|
|
if (gGLManager.mHasPointParameters)
|
|
{
|
|
float param[] = {1, 0, 0 };
|
|
glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param);
|
|
}*/
|
|
}
|