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 {
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)) {
#ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_VERSION_SUPPORTED(Version::GL320);
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)
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::OES::standard_derivatives);
#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});
CORRADE_INTERNAL_ASSERT(flags & Flag::NoGeometryShader || version >= Version::GL320);
#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
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(rs.get("MeshVisualizer.frag"));
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
std::optional<Shader> geom;
if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) {
geom = Implementation::createCompatibilityShader(rs, version, Shader::Type::Geometry);
@ -86,14 +91,14 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
}
#endif
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(geom) CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, *geom, frag}));
else
#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag}));
attachShaders({vert, frag});
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
if(geom) attachShader(*geom);
#endif

11
src/Magnum/Shaders/MeshVisualizer.frag

@ -40,6 +40,10 @@
#extension GL_OES_standard_derivatives : enable
#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
layout(location = 2) uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0);
#else
@ -58,7 +62,10 @@ uniform lowp float smoothness;
#endif
#ifndef NO_GEOMETRY_SHADER
noperspective in lowp vec3 dist;
#ifdef GL_NV_shader_noperspective_interpolation
noperspective
#endif
in lowp vec3 dist;
#else
in lowp vec3 barycentric;
#endif
@ -72,7 +79,7 @@ void main() {
#ifdef WIREFRAME_RENDERING
#ifndef NO_GEOMETRY_SHADER
/* 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 */
fragmentColor = mix(wireframeColor, color, smoothstep(wireframeWidth-smoothness, wireframeWidth+smoothness, nearest));

18
src/Magnum/Shaders/MeshVisualizer.geom

@ -27,6 +27,13 @@
#define const
#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
layout(location = 1) uniform vec2 viewportSize;
#else
@ -37,8 +44,11 @@ layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
/* Interpolate in screen space */
noperspective out vec3 dist;
/* Interpolate in screen space (if possible) */
#ifdef GL_NV_shader_noperspective_interpolation
noperspective
#endif
out lowp vec3 dist;
void main() {
/* 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;
/* Vector of each triangle side */
const vec2 v[3] = {
const vec2 v[3] = vec2[3](
p[2]-p[1],
p[2]-p[0],
p[1]-p[0]
};
);
/* Compute area using perp-dot product */
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
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
(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
you have OpenGL < 3.1 or OpenGL ES 2.0, you need to provide also
@ref VertexIndex attribute.
@requires_es_extension Extension @extension{OES,standard_derivatives} for
wireframe rendering.
@requires_gles30 Extension @es_extension{OES,standard_derivatives} for
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
@ -174,10 +179,10 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizer: public AbstractShaderProgram {
*/
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.
*/
#ifndef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_GLES2
Wireframe = 1 << 0,
#else
Wireframe = (1 << 0) | (1 << 1),

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

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

Loading…
Cancel
Save