Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/water/src/world_entities/environments/mapped_water.cc @ 8632

Last change on this file since 8632 was 8632, checked in by stefalie, 18 years ago

water: mighty reflection is still at the wrong place

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.getDiffuseTexture(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.getDiffuseTexture(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.