Browse Source

Added Mesh::addVertexBufferInstanced().

Functionality provided by GL 3.3 and ARB_instanced_arrays, on ES2 this
is again implemented in three different extensions --
{ANGLE,EXT,NV}_instanced_arrays. They are disabled until Magnum has
proper extension loading on ES.
pull/54/head
Vladimír Vondruš 12 years ago
parent
commit
71a5766594
  1. 2
      doc/opengl-mapping.dox
  2. 6
      doc/opengl-support.dox
  3. 2
      src/Magnum/Context.cpp
  4. 2
      src/Magnum/Extensions.h
  5. 18
      src/Magnum/Implementation/MeshState.cpp
  6. 3
      src/Magnum/Implementation/MeshState.h
  7. 2
      src/Magnum/Implementation/setupDriverWorkarounds.cpp
  8. 35
      src/Magnum/Mesh.cpp
  9. 65
      src/Magnum/Mesh.h
  10. 133
      src/Magnum/Test/MeshGLTest.cpp

2
doc/opengl-mapping.dox

@ -247,7 +247,7 @@ OpenGL function | Matching API
@fn_gl{ValidateProgramPipeline} | |
@fn_gl{VertexAttrib} | not supported (@ref opengl-unsupported "details")
@fn_gl{VertexAttribBinding} | |
@fn_gl{VertexAttribDivisor} | |
@fn_gl{VertexAttribDivisor}, \n @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access} | @ref Mesh::addVertexBufferInstanced()
@fn_gl{VertexAttribFormat} | |
@fn_gl{VertexAttribPointer}, \n @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} | @ref Mesh::addVertexBuffer()
@fn_gl{VertexBindingDivisor} | |

6
doc/opengl-support.dox

@ -107,7 +107,7 @@ following:
%Extension | Status
-------------------------------------------- | ------
@extension{ARB,instanced_arrays} | |
@extension{ARB,instanced_arrays} | done
@extension{ARB,blend_func_extended} | missing limit query
@extension{ARB,explicit_attrib_location} | done (shading language only)
@extension{ARB,occlusion_query2} | done
@ -243,7 +243,7 @@ supported.
-------------------------------------------- | ------
@es_extension{ANGLE,framebuffer_blit} | done
@es_extension{ANGLE,framebuffer_multisample} | done
@es_extension{ANGLE,instanced_arrays} | missing vertex attrib divisor
@es_extension{ANGLE,instanced_arrays} | done
@es_extension{ANGLE,depth_texture} | done
@es_extension{APPLE,framebuffer_multisample} | done (ES 3.0 subset)
@es_extension{APPLE,texture_max_level} | done
@ -257,6 +257,7 @@ supported.
@es_extension{EXT,texture_rg} | done
@es_extension{EXT,texture_storage} | done
@es_extension{EXT,map_buffer_range} | done
@es_extension{EXT,instanced_arrays} | done
@es_extension2{EXT,draw_instanced,draw_instanced} | done
@es_extension{NV,draw_buffers} | done
@es_extension{NV,fbo_color_attachments} | done
@ -264,6 +265,7 @@ supported.
@es_extension{NV,draw_instanced} | done
@es_extension{NV,framebuffer_blit} | done
@es_extension{NV,framebuffer_multisample} | done
@es_extension{NV,instanced_arrays} | done
@es_extension{NV,shadow_samplers_array} | done (shading language only)
@es_extension{NV,shadow_samplers_cube} | done (shading language only)
@es_extension{OES,depth24} | done

2
src/Magnum/Context.cpp

@ -226,6 +226,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_rg),
_extension(GL,EXT,texture_storage),
_extension(GL,EXT,map_buffer_range),
_extension(GL,EXT,instanced_arrays),
_extension(GL,EXT,draw_instanced),
_extension(GL,NV,draw_buffers),
_extension(GL,NV,fbo_color_attachments),
@ -233,6 +234,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,NV,draw_instanced),
_extension(GL,NV,framebuffer_blit),
_extension(GL,NV,framebuffer_multisample),
_extension(GL,NV,instanced_arrays),
_extension(GL,NV,shadow_samplers_array),
_extension(GL,NV,shadow_samplers_cube),
_extension(GL,OES,depth24),

2
src/Magnum/Extensions.h

@ -255,6 +255,7 @@ namespace GL {
#endif
_extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150
#ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,instanced_arrays, GLES200, GLES300) // #156
_extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157
#endif
#ifndef MAGNUM_TARGET_GLES2
@ -276,6 +277,7 @@ namespace GL {
_extension(GL,NV,draw_instanced, GLES200, GLES300) // #141
_extension(GL,NV,framebuffer_blit, GLES200, GLES300) // #142
_extension(GL,NV,framebuffer_multisample, GLES200, GLES300) // #143
_extension(GL,NV,instanced_arrays, GLES200, GLES300) // #145
_extension(GL,NV,shadow_samplers_array, GLES200, GLES300) // #146
_extension(GL,NV,shadow_samplers_cube, GLES200, GLES300) // #147
#endif

18
src/Magnum/Implementation/MeshState.cpp

@ -117,6 +117,24 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
drawArraysInstancedImplementation = nullptr;
drawElementsInstancedImplementation = nullptr;
}
/* Instanced arrays implementation on ES2 */
if(context.isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>()) {
/* Extension added above */
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE;
} else if(context.isExtensionSupported<Extensions::GL::EXT::instanced_arrays>()) {
extensions.push_back(Extensions::GL::EXT::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT;
} else if(context.isExtensionSupported<Extensions::GL::NV::instanced_arrays>()) {
extensions.push_back(Extensions::GL::NV::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV;
} else vertexAttribDivisorImplementation = nullptr;
#endif
}

3
src/Magnum/Implementation/MeshState.h

@ -44,6 +44,9 @@ struct MeshState {
void(Mesh::*attributeLPointerImplementation)(const Mesh::LongAttribute&);
#endif
#endif
#ifdef MAGNUM_TARGET_GLES2
void(Mesh::*vertexAttribDivisorImplementation)(GLuint, GLuint);
#endif
void(Mesh::*bindIndexBufferImplementation)(Buffer&);
void(Mesh::*bindImplementation)();
void(Mesh::*unbindImplementation)();

2
src/Magnum/Implementation/setupDriverWorkarounds.cpp

@ -77,6 +77,7 @@ void Context::setupDriverWorkarounds() {
#endif
_setRequiredVersion(GL::EXT::texture_storage, None);
_setRequiredVersion(GL::EXT::map_buffer_range, None);
_setRequiredVersion(GL::EXT::instanced_arrays, None);
_setRequiredVersion(GL::EXT::draw_instanced, None);
_setRequiredVersion(GL::NV::draw_buffers, None);
_setRequiredVersion(GL::NV::fbo_color_attachments, None); // ??
@ -84,6 +85,7 @@ void Context::setupDriverWorkarounds() {
_setRequiredVersion(GL::NV::draw_instanced, None);
_setRequiredVersion(GL::NV::framebuffer_blit, None);
_setRequiredVersion(GL::NV::framebuffer_multisample, None);
_setRequiredVersion(GL::NV::instanced_arrays, None);
_setRequiredVersion(GL::OES::texture_3D, None);
_setRequiredVersion(GL::OES::vertex_array_object, None);
#endif

35
src/Magnum/Mesh.cpp

@ -348,6 +348,7 @@ void Mesh::attributePointerImplementationVAO(const Attribute& attribute) {
void Mesh::attributePointerImplementationDSA(const Attribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
}
#endif
@ -355,6 +356,13 @@ void Mesh::vertexAttribPointer(const Attribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribPointer(attribute.location, attribute.size, attribute.type, attribute.normalized, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) {
#ifndef MAGNUM_TARGET_GLES2
glVertexAttribDivisor(attribute.location, attribute.divisor);
#else
(this->*Context::current()->state().mesh->vertexAttribDivisorImplementation)(attribute.location, attribute.divisor);
#endif
}
}
#ifndef MAGNUM_TARGET_GLES2
@ -375,6 +383,7 @@ void Mesh::attributePointerImplementationVAO(const IntegerAttribute& attribute)
void Mesh::attributePointerImplementationDSA(const IntegerAttribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribIOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
}
#endif
@ -382,6 +391,7 @@ void Mesh::vertexAttribPointer(const IntegerAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribIPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
}
#endif
@ -402,12 +412,37 @@ void Mesh::attributePointerImplementationVAO(const LongAttribute& attribute) {
void Mesh::attributePointerImplementationDSA(const LongAttribute& attribute) {
glEnableVertexArrayAttribEXT(_id, attribute.location);
glVertexArrayVertexAttribLOffsetEXT(_id, attribute.buffer->id(), attribute.location, attribute.size, attribute.type, attribute.stride, attribute.offset);
if(attribute.divisor) glVertexArrayVertexAttribDivisorEXT(_id, attribute.location, attribute.divisor);
}
void Mesh::vertexAttribPointer(const LongAttribute& attribute) {
glEnableVertexAttribArray(attribute.location);
attribute.buffer->bind(Buffer::Target::Array);
glVertexAttribLPointer(attribute.location, attribute.size, attribute.type, attribute.stride, reinterpret_cast<const GLvoid*>(attribute.offset));
if(attribute.divisor) glVertexAttribDivisor(attribute.location, attribute.divisor);
}
#endif
#ifdef MAGNUM_TARGET_GLES2
void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorANGLE(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
}
void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorEXT(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
}
void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) {
//glVertexAttribDivisorNV(index, divisor);
CORRADE_INTERNAL_ASSERT(false);
static_cast<void>(index);
static_cast<void>(divisor);
}
#endif

65
src/Magnum/Mesh.h

@ -669,7 +669,34 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* if @extension{APPLE,vertex_array_object} is available
*/
template<class ...T> inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), attributes...);
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...);
return *this;
}
/**
* @brief Add instanced vertex buffer
* @return Reference to self (for method chaining)
*
* Similar to the above function, the @p divisor parameter specifies
* number of instances that will pass until new data are fetched from
* the buffer. Setting it to `0` is equivalent to calling
* @ref addVertexBuffer().
* @see @ref maxVertexAttributes(), @ref setPrimitive(),
* @ref setCount(), @ref setInstanceCount(), @ref setBaseInstance(),
* @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray},
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{VertexAttribDivisor} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribDivisor,EXT,direct_state_access}
* if @extension{APPLE,vertex_array_object} is available
* @requires_gl33 %Extension @extension{ARB,instanced_arrays}
* @requires_gles30 %Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension{EXT,instanced_arrays} or
* @es_extension{NV,instanced_arrays} in OpenGL ES 2.0.
*/
template<class ...T> inline Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...);
return *this;
}
@ -773,6 +800,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
bool normalized;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#ifndef MAGNUM_TARGET_GLES2
@ -783,6 +811,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#ifndef MAGNUM_TARGET_GLES
@ -793,6 +822,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum type;
GLintptr offset;
GLsizei stride;
GLuint divisor;
};
#endif
#endif
@ -808,19 +838,19 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
static GLsizei strideOfInterleaved() { return 0; }
/* Adding interleaved vertex attributes */
template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
addVertexAttribute(buffer, attribute, offset, stride);
template<UnsignedInt location, class T, class ...U> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, const AbstractShaderProgram::Attribute<location, T>& attribute, const U&... attributes) {
addVertexAttribute(buffer, attribute, offset, stride, divisor);
/* Add size of this attribute to offset for next attribute */
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, attributes...);
addVertexBufferInternal(buffer, offset+attribute.vectorSize()*AbstractShaderProgram::Attribute<location, T>::VectorCount, stride, divisor, attributes...);
}
template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) {
template<class ...T> void addVertexBufferInternal(Buffer& buffer, GLintptr offset, GLsizei stride, GLuint divisor, GLintptr gap, const T&... attributes) {
/* Add the gap to offset for next attribute */
addVertexBufferInternal(buffer, offset+gap, stride, attributes...);
addVertexBufferInternal(buffer, offset+gap, stride, divisor, attributes...);
}
void addVertexBufferInternal(Buffer&, GLsizei, GLintptr) {}
void addVertexBufferInternal(Buffer&, GLsizei, GLuint, GLintptr) {}
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Float>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(Attribute{
&buffer,
@ -829,24 +859,26 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLenum(attribute.dataType()),
bool(attribute.dataOptions() & AbstractShaderProgram::Attribute<location, T>::DataOption::Normalized),
GLintptr(offset+i*attribute.vectorSize()),
stride
stride,
divisor
});
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_integral<typename Implementation::Attribute<T>::ScalarType>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
attributePointerInternal(IntegerAttribute{
&buffer,
location,
GLint(attribute.components()),
GLenum(attribute.dataType()),
offset,
stride
stride,
divisor
});
}
#ifndef MAGNUM_TARGET_GLES
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride) {
template<UnsignedInt location, class T> void addVertexAttribute(typename std::enable_if<std::is_same<typename Implementation::Attribute<T>::ScalarType, Double>::value, Buffer&>::type buffer, const AbstractShaderProgram::Attribute<location, T>& attribute, GLintptr offset, GLsizei stride, GLuint divisor) {
for(UnsignedInt i = 0; i != AbstractShaderProgram::Attribute<location, T>::VectorCount; ++i)
attributePointerInternal(LongAttribute{
&buffer,
@ -854,7 +886,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLint(attribute.components()),
GLenum(attribute.dataType()),
GLintptr(offset+i*attribute.vectorSize()),
stride
stride,
divisor
});
}
#endif
@ -902,6 +935,12 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL vertexAttribPointer(const LongAttribute& attribute);
#endif
#ifdef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL vertexAttribDivisorImplementationANGLE(GLuint index, GLuint divisor);
void MAGNUM_LOCAL vertexAttribDivisorImplementationEXT(GLuint index, GLuint divisor);
void MAGNUM_LOCAL vertexAttribDivisorImplementationNV(GLuint index, GLuint divisor);
#endif
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&);
void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer);

