To create a shader program that applies the Sobel edge detection filter, perform the following steps:
- The vertex shader just converts the position and normal to camera coordinates and passes them along to the fragment shader.
- The fragment shader applies the reflection model in the first pass, and applies the edge detection filter in the second pass:
in vec3 Position; in vec3 Normal;
uniform int Pass; // Pass number // The texture containing the results of the first pass layout( binding=0 ) uniform sampler2D RenderTex; uniform float EdgeThreshold; // The squared threshold // Light/material uniforms... layout( location = 0 ) out vec4 FragColor; const vec3 lum = vec3(0.2126, 0.7152, 0.0722); vec3 blinnPhong( vec3 pos, vec3 norm ) {
// ... } // Approximates the brightness of a RGB value. float luminance( vec3 color ) { return dot(lum, color); }
vec4 pass1() { return vec4(blinnPhong( Position, normalize(Normal) ),1.0); }
vec4 pass2() { ivec2 pix = ivec2(gl_FragCoord.xy); float s00 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(-1,1)).rgb); float s10 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(-1,0)).rgb); float s20 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(-1,-1)).rgb); float s01 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(0,1)).rgb); float s21 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(0,-1)).rgb); float s02 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(1,1)).rgb); float s12 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(1,0)).rgb); float s22 = luminance( texelFetchOffset(RenderTex, pix, 0, ivec2(1,-1)).rgb); float sx = s00 + 2 * s10 + s20 - (s02 + 2 * s12 + s22); float sy = s00 + 2 * s01 + s02 - (s20 + 2 * s21 + s22); float g = sx * sx + sy * sy; if( g > EdgeThreshold ) return vec4(1.0); else return vec4(0.0,0.0,0.0,1.0); } void main() { if( Pass == 1 ) FragColor = pass1();
if( Pass == 2 ) FragColor = pass2(); }
In the render function of your OpenGL application, follow these steps for pass #1:
- Select FBO, and clear the color/depth buffers
- Set the Pass uniform to 1
- Set up the model, view, and projection matrices, and draw the scene
For pass #2, carry out the following steps:
- Deselect the FBO (revert to the default framebuffer) and clear the color/depth buffers
- Set the Pass uniform to 2
- Set the model, view, and projection matrices to the identity matrix
- Draw a single quad (or two triangles) that fills the screen (-1 to +1 in x and y), with texture coordinates that range from 0 to 1 in each dimension.