Browse Source

Shaders: ported MeshVisualizer to use geometry shaders also on ES3+AEP.

Please note that in ES3 there is a behavioral change -- geometry shader
is no longer explicitly disabled, but it is enabled by default and you
have to disable it if you don't have the required extension or don't
want to use it.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
0ccd9aa26e
  1. 17
      src/Magnum/Shaders/MeshVisualizer.cpp
  2. 11
      src/Magnum/Shaders/MeshVisualizer.frag
  3. 18
      src/Magnum/Shaders/MeshVisualizer.geom
  4. 15
      src/Magnum/Shaders/MeshVisualizer.h
  5. 18
      src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp

17
src/Magnum/Shaders/MeshVisualizer.cpp

@ -37,12 +37,16 @@
namespace Magnum { namespace Shaders { namespace Magnum { namespace Shaders {
MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) { MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationProjectionMatrixUniform(0), viewportSizeUniform(1), colorUniform(2), wireframeColorUniform(3), wireframeWidthUniform(4), smoothnessUniform(5) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320); MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320);
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::geometry_shader4);
#else
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::EXT::geometry_shader);
#endif
} }
#elif defined(MAGNUM_TARGET_GLES2) #else
if(flags & Flag::Wireframe) if(flags & Flag::Wireframe)
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives); MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives);
#endif #endif
@ -58,7 +62,8 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210}); const Version version = Context::current()->supportedVersion({Version::GL320, Version::GL310, Version::GL300, Version::GL210});
CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GL320); CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GL320);
#else #else
const Version version = Context::current()->supportedVersion({Version::GLES300, Version::GLES200}); const Version version = Context::current()->supportedVersion({Version::GLES310, Version::GLES300, Version::GLES200});
CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GLES310);
#endif #endif
Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex); Shader vert = Implementation::createCompatibilityShader(rs, version, Shader::Type::Vertex);
@ -78,7 +83,7 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
.addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(flags & Flag::NoGeometryShader ? "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.get("MeshVisualizer.frag")); .addSource(rs.get("MeshVisualizer.frag"));
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
std::optional<Shader> geom; std::optional<Shader> geom;
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry); geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry);
@ -86,14 +91,14 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, *geom, frag})); if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, *geom, frag}));
else else
#endif #endif
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag}));
attachShaders({vert, frag}); attachShaders({vert, frag});
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
if(geom) attachShader(*geom); if(geom) attachShader(*geom);
#endif #endif

11
src/Magnum/Shaders/MeshVisualizer.frag

