diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/lldrawpoolwater.cpp | 475 | ||||
-rw-r--r-- | indra/newview/lldrawpoolwater.h | 3 |
2 files changed, 193 insertions, 285 deletions
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 1e638f3088..e2d3f67e46 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -50,8 +50,6 @@ #include "llsettingssky.h" #include "llsettingswater.h" -static float sTime; - BOOL deferred_render = FALSE; BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; @@ -146,7 +144,7 @@ void LLDrawPoolWater::renderDeferred(S32 pass) } deferred_render = TRUE; - shade(); + renderWater(); deferred_render = FALSE; } @@ -182,7 +180,7 @@ void LLDrawPoolWater::render(S32 pass) if ((mShaderLevel > 0) && !sSkipScreenCopy) { - shade(); + renderWater(); return; } @@ -485,335 +483,246 @@ void LLDrawPoolWater::renderReflection(LLFace* face) face->renderIndexed(); } -void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp) +void LLDrawPoolWater::renderWater() { LL_PROFILE_ZONE_SCOPED; - F32 water_height = LLEnvironment::instance().getWaterHeight(); - F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; - F32 eyedepth = camera_height - water_height; - bool underwater = eyedepth <= 0.0f; - - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); - - shader->bind(); - -// bind textures for water rendering - if (deferred_render) - { - if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) - { - glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); - shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); - } - } - - LLColor4 specular(psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor()); - shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); - - sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f; - - S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); - - if (reftex > -1) - { - gGL.getTexUnit(reftex)->activate(); - gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); - gGL.getTexUnit(0)->activate(); - } + if (!deferred_render) + { + gGL.setColorMask(true, true); + } - //bind normal map - S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); + LLGLDisable blend(GL_BLEND); - LLViewerTexture* tex_a = mWaterNormp[0]; - LLViewerTexture* tex_b = mWaterNormp[1]; + LLColor3 light_diffuse(0, 0, 0); + F32 light_exp = 0.0f; - F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor(); - - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + LLEnvironment & environment = LLEnvironment::instance(); + LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); + LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + LLVector3 light_dir = environment.getLightDirection(); + bool sun_up = environment.getIsSunUp(); + bool moon_up = environment.getIsMoonUp(); + bool has_normal_mips = gSavedSettings.getBOOL("RenderWaterMipNormal"); + bool underwater = LLViewerCamera::getInstance()->cameraUnderWater(); - if (tex_a && (!tex_b || (tex_a == tex_b))) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b && !tex_a) + if (sun_up) { - gGL.getTexUnit(bumpTex)->bind(tex_b); - blend_factor = 0; // only one tex provided, no blending + light_diffuse += psky->getSunlightColor(); } - else if (tex_b != tex_a) + // moonlight is several orders of magnitude less bright than sunlight, + // so only use this color when the moon alone is showing + else if (moon_up) { - gGL.getTexUnit(bumpTex)->bind(tex_a); - gGL.getTexUnit(bumpTex2)->bind(tex_b); + light_diffuse += psky->getMoonlightColor(); } - - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); - F32 screenRes[] = - { - 1.f/gGLViewport[2], - 1.f/gGLViewport[3] - }; - - S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - stop_glerror(); - -// set uniforms for water rendering - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); - - LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f); - F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); - if (screentex > -1) - { - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); - gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - } - - if (mShaderLevel == 1) - { - //F32 fog_density_slider_value = param_mgr->mDensitySliderValue; - //sWaterFogColor.mV[3] = fog_density_slider_value; - fog_color.mV[VW] = log(fog_density) / log(2); - } - - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); - - //shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix); - shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth); - shader->uniform1f(LLShaderMgr::WATER_TIME, sTime); - shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); - shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); - shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); - if (LLEnvironment::instance().isCloudScrollPaused()) + // Apply magic numbers translating light direction into intensities + light_dir.normalize(); + F32 ground_proj_sq = light_dir.mV[0] * light_dir.mV[0] + light_dir.mV[1] * light_dir.mV[1]; + light_exp = llmax(32.f, 256.f * powf(ground_proj_sq, 16.0f)); + if (0.f < light_diffuse.normalize()) // Normalizing a color? Puzzling... { - static const std::array<F32, 2> zerowave{ {0.0f, 0.0f} }; - - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data()); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data()); + light_diffuse *= (1.5f + (6.f * ground_proj_sq)); } - else + + // set up normal maps filtering + for (auto norm_map : mWaterNormp) { - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); + if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); } - shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); - shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); + LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); + F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; + bool edge = false; + LLGLSLShader *shader = nullptr; + do // twice through, once with normal shader bound & once with edge shader bound + { + // select shader + if (underwater && LLPipeline::sWaterReflections) + { + shader = deferred_render ? &gDeferredUnderWaterProgram : &gUnderWaterProgram; + } + else + { + if (edge && !deferred_render) + { + shader = &gWaterEdgeProgram; + } + else + { + shader = deferred_render ? &gDeferredWaterProgram : &gWaterProgram; + } + } + shader->bind(); - F32 sunAngle = llmax(0.f, light_dir.mV[1]); - F32 scaledAngle = 1.f - sunAngle; + // bind textures for water rendering + S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX); + if (reftex > -1) + { + gGL.getTexUnit(reftex)->activate(); + gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef); + gGL.getTexUnit(0)->activate(); + } - shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); - shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle); - shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); + // bind normal map + S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); + S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); - LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm(); - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + LLViewerTexture *tex_a = mWaterNormp[0]; + LLViewerTexture *tex_b = mWaterNormp[1]; - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); - } - else - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); - } + F32 blend_factor = pwater->getBlendFactor(); - { - LLGLDisable cullface(GL_CULL_FACE); + gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - if (edge) + if (tex_a && (!tex_b || (tex_a == tex_b))) { - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (face) - { - LLVOWater* water = (LLVOWater*) face->getViewerObject(); - gGL.getTexUnit(diffTex)->bind(face->getTexture()); - - if (water) - { - bool edge_patch = water->getIsEdgePatch(); - if (edge_patch) - { - face->renderIndexed(); - } - } - } - } + gGL.getTexUnit(bumpTex)->bind(tex_a); + blend_factor = 0; // only one tex provided, no blending } - else + else if (tex_b && !tex_a) { - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - if (face) - { - LLVOWater* water = (LLVOWater*) face->getViewerObject(); - gGL.getTexUnit(diffTex)->bind(face->getTexture()); - - if (water) - { - bool edge_patch = water->getIsEdgePatch(); - if (!edge_patch) - { - if (!LLPipeline::sUseOcclusion) - { - // If occlusion is enabled, these are set within LLOcclusionCullingGroup::checkOcclusion() - sNeedsReflectionUpdate = TRUE; - sNeedsDistortionUpdate = TRUE; - } - face->renderIndexed(); - } - } - } - } + gGL.getTexUnit(bumpTex)->bind(tex_b); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b != tex_a) + { + gGL.getTexUnit(bumpTex)->bind(tex_a); + gGL.getTexUnit(bumpTex2)->bind(tex_b); } - } - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + // bind reflection texture from RenderTarget + S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + F32 screenRes[] = {1.f / gGLViewport[2], 1.f / gGLViewport[3]}; - shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); - shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); - shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); + S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP); - shader->unbind(); -} + // set uniforms for shader + if (deferred_render) + { + if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0) + { + glh::matrix4f norm_mat = get_current_modelview().inverse().transpose(); + shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m); + } + } -void LLDrawPoolWater::shade() -{ - LL_PROFILE_ZONE_SCOPED; - if (!deferred_render) - { - gGL.setColorMask(true, true); - } + shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); + shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); - LLVOSky *voskyp = gSky.mVOSkyp; + LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f); + F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); - if(voskyp == NULL) - { - return; - } + if (screentex > -1) + { + shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); + gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); + } - LLGLDisable blend(GL_BLEND); + if (mShaderLevel == 1) + { + fog_color.mV[VW] = log(fog_density) / log(2); + } - LLColor3 light_diffuse(0,0,0); - F32 light_exp = 0.0f; - LLVector3 light_dir; + F32 water_height = environment.getWaterHeight(); + F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; + shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height); + shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time); + shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); - LLEnvironment& environment = LLEnvironment::instance(); - LLSettingsWater::ptr_t pwater = environment.getCurrentWater(); - LLSettingsSky::ptr_t psky = environment.getCurrentSky(); + shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); + shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); - light_dir = environment.getLightDirection(); - light_dir.normalize(); + shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); + shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); + if (LLEnvironment::instance().isCloudScrollPaused()) + { + static const std::array<F32, 2> zerowave {{0.0f, 0.0f}}; - bool sun_up = environment.getIsSunUp(); - bool moon_up = environment.getIsMoonUp(); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data()); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data()); + } + else + { + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); + } + shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - if (sun_up) - { - light_diffuse += voskyp->getSun().getColorCached(); - } - // moonlight is several orders of magnitude less bright than sunlight, - // so only use this color when the moon alone is showing - else if (moon_up) - { - light_diffuse += psky->getMoonDiffuse(); - } + shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); + shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); - light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f); + F32 sunAngle = llmax(0.f, light_dir.mV[1]); + F32 scaledAngle = 1.f - sunAngle; - light_diffuse.normalize(); - light_diffuse *= (light_exp + 0.25f); + shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); + shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); + shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle); + shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= light_exp; - light_exp *= 256.f; - light_exp = light_exp > 32.f ? light_exp : 32.f; + LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm(); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); - light_diffuse *= 6.f; + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + } + else + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + } - LLGLSLShader* shader = nullptr; - LLGLSLShader* edge_shader = nullptr; + LLGLDisable cullface(GL_CULL_FACE); - F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight(); - - if (eyedepth < 0.f && LLPipeline::sWaterReflections) - { - if (deferred_render) - { - shader = &gDeferredUnderWaterProgram; - } - else + LLVOWater *water = nullptr; + for (LLFace *const &face : mDrawFace) { - shader = &gUnderWaterProgram; - } - } - else if (deferred_render) - { - shader = &gDeferredWaterProgram; - edge_shader = nullptr; - } - else - { - shader = &gWaterProgram; - edge_shader = &gWaterEdgeProgram; - } + if (!face) continue; + water = static_cast<LLVOWater *>(face->getViewerObject()); + if (!water) continue; - if (mWaterNormp[0]) - { - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT); - } - } + gGL.getTexUnit(diffTex)->bind(face->getTexture()); - if (mWaterNormp[1]) - { - if (gSavedSettings.getBOOL("RenderWaterMipNormal")) - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); - } - else - { - mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT); - } - } + if (edge == (bool) water->getIsEdgePatch()) + { + face->renderIndexed(); - shade2(false, shader, light_diffuse, light_dir, light_exp); - shade2(true, edge_shader ? edge_shader : shader, light_diffuse, light_dir, light_exp); + // If not occlusion culling, record non-void water being drawn + // (If occlusion is enabled, these are set within LLOcclusionCullingGroup::checkOcclusion() ) + if (!edge && !LLPipeline::sUseOcclusion) + { + sNeedsReflectionUpdate = TRUE; + sNeedsDistortionUpdate = TRUE; + } + } + } - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); - if (!deferred_render) - { - gGL.setColorMask(true, false); - } + shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); + shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); + shader->disableTexture(LLShaderMgr::BUMP_MAP); + shader->disableTexture(LLShaderMgr::DIFFUSE_MAP); + shader->disableTexture(LLShaderMgr::WATER_REFTEX); + shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH); + + // clean up + shader->unbind(); + gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + + edge = !edge; + } while (!edge); + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!deferred_render) + { + gGL.setColorMask(true, false); + } } LLViewerTexture *LLDrawPoolWater::getDebugTexture() diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index a5d163e0d7..6f2fc3271d 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -78,8 +78,7 @@ public: /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderReflection(LLFace* face); - void shade(); - void shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp); + void renderWater(); void setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId); void setOpaqueTexture(const LLUUID& opaqueTextureId); |