Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

water: cleanup… and hey: the mighty reflection is back :-)

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