GLSL 4.0: Discarding Fragments to Create a Perforated Look

Exclusive offer: get 50% off this eBook here
OpenGL 4.0 Shading Language Cookbook

OpenGL 4.0 Shading Language Cookbook — Save 50%

Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use

€23.99    €12.00
by David Wolff | August 2011 | Cookbooks Open Source Web Graphics & Video

Fragment shaders can make use of the discard keyword to "throw away" fragments. Use of this keyword causes the fragment shader to stop execution, without writing anything (including depth) to the output buffer. This provides a way to create holes in polygons without using blending. In fact, since fragments are completely discarded, there is no dependence on the order in which objects are drawn, saving us the trouble of doing any depth sorting that might have been necessary if blending was used. In this recipe by David Wolff, author of OpenGL 4.0 Shading Language Cookbook, we'll draw a teapot, and use the discard keyword to remove fragments selectively based on texture coordinates.

 

OpenGL 4.0 Shading Language Cookbook

OpenGL 4.0 Shading Language Cookbook

Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use

        Read more about this book      

(For more resources on this subject, see here.)

The result will look like the following image:

OpenGL GLSL 4.0 Shading Language tutorial

Getting ready

The vertex position, normal, and texture coordinates must be provided to the vertex shader from the OpenGL application. The position should be provided at location 0, the normal at location 1, and the texture coordinates at location 2. As in previous examples, the lighting parameters must be set from the OpenGL application via the appropriate uniform variables.

How to do it...

To create a shader program that discards fragments based on a square lattice (as in the preceding image), use the following code:

  1. Use the following code for the vertex shader:

    #version 400

    layout (location = 0) in vec3 VertexPosition;
    layout (location = 1) in vec3 VertexNormal;
    layout (location = 2) in vec2 VertexTexCoord;

    out vec3 FrontColor;
    out vec3 BackColor;
    out vec2 TexCoord;

    struct LightInfo {
    vec4 Position; // Light position in eye coords.
    vec3 La; // Ambient light intensity
    vec3 Ld; // Diffuse light intensity
    vec3 Ls; // Specular light intensity
    };
    uniform LightInfo Light;

    struct MaterialInfo {
    vec3 Ka; // Ambient reflectivity
    vec3 Kd; // Diffuse reflectivity
    vec3 Ks; // Specular reflectivity
    float Shininess; // Specular shininess factor
    };
    uniform MaterialInfo Material;

    uniform mat4 ModelViewMatrix;
    uniform mat3 NormalMatrix;
    uniform mat4 ProjectionMatrix;
    uniform mat4 MVP;

    void getEyeSpace( out vec3 norm, out vec4 position )
    {
    norm = normalize( NormalMatrix * VertexNormal);
    position = ModelViewMatrix * vec4(VertexPosition,1.0);
    }

    vec3 phongModel( vec4 position, vec3 norm )
    {
    // The ADS shading calculations go here (see: "Using
    // functions in shaders," and "Implementing
    // per-vertex ambient, diffuse and specular (ADS) shading")
    ...
    }

    void main()
    {
    vec3 eyeNorm;
    vec4 eyePosition;

    TexCoord = VertexTexCoord;

    // Get the position and normal in eye space
    getEyeSpace(eyeNorm, eyePosition);

    FrontColor = phongModel( eyePosition, eyeNorm );
    BackColor = phongModel( eyePosition, -eyeNorm );

    gl_Position = MVP * vec4(VertexPosition,1.0);
    }

  2. Use the following code for the fragment shader:

    #version 400

    in vec3 FrontColor;
    in vec3 BackColor;
    in vec2 TexCoord;

    layout( location = 0 ) out vec4 FragColor;

    void main() {
    const float scale = 15.0;
    bvec2 toDiscard = greaterThan( fract(TexCoord * scale),
    vec2(0.2,0.2) );

    if( all(toDiscard) )
    discard;

    if( gl_FrontFacing )
    FragColor = vec4(FrontColor, 1.0);
    else
    FragColor = vec4(BackColor, 1.0);
    }

  3. Compile and link both shaders within the OpenGL application, and install the shader program prior to rendering.

How it works...

Since we will be discarding some parts of the teapot, we will be able to see through the teapot to the other side. This will cause the back sides of some polygons to become visible. Therefore, we need to compute the lighting equation appropriately for both sides of each face. We'll use the same technique presented earlier in the two-sided shading recipe.

The vertex shader is essentially the same as in the two-sided shading recipe, with the main difference being the addition of the texture coordinate. The differences are highlighted in the above listing. To manage the texture coordinate, we have an additional input variable, VertexTexCoord, that corresponds to attribute location 2. The value of this input variable is passed directly on to the fragment shader unchanged via the output variable TexCoord. The ADS shading model is calculated twice, once using the given normal vector, storing the result in FrontColor, and again using the reversed normal, storing that result in BackColor.

In the fragment shader, we calculate whether or not the fragment should be discarded based on a simple technique designed to produce the lattice-like pattern shown in the preceding image. We first scale the texture coordinate by the arbitrary scaling factor scale. This corresponds to the number of lattice rectangles per unit (scaled) texture coordinate. We then compute the fractional part of each component of the scaled texture coordinate using the built-in function fract. Each component is compared to 0.2 using the built-in function greaterThan, and the result is stored in the bool vector toDiscard. The greaterThan function compares the two vectors component-wise, and stores the Boolean results in the corresponding components of the return value.

If both components of the vector toDiscard are true, then the fragment lies within the inside of each lattice frame, and therefore we wish to discard this fragment. We can use the built-in function all to help with this check. The function all will return true if all of the components of the parameter vector are true. If the function returns true, we execute the discard statement to reject the fragment.

In the else branch, we color the fragment based on the orientation of the polygon, as in the two-sided shading recipe presented earlier.

Summary

This recipe showed us how to use the discard keyword to "throw away" fragments and create a perforated look.


Further resources on this subject:


OpenGL 4.0 Shading Language Cookbook Over 60 highly focused, practical recipes to maximize your OpenGL Shading language use
Published: July 2011
eBook Price: €23.99
Book Price: €38.99
See more
Select your format and quantity:

About the Author :


David Wolff

David Wolff is an associate professor in the Computer Science and Computer Engineering Department at Pacific Lutheran University (PLU). He received a PhD in Physics and an MS in Computer Science from Oregon State University. He has been teaching computer graphics to undergraduates at PLU for over 10 years, using OpenGL.

Books From Packt


OGRE 3D 1.7 Beginner's Guide
OGRE 3D 1.7 Beginner's Guide

OpenSceneGraph 3.0: Beginner's Guide
OpenSceneGraph 3.0: Beginner's Guide

Blender 2.5 HOTSHOT
Blender 2.5 HOTSHOT

Blender 2.49 Scripting
Blender 2.49 Scripting

Away3D 3.6 Cookbook
Away3D 3.6 Cookbook

3D Graphics with XNA Game Studio 4.0
3D Graphics with XNA Game Studio 4.0

Panda3D 1.7 Game Developer's Cookbook
Panda3D 1.7 Game Developer's Cookbook

Papervision3D Essentials
Papervision3D Essentials


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software