1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2004
4 // This file is part of Scorched3D.
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with Scorched3D; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ////////////////////////////////////////////////////////////////////////////////
21 #include <water/Water2Renderer.h>
22 #include <water/Water2.h>
23 #include <water/WaterMapPoints.h>
24 #include <water/WaterWaves.h>
25 #include <common/Vector4.h>
26 #include <image/ImageFactory.h>
27 #include <image/ImageFactory.h>
28 #include <GLEXT/GLStateExtension.h>
29 #include <GLEXT/GLCamera.h>
30 #include <GLEXT/GLTextureCubeMap.h>
31 #include <client/ScorchedClient.h>
33 #include <land/VisibilityPatchGrid.h>
34 #include <landscapemap/LandscapeMaps.h>
35 #include <landscapedef/LandscapeTex.h>
36 #include <landscapedef/LandscapeDefn.h>
37 #include <landscape/Landscape.h>
38 #include <graph/MainCamera.h>
39 #include <graph/OptionsDisplay.h>
41 #include <water/Water2Constants.h>
43 Water2Renderer::Water2Renderer() :
45 currentPatch_(0), totalTime_(0.0f
),
46 noShaderWaterTexture_(0)
50 Water2Renderer::~Water2Renderer()
54 void Water2Renderer::simulate(float frameTime
)
56 totalTime_
+= frameTime
* 24.0f
;
59 void Water2Renderer::draw(Water2
&water2
, WaterMapPoints
&points
, WaterWaves
&waves
)
61 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_PATCHSETUP");
62 // Choose correct water frame
63 Water2Patches
¤tPatch
= water2
.getPatch(totalTime_
);
64 if (¤tPatch
!= currentPatch_
)
66 currentPatch_
= ¤tPatch
;
68 // Set the normal map for the current water frame
69 if (GLStateExtension::hasShaders() &&
70 !OptionsDisplay::instance()->getNoWaterMovement() &&
71 !OptionsDisplay::instance()->getSimpleWaterShaders())
73 normalTexture_
.replace(currentPatch_
->getNormalMap(),
74 GLStateExtension::hasHardwareMipmaps());
77 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_PATCHSETUP");
80 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_WAVES");
81 waves
.draw(*currentPatch_
);
82 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_WAVES");
85 if (GLStateExtension::hasShaders() &&
86 OptionsDisplay::instance()->getUseWaterTexture())
88 drawWaterShaders(water2
);
92 drawWaterNoShaders(water2
);
95 GAMESTATE_PERF_COUNTER_START(ScorchedClient::instance()->getGameState(), "WATER_DRAWPOINTS");
97 GAMESTATE_PERF_COUNTER_END(ScorchedClient::instance()->getGameState(), "WATER_DRAWPOINTS");
100 void Water2Renderer::drawPoints(WaterMapPoints
&points
)
102 if (!currentPatch_
) return;
105 points
.draw(*currentPatch_
);
108 void Water2Renderer::drawWaterShaders(Water2
&water2
)
110 GLState
state(GLState::LIGHTING_OFF
| GLState::TEXTURE_ON
| GLState::BLEND_ON
);
112 glPushAttrib(GL_ALL_ATTRIB_BITS
);
114 Vector cameraPos
= GLCamera::getCurrentCamera()->getCurrentPos();
115 cameraPos
[2] = -waterHeight_
;
117 waterShader_
->set_uniform("viewpos", cameraPos
);
120 if (!OptionsDisplay::instance()->getSimpleWaterShaders())
122 waterShader_
->set_gl_texture(currentPatch_
->getAOF(), "tex_foamamount", 3);
126 if (Landscape::instance()->getShadowFrameBuffer().bufferValid())
128 glActiveTextureARB(GL_TEXTURE2_ARB
);
129 glEnable(GL_TEXTURE_2D
);
130 waterShader_
->set_gl_texture(Landscape::instance()->getShadowFrameBuffer(),
132 glMatrixMode(GL_TEXTURE
);
133 glLoadMatrixf(Landscape::instance()->getShadowTextureMatrix());
134 glMatrixMode(GL_MODELVIEW
);
137 // texture units / coordinates:
138 // tex0: noise map (color normals) / matching texcoords
139 // tex1: reflection map / matching texcoords
141 // tex3: amount of foam
143 // set up scale/translation of foam and noise maps
144 // we do not use the texture matrix here, as this would be overkill
145 // and would be clumsy
147 // need to divide by noise tile size here too (tex coordinates are in [0...1], not meters)
148 Vector D_0
= windDir1_
* (windSpeed1_
/ (-64.0f
* 6.0f
)); // noise tile is 256/8=32m long
149 Vector D_1
= windDir2_
* (windSpeed2_
/ (-16.0f
* 6.0f
)); // noise tile is 256/32=8m long
151 float mytime
= totalTime_
/ 24.0f
;
152 Vector noise_0_pos
= D_0
* mytime
;
153 Vector noise_1_pos
= D_1
* mytime
;
154 noise_0_pos
[2] = wavetile_length_rcp
* 8.0f
;
155 noise_1_pos
[2] = wavetile_length_rcp
* 32.0f
;
157 //fixme: do we have to treat the viewer offset here, like with tex matrix
161 glActiveTextureARB(GL_TEXTURE0
);
162 if (!OptionsDisplay::instance()->getSimpleWaterShaders())
164 waterShader_
->set_uniform("noise_xform_0", noise_0_pos
);
165 waterShader_
->set_uniform("noise_xform_1", noise_1_pos
);
166 waterShader_
->set_gl_texture(normalTexture_
, "tex_normal", 0);
169 const float noisetilescale
= 1.0f
/32.0f
;//meters (128/16=8, 8tex/m).
170 glMatrixMode(GL_TEXTURE
);
172 glScalef(noisetilescale
, noisetilescale
, 1.0f
); // fixme adjust scale
173 glMatrixMode(GL_MODELVIEW
);
176 glActiveTextureARB(GL_TEXTURE1
);
177 glEnable(GL_TEXTURE_2D
);
178 waterShader_
->set_gl_texture(reflectionTexture_
, "tex_reflection", 1);
181 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
182 drawWater(water2
, waterShader_
);
185 waterShader_
->use_fixed();
187 glActiveTextureARB(GL_TEXTURE2
);
188 glMatrixMode(GL_TEXTURE
);
190 glMatrixMode(GL_MODELVIEW
);
191 glDisable(GL_TEXTURE_2D
);
193 glActiveTextureARB(GL_TEXTURE1
);
194 glMatrixMode(GL_TEXTURE
);
196 glMatrixMode(GL_MODELVIEW
);
197 glDisable(GL_TEXTURE_2D
);
199 glActiveTextureARB(GL_TEXTURE0
);
200 glMatrixMode(GL_TEXTURE
);
202 glMatrixMode(GL_MODELVIEW
);
207 void Water2Renderer::drawWaterNoShaders(Water2
&water2
)
209 glPushAttrib(GL_TEXTURE_BIT
);
211 // Set up texture coordinate generation for reflections
212 static float PlaneS
[] = { 0.0f
, 1.0f
/ 20.0f
, 0.0f
, 0.0f
};
213 static float PlaneT
[] = { 1.0f
/ 20.0f
, 0.0f
, 0.0f
, 0.0f
};
215 if (GLStateExtension::hasMultiTex() &&
216 OptionsDisplay::instance()->getUseWaterTexture())
218 // Set up texture coordinate generation for base texture
219 glActiveTextureARB(GL_TEXTURE1
);
220 glEnable(GL_TEXTURE_2D
);
221 glEnable(GL_TEXTURE_GEN_S
);
222 glEnable(GL_TEXTURE_GEN_T
);
223 glTexGenf(GL_S
, GL_TEXTURE_GEN_MODE
, GL_OBJECT_LINEAR
);
224 glTexGenf(GL_T
, GL_TEXTURE_GEN_MODE
, GL_OBJECT_LINEAR
);
225 glTexGenfv(GL_S
, GL_OBJECT_PLANE
, PlaneS
);
226 glTexGenfv(GL_T
, GL_OBJECT_PLANE
, PlaneT
);
227 reflectionTexture_
.draw(true);
229 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_ARB
);
230 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_ARB
, 2);
232 glActiveTextureARB(GL_TEXTURE0
);
235 glColor4f(0.3f
, 0.3f
, 0.3f
, 0.8f
);
239 glColor4f(0.7f
, 0.7f
, 0.7f
, 0.8f
);
242 // Turn lighting on (if enabled)
243 unsigned int state
= 0;
244 if (!OptionsDisplay::instance()->getNoModelLighting())
247 GLState::LIGHTING_ON
|
250 Vector4
ambientColor(0.2f
, 0.2f
, 0.2f
, 0.8f
);
251 Vector4
diffuseColor(0.8f
, 0.8f
, 0.8f
, 0.8f
);
252 Vector4
specularColor(1.0f
, 1.0f
, 1.0f
, 0.8f
);
253 Vector4
emissiveColor(0.0f
, 0.0f
, 0.0f
, 0.8f
);
254 float shininess
= 100.0f
;
255 glMaterialfv(GL_FRONT_AND_BACK
, GL_AMBIENT
, ambientColor
);
256 glMaterialfv(GL_FRONT_AND_BACK
, GL_DIFFUSE
, diffuseColor
);
257 glMaterialfv(GL_FRONT_AND_BACK
, GL_SPECULAR
, specularColor
);
258 glMaterialfv(GL_FRONT_AND_BACK
, GL_EMISSION
, emissiveColor
);
259 glMaterialf(GL_FRONT_AND_BACK
, GL_SHININESS
, shininess
);
261 Landscape::instance()->getSky().getSun().setLightPosition();
264 if (!OptionsDisplay::instance()->getUseWaterTexture())
266 GLState
currentState(GLState::LIGHTING_OFF
| GLState::TEXTURE_OFF
);
267 glColor3f(0.0f
, 0.3f
, 1.0f
);
268 drawWater(water2
, 0);
270 else if (GLStateExtension::hasCubeMap())
272 GLState
currentState(state
| GLState::TEXTURE_OFF
| GLState::BLEND_ON
| GLState::CUBEMAP_ON
);
274 // Set up texture coordinate generation for cubemap reflections
275 glEnable(GL_TEXTURE_GEN_S
);
276 glEnable(GL_TEXTURE_GEN_T
);
277 glEnable(GL_TEXTURE_GEN_R
);
278 glTexGenf(GL_S
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_EXT
);
279 glTexGenf(GL_T
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_EXT
);
280 glTexGenf(GL_R
, GL_TEXTURE_GEN_MODE
, GL_REFLECTION_MAP_EXT
);
282 drawWater(water2
, 0);
284 else if (GLStateExtension::hasSphereMap())
286 GLState
currentState(state
| GLState::TEXTURE_ON
| GLState::BLEND_ON
);
287 noShaderWaterTexture_
->draw();
289 // Set up texture coordinate generation for spheremap reflections
290 glEnable(GL_TEXTURE_GEN_S
);
291 glEnable(GL_TEXTURE_GEN_T
);
292 glEnable(GL_TEXTURE_GEN_R
);
293 glTexGenf(GL_S
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
294 glTexGenf(GL_T
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
295 glTexGenf(GL_R
, GL_TEXTURE_GEN_MODE
, GL_SPHERE_MAP
);
297 drawWater(water2
, 0);
301 GLState
currentState(state
| GLState::TEXTURE_ON
| GLState::BLEND_ON
);
302 noShaderWaterTexture_
->draw();
304 // Set up texture coordinate generation for linear reflections
305 glEnable(GL_TEXTURE_GEN_S
);
306 glEnable(GL_TEXTURE_GEN_T
);
307 glTexGenf(GL_S
, GL_TEXTURE_GEN_MODE
, GL_OBJECT_LINEAR
);
308 glTexGenf(GL_T
, GL_TEXTURE_GEN_MODE
, GL_OBJECT_LINEAR
);
309 glTexGenfv(GL_S
, GL_OBJECT_PLANE
, PlaneS
);
310 glTexGenfv(GL_T
, GL_OBJECT_PLANE
, PlaneT
);
312 drawWater(water2
, 0);
315 if (GLStateExtension::hasMultiTex())
317 glActiveTextureARB(GL_TEXTURE1
);
318 glDisable(GL_TEXTURE_GEN_S
);
319 glDisable(GL_TEXTURE_GEN_T
);
320 glDisable(GL_TEXTURE_GEN_R
);
321 glDisable(GL_TEXTURE_2D
);
323 glActiveTextureARB(GL_TEXTURE0
);
324 glDisable(GL_TEXTURE_GEN_S
);
325 glDisable(GL_TEXTURE_GEN_T
);
326 glDisable(GL_TEXTURE_GEN_R
);
332 void Water2Renderer::drawWater(Water2
&water2
, GLSLShaderSetup
*waterShader
)
335 Vector
&cameraPos
= GLCamera::getCurrentCamera()->getCurrentPos();
336 VisibilityPatchGrid::instance()->drawWater(
337 *currentPatch_
, water2
.getIndexs(), cameraPos
, landscapeSize_
, waterShader
);
340 void Water2Renderer::generate(LandscapeTexBorderWater
*water
, ProgressCounter
*counter
)
343 if (GLStateExtension::hasShaders())
348 GLSLShader::defines_list dl
;
349 if (Landscape::instance()->getShadowFrameBuffer().bufferValid())
351 dl
.push_back("USE_SHADOWS");
354 if (OptionsDisplay::instance()->getSimpleWaterShaders())
356 waterShader_
= new GLSLShaderSetup(
357 S3D::getDataFile("data/shaders/watersimple.vshader"),
358 S3D::getDataFile("data/shaders/watersimple.fshader"),
363 waterShader_
= new GLSLShaderSetup(
364 S3D::getDataFile("data/shaders/water.vshader"),
365 S3D::getDataFile("data/shaders/water.fshader"),
371 // Set the water height
372 waterHeight_
= water
->height
.asFloat();
374 // fixme: color depends also on weather. bad weather -> light is less bright
375 // so this will be computed implicitly. Environment can also change water color
376 // (light blue in tropic waters), water depth also important etc.
377 // this depends on sky color...
379 // color wavetop = color(color(10, 10, 10), color(18, 93, 77), light_brightness);
380 // color wavebottom = color(color(10, 10, 20), color(18, 73, 107), light_brightness);
381 // rather bad weather
382 //fixme: multiply with light color here, not only light brightness.
383 //dim yellow light should result in dim yellow-green upwelling color, not dim green.
384 Vector4
light_color(water
->wavelight
, 1.0f
);
385 Vector4
wavetopA(water
->wavetopa
, 0.0f
);
386 Vector4
wavetopB(water
->wavetopb
, 0.0f
);
387 Vector4
wavebottomA(water
->wavebottoma
, 0.0f
);
388 Vector4
wavebottomB(water
->wavebottomb
, 0.0f
);
389 Vector4 wavetop
= light_color
.lerp(wavetopA
, wavetopB
);
390 Vector4 wavebottom
= light_color
.lerp(wavebottomA
, wavebottomB
);
393 if (GLStateExtension::hasFBO() &&
394 GLStateExtension::hasShaders() &&
395 !OptionsDisplay::instance()->getNoWaterReflections())
397 reflectionTexture_
.createBufferTexture(512, 512, false);
398 reflectionBuffer_
.create(reflectionTexture_
, true);
402 ImageHandle loadedBitmapWater
=
403 ImageFactory::loadImageHandle(S3D::getDataFile(water
->texture
.c_str()));
404 ImageHandle bitmapWater2
= loadedBitmapWater
.createResize(128, 128);
405 reflectionTexture_
.create(bitmapWater2
, true); // Not the reflection in this case
408 ImageHandle map
= ImageFactory::createBlank(128, 128, false, 0);
409 normalTexture_
.create(map
, GLStateExtension::hasHardwareMipmaps());
411 LandscapeDefn
&defn
= *ScorchedClient::instance()->getLandscapeMaps().
412 getDefinitions().getDefn();
413 landscapeSize_
= Vector(defn
.getLandscapeWidth(), defn
.getLandscapeHeight());
415 if (GLStateExtension::hasShaders())
417 Vector
upwelltop(wavetop
[0], wavetop
[1], wavetop
[2]);
418 Vector
upwellbot(wavebottom
[0], wavebottom
[1], wavebottom
[2]);
419 Vector upwelltopbot
= upwelltop
- upwellbot
;
422 waterShader_
->set_uniform("upwelltop", upwelltop
);
423 waterShader_
->set_uniform("upwellbot", upwellbot
);
424 waterShader_
->set_uniform("upwelltopbot", upwelltopbot
);
425 if (!OptionsDisplay::instance()->getSimpleWaterShaders())
428 waterShader_
->set_uniform("landfoam", landfoam
);
429 waterShader_
->set_uniform("landscape_size", landscapeSize_
);
431 waterShader_
->use_fixed();
435 // Load the water reflection bitmap
436 // Create water cubemap texture
437 ImageHandle loadedBitmapWater
=
438 ImageFactory::loadImageHandle(S3D::getDataFile(water
->reflection
.c_str()));
439 ImageHandle bitmapWater2
= loadedBitmapWater
.createResize(256, 256);
440 delete noShaderWaterTexture_
;
441 if (GLStateExtension::hasCubeMap())
443 GLTextureCubeMap
*waterCubeMap
= new GLTextureCubeMap();
444 waterCubeMap
->create(bitmapWater2
, false);
445 noShaderWaterTexture_
= waterCubeMap
;
449 GLTexture
*waterNormalMap
= new GLTexture();
450 waterNormalMap
->create(bitmapWater2
, false);
451 noShaderWaterTexture_
= waterNormalMap
;
455 // Setup wind dir/speed
456 windSpeed1_
= ScorchedClient::instance()->
457 getOptionsTransient().getWindSpeed().asFloat() * 2.0f
+ 3.0f
;
458 windDir1_
= ScorchedClient::instance()->
459 getOptionsTransient().getWindDirection().asVector();
461 windSpeed2_
= MAX(0.0f
, RAND
* 2.0f
- 1.0f
+ windSpeed1_
);
462 windDir2_
= Vector(windDir1_
[0] + RAND
* 0.4f
- 0.2f
,
463 windDir1_
[1] + RAND
* 0.4f
- 0.2f
);
464 windDir1_
.StoreNormalize();
465 windDir2_
.StoreNormalize();