lldrawpoolwater.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llfeaturemanager.h"
00034 #include "lldrawpoolwater.h"
00035 
00036 #include "llviewercontrol.h"
00037 #include "lldir.h"
00038 #include "llerror.h"
00039 #include "m3math.h"
00040 
00041 #include "llagent.h"            // for gAgent for getRegion for getWaterHeight
00042 #include "llcubemap.h"
00043 #include "lldrawable.h"
00044 #include "llface.h"
00045 #include "llsky.h"
00046 #include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION
00047 #include "llviewerimagelist.h"
00048 #include "llviewerregion.h"
00049 #include "llvosky.h"
00050 #include "llvowater.h"
00051 #include "llworld.h"
00052 #include "pipeline.h"
00053 #include "llglslshader.h"
00054 #include "llwaterparammanager.h"
00055 
00056 const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
00057 
00058 static float sTime;
00059 
00060 BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
00061 BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
00062 BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
00063 LLColor4 LLDrawPoolWater::sWaterFogColor = LLColor4(0.2f, 0.5f, 0.5f, 0.f);
00064 LLVector3 LLDrawPoolWater::sLightDir;
00065 
00066 LLDrawPoolWater::LLDrawPoolWater() :
00067         LLFacePool(POOL_WATER)
00068 {
00069         mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE);
00070         mHBTex[0]->bind();
00071         mHBTex[0]->setClamp(TRUE, TRUE);
00072 
00073         mHBTex[1] = gImageList.getImage(gMoonTextureID, TRUE, TRUE);
00074         mHBTex[1]->bind();
00075         mHBTex[1]->setClamp(TRUE, TRUE);
00076 
00077         mWaterImagep = gImageList.getImage(WATER_TEST);
00078         mWaterNormp = gImageList.getImage(DEFAULT_WATER_NORMAL);
00079 
00080         restoreGL();
00081 }
00082 
00083 LLDrawPoolWater::~LLDrawPoolWater()
00084 {
00085 }
00086 
00087 //static
00088 void LLDrawPoolWater::restoreGL()
00089 {
00090         
00091 }
00092 
00093 LLDrawPool *LLDrawPoolWater::instancePool()
00094 {
00095         llerrs << "Should never be calling instancePool on a water pool!" << llendl;
00096         return NULL;
00097 }
00098 
00099 
00100 void LLDrawPoolWater::prerender()
00101 {
00102         mVertexShaderLevel = (gGLManager.mHasCubeMap && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap")) ?
00103                 LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_WATER) : 0;
00104 
00105         // got rid of modulation by light color since it got a little too
00106         // green at sunset and sl-57047 (underwater turns black at 8:00)
00107         sWaterFogColor = LLWaterParamManager::instance()->getFogColor();
00108         sWaterFogColor.mV[3] = 0;
00109 
00110 }
00111 
00112 S32 LLDrawPoolWater::getNumPasses()
00113 {
00114         if (LLViewerCamera::getInstance()->getOrigin().mV[2] < 1024.f)
00115         {
00116                 return 1;
00117         }
00118 
00119         return 0;
00120 }
00121 
00122 void LLDrawPoolWater::render(S32 pass)
00123 {
00124         LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER);
00125         if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1)
00126         {
00127                 return;
00128         }
00129 
00130         //do a quick 'n dirty depth sort
00131         for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
00132                          iter != mDrawFace.end(); iter++)
00133         {
00134                 LLFace* facep = *iter;
00135                 facep->mDistance = -facep->mCenterLocal.mV[2];
00136         }
00137 
00138         std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater());
00139 
00140         LLGLEnable blend(GL_BLEND);
00141 
00142         if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
00143         {
00144                 shade();
00145                 return;
00146         }
00147 
00148         LLVOSky *voskyp = gSky.mVOSkyp;
00149 
00150         stop_glerror();
00151 
00152         if (!gGLManager.mHasMultitexture)
00153         {
00154                 // Ack!  No multitexture!  Bail!
00155                 return;
00156         }
00157 
00158         LLFace* refl_face = voskyp->getReflFace();
00159 
00160         gPipeline.disableLights();
00161         
00162         LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
00163 
00164         LLGLDisable cullFace(GL_CULL_FACE);
00165         
00166         // Set up second pass first
00167         mWaterImagep->addTextureStats(1024.f*1024.f);
00168         mWaterImagep->bind(1);
00169         glActiveTextureARB(GL_TEXTURE1_ARB);
00170         
00171         glEnable(GL_TEXTURE_2D); // Texture unit 1
00172 
00173         LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
00174         F32 up_dot = camera_up * LLVector3::z_axis;
00175 
00176         LLColor4 water_color;
00177         if (LLViewerCamera::getInstance()->cameraUnderWater())
00178         {
00179                 water_color.setVec(1.f, 1.f, 1.f, 0.4f);
00180         }
00181         else
00182         {
00183                 water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
00184         }
00185 
00186         glColor4fv(water_color.mV);
00187 
00188         // Automatically generate texture coords for detail map
00189         glEnable(GL_TEXTURE_GEN_S); //texture unit 1
00190         glEnable(GL_TEXTURE_GEN_T); //texture unit 1
00191         glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00192         glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00193 
00194         // Slowly move over time.
00195         F32 offset = fmod(gFrameTimeSeconds*2.f, 100.f);
00196         F32 tp0[4] = {16.f/256.f, 0.0f, 0.0f, offset*0.01f};
00197         F32 tp1[4] = {0.0f, 16.f/256.f, 0.0f, offset*0.01f};
00198         glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0);
00199         glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1);
00200 
00201         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,          GL_COMBINE_ARB);
00202         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB,           GL_MODULATE);
00203         glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB,         GL_REPLACE);
00204 
00205         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB,           GL_PREVIOUS_ARB);
00206         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB,          GL_SRC_COLOR);
00207         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB,           GL_TEXTURE);
00208         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB,          GL_SRC_COLOR);
00209         glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB,         GL_PREVIOUS_ARB);
00210         glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB,        GL_SRC_ALPHA);
00211 
00212         glActiveTextureARB(GL_TEXTURE0_ARB);
00213         
00214         glClearStencil(1);
00215         glClear(GL_STENCIL_BUFFER_BIT);
00216         LLGLEnable gls_stencil(GL_STENCIL_TEST);
00217         glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP);
00218         glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
00219 
00220         for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
00221                  iter != mDrawFace.end(); iter++)
00222         {
00223                 LLFace *face = *iter;
00224                 if (voskyp->isReflFace(face))
00225                 {
00226                         continue;
00227                 }
00228                 face->bindTexture();
00229                 face->renderIndexed();
00230         }
00231 
00232         // Now, disable texture coord generation on texture state 1
00233         glActiveTextureARB(GL_TEXTURE1_ARB);
00234         glDisable(GL_TEXTURE_2D); // Texture unit 1
00235         glDisable(GL_TEXTURE_GEN_S); //texture unit 1
00236         glDisable(GL_TEXTURE_GEN_T); //texture unit 1
00237         LLImageGL::unbindTexture(1, GL_TEXTURE_2D);
00238 
00239         // Disable texture coordinate and color arrays
00240         glActiveTextureARB(GL_TEXTURE0_ARB);
00241         LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00242 
00243         stop_glerror();
00244         
00245         if (gSky.mVOSkyp->getCubeMap())
00246         {
00247                 gSky.mVOSkyp->getCubeMap()->enable(0);
00248                 gSky.mVOSkyp->getCubeMap()->bind();
00249 
00250                 glMatrixMode(GL_TEXTURE);
00251                 glLoadIdentity();
00252                 LLMatrix4 camera_mat = LLViewerCamera::getInstance()->getModelview();
00253                 LLMatrix4 camera_rot(camera_mat.getMat3());
00254                 camera_rot.invert();
00255 
00256                 glLoadMatrixf((F32 *)camera_rot.mMatrix);
00257 
00258                 glMatrixMode(GL_MODELVIEW);
00259                 LLOverrideFaceColor overrid(this, 1.f, 1.f, 1.f,  0.5f*up_dot);
00260 
00261                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00262 
00263                 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
00264                          iter != mDrawFace.end(); iter++)
00265                 {
00266                         LLFace *face = *iter;
00267                         if (voskyp->isReflFace(face))
00268                         {
00269                                 //refl_face = face;
00270                                 continue;
00271                         }
00272 
00273                         if (face->getGeomCount() > 0)
00274                         {                                       
00275                                 face->renderIndexed();
00276                         }
00277                 }
00278 
00279                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00280 
00281                 if (gSky.mVOSkyp->getCubeMap())
00282                 {
00283                         gSky.mVOSkyp->getCubeMap()->disable();
00284                 }
00285                 LLImageGL::unbindTexture(0, GL_TEXTURE_2D);
00286                 glEnable(GL_TEXTURE_2D);
00287                 glMatrixMode(GL_TEXTURE);
00288                 glLoadIdentity();
00289                 glMatrixMode(GL_MODELVIEW);
00290                 
00291         }
00292 
00293         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00294 
00295     if (refl_face)
00296         {
00297                 glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
00298                 renderReflection(refl_face);
00299         }
00300 
00301         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00302 }
00303 
00304 void LLDrawPoolWater::renderReflection(LLFace* face)
00305 {
00306         LLVOSky *voskyp = gSky.mVOSkyp;
00307 
00308         if (!voskyp)
00309         {
00310                 return;
00311         }
00312 
00313         if (!face->getGeomCount())
00314         {
00315                 return;
00316         }
00317         
00318         S8 dr = voskyp->getDrawRefl();
00319         if (dr < 0)
00320         {
00321                 return;
00322         }
00323 
00324         LLGLSNoFog noFog;
00325 
00326         LLViewerImage::bindTexture(mHBTex[dr]);
00327 
00328         LLOverrideFaceColor override(this, face->getFaceColor().mV);
00329         face->renderIndexed();
00330 }
00331 
00332 void LLDrawPoolWater::shade()
00333 {
00334         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00335 
00336         LLVOSky *voskyp = gSky.mVOSkyp;
00337 
00338         if(voskyp == NULL) 
00339         {
00340                 return;
00341         }
00342 
00343         LLGLDisable blend(GL_BLEND);
00344 
00345         LLColor3 light_diffuse(0,0,0);
00346         F32 light_exp = 0.0f;
00347         LLVector3 light_dir;
00348         LLColor3 light_color;
00349 
00350         if (gSky.getSunDirection().mV[2] > NIGHTTIME_ELEVATION_COS)      
00351     {    
00352         light_dir  = gSky.getSunDirection();     
00353         light_dir.normVec();    
00354                 light_color = gSky.getSunDiffuseColor();
00355                 if(gSky.mVOSkyp) {
00356                 light_diffuse = gSky.mVOSkyp->getSun().getColorCached();         
00357                         light_diffuse.normVec();         
00358                 }
00359         light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0);          
00360         light_diffuse *= light_exp + 0.25f;      
00361     }    
00362     else         
00363     {    
00364         light_dir       = gSky.getMoonDirection();       
00365         light_dir.normVec();     
00366                 light_color = gSky.getMoonDiffuseColor();
00367         light_diffuse   = gSky.mVOSkyp->getMoon().getColorCached();      
00368         light_diffuse.normVec();         
00369         light_diffuse *= 0.5f;   
00370         light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0);          
00371     }
00372 
00373         light_exp *= light_exp;
00374         light_exp *= light_exp;
00375         light_exp *= light_exp;
00376         light_exp *= light_exp;
00377         light_exp *= 256.f;
00378         light_exp = light_exp > 32.f ? light_exp : 32.f;
00379 
00380         LLGLSLShader* shader;
00381 
00382         F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight();
00383         
00384         if (eyedepth < 0.f && LLPipeline::sWaterReflections)
00385         {
00386                 shader = &gUnderWaterProgram;
00387         }
00388         else
00389         {
00390                 shader = &gWaterProgram;
00391         }
00392 
00393         sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
00394         
00395         S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
00396                 
00397         if (reftex > -1)
00398         {
00399                 glActiveTextureARB(GL_TEXTURE0_ARB+reftex);
00400                 gPipeline.mWaterRef.bindTexture();
00401                 glActiveTextureARB(GL_TEXTURE0_ARB);
00402         }       
00403 
00404         //bind normal map
00405         S32 bumpTex = shader->enableTexture(LLShaderMgr::BUMP_MAP);
00406 
00407         LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
00408 
00409         // change mWaterNormp if needed
00410         if (mWaterNormp->getID() != param_mgr->getNormalMapID())
00411         {
00412                 mWaterNormp = gImageList.getImage(param_mgr->getNormalMapID());
00413         }
00414 
00415         mWaterNormp->addTextureStats(1024.f*1024.f);
00416         mWaterNormp->bind(bumpTex);
00417         if (!gSavedSettings.getBOOL("RenderWaterMipNormal"))
00418         {
00419                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00420         }
00421         else
00422         {
00423                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00424         }
00425         
00426         S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);    
00427         stop_glerror();
00428         
00429         shader->bind();
00430 
00431         if (screentex > -1)
00432         {
00433                 shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
00434                 shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, 
00435                         param_mgr->getFogDensity());
00436         }
00437         
00438         gPipeline.mWaterDis.bindTexture();
00439 
00440         if (mVertexShaderLevel == 1)
00441         {
00442                 sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue;
00443                 shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
00444         }
00445 
00446         F32 screenRes[] = 
00447         {
00448                 1.f/gGLViewport[2],
00449                 1.f/gGLViewport[3]
00450         };
00451         shader->uniform2fv("screenRes", 1, screenRes);
00452         stop_glerror();
00453         
00454         S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
00455         stop_glerror();
00456         
00457         light_dir.normVec();
00458         sLightDir = light_dir;
00459         
00460         light_diffuse *= 6.f;
00461 
00462         //shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
00463         shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
00464         shader->uniform1f(LLShaderMgr::WATER_TIME, sTime);
00465         shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
00466         shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
00467         shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
00468         shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV);
00469         shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV);
00470         shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
00471 
00472         shader->uniform3fv("normScale", 1, param_mgr->getNormalScale().mV);
00473         shader->uniform1f("fresnelScale", param_mgr->getFresnelScale());
00474         shader->uniform1f("fresnelOffset", param_mgr->getFresnelOffset());
00475         shader->uniform1f("blurMultiplier", param_mgr->getBlurMultiplier());
00476 
00477         F32 sunAngle = llmax(0.f, light_dir.mV[2]);
00478         F32 scaledAngle = 1.f - sunAngle;
00479 
00480         shader->uniform1f("sunAngle", sunAngle);
00481         shader->uniform1f("scaledAngle", scaledAngle);
00482         shader->uniform1f("sunAngle2", 0.1f + 0.2f*sunAngle);
00483 
00484         LLColor4 water_color;
00485         LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
00486         F32 up_dot = camera_up * LLVector3::z_axis;
00487         if (LLViewerCamera::getInstance()->cameraUnderWater())
00488         {
00489                 water_color.setVec(1.f, 1.f, 1.f, 0.4f);
00490                 shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());
00491         }
00492         else
00493         {
00494                 water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
00495                 shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());
00496         }
00497 
00498         if (water_color.mV[3] > 0.9f)
00499         {
00500                 water_color.mV[3] = 0.9f;
00501         }
00502 
00503         glColor4fv(water_color.mV);
00504 
00505         {
00506                 LLGLDisable cullface(GL_CULL_FACE);
00507                 for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
00508                         iter != mDrawFace.end(); iter++)
00509                 {
00510                         LLFace *face = *iter;
00511 
00512                         if (voskyp->isReflFace(face))
00513                         {
00514                                 continue;
00515                         }
00516 
00517                         LLVOWater* water = (LLVOWater*) face->getViewerObject();
00518                         face->bindTexture(diffTex);
00519 
00520                         sNeedsReflectionUpdate = TRUE;
00521                         
00522                         if (water->getUseTexture())
00523                         {
00524                                 sNeedsDistortionUpdate = TRUE;
00525                                 face->renderIndexed();
00526                         }
00527                         else
00528                         { //smash background faces to far clip plane
00529                                 if (water->getIsEdgePatch())
00530                                 {
00531                                         LLGLClampToFarClip far_clip(glh_get_current_projection());
00532                                         face->renderIndexed();
00533                                 }
00534                                 else
00535                                 {
00536                                         sNeedsDistortionUpdate = TRUE;
00537                                         face->renderIndexed();
00538                                 }
00539                         }
00540                 }
00541         }
00542         
00543         shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
00544         shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);   
00545         shader->disableTexture(LLShaderMgr::BUMP_MAP);
00546         shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
00547         shader->disableTexture(LLShaderMgr::WATER_REFTEX);
00548         shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
00549         shader->unbind();
00550 
00551         glActiveTextureARB(GL_TEXTURE0_ARB);
00552         glEnable(GL_TEXTURE_2D);
00553         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_FALSE);
00554 
00555 }
00556 
00557 void LLDrawPoolWater::renderForSelect()
00558 {
00559         // Can't select water!
00560         return;
00561 }
00562 
00563 
00564 void LLDrawPoolWater::renderFaceSelected(LLFace *facep, 
00565                                                                         LLImageGL *image, 
00566                                                                         const LLColor4 &color,
00567                                                                         const S32 index_offset, const S32 index_count)
00568 {
00569         // Can't select water
00570         return;
00571 }
00572 
00573 
00574 LLViewerImage *LLDrawPoolWater::getDebugTexture()
00575 {
00576         return LLViewerImage::sSmokeImagep;
00577 }
00578 
00579 LLColor3 LLDrawPoolWater::getDebugColor() const
00580 {
00581         return LLColor3(0.f, 1.f, 1.f);
00582 }

Generated on Fri May 16 08:33:20 2008 for SecondLife by  doxygen 1.5.5