Adding a scanline and vignette effect

This recipe will show you a very typical use of post-processing. You will create an effect that makes the scene feel as if it were observed through a security camera or the eye of a remote controlled robot by dropping every other line of output. Additionally, you will learn how to implement a simple vignette effect that directs the focus to the center of the screen.

After completing this article, you will see how very simple post-processing techniques can have a major impact on the look and feel of a scene.

Getting ready

We will be using the same scene and project setup as in Building custom effects found in this chapter. Please follow the recipe until you complete step 1 before proceeding with this one.

How to do it...

These are the tasks required for completing this recipe:

  1. Open Application.py and add this method to the Application class:
    def setupPostFx(self):
    self.filterMan = FilterManager(self.win, self.cam)
    colorTex = Texture()
    finalQuad = self.filterMan.renderSceneInto(colortex = colorTex)
    finalQuad.setShader(loader.loadShader("scanline.cg"))
    finalQuad.setShaderInput("color", colorTex)
    
  2. Add a new file called scanline.cg to the shaders directory.
  3. Open scanline.cg in an editor and add the following code:
    //Cg
    void vshader(float4 vtx_position : POSITION,
    out float4 l_position : POSITION,
    out float2 l_texcoord : TEXCOORD0,
    uniform float4 texpad_color,
    uniform float4x4 mat_modelproj)
    {
    l_position = mul(mat_modelproj, vtx_position);
    l_texcoord = (vtx_position.xz * texpad_color.xy) + texpad_color.xy;
    }
    #define DRAW 4
    #define DROP 2
    #define DRAW_INTENSITY 1.1
    #define DROP_INTENSITY 0.5
    void fshader(float2 l_texcoord : TEXCOORD0,
    uniform sampler2D k_color : TEXUNIT0,
    uniform sampler2D k_line : TEXUNIT1,
    uniform float4 texpix_color,
    uniform float4 texpad_color,
    out float4 o_color : COLOR)
    {
    float4 color = tex2D(k_color, l_texcoord);
    float falloff = 1.1 - length(l_texcoord - texpad_color);
    color *= pow(falloff, 4);
    o_color = color * (int(l_texcoord.y / texpix_color.y) % DRAW + DROP < DRAW ? DRAW_INTENSITY : DROP_INTENSITY);
    }
    
  4. In the Netbeans IDE, press F6 to launch the sample:
How to do it...

How it works...

In this sample, our buffer setup is very simple. The scene is rendered into colorTex, which is modified and applied to the final fullscreen quad by the shader found in scanline.cg.

The interesting parts of this recipe can be found in the fshader() function of the shader file, which is the pixel shader code. Here we first read the color value at the current texture coordinate into a four-component vector.

The next two lines are responsible for the vignette effect. The falloff value is based on the distance of the current texture coordinate from the center of the texture, stored in texpad_color. The value of 1.1 from which the length is subtracted was chosen to make the final image appear a bit brighter and make the effect appear less harsh. The falloff is then raised to the power of 4, which results in a nice circular decline in intensity, moving the panda into focus.

The next two lines are responsible for the vignette effect. The falloff value is based on the distance of the current texture coordinate from the center of the texture, stored in texpad_color. The value of 1.1 from which the length is subtracted was chosen to make the final image appear a bit brighter and make the effect appear less harsh. The falloff is then raised to the power of 4, which results in a nice circular decline in intensity, moving the panda into focus.

Finally, we need to decide if the current pixel is on a scanline or not. The macros DRAW, DROP, DRAW_INTENSITY, and DROP_INTENSITY define how many lines to draw, how many lines to drop, at which intensity drawn lines are put onto the screen and the intensity of dropped lines, respectively. Whether the current pixel lies on a dropped or drawn line is decided by some simple math. We take the integral part of the current vertical texture coordinate (l_texcoords.y) divided by the normalized height of a pixel (texpix_color.y) modulo the number of lines we observe in our scanline pattern. If the result of this function is smaller than number of lines to draw the line is considered visible. If it is bigger than DRAW, the current line is discarded.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset