Lerp

Math | Sunday 5 October 2008 6:57 pm

Lerp is the procedure to interpolate between two vectors with a specified weight. An example below

float weight; // the weight for lerping
 
vec2 input1, input2; // the inputs to lerp between
 
vec2 lerpResult = input1(1.0-weight)+input2(weight);

In GLSL it’s named mix( genType, genType, float ) instead of lerp which can be misleading. But when testing, it actually works to use lerp instead of mix in GLSL shaders when running them on a Nvidia GeForce 8800GTS although it’s not recommended.

Here’s the OpenGL GLSL quick reference guide which contains all functions you can use inside of a shader (and much more).
 http://www.opengl.org/sdk/libs/OpenSceneGraph/glsl_quickref.pdf

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Bilinear Interpolation

Filtering | Sunday 5 October 2008 5:18 pm

When sampling a texel from a texture that has been re-sized (which is nearly always the case in 3D rendering) you need to use some kind of filter to select what result you should get. Bilinear interpolation uses the four nearest neighbors to interpolate an average texel value.

Bilinear Interpolation

This is a built in filter in OpenGL and to activate it you set the following lines when setting up a texture:

// set the minification filter
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
// set the magnification filter
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

If you for some reason wants to do bilinear interpolation manually in a shader then the function to do so looks like the following in GLSL. Note that in vertex shaders you have to do manual bilinear interpolation between texture samples.

const float textureSize = 512.0; //size of the texture
const float texelSize = 1.0 / textureSize; //size of one texel 
 
vec4 texture2DBilinear( sampler2D textureSampler, vec2 uv )
{
    // in vertex shaders you should use texture2DLod instead of texture2D
    vec4 tl = texture2D(textureSampler, uv);
    vec4 tr = texture2D(textureSampler, uv + vec2(texelSize, 0));
    vec4 bl = texture2D(textureSampler, uv + vec2(0, texelSize));
    vec4 br = texture2D(textureSampler, uv + vec2(texelSize , texelSize));
    vec2 f = fract( uv.xy * textureSize ); // get the decimal part
    vec4 tA = mix( tl, tr, f.x ); // will interpolate the red dot in the image
    vec4 tB = mix( bl, br, f.x ); // will interpolate the blue dot in the image
    return mix( tA, tB, f.y ); // will interpolate the green dot in the image
}

Here’s a magnification of a texture using using three different types of filters. The texture is mapped on a sphere and the viewport has been zoomed in on a small part of it.

Nearest Neigbour  (OpenGL fixed function implementation)

Nearest Neigbor filter

Bilinear Interpolation (OpenGL fixed function implementation)

Bilinear Interpolation OpenGL

Bilinear Interpolation (GLSL implementation, the code above)

Bilinear Interpolation GLSL

Some information about OpenGL texture mapping and how to set the filtering properties:
http://www.nullterminator.net/gltexture.html

Here’s some discussion why you should not always use bilinear interpolation:
http://gregs-blog.com/2008/01/14/how-to-turn-off-bilinear-filtering-in-opengl/

Link to a bilinear interpolation function for DirectX:
http://www.catalinzima.com/?page_id=85

Article on GameDev.net about bilinear filtering:
http://www.gamedev.net/reference/articles/article669.asp

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Eye Space

Cameras | Sunday 5 October 2008 1:56 am

Eye Space or often called View Space or Camera Space is the space where the camera is located in origin (0,0,0) and all objects are transformed accordingly. More specifically the camera (in OpenGL) is located in origin, looking down the negative z-axis and has the x-axis pointing to the right and the y-axis pointing up. This mean that objects further away from the camera (when looking at them) has lower z-value. In OpenGL the ModelView determines how the objects should be transformed to be end up in eye space.

A vertex can be transformed to eye space with the following vertex shader (GLSL):

void main(void)
{
   vec4 eyeSpaceVertex = gl_ModelViewMatrix * gl_Vertex;
   // now do what you want with it
}

A normal can be transformed to eye space with the following vertex shader (GLSL):

void main(void)
{
   vec3 eyeSpaceNormal = normalize(gl_NormalMatrix * gl_Normal);
   // now do what you want with it
} 

The gl_NormalMatrix can also be used to transform tangents and binormals to eye space.

void main(void)
{
   vec3 eyeSpaceNormal = normalize(gl_NormalMatrix * gl_Normal);
   vec3 eyeSpaceTangent = normalize(gl_NormalMatrix * Tangent);
   vec3 eyeSpaceBinormal = normalize(gl_NormalMatrix * Binormal);
   // now do what you want with it
} 

Note that neither of these shaders are complete because they don’t write anything to gl_Position.

Lights are passed to the shader in eye space as default and most lightning calculations take place in eye space.

Description of different 3D spaces:
http://vesta.astro.amu.edu.pl/Library/Linux/LinFocus/May1998/article6.html

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks

Linear depth texture

Rendering Methods | Sunday 28 September 2008 11:06 pm

In some occasions a linear depth texture is preferred over the usual non-linear depth buffer (z-buffer). The linearized depth could for example be used when doing SSAO or depth of field. Rendering linear z-buffers is very easy and only the following lines of code is required ( a float texture should be set as render target):

Vertex shader:

varying float depth;
void main()
{
    vec4 viewPos = gl_ModelViewMatrix * gl_Vertex; // this will transform the vertex into eyespace
    depth = -viewPos.z; // minus because in OpenGL we are looking in the negative z-direction
    gl_Position = ftransform();
}

Fragment shader:

varying float depth;
void main()
{
    gl_FragColor.r = depth;
}

 
You might want to scale the depth in the vertex shader to a more appropriate range as the the distance will otherwise be the same as the distance from the camera to the vertex. The following vertex shader will map the near and far distances to 0..1 which is often a good idea.

varying float depth;
void main()
{
    vec4 viewPos = gl_ModelViewMatrix * gl_Vertex; // this will transform the vertex into eyespace
    depth = (-viewPos.z-near)/(far-near); // will map near..far to 0..1
    gl_Position = ftransform();
}

Here’s how the shader looks like if you render a cube.

Linear Depth Rendering of a Cube

Link to a page about the depth buffer in DirectX
http://www.mvps.org/directx/articles/linear_z/linearz.htm

A good introduction to the depth buffer in OpenGL
http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html

Please share:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Current
  • LinkedIn
  • Live
  • MySpace
  • Netvibes
  • StumbleUpon
  • Twitter
  • Reddit
  • Technorati
  • Yahoo! Bookmarks
« Previous PageNext Page »