Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/world_entities/environments/mapped_water.cc @ 8719

Last change on this file since 8719 was 8719, checked in by bensch, 18 years ago

merged the water branche back. conflicts resolved in favour of the trunk

File size: 11.8 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program 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, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Stefan Lienard
13   co-programmer: ...
14*/
15
16#include "mapped_water.h"
17#include "util/loading/load_param.h"
18#include "util/loading/factory.h"
19#include "util/loading/resource_manager.h"
20#include "state.h"
21
22
23CREATE_FACTORY(MappedWater, CL_MAPPED_WATER);
24
25/**
26 * @brief constructor
27 * @param root xml data
28 */
29MappedWater::MappedWater(const TiXmlElement* root)
30{
31  this->setClassID(CL_MAPPED_WATER, "MappedWater");
32  this->toList(OM_ENVIRON);
33
34  /// sets start values and parameters
35  this->initParams();
36  // now the standard values were loaded, if the values are specified in the .oxw file
37  // loadParams will overwrite the standard values with the specified values
38  if (root != NULL)
39    this->loadParams(root);
40
41  /// initialization of the textures
42  this->initTextures();
43
44  /// initialization of the shaders
45  this->initShaders();
46}
47
48/**
49 * @brief deltes shader and the uniform used by the camera
50 */
51MappedWater::~MappedWater()
52{
53  delete shader;
54  delete cam_uni;
55}
56
57/**
58 * @brief initialization of loadable parameters, sets start standard values
59 */
60void MappedWater::initParams()
61{
62  // those standardvalues will be overwritten if they're also set in the oxw file
63  this->setWaterPos(0, 0, 0);
64  this->setWaterSize(100, 100);
65  this->setWaterUV(9);
66  this->setWaterFlow(0.08);
67  this->setLightPos(0, 10, 0);
68  this->setWaterAngle(0);
69  this->setNormalMapScale(0.25f);
70
71  // initialization of the texture coords, speeds etc...
72  // normalUV wont change anymore
73  this->normalUV = this->waterUV * this->kNormalMapScale;
74  // move and move2 are used for the reflection and refraction, the values are changed in tick()
75  this->move = 0;
76  this->move2 = this->move * this->kNormalMapScale;
77}
78
79/**
80 * @brief initialization of the textures
81 */
82void MappedWater::initTextures()
83{
84  // sets parameters for the textures
85  this->textureSize = 512;
86  unsigned int channels = 32;
87  GLenum type = GL_RGBA;
88
89  // set up refleciton texture
90  Texture reflTex(GL_TEXTURE_2D, this->textureSize, this->textureSize, channels, type);
91  mat.setDiffuseMap(reflTex, 0);
92  // set up refraction texture
93  Texture refrTex(GL_TEXTURE_2D, this->textureSize, this->textureSize, channels, type);
94  mat.setDiffuseMap(refrTex, 1);
95  // load normal map
96  mat.setDiffuseMap("pictures/normalmap.bmp", GL_TEXTURE_2D, 2);
97  // load dudv map
98  mat.setDiffuseMap("pictures/dudvmap.bmp", GL_TEXTURE_2D, 3);
99
100  // sets texture parameters for reflection texture
101  glBindTexture(GL_TEXTURE_2D, this->mat.diffuseTextureID(0));
102  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
103  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
104  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
105  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
106  // sets texture parameters for refraction texture
107  glBindTexture(GL_TEXTURE_2D, this->mat.diffuseTextureID(1));
108  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
109  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
110  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
111  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
112}
113
114/**
115 * @brief initialization of the shaders
116 */
117void MappedWater::initShaders()
118{
119  // load shader files
120  shader = new Shader( ResourceManager::getInstance()->getDataDir() + "/shaders/mapped_water.vert", ResourceManager::getInstance()->getDataDir() +"/shaders/mapped_water.frag");
121
122  this->shader->activateShader();
123  // Set the variable "reflection" to correspond to the first texture unit
124  Shader::Uniform(shader, "reflection").set(0);
125  // Set the variable "refraction" to correspond to the second texture unit
126  Shader::Uniform(shader, "refraction").set(1);
127  // Set the variable "normalMap" to correspond to the third texture unit
128  Shader::Uniform(shader, "normalMap").set(2);
129  // Set the variable "dudvMap" to correspond to the fourth texture unit
130  Shader::Uniform(shader, "dudvMap").set(3);
131  // Set the variable "depthMap" to correspond to the fifth texture unit
132  Shader::Uniform(shader, "depthMap").set(2);
133  // Give the variable "waterColor" a blue color
134  Shader::Uniform(shader, "waterColor").set(0.1f, 0.2f, 0.4f, 1.0f);
135  // Give the variable "lightPos" our hard coded light position
136  Shader::Uniform(shader, "lightPos").set(lightPos.x, lightPos.y, lightPos.z, 1.0f);
137  // uniform for the camera position
138  cam_uni = new Shader::Uniform(shader, "cameraPos");
139
140  this->shader->deactivateShader();
141}
142
143/**
144 * @brief ends the refraction and saves the graphic buffer into a texture
145 * @param root xml data
146 */
147void MappedWater::loadParams(const TiXmlElement* root)
148{
149  WorldEntity::loadParams(root);
150
151  LoadParam(root, "waterpos", this, MappedWater, setWaterPos);
152  LoadParam(root, "watersize", this, MappedWater, setWaterSize);
153  LoadParam(root, "lightpos", this, MappedWater, setLightPos);
154  LoadParam(root, "wateruv", this, MappedWater, setWaterUV);
155  LoadParam(root, "waterflow", this, MappedWater, setWaterFlow);
156  LoadParam(root, "normalmapscale", this, MappedWater, setNormalMapScale);
157  LoadParam(root, "waterangle", this, MappedWater, setWaterAngle);
158}
159
160/**
161 * @brief activates the water shader and draws a quad with four textures on it
162 */
163void MappedWater::draw() const
164{
165  glMatrixMode(GL_MODELVIEW);
166
167  glPushMatrix();
168  // don't use a glTranslate here, the reflection point won't be at the right place anymore
169  glRotatef(this->waterAngle, 0, 1, 0);
170
171  mat.select();
172
173  this->shader->activateShader();
174
175  // reset the camera uniform to the current cam position
176  Vector pos = State::getCameraNode()->getAbsCoor();
177  cam_uni->set(pos.x, pos.y, pos.z, 1.0f);
178
179  glDisable(GL_BLEND);
180
181  glBegin(GL_QUADS);
182  // The back left vertice for the water
183  glMultiTexCoord2f(GL_TEXTURE0, 0, waterUV);            // Reflection texture
184  glMultiTexCoord2f(GL_TEXTURE1, 0, waterUV - move);        // Refraction texture
185  glMultiTexCoord2f(GL_TEXTURE2, 0, normalUV + move2);     // Normal map texture
186  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                       // DUDV map texture
187  glVertex3f(this->waterPos.x, this->waterPos.y, this->waterPos.z);
188
189  // The front left vertice for the water
190  glMultiTexCoord2f(GL_TEXTURE0, 0, 0);                  // Reflection texture
191  glMultiTexCoord2f(GL_TEXTURE1, 0, -move);           // Refraction texture
192  glMultiTexCoord2f(GL_TEXTURE2, 0, move2);          // Normal map texture
193  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
194  glVertex3f(this->waterPos.x, this->waterPos.y, this->waterPos.z + this->zWidth);
195
196  // The front right vertice for the water
197  glMultiTexCoord2f(GL_TEXTURE0, waterUV, 0);             // Reflection texture
198  glMultiTexCoord2f(GL_TEXTURE1, waterUV, -move);         // Refraction texture
199  glMultiTexCoord2f(GL_TEXTURE2, normalUV, move2);      // Normal map texture
200  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
201  glVertex3f(this->waterPos.x + this->xWidth, this->waterPos.y, this->waterPos.z + this->zWidth);
202
203  // The back right vertice for the water
204  glMultiTexCoord2f(GL_TEXTURE0, waterUV, waterUV);        // Reflection texture
205  glMultiTexCoord2f(GL_TEXTURE1, waterUV, waterUV - move);       // Refraction texture
206  glMultiTexCoord2f(GL_TEXTURE2, normalUV, normalUV + move2);  // Normal map texture
207  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
208  glVertex3f(this->waterPos.x + this->xWidth, this->waterPos.y, this->waterPos.z);
209  glEnd();
210
211  this->shader->deactivateShader();
212
213  mat.unselect();
214
215  glPopMatrix();
216}
217
218/**
219 * @brief tick tack, calculates the flow of the water
220 */
221void MappedWater::tick(float dt)
222{
223  // makes the water flow
224  this->move += this->waterFlow * dt;
225  this->move2 = this->move * this->kNormalMapScale;
226}
227
228/**
229 * @brief prepares everything to render the reflection texutre
230 */
231void MappedWater::activateReflection()
232{
233  // To create the reflection texture we just need to set the view port
234  // to our texture map size, then render the current scene our camera
235  // is looking at to the already allocated texture unit.  Since this
236  // is a reflection of the top of the water surface we use clipping
237  // planes to only render the top of the world as a reflection.  If
238  // we are below the water we don't flip the reflection but just use
239  // the current view of the top as we are seeing through the water.
240  // When you look through water at the surface it isn't really reflected,
241  // only when looking down from above the water on the surface.
242
243  // save viewport matrix and change the viewport size
244  glPushAttrib(GL_VIEWPORT_BIT);
245  glViewport(0,0, textureSize, textureSize);
246
247  glMatrixMode(GL_MODELVIEW);
248  glPushMatrix();
249
250  // If our camera is above the water we will render the scene flipped upside down.
251  // In order to line up the reflection nicely with the world we have to translate
252  // the world to the position of our reflected surface, multiplied by two.
253  glEnable(GL_CLIP_PLANE0);
254  Vector pos = State::getCameraNode()->getAbsCoor();
255
256  if(pos.y > waterPos.y)
257  {
258    // Translate the world, then flip it upside down
259    glTranslatef(0, waterPos.y*2, 0);
260    glScalef(1, -1, 1);
261
262    // Since the world is updside down we need to change the culling to FRONT
263    glCullFace(GL_FRONT);
264
265    // Set our plane equation and turn clipping on
266    double plane[4] = {0, 1, 0, -waterPos.y};
267    glClipPlane(GL_CLIP_PLANE0, plane);
268  }
269  else
270  {
271    // If the camera is below the water we don't want to flip the world,
272    // but just render it clipped so only the top is drawn.
273    double plane[4] = {0, 1, 0, waterPos.y};
274    glClipPlane(GL_CLIP_PLANE0, plane);
275  }
276}
277
278/**
279 * @brief ends the reflection and saves the graphic buffer into a texture
280 */
281void MappedWater::deactivateReflection()
282{
283  glDisable(GL_CLIP_PLANE0);
284  glCullFace(GL_BACK);
285
286  // Create the texture and store it on the video card
287  mat.renderToTexture(0, GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureSize, textureSize);
288
289  glPopMatrix();
290  glPopAttrib();
291}
292
293/**
294 * @brief prepares everything to render the refraction texutre
295 */
296void MappedWater::activateRefraction()
297{
298  // To create the refraction and depth textures we do the same thing
299  // we did for the reflection texture, except we don't need to turn
300  // the world upside down.  We want to find the depth of the water,
301  // not the depth of the sky and above water terrain.
302
303  // save viewport matrix and change the viewport size
304  glPushAttrib(GL_VIEWPORT_BIT);
305  glViewport(0,0, textureSize, textureSize);
306
307  glMatrixMode(GL_MODELVIEW);
308  glPushMatrix();
309
310  // If our camera is above the water we will render only the parts that
311  // are under the water.  If the camera is below the water we render
312  // only the stuff above the water.  Like the reflection texture, we
313  // incorporate clipping planes to only render what we need.
314
315  // If the camera is above water, render the data below the water
316  glEnable(GL_CLIP_PLANE0);
317  Vector pos = State::getCameraNode()->getAbsCoor();
318  if(pos.y > waterPos.y)
319  {
320    double plane[4] = {0, -1, 0, waterPos.y};
321    glClipPlane(GL_CLIP_PLANE0, plane);
322  }
323  // If the camera is below the water, only render the data above the water
324  else
325  {
326    glCullFace(GL_FRONT);
327    double plane[4] = {0, 1, 0, -waterPos.y};
328    glClipPlane(GL_CLIP_PLANE0, plane);
329  }
330}
331
332/**
333 * @brief ends the refraction and saves the graphic buffer into a texture
334 */
335void MappedWater::deactivateRefraction()
336{
337  glDisable(GL_CLIP_PLANE0);
338  glCullFace(GL_BACK);
339
340  // Create the texture and store it on the video card
341  mat.renderToTexture(1, GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureSize, textureSize);
342
343  glPopMatrix();
344  glPopAttrib();
345}
Note: See TracBrowser for help on using the repository browser.