root/OpenSceneGraph/trunk/examples/osgoit/HeatMap.cpp @ 13556

Revision 13556, 8.6 kB (checked in by robert, 2 days ago)

Added shaders to support experimental shader based displacement mapping technique osgTerrain::ShaderTerrain?.

Line 
1/*
2 * 3D Heat map using vertex displacement mapping
3 * Rendered using depth peeling in fragment shader.
4 */
5
6#include <osg/Geode>
7#include <osg/Geometry>
8#include <osg/Vec3>
9#include <osg/MatrixTransform>
10#include <osg/PositionAttitudeTransform>
11#include <osg/LightModel>
12#include <osg/io_utils>
13#include <osg/Material>
14#include <osgDB/ReadFile>
15#include <osgDB/WriteFile>
16#include <osgGA/TrackballManipulator>
17#include <osgViewer/Viewer>
18#include <osg/Math>
19#include <iostream>
20
21#define _USE_MATH_DEFINES
22#include <math.h>
23
24#include <osg/TexEnv>
25#include <osg/TexMat>
26#include <osg/Depth>
27#include <osg/ShapeDrawable>
28#include <osg/Texture1D>
29#include <osg/Texture2D>
30#include <osg/PolygonMode>
31#include <osg/PolygonOffset>
32
33#include "HeatMap.h"
34#include "DepthPeeling.h"
35
36///////////////////////////////////////////////////////////////////////////
37// in-line GLSL source code
38
39static const char *VertexShader = {
40    "#version 120\n"
41    "uniform float maximum;\n"
42    "uniform float maxheight;\n"
43    "uniform float transparency;\n"
44    "uniform sampler1D colortex;\n"
45    "uniform sampler2D datatex;\n"
46    "in vec2  xypos;\n"
47    "void main(void)\n"
48    "{\n"
49    "    float foo;\n"
50    "    float tmp     = min(texture2D(datatex, xypos).x / maximum, 1.0);\n"
51    "    gl_Position   = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(0.0, 0.0, maxheight * tmp, 0.0));\n"
52    "    vec4 color    = texture1D(colortex, tmp);\n"
53    "    color.w       = color.w * transparency;\n"
54    "    gl_FrontColor = color;\n"
55    "    gl_BackColor  = color;\n"
56    "}\n"
57};
58
59static const char *FragmentShader =
60{
61    "#version 120\n"
62    "bool depthpeeling();\n"
63    "void main(void)\n"
64    "{\n"
65    "  if( depthpeeling() ) discard;\n"
66    "  gl_FragColor = gl_Color;\n"
67    "}\n"
68};
69
70/**
71 * Overloaded Geometry class to return predefined bounds
72 */
73class MyGeometry : public osg::Geometry
74{
75public:
76    MyGeometry(osg::BoundingBox bounds)
77    {
78        m_bounds = bounds;
79        m_bsphere = osg::BoundingSphere(bounds);
80    }
81
82    // an attempt to return a reasonable bounding box. Still does not prevent clipping of the heat map.
83    virtual const osg::BoundingBox& getBoundingBox() const {return m_bounds;}
84    virtual osg::BoundingBox computeBound() const {return m_bounds;}
85    virtual const osg::BoundingSphere& getBound() const {return m_bsphere;}
86
87protected:
88    osg::BoundingBox m_bounds;
89    osg::BoundingSphere m_bsphere;
90};
91
92Heatmap::Heatmap(float width, float depth, float maxheight, unsigned int K, unsigned int N, float maximum, float transparency)
93{
94    m_K = K;
95    m_N = N;
96    const int O = 4;
97
98    // create Geometry object to store all the vertices primitives.
99    osg::Geometry *meshGeom  = new MyGeometry(osg::BoundingBox(osg::Vec3(-width/2, -depth/2, 0), osg::Vec3(width/2, depth/2, maxheight)));
100
101    // we use a float attribute array storing texcoords
102    osg::Vec2Array* xypositions = new osg::Vec2Array();
103    xypositions->setName("xypos");
104
105    // create vertex coordinates
106    osg::Vec3Array* vertices = new osg::Vec3Array();
107    osg::Vec3 off(-width/2, -depth/2, 0);
108    for (unsigned int y=0; y < O*N; y++) {
109        if (y % 2 == 0)
110        {
111            for (unsigned int x=0; x < O*K; x++) {
112                vertices->push_back(osg::Vec3(width*x/(O*K-1), depth*y/(O*N-1), 0.0)+off);
113                xypositions->push_back(osg::Vec2(((float)x+0.5f)/(O*K),((float)y+0.5f)/(O*N)));
114            }
115        }
116        else
117        {
118            vertices->push_back(osg::Vec3(0, depth*y/(O*N-1), 0.0)+off);
119            xypositions->push_back(osg::Vec2(0.5f/(O*K),((float)y+0.5f)/(O*N)));
120            for (unsigned int x=0; x < O*K-1; x++) {
121                vertices->push_back(osg::Vec3(width*(0.5+x)/(O*K-1), depth*y/(O*N-1), 0.0)+off);
122                xypositions->push_back(osg::Vec2(((float)(x+0.5f)+0.5f)/(O*K),((float)y+0.5f)/(O*N)));
123            }
124            vertices->push_back(osg::Vec3(width, depth*y/(O*N-1), 0.0)+off);
125            xypositions->push_back(osg::Vec2(1.0f-0.5f/(O*K),((float)y+0.5f)/(O*N)));
126        }
127    }
128
129    meshGeom->setVertexAttribArray(6, xypositions);
130    meshGeom->setVertexAttribNormalize(6, false);
131    meshGeom->setVertexAttribBinding(6, osg::Geometry::BIND_PER_VERTEX);
132    meshGeom->setVertexArray(vertices);
133
134    // generate several tri strips to form a mesh
135    GLuint *indices = new GLuint[4*O*K];
136    for (unsigned int y=0; y < O*N-1; y++) {
137        if (y % 2 == 0)
138        {
139            int base  = (y/2) * (O*K+O*K+1);
140            int base2 = (y/2) * (O*K+O*K+1) + O*K;
141            int i=0; for (unsigned int x=0; x < O*K; x++) { indices[i++] = base2+x; indices[i++] = base+x;}
142            indices[i++] = base2+O*K;
143            meshGeom->addPrimitiveSet(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, i, indices));
144        }
145        else
146        {
147            int base = (y/2) * (O*K+O*K+1) + O*K;
148            int base2 = (y/2) * (O*K+O*K+1) + O*K + O*K+1;
149            int i=0; for (unsigned int x=0; x < O*K; x++) { indices[i++] = base+x; indices[i++] = base2+x;}
150            indices[i++] = base+O*K;
151            meshGeom->addPrimitiveSet(new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, i, indices));
152        }
153    }
154    delete[] indices;
155
156    // create vertex and fragment shader
157    osg::Program* program = new osg::Program;
158    program->setName( "mesh" );
159    program->addBindAttribLocation("xypos", 6);
160    program->addShader( new osg::Shader( osg::Shader::VERTEX, VertexShader ) );
161    program->addShader( new osg::Shader( osg::Shader::FRAGMENT, DepthPeeling::PeelingShader ) );
162    program->addShader( new osg::Shader( osg::Shader::FRAGMENT, FragmentShader ) );
163
164    // create a 1D texture for color lookups
165    colorimg = new osg::Image();
166    colorimg->allocateImage(5, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE);
167    unsigned char *data = colorimg->data();
168    *data++ =   0; *data++ =   0; *data++ = 255; *data++ =   0;  // fully transparent blue
169    *data++ =   0; *data++ = 255; *data++ = 255; *data++ = 255;  // turquoise
170    *data++ =   0; *data++ = 255; *data++ =   0; *data++ = 255;  // green
171    *data++ = 255; *data++ = 255; *data++ =   0; *data++ = 255;  // yellow
172    *data++ = 255; *data++ =   0; *data++ =   0; *data++ = 255;  // red
173    colortex = new osg::Texture1D(colorimg.get());
174    colortex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
175    colortex->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
176    colortex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
177    colortex->setResizeNonPowerOfTwoHint(false);
178
179    // create a 2D texture for data lookups
180    m_img2 = new osg::Image();
181    m_img2->allocateImage(K, N, 1, GL_LUMINANCE, GL_FLOAT);
182    m_img2->setInternalTextureFormat(GL_RGB32F_ARB);
183    m_data = (float*)m_img2.get()->data();
184    m_tex2 = new osg::Texture2D(m_img2.get());
185    m_tex2.get()->setResizeNonPowerOfTwoHint(false);
186    m_tex2.get()->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
187    m_tex2.get()->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
188    m_tex2.get()->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
189    m_tex2.get()->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
190
191    // set render states
192    osg::StateSet *meshstate = meshGeom->getOrCreateStateSet();
193    meshstate->setMode(GL_BLEND,  osg::StateAttribute::ON);
194    meshstate->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
195    meshstate->setAttributeAndModes(program, osg::StateAttribute::ON);
196    meshstate->setTextureAttributeAndModes(0,colortex.get(),osg::StateAttribute::ON);
197    meshstate->setTextureAttributeAndModes(1,m_tex2.get(),osg::StateAttribute::ON);
198
199    // uniforms for height and color scaling
200    maximumUniform = new osg::Uniform( "maximum", (float)maximum );
201    maxheightUniform = new osg::Uniform( "maxheight", (float)maxheight );
202    transparencyUniform = new osg::Uniform( "transparency", (float)transparency);
203
204    osg::Uniform* texUniform = new osg::Uniform(osg::Uniform::SAMPLER_1D, "colortex");
205    texUniform->set(0);
206    osg::Uniform* texUniform2 = new osg::Uniform(osg::Uniform::SAMPLER_2D, "datatex");
207    texUniform2->set(1);
208    meshstate->addUniform(texUniform);
209    meshstate->addUniform(texUniform2);
210    meshstate->addUniform(maximumUniform);
211    meshstate->addUniform(maxheightUniform);
212    meshstate->addUniform(transparencyUniform);
213
214    // add the geometries to the geode.
215    meshGeom->setUseDisplayList(false);
216    addDrawable(meshGeom);
217}
218
219void Heatmap::setData(float *buffer, float maxheight, float maximum, float transparency)
220{
221    memcpy(m_data, buffer, m_N*m_K*sizeof(float));
222
223    maximumUniform->set( maximum );
224    maxheightUniform->set( maxheight );
225    transparencyUniform->set ( transparency );
226
227    m_img2.get()->dirty();
228}
229
230Heatmap::~Heatmap()
231{
232}
Note: See TracBrowser for help on using the browser.