@ -40,6 +40,10 @@
#extension GL_OES_standard_derivatives : enable #extension GL_OES_standard_derivatives : enable
#endif #endif
#if defined(GL_ES) && !defined(NO_GEOMETRY_SHADER) && defined(GL_NV_shader_noperspective_interpolation)
#extension GL_NV_shader_noperspective_interpolation: require
#endif
#ifndef GL_ES #ifndef GL_ES
layout(location = 2) uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0); layout(location = 2) uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
#else #else
@ -58,7 +62,10 @@ uniform lowp float smoothness;
#endif #endif
#ifndef NO_GEOMETRY_SHADER #ifndef NO_GEOMETRY_SHADER
noperspective in lowp vec3 dist; #ifdef GL_NV_shader_noperspective_interpolation
noperspective
#endif
in lowp vec3 dist;
#else #else
in lowp vec3 barycentric; in lowp vec3 barycentric;
#endif #endif
@ -72,7 +79,7 @@ void main() {
#ifdef WIREFRAME_RENDERING #ifdef WIREFRAME_RENDERING
#ifndef NO_GEOMETRY_SHADER #ifndef NO_GEOMETRY_SHADER
/* Distance to nearest side */ /* Distance to nearest side */
const float nearest = min(min(dist.x, dist.y), dist.z); lowp const float nearest = min(min(dist.x, dist.y), dist.z);
/* Smooth step between face color and wireframe color based on distance */ /* Smooth step between face color and wireframe color based on distance */
fragmentColor = mix(wireframeColor, color, smoothstep(wireframeWidth-smoothness, wireframeWidth+smoothness, nearest)); fragmentColor = mix(wireframeColor, color, smoothstep(wireframeWidth-smoothness, wireframeWidth+smoothness, nearest));

18
src/Magnum/Shaders/MeshVisualizer.geom

@ -27,6 +27,13 @@
#define const #define const
#endif #endif
#ifdef GL_ES
#extension GL_EXT_geometry_shader: require
#ifdef GL_NV_shader_noperspective_interpolation
#extension GL_NV_shader_noperspective_interpolation: require
#endif
#endif
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 1) uniform vec2 viewportSize; layout(location = 1) uniform vec2 viewportSize;
#else #else
@ -37,8 +44,11 @@ layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out; layout(triangle_strip, max_vertices = 3) out;
/* Interpolate in screen space */ /* Interpolate in screen space (if possible) */
noperspective out vec3 dist; #ifdef GL_NV_shader_noperspective_interpolation
noperspective
#endif
out lowp vec3 dist;
void main() { void main() {
/* Screen position of each vertex */ /* Screen position of each vertex */
@ -47,11 +57,11 @@ void main() {
p[i] = viewportSize*gl_in[i].gl_Position.xy/gl_in[i].gl_Position.w; p[i] = viewportSize*gl_in[i].gl_Position.xy/gl_in[i].gl_Position.w;
/* Vector of each triangle side */ /* Vector of each triangle side */
const vec2 v[3] = { const vec2 v[3] = vec2[3](
p[2]-p[1], p[2]-p[1],
p[2]-p[0], p[2]-p[0],
p[1]-p[0] p[1]-p[0]
}; );
/* Compute area using perp-dot product */ /* Compute area using perp-dot product */
const float area = abs(dot(vec2(-v[1].y, v[1].x), v[2])); const float area = abs(dot(vec2(-v[1].y, v[1].x), v[2]));

15
src/Magnum/Shaders/MeshVisualizer.h

@ -56,15 +56,20 @@ If you have geometry shaders available, you don't need to do anything else.
@requires_gl32 Extension @extension{ARB,geometry_shader4} for wireframe @requires_gl32 Extension @extension{ARB,geometry_shader4} for wireframe
rendering using geometry shaders. rendering using geometry shaders.
@requires_es_extension Extension @es_extension{EXT,geometry_shader} for
wireframe rendering using geometry shaders.
If you don't have geometry shaders, you need to set @ref Flag::NoGeometryShader If you don't have geometry shaders, you need to set @ref Flag::NoGeometryShader
(it's enabled by default in OpenGL ES) and use only **non-indexed** triangle (it's enabled by default in OpenGL ES 2.0) and use only **non-indexed** triangle
meshes (see @ref MeshTools::duplicate() for possible solution). Additionaly, if meshes (see @ref MeshTools::duplicate() for possible solution). Additionaly, if
you have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also you have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also
@ref VertexIndex attribute. @ref VertexIndex attribute.
@requires_es_extension Extension @extension{OES,standard_derivatives} for @requires_gles30 Extension @es_extension{OES,standard_derivatives} for
wireframe rendering. wireframe rendering without geometry shaders.
If using geometry shaders on OpenGL ES, @es_extension{NV,shader_noperspective_interpolation}
is optionally used for improving line appearance.
## Example usage ## Example usage
@ -174,10 +179,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram {
*/ */
enum class Flag: UnsignedByte { enum class Flag: UnsignedByte {
/** /**
* Visualize wireframe. On OpenGL ES this also enables * Visualize wireframe. On OpenGL ES 2.0 this also enables
* @ref Flag::NoGeometryShader. * @ref Flag::NoGeometryShader.
*/ */
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES2
Wireframe = 1 << 0, Wireframe = 1 << 0,
#else #else
Wireframe = (1 << 0) | (1 << 1), Wireframe = (1 << 0) | (1 << 1),

18
src/Magnum/Shaders/Test/MeshVisualizerGLTest.cpp

@ -34,13 +34,17 @@ struct MeshVisualizerGLTest: Magnum::Test::AbstractOpenGLTester {
explicit MeshVisualizerGLTest(); explicit MeshVisualizerGLTest();
void compile(); void compile();
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void compileWireframeGeometryShader(); void compileWireframeGeometryShader();
#endif
void compileWireframeNoGeometryShader(); void compileWireframeNoGeometryShader();
}; };
MeshVisualizerGLTest::MeshVisualizerGLTest() { MeshVisualizerGLTest::MeshVisualizerGLTest() {
addTests({&MeshVisualizerGLTest::compile, addTests({&MeshVisualizerGLTest::compile,
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
&MeshVisualizerGLTest::compileWireframeGeometryShader, &MeshVisualizerGLTest::compileWireframeGeometryShader,
#endif
&MeshVisualizerGLTest::compileWireframeNoGeometryShader}); &MeshVisualizerGLTest::compileWireframeNoGeometryShader});
} }
@ -49,17 +53,23 @@ void MeshVisualizerGLTest::compile() {
CORRADE_VERIFY(shader.validate().first); CORRADE_VERIFY(shader.validate().first);
} }
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
void MeshVisualizerGLTest::compileWireframeGeometryShader() { void MeshVisualizerGLTest::compileWireframeGeometryShader() {
#ifdef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_SKIP("Geometry shader is not available in OpenGL ES");
#else
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::geometry_shader4>())
CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not supported")); CORRADE_SKIP(Extensions::GL::ARB::geometry_shader4::string() + std::string(" is not supported"));
#else
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::geometry_shader>())
CORRADE_SKIP(Extensions::GL::EXT::geometry_shader::string() + std::string(" is not supported"));
#endif
if(Context::current()->isExtensionSupported<Extensions::GL::NV::shader_noperspective_interpolation>())
Debug() << "Using" << Extensions::GL::NV::shader_noperspective_interpolation::string();
Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe); Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe);
CORRADE_VERIFY(shader.validate().first); CORRADE_VERIFY(shader.validate().first);
#endif
} }
#endif
void MeshVisualizerGLTest::compileWireframeNoGeometryShader() { void MeshVisualizerGLTest::compileWireframeNoGeometryShader() {
Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe|Shaders::MeshVisualizer::Flag::NoGeometryShader); Shaders::MeshVisualizer shader(Shaders::MeshVisualizer::Flag::Wireframe|Shaders::MeshVisualizer::Flag::NoGeometryShader);

Loading…
Cancel
Save