133
src/Magnum/Test/MeshGLTest.cpp

@ -118,6 +118,14 @@ class MeshGLTest: public AbstractOpenGLTester {
void setInstanceCountBaseVertex();
void setInstanceCountBaseVertexBaseInstance();
#endif
void addVertexBufferInstancedFloat();
#ifndef MAGNUM_TARGET_GLES2
void addVertexBufferInstancedInteger();
#endif
#ifndef MAGNUM_TARGET_GLES
void addVertexBufferInstancedDouble();
#endif
};
MeshGLTest::MeshGLTest() {
@ -191,7 +199,15 @@ MeshGLTest::MeshGLTest() {
&MeshGLTest::setInstanceCountBaseInstance,
&MeshGLTest::setInstanceCountBaseInstanceIndexed,
&MeshGLTest::setInstanceCountBaseVertex,
&MeshGLTest::setInstanceCountBaseVertexBaseInstance
&MeshGLTest::setInstanceCountBaseVertexBaseInstance,
#endif
&MeshGLTest::addVertexBufferInstancedFloat,
#ifndef MAGNUM_TARGET_GLES2
&MeshGLTest::addVertexBufferInstancedInteger,
#endif
#ifndef MAGNUM_TARGET_GLES
&MeshGLTest::addVertexBufferInstancedDouble
#endif
});
}
@ -1538,6 +1554,121 @@ void MeshGLTest::setInstanceCountBaseVertexBaseInstance() {
}
#endif
void MeshGLTest::addVertexBufferInstancedFloat() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
#elif defined(MAGNUM_TARGET_GLES2)
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::instanced_arrays>())
CORRADE_SKIP("Required instancing extension is not available.");
if(!Context::current()->isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>() && !Context::current()->isExtensionSupported<Extensions::GL::EXT::draw_instanced>() && !Context::current()->isExtensionSupported<Extensions::GL::NV::draw_instanced>())
CORRADE_SKIP("Required drawing extension is not available.");
#endif
typedef AbstractShaderProgram::Attribute<0, Float> Attribute;
const Float data[] = {
0.0f, /* Offset */
/* Base vertex is ignored for instanced arrays */
-0.7f, /* First instance */
0.3f, /* Second instance */
Math::normalize<Float, UnsignedByte>(96) /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 4, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"),
#ifndef MAGNUM_TARGET_GLES2
RenderbufferFormat::RGBA8,
#else
RenderbufferFormat::RGBA4,
#endif
mesh).get<UnsignedByte>(ColorFormat::RGBA, ColorType::UnsignedByte);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 96);
}
#ifndef MAGNUM_TARGET_GLES2
void MeshGLTest::addVertexBufferInstancedInteger() {
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>())
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available."));
#endif
typedef AbstractShaderProgram::Attribute<0, UnsignedInt> Attribute;
constexpr UnsignedInt data[] = {
0, /* Offset */
/* Base vertex is ignored for instanced arrays */
157, /* First instance */
25, /* Second instance */
35681 /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 4, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R32UI, mesh)
.get<UnsignedInt>(ColorFormat::RedInteger, ColorType::UnsignedInt);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 35681);
}
#endif
#ifndef MAGNUM_TARGET_GLES
void MeshGLTest::addVertexBufferInstancedDouble() {
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_instanced>())
CORRADE_SKIP(Extensions::GL::ARB::draw_instanced::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::instanced_arrays>())
CORRADE_SKIP(Extensions::GL::ARB::instanced_arrays::string() + std::string(" is not available."));
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_attrib_64bit>())
CORRADE_SKIP(Extensions::GL::ARB::vertex_attrib_64bit::string() + std::string(" is not available."));
typedef AbstractShaderProgram::Attribute<0, Double> Attribute;
const Double data[] = {
0.0, /* Offset */
/* Base vertex is ignored for instanced arrays */
-0.7, /* First instance */
0.3, /* Second instance */
Math::normalize<Double, UnsignedShort>(45828) /* Third instance */
};
Buffer buffer;
buffer.setData(data, BufferUsage::StaticDraw);
Mesh mesh;
mesh.setInstanceCount(3)
.addVertexBufferInstanced(buffer, 1, 8, Attribute{});
MAGNUM_VERIFY_NO_ERROR();
const auto value = Checker(DoubleShader("double", "float", "vec4(value, 0.0, 0.0, 0.0)"),
RenderbufferFormat::R16, mesh).get<UnsignedShort>(ColorFormat::Red, ColorType::UnsignedShort);
MAGNUM_VERIFY_NO_ERROR();
CORRADE_COMPARE(value, 45828);
}
#endif
}}
CORRADE_TEST_MAIN(Magnum::Test::MeshGLTest)

Loading…
Cancel
Save