summaryrefslogtreecommitdiff
path: root/indra/newview/lldrawpoolwater.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/lldrawpoolwater.cpp
Print done when done.
Diffstat (limited to 'indra/newview/lldrawpoolwater.cpp')
-rw-r--r--indra/newview/lldrawpoolwater.cpp729
1 files changed, 729 insertions, 0 deletions
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
new file mode 100644
index 0000000000..108048efbc
--- /dev/null
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -0,0 +1,729 @@
+/**
+ * @file lldrawpoolwater.cpp
+ * @brief LLDrawPoolWater class implementation
+ *
+ * Copyright (c) 2002-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfeaturemanager.h"
+#include "lldrawpoolwater.h"
+
+#include "llviewercontrol.h"
+#include "lldir.h"
+#include "llerror.h"
+#include "m3math.h"
+
+#include "llagent.h" // for gAgent for getRegion for getWaterHeight
+#include "llagparray.h"
+#include "llcubemap.h"
+#include "lldrawable.h"
+#include "llface.h"
+#include "llsky.h"
+#include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION
+#include "llviewerimagelist.h"
+#include "llviewerregion.h"
+#include "llvosky.h"
+#include "llvowater.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "viewer.h" // gSunTextureID, gMoonTextureID
+
+const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+
+static float sTime;
+
+int nhpo2(int v)
+{
+ int r = 1;
+ while (r < v) {
+ r *= 2;
+ }
+ return r;
+}
+
+static GLuint sScreenTex = 0;
+
+LLDrawPoolWater::LLDrawPoolWater() :
+ LLDrawPool(POOL_WATER, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK)
+{
+ mCleanupUnused = TRUE;
+ mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE);
+ mHBTex[0]->bind();
+ mHBTex[0]->setClamp(TRUE, TRUE);
+
+ mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
+ mHBTex[1]->bind();
+ mHBTex[1]->setClamp(TRUE, TRUE);
+
+ mWaterImagep = gImageList.getImage(WATER_TEST);
+ mWaterNormp = gImageList.getImage(LLUUID(gViewerArt.getString("water_normal.tga")));
+
+ restoreGL();
+}
+
+LLDrawPoolWater::~LLDrawPoolWater()
+{
+}
+
+//static
+void LLDrawPoolWater::restoreGL()
+{
+ if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) >= SHADER_LEVEL_RIPPLE)
+ {
+ //build screen texture
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glGenTextures(1, &sScreenTex);
+ LLGLEnable gl_texture_2d(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, sScreenTex);
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ GLuint resX = nhpo2(viewport[2]);
+ GLuint resY = nhpo2(viewport[3]);
+
+ gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+}
+
+
+LLDrawPool *LLDrawPoolWater::instancePool()
+{
+ llerrs << "Should never be calling instancePool on a water pool!" << llendl;
+ return NULL;
+}
+
+
+void LLDrawPoolWater::prerender()
+{
+#if 1 // 1.9.1
+ mVertexShaderLevel = gSavedSettings.getBOOL("RenderRippleWater") ?
+ gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) : 0;
+#else
+ mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT);
+#endif
+}
+
+extern LLColor4U MAX_WATER_COLOR;
+
+void LLDrawPoolWater::render(S32 pass)
+{
+ LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER);
+ if (mDrawFace.empty())
+ {
+ return;
+ }
+
+ LLGLSPipelineAlpha alphaState;
+
+ if ((mVertexShaderLevel >= SHADER_LEVEL_RIPPLE))
+ {
+ shade();
+ return;
+ }
+
+ if ((mVertexShaderLevel > 0))
+ {
+ renderShaderSimple();
+ return;
+ }
+
+ LLVOSky *voskyp = gSky.mVOSkyp;
+
+ stop_glerror();
+
+ if (!gGLManager.mHasMultitexture)
+ {
+ // Ack! No multitexture! Bail!
+ return;
+ }
+
+ const LLFace* refl_face = voskyp->getReflFace();
+
+ gPipeline.disableLights();
+
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+
+ LLGLDisable cullFace(GL_CULL_FACE);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+ bindGLTexCoordPointer();
+
+ // Set up second pass first
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ mWaterImagep->addTextureStats(1024.f*1024.f);
+ mWaterImagep->bind(1);
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D); // Texture unit 1
+
+ LLVector3 camera_up = gCamera->getUpAxis();
+ F32 up_dot = camera_up * LLVector3::z_axis;
+
+ LLColor4 water_color;
+ if (gCamera->cameraUnderWater())
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.4f);
+ }
+ else
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
+ }
+
+ glColor4fv(water_color.mV);
+
+ // Automatically generate texture coords for detail map
+ glEnable(GL_TEXTURE_GEN_S); //texture unit 1
+ glEnable(GL_TEXTURE_GEN_T); //texture unit 1
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ // Slowly move over time.
+ F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f);
+ F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
+ F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
+
+ 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_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_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ LLGLEnable gls_stencil(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP);
+ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *face = *iter;
+ if (voskyp->isReflFace(face))
+ {
+ continue;
+ }
+ face->bindTexture();
+ face->renderIndexed(getRawIndices());
+ mIndicesDrawn += face->getIndicesCount();
+ }
+
+ // Now, disable texture coord generation on texture state 1
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisable(GL_TEXTURE_2D); // Texture unit 1
+ LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
+ glDisable(GL_TEXTURE_GEN_S); //texture unit 1
+ glDisable(GL_TEXTURE_GEN_T); //texture unit 1
+
+ // Disable texture coordinate and color arrays
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ stop_glerror();
+
+ if (gSky.mVOSkyp->getCubeMap())
+ {
+ gSky.mVOSkyp->getCubeMap()->enable(0);
+ gSky.mVOSkyp->getCubeMap()->bind();
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ LLMatrix4 camera_mat = gCamera->getModelview();
+ LLMatrix4 camera_rot(camera_mat.getMat3());
+ camera_rot.invert();
+
+ glLoadMatrixf((F32 *)camera_rot.mMatrix);
+
+ glMatrixMode(GL_MODELVIEW);
+ LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f, 0.5f*up_dot);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ /*glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
+
+ 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_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);*/
+
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *face = *iter;
+ if (voskyp->isReflFace(face))
+ {
+ //refl_face = face;
+ continue;
+ }
+
+ if (face->getGeomCount() > 0)
+ {
+ face->renderIndexed(getRawIndices());
+ mIndicesDrawn += face->getIndicesCount();
+ }
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ if (gSky.mVOSkyp->getCubeMap())
+ {
+ gSky.mVOSkyp->getCubeMap()->disable();
+ }
+ LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
+ glEnable(GL_TEXTURE_2D);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
+ }
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ if (refl_face)
+ {
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+ renderReflection(refl_face);
+ }
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+}
+
+
+void LLDrawPoolWater::renderShaderSimple()
+{
+ LLVOSky *voskyp = gSky.mVOSkyp;
+
+ stop_glerror();
+
+ if (!gGLManager.mHasMultitexture)
+ {
+ // Ack! No multitexture! Bail!
+ return;
+ }
+
+ const LLFace* refl_face = voskyp->getReflFace();
+
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+
+ LLGLDisable cullFace(GL_CULL_FACE);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+ bindGLTexCoordPointer();
+
+ // Set up second pass first
+ S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP);
+ mWaterImagep->addTextureStats(1024.f*1024.f);
+ mWaterImagep->bind(bumpTex);
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ LLVector3 camera_up = gCamera->getUpAxis();
+ F32 up_dot = camera_up * LLVector3::z_axis;
+
+ LLColor4 water_color;
+ if (gCamera->cameraUnderWater())
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.4f);
+ }
+ else
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
+ }
+
+ glColor4fv(water_color.mV);
+
+ // Automatically generate texture coords for detail map
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glEnable(GL_TEXTURE_GEN_S); //texture unit 1
+ glEnable(GL_TEXTURE_GEN_T); //texture unit 1
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
+
+ // Slowly move over time.
+ F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f);
+ F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
+ F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
+ glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
+ glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+
+ glClearStencil(1);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ LLGLEnable gls_stencil(GL_STENCIL_TEST);
+ glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP);
+ glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
+
+ S32 envTex = -1;
+
+ if (gSky.mVOSkyp->getCubeMap())
+ {
+ envTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ gSky.mVOSkyp->getCubeMap()->bind();
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ LLMatrix4 camera_mat = gCamera->getModelview();
+ LLMatrix4 camera_rot(camera_mat.getMat3());
+ camera_rot.invert();
+
+ glLoadMatrixf((F32 *)camera_rot.mMatrix);
+
+ glMatrixMode(GL_MODELVIEW);
+ }
+
+ S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
+ LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
+
+ S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
+
+ gPipeline.mWaterProgram.bind();
+
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *face = *iter;
+ if (voskyp->isReflFace(face))
+ {
+ continue;
+ }
+ face->bindTexture(diffTex);
+ face->renderIndexed(getRawIndices());
+ mIndicesDrawn += face->getIndicesCount();
+ }
+
+ if (gSky.mVOSkyp->getCubeMap())
+ {
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ }
+
+ // Now, disable texture coord generation on texture state 1
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP);
+ LLImageGL::unbindTexture(bumpTex, GL_TEXTURE_2D);
+
+ glActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisable(GL_TEXTURE_GEN_S); //texture unit 1
+ glDisable(GL_TEXTURE_GEN_T); //texture unit 1
+
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
+
+ // Disable texture coordinate and color arrays
+ LLImageGL::unbindTexture(diffTex, GL_TEXTURE_2D);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ stop_glerror();
+
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glUseProgramObjectARB(0);
+ gPipeline.disableLights();
+
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glEnable(GL_TEXTURE_2D);
+
+ if (refl_face)
+ {
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
+ renderReflection(refl_face);
+ }
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+}
+
+void LLDrawPoolWater::renderReflection(const LLFace* face)
+{
+ LLVOSky *voskyp = gSky.mVOSkyp;
+
+ if (!voskyp)
+ {
+ return;
+ }
+
+ if (!face->getGeomCount())
+ {
+ return;
+ }
+
+ S8 dr = voskyp->getDrawRefl();
+ if (dr < 0)
+ {
+ return;
+ }
+
+ LLGLSNoFog noFog;
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ LLViewerImage::bindTexture(mHBTex[dr]);
+
+ LLOverrideFaceColor override(this, face->getFaceColor().mV);
+ face->renderIndexed(getRawIndices());
+ mIndicesDrawn += face->getIndicesCount();
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+}
+
+void bindScreenToTexture()
+{
+ GLint viewport[4];
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ GLuint resX = nhpo2(viewport[2]);
+ GLuint resY = nhpo2(viewport[3]);
+
+ glBindTexture(GL_TEXTURE_2D, sScreenTex);
+ GLint cResX;
+ GLint cResY;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY);
+
+ if (cResX != (GLint)resX || cResY != (GLint)resY)
+ {
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL);
+ gImageList.updateMaxResidentTexMem(-1, resX*resY*3);
+ }
+
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ float scale[2];
+ scale[0] = (float) viewport[2]/resX;
+ scale[1] = (float) viewport[3]/resY;
+ glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale);
+
+ LLImageGL::sBoundTextureMemory += resX * resY * 3;
+}
+
+void LLDrawPoolWater::shade()
+{
+ static LLVector2 d1( 0.5f, -0.17f );
+ static LLVector2 d2( 0.58f, -0.67f );
+ static LLVector2 d3( 0.5f, 0.25f );
+
+ static LLVector3 wave1(1,0.42f,1);
+ static LLVector3 wave2(0.58f,0.42f,0.17f);
+ static LLVector3 wave3(0.42f,0.67f,0.33f);
+
+ /*static LLVector2 d1( 0.83f, -1 );
+ static LLVector2 d2( 0.58f, 1 );
+ static LLVector2 d3( 1, -0.88f );
+
+ static LLVector4 wave1(0.75f,0.08f,0.5f,0.67f);
+ static LLVector4 wave2(0.17f,0.33f,0.53f,0.62f);
+ static LLVector4 wave3(0.17f,0.6f,0.67f,1);*/
+
+ /*LLDebugVarMessageBox::show("Wave Direction 1", &d1, LLVector2(1,1), LLVector2(0.01f, 0.01f));
+ LLDebugVarMessageBox::show("Wave Direction 2", &d2, LLVector2(1,1), LLVector2(0.01f, 0.01f));
+ LLDebugVarMessageBox::show("Wave Direction 3", &d3, LLVector2(1,1), LLVector2(0.01f, 0.01f));
+
+ LLDebugVarMessageBox::show("Wave 1", &wave1, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f));
+ LLDebugVarMessageBox::show("Wave 2", &wave2, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f));
+ LLDebugVarMessageBox::show("Wave 3", &wave3, LLVector3(2,1,4), LLVector3(0.01f, 0.01f, 0.01f));*/
+
+ LLVOSky *voskyp = gSky.mVOSkyp;
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ LLGLDisable blend(GL_BLEND);
+ bindGLVertexPointer();
+ bindGLNormalPointer();
+ bindGLTexCoordPointer();
+
+ LLColor3 light_diffuse(0,0,0);
+ F32 light_exp = 0.0f;
+ LLVector3 light_dir;
+
+ if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS)
+ {
+ light_dir = gSky.getSunDirection();
+ light_dir.normVec();
+ light_diffuse = gSky.mVOSkyp->getSun().getColorCached();
+ light_diffuse.normVec();
+ light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0);
+ light_diffuse *= light_exp + 0.25f;
+ }
+ else
+ {
+ light_dir = gSky.getMoonDirection();
+ light_dir.normVec();
+ light_diffuse = gSky.mVOSkyp->getMoon().getColorCached();
+ light_diffuse.normVec();
+ light_diffuse *= 0.5f;
+ light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0);
+ }
+
+ light_exp *= light_exp;
+ light_exp *= light_exp;
+ light_exp *= light_exp;
+ light_exp *= light_exp;
+ light_exp *= light_exp;
+ light_exp *= 512.f;
+ light_exp = light_exp > 32.f ? light_exp : 32.f;
+
+ sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
+
+ LLCubeMap* skyMap = gSky.mVOSkyp->getCubeMap();
+
+ gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ skyMap->bind();
+
+ //bind normal map
+ S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP);
+ mWaterNormp->addTextureStats(1024.f*1024.f);
+ mWaterNormp->bind(bumpTex);
+
+ gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_WATER_SCREENTEX);
+
+ gPipeline.mWaterProgram.bind();
+
+ bindScreenToTexture();
+
+ S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP);
+ LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex);
+
+ S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
+
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
+
+ glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_TIME], sTime);
+ glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_SPECULAR], 1, light_diffuse.mV);
+ glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_SPECULAR_EXP], light_exp);
+ glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_EYEVEC], 1, gCamera->getOrigin().mV);
+ glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_WAVE_DIR1], 1, d1.mV);
+ glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_WAVE_DIR2], 1, d2.mV);
+ glUniform3fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_LIGHT_DIR], 1, light_dir.mV);
+
+ LLColor4 water_color;
+ LLVector3 camera_up = gCamera->getUpAxis();
+ F32 up_dot = camera_up * LLVector3::z_axis;
+ if (gCamera->cameraUnderWater())
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.4f);
+ glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_REFSCALE], 0.25f);
+ }
+ else
+ {
+ water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
+ glUniform1fARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_REFSCALE], 0.01f);
+ }
+ if (water_color.mV[3] > 0.9f)
+ {
+ water_color.mV[3] = 0.9f;
+ }
+
+ glColor4fv(water_color.mV);
+
+ {
+ LLGLDisable cullface(GL_CULL_FACE);
+ for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
+ iter != mDrawFace.end(); iter++)
+ {
+ LLFace *face = *iter;
+
+ if (voskyp->isReflFace(face))
+ {
+ continue;
+ }
+
+ face->bindTexture(diffTex);
+ face->renderIndexed(getRawIndices());
+ mIndicesDrawn += face->getIndicesCount();
+ }
+ }
+
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_WATER_SCREENTEX);
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP);
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP);
+ gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP);
+
+ glActiveTextureARB(GL_TEXTURE0_ARB);
+ glEnable(GL_TEXTURE_2D);
+ glUseProgramObjectARB(0);
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ /*glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);*/
+}
+
+void LLDrawPoolWater::renderForSelect()
+{
+ // Can't select water!
+ return;
+}
+
+
+void LLDrawPoolWater::renderFaceSelected(LLFace *facep,
+ LLImageGL *image,
+ const LLColor4 &color,
+ const S32 index_offset, const S32 index_count)
+{
+ // Can't select water
+ return;
+}
+
+
+LLViewerImage *LLDrawPoolWater::getDebugTexture()
+{
+ return LLViewerImage::sSmokeImagep;
+}
+
+LLColor3 LLDrawPoolWater::getDebugColor() const
+{
+ return LLColor3(0.f, 1.f, 1.f);
+}