1 /***********************************************************************
2 SurfaceRenderer - Class to render a surface defined by a regular grid in
4 Copyright (c) 2012-2018 Oliver Kreylos
6 This file is part of the Augmented Reality Sandbox (SARndbox).
8 The Augmented Reality Sandbox is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
13 The Augmented Reality Sandbox is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with the Augmented Reality Sandbox; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 ***********************************************************************/
23 #include "SurfaceRenderer.h"
27 #include <Misc/PrintInteger.h>
28 #include <Misc/ThrowStdErr.h>
29 #include <Misc/MessageLogger.h>
31 #include <GL/GLVertexArrayParts.h>
32 #include <GL/Extensions/GLARBFragmentShader.h>
33 #include <GL/Extensions/GLARBMultitexture.h>
34 #include <GL/Extensions/GLARBShaderObjects.h>
35 #include <GL/Extensions/GLARBTextureFloat.h>
36 #include <GL/Extensions/GLARBTextureRectangle.h>
37 #include <GL/Extensions/GLARBTextureRg.h>
38 #include <GL/Extensions/GLARBVertexShader.h>
39 #include <GL/Extensions/GLEXTFramebufferObject.h>
40 #include <GL/GLLightTracker.h>
41 #include <GL/GLContextData.h>
42 #include <GL/GLTransformationWrappers.h>
43 #include <GL/GLGeometryVertex.h>
45 #include "DepthImageRenderer.h"
46 #include "ElevationColorMap.h"
48 #include "WaterTable2.h"
49 #include "ShaderHelper.h"
52 /******************************************
53 Methods of class SurfaceRenderer::DataItem:
54 ******************************************/
56 SurfaceRenderer::DataItem::DataItem(void)
57 : contourLineFramebufferObject(0), contourLineDepthBufferObject(0),
58 contourLineColorTextureObject(0), contourLineVersion(0),
59 heightMapShader(0), surfaceSettingsVersion(0), lightTrackerVersion(0),
60 globalAmbientHeightMapShader(0), shadowedIlluminatedHeightMapShader(0) {
61 /* Initialize all required extensions: */
62 GLARBFragmentShader::initExtension();
63 GLARBMultitexture::initExtension();
64 GLARBShaderObjects::initExtension();
65 GLARBTextureFloat::initExtension();
66 GLARBTextureRectangle::initExtension();
67 GLARBTextureRg::initExtension();
68 GLARBVertexShader::initExtension();
69 GLEXTFramebufferObject::initExtension();
72 SurfaceRenderer::DataItem::~DataItem(void) {
73 /* Release all allocated buffers, textures, and shaders: */
74 glDeleteFramebuffersEXT(1, &contourLineFramebufferObject
);
75 glDeleteRenderbuffersEXT(1, &contourLineDepthBufferObject
);
76 glDeleteTextures(1, &contourLineColorTextureObject
);
77 glDeleteObjectARB(heightMapShader
);
78 glDeleteObjectARB(globalAmbientHeightMapShader
);
79 glDeleteObjectARB(shadowedIlluminatedHeightMapShader
);
82 /********************************
83 Methods of class SurfaceRenderer:
84 ********************************/
86 void SurfaceRenderer::shaderSourceFileChanged(const IO::FileMonitor::Event
& event
) {
87 /* Invalidate the single-pass surface shader: */
88 ++surfaceSettingsVersion
;
91 GLhandleARB
SurfaceRenderer::createSinglePassSurfaceShader(const GLLightTracker
& lt
,
92 GLint
* uniformLocations
) const {
93 GLhandleARB result
= 0;
95 std::vector
<GLhandleARB
> shaders
;
97 /*********************************************************************
98 Assemble and compile the surface rendering vertex shader:
99 *********************************************************************/
101 /* Assemble the function and declaration strings: */
102 std::string vertexFunctions
= "\
103 #extension GL_ARB_texture_rectangle : enable\n";
105 std::string vertexUniforms
= "\
106 uniform sampler2DRect depthSampler; // Sampler for the depth image-space elevation texture\n\
107 uniform mat4 depthProjection; // Transformation from depth image space to camera space\n\
108 uniform mat4 projectionModelviewDepthProjection; // Transformation from depth image space to clip space\n";
110 std::string vertexVaryings
;
112 /* Assemble the vertex shader's main function: */
113 std::string vertexMain
= "\
116 /* Get the vertex' depth image-space z coordinate from the texture: */\n\
117 vec4 vertexDic=gl_Vertex;\n\
118 vertexDic.z=texture2DRect(depthSampler,gl_Vertex.xy).r;\n\
120 /* Transform the vertex from depth image space to camera space and normalize it: */\n\
121 vec4 vertexCc=depthProjection*vertexDic;\n\
122 vertexCc/=vertexCc.w;\n\
126 /* Add declarations for DEM matching: */
128 uniform mat4 demTransform; // Transformation from camera space to DEM space\n\
129 uniform sampler2DRect demSampler; // Sampler for the DEM texture\n\
130 uniform float demDistScale; // Distance from surface to DEM at which the color map saturates\n";
133 varying float demDist; // Scaled signed distance from surface to DEM\n";
135 /* Add DEM matching code to vertex shader's main function: */
137 /* Transform the camera-space vertex to scaled DEM space: */\n\
138 vec4 vertexDem=demTransform*vertexCc;\n\
140 /* Calculate scaled DEM-surface distance: */\n\
141 demDist=(vertexDem.z-texture2DRect(demSampler,vertexDem.xy).r)*demDistScale;\n\
144 if(elevationColorMap
!= 0) {
145 /* Add declarations for height mapping: */
147 uniform vec4 heightColorMapPlaneEq; // Plane equation of the base plane in camera space, scaled for height map textures\n";
150 varying float heightColorMapTexCoord; // Texture coordinate for the height color map\n";
152 /* Add height mapping code to vertex shader's main function: */
154 /* Plug camera-space vertex into the scaled and offset base plane equation: */\n\
155 heightColorMapTexCoord=dot(heightColorMapPlaneEq,vertexCc);\n\
160 /* Add declarations for dipping bed rendering: */
161 if(dippingBedFolded
) {
163 uniform float dbc[5]; // Dipping bed coefficients\n";
166 uniform vec4 dippingBedPlaneEq; // Plane equation of the dipping bed\n";
170 varying float dippingBedDistance; // Vertex distance to dipping bed\n";
172 /* Add dipping bed code to vertex shader's main function: */
173 if(dippingBedFolded
) {
175 /* Calculate distance from camera-space vertex to dipping bed equation: */\n\
176 dippingBedDistance=vertexCc.z-(((1.0-dbc[3])+cos(dbc[0]*vertexCc.x)*dbc[3])*sin(dbc[1]*vertexCc.y)*dbc[2]+dbc[4]);\n\
180 /* Plug camera-space vertex into the dipping bed equation: */\n\
181 dippingBedDistance=dot(dippingBedPlaneEq,vertexCc);\n\
188 /* Add declarations for illumination: */
190 uniform mat4 modelview; // Transformation from camera space to eye space\n\
191 uniform mat4 tangentModelviewDepthProjection; // Transformation from depth image space to eye space for tangent planes\n";
194 varying vec4 diffColor,specColor; // Diffuse and specular colors, interpolated separately for correct highlights\n";
196 /* Add illumination code to vertex shader's main function: */
198 /* Calculate the vertex' tangent plane equation in depth image space: */\n\
200 tangentDic.x=texture2DRect(depthSampler,vec2(vertexDic.x-1.0,vertexDic.y)).r-texture2DRect(depthSampler,vec2(vertexDic.x+1.0,vertexDic.y)).r;\n\
201 tangentDic.y=texture2DRect(depthSampler,vec2(vertexDic.x,vertexDic.y-1.0)).r-texture2DRect(depthSampler,vec2(vertexDic.x,vertexDic.y+1.0)).r;\n\
203 tangentDic.w=-dot(vertexDic.xyz,tangentDic.xyz)/vertexDic.w;\n\
205 /* Transform the vertex and its tangent plane from depth image space to eye space: */\n\
206 vec4 vertexEc=modelview*vertexCc;\n\
207 vec3 normalEc=normalize((tangentModelviewDepthProjection*tangentDic).xyz);\n\
209 /* Initialize the color accumulators: */\n\
210 diffColor=gl_LightModel.ambient*gl_FrontMaterial.ambient;\n\
211 specColor=vec4(0.0,0.0,0.0,0.0);\n\
214 /* Call the appropriate light accumulation function for every enabled light source: */
215 bool firstLight
= true;
216 for(int lightIndex
= 0; lightIndex
< lt
.getMaxNumLights(); ++lightIndex
)
217 if(lt
.getLightState(lightIndex
).isEnabled()) {
218 /* Create the light accumulation function: */
219 vertexFunctions
.push_back('\n');
220 vertexFunctions
+= lt
.createAccumulateLightFunction(lightIndex
);
224 /* Call the light accumulation functions for all enabled light sources: */\n";
228 /* Call the light accumulation function from vertex shader's main function: */
232 vertexMain
.append(Misc::print(lightIndex
, liBuffer
+ 11));
234 "(vertexEc,normalEc,gl_FrontMaterial.ambient,gl_FrontMaterial.diffuse,gl_FrontMaterial.specular,gl_FrontMaterial.shininess,diffColor,specColor);\n";
241 if(waterTable
!= 0 && dem
== 0) {
242 /* Add declarations for water handling: */
244 uniform mat4 waterTransform; // Transformation from camera space to water level texture coordinate space\n";
246 varying vec2 waterTexCoord; // Texture coordinate for water level texture\n";
248 /* Add water handling code to vertex shader's main function: */
250 /* Transform the vertex from camera space to water level texture coordinate space: */\n\
251 waterTexCoord=(waterTransform*vertexCc).xy;\n\
255 /* Finish the vertex shader's main function: */
257 /* Transform vertex from depth image space to clip space: */\n\
258 gl_Position=projectionModelviewDepthProjection*vertexDic;\n\
261 /* Compile the vertex shader: */
262 shaders
.push_back(glCompileVertexShaderFromStrings(7, vertexFunctions
.c_str(), "\t\t\n",
263 vertexUniforms
.c_str(), "\t\t\n", vertexVaryings
.c_str(), "\t\t\n", vertexMain
.c_str()));
265 /*********************************************************************
266 Assemble and compile the surface rendering fragment shaders:
267 *********************************************************************/
269 /* Assemble the fragment shader's function declarations: */
270 std::string fragmentDeclarations
;
272 /* Assemble the fragment shader's uniform and varying variables: */
273 std::string fragmentUniforms
;
274 std::string fragmentVaryings
;
276 /* Assemble the fragment shader's main function: */
277 std::string fragmentMain
= "\
282 /* Add declarations for DEM matching: */
283 fragmentVaryings
+= "\
284 varying float demDist; // Scaled signed distance from surface to DEM\n";
286 /* Add DEM matching code to the fragment shader's main function: */
288 /* Calculate the fragment's color from a double-ramp function: */\n\
291 baseColor=mix(vec4(1.0,1.0,1.0,1.0),vec4(1.0,0.0,0.0,1.0),min(-demDist,1.0));\n\
293 baseColor=mix(vec4(1.0,1.0,1.0,1.0),vec4(0.0,0.0,1.0,1.0),min(demDist,1.0));\n\
296 if(elevationColorMap
!= 0) {
297 /* Add declarations for height mapping: */
298 fragmentUniforms
+= "\
299 uniform sampler1D heightColorMapSampler;\n";
300 fragmentVaryings
+= "\
301 varying float heightColorMapTexCoord; // Texture coordinate for the height color map\n";
303 /* Add height mapping code to the fragment shader's main function: */
305 /* Get the fragment's color from the height color map: */\n\
306 vec4 baseColor=texture1D(heightColorMapSampler,heightColorMapTexCoord);\n\
310 /* Set the surface's base color to white: */\n\
311 vec4 baseColor=vec4(1.0,1.0,1.0,1.0);\n\
316 /* Add declarations for dipping bed rendering: */
317 fragmentUniforms
+= "\
318 uniform float dippingBedThickness; // Thickness of dipping bed in camera-space units\n";
320 fragmentVaryings
+= "\
321 varying float dippingBedDistance; // Vertex distance to dipping bed plane\n";
323 /* Add dipping bed code to fragment shader's main function: */
325 /* Check fragment's dipping plane distance against dipping bed thickness: */\n\
326 float w=fwidth(dippingBedDistance)*1.0;\n\
327 if(dippingBedDistance<0.0)\n\
328 baseColor=mix(baseColor,vec4(1.0,0.0,0.0,1.0),smoothstep(-dippingBedThickness*0.5-w,-dippingBedThickness*0.5+w,dippingBedDistance));\n\
330 baseColor=mix(vec4(1.0,0.0,0.0,1.0),baseColor,smoothstep(dippingBedThickness*0.5-w,dippingBedThickness*0.5+w,dippingBedDistance));\n\
335 if(drawContourLines
) {
336 /* Declare the contour line function: */
337 fragmentDeclarations
+= "\
338 void addContourLines(in vec2,inout vec4);\n";
340 /* Compile the contour line shader: */
341 shaders
.push_back(compileFragmentShader("SurfaceAddContourLines"));
343 /* Call contour line function from fragment shader's main function: */
345 /* Modulate the base color by contour line color: */\n\
346 addContourLines(gl_FragCoord.xy,baseColor);\n\
351 /* Declare the illumination function: */
352 fragmentDeclarations
+= "\
353 void illuminate(inout vec4);\n";
355 /* Compile the illumination shader: */
356 shaders
.push_back(compileFragmentShader("SurfaceIlluminate"));
358 /* Call illumination function from fragment shader's main function: */
360 /* Apply illumination to the base color: */\n\
361 illuminate(baseColor);\n\
365 if(waterTable
!= 0 && dem
== 0) {
366 /* Declare the water handling functions: */
367 fragmentDeclarations
+= "\
368 void addWaterColor(in vec2,inout vec4);\n\
369 void addWaterColorAdvected(inout vec4);\n";
371 /* Compile the water handling shader: */
372 shaders
.push_back(compileFragmentShader("SurfaceAddWaterColor"));
374 /* Call water coloring function from fragment shader's main function: */
375 if(advectWaterTexture
) {
377 /* Modulate the base color with water color: */\n\
378 addWaterColorAdvected(baseColor);\n\
382 /* Modulate the base color with water color: */\n\
383 addWaterColor(gl_FragCoord.xy,baseColor);\n\
388 /* Finish the fragment shader's main function: */
390 /* Assign the final color to the fragment: */\n\
391 gl_FragColor=baseColor;\n\
394 /* Compile the fragment shader: */
395 shaders
.push_back(glCompileFragmentShaderFromStrings(7, fragmentDeclarations
.c_str(), "\t\t\n",
396 fragmentUniforms
.c_str(), "\t\t\n", fragmentVaryings
.c_str(), "\t\t\n", fragmentMain
.c_str()));
398 /* Link the shader program: */
399 result
= glLinkShader(shaders
);
401 /* Release all compiled shaders: */
402 for(std::vector
<GLhandleARB
>::iterator shIt
= shaders
.begin(); shIt
!= shaders
.end(); ++shIt
)
403 glDeleteObjectARB(*shIt
);
405 /*******************************************************************
406 Query the shader program's uniform locations:
407 *******************************************************************/
409 GLint
* ulPtr
= uniformLocations
;
411 /* Query common uniform variables: */
412 *(ulPtr
++) = glGetUniformLocationARB(result
, "depthSampler");
413 *(ulPtr
++) = glGetUniformLocationARB(result
, "depthProjection");
415 /* Query DEM matching uniform variables: */
416 *(ulPtr
++) = glGetUniformLocationARB(result
, "demTransform");
417 *(ulPtr
++) = glGetUniformLocationARB(result
, "demSampler");
418 *(ulPtr
++) = glGetUniformLocationARB(result
, "demDistScale");
419 } else if(elevationColorMap
!= 0) {
420 /* Query height color mapping uniform variables: */
421 *(ulPtr
++) = glGetUniformLocationARB(result
, "heightColorMapPlaneEq");
422 *(ulPtr
++) = glGetUniformLocationARB(result
, "heightColorMapSampler");
424 if(drawContourLines
) {
425 *(ulPtr
++) = glGetUniformLocationARB(result
, "pixelCornerElevationSampler");
426 *(ulPtr
++) = glGetUniformLocationARB(result
, "contourLineFactor");
430 *(ulPtr
++) = glGetUniformLocationARB(result
, "dbc");
432 *(ulPtr
++) = glGetUniformLocationARB(result
, "dippingBedPlaneEq");
433 *(ulPtr
++) = glGetUniformLocationARB(result
, "dippingBedThickness");
436 /* Query illumination uniform variables: */
437 *(ulPtr
++) = glGetUniformLocationARB(result
, "modelview");
438 *(ulPtr
++) = glGetUniformLocationARB(result
, "tangentModelviewDepthProjection");
440 if(waterTable
!= 0 && dem
== 0) {
441 /* Query water handling uniform variables: */
442 *(ulPtr
++) = glGetUniformLocationARB(result
, "waterTransform");
443 *(ulPtr
++) = glGetUniformLocationARB(result
, "bathymetrySampler");
444 *(ulPtr
++) = glGetUniformLocationARB(result
, "quantitySampler");
445 *(ulPtr
++) = glGetUniformLocationARB(result
, "waterCellSize");
446 *(ulPtr
++) = glGetUniformLocationARB(result
, "waterOpacity");
447 *(ulPtr
++) = glGetUniformLocationARB(result
, "waterAnimationTime");
449 *(ulPtr
++) = glGetUniformLocationARB(result
, "projectionModelviewDepthProjection");
451 /* Clean up and re-throw the exception: */
452 for(std::vector
<GLhandleARB
>::iterator shIt
= shaders
.begin(); shIt
!= shaders
.end(); ++shIt
)
453 glDeleteObjectARB(*shIt
);
460 void SurfaceRenderer::renderPixelCornerElevations(const int viewport
[4],
461 const PTransform
& projectionModelview
, GLContextData
& contextData
,
462 SurfaceRenderer::DataItem
* dataItem
) const {
463 /* Save the currently-bound frame buffer and clear color: */
464 GLint currentFrameBuffer
;
465 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT
, ¤tFrameBuffer
);
466 GLfloat currentClearColor
[4];
467 glGetFloatv(GL_COLOR_CLEAR_VALUE
, currentClearColor
);
469 /* Check if the contour line rendering frame buffer needs to be created: */
470 if(dataItem
->contourLineFramebufferObject
== 0) {
471 /* Initialize the frame buffer: */
472 for(int i
= 0; i
< 2; ++i
)
473 dataItem
->contourLineFramebufferSize
[i
] = 0;
474 glGenFramebuffersEXT(1, &dataItem
->contourLineFramebufferObject
);
475 glGenRenderbuffersEXT(1, &dataItem
->contourLineDepthBufferObject
);
476 glGenTextures(1, &dataItem
->contourLineColorTextureObject
);
479 /* Bind the contour line rendering frame buffer object: */
480 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, dataItem
->contourLineFramebufferObject
);
482 /* Check if the contour line frame buffer needs to be resized: */
483 if(dataItem
->contourLineFramebufferSize
[0] != (unsigned int)(viewport
[2] + 1)
484 || dataItem
->contourLineFramebufferSize
[1] != (unsigned int)(viewport
[3] + 1)) {
485 /* Remember if the render buffers must still be attached to the frame buffer: */
486 bool mustAttachBuffers
= dataItem
->contourLineFramebufferSize
[0] == 0
487 && dataItem
->contourLineFramebufferSize
[1] == 0;
489 /* Update the frame buffer size: */
490 for(int i
= 0; i
< 2; ++i
)
491 dataItem
->contourLineFramebufferSize
[i
] = (unsigned int)(viewport
[2 + i
] + 1);
493 /* Resize the topographic contour line rendering depth buffer: */
494 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, dataItem
->contourLineDepthBufferObject
);
495 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT
, GL_DEPTH_COMPONENT
,
496 dataItem
->contourLineFramebufferSize
[0], dataItem
->contourLineFramebufferSize
[1]);
497 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT
, 0);
499 /* Resize the topographic contour line rendering color texture: */
500 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->contourLineColorTextureObject
);
501 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
502 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
503 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
504 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
505 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB
, 0, GL_R32F
, dataItem
->contourLineFramebufferSize
[0],
506 dataItem
->contourLineFramebufferSize
[1], 0, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, 0);
507 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
509 if(mustAttachBuffers
) {
510 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT
, GL_DEPTH_ATTACHMENT_EXT
, GL_RENDERBUFFER_EXT
,
511 dataItem
->contourLineDepthBufferObject
);
512 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
, GL_COLOR_ATTACHMENT0_EXT
, GL_TEXTURE_RECTANGLE_ARB
,
513 dataItem
->contourLineColorTextureObject
, 0);
514 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT
);
515 glReadBuffer(GL_NONE
);
519 /* Extend the viewport to render the corners of all pixels: */
520 glViewport(0, 0, viewport
[2] + 1, viewport
[3] + 1);
521 glClearColor(0.0f
, 0.0f
, 0.0f
, 1.0f
);
522 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
524 /* Shift the projection matrix by half a pixel to render the corners of the final pixels: */
525 PTransform shiftedProjectionModelview
= projectionModelview
;
526 PTransform::Matrix
& spmm
= shiftedProjectionModelview
.getMatrix();
527 Scalar xs
= Scalar(viewport
[2]) / Scalar(viewport
[2] + 1);
528 Scalar ys
= Scalar(viewport
[3]) / Scalar(viewport
[3] + 1);
529 for(int j
= 0; j
< 4; ++j
) {
534 /* Render the surface elevation into the half-pixel offset frame buffer: */
535 depthImageRenderer
->renderElevation(shiftedProjectionModelview
, contextData
);
537 /* Restore the original viewport: */
538 glViewport(viewport
[0], viewport
[1], viewport
[2], viewport
[3]);
540 /* Restore the original clear color and frame buffer binding: */
541 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, currentFrameBuffer
);
542 glClearColor(currentClearColor
[0], currentClearColor
[1], currentClearColor
[2],
543 currentClearColor
[3]);
546 SurfaceRenderer::SurfaceRenderer(const DepthImageRenderer
* sDepthImageRenderer
)
547 : depthImageRenderer(sDepthImageRenderer
),
548 drawContourLines(true), contourLineFactor(1.0f
),
549 elevationColorMap(0),
550 drawDippingBed(false), dippingBedFolded(false),
551 dippingBedPlane(Plane::Vector(0, 0, 1), 0.0f
), dippingBedThickness(1),
552 dem(0), demDistScale(1.0f
),
554 waterTable(0), advectWaterTexture(false), waterOpacity(2.0f
),
555 surfaceSettingsVersion(1),
557 /* Copy the depth image size: */
558 for(int i
= 0; i
< 2; ++i
)
559 depthImageSize
[i
] = depthImageRenderer
->getDepthImageSize(i
);
561 /* Check if the depth projection matrix retains right-handedness: */
562 const PTransform
& depthProjection
= depthImageRenderer
->getDepthProjection();
563 Point p1
= depthProjection
.transform(Point(0, 0, 0));
564 Point p2
= depthProjection
.transform(Point(1, 0, 0));
565 Point p3
= depthProjection
.transform(Point(0, 1, 0));
566 Point p4
= depthProjection
.transform(Point(0, 0, 1));
567 bool depthProjectionInverts
= ((p2
- p1
) ^ (p3
- p1
)) * (p4
- p1
) < Scalar(0);
569 /* Calculate the transposed tangent plane depth projection: */
570 tangentDepthProjection
= Geometry::invert(depthProjection
);
571 if(depthProjectionInverts
)
572 tangentDepthProjection
*= PTransform::scale(PTransform::Scale(-1, -1, -1));
574 /* Monitor the external shader source files: */
575 fileMonitor
.addPath((std::string(CONFIG_SHADERDIR
) +
576 std::string("/SurfaceAddContourLines.fs")).c_str(), IO::FileMonitor::Modified
,
577 Misc::createFunctionCall(this, &SurfaceRenderer::shaderSourceFileChanged
));
578 fileMonitor
.addPath((std::string(CONFIG_SHADERDIR
) + std::string("/SurfaceIlluminate.fs")).c_str(),
579 IO::FileMonitor::Modified
, Misc::createFunctionCall(this,
580 &SurfaceRenderer::shaderSourceFileChanged
));
581 fileMonitor
.addPath((std::string(CONFIG_SHADERDIR
) +
582 std::string("/SurfaceAddWaterColor.fs")).c_str(), IO::FileMonitor::Modified
,
583 Misc::createFunctionCall(this, &SurfaceRenderer::shaderSourceFileChanged
));
584 fileMonitor
.startPolling();
587 void SurfaceRenderer::initContext(GLContextData
& contextData
) const {
588 /* Create a data item and add it to the context: */
589 DataItem
* dataItem
= new DataItem
;
590 contextData
.addDataItem(this, dataItem
);
592 /* Create the height map render shader: */
593 dataItem
->heightMapShader
= createSinglePassSurfaceShader(*contextData
.getLightTracker(),
594 dataItem
->heightMapShaderUniforms
);
595 dataItem
->surfaceSettingsVersion
= surfaceSettingsVersion
;
596 dataItem
->lightTrackerVersion
= contextData
.getLightTracker()->getVersion();
598 /* Create the global ambient height map render shader: */
599 dataItem
->globalAmbientHeightMapShader
=
600 linkVertexAndFragmentShader("SurfaceGlobalAmbientHeightMapShader");
601 dataItem
->globalAmbientHeightMapShaderUniforms
[0] = glGetUniformLocationARB(
602 dataItem
->globalAmbientHeightMapShader
, "depthSampler");
603 dataItem
->globalAmbientHeightMapShaderUniforms
[1] = glGetUniformLocationARB(
604 dataItem
->globalAmbientHeightMapShader
, "depthProjection");
605 dataItem
->globalAmbientHeightMapShaderUniforms
[2] = glGetUniformLocationARB(
606 dataItem
->globalAmbientHeightMapShader
, "basePlane");
607 dataItem
->globalAmbientHeightMapShaderUniforms
[3] = glGetUniformLocationARB(
608 dataItem
->globalAmbientHeightMapShader
, "pixelCornerElevationSampler");
609 dataItem
->globalAmbientHeightMapShaderUniforms
[4] = glGetUniformLocationARB(
610 dataItem
->globalAmbientHeightMapShader
, "contourLineFactor");
611 dataItem
->globalAmbientHeightMapShaderUniforms
[5] = glGetUniformLocationARB(
612 dataItem
->globalAmbientHeightMapShader
, "heightColorMapSampler");
613 dataItem
->globalAmbientHeightMapShaderUniforms
[6] = glGetUniformLocationARB(
614 dataItem
->globalAmbientHeightMapShader
, "heightColorMapTransformation");
615 dataItem
->globalAmbientHeightMapShaderUniforms
[7] = glGetUniformLocationARB(
616 dataItem
->globalAmbientHeightMapShader
, "waterLevelSampler");
617 dataItem
->globalAmbientHeightMapShaderUniforms
[8] = glGetUniformLocationARB(
618 dataItem
->globalAmbientHeightMapShader
, "waterLevelTextureTransformation");
619 dataItem
->globalAmbientHeightMapShaderUniforms
[9] = glGetUniformLocationARB(
620 dataItem
->globalAmbientHeightMapShader
, "waterOpacity");
622 /* Create the shadowed illuminated height map render shader: */
623 dataItem
->shadowedIlluminatedHeightMapShader
=
624 linkVertexAndFragmentShader("SurfaceShadowedIlluminatedHeightMapShader");
625 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[0] = glGetUniformLocationARB(
626 dataItem
->shadowedIlluminatedHeightMapShader
, "depthSampler");
627 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[1] = glGetUniformLocationARB(
628 dataItem
->shadowedIlluminatedHeightMapShader
, "depthProjection");
629 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[2] = glGetUniformLocationARB(
630 dataItem
->shadowedIlluminatedHeightMapShader
, "tangentDepthProjection");
631 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[3] = glGetUniformLocationARB(
632 dataItem
->shadowedIlluminatedHeightMapShader
, "basePlane");
633 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[4] = glGetUniformLocationARB(
634 dataItem
->shadowedIlluminatedHeightMapShader
, "pixelCornerElevationSampler");
635 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[5] = glGetUniformLocationARB(
636 dataItem
->shadowedIlluminatedHeightMapShader
, "contourLineFactor");
637 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[6] = glGetUniformLocationARB(
638 dataItem
->shadowedIlluminatedHeightMapShader
, "heightColorMapSampler");
639 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[7] = glGetUniformLocationARB(
640 dataItem
->shadowedIlluminatedHeightMapShader
, "heightColorMapTransformation");
641 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[8] = glGetUniformLocationARB(
642 dataItem
->shadowedIlluminatedHeightMapShader
, "waterLevelSampler");
643 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[9] = glGetUniformLocationARB(
644 dataItem
->shadowedIlluminatedHeightMapShader
, "waterLevelTextureTransformation");
645 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[10] = glGetUniformLocationARB(
646 dataItem
->shadowedIlluminatedHeightMapShader
, "waterOpacity");
647 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[11] = glGetUniformLocationARB(
648 dataItem
->shadowedIlluminatedHeightMapShader
, "shadowTextureSampler");
649 dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[12] = glGetUniformLocationARB(
650 dataItem
->shadowedIlluminatedHeightMapShader
, "shadowProjection");
653 void SurfaceRenderer::setDrawContourLines(bool newDrawContourLines
) {
654 drawContourLines
= newDrawContourLines
;
655 ++surfaceSettingsVersion
;
658 void SurfaceRenderer::setContourLineDistance(GLfloat newContourLineDistance
) {
659 /* Set the new contour line factor: */
660 contourLineFactor
= 1.0f
/ newContourLineDistance
;
663 void SurfaceRenderer::setElevationColorMap(ElevationColorMap
* newElevationColorMap
) {
664 /* Check if setting this elevation color map invalidates the shader: */
665 if(dem
== 0 && ((newElevationColorMap
!= 0 && elevationColorMap
== 0)
666 || (newElevationColorMap
== 0 && elevationColorMap
!= 0)))
667 ++surfaceSettingsVersion
;
669 /* Set the elevation color map: */
670 elevationColorMap
= newElevationColorMap
;
673 void SurfaceRenderer::setDrawDippingBed(bool newDrawDippingBed
) {
674 drawDippingBed
= newDrawDippingBed
;
675 ++surfaceSettingsVersion
;
678 void SurfaceRenderer::setDippingBedPlane(const SurfaceRenderer::Plane
& newDippingBedPlane
) {
679 /* Set the dipping bed mode to planar: */
680 if(dippingBedFolded
) {
681 dippingBedFolded
= false;
682 ++surfaceSettingsVersion
;
685 /* Set the dipping bed's plane equation: */
686 dippingBedPlane
= newDippingBedPlane
;
689 void SurfaceRenderer::setDippingBedCoeffs(const GLfloat newDippingBedCoeffs
[5]) {
690 /* Set the dipping bed mode to folded: */
691 if(!dippingBedFolded
) {
692 dippingBedFolded
= true;
693 ++surfaceSettingsVersion
;
696 /* Set the dipping bed's coefficients: */
697 for(int i
= 0; i
< 5; ++i
)
698 dippingBedCoeffs
[i
] = newDippingBedCoeffs
[i
];
701 void SurfaceRenderer::setDippingBedThickness(GLfloat newDippingBedThickness
) {
702 dippingBedThickness
= newDippingBedThickness
;
705 void SurfaceRenderer::setDem(DEM
* newDem
) {
706 /* Check if setting this DEM invalidates the shader: */
707 if((newDem
!= 0 && dem
== 0) || (newDem
== 0 && dem
!= 0))
708 ++surfaceSettingsVersion
;
710 /* Set the new DEM: */
714 void SurfaceRenderer::setDemDistScale(GLfloat newDemDistScale
) {
715 demDistScale
= newDemDistScale
;
718 void SurfaceRenderer::setIlluminate(bool newIlluminate
) {
719 illuminate
= newIlluminate
;
720 ++surfaceSettingsVersion
;
723 void SurfaceRenderer::setWaterTable(WaterTable2
* newWaterTable
) {
724 waterTable
= newWaterTable
;
725 ++surfaceSettingsVersion
;
728 void SurfaceRenderer::setAdvectWaterTexture(bool newAdvectWaterTexture
) {
729 advectWaterTexture
= false; // newAdvectWaterTexture;
730 ++surfaceSettingsVersion
;
733 void SurfaceRenderer::setWaterOpacity(GLfloat newWaterOpacity
) {
734 /* Set the new opacity factor: */
735 waterOpacity
= newWaterOpacity
;
738 void SurfaceRenderer::setAnimationTime(double newAnimationTime
) {
739 /* Set the new animation time: */
740 animationTime
= newAnimationTime
;
742 /* Poll the file monitor: */
743 fileMonitor
.processEvents();
746 void SurfaceRenderer::renderSinglePass(const int viewport
[4], const PTransform
& projection
,
747 const OGTransform
& modelview
, GLContextData
& contextData
) const {
748 /* Get the data item: */
749 DataItem
* dataItem
= contextData
.retrieveDataItem
<DataItem
>(this);
751 /* Calculate the required matrices: */
752 PTransform projectionModelview
= projection
;
753 projectionModelview
*= modelview
;
755 /* Check if contour line rendering is enabled: */
756 if(drawContourLines
) {
757 /* Run the first rendering pass to create a half-pixel offset texture of surface elevations: */
758 renderPixelCornerElevations(viewport
, projectionModelview
, contextData
, dataItem
);
759 } else if(dataItem
->contourLineFramebufferObject
!= 0) {
760 /* Delete the contour line rendering frame buffer: */
761 glDeleteFramebuffersEXT(1, &dataItem
->contourLineFramebufferObject
);
762 dataItem
->contourLineFramebufferObject
= 0;
763 glDeleteRenderbuffersEXT(1, &dataItem
->contourLineDepthBufferObject
);
764 dataItem
->contourLineDepthBufferObject
= 0;
765 glDeleteTextures(1, &dataItem
->contourLineColorTextureObject
);
766 dataItem
->contourLineColorTextureObject
= 0;
769 /* Check if the single-pass surface shader is outdated: */
770 if(dataItem
->surfaceSettingsVersion
!= surfaceSettingsVersion
|| (illuminate
771 && dataItem
->lightTrackerVersion
!= contextData
.getLightTracker()->getVersion())) {
772 /* Rebuild the shader: */
774 GLhandleARB newShader
= createSinglePassSurfaceShader(*contextData
.getLightTracker(),
775 dataItem
->heightMapShaderUniforms
);
776 glDeleteObjectARB(dataItem
->heightMapShader
);
777 dataItem
->heightMapShader
= newShader
;
778 } catch(const std::runtime_error
& err
) {
779 Misc::formattedUserError("SurfaceRenderer::renderSinglePass: Caught exception %s while rebuilding surface shader",
783 /* Mark the shader as up-to-date: */
784 dataItem
->surfaceSettingsVersion
= surfaceSettingsVersion
;
785 dataItem
->lightTrackerVersion
= contextData
.getLightTracker()->getVersion();
788 /* Bind the single-pass surface shader: */
789 glUseProgramObjectARB(dataItem
->heightMapShader
);
790 const GLint
* ulPtr
= dataItem
->heightMapShaderUniforms
;
792 /* Bind the current depth image texture: */
793 glActiveTextureARB(GL_TEXTURE0_ARB
);
794 depthImageRenderer
->bindDepthTexture(contextData
);
795 glUniform1iARB(*(ulPtr
++), 0);
797 /* Upload the depth projection matrix: */
798 depthImageRenderer
->uploadDepthProjection(*(ulPtr
++));
801 /* Upload the DEM transformation: */
802 dem
->uploadDemTransform(*(ulPtr
++));
804 /* Bind the DEM texture: */
805 glActiveTextureARB(GL_TEXTURE1_ARB
);
806 dem
->bindTexture(contextData
);
807 glUniform1iARB(*(ulPtr
++), 1);
809 /* Upload the DEM distance scale factor: */
810 glUniform1fARB(*(ulPtr
++), 1.0f
/ (demDistScale
* dem
->getVerticalScale()));
811 } else if(elevationColorMap
!= 0) {
812 /* Upload the texture mapping plane equation: */
813 elevationColorMap
->uploadTexturePlane(*(ulPtr
++));
815 /* Bind the height color map texture: */
816 glActiveTextureARB(GL_TEXTURE1_ARB
);
817 elevationColorMap
->bindTexture(contextData
);
818 glUniform1iARB(*(ulPtr
++), 1);
821 if(drawContourLines
) {
822 /* Bind the pixel corner elevation texture: */
823 glActiveTextureARB(GL_TEXTURE2_ARB
);
824 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->contourLineColorTextureObject
);
825 glUniform1iARB(*(ulPtr
++), 2);
827 /* Upload the contour line distance factor: */
828 glUniform1fARB(*(ulPtr
++), contourLineFactor
);
832 if(dippingBedFolded
) {
833 /* Upload the dipping bed coefficients: */
834 glUniformARB
<1>(*(ulPtr
++), 5, dippingBedCoeffs
);
836 /* Upload the dipping bed plane equation: */
838 for(int i
= 0; i
< 3; ++i
)
839 planeEq
[i
] = dippingBedPlane
.getNormal()[i
];
840 planeEq
[3] = -dippingBedPlane
.getOffset();
841 glUniformARB
<4>(*(ulPtr
++), 1, planeEq
);
844 /* Upload the dipping bed thickness: */
845 glUniform1fARB(*(ulPtr
++), dippingBedThickness
);
849 /* Upload the modelview matrix: */
850 glUniformARB(*(ulPtr
++), modelview
);
852 /* Calculate and upload the tangent-plane modelview depth projection matrix: */
853 PTransform tangentModelviewDepthProjection
= tangentDepthProjection
;
854 tangentModelviewDepthProjection
*= Geometry::invert(modelview
);
855 const Scalar
* tmdpPtr
= tangentModelviewDepthProjection
.getMatrix().getEntries();
857 GLfloat
* mPtr
= matrix
;
858 for(int i
= 0; i
< 16; ++i
, ++tmdpPtr
, ++mPtr
)
859 *mPtr
= GLfloat(*tmdpPtr
);
860 glUniformMatrix4fvARB(*(ulPtr
++), 1, GL_FALSE
, matrix
);
863 if(waterTable
!= 0 && dem
== 0) {
864 /* Upload the water table texture coordinate matrix: */
865 waterTable
->uploadWaterTextureTransform(*(ulPtr
++));
867 /* Bind the bathymetry texture: */
868 glActiveTextureARB(GL_TEXTURE3_ARB
);
869 waterTable
->bindBathymetryTexture(contextData
);
870 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
871 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
872 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
873 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
874 glUniform1iARB(*(ulPtr
++), 3);
876 /* Bind the quantities texture: */
877 glActiveTextureARB(GL_TEXTURE4_ARB
);
878 waterTable
->bindQuantityTexture(contextData
);
879 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
880 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
881 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
882 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
883 glUniform1iARB(*(ulPtr
++), 4);
885 /* Upload the water grid cell size for normal vector calculation: */
886 glUniformARB
<2>(*(ulPtr
++), 1, waterTable
->getCellSize());
888 /* Upload the water opacity factor: */
889 glUniform1fARB(*(ulPtr
++), waterOpacity
);
891 /* Upload the water animation time: */
892 glUniform1fARB(*(ulPtr
++), GLfloat(animationTime
));
895 /* Upload the combined projection, modelview, and depth unprojection matrix: */
896 PTransform projectionModelviewDepthProjection
= projectionModelview
;
897 projectionModelviewDepthProjection
*= depthImageRenderer
->getDepthProjection();
898 glUniformARB(*(ulPtr
++), projectionModelviewDepthProjection
);
900 /* Draw the surface: */
901 depthImageRenderer
->renderSurfaceTemplate(contextData
);
903 /* Unbind all textures and buffers: */
904 if(waterTable
!= 0 && dem
== 0) {
905 glActiveTextureARB(GL_TEXTURE4_ARB
);
906 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
907 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
908 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
909 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
910 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
911 glActiveTextureARB(GL_TEXTURE3_ARB
);
912 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
913 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
914 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
915 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
916 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
918 if(drawContourLines
) {
919 glActiveTextureARB(GL_TEXTURE2_ARB
);
920 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
923 glActiveTextureARB(GL_TEXTURE1_ARB
);
924 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
925 } else if(elevationColorMap
!= 0) {
926 glActiveTextureARB(GL_TEXTURE1_ARB
);
927 glBindTexture(GL_TEXTURE_1D
, 0);
929 glActiveTextureARB(GL_TEXTURE0_ARB
);
930 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
932 /* Unbind the height map shader: */
933 glUseProgramObjectARB(0);
938 void SurfaceRenderer::renderGlobalAmbientHeightMap(GLuint heightColorMapTexture
,
939 GLContextData
& contextData
) const {
940 /* Get the data item: */
941 DataItem
* dataItem
= contextData
.retrieveDataItem
<DataItem
>(this);
943 /* Check if contour line rendering is enabled: */
944 if(drawContourLines
) {
945 /* Run the first rendering pass to create a half-pixel offset texture of surface elevations: */
946 glPrepareContourLines(contextData
);
947 } else if(dataItem
->contourLineFramebufferObject
!= 0) {
948 /* Delete the contour line rendering frame buffer: */
949 glDeleteFramebuffersEXT(1, &dataItem
->contourLineFramebufferObject
);
950 dataItem
->contourLineFramebufferObject
= 0;
951 glDeleteRenderbuffersEXT(1, &dataItem
->contourLineDepthBufferObject
);
952 dataItem
->contourLineDepthBufferObject
= 0;
953 glDeleteTextures(1, &dataItem
->contourLineColorTextureObject
);
954 dataItem
->contourLineColorTextureObject
= 0;
957 /* Bind the global ambient height map shader: */
958 glUseProgramObjectARB(dataItem
->globalAmbientHeightMapShader
);
960 /* Bind the vertex and index buffers: */
961 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dataItem
->vertexBuffer
);
962 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, dataItem
->indexBuffer
);
964 /* Set up the depth image texture: */
965 if(!usePreboundDepthTexture
) {
966 glActiveTextureARB(GL_TEXTURE0_ARB
);
967 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->depthTexture
);
969 /* Check if the texture is outdated: */
970 if(dataItem
->depthTextureVersion
!= depthImageVersion
) {
971 /* Upload the new depth texture: */
972 glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB
, 0, 0, 0, size
[0], size
[1], GL_LUMINANCE
, GL_FLOAT
,
973 depthImage
.getBuffer());
975 /* Mark the depth texture as current: */
976 dataItem
->depthTextureVersion
= depthImageVersion
;
979 glUniform1iARB(dataItem
->globalAmbientHeightMapShaderUniforms
[0], 0);
981 /* Upload the depth projection matrix: */
982 glUniformMatrix4fvARB(dataItem
->globalAmbientHeightMapShaderUniforms
[1], 1, GL_FALSE
,
983 depthProjectionMatrix
);
985 /* Upload the base plane equation: */
986 glUniformARB
<4>(dataItem
->globalAmbientHeightMapShaderUniforms
[2], 1, basePlaneEq
);
988 /* Bind the pixel corner elevation texture: */
989 glActiveTextureARB(GL_TEXTURE1_ARB
);
990 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->contourLineColorTextureObject
);
991 glUniform1iARB(dataItem
->globalAmbientHeightMapShaderUniforms
[3], 1);
993 /* Upload the contour line distance factor: */
994 glUniform1fARB(dataItem
->globalAmbientHeightMapShaderUniforms
[4], contourLineFactor
);
996 /* Bind the height color map texture: */
997 glActiveTextureARB(GL_TEXTURE2_ARB
);
998 glBindTexture(GL_TEXTURE_1D
, heightColorMapTexture
);
999 glUniform1iARB(dataItem
->globalAmbientHeightMapShaderUniforms
[5], 2);
1001 /* Upload the height color map texture coordinate transformation: */
1002 glUniform2fARB(dataItem
->globalAmbientHeightMapShaderUniforms
[6], heightMapScale
, heightMapOffset
);
1004 if(waterTable
!= 0) {
1005 /* Bind the water level texture: */
1006 glActiveTextureARB(GL_TEXTURE3_ARB
);
1007 //waterTable->bindWaterLevelTexture(contextData);
1008 glUniform1iARB(dataItem
->globalAmbientHeightMapShaderUniforms
[7], 3);
1010 /* Upload the water table texture coordinate matrix: */
1011 glUniformMatrix4fvARB(dataItem
->globalAmbientHeightMapShaderUniforms
[8], 1, GL_FALSE
,
1012 waterTable
->getWaterTextureMatrix());
1014 /* Upload the water opacity factor: */
1015 glUniform1fARB(dataItem
->globalAmbientHeightMapShaderUniforms
[9], waterOpacity
);
1018 /* Draw the surface: */
1019 typedef GLGeometry::Vertex
<void, 0, void, 0, void, float, 3> Vertex
;
1020 GLVertexArrayParts::enable(Vertex::getPartsMask());
1021 glVertexPointer(static_cast<const Vertex
*>(0));
1022 for(unsigned int y
= 1; y
< size
[1]; ++y
)
1023 glDrawElements(GL_QUAD_STRIP
, size
[0] * 2, GL_UNSIGNED_INT
,
1024 static_cast<const GLuint
*>(0) + (y
- 1)*size
[0] * 2);
1025 GLVertexArrayParts::disable(Vertex::getPartsMask());
1027 /* Unbind all textures and buffers: */
1028 if(waterTable
!= 0) {
1029 glActiveTextureARB(GL_TEXTURE3_ARB
);
1030 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1032 glActiveTextureARB(GL_TEXTURE2_ARB
);
1033 glBindTexture(GL_TEXTURE_1D
, 0);
1034 glActiveTextureARB(GL_TEXTURE1_ARB
);
1035 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1036 if(!usePreboundDepthTexture
) {
1037 glActiveTextureARB(GL_TEXTURE0_ARB
);
1038 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1040 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
1041 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
1043 /* Unbind the global ambient height map shader: */
1044 glUseProgramObjectARB(0);
1047 void SurfaceRenderer::renderShadowedIlluminatedHeightMap(GLuint heightColorMapTexture
,
1048 GLuint shadowTexture
, const PTransform
& shadowProjection
, GLContextData
& contextData
) const {
1049 /* Get the data item: */
1050 DataItem
* dataItem
= contextData
.retrieveDataItem
<DataItem
>(this);
1052 /* Bind the shadowed illuminated height map shader: */
1053 glUseProgramObjectARB(dataItem
->shadowedIlluminatedHeightMapShader
);
1055 /* Bind the vertex and index buffers: */
1056 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, dataItem
->vertexBuffer
);
1057 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, dataItem
->indexBuffer
);
1059 /* Set up the depth image texture: */
1060 if(!usePreboundDepthTexture
) {
1061 glActiveTextureARB(GL_TEXTURE0_ARB
);
1062 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->depthTexture
);
1064 /* Check if the texture is outdated: */
1065 if(dataItem
->depthTextureVersion
!= depthImageVersion
) {
1066 /* Upload the new depth texture: */
1067 glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB
, 0, 0, 0, size
[0], size
[1], GL_LUMINANCE
, GL_FLOAT
,
1068 depthImage
.getBuffer());
1070 /* Mark the depth texture as current: */
1071 dataItem
->depthTextureVersion
= depthImageVersion
;
1074 glUniform1iARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[0], 0);
1076 /* Upload the depth projection matrix: */
1077 glUniformMatrix4fvARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[1], 1, GL_FALSE
,
1078 depthProjectionMatrix
);
1080 /* Upload the tangent-plane depth projection matrix: */
1081 glUniformMatrix4fvARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[2], 1, GL_FALSE
,
1082 tangentDepthProjectionMatrix
);
1084 /* Upload the base plane equation: */
1085 glUniformARB
<4>(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[3], 1, basePlaneEq
);
1087 /* Bind the pixel corner elevation texture: */
1088 glActiveTextureARB(GL_TEXTURE1_ARB
);
1089 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, dataItem
->contourLineColorTextureObject
);
1090 glUniform1iARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[4], 1);
1092 /* Upload the contour line distance factor: */
1093 glUniform1fARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[5], contourLineFactor
);
1095 /* Bind the height color map texture: */
1096 glActiveTextureARB(GL_TEXTURE2_ARB
);
1097 glBindTexture(GL_TEXTURE_1D
, heightColorMapTexture
);
1098 glUniform1iARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[6], 2);
1100 /* Upload the height color map texture coordinate transformation: */
1101 glUniform2fARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[7], heightMapScale
,
1104 if(waterTable
!= 0) {
1105 /* Bind the water level texture: */
1106 glActiveTextureARB(GL_TEXTURE3_ARB
);
1107 //waterTable->bindWaterLevelTexture(contextData);
1108 glUniform1iARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[8], 3);
1110 /* Upload the water table texture coordinate matrix: */
1111 glUniformMatrix4fvARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[9], 1, GL_FALSE
,
1112 waterTable
->getWaterTextureMatrix());
1114 /* Upload the water opacity factor: */
1115 glUniform1fARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[10], waterOpacity
);
1118 /* Bind the shadow texture: */
1119 glActiveTextureARB(GL_TEXTURE4_ARB
);
1120 glBindTexture(GL_TEXTURE_2D
, shadowTexture
);
1121 glUniform1iARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[11], 4);
1123 /* Upload the combined shadow viewport, shadow projection and modelview, and depth projection matrix: */
1124 PTransform
spdp(1.0);
1125 spdp
.getMatrix()(0, 0) = 0.5;
1126 spdp
.getMatrix()(0, 3) = 0.5;
1127 spdp
.getMatrix()(1, 1) = 0.5;
1128 spdp
.getMatrix()(1, 3) = 0.5;
1129 spdp
.getMatrix()(2, 2) = 0.5;
1130 spdp
.getMatrix()(2, 3) = 0.5;
1131 spdp
*= shadowProjection
;
1132 spdp
*= depthProjection
;
1133 GLfloat spdpMatrix
[16];
1134 GLfloat
* spdpPtr
= spdpMatrix
;
1135 for(int j
= 0; j
< 4; ++j
)
1136 for(int i
= 0; i
< 4; ++i
, ++spdpPtr
)
1137 *spdpPtr
= GLfloat(spdp
.getMatrix()(i
, j
));
1138 glUniformMatrix4fvARB(dataItem
->shadowedIlluminatedHeightMapShaderUniforms
[12], 1, GL_FALSE
,
1141 /* Draw the surface: */
1142 typedef GLGeometry::Vertex
<void, 0, void, 0, void, float, 3> Vertex
;
1143 GLVertexArrayParts::enable(Vertex::getPartsMask());
1144 glVertexPointer(static_cast<const Vertex
*>(0));
1145 for(unsigned int y
= 1; y
< size
[1]; ++y
)
1146 glDrawElements(GL_QUAD_STRIP
, size
[0] * 2, GL_UNSIGNED_INT
,
1147 static_cast<const GLuint
*>(0) + (y
- 1)*size
[0] * 2);
1148 GLVertexArrayParts::disable(Vertex::getPartsMask());
1150 /* Unbind all textures and buffers: */
1151 if(waterTable
!= 0) {
1152 glActiveTextureARB(GL_TEXTURE3_ARB
);
1153 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1155 glActiveTextureARB(GL_TEXTURE2_ARB
);
1156 glBindTexture(GL_TEXTURE_1D
, 0);
1157 glActiveTextureARB(GL_TEXTURE1_ARB
);
1158 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1159 if(!usePreboundDepthTexture
) {
1160 glActiveTextureARB(GL_TEXTURE0_ARB
);
1161 glBindTexture(GL_TEXTURE_RECTANGLE_ARB
, 0);
1163 glBindBufferARB(GL_ARRAY_BUFFER_ARB
, 0);
1164 glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB
, 0);
1166 /* Unbind the shadowed illuminated height map shader: */
1167 glUseProgramObjectARB(0);