laumaya / GLC_lib

GLC_lib is a C++ library for high performance 3D application based on OpenGL and Qt4 GUI
http://www.glc-lib.net
Other
62 stars 31 forks source link

Next #7

Closed PhoenixBlack closed 11 years ago

PhoenixBlack commented 11 years ago

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).

PhoenixBlack commented 11 years ago

An anti-aliased version of outline shader is available. It does basic multi-sampling on the source texture:

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);
}

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

  vec4 d00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x*1.0*f_outlineThickness,v_texCoord2D.y));
  vec4 d01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x*1.0*f_outlineThickness,v_texCoord2D.y));
  vec4 d10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y*1.0*f_outlineThickness));
  vec4 d11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y*1.0*f_outlineThickness));

  vec4 e00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x*1.5*f_outlineThickness,v_texCoord2D.y));
  vec4 e01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x*1.5*f_outlineThickness,v_texCoord2D.y));
  vec4 e10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y*1.5*f_outlineThickness));
  vec4 e11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y*1.5*f_outlineThickness));

  //Get values of nearby points
  float u00 = unpack_id(c00);
  float u01 = unpack_id(c01);
  float u10 = unpack_id(c10);
  float u11 = unpack_id(c11);

  float v00 = unpack_id(d00);
  float v01 = unpack_id(d01);
  float v10 = unpack_id(d10);
  float v11 = unpack_id(d11);

  float w00 = unpack_id(e00);
  float w01 = unpack_id(e01);
  float w10 = unpack_id(e10);
  float w11 = unpack_id(e11);

  //Contour shader
  float d1x = u00 - u01;
  float d1y = u10 - u11;
  float d1 = sqrt(d1x*d1x+d1y*d1y);

  float d2x = v00 - v01;
  float d2y = v10 - v11;
  float d2 = sqrt(d2x*d2x+d2y*d2y);

  float d3x = w00 - w01;
  float d3y = w10 - w11;
  float d3 = sqrt(d3x*d3x+d3y*d3y);

  //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
  float contour = 0.0;
  if (d1 > 0.0) contour += 0.25;
  if (d2 > 0.0) contour += 0.50;
  if (d3 > 0.0) contour += 0.25;
  return vec4(contour_color,contour);
}

void main(void) {
  gl_FragColor = outline_aa();
}
laumaya commented 11 years ago

Thanks, Your change has been integrated.

@+

Le 25 mai 2013 à 12:46, Black Phoenix notifications@github.com a écrit :

An anti-aliased version of outline shader is available. It does basic multi-sampling on the source texture:

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); }

vec4 outline_aa() { //Get color of nearby points vec4 c00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x_0.5_f_outlineThickness,v_texCoord2D.y)); vec4 c01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x_0.5_f_outlineThickness,v_texCoord2D.y)); vec4 c10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y_0.5_f_outlineThickness)); vec4 c11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y_0.5_f_outlineThickness));

vec4 d00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x_1.0_f_outlineThickness,v_texCoord2D.y)); vec4 d01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x_1.0_f_outlineThickness,v_texCoord2D.y)); vec4 d10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y_1.0_f_outlineThickness)); vec4 d11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y_1.0_f_outlineThickness));

vec4 e00 = texture2D(s_Data, vec2(v_texCoord2D.x-v_invScreenSize.x_1.5_f_outlineThickness,v_texCoord2D.y)); vec4 e01 = texture2D(s_Data, vec2(v_texCoord2D.x+v_invScreenSize.x_1.5_f_outlineThickness,v_texCoord2D.y)); vec4 e10 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y-v_invScreenSize.y_1.5_f_outlineThickness)); vec4 e11 = texture2D(s_Data, vec2(v_texCoord2D.x,v_texCoord2D.y+v_invScreenSize.y_1.5_f_outlineThickness));

//Get values of nearby points float u00 = unpack_id(c00); float u01 = unpack_id(c01); float u10 = unpack_id(c10); float u11 = unpack_id(c11);

float v00 = unpack_id(d00); float v01 = unpack_id(d01); float v10 = unpack_id(d10); float v11 = unpack_id(d11);

float w00 = unpack_id(e00); float w01 = unpack_id(e01); float w10 = unpack_id(e10); float w11 = unpack_id(e11);

//Contour shader float d1x = u00 - u01; float d1y = u10 - u11; float d1 = sqrt(d1x_d1x+d1y_d1y);

float d2x = v00 - v01; float d2y = v10 - v11; float d2 = sqrt(d2x_d2x+d2y_d2y);

float d3x = w00 - w01; float d3y = w10 - w11; float d3 = sqrt(d3x_d3x+d3y_d3y);

//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 float contour = 0.0; if (d1 > 0.0) contour += 0.25; if (d2 > 0.0) contour += 0.50; if (d3 > 0.0) contour += 0.25; return vec4(contour_color,contour); }

void main(void) { gl_FragColor = outline_aa(); } — Reply to this email directly or view it on GitHub.

laumaya commented 11 years ago

I guess an example which draws scene with outlines is needed

I'm agree with you :-) Perhaps, it will be a good idea to integrate your shader into GLC_lib.

Do you use GLC_lib shader program wrapper which are not complete ? I will have to work on shader feature to be compatible with OpenGL ES2.

@+

Le 25 mai 2013 à 12:45, Black Phoenix notifications@github.com a écrit :

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).

You can merge this Pull Request by running

git pull https://github.com/PhoenixBlack/GLC_lib next Or view, comment on, or merge it at:

https://github.com/laumaya/GLC_lib/pull/7

Commit Summary

Added silhouette outline rendering flag for drawing outlines Back and front faces are now rendered with different color coding - outlines are drawn correctly for concave objects Fixed small typo Silhouette renderer now includes information about which objects are selected There is an option to disable the selection material now (setUseSelectionMaterial) File Changes

M src/geometry/glc_mesh.cpp (64) M src/geometry/glc_mesh.h (3) M src/sceneGraph/glc_3dviewinstance.h (2) M src/shading/glc_renderproperties.h (3) M src/shading/glc_selectionmaterial.cpp (8) M src/shading/glc_selectionmaterial.h (6) Patch Links:

https://github.com/laumaya/GLC_lib/pull/7.patch https://github.com/laumaya/GLC_lib/pull/7.diff

PhoenixBlack commented 11 years ago

The shader is 2.0 shader. It should be compatible with anything really - it only uses conditionals and makes 4 (or 12 in anti-aliased case) texture fetches. I'm going to work on adding outline rendering functionality as part of GLC_lib - possibly as a special class or an addon somewhere.

I don't use GLC_lib shader program wrapper, just Qt shader. It shouldn't be hard to change that.