laumaya/GLC_lib — pull request #7 by PhoenixBlack (2013-05-25 10:45:12+00:00)
Title: Next

Added silhouette rendering mode which encodes object ID's and primitive ID's into image, along with information on whether object is selected or no.

The resulting color image must be rendered into FBO and then the FBO drawn on screen with this shader:
~~~
uniform sampler2D s_Data;
varying vec2 v_texCoord2D;
uniform vec2 v_invScreenSize;
uniform float f_outlineThickness;

const vec3 v_selectionColor = vec3(1.0,0.7,0.0);

float unpack_id(vec4 c) {
return (c.r + c.g*256.0 + c.b*256.0*256.0 + c.a*256.0*256.0*256.0)*255.0;
}

vec4 outline() {
//Get color of nearby points
vec4 c00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x*f_outlineThickness,v_texCoord2D.y));
vec4 c01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x*f_outlineThickness,v_texCoord2D.y));
vec4 c10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y*f_outlineThickness));
vec4 c11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y*f_outlineThickness));

//Get values of nearby points
float v00 = unpack_id(c00);
float v01 = unpack_id(c01);
float v10 = unpack_id(c10);
float v11 = unpack_id(c11);

//Contour shader
float dx = v00 - v01;
float dy = v10 - v11;
float d = sqrt(dx*dx+dy*dy);

//Check if selection is present
vec3 contour_color = vec3(0,0,0);
if ((v00 > 8388607.0) ||
(v01 > 8388607.0) ||
(v10 > 8388607.0) ||
(v11 > 8388607.0)) {
contour_color = v_selectionColor;
}

//Edge detection
if (d > 0.0) {
return vec4(contour_color,1.0);
}
return vec4(contour_color,0.0);
}

void main(void) {
gl_FragColor = outline();
}
~~~

I will work on making some easier way of doing this later. Here's the C++ code that draws outlines:
~~~
//Draw into outline buffer
fbo_outline->bind(); //Outlines for all objects
world->render(0, glc::OutlineSilhouetteRenderFlag);
world->render(1, glc::OutlineSilhouetteRenderFlag);
fbo_outline->release();

fbo_outline_selected->bind(); //Selected objects
world->render(1, glc::OutlineSilhouetteRenderFlag);
fbo_outline_selected->release();

/////////////////////////////////////////////////////

shader_outline->bind();
shader_outline->setUniformValue("s_Data",0);
shader_outline->setUniformValue("v_invScreenSize",1.0f/rect.width(),1.0f/rect.height());
shader_outline->setUniformValue("f_outlineThickness",1.0f);
glBindTexture(GL_TEXTURE_2D, fbo_outline->texture());
drawScreenQuad();
glBindTexture(GL_TEXTURE_2D, fbo_outline_selected->texture());
drawScreenQuad();
shader_outline->release();
~~~

Also selection material can now be disabled (I didn't find if there was any support to do this. Disabling selection material is useful when you only want to show selection via change in outlines color - but not modify the objects themselves).

I guess an example which draws scene with outlines is needed, I'll see if I can prepare one like that (maybe also make it include custom LOD's generation or something).