WGEShadingTools.glsl 16.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

25 26 27 28 29
#ifndef WGESHADINGTOOLS_GLSL
#define WGESHADINGTOOLS_GLSL

#version 120

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/**
 * A struct containing the needed light and material parameters commonly used in most shaders.
 *
 * \note This is for evaluating the phong equation for 1 channel only.
 */
struct wge_LightIntensityParameter
{
    // These 4 parameters are similar to those in gl_MaterialParameters
    float materialAmbient;  //!< Material ambient intensity.
    float materialDiffuse;  //!< Material diffuse intensity.
    float materialSpecular; //!< Material Specular intensity.
    float materialShinines; //!< Material shinines factor

    // These 4 parametes are a stripped down version of gl_LightSourceParameters
    float lightDiffuse;     //!< Light diffuse intensity.
    float lightAmbient;     //!< Light ambient intensity.
    vec3  lightPosition;    //!< Light position in world-space

    vec3  viewDirection;    //!< View direction vector. Well this actually is -vec3( 0.0, 0.0, -1.0 )
};

/**
 * This variable contains the OpenWalnut default light. You should definitely use this for your lighting to obtain an identical look for all
 * rendered images.
 */
wge_LightIntensityParameter wge_DefaultLightIntensity = wge_LightIntensityParameter(
56
    0.04,                            // material ambient
57
    0.75,                            // material diffuse
58
    1.0,                             // material specular
59
    250.0,                           // material shininess
60
    1.0,                             // light diffuse
61
    1.0,                             // light ambient
62 63 64 65
    gl_LightSource[0].position.xyz,  // light position
    vec3( 0.0, 0.0, 1.0 )            // view direction
);

66 67 68 69 70 71 72 73
/**
 * This variable contains the OpenWalnut default light. You should definitely use this for your lighting to obtain an identical look for all
 * rendered images. This version looks has no ambient factor and provides full diffuse colors.
 */
wge_LightIntensityParameter wge_DefaultLightIntensityFullDiffuse = wge_LightIntensityParameter(
    0.0,                             // material ambient
    1.0,                             // material diffuse
    1.0,                             // material specular
74
    250.0,                           // material shininess
75 76
    1.0,                             // light diffuse
    1.0,                             // light ambient
77 78 79 80 81 82 83 84 85
    gl_LightSource[0].position.xyz,  // light position
    vec3( 0.0, 0.0, 1.0 )            // view direction
);

/**
 * This variable contains the OpenWalnut default light. You should definitely use this for your lighting to obtain an identical look for all
 * rendered images. This version looks a little bit more metallic.
 */
wge_LightIntensityParameter wge_DefaultLightIntensityLessDiffuse = wge_LightIntensityParameter(
86
    0.0,                             // material ambient
87
    0.35,                            // material diffuse
88
    1.0,                             // material specular
89
    250.0,                           // material shininess
90
    1.0,                             // light diffuse
91
    1.0,                             // light ambient
92 93 94 95 96
    gl_LightSource[0].position.xyz,  // light position
    vec3( 0.0, 0.0, 1.0 )            // view direction
);

/**
97 98
 * Function to calculate lighting based on "Real-Time Volume Graphics, p 119, chapter 5.4, Listing 5.1".
 *
99 100 101 102 103 104 105 106 107
 * \param ambient   materials ambient color
 * \param diffuse   materials diffuse color
 * \param specular  materials specular color
 * \param shininess material shininess
 * \param lightColor  the light color
 * \param ambientLight the ambient light color
 * \param normalDir the normal
 * \param viewDir   viewing direction
 * \param lightDir  light direction
108
 *
109
 * \return the color.
110
 */
111 112 113
vec4 blinnPhongIllumination( vec3 ambient, vec3 diffuse, vec3 specular, float shininess,
                             vec3 lightColor, vec3 ambientLight,
                             vec3 normalDir, vec3 viewDir, vec3 lightDir )
