~ubuntu-branches/ubuntu/precise/openwalnut/precise

« back to all changes in this revision

Viewing changes to src/modules/superquadricGlyphs/shaders/WMSuperquadricGlyphs-fragment.glsl

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Eichelbaum
  • Date: 2011-06-21 10:26:54 UTC
  • Revision ID: james.westby@ubuntu.com-20110621102654-rq0zf436q949biih
Tags: upstream-1.2.5
ImportĀ upstreamĀ versionĀ 1.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------
 
2
//
 
3
// Project: OpenWalnut ( http://www.openwalnut.org )
 
4
//
 
5
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
 
6
// For more information see http://www.openwalnut.org/copying
 
7
//
 
8
// This file is part of OpenWalnut.
 
9
//
 
10
// OpenWalnut is free software: you can redistribute it and/or modify
 
11
// it under the terms of the GNU Lesser General Public License as published by
 
12
// the Free Software Foundation, either version 3 of the License, or
 
13
// (at your option) any later version.
 
14
//
 
15
// OpenWalnut is distributed in the hope that it will be useful,
 
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
// GNU Lesser General Public License for more details.
 
19
//
 
20
// You should have received a copy of the GNU Lesser General Public License
 
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
 
22
//
 
23
//---------------------------------------------------------------------------
 
24
 
 
25
#version 120
 
26
 
 
27
#include "WGEShadingTools.glsl"
 
28
 
 
29
// commonly used variables
 
30
#include "WMSuperquadricGlyphs-varyings.glsl"
 
31
 
 
32
// tollerance value for float comparisons
 
33
float zeroTollerance = 0.01;
 
34
 
 
35
#define RenderMode_Superquadric
 
36
//#define RenderMode_Ellipsoid
 
37
 
 
38
/////////////////////////////////////////////////////////////////////////////////////////////
 
39
// GPU Super Quadrics -- fragment shader -- sPow
 
40
//
 
41
// This function extends the "pow" function with features to handle negative base values.
 
42
/////////////////////////////////////////////////////////////////////////////////////////////
 
43
float sPow( float x, float y )
 
44
{
 
45
    if( y == 0.0 )
 
46
    {
 
47
        return 1.0;
 
48
    }
 
49
    else
 
50
    {
 
51
        return pow( abs( x ), y );
 
52
    }
 
53
}
 
54
 
 
55
/////////////////////////////////////////////////////////////////////////////////////////////
 
56
// GPU Super Quadrics -- fragment shader -- superquadric
 
57
//
 
58
// This function calculates allmost every value at a given point (the value of the
 
59
// superquadric function, gradient and derivate)
 
60
//
 
61
// Parameters:
 
62
// viewDir:     viewing direction vector
 
63
// planePoint:  point on projection plane
 
64
// t:           current point on ray
 
65
// ray:         returns position on ray
 
66
// gradient:    the gradient vector at current ray point
 
67
// sqd:         value of derived function at current ray point
 
68
//
 
69
// Returns:
 
70
//              The function value of the superquadrics function at current point
 
71
/////////////////////////////////////////////////////////////////////////////////////////////
 
72
float superquadric( vec3 viewDir, vec3 planePoint, float t, out vec3 ray, out vec3 gradient, out float sqd )
 
73
{
 
74
    ray = planePoint.xyz + t*viewDir.xyz;
 
75
 
 
76
    // those values will be needed multiple times ...
 
77
    float rayXYPow = sPow( ray.x, v_alphaBeta.x ) + sPow( ray.y, v_alphaBeta.x );
 
78
    float rayZPow = sPow( ray.z, v_alphaBeta.y );
 
79
 
 
80
    // the value at given position
 
81
    float sq = sPow( rayXYPow, v_alphaBeta.z ) + rayZPow  - 1.0;
 
82
 
 
83
    // calculate squadric value for current t
 
84
 
 
85
    // if we get a hit we need those values for calculating the gradient at the hit point
 
86
    // if we do not get a hit we use those values for calculating the derivation at the current point
 
87
    // for doing the next newton step
 
88
 
 
89
    /////////////////// HINT ///////////////////
 
90
    // If we derive sign(x)*pow(abs(x),y) we use product rule to get:
 
91
    //                    sign' * pow + sign * pow'
 
92
    // Well the derived sign function is nothing else than the unit impulse delta.
 
93
    // It is              delta<>0 iff x=0
 
94
    // And also           x=0 -> pow(x, y)=0
 
95
    // so delta(x)*pow(x) will allways be 0 ... we can drop it
 
96
    //
 
97
    // ==> y * sign(x)* sPow(x, y-1.0);
 
98
 
 
99
 
 
100
    float a  = sign( rayXYPow ) * sPow( rayXYPow, v_alphaBeta.z - 1.0 );
 
101
    float b1 = sign( ray.x ) * sPow( ray.x, v_alphaBeta.x - 1.0 );
 
102
 
 
103
    float b2 = sign( ray.y ) * sPow( ray.y, v_alphaBeta.x - 1.0 );
 
104
    float c = v_alphaBeta.y  * sign( ray.z ) * sPow( ray.z, v_alphaBeta.y  - 1.0 );
 
105
 
 
106
    // now we can reuse some values to calculate the gradient vector at the hit point
 
107
    gradient = vec3( v_alphaBeta.y * a * b1, v_alphaBeta.y * a * b2, c );
 
108
 
 
109
    // calculate the derived function, reuse as much previously calculated values as possible
 
110
    sqd = dot( gradient, viewDir );
 
111
 
 
112
    // thats it, return value at current point
 
113
    return sq;
 
114
}
 
115
 
 
116
/////////////////////////////////////////////////////////////////////////////////////////////
 
117
// GPU Super Quadrics -- fragment shader -- superquadric
 
118
//
 
119
// This function is the "light" version of the above one. It just calculates the result of
 
120
// the superquadrics function.
 
121
//
 
122
// Parameters:
 
123
// viewDir:     viewing direction vector
 
124
// planePoint:  point on projection plane
 
125
// t:           current point on ray
 
126
//
 
127
// Returns:
 
128
//              The function value of the superquadrics function at current point
 
129
/////////////////////////////////////////////////////////////////////////////////////////////
 
130
float superquadric( vec3 viewDir, vec3 planePoint, float t )
 
131
{
 
132
    vec3 ray = planePoint.xyz + t*viewDir.xyz;
 
133
 
 
134
    // those values will be needed multiple times ...
 
135
    float rayXYPow = sPow( ray.x, v_alphaBeta.x ) + sPow( ray.y, v_alphaBeta.x );
 
136
    float rayZPow = sPow( ray.z, v_alphaBeta.y );
 
137
 
 
138
    // the value at given position
 
139
    float sq = sPow( rayXYPow, v_alphaBeta.z ) + rayZPow  - 1.0;
 
140
 
 
141
    // thats it, return value at current point
 
142
    return sq;
 
143
}
 
144
 
 
145
/////////////////////////////////////////////////////////////////////////////////////////////
 
146
// GPU Super Quadrics -- fragment shader -- main
 
147
/////////////////////////////////////////////////////////////////////////////////////////////
 
148
void main( void )
 
149
{
 
150
    // filter out glyphs whose anisotropy is smaller than the threshold or where the eigenvalues
 
151
    // are below the threshold (alphaBeta.w is != if this is the case)
 
152
    if( v_alphaBeta.w > 0.0 )
 
153
    {
 
154
        discard;
 
155
    }
 
156
 
 
157
    /////////////////////////////////////////////////////////////////////////////////////////////
 
158
    // 1: try to find a goot start value for newton iteration
 
159
    /////////////////////////////////////////////////////////////////////////////////////////////
 
160
 
 
161
    // well the following value is quite empiric but it works well with squadrics whose beta<=alpha<=1.0
 
162
    // HINT: if the ray hits the surface of the glyph lastT will allways be negative!
 
163
    float lastT = 0.0;
 
164
    int numNewtonLoops = 10;
 
165
 
 
166
    // this vector stores the gradient if there has been a hit
 
167
    vec3 grad = vec3( 0.0, 0.0, 1.0 );
 
168
 
 
169
    // some vars that will be needed later
 
170
    // got a hit?
 
171
    bool hit = false;
 
172
    vec3 hitPoint = vec3( 0.0, 0.0, 0.0 );
 
173
 
 
174
#ifdef RenderMode_Superquadric // Superquadric based rendermode
 
175
 
 
176
    /////////////////////////////////////////////////////////////////////////////////////////////
 
177
    // 2: newton iteration to determine roots of the superquadric-ray intersection
 
178
    /////////////////////////////////////////////////////////////////////////////////////////////
 
179
 
 
180
    // now try to calculate the intersection of the given ray with the superquadric.
 
181
    // here we are using newtons iterative method for finding roots
 
182
 
 
183
    // the iteration loop (NOTE: due to the fact that the shaders do not support an at compile time unknown loop count we set it to
 
184
    // this quite empiric value (which works well (for at least the squadrics with beta<=alpha<=1.0))
 
185
    for( int i = 0; i < numNewtonLoops; i++ )
 
186
    {
 
187
        // calculate all needed values
 
188
        float sqd = 0.0;
 
189
        float sq = superquadric( v_viewDir.xyz, v_planePoint.xyz, lastT, hitPoint, grad, sqd );
 
190
 
 
191
        // new ray parameter
 
192
        float newT = lastT - ( sq / sqd );
 
193
 
 
194
        // near enough?
 
195
        // or has t not changed much since last iteration?
 
196
        if( !hit && ( ( abs( sq ) <= zeroTollerance ) || ( abs( newT - lastT ) < zeroTollerance ) ) )
 
197
        {
 
198
            hit = true;
 
199
            break;
 
200
        }
 
201
 
 
202
        // if the ray parameter starts to jump around (it should get smaller step by step (because lastT is negative))
 
203
        // NOTE: this speeds up rendering at rays that will miss the glyph (round about 50% faster!)
 
204
        if( newT > lastT )
 
205
            break;
 
206
 
 
207
        // not near enough -> another newton step
 
208
        lastT = newT;
 
209
    }
 
210
 
 
211
#endif
 
212
 
 
213
#ifdef RenderMode_Ellipsoid // Render ellipsoids
 
214
 
 
215
/////////////////////////////////////////////////////////////////////////////////////////////
 
216
// 2: solve ellipsoid equation to determine roots of the intersection
 
217
/////////////////////////////////////////////////////////////////////////////////////////////
 
218
 
 
219
    float A = dot( v_viewDir.xyz, v_viewDir.xyz );
 
220
    float B = 2.0 * dot( v_viewDir.xyz, v_planePoint.xyz );
 
221
    float C = dot( v_planePoint.xyz, v_planePoint.xyz ) - 1.0;
 
222
 
 
223
    // try to solve At^2 + Bt + C = 0
 
224
    float discriminant = ( B * B ) - ( 4.0 * A * C );
 
225
 
 
226
    // no solution
 
227
    if( discriminant <= 0.0 )
 
228
    {
 
229
        discard;
 
230
    }
 
231
 
 
232
    // there will be a solution
 
233
    hit = true;
 
234
 
 
235
    // use solution formula
 
236
    float twoAinv = 1.0 / ( 2.0 * A );
 
237
    float root = sqrt( discriminant );
 
238
    float t1 = ( -B + root ) * twoAinv;
 
239
    float t2 = ( -B - root ) * twoAinv;
 
240
 
 
241
    lastT = min( t1, t2 );
 
242
    if( lastT < 0.0 )
 
243
    {
 
244
        discard;
 
245
    }
 
246
 
 
247
    // on a sphere surface the normal is allways the vector from the middle point (in our case (0,0,0))
 
248
    // to the surface point
 
249
    grad = -( v_planePoint.xyz + v_viewDir.xyz * lastT );
 
250
 
 
251
#endif
 
252
 
 
253
    /////////////////////////////////////////////////////////////////////////////////////////////
 
254
    // 3: draw or discard the pixel
 
255
    /////////////////////////////////////////////////////////////////////////////////////////////
 
256
 
 
257
    if( hit )
 
258
    {
 
259
        // draw shaded pixel
 
260
        gl_FragColor = blinnPhongIllumination(
 
261
            // material properties
 
262
            gl_Color.rgb * 0.2,                    // ambient color
 
263
            gl_Color.rgb * 2.0,                    // diffuse color
 
264
            gl_Color.rgb,                          // specular color
 
265
            30.0,                                  // shininess
 
266
 
 
267
            // light color properties
 
268
            gl_LightSource[0].diffuse.rgb,         // light color
 
269
            gl_LightSource[0].ambient.rgb,         // ambient light
 
270
 
 
271
            // directions
 
272
            normalize( grad ),                     // normal
 
273
            v_viewDir.xyz,                         // viewdir
 
274
            v_lightDir.xyz );                      // light direction
 
275
    }
 
276
    else // no hit: discard
 
277
    {
 
278
        // want to see the bounding box? uncomment this line
 
279
        // gl_FragColor=vec4(0.5, 0.5, 1., 1.0);
 
280
        discard;
 
281
    }
 
282
}
 
283