Water2Renderer.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <water/Water2Renderer.h>
00022 #include <water/Water2.h>
00023 #include <water/WaterMapPoints.h>
00024 #include <water/WaterWaves.h>
00025 #include <common/Vector4.h>
00026 #include <image/ImageFactory.h>
00027 #include <image/ImageFactory.h>
00028 #include <GLEXT/GLStateExtension.h>
00029 #include <GLEXT/GLCamera.h>
00030 #include <GLEXT/GLTextureCubeMap.h>
00031 #include <client/ScorchedClient.h>
00032 #include <sky/Sky.h>
00033 #include <land/VisibilityPatchGrid.h>
00034 #include <landscapemap/LandscapeMaps.h>
00035 #include <landscapedef/LandscapeTex.h>
00036 #include <landscapedef/LandscapeDefn.h>
00037 #include <landscape/Landscape.h>
00038 #include <graph/MainCamera.h>
00039 #include <graph/OptionsDisplay.h>
00040 
00041 #include <water/Water2Constants.h>
00042 
00043 Water2Renderer::Water2Renderer() : 
00044         waterShader_(0),
00045         currentPatch_(0), totalTime_(0.0f),
00046         noShaderWaterTexture_(0)
00047 {
00048 }
00049 
00050 Water2Renderer::~Water2Renderer()
00051 {
00052 }
00053 
00054 void Water2Renderer::simulate(float frameTime)
00055 {
00056         totalTime_ += frameTime * 24.0f;
00057 }
00058 
00059 void Water2Renderer::draw(Water2 &water2, WaterMapPoints &points, WaterWaves &waves)
00060 {
00061         GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_PATCHSETUP");
00062         // Choose correct water frame
00063         Water2Patches &currentPatch = water2.getPatch(totalTime_);
00064         if (&currentPatch != currentPatch_)
00065         {
00066                 currentPatch_ = &currentPatch;
00067 
00068                 // Set the normal map for the current water frame
00069                 if (GLStateExtension::hasShaders() &&
00070                         !OptionsDisplay::instance()->getNoWaterMovement() &&
00071                         !OptionsDisplay::instance()->getSimpleWaterShaders())
00072                 {
00073                         normalTexture_.replace(currentPatch_->getNormalMap(), 
00074                                 GLStateExtension::hasHardwareMipmaps());
00075                 }
00076         }
00077         GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_PATCHSETUP");
00078 
00079         // Draw waves
00080         GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_WAVES");
00081         waves.draw(*currentPatch_);
00082         GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_WAVES");
00083 
00084         // Draw Water
00085         if (GLStateExtension::hasShaders() &&
00086                 OptionsDisplay::instance()->getUseWaterTexture())
00087         {
00088                 drawWaterShaders(water2);
00089         }
00090         else
00091         {
00092                 drawWaterNoShaders(water2);
00093         }
00094 
00095         GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_DRAWPOINTS");
00096         drawPoints(points);
00097         GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_DRAWPOINTS");
00098 }
00099 
00100 void Water2Renderer::drawPoints(WaterMapPoints &points)
00101 {
00102         if (!currentPatch_) return;
00103 
00104         // Draw Points
00105         points.draw(*currentPatch_);
00106 }
00107 
00108 void Water2Renderer::drawWaterShaders(Water2 &water2)
00109 {
00110         GLState state(GLState::LIGHTING_OFF | GLState::TEXTURE_ON | GLState::BLEND_ON);
00111 
00112         glPushAttrib(GL_ALL_ATTRIB_BITS);
00113 
00114         Vector cameraPos = GLCamera::getCurrentCamera()->getCurrentPos();
00115         cameraPos[2] = -waterHeight_;
00116         waterShader_->use();
00117         waterShader_->set_uniform("viewpos", cameraPos);
00118 
00119         // Tex 3
00120         if (!OptionsDisplay::instance()->getSimpleWaterShaders())
00121         {
00122                 waterShader_->set_gl_texture(currentPatch_->getAOF(), "tex_foamamount", 3);
00123         }
00124 
00125         // Tex 2
00126         if (Landscape::instance()->getShadowFrameBuffer().bufferValid())
00127         {
00128                 glActiveTextureARB(GL_TEXTURE2_ARB);
00129                 glEnable(GL_TEXTURE_2D);
00130                 waterShader_->set_gl_texture(Landscape::instance()->getShadowFrameBuffer(), 
00131                         "tex_shadow", 2);
00132                 glMatrixMode(GL_TEXTURE);
00133                 glLoadMatrixf(Landscape::instance()->getShadowTextureMatrix());
00134                 glMatrixMode(GL_MODELVIEW);
00135         }
00136 
00137         // texture units / coordinates:
00138         // tex0: noise map (color normals) / matching texcoords
00139         // tex1: reflection map / matching texcoords
00140         // tex2: foam
00141         // tex3: amount of foam
00142 
00143         // set up scale/translation of foam and noise maps
00144         // we do not use the texture matrix here, as this would be overkill
00145         // and would be clumsy
00146 
00147         // need to divide by noise tile size here too (tex coordinates are in [0...1], not meters)
00148         Vector D_0 = windDir1_ * (windSpeed1_ / (-64.0f * 6.0f)); // noise tile is 256/8=32m long
00149         Vector D_1 = windDir2_ * (windSpeed2_ / (-16.0f * 6.0f));  // noise tile is 256/32=8m long
00150 
00151         float mytime = totalTime_ / 24.0f;
00152         Vector noise_0_pos = D_0 * mytime;
00153         Vector noise_1_pos = D_1 * mytime;
00154         noise_0_pos[2] = wavetile_length_rcp * 8.0f;
00155         noise_1_pos[2] = wavetile_length_rcp * 32.0f;
00156 
00157         //fixme: do we have to treat the viewer offset here, like with tex matrix
00158         //       setup below?!
00159 
00160         // Tex 0
00161         glActiveTextureARB(GL_TEXTURE0);
00162         if (!OptionsDisplay::instance()->getSimpleWaterShaders())
00163         {
00164                 waterShader_->set_uniform("noise_xform_0", noise_0_pos);
00165                 waterShader_->set_uniform("noise_xform_1", noise_1_pos);
00166                 waterShader_->set_gl_texture(normalTexture_, "tex_normal", 0);
00167         }
00168 
00169         const float noisetilescale = 1.0f/32.0f;//meters (128/16=8, 8tex/m).
00170         glMatrixMode(GL_TEXTURE);
00171         glLoadIdentity();
00172         glScalef(noisetilescale, noisetilescale, 1.0f); // fixme adjust scale
00173         glMatrixMode(GL_MODELVIEW);
00174 
00175         // Tex 1
00176         glActiveTextureARB(GL_TEXTURE1);
00177         glEnable(GL_TEXTURE_2D);
00178         waterShader_->set_gl_texture(reflectionTexture_, "tex_reflection", 1);
00179 
00180         // Draw Water
00181         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00182         drawWater(water2, waterShader_);
00183 
00184         // Cleanup      
00185         waterShader_->use_fixed();
00186 
00187         glActiveTextureARB(GL_TEXTURE2);
00188         glMatrixMode(GL_TEXTURE);
00189         glLoadIdentity();
00190         glMatrixMode(GL_MODELVIEW);
00191         glDisable(GL_TEXTURE_2D);
00192 
00193         glActiveTextureARB(GL_TEXTURE1);
00194         glMatrixMode(GL_TEXTURE);
00195         glLoadIdentity();
00196         glMatrixMode(GL_MODELVIEW);
00197         glDisable(GL_TEXTURE_2D);
00198 
00199         glActiveTextureARB(GL_TEXTURE0);
00200         glMatrixMode(GL_TEXTURE);
00201         glLoadIdentity();
00202         glMatrixMode(GL_MODELVIEW);
00203 
00204         glPopAttrib();
00205 }
00206 
00207 void Water2Renderer::drawWaterNoShaders(Water2 &water2)
00208 {
00209         glPushAttrib(GL_TEXTURE_BIT);
00210 
00211         // Set up texture coordinate generation for reflections
00212         static float PlaneS[] = { 0.0f, 1.0f / 20.0f, 0.0f, 0.0f };
00213         static float PlaneT[] = { 1.0f / 20.0f, 0.0f, 0.0f, 0.0f };
00214 
00215         if (GLStateExtension::hasMultiTex() &&
00216                 OptionsDisplay::instance()->getUseWaterTexture())
00217         {
00218                 // Set up texture coordinate generation for base texture
00219                 glActiveTextureARB(GL_TEXTURE1);
00220                 glEnable(GL_TEXTURE_2D);
00221                 glEnable(GL_TEXTURE_GEN_S); 
00222                 glEnable(GL_TEXTURE_GEN_T);
00223                 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00224                 glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00225                 glTexGenfv(GL_S, GL_OBJECT_PLANE, PlaneS);
00226                 glTexGenfv(GL_T, GL_OBJECT_PLANE, PlaneT);
00227                 reflectionTexture_.draw(true);
00228 
00229                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
00230                 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 2);
00231 
00232                 glActiveTextureARB(GL_TEXTURE0);
00233 
00234 
00235                 glColor4f(0.3f, 0.3f, 0.3f, 0.8f);
00236         }
00237         else
00238         {
00239                 glColor4f(0.7f, 0.7f, 0.7f, 0.8f);
00240         }
00241 
00242         // Turn lighting on (if enabled)
00243         unsigned int state = 0;
00244         if (!OptionsDisplay::instance()->getNoModelLighting())
00245         {
00246                 state = 
00247                         GLState::LIGHTING_ON | 
00248                         GLState::LIGHT1_ON;
00249 
00250                 Vector4 ambientColor(0.2f, 0.2f, 0.2f, 0.8f);
00251                 Vector4 diffuseColor(0.8f, 0.8f, 0.8f, 0.8f);
00252                 Vector4 specularColor(1.0f, 1.0f, 1.0f, 0.8f);
00253                 Vector4 emissiveColor(0.0f, 0.0f, 0.0f, 0.8f);
00254                 float shininess = 100.0f;
00255                 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambientColor);
00256                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuseColor);
00257                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularColor);
00258                 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emissiveColor);
00259                 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
00260 
00261                 Landscape::instance()->getSky().getSun().setLightPosition();
00262         }
00263 
00264         if (!OptionsDisplay::instance()->getUseWaterTexture())
00265         {
00266                 GLState currentState(GLState::LIGHTING_OFF | GLState::TEXTURE_OFF);
00267                 glColor3f(0.0f, 0.3f, 1.0f);
00268                 drawWater(water2, 0);
00269         }
00270         else if (GLStateExtension::hasCubeMap())
00271         {
00272                 GLState currentState(state | GLState::TEXTURE_OFF | GLState::BLEND_ON | GLState::CUBEMAP_ON);
00273 
00274                 // Set up texture coordinate generation for cubemap reflections
00275                 glEnable(GL_TEXTURE_GEN_S); 
00276                 glEnable(GL_TEXTURE_GEN_T);
00277                 glEnable(GL_TEXTURE_GEN_R);
00278                 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
00279                 glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
00280                 glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT);
00281 
00282                 drawWater(water2, 0);
00283         }
00284         else if (GLStateExtension::hasSphereMap())
00285         {
00286                 GLState currentState(state | GLState::TEXTURE_ON | GLState::BLEND_ON);
00287                 noShaderWaterTexture_->draw();
00288 
00289                 // Set up texture coordinate generation for spheremap reflections
00290                 glEnable(GL_TEXTURE_GEN_S); 
00291                 glEnable(GL_TEXTURE_GEN_T);
00292                 glEnable(GL_TEXTURE_GEN_R);
00293                 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
00294                 glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
00295                 glTexGenf(GL_R, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
00296 
00297                 drawWater(water2, 0);
00298         }
00299         else
00300         {
00301                 GLState currentState(state | GLState::TEXTURE_ON | GLState::BLEND_ON);
00302                 noShaderWaterTexture_->draw();
00303 
00304                 // Set up texture coordinate generation for linear reflections
00305                 glEnable(GL_TEXTURE_GEN_S); 
00306                 glEnable(GL_TEXTURE_GEN_T);
00307                 glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00308                 glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
00309                 glTexGenfv(GL_S, GL_OBJECT_PLANE, PlaneS);
00310                 glTexGenfv(GL_T, GL_OBJECT_PLANE, PlaneT);
00311 
00312                 drawWater(water2, 0);
00313         }
00314 
00315         if (GLStateExtension::hasMultiTex())
00316         {
00317                 glActiveTextureARB(GL_TEXTURE1);
00318                 glDisable(GL_TEXTURE_GEN_S); 
00319                 glDisable(GL_TEXTURE_GEN_T);
00320                 glDisable(GL_TEXTURE_GEN_R);
00321                 glDisable(GL_TEXTURE_2D);
00322 
00323                 glActiveTextureARB(GL_TEXTURE0);
00324                 glDisable(GL_TEXTURE_GEN_S); 
00325                 glDisable(GL_TEXTURE_GEN_T);
00326                 glDisable(GL_TEXTURE_GEN_R);
00327         }
00328 
00329         glPopAttrib();
00330 }
00331 
00332 void Water2Renderer::drawWater(Water2 &water2, GLSLShaderSetup *waterShader)
00333 {
00334         // Draw Water
00335         Vector &cameraPos = GLCamera::getCurrentCamera()->getCurrentPos();
00336         VisibilityPatchGrid::instance()->drawWater(
00337                 *currentPatch_, water2.getIndexs(), cameraPos, landscapeSize_, waterShader);
00338 }
00339 
00340 void Water2Renderer::generate(LandscapeTexBorderWater *water, ProgressCounter *counter)
00341 {
00342         currentPatch_ = 0;
00343         if (GLStateExtension::hasShaders())
00344         {
00345                 // Load shaders
00346                 if (!waterShader_) 
00347                 {
00348                         GLSLShader::defines_list dl;
00349                         if (Landscape::instance()->getShadowFrameBuffer().bufferValid())
00350                         {
00351                                 dl.push_back("USE_SHADOWS");
00352                         }
00353 
00354                         if (OptionsDisplay::instance()->getSimpleWaterShaders())
00355                         {
00356                                 waterShader_ = new GLSLShaderSetup(
00357                                         S3D::getDataFile("data/shaders/watersimple.vshader"),
00358                                         S3D::getDataFile("data/shaders/watersimple.fshader"),
00359                                         dl);
00360                         }
00361                         else
00362                         {
00363                                 waterShader_ = new GLSLShaderSetup(
00364                                         S3D::getDataFile("data/shaders/water.vshader"),
00365                                         S3D::getDataFile("data/shaders/water.fshader"),
00366                                         dl);
00367                         }
00368                 }
00369         }
00370 
00371         // Set the water height
00372         waterHeight_ = water->height.asFloat();
00373 
00374         // fixme: color depends also on weather. bad weather -> light is less bright
00375         // so this will be computed implicitly. Environment can also change water color
00376         // (light blue in tropic waters), water depth also important etc.
00377         // this depends on sky color...
00378         // good weather
00379         //      color wavetop = color(color(10, 10, 10), color(18, 93, 77), light_brightness);
00380         //      color wavebottom = color(color(10, 10, 20), color(18, 73, 107), light_brightness);
00381         // rather bad weather
00382         //fixme: multiply with light color here, not only light brightness.
00383         //dim yellow light should result in dim yellow-green upwelling color, not dim green.
00384         Vector4 light_color(water->wavelight, 1.0f);
00385         Vector4 wavetopA(water->wavetopa, 0.0f);
00386         Vector4 wavetopB(water->wavetopb, 0.0f);
00387         Vector4 wavebottomA(water->wavebottoma, 0.0f);
00388         Vector4 wavebottomB(water->wavebottomb, 0.0f);
00389         Vector4 wavetop = light_color.lerp(wavetopA, wavetopB);
00390         Vector4 wavebottom = light_color.lerp(wavebottomA, wavebottomB);
00391 
00392         // Create textures
00393         if (GLStateExtension::hasFBO() &&
00394                 GLStateExtension::hasShaders() &&
00395                 !OptionsDisplay::instance()->getNoWaterReflections())
00396         {
00397                 reflectionTexture_.createBufferTexture(512, 512, false);
00398                 reflectionBuffer_.create(reflectionTexture_, true);
00399         }
00400         else
00401         {
00402                 ImageHandle loadedBitmapWater = 
00403                         ImageFactory::loadImageHandle(S3D::getDataFile(water->texture.c_str()));
00404                 ImageHandle bitmapWater2 = loadedBitmapWater.createResize(128, 128);
00405                 reflectionTexture_.create(bitmapWater2, true); // Not the reflection in this case
00406         }
00407 
00408         ImageHandle map = ImageFactory::createBlank(128, 128, false, 0);
00409         normalTexture_.create(map, GLStateExtension::hasHardwareMipmaps());
00410 
00411         LandscapeDefn &defn = *ScorchedClient::instance()->getLandscapeMaps().
00412                 getDefinitions().getDefn();
00413         landscapeSize_ = Vector(defn.getLandscapeWidth(), defn.getLandscapeHeight());
00414 
00415         if (GLStateExtension::hasShaders())
00416         {
00417                 Vector upwelltop(wavetop[0], wavetop[1], wavetop[2]);
00418                 Vector upwellbot(wavebottom[0], wavebottom[1], wavebottom[2]);
00419                 Vector upwelltopbot = upwelltop - upwellbot;
00420 
00421                 waterShader_->use();
00422                 waterShader_->set_uniform("upwelltop", upwelltop);
00423                 waterShader_->set_uniform("upwellbot", upwellbot);
00424                 waterShader_->set_uniform("upwelltopbot", upwelltopbot);
00425                 if (!OptionsDisplay::instance()->getSimpleWaterShaders())
00426                 {
00427                         Vector landfoam;
00428                         waterShader_->set_uniform("landfoam", landfoam);
00429                         waterShader_->set_uniform("landscape_size", landscapeSize_);
00430                 }
00431                 waterShader_->use_fixed();
00432         }
00433         else
00434         {
00435                 // Load the water reflection bitmap
00436                 // Create water cubemap texture
00437                 ImageHandle loadedBitmapWater = 
00438                         ImageFactory::loadImageHandle(S3D::getDataFile(water->reflection.c_str()));
00439                 ImageHandle bitmapWater2 = loadedBitmapWater.createResize(256, 256);
00440                 delete noShaderWaterTexture_;
00441                 if (GLStateExtension::hasCubeMap())
00442                 {
00443                         GLTextureCubeMap *waterCubeMap = new GLTextureCubeMap();
00444                         waterCubeMap->create(bitmapWater2, false);
00445                         noShaderWaterTexture_ = waterCubeMap;
00446                 }
00447                 else 
00448                 {
00449                         GLTexture *waterNormalMap = new GLTexture();
00450                         waterNormalMap->create(bitmapWater2, false);
00451                         noShaderWaterTexture_ = waterNormalMap;
00452                 }
00453         }
00454 
00455         // Setup wind dir/speed
00456         windSpeed1_ = ScorchedClient::instance()->
00457                 getOptionsTransient().getWindSpeed().asFloat() * 2.0f + 3.0f;
00458         windDir1_ = ScorchedClient::instance()->
00459                 getOptionsTransient().getWindDirection().asVector();
00460         windDir1_[2] = 0.0f;
00461         windSpeed2_ = MAX(0.0f, RAND * 2.0f - 1.0f + windSpeed1_);
00462         windDir2_ = Vector(windDir1_[0] + RAND * 0.4f - 0.2f,
00463                 windDir1_[1] + RAND * 0.4f - 0.2f);
00464         windDir1_.StoreNormalize();
00465         windDir2_.StoreNormalize();
00466 }

Generated on Mon Feb 16 15:14:48 2009 for Scorched3D by  doxygen 1.5.3