114
{
115 116
    normalDir *= sign( dot( normalDir, viewDir ) );

117
    vec3 H =  normalize( lightDir + viewDir );
118

119 120
    // compute ambient term
    vec3 ambientV = ambient * ambientLight;
121

122 123 124
    // compute diffuse term
    float diffuseLight = max( dot( lightDir, normalDir ), 0.0 );
    vec3 diffuseV = diffuse * diffuseLight;
125

126 127 128 129
    // compute specular term
    float specularLight = pow( max( dot( H, normalDir ), 0.0 ), shininess );
    if( diffuseLight <= 0.) specularLight = 0.;
    vec3 specularV = specular * specularLight;
130

131
    return vec4( ambientV + ( diffuseV + specularV ) * lightColor, 1.0 );
132 133
}

134
/**
135
 * Function to calculate lighting intensity based on "Real-Time Volume Graphics, p 119, chapter 5.4, Listing 5.1".
136
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
137
 * the intensity.
138
 *
139 140 141 142 143 144 145 146 147
 * \param ambient   materials ambient intensity
 * \param diffuse   materials diffuse intensity
 * \param specular  materials specular intensity
 * \param shininess material shininess
 * \param lightIntensity  the light intensity
 * \param ambientIntensity the ambient light intensity
 * \param normalDir the normal
 * \param viewDir   viewing direction
 * \param lightDir  light direction
148
 *
149
 * \return the light intensity.
150
 */
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
151 152 153
float blinnPhongIlluminationIntensity( float ambient, float diffuse, float specular, float shininess,
                                       float lightIntensity, float ambientIntensity,
                                       vec3 normalDir, vec3 viewDir, vec3 lightDir )
154
{
155 156
    normalDir *= sign( dot( normalDir, viewDir ) );

157
    vec3 H =  normalize( lightDir + viewDir );
158

159 160
    // compute ambient term
    float ambientV = ambient * ambientIntensity;
161

162 163 164
    // compute diffuse term
    float diffuseLight = max( dot( lightDir, normalDir ), 0.0 );
    float diffuseV = diffuse * diffuseLight;
165

166 167 168 169
    // compute specular term
    float specularLight = pow( max( dot( H, normalDir ), 0.0 ), shininess );
    if( diffuseLight <= 0.) specularLight = 0.;
    float specularV = specular * specularLight;
170

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
    return ambientV + ( diffuseV + specularV ) * lightIntensity;
}

/**
 * Function to calculate lighting intensity based on "Real-Time Volume Graphics, p 119, chapter 5.4, Listing 5.1".
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
 * the intensity.
 *
 * \param parameter the wge_LightIntensityParameter defining material and light
 * \param normal the normal. Needs to be normalized.
 *
 * \return lighting intensity.
 */
float blinnPhongIlluminationIntensity( in wge_LightIntensityParameter parameter, in vec3 normal )
{
    return blinnPhongIlluminationIntensity(
        parameter.materialAmbient,
        parameter.materialDiffuse,
        parameter.materialSpecular,
        parameter.materialShinines,
        parameter.lightDiffuse,
        parameter.lightAmbient,
        normal,
        parameter.viewDirection,
        parameter.lightPosition
        );
}

/**
 * Function to calculate lighting intensity based on "Real-Time Volume Graphics, p 119, chapter 5.4, Listing 5.1".
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
 * the intensity. This uses the wge_DefaultLightIntensity.
 *
 * \param normal the normal. Must be normalized beforehand
 *
 * \return the light intensity
 */
float blinnPhongIlluminationIntensity( in vec3 normal )
{
    return blinnPhongIlluminationIntensity( wge_DefaultLightIntensity, normal );
211 212
}

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
/**
 * Function to calculate lighting intensity for a matte (non-specular) Phong illumination.
 *
 * \param ambient   materials ambient color
 * \param diffuse   materials diffuse color
 * \param lightColor  the light color
 * \param ambientLight the ambient light color
 * \param normalDir the normal
 * \param viewDir   viewing direction
 * \param lightDir  light direction
 *
 * \return the color.
 */
vec4 mattePhongIllumination( vec3 ambient, vec3 diffuse,
                             vec3 lightColor, vec3 ambientLight,
                             vec3 normalDir, vec3 viewDir, vec3 lightDir )
{
    vec3 H =  normalize( lightDir + viewDir );

    // compute ambient term
    vec3 ambientV = ambient * ambientLight;

    // compute diffuse term
    float diffuseLight = max( dot( lightDir, normalDir ), 0.0 );
    vec3 diffuseV = diffuse * diffuseLight;

    return vec4( ambientV + diffuseV * lightColor, 1.0 );
}

/**
 * Function to calculate lighting intensity for a matte (non-specular) Phong illumination.
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
 * the intensity.
 *
 * \param ambient   materials ambient intensity
 * \param diffuse   materials diffuse intensity
 * \param specular  materials specular intensity
 * \param shininess material shininess
 * \param lightIntensity  the light intensity
 * \param ambientIntensity the ambient light intensity
 * \param normalDir the normal
 * \param viewDir   viewing direction
 * \param lightDir  light direction
 *
 * \return the light intensity.
 */
float mattePhongIlluminationIntensity( float ambient, float diffuse,
                                       float lightIntensity, float ambientIntensity,
                                       vec3 normalDir, vec3 viewDir, vec3 lightDir )
{
    vec3 H =  normalize( lightDir + viewDir );

    // compute ambient term
    float ambientV = ambient * ambientIntensity;

    // compute diffuse term
    float diffuseLight = max( dot( lightDir, normalDir ), 0.0 );
    float diffuseV = diffuse * diffuseLight;

    return ambientV + diffuseV * lightIntensity;
}

/**
 * Function to calculate lighting intensity for a matte (non-specular) Phong illumination.
 * Any specular or shininess given with the parameters will be ignored.
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
 * the intensity.
 *
 * \param parameter the wge_LightIntensityParameter defining material and light
 * \param normal the normal. Needs to be normalized.
 *
 * \return lighting intensity.
 */
float mattePhongIlluminationIntensity( in wge_LightIntensityParameter parameter, in vec3 normal )
{
    return mattePhongIlluminationIntensity(
        parameter.materialAmbient,
        parameter.materialDiffuse,
        parameter.lightDiffuse,
        parameter.lightAmbient,
        normal,
        parameter.viewDirection,
        parameter.lightPosition
        );
}

/**
 * Function to calculate lighting intensity for a matte (non-specular) Phong illumination.
 * It is basically the same as blinnPhongIllumination function above. But it is faster if you just need
 * the intensity. This uses the wge_DefaultLightIntensity without the specular and shininess.
 *
 * \param normal the normal. Must be normalized beforehand
 *
 * \return the light intensity
 */
float mattePhongIlluminationIntensity( in vec3 normal )
{
    wge_LightIntensityParameter noSpecular = wge_DefaultLightIntensity;
    noSpecular.materialShinines = 0.0;
    noSpecular.materialSpecular = 0.0;
    return mattePhongIlluminationIntensity( noSpecular, normal );
}

316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350
/**
 * This illumination technique is from "Jens Krüger and Rüdiger Westermann - EFFICIENT STIPPLE RENDERING". It is a non-linear illumination model
 * which only handles ambient and diffuse components. The parameter alpha determines how much the diffuse light should depend on the orientation
 * of the surface towards the light source (the camera in OpenWalnut's default case ). It is acutally quite similar to the Phong specular term.
 *
 * \param parameter the light parameter
 * \param normal the normal. Must be normalized beforehand.
 * \param alpha the non-linear influence of surface orientation
 *
 * \return light intensity
 */
float kruegerNonLinearIllumination( in wge_LightIntensityParameter parameter, in vec3 normal, in float alpha )
{
    float diffuseIntensity = pow( ( dot( parameter.lightPosition.xyz, normal ) + 1.0 ) / 2.0, alpha );
    float diffuse = parameter.lightDiffuse *  parameter.materialDiffuse * diffuseIntensity;
    float ambient = parameter.materialAmbient * parameter.lightAmbient;
    return ambient + diffuse;
}

/**
 * This illumination technique is from "Jens Krüger and Rüdiger Westermann - EFFICIENT STIPPLE RENDERING". It is a non-linear illumination model
 * which only handles ambient and diffuse components. The parameter alpha determines how much the diffuse light should depend on the orientation
 * of the surface towards the light source (the camera in OpenWalnut's default case ). This version uses wge_DefaultLightIntensityFullDiffuse as
 * parameter. It is acutally quite similar to the Phong specular term.
 *
 * \param normal the normal. Must be normalized beforehand.
 * \param alpha the non-linear influence of surface orientation
 *
 * \return light intensity
 */
float kruegerNonLinearIllumination( in vec3 normal, in float alpha )
{
    return kruegerNonLinearIllumination( wge_DefaultLightIntensityFullDiffuse, normal, alpha );
}

351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
/**
 * Calculates the gradient inside a luminance 3D texture at the specified position.
 *
 * \param sampler the texture sampler to use
 * \param pos where in the texture
 * \param stepsize the offset used in the kernel. Should be related to the nb. of voxels.
 *
 * \return the gradient
 */
vec3 getGradient( in sampler3D sampler, in vec3 pos, in float stepsize )
{
    float valueXP = texture3D( sampler, pos + vec3( stepsize, 0.0, 0.0 ) ).r;
    float valueXM = texture3D( sampler, pos - vec3( stepsize, 0.0, 0.0 ) ).r;
    float valueYP = texture3D( sampler, pos + vec3( 0.0, stepsize, 0.0 ) ).r;
    float valueYM = texture3D( sampler, pos - vec3( 0.0, stepsize, 0.0 ) ).r;
    float valueZP = texture3D( sampler, pos + vec3( 0.0, 0.0, stepsize ) ).r;
    float valueZM = texture3D( sampler, pos - vec3( 0.0, 0.0, stepsize ) ).r;

    return vec3( valueXP - valueXM, valueYP - valueYM, valueZP - valueZM );
}

/**
 * Calculates the gradient inside a luminance 3D texture at the specified position.
 *
 * \param sampler the texture sampler to use
 * \param pos where in the texture
 *
 * \return the gradient
 */
vec3 getGradient( in sampler3D sampler, in vec3 pos )
{
    // unfortunately the ATI driver does not allow default values for function arguments
    return getGradient( sampler, pos, 0.005 );
}

/**
 * Calculates the gradient in a luminance 3D texture at the specified position. Unlike getGradient, this switches the orientation of the gradient
 * according to the viewing direction. This ensures, that the gradient always points towards the camera and therefore is useful as a normal.
 *
 * \param sampler the texture sampler to use
 * \param pos where in the texture
 * \param viewDir the direction from the camera to pos
 * \param stepsize the offset used in the kernel. Should be related to the nb. of voxels.
 *
 * \return the gradient
 */
vec3 getGradientViewAligned( in sampler3D sampler, in vec3 pos, in vec3 viewDir, in float stepsize )
{
    vec3 grad = getGradient( sampler, pos, stepsize );
    return  sign( dot( grad, -viewDir ) ) * grad;
}

/**
 * Calculates the gradient in a luminance 3D texture at the specified position. Unlike getGradient, this switches the orientation of the gradient
 * according to the viewing direction. This ensures, that the gradient always points towards the camera and therefore is useful as a normal.
 *
 * \param sampler the texture sampler to use
 * \param pos where in the texture
 * \param viewDir the direction from the camera to pos
 *
 * \return the gradient
 */
vec3 getGradientViewAligned( in sampler3D sampler, in vec3 pos, in vec3 viewDir )
{
    // unfortunately the ATI driver does not allow default values for function arguments
    return getGradientViewAligned( sampler, pos, viewDir, 0.005 );
}

419 420 421 422 423 424 425 426 427 428 429 430
/**
 * Re-orient the specified vector to point towards the camera. This should be done AFTER modelview transformation.
 *
 * \param v the vector to re-orient
 *
 * \return the new vector. Only normalized if v was normalized.
 */
vec3 viewAlign( vec3 v )
{
    return sign( dot( v, vec3( 0.0, 0.0, 1.0 ) ) ) * v;
}

431 432
#endif // WGESHADINGTOOLS_GLSL