Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

water: cleanup and waste of time, but i got nothing better to do ;-)

File size: 11.6 KB
RevLine 
[7796]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"
[8037]20#include "state.h"
[7796]21
22
23CREATE_FACTORY(MappedWater, CL_MAPPED_WATER);
24
[8482]25/**
26 * @brief constructor
27 * @param root xml data
28 */
[7796]29MappedWater::MappedWater(const TiXmlElement* root)
30{
31  this->setClassID(CL_MAPPED_WATER, "MappedWater");
32  this->toList(OM_ENVIRON);
33
[8628]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{
[8622]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);
[8617]69  this->setNormalMapScale(0.25f);
70
[8628]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}
[8622]78
[8628]79/**
80 * @brief initialization of the textures
81 */
82void MappedWater::initTextures()
83{
[8587]84  // sets parameters for the textures
85  this->textureSize = 512;
[8488]86  unsigned int channels = 32;
87  GLenum type = GL_RGBA;
[8628]88
[7796]89  // set up refleciton texture
[8587]90  Texture reflTex(GL_TEXTURE_2D, this->textureSize, this->textureSize, channels, type);
91  mat.setDiffuseMap(reflTex, 0);
[8628]92  // set up refraction texture
[8587]93  Texture refrTex(GL_TEXTURE_2D, this->textureSize, this->textureSize, channels, type);
94  mat.setDiffuseMap(refrTex, 1);
[7796]95  // load normal map
[8312]96  mat.setDiffuseMap("pictures/normalmap.bmp", GL_TEXTURE_2D, 2);
[7796]97  // load dudv map
[8312]98  mat.setDiffuseMap("pictures/dudvmap.bmp", GL_TEXTURE_2D, 3);
[7796]99
[8628]100  // sets texture parameters for reflection texture
[7796]101  glBindTexture(GL_TEXTURE_2D, this->mat.getDiffuseTexture(0));
[8312]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);
[8628]106  // sets texture parameters for refraction texture
[8037]107  glBindTexture(GL_TEXTURE_2D, this->mat.getDiffuseTexture(1));
[7796]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);
[8484]112}
113
114/**
115 * @brief initialization of the shaders
116 */
117void MappedWater::initShaders()
118{
[8037]119  // load shader files
[8312]120  shader = new Shader( ResourceManager::getInstance()->getDataDir() + "/shaders/mapped_water.vert", ResourceManager::getInstance()->getDataDir() +"/shaders/mapped_water.frag");
[8037]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
[8312]132  Shader::Uniform(shader, "depthMap").set(2);
[8037]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
[8312]140  this->shader->deactivateShader();
[7796]141}
142
[8482]143/**
144 * @brief ends the refraction and saves the graphic buffer into a texture
145 * @param root xml data
146 */
[7796]147void MappedWater::loadParams(const TiXmlElement* root)
148{
149  WorldEntity::loadParams(root);
150
[8477]151  LoadParam(root, "waterpos", this, MappedWater, setWaterPos);
152  LoadParam(root, "watersize", this, MappedWater, setWaterSize);
[8622]153  LoadParam(root, "lightpos", this, MappedWater, setLightPos);
[8482]154  LoadParam(root, "wateruv", this, MappedWater, setWaterUV);
155  LoadParam(root, "waterflow", this, MappedWater, setWaterFlow);
[8617]156  LoadParam(root, "normalmapscale", this, MappedWater, setNormalMapScale);
[8622]157  LoadParam(root, "waterangle", this, MappedWater, setWaterAngle);
[7796]158}
159
[8482]160/**
161 * @brief activates the water shader and draws a quad with four textures on it
162 */
[7796]163void MappedWater::draw() const
164{
[8312]165  glMatrixMode(GL_MODELVIEW);
166
[7796]167  glPushMatrix();
[8586]168  glTranslatef(this->waterPos.x ,0 ,this->waterPos.z);
[8622]169  glRotatef(this->waterAngle, 0, 1, 0);
[7796]170
171  mat.select();
172
[8312]173  this->shader->activateShader();
[7796]174
[8037]175  // reset the camera uniform to the current cam position
176  Vector pos = State::getCameraNode()->getAbsCoor();
[8312]177  cam_uni->set(pos.x, pos.y, pos.z, 1.0f);
[7796]178
[8587]179  glDisable(GL_BLEND);
180
[8037]181  glBegin(GL_QUADS);
182  // The back left vertice for the water
[8628]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
[8037]186  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                       // DUDV map texture
[8628]187  glVertex3f(0, this->waterPos.y, 0);
[7796]188
[8037]189  // The front left vertice for the water
[8628]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
[8037]193  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
[8628]194  glVertex3f(0, this->waterPos.y, this->zWidth);
[7796]195
[8037]196  // The front right vertice for the water
[8628]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
[8037]200  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
[8477]201  glVertex3f(this->xWidth, this->waterPos.y, this->zWidth);
[7796]202
[8037]203  // The back right vertice for the water
[8617]204  glMultiTexCoord2f(GL_TEXTURE0, waterUV, waterUV);        // Reflection texture
205  glMultiTexCoord2f(GL_TEXTURE1, waterUV, waterUV - move);       // Refraction texture
[8037]206  glMultiTexCoord2f(GL_TEXTURE2, normalUV, normalUV + move2);  // Normal map texture
207  glMultiTexCoord2f(GL_TEXTURE3, 0, 0);                        // DUDV map texture
[8628]208  glVertex3f(this->xWidth, this->waterPos.y, 0);
[8037]209  glEnd();
[7796]210
[8312]211  this->shader->deactivateShader();
[7796]212
[8037]213  mat.unselect();
[7796]214
215  glPopMatrix();
216}
217
[8482]218/**
219 * @brief tick tack, calculates the flow of the water
220 */
[7796]221void MappedWater::tick(float dt)
222{
[8037]223  // makes the water flow
[8617]224  this->move += this->waterFlow * dt;
[8037]225  this->move2 = this->move * this->kNormalMapScale;
[7796]226}
227
[8482]228/**
229 * @brief prepares everything to render the reflection texutre
230 */
[7796]231void MappedWater::activateReflection()
232{
[8482]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
[8037]243  // save viewport matrix and change the viewport size
[7796]244  glPushAttrib(GL_VIEWPORT_BIT);
245  glViewport(0,0, textureSize, textureSize);
246
[8312]247  glMatrixMode(GL_MODELVIEW);
[8037]248  glPushMatrix();
[7796]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.
[8037]253  glEnable(GL_CLIP_PLANE0);
254  Vector pos = State::getCameraNode()->getAbsCoor();
[8482]255
[8467]256  if(pos.y > waterPos.y)
[8037]257  {
258    // Translate the world, then flip it upside down
[8628]259    glTranslatef(0, waterPos.y*2, 0);
260    glScalef(1, -1, 1);
[7796]261
[8037]262    // Since the world is updside down we need to change the culling to FRONT
263    glCullFace(GL_FRONT);
[7796]264
[8037]265    // Set our plane equation and turn clipping on
[8628]266    double plane[4] = {0, 1, 0, -waterPos.y};
[8037]267    glClipPlane(GL_CLIP_PLANE0, plane);
268  }
269  else
[7796]270  {
[8037]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.
[8628]273    double plane[4] = {0, 1, 0, waterPos.y};
[8037]274    glClipPlane(GL_CLIP_PLANE0, plane);
275  }
[7796]276}
277
[8482]278/**
279 * @brief ends the reflection and saves the graphic buffer into a texture
280 */
[7796]281void MappedWater::deactivateReflection()
282{
[8037]283  glDisable(GL_CLIP_PLANE0);
284  glCullFace(GL_BACK);
[7796]285
[8312]286  // Create the texture and store it on the video card
[8484]287  mat.renderToTexture(0, GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureSize, textureSize);
[8312]288
[8037]289  glPopMatrix();
[7796]290  glPopAttrib();
291}
292
[8482]293/**
294 * @brief prepares everything to render the refraction texutre
295 */
[7796]296void MappedWater::activateRefraction()
[8482]297{
[8037]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
[8312]307  glMatrixMode(GL_MODELVIEW);
[8037]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();
[8467]318  if(pos.y > waterPos.y)
[8037]319  {
[8628]320    double plane[4] = {0, -1, 0, waterPos.y}; 
[8037]321    glClipPlane(GL_CLIP_PLANE0, plane);
[8312]322
[8037]323  }
324  // If the camera is below the water, only render the data above the water
325  else
326  {
327    glCullFace(GL_FRONT);
[8628]328    double plane[4] = {0, 1, 0, -waterPos.y}; 
[8037]329    glClipPlane(GL_CLIP_PLANE0, plane);
330  }
[7796]331}
332
[8482]333/**
334 * @brief ends the refraction and saves the graphic buffer into a texture
335 */
[7796]336void MappedWater::deactivateRefraction()
337{
[8037]338  glDisable(GL_CLIP_PLANE0);
339  glCullFace(GL_BACK);
340
[8312]341  // Create the texture and store it on the video card
[8484]342  mat.renderToTexture(1, GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureSize, textureSize);
[8312]343
344  glPopMatrix();
345  glPopAttrib();
[7796]346}
Note: See TracBrowser for help on using the repository browser.