diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 607d66bbb52..91e7f3dfbe1 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -159,6 +159,8 @@ data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.gl data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC) +data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_edges_front_back_ortho_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_text_frag.glsl SRC) diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 699028d6570..39cdbbccd8b 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -79,6 +79,8 @@ extern char datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl[]; extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl[]; extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[]; +extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[]; +extern char datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl[]; extern char datatoc_gpu_shader_edges_front_back_ortho_vert_glsl[]; extern char datatoc_gpu_shader_text_vert_glsl[]; extern char datatoc_gpu_shader_text_frag_glsl[]; @@ -671,10 +673,20 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) break; case GPU_SHADER_EDGES_FRONT_BACK_PERSP: if (!GG.shaders.edges_front_back_persp) - GG.shaders.edges_front_back_persp = GPU_shader_create( - datatoc_gpu_shader_edges_front_back_persp_vert_glsl, - datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl, - NULL, NULL, NULL, 0, 0, 0); + if (GLEW_VERSION_3_2) { + /* this version is magical but slooow */ + GG.shaders.edges_front_back_persp = GPU_shader_create( + datatoc_gpu_shader_edges_front_back_persp_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_gpu_shader_edges_front_back_persp_geom_glsl, + NULL, NULL, 0, 0, 0); + } + else { + GG.shaders.edges_front_back_persp = GPU_shader_create( + datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl, + datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl, + NULL, NULL, NULL, 0, 0, 0); + } retval = GG.shaders.edges_front_back_persp; break; case GPU_SHADER_EDGES_FRONT_BACK_ORTHO: diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl new file mode 100644 index 00000000000..10b5fad7972 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl @@ -0,0 +1,60 @@ + +// Draw "fancy" wireframe, displaying front-facing, back-facing and +// silhouette lines differently. +// Mike Erwin, April 2015 + +// After working with this shader a while, convinced we should make +// separate shaders for perpective & ortho. (Oct 2016) + +// Due to perspective, the line segment's endpoints might disagree on +// whether the adjacent faces are front facing. This geometry shader +// decides which edge type to use if endpoints disagree. + +uniform mat4 ProjectionMatrix; + +uniform bool drawFront = true; +uniform bool drawBack = true; +uniform bool drawSilhouette = true; + +uniform vec4 frontColor; +uniform vec4 backColor; +uniform vec4 silhouetteColor; + +layout(lines) in; +layout(line_strip, max_vertices = 2) out; + +in vec4 MV_pos[]; +in float edgeClass[]; + +flat out vec4 finalColor; + +void emitLine(vec4 color) +{ + gl_Position = ProjectionMatrix * MV_pos[0]; + EmitVertex(); + gl_Position = ProjectionMatrix * MV_pos[1]; + finalColor = color; + EmitVertex(); + EndPrimitive(); +} + +void main() +{ + float finalEdgeClass = max(edgeClass[0], edgeClass[1]); + + if (finalEdgeClass > 0.0f) { + // front-facing edge + if (drawFront) + emitLine(frontColor); + } + else if (finalEdgeClass < 0.0f) { + // back-facing edge + if (drawBack) + emitLine(backColor); + } + else { + // exactly one face is front-facing, silhouette edge + if (drawSilhouette) + emitLine(silhouetteColor); + } +} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl new file mode 100644 index 00000000000..baf69c3e272 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl @@ -0,0 +1,78 @@ + +// Draw "fancy" wireframe, displaying front-facing, back-facing and +// silhouette lines differently. +// Mike Erwin, April 2015 + +// After working with this shader a while, convinced we should make +// separate shaders for perpective & ortho. (Oct 2016) + +// This shader is an imperfect stepping stone until all platforms are +// ready for geometry shaders. + +// Due to perspective, the line segment's endpoints might disagree on +// whether the adjacent faces are front facing. Need to use a geometry +// shader or pass in an extra position attribute (the other endpoint) +// to do this properly. + +uniform bool drawFront = true; +uniform bool drawBack = true; +uniform bool drawSilhouette = true; + +uniform vec4 frontColor; +uniform vec4 backColor; +uniform vec4 silhouetteColor; + +uniform mat4 ModelViewMatrix; +uniform mat4 ModelViewProjectionMatrix; +uniform mat3 NormalMatrix; + +#if __VERSION__ == 120 + attribute vec3 pos; + + // normals of faces this edge joins (object coords) + attribute vec3 N1; + attribute vec3 N2; + + flat varying vec4 finalColor; +#else + in vec3 pos; + + // normals of faces this edge joins (object coords) + in vec3 N1; + in vec3 N2; + + flat out vec4 finalColor; +#endif + +// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley + +// to discard an entire line, set its color to invisible +// (must have GL_BLEND enabled, or discard in fragment shader) +const vec4 invisible = vec4(0.0); + +bool front(vec3 N) +{ + vec4 xformed = ModelViewMatrix * vec4(pos, 1.0); + return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0; +} + +void main() +{ + bool face_1_front = front(N1); + bool face_2_front = front(N2); + + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + if (face_1_front && face_2_front) { + // front-facing edge + finalColor = drawFront ? frontColor : invisible; + } + else if (face_1_front || face_2_front) { + // exactly one face is front-facing, silhouette edge + finalColor = drawSilhouette ? silhouetteColor : invisible; + } + else { + // back-facing edge + finalColor = drawBack ? backColor : invisible; + } +} diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl index baf69c3e272..e1fb78dd1a9 100755 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl @@ -6,73 +6,39 @@ // After working with this shader a while, convinced we should make // separate shaders for perpective & ortho. (Oct 2016) -// This shader is an imperfect stepping stone until all platforms are -// ready for geometry shaders. - // Due to perspective, the line segment's endpoints might disagree on -// whether the adjacent faces are front facing. Need to use a geometry -// shader or pass in an extra position attribute (the other endpoint) -// to do this properly. - -uniform bool drawFront = true; -uniform bool drawBack = true; -uniform bool drawSilhouette = true; - -uniform vec4 frontColor; -uniform vec4 backColor; -uniform vec4 silhouetteColor; +// whether the adjacent faces are front facing. We use a geometry +// shader to resolve this properly. uniform mat4 ModelViewMatrix; -uniform mat4 ModelViewProjectionMatrix; uniform mat3 NormalMatrix; -#if __VERSION__ == 120 - attribute vec3 pos; +in vec3 pos; +in vec3 N1, N2; // normals of faces this edge joins (object coords) - // normals of faces this edge joins (object coords) - attribute vec3 N1; - attribute vec3 N2; - - flat varying vec4 finalColor; -#else - in vec3 pos; - - // normals of faces this edge joins (object coords) - in vec3 N1; - in vec3 N2; - - flat out vec4 finalColor; -#endif +out vec4 MV_pos; +out float edgeClass; // TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley -// to discard an entire line, set its color to invisible -// (must have GL_BLEND enabled, or discard in fragment shader) -const vec4 invisible = vec4(0.0); - -bool front(vec3 N) +bool front(vec3 N, vec3 eye) { - vec4 xformed = ModelViewMatrix * vec4(pos, 1.0); - return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0; + return dot(NormalMatrix * N, eye) > 0.0; } void main() { - bool face_1_front = front(N1); - bool face_2_front = front(N2); + MV_pos = ModelViewMatrix * vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 eye = normalize(-MV_pos.xyz); - if (face_1_front && face_2_front) { - // front-facing edge - finalColor = drawFront ? frontColor : invisible; - } - else if (face_1_front || face_2_front) { - // exactly one face is front-facing, silhouette edge - finalColor = drawSilhouette ? silhouetteColor : invisible; - } - else { - // back-facing edge - finalColor = drawBack ? backColor : invisible; - } + bool face_1_front = front(N1, eye); + bool face_2_front = front(N2, eye); + + if (face_1_front && face_2_front) + edgeClass = 1.0; // front-facing edge + else if (face_1_front || face_2_front) + edgeClass = 0.0; // exactly one face is front-facing, silhouette edge + else + edgeClass = -1.0; // back-facing edge }