summaryrefslogtreecommitdiff
path: root/indra/newview/lldrawpoolterrain.cpp
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
committerJames Cook <james@lindenlab.com>2007-01-02 08:33:20 +0000
commit420b91db29485df39fd6e724e782c449158811cb (patch)
treeb471a94563af914d3ed3edd3e856d21cb1b69945 /indra/newview/lldrawpoolterrain.cpp
Print done when done.
Diffstat (limited to 'indra/newview/lldrawpoolterrain.cpp')
-rw-r--r--indra/newview/lldrawpoolterrain.cpp1091
1 files changed, 1091 insertions, 0 deletions
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
new file mode 100644
index 0000000000..3e51e01699
--- /dev/null
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -0,0 +1,1091 @@
+/**
+ * @file lldrawpoolterrain.cpp
+ * @brief LLDrawPoolTerrain class implementation
+ *
+ * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldrawpoolterrain.h"
+
+#include "llfasttimer.h"
+
+#include "llagent.h"
+#include "llagparray.h"
+#include "llviewercontrol.h"
+#include "lldrawable.h"
+#include "llface.h"
+#include "llsky.h"
+#include "llsurface.h"
+#include "llsurfacepatch.h"
+#include "llviewerregion.h"
+#include "llvlcomposition.h"
+#include "llviewerparcelmgr.h" // for gRenderParcelOwnership
+#include "llviewerparceloverlay.h"
+#include "llvosurfacepatch.h"
+#include "llviewercamera.h"
+#include "llviewerimagelist.h" // To get alpha gradients
+#include "llworld.h"
+#include "pipeline.h"
+
+const F32 DETAIL_SCALE = 1.f/16.f;
+int DebugDetailMap = 0;
+
+S32 LLDrawPoolTerrain::sDetailMode = 1;
+F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE;
+
+LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) :
+ LLDrawPool(POOL_TERRAIN, DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK | DATA_TEX_COORDS1_MASK, DATA_SIMPLE_NIL_MASK),
+ mTexturep(texturep)
+{
+ // Hack!
+ sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
+ sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
+ mAlphaRampImagep = gImageList.getImageFromUUID(LLUUID(gViewerArt.getString("alpha_gradient.tga")),
+ TRUE, TRUE, GL_ALPHA8, GL_ALPHA);
+ mAlphaRampImagep->bind(0);
+ mAlphaRampImagep->setClamp(TRUE, TRUE);
+
+ m2DAlphaRampImagep = gImageList.getImageFromUUID(LLUUID(gViewerArt.getString("alpha_gradient_2d.tga")),
+ TRUE, TRUE, GL_ALPHA8, GL_ALPHA);
+ m2DAlphaRampImagep->bind(0);
+ m2DAlphaRampImagep->setClamp(TRUE, TRUE);
+
+ mTexturep->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+}
+
+LLDrawPoolTerrain::~LLDrawPoolTerrain()
+{
+ llassert( gPipeline.findPool( getType(), getTexture() ) == NULL );
+}
+
+
+LLDrawPool *LLDrawPoolTerrain::instancePool()
+{
+ return new LLDrawPoolTerrain(mTexturep);
+}
+
+
+void LLDrawPoolTerrain::prerender()
+{
+#if 0 // 1.9.2
+ mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT);
+#endif
+}
+
+void LLDrawPoolTerrain::render(S32 pass)
+{
+ LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN);
+
+ if (mDrawFace.empty())
+ {
+ return;
+ }
+
+ if (!gGLManager.mHasMultitexture)
+ {
+ // No mulititexture, render simple land.
+ renderSimple(); // Render without multitexture
+ return;
+ }
+ // Render simplified land if video card can't do sufficient multitexturing
+ if (!gGLManager.mHasARBEnvCombine || (gGLManager.mNumTextureUnits < 2))
+ {
+ renderSimple(); // Render without multitexture
+ return;
+ }
+
+ LLGLSPipeline gls;
+ LLOverrideFaceColor override(this, 1.f, 1.f, 1.f, 1.f);
+
+ if (mVertexShaderLevel > 0)
+ {
+ gPipeline.enableLightsDynamic(1.f);
+ renderFull4TUShader();
+ }
+ else
+ {
+ gPipeline.enableLightsStatic(1.f);
+ switch (sDetailMode)
+ {
+ case 0:
+ renderSimple();
+ break;
+ default:
+ if (gGLManager.mNumTextureUnits < 4)
+ {
+ renderFull2TU();
+ }
+ else
+ {
+ renderFull4TU();
+ }
+ break;
+ }
+ }
+
+ // Special-case for land ownership feedback
+ if (gSavedSettings.getBOOL("ShowParcelOwners"))
+ {
+ gPipeline.disableLights();
+ if ((mVertexShaderLevel > 0))
+ {
+ gPipeline.mHighlightProgram.bind();
+ gPipeline.mHighlightProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR,1,1,1,1);
+ renderOwnership();
+ gPipeline.mTerrainProgram.bind();
+ }
+ else
+ {
+ renderOwnership();
+ }
+ }
+}
+
+
+void LLDrawPoolTerrain::renderFull4TUShader()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+ if (gPipeline.getLightingDetail() >= 2)
+ {
+ glEnableClientState(GL_COLOR_ARRAY);
+ bindGLColorPointer();
+ }
+
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+
+ // Hack! Get the region that this draw pool is rendering from!
+ LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
+ LLVLComposition *compp = regionp->getComposition();
+ for (S32 i = 0; i < 4; i++)
+ {
+ compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+ }
+
+ LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+
+ static F32 dp = 0.f;
+ static LLFrameTimer timer;
+ dp += timer.getElapsedTimeAndResetF32();
+
+ LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
+
+ F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
+ F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale;
+
+ LLVector4 tp0, tp1;
+
+ tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x);
+ tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y);
+
+ //----------------------------------------------------------------------------
+ // Pass 1/1
+
+ //
+ // Stage 0: detail texture 0
+ //
+
+ S32 detailTex0 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0);
+ S32 detailTex1 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1);
+ S32 rampTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP);
+ S32 scatterTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
+
+ LLViewerImage::bindTexture(detail_texture0p,detailTex0);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ //
+ // Stage 1: Generate alpha ramp for detail0/detail1 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,rampTex);
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ //
+ // Stage 2: Interpolate detail1 with existing based on ramp
+ //
+ LLViewerImage::bindTexture(detail_texture1p,detailTex1);
+
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ // Stage 4: Haze
+ LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
+
+ //
+ // Stage 3: Modulate with primary color for lighting
+ //
+ //LLViewerImage::bindTexture(detail_texture1p,3); // bind any texture
+ //glEnable(GL_TEXTURE_2D); // Texture unit 3
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+ glActiveTextureARB(GL_TEXTURE3_ARB);
+ // GL_BLEND disabled by default
+ drawLoop();
+
+ //----------------------------------------------------------------------------
+ // Second pass
+
+ //
+ // Stage 0: Write detail3 into base
+ //
+ LLViewerImage::bindTexture(detail_texture2p,detailTex0);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ //
+ // Stage 1: Generate alpha ramp for detail2/detail3 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,rampTex);
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ bindGLTexCoordPointer(1);
+
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-2.f, 0.f, 0.f);
+
+ //
+ // Stage 2: Interpolate detail2 with existing based on ramp
+ //
+ LLViewerImage::bindTexture(detail_texture3p,detailTex1);
+
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ //
+ // Stage 3: Generate alpha ramp for detail1/detail2 transition
+ //
+ //LLViewerImage::bindTexture(m2DAlphaRampImagep,3);
+
+ //glEnable(GL_TEXTURE_2D); // Texture unit 3
+
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+ glActiveTextureARB(GL_TEXTURE3_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-1.f, 0.f, 0.f);
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ drawLoop();
+ }
+
+ // Disable multitexture
+ gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
+ gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP);
+ gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0);
+ gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1);
+
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+ glActiveTextureARB(GL_TEXTURE3_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore blend state
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ //----------------------------------------------------------------------------
+ // Restore Texture Unit 0 defaults
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glEnable(GL_TEXTURE_2D);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore non Texture Unit specific defaults
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+void LLDrawPoolTerrain::renderFull4TU()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+
+ // Hack! Get the region that this draw pool is rendering from!
+ LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
+ LLVLComposition *compp = regionp->getComposition();
+ for (S32 i = 0; i < 4; i++)
+ {
+ compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+ }
+
+ LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+
+ LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
+ F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
+ F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale;
+
+ LLVector4 tp0, tp1;
+
+ tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x);
+ tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y);
+
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+
+ //----------------------------------------------------------------------------
+ // Pass 1/1
+
+ //
+ // Stage 0: detail texture 0
+ //
+ LLViewerImage::bindTexture(detail_texture0p,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+
+ //
+ // Stage 1: Generate alpha ramp for detail0/detail1 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
+
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Care about alpha only
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ //
+ // Stage 2: Interpolate detail1 with existing based on ramp
+ //
+ LLViewerImage::bindTexture(detail_texture1p,2);
+ glEnable(GL_TEXTURE_2D); // Texture unit 2
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
+
+ //
+ // Stage 3: Modulate with primary (vertex) color for lighting
+ //
+ LLViewerImage::bindTexture(detail_texture1p,3); // bind any texture
+ glEnable(GL_TEXTURE_2D); // Texture unit 3
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+
+ // Set alpha texture and do lighting modulation
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+
+ // GL_BLEND disabled by default
+ drawLoop();
+
+ //----------------------------------------------------------------------------
+ // Second pass
+
+ // Stage 0: Write detail3 into base
+ //
+ LLViewerImage::bindTexture(detail_texture3p,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+
+
+ //
+ // Stage 1: Generate alpha ramp for detail2/detail3 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,1);
+
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-2.f, 0.f, 0.f);
+
+ // Care about alpha only
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+
+ //
+ // Stage 2: Interpolate detail2 with existing based on ramp
+ //
+ LLViewerImage::bindTexture(detail_texture2p,2);
+ glEnable(GL_TEXTURE_2D); // Texture unit 2
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_ONE_MINUS_SRC_ALPHA);
+
+
+ //
+ // Stage 3: Generate alpha ramp for detail1/detail2 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,3);
+
+ glEnable(GL_TEXTURE_2D); // Texture unit 3
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-1.f, 0.f, 0.f);
+
+ // Set alpha texture and do lighting modulation
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ drawLoop();
+ }
+
+ // Disable multitexture
+ LLImageGL::unbindTexture(3, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE3_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D); // Texture unit 3
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ LLImageGL::unbindTexture(2, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D); // Texture unit 2
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D); // Texture unit 1
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore blend state
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ //----------------------------------------------------------------------------
+ // Restore Texture Unit 0 defaults
+
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore non Texture Unit specific defaults
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+void LLDrawPoolTerrain::renderFull2TU()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+
+ // Hack! Get the region that this draw pool is rendering from!
+ LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
+ LLVLComposition *compp = regionp->getComposition();
+ for (S32 i = 0; i < 4; i++)
+ {
+ compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN);
+ compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+ }
+
+ LLViewerImage *detail_texture0p = compp->mDetailTextures[0];
+ LLViewerImage *detail_texture1p = compp->mDetailTextures[1];
+ LLViewerImage *detail_texture2p = compp->mDetailTextures[2];
+ LLViewerImage *detail_texture3p = compp->mDetailTextures[3];
+
+ LLVector3d region_origin_global = gAgent.getRegion()->getOriginGlobal();
+ F32 offset_x = (F32)fmod(region_origin_global.mdV[VX], 1.0/(F64)sDetailScale)*sDetailScale;
+ F32 offset_y = (F32)fmod(region_origin_global.mdV[VY], 1.0/(F64)sDetailScale)*sDetailScale;
+
+ LLVector4 tp0, tp1;
+
+ tp0.setVec(sDetailScale, 0.0f, 0.0f, offset_x);
+ tp1.setVec(0.0f, sDetailScale, 0.0f, offset_y);
+
+ glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+
+ //----------------------------------------------------------------------------
+ // Pass 1/4
+
+ //
+ // Stage 0: Render detail 0 into base
+ //
+ LLViewerImage::bindTexture(detail_texture0p,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+
+ drawLoop();
+
+ //----------------------------------------------------------------------------
+ // Pass 2/4
+
+ //
+ // Stage 0: Generate alpha ramp for detail0/detail1 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Care about alpha only
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+
+ //
+ // Stage 1: Write detail1
+ //
+ LLViewerImage::bindTexture(detail_texture1p,1); // Texture unit 1
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ drawLoop();
+ }
+ //----------------------------------------------------------------------------
+ // Pass 3/4
+
+ //
+ // Stage 0: Generate alpha ramp for detail1/detail2 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-1.f, 0.f, 0.f);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Care about alpha only
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ //
+ // Stage 1: Write detail2
+ //
+
+ LLViewerImage::bindTexture(detail_texture2p,1);
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ drawLoop();
+ }
+
+ //----------------------------------------------------------------------------
+ // Pass 4/4
+
+ //
+ // Stage 0: Generate alpha ramp for detail2/detail3 transition
+ //
+ LLViewerImage::bindTexture(m2DAlphaRampImagep,0);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ // Set the texture matrix
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glTranslatef(-2.f, 0.f, 0.f);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ bindGLTexCoordPointer(1);
+
+ // Care about alpha only
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ // Stage 1: Write detail3
+
+ LLViewerImage::bindTexture(detail_texture3p,1);
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ {
+ LLGLEnable blend(GL_BLEND);
+ drawLoop();
+ }
+
+ // Restore blend state
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ // Disable multitexture
+ LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisable(GL_TEXTURE_2D); // Texture unit 1
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ //----------------------------------------------------------------------------
+ // Restore Texture Unit 0 defaults
+
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore non Texture Unit specific defaults
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+
+void LLDrawPoolTerrain::renderSimple()
+{
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+
+ LLVector4 tp0, tp1;
+
+ //----------------------------------------------------------------------------
+ // Pass 1/1
+
+ // Stage 0: Base terrain texture pass
+ mTexturep->addTextureStats(1024.f*1024.f);
+ mTexturep->bind(0);
+
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glEnable(GL_TEXTURE_2D); // Texture unit 2
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ LLVector3 origin_agent = mDrawFace[0]->getDrawable()->getVObj()->getRegion()->getOriginAgent();
+ F32 tscale = 1.f/256.f;
+ tp0.setVec(tscale, 0.f, 0.0f, -1.f*(origin_agent.mV[0]/256.f));
+ tp1.setVec(0.f, tscale, 0.0f, -1.f*(origin_agent.mV[1]/256.f));
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
+
+ drawLoop();
+
+ //----------------------------------------------------------------------------
+ // Restore Texture Unit 0 defaults
+
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore non Texture Unit specific defaults
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+}
+
+//============================================================================
+
+void LLDrawPoolTerrain::renderOwnership()
+{
+ LLGLSPipelineAlpha gls_pipeline_alpha;
+
+ llassert(!mDrawFace.empty());
+
+ // Each terrain pool is associated with a single region.
+ // We need to peek back into the viewer's data to find out
+ // which ownership overlay texture to use.
+ LLFace *facep = mDrawFace[0];
+ LLDrawable *drawablep = facep->getDrawable();
+ const LLViewerObject *objectp = drawablep->getVObj();
+ const LLVOSurfacePatch *vo_surface_patchp = (LLVOSurfacePatch *)objectp;
+ LLSurfacePatch *surface_patchp = vo_surface_patchp->getPatch();
+ LLSurface *surfacep = surface_patchp->getSurface();
+ LLViewerRegion *regionp = surfacep->getRegion();
+ LLViewerParcelOverlay *overlayp = regionp->getParcelOverlay();
+ LLImageGL *texturep = overlayp->getTexture();
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLTexCoordPointer(0);
+
+ LLViewerImage::bindTexture(texturep);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ // HACK: Because the region is 256 meters wide, but has 257 pixels, the
+ // texture coordinates for pixel 256x256 is not 1,1. This makes the
+ // ownership map not line up with the selection. Fix this with a texture
+ // matrix multiply.
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+
+ const F32 TEXTURE_FUDGE = 257.f / 256.f;
+ glScalef( TEXTURE_FUDGE, TEXTURE_FUDGE, 1.f );
+
+ const U32* index_array = getRawIndices();
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *facep = *iter;
+ facep->renderIndexed(index_array);
+ }
+
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ // Restore non Texture Unit specific defaults
+ glDisableClientState(GL_NORMAL_ARRAY);
+}
+
+
+void LLDrawPoolTerrain::renderForSelect()
+{
+ if (mDrawFace.empty() || !mMemory.count())
+ {
+ return;
+ }
+
+ glEnableClientState ( GL_VERTEX_ARRAY );
+
+ bindGLVertexPointer();
+
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *facep = *iter;
+ if (!facep->getDrawable()->isDead() && (facep->getDrawable()->getVObj()->mGLName))
+ {
+ facep->renderForSelect();
+ }
+ }
+}
+
+void LLDrawPoolTerrain::dirtyTexture(const LLViewerImage *texturep)
+{
+ if (mTexturep == texturep)
+ {
+ for (std::vector<LLFace*>::iterator iter = mReferences.begin();
+ iter != mReferences.end(); iter++)
+ {
+ LLFace *facep = *iter;
+ gPipeline.markTextured(facep->getDrawable());
+ }
+ }
+}
+
+LLViewerImage *LLDrawPoolTerrain::getTexture()
+{
+ return mTexturep;
+}
+
+LLViewerImage *LLDrawPoolTerrain::getDebugTexture()
+{
+ return mTexturep;
+}
+
+
+LLColor3 LLDrawPoolTerrain::getDebugColor() const
+{
+ return LLColor3(0.f, 0.f, 1.f);
+}
+
+S32 LLDrawPoolTerrain::getMaterialAttribIndex()
+{
+ return gPipeline.mTerrainProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR];
+}