mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1889 lines
65 KiB
1889 lines
65 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015 |
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
#include "Magnum/AbstractShaderProgram.h" |
|
#include "Magnum/Buffer.h" |
|
#include "Magnum/Framebuffer.h" |
|
#include "Magnum/Image.h" |
|
#include "Magnum/Mesh.h" |
|
#include "Magnum/MeshView.h" |
|
#include "Magnum/PixelFormat.h" |
|
#include "Magnum/Renderbuffer.h" |
|
#include "Magnum/RenderbufferFormat.h" |
|
#include "Magnum/Shader.h" |
|
#include "Magnum/Math/Color.h" |
|
#include "Magnum/Math/Matrix.h" |
|
#include "Magnum/Math/Vector4.h" |
|
#include "Magnum/Test/AbstractOpenGLTester.h" |
|
|
|
namespace Magnum { namespace Test { |
|
|
|
/* Tests also MeshView class. */ |
|
|
|
struct MeshGLTest: AbstractOpenGLTester { |
|
explicit MeshGLTest(); |
|
|
|
void construct(); |
|
void constructNoCreate(); |
|
void constructCopy(); |
|
void constructMove(); |
|
void wrap(); |
|
|
|
void label(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferUnsignedInt(); |
|
void addVertexBufferInt(); |
|
#endif |
|
void addVertexBufferFloat(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferDouble(); |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferVectorNui(); |
|
void addVertexBufferVectorNi(); |
|
#endif |
|
void addVertexBufferVectorN(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferVectorNd(); |
|
#endif |
|
void addVertexBufferMatrixNxN(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferMatrixNxNd(); |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferMatrixMxN(); |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferMatrixMxNd(); |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferUnsignedIntWithUnsignedShort(); |
|
void addVertexBufferUnsignedIntWithShort(); |
|
void addVertexBufferIntWithUnsignedShort(); |
|
void addVertexBufferIntWithShort(); |
|
#endif |
|
/* Other Float types omitted (covered by addVertexBufferNormalized()) */ |
|
void addVertexBufferFloatWithHalfFloat(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferFloatWithDouble(); |
|
void addVertexBufferVector3WithUnsignedInt10f11f11fRev(); |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferVector4WithUnsignedInt2101010Rev(); |
|
void addVertexBufferVector4WithInt2101010Rev(); |
|
#endif |
|
|
|
void addVertexBufferLessVectorComponents(); |
|
void addVertexBufferNormalized(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferBGRA(); |
|
#endif |
|
|
|
void addVertexBufferMultiple(); |
|
void addVertexBufferMultipleGaps(); |
|
|
|
void setIndexBuffer(); |
|
void setIndexBufferRange(); |
|
void setIndexBufferUnsignedInt(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void setBaseVertex(); |
|
#endif |
|
void setInstanceCount(); |
|
void setInstanceCountIndexed(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void setInstanceCountBaseInstance(); |
|
void setInstanceCountBaseInstanceIndexed(); |
|
void setInstanceCountBaseVertex(); |
|
void setInstanceCountBaseVertexBaseInstance(); |
|
#endif |
|
|
|
void addVertexBufferInstancedFloat(); |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void addVertexBufferInstancedInteger(); |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES |
|
void addVertexBufferInstancedDouble(); |
|
#endif |
|
|
|
void multiDraw(); |
|
void multiDrawIndexed(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void multiDrawBaseVertex(); |
|
#endif |
|
}; |
|
|
|
MeshGLTest::MeshGLTest() { |
|
addTests({&MeshGLTest::construct, |
|
&MeshGLTest::constructNoCreate, |
|
&MeshGLTest::constructCopy, |
|
&MeshGLTest::constructMove, |
|
&MeshGLTest::wrap, |
|
|
|
&MeshGLTest::label, |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferUnsignedInt, |
|
&MeshGLTest::addVertexBufferInt, |
|
#endif |
|
&MeshGLTest::addVertexBufferFloat, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferDouble, |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferVectorNui, |
|
&MeshGLTest::addVertexBufferVectorNi, |
|
#endif |
|
&MeshGLTest::addVertexBufferVectorN, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferVectorNd, |
|
#endif |
|
&MeshGLTest::addVertexBufferMatrixNxN, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferMatrixNxNd, |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferMatrixMxN, |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferMatrixMxNd, |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort, |
|
&MeshGLTest::addVertexBufferUnsignedIntWithShort, |
|
&MeshGLTest::addVertexBufferIntWithUnsignedShort, |
|
&MeshGLTest::addVertexBufferIntWithShort, |
|
#endif |
|
&MeshGLTest::addVertexBufferFloatWithHalfFloat, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferFloatWithDouble, |
|
&MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev, |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev, |
|
&MeshGLTest::addVertexBufferVector4WithInt2101010Rev, |
|
#endif |
|
|
|
&MeshGLTest::addVertexBufferLessVectorComponents, |
|
&MeshGLTest::addVertexBufferNormalized, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferBGRA, |
|
#endif |
|
|
|
&MeshGLTest::addVertexBufferMultiple, |
|
&MeshGLTest::addVertexBufferMultipleGaps, |
|
|
|
&MeshGLTest::setIndexBuffer, |
|
&MeshGLTest::setIndexBufferRange, |
|
&MeshGLTest::setIndexBufferUnsignedInt, |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::setBaseVertex, |
|
#endif |
|
&MeshGLTest::setInstanceCount, |
|
&MeshGLTest::setInstanceCountIndexed, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::setInstanceCountBaseInstance, |
|
&MeshGLTest::setInstanceCountBaseInstanceIndexed, |
|
&MeshGLTest::setInstanceCountBaseVertex, |
|
&MeshGLTest::setInstanceCountBaseVertexBaseInstance, |
|
#endif |
|
|
|
&MeshGLTest::addVertexBufferInstancedFloat, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
&MeshGLTest::addVertexBufferInstancedInteger, |
|
#endif |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::addVertexBufferInstancedDouble, |
|
#endif |
|
|
|
&MeshGLTest::multiDraw, |
|
&MeshGLTest::multiDrawIndexed, |
|
#ifndef MAGNUM_TARGET_GLES |
|
&MeshGLTest::multiDrawBaseVertex |
|
#endif |
|
}); |
|
} |
|
|
|
void MeshGLTest::construct() { |
|
{ |
|
const Mesh mesh; |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>()) |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) |
|
#endif |
|
{ |
|
CORRADE_VERIFY(mesh.id() > 0); |
|
} |
|
} |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
} |
|
|
|
void MeshGLTest::constructNoCreate() { |
|
{ |
|
Mesh mesh{NoCreate}; |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(mesh.id(), 0); |
|
} |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
} |
|
|
|
void MeshGLTest::constructCopy() { |
|
CORRADE_VERIFY(!(std::is_constructible<Mesh, const Mesh&>{})); |
|
CORRADE_VERIFY(!(std::is_assignable<Mesh, const Mesh&>{})); |
|
} |
|
|
|
void MeshGLTest::constructMove() { |
|
Mesh a; |
|
const Int id = a.id(); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>()) |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) |
|
#endif |
|
{ |
|
CORRADE_VERIFY(id > 0); |
|
} |
|
|
|
Mesh b(std::move(a)); |
|
|
|
CORRADE_COMPARE(a.id(), 0); |
|
CORRADE_COMPARE(b.id(), id); |
|
|
|
Mesh c; |
|
const Int cId = c.id(); |
|
c = std::move(b); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
if(Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>()) |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
if(Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) |
|
#endif |
|
{ |
|
CORRADE_VERIFY(cId > 0); |
|
} |
|
|
|
CORRADE_COMPARE(b.id(), cId); |
|
CORRADE_COMPARE(c.id(), id); |
|
} |
|
|
|
void MeshGLTest::wrap() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_object>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::vertex_array_object::string() + std::string{" is not supported."}); |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_array_object>()) |
|
CORRADE_SKIP(Extensions::GL::OES::vertex_array_object::string() + std::string{" is not supported."}); |
|
#endif |
|
|
|
GLuint id; |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
glGenVertexArrays(1, &id); |
|
#else |
|
glGenVertexArraysOES(1, &id); |
|
#endif |
|
|
|
/* Releasing won't delete anything */ |
|
{ |
|
auto mesh = Mesh::wrap(id, ObjectFlag::DeleteOnDestruction); |
|
CORRADE_COMPARE(mesh.release(), id); |
|
} |
|
|
|
/* ...so we can wrap it again */ |
|
Mesh::wrap(id); |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
glDeleteVertexArrays(1, &id); |
|
#else |
|
glDeleteVertexArraysOES(1, &id); |
|
#endif |
|
} |
|
|
|
void MeshGLTest::label() { |
|
/* No-Op version is tested in AbstractObjectGLTest */ |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::KHR::debug>() && |
|
!Context::current()->isExtensionSupported<Extensions::GL::EXT::debug_label>()) |
|
CORRADE_SKIP("Required extension is not available"); |
|
|
|
Mesh mesh; |
|
|
|
CORRADE_COMPARE(mesh.label(), ""); |
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
mesh.setLabel("MyMesh"); |
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
CORRADE_COMPARE(mesh.label(), "MyMesh"); |
|
} |
|
|
|
namespace { |
|
struct FloatShader: AbstractShaderProgram { |
|
explicit FloatShader(const std::string& type, const std::string& conversion); |
|
}; |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
struct IntegerShader: AbstractShaderProgram { |
|
explicit IntegerShader(const std::string& type); |
|
}; |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
struct DoubleShader: AbstractShaderProgram { |
|
explicit DoubleShader(const std::string& type, const std::string& outputType, const std::string& conversion); |
|
}; |
|
#endif |
|
|
|
struct Checker { |
|
Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh& mesh); |
|
|
|
template<class T> T get(PixelFormat format, PixelType type); |
|
|
|
Renderbuffer renderbuffer; |
|
Framebuffer framebuffer; |
|
}; |
|
} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
FloatShader::FloatShader(const std::string& type, const std::string& conversion) { |
|
/* We need special version for ES3, because GLSL in ES2 doesn't support |
|
rectangle matrices */ |
|
#ifndef MAGNUM_TARGET_GLES |
|
Shader vert(Version::GL210, Shader::Type::Vertex); |
|
Shader frag(Version::GL210, Shader::Type::Fragment); |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
Shader vert(Version::GLES200, Shader::Type::Vertex); |
|
Shader frag(Version::GLES200, Shader::Type::Fragment); |
|
#else |
|
Shader vert(Version::GLES300, Shader::Type::Vertex); |
|
Shader frag(Version::GLES300, Shader::Type::Fragment); |
|
#endif |
|
|
|
vert.addSource( |
|
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) |
|
"#if !defined(GL_ES) && __VERSION__ == 120\n" |
|
"#define mediump\n" |
|
"#endif\n" |
|
"attribute mediump " + type + " value;\n" |
|
"varying mediump " + type + " valueInterpolated;\n" |
|
#else |
|
"in mediump " + type + " value;\n" |
|
"out mediump " + type + " valueInterpolated;\n" |
|
#endif |
|
"void main() {\n" |
|
" valueInterpolated = value;\n" |
|
" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
|
"}\n"); |
|
|
|
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) |
|
frag.addSource("#if !defined(GL_ES) && __VERSION__ == 120\n" |
|
"#define mediump\n" |
|
"#endif\n" |
|
"varying mediump " + type + " valueInterpolated;\n" |
|
"void main() { gl_FragColor = " + conversion + "; }\n"); |
|
#else |
|
frag.addSource("in mediump " + type + " valueInterpolated;\n" |
|
"out mediump vec4 result;\n" |
|
"void main() { result = " + conversion + "; }\n"); |
|
#endif |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); |
|
|
|
attachShaders({vert, frag}); |
|
|
|
bindAttributeLocation(0, "value"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
IntegerShader::IntegerShader(const std::string& type) { |
|
#ifndef MAGNUM_TARGET_GLES |
|
Shader vert(Version::GL300, Shader::Type::Vertex); |
|
Shader frag(Version::GL300, Shader::Type::Fragment); |
|
#else |
|
Shader vert(Version::GLES300, Shader::Type::Vertex); |
|
Shader frag(Version::GLES300, Shader::Type::Fragment); |
|
#endif |
|
|
|
vert.addSource("in mediump " + type + " value;\n" |
|
"flat out mediump " + type + " valueInterpolated;\n" |
|
"void main() {\n" |
|
" valueInterpolated = value;\n" |
|
" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
|
"}\n"); |
|
frag.addSource("flat in mediump " + type + " valueInterpolated;\n" |
|
"out mediump " + type + " result;\n" |
|
"void main() { result = valueInterpolated; }\n"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); |
|
|
|
attachShaders({vert, frag}); |
|
|
|
bindAttributeLocation(0, "value"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
DoubleShader::DoubleShader(const std::string& type, const std::string& outputType, const std::string& conversion) { |
|
Shader vert(Version::GL410, Shader::Type::Vertex); |
|
Shader frag(Version::GL410, Shader::Type::Fragment); |
|
|
|
vert.addSource("in " + type + " value;\n" |
|
"out " + outputType + " valueInterpolated;\n" |
|
"void main() {\n" |
|
" valueInterpolated = " + conversion + ";\n" |
|
" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
|
"}\n"); |
|
frag.addSource("in " + outputType + " valueInterpolated;\n" |
|
"out " + outputType + " result;\n" |
|
"void main() { result = valueInterpolated; }\n"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); |
|
|
|
attachShaders({vert, frag}); |
|
|
|
bindAttributeLocation(0, "value"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); |
|
} |
|
#endif |
|
|
|
Checker::Checker(AbstractShaderProgram&& shader, RenderbufferFormat format, Mesh& mesh): framebuffer({{}, Vector2i(1)}) { |
|
renderbuffer.setStorage(format, Vector2i(1)); |
|
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); |
|
|
|
framebuffer.bind(); |
|
mesh.setPrimitive(MeshPrimitive::Points) |
|
.setCount(2); |
|
|
|
/* Skip first vertex so we test also offsets */ |
|
MeshView(mesh) |
|
.setCount(1) |
|
.setBaseVertex(mesh.baseVertex()) |
|
.setInstanceCount(mesh.instanceCount()) |
|
#ifndef MAGNUM_TARGET_GLES |
|
.setBaseInstance(mesh.baseInstance()) |
|
#endif |
|
.setIndexRange(1) |
|
.draw(shader); |
|
} |
|
|
|
template<class T> T Checker::get(PixelFormat format, PixelType type) { |
|
return framebuffer.read({{}, Vector2i{1}}, {format, type}).data<T>()[0]; |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void MeshGLTest::addVertexBufferUnsignedInt() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, UnsignedInt> Attribute; |
|
|
|
constexpr UnsignedInt data[] = { 0, 157, 35681 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R32UI, mesh) |
|
.get<UnsignedInt>(PixelFormat::RedInteger, PixelType::UnsignedInt); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 35681); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferInt() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Int> Attribute; |
|
|
|
constexpr Int data[] = { 0, 457931, 27530 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("int"), RenderbufferFormat::R32I, mesh) |
|
.get<Int>(PixelFormat::RedInteger, PixelType::Int); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 27530); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferFloat() { |
|
typedef Attribute<0, Float> Attribute; |
|
|
|
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 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>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 96); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferDouble() { |
|
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 Attribute<0, Double> Attribute; |
|
|
|
const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedShort>(45828) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 8, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(DoubleShader("double", "float", "float(value)"), |
|
RenderbufferFormat::R16, mesh).get<UnsignedShort>(PixelFormat::Red, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 45828); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void MeshGLTest::addVertexBufferVectorNui() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector3ui> Attribute; |
|
|
|
constexpr Vector3ui data[] = { {}, {37448, 547686, 156}, {27592, 157, 25} }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("uvec3"), RenderbufferFormat::RGBA32UI, mesh) |
|
.get<Vector3ui>(PixelFormat::RGBAInteger, PixelType::UnsignedInt); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Vector3ui(27592, 157, 25)); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferVectorNi() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector2i> Attribute; |
|
|
|
constexpr Vector2i data[] = { {}, {-37448, 547686}, {27592, -157} }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2*4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("ivec2"), RenderbufferFormat::RG32I, mesh) |
|
.get<Vector2i>(PixelFormat::RGInteger, PixelType::Int); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Vector2i(27592, -157)); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferVectorN() { |
|
typedef Attribute<0, Vector3> Attribute; |
|
|
|
const Vector3 data[] = { {}, {0.0f, -0.9f, 1.0f}, Math::normalize<Vector3>(Color3ub(96, 24, 156)) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("vec3", "vec4(valueInterpolated, 0.0)"), |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color3ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color3ub(96, 24, 156)); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferVectorNd() { |
|
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 Attribute<0, Vector4d> Attribute; |
|
|
|
const Vector4d data[] = { |
|
{}, {0.0, -0.9, 1.0, 1.25}, |
|
Math::normalize<Vector4d>(Math::Vector4<UnsignedShort>(315, 65201, 2576, 12)) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4*8, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(DoubleShader("dvec4", "vec4", "vec4(value)"), |
|
RenderbufferFormat::RGBA16, mesh).get<Math::Vector4<UnsignedShort>>(PixelFormat::RGBA, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Math::Vector4<UnsignedShort>(315, 65201, 2576, 12)); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferMatrixNxN() { |
|
typedef Attribute<0, Matrix3x3> Attribute; |
|
|
|
const Matrix3x3 data[] = { |
|
{}, |
|
Matrix3x3::fromDiagonal({0.0f, -0.9f, 1.0f}), |
|
Matrix3x3::fromDiagonal(Math::normalize<Vector3>(Color3ub(96, 24, 156))) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*3*4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("mat3", |
|
"vec4(valueInterpolated[0][0], valueInterpolated[1][1], valueInterpolated[2][2], 0.0)"), |
|
RenderbufferFormat::RGBA8, mesh).get<Color3ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color3ub(96, 24, 156)); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferMatrixNxNd() { |
|
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 Attribute<0, Matrix3x3d> Attribute; |
|
|
|
const Matrix3x3d data[] = { |
|
{}, |
|
Matrix3x3d::fromDiagonal({0.0, -0.9, 1.0}), |
|
Matrix3x3d::fromDiagonal(Math::normalize<Vector3d>(Math::Vector3<UnsignedShort>(315, 65201, 2576))) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*3*8, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(DoubleShader("dmat3", "vec4", |
|
"vec4(value[0][0], value[1][1], value[2][2], 0.0)"), |
|
RenderbufferFormat::RGBA16, mesh).get<Math::Vector3<UnsignedShort>>(PixelFormat::RGB, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
{ |
|
CORRADE_EXPECT_FAIL("Somehow only first two values are extracted"); |
|
CORRADE_COMPARE(value, Math::Vector3<UnsignedShort>(315, 65201, 2576)); |
|
} |
|
/* This is wrong, but check if it's still the right wrong */ |
|
CORRADE_COMPARE(value, Math::Vector3<UnsignedShort>(315, 65201, 0)); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void MeshGLTest::addVertexBufferMatrixMxN() { |
|
typedef Attribute<0, Matrix3x4> Attribute; |
|
|
|
const Matrix3x4 data[] = { |
|
{}, |
|
Matrix3x4::fromDiagonal({0.0f, -0.9f, 1.0f}), |
|
Matrix3x4::fromDiagonal(Math::normalize<Vector3>(Color3ub(96, 24, 156))) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*4*4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("mat3x4", |
|
"vec4(valueInterpolated[0][0], valueInterpolated[1][1], valueInterpolated[2][2], 0.0)"), |
|
RenderbufferFormat::RGBA8, mesh).get<Color3ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color3ub(96, 24, 156)); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferMatrixMxNd() { |
|
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 Attribute<0, Matrix3x4d> Attribute; |
|
|
|
const Matrix3x4d data[] = { |
|
{}, |
|
Matrix3x4d::fromDiagonal({0.0f, -0.9f, 1.0f}), |
|
Matrix3x4d::fromDiagonal(Math::normalize<Vector3d>(Math::Vector3<UnsignedShort>(315, 65201, 2576))) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*4*8, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(DoubleShader("dmat3x4", "vec4", |
|
"vec4(value[0][0], value[1][1], value[2][2], 0.0)"), |
|
RenderbufferFormat::RGBA16, mesh).get<Math::Vector3<UnsignedShort>>(PixelFormat::RGB, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
{ |
|
CORRADE_EXPECT_FAIL("Somehow only first two values are extracted"); |
|
CORRADE_COMPARE(value, Math::Vector3<UnsignedShort>(315, 65201, 2576)); |
|
} |
|
/* This is wrong, but check if it's still the right wrong */ |
|
CORRADE_COMPARE(value, Math::Vector3<UnsignedShort>(315, 65201, 0)); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void MeshGLTest::addVertexBufferUnsignedIntWithUnsignedShort() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, UnsignedInt> Attribute; |
|
|
|
constexpr UnsignedShort data[] = { 0, 49563, 16583 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::UnsignedShort)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R16UI, mesh) |
|
.get<UnsignedShort>(PixelFormat::RedInteger, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 16583); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferUnsignedIntWithShort() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, UnsignedInt> Attribute; |
|
|
|
constexpr Short data[] = { 0, 24563, 16583 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::Short)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("uint"), RenderbufferFormat::R16I, mesh) |
|
.get<Short>(PixelFormat::RedInteger, PixelType::Short); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 16583); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferIntWithUnsignedShort() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Int> Attribute; |
|
|
|
constexpr UnsignedShort data[] = { 0, 49563, 16583 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::UnsignedShort)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("int"), RenderbufferFormat::R16UI, mesh) |
|
.get<UnsignedShort>(PixelFormat::RedInteger, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 16583); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferIntWithShort() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::gpu_shader4>()) |
|
CORRADE_SKIP(Extensions::GL::EXT::gpu_shader4::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Int> Attribute; |
|
|
|
constexpr Short data[] = { 0, 24563, -16583 }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::Short)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(IntegerShader("int"), RenderbufferFormat::R16I, mesh) |
|
.get<Short>(PixelFormat::RedInteger, PixelType::Short); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, -16583); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferFloatWithHalfFloat() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::half_float_vertex>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::half_float_vertex::string() + std::string(" is not supported.")); |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::vertex_half_float>()) |
|
CORRADE_SKIP(Extensions::GL::OES::vertex_half_float::string() + std::string(" is not supported.")); |
|
#endif |
|
|
|
typedef Attribute<0, Float> Attribute; |
|
|
|
Buffer buffer; |
|
buffer.setData({nullptr, 6}, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 2, Attribute(Attribute::DataType::HalfFloat)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
/* Won't test the actual values */ |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferFloatWithDouble() { |
|
typedef Attribute<0, Float> Attribute; |
|
|
|
const Double data[] = { 0.0, -0.7, Math::normalize<Double, UnsignedByte>(186) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 8, Attribute(Attribute::DataType::Double)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), |
|
RenderbufferFormat::RGBA8, mesh).get<UnsignedByte>(PixelFormat::RGBA, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 186); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferVector3WithUnsignedInt10f11f11fRev() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_type_10f_11f_11f_rev>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_10f_11f_11f_rev::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector3> Attribute; |
|
|
|
Buffer buffer; |
|
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt10f11f11fRev)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
/* Won't test the actual values */ |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES2 |
|
void MeshGLTest::addVertexBufferVector4WithUnsignedInt2101010Rev() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_type_2_10_10_10_rev>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector4> Attribute; |
|
|
|
Buffer buffer; |
|
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::UnsignedInt2101010Rev)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
/* Won't test the actual values */ |
|
} |
|
|
|
void MeshGLTest::addVertexBufferVector4WithInt2101010Rev() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_type_2_10_10_10_rev>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::vertex_type_2_10_10_10_rev::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector4> Attribute; |
|
|
|
Buffer buffer; |
|
buffer.setData({nullptr, 12}, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute(Attribute::DataType::Int2101010Rev)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
/* Won't test the actual values */ |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferLessVectorComponents() { |
|
typedef Attribute<0, Vector4> Attribute; |
|
|
|
const Vector3 data[] = { |
|
{}, {0.0f, -0.9f, 1.0f}, |
|
Math::normalize<Vector3>(Color3ub(96, 24, 156)) |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3*4, Attribute(Attribute::Components::Three)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("vec4", "valueInterpolated"), |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color4ub(96, 24, 156, 255)); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferNormalized() { |
|
typedef Attribute<0, Vector3> Attribute; |
|
|
|
constexpr Color3ub data[] = { {}, {0, 128, 64}, {32, 156, 228} }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 3, Attribute(Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("vec3", "vec4(valueInterpolated, 0.0)"), |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color3ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color3ub(32, 156, 228)); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::addVertexBufferBGRA() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::vertex_array_bgra>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::vertex_array_bgra::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
typedef Attribute<0, Vector4> Attribute; |
|
|
|
constexpr Color4ub data[] = { {}, {0, 128, 64, 161}, {96, 24, 156, 225} }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4, Attribute(Attribute::Components::BGRA, Attribute::DataType::UnsignedByte, Attribute::DataOption::Normalized)); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("vec4", "valueInterpolated"), |
|
RenderbufferFormat::RGBA8, mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color4ub(156, 24, 96, 225)); |
|
} |
|
#endif |
|
|
|
namespace { |
|
struct MultipleShader: AbstractShaderProgram { |
|
typedef Attribute<0, Vector3> Position; |
|
typedef Attribute<1, Vector3> Normal; |
|
typedef Attribute<2, Vector2> TextureCoordinates; |
|
|
|
explicit MultipleShader(); |
|
}; |
|
} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
MultipleShader::MultipleShader() { |
|
#ifndef MAGNUM_TARGET_GLES |
|
Shader vert(Version::GL210, Shader::Type::Vertex); |
|
Shader frag(Version::GL210, Shader::Type::Fragment); |
|
#else |
|
Shader vert(Version::GLES200, Shader::Type::Vertex); |
|
Shader frag(Version::GLES200, Shader::Type::Fragment); |
|
#endif |
|
|
|
vert.addSource("#if !defined(GL_ES) && __VERSION__ == 120\n" |
|
"#define mediump\n" |
|
"#endif\n" |
|
"attribute mediump vec4 position;\n" |
|
"attribute mediump vec3 normal;\n" |
|
"attribute mediump vec2 textureCoordinates;\n" |
|
"varying mediump vec4 valueInterpolated;\n" |
|
"void main() {\n" |
|
" valueInterpolated = position + vec4(normal, 0.0) + vec4(textureCoordinates, 0.0, 0.0);\n" |
|
" gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
|
"}\n"); |
|
frag.addSource("varying mediump vec4 valueInterpolated;\n" |
|
"void main() { gl_FragColor = valueInterpolated; }\n"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(Shader::compile({vert, frag})); |
|
|
|
attachShaders({vert, frag}); |
|
|
|
bindAttributeLocation(Position::Location, "position"); |
|
bindAttributeLocation(Normal::Location, "normal"); |
|
bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); |
|
|
|
CORRADE_INTERNAL_ASSERT_OUTPUT(link()); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::addVertexBufferMultiple() { |
|
const Float data[] = { |
|
0.0f, /* Offset */ |
|
|
|
/* First attribute */ |
|
0.3f, 0.1f, 0.5f, |
|
0.4f, 0.0f, -0.9f, |
|
1.0f, -0.5f, |
|
|
|
/* Second attribute */ |
|
Math::normalize<Float, UnsignedByte>(64), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(56), |
|
Math::normalize<Float, UnsignedByte>(15), |
|
Math::normalize<Float, UnsignedByte>(164), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(97), |
|
Math::normalize<Float, UnsignedByte>(28) |
|
}; |
|
|
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader(), |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color4ub(64 + 15 + 97, 17 + 164 + 28, 56 + 17, 255)); |
|
} |
|
|
|
void MeshGLTest::addVertexBufferMultipleGaps() { |
|
const Float data[] = { |
|
0.0f, 0.0f, 0.0f, 0.0f, /* Offset */ |
|
|
|
/* First attribute */ |
|
0.3f, 0.1f, 0.5f, 0.0f, |
|
0.4f, 0.0f, -0.9f, 0.0f, |
|
1.0f, -0.5f, 0.0f, 0.0f, |
|
|
|
/* Second attribute */ |
|
Math::normalize<Float, UnsignedByte>(64), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(56), 0.0f, |
|
Math::normalize<Float, UnsignedByte>(15), |
|
Math::normalize<Float, UnsignedByte>(164), |
|
Math::normalize<Float, UnsignedByte>(17), 0.0f, |
|
Math::normalize<Float, UnsignedByte>(97), |
|
Math::normalize<Float, UnsignedByte>(28), 0.0f, 0.0f |
|
}; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.addVertexBuffer(buffer, 4*4, |
|
MultipleShader::Position(), 1*4, |
|
MultipleShader::Normal(), 1*4, |
|
MultipleShader::TextureCoordinates(), 2*4); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader(), |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, Color4ub(64 + 15 + 97, 17 + 164 + 28, 56 + 17, 255)); |
|
} |
|
|
|
namespace { |
|
const Float indexedVertexData[] = { |
|
0.0f, /* Offset */ |
|
|
|
/* First vertex */ |
|
Math::normalize<Float, UnsignedByte>(64), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(56), |
|
Math::normalize<Float, UnsignedByte>(15), |
|
Math::normalize<Float, UnsignedByte>(164), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(97), |
|
Math::normalize<Float, UnsignedByte>(28), |
|
|
|
/* Second vertex */ |
|
0.3f, 0.1f, 0.5f, |
|
0.4f, 0.0f, -0.9f, |
|
1.0f, -0.5f |
|
}; |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
const Float indexedVertexDataBaseVertex[] = { |
|
0.0f, 0.0f, /* Offset */ |
|
|
|
/* First vertex */ |
|
0.0f, 0.0f, 0.0f, |
|
0.0f, 0.0f, 0.0f, |
|
0.0f, 0.0f, |
|
|
|
/* Second vertex */ |
|
0.0f, 0.0f, 0.0f, |
|
0.0f, 0.0f, 0.0f, |
|
0.0f, 0.0f, |
|
|
|
/* Third vertex */ |
|
Math::normalize<Float, UnsignedByte>(64), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(56), |
|
Math::normalize<Float, UnsignedByte>(15), |
|
Math::normalize<Float, UnsignedByte>(164), |
|
Math::normalize<Float, UnsignedByte>(17), |
|
Math::normalize<Float, UnsignedByte>(97), |
|
Math::normalize<Float, UnsignedByte>(28), |
|
|
|
/* Fourth vertex */ |
|
0.3f, 0.1f, 0.5f, |
|
0.4f, 0.0f, -0.9f, |
|
1.0f, -0.5f |
|
}; |
|
#endif |
|
|
|
constexpr Color4ub indexedResult(64 + 15 + 97, 17 + 164 + 28, 56 + 17, 255); |
|
} |
|
|
|
void MeshGLTest::setIndexBuffer() { |
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
void MeshGLTest::setIndexBufferRange() { |
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort, 0, 1); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
void MeshGLTest::setIndexBufferUnsignedInt() { |
|
#ifdef MAGNUM_TARGET_GLES2 |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::OES::element_index_uint>()) |
|
CORRADE_SKIP(Extensions::GL::OES::element_index_uint::string() + std::string(" is not available.")); |
|
#endif |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedInt indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 4, Mesh::IndexType::UnsignedInt); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::setBaseVertex() { |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_elements_base_vertex>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(2) |
|
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, RenderbufferFormat::RGBA8, |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
#endif |
|
|
|
void MeshGLTest::setInstanceCount() { |
|
/* Verbatim copy of addVertexBufferFloat() with added extension check and |
|
setInstanceCount() call. It would just render three times the same |
|
value. I'm too lazy to invent proper test case, so I'll just check that |
|
it didn't generate any error and rendered something */ |
|
|
|
#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.")); |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
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 extension is not available."); |
|
#endif |
|
|
|
typedef Attribute<0, Float> Attribute; |
|
|
|
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.setInstanceCount(3) |
|
.addVertexBuffer(buffer, 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>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 96); |
|
} |
|
|
|
void MeshGLTest::setInstanceCountIndexed() { |
|
/* Verbatim copy of setIndexBuffer() with added extension check and |
|
setInstanceCount() call. It would just render three times the same |
|
value. I'm too lazy to invent proper test case, so I'll just check that |
|
it didn't generate any error and rendered something */ |
|
|
|
#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.")); |
|
#elif defined(MAGNUM_TARGET_GLES2) |
|
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 extension is not available."); |
|
#endif |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setInstanceCount(3) |
|
.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::setInstanceCountBaseInstance() { |
|
/* Verbatim copy of setInstanceCount() with additional extension check and |
|
setBaseInstance() call. It would just render three times the same |
|
value. I'm too lazy to invent proper test case, so I'll just check that |
|
it didn't generate any error and rendered something */ |
|
|
|
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::base_instance>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); |
|
|
|
typedef Attribute<0, Float> Attribute; |
|
|
|
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(1) |
|
.setInstanceCount(3) |
|
.setBaseInstance(72) |
|
.addVertexBuffer(buffer, 4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), |
|
RenderbufferFormat::RGBA8, |
|
mesh).get<UnsignedByte>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 96); |
|
} |
|
|
|
void MeshGLTest::setInstanceCountBaseInstanceIndexed() { |
|
/* Verbatim copy of setInstanceCountIndexed() with additional extension |
|
check and setBaseInstance() call. It would just render three times the |
|
same value. I'm too lazy to invent proper test case, so I'll just check |
|
that it didn't generate any error and rendered something */ |
|
|
|
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::base_instance>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setInstanceCount(3) |
|
.setBaseInstance(72) |
|
.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, RenderbufferFormat::RGBA8, |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
void MeshGLTest::setInstanceCountBaseVertex() { |
|
/* Verbatim copy of setBaseVertex() with additional extension check and |
|
setInstanceCount() call. It would just render three times the same |
|
value. I'm too lazy to invent proper test case, so I'll just check |
|
that it didn't generate any error and rendered something */ |
|
|
|
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::draw_elements_base_vertex>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(2) |
|
.setInstanceCount(3) |
|
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, RenderbufferFormat::RGBA8, |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
void MeshGLTest::setInstanceCountBaseVertexBaseInstance() { |
|
/* Verbatim copy of setInstanceCountBaseVertex() with added extension check |
|
and setBaseInstance() call. It would just render three times the same |
|
value. I'm too lazy to invent proper test case, so I'll just check |
|
that it didn't generate any error and rendered something */ |
|
|
|
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::draw_elements_base_vertex>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::base_instance>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::base_instance::string() + std::string(" is not available.")); |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(2) |
|
.setInstanceCount(3) |
|
.setBaseInstance(72) |
|
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = Checker(MultipleShader{}, RenderbufferFormat::RGBA8, |
|
mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
#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 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>(PixelFormat::RGBA, PixelType::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 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>(PixelFormat::RedInteger, PixelType::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 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", "float(value)"), |
|
RenderbufferFormat::R16, mesh).get<UnsignedShort>(PixelFormat::Red, PixelType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 45828); |
|
} |
|
#endif |
|
|
|
namespace { |
|
struct MultiChecker { |
|
MultiChecker(AbstractShaderProgram&& shader, Mesh& mesh); |
|
|
|
template<class T> T get(PixelFormat format, PixelType type); |
|
|
|
Renderbuffer renderbuffer; |
|
Framebuffer framebuffer; |
|
}; |
|
} |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
MultiChecker::MultiChecker(AbstractShaderProgram&& shader, Mesh& mesh): framebuffer({{}, Vector2i(1)}) { |
|
renderbuffer.setStorage( |
|
#ifndef MAGNUM_TARGET_GLES2 |
|
RenderbufferFormat::RGBA8, |
|
#else |
|
RenderbufferFormat::RGBA4, |
|
#endif |
|
Vector2i(1)); |
|
framebuffer.attachRenderbuffer(Framebuffer::ColorAttachment(0), renderbuffer); |
|
|
|
framebuffer.bind(); |
|
mesh.setPrimitive(MeshPrimitive::Points) |
|
.setCount(2); |
|
|
|
/* Skip first vertex so we test also offsets */ |
|
MeshView a(mesh); |
|
a.setCount(1) |
|
.setBaseVertex(mesh.baseVertex()); |
|
|
|
MeshView b(mesh); |
|
b.setCount(1); |
|
if(mesh.isIndexed()) { |
|
b.setBaseVertex(mesh.baseVertex()) |
|
.setIndexRange(1); |
|
} else b.setBaseVertex(1); |
|
|
|
MeshView::draw(shader, {a, b}); |
|
} |
|
|
|
template<class T> T MultiChecker::get(PixelFormat format, PixelType type) { |
|
return framebuffer.read({{}, Vector2i{1}}, {format, type}).data<T>()[0]; |
|
} |
|
#endif |
|
|
|
void MeshGLTest::multiDraw() { |
|
#ifdef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) |
|
Debug() << Extensions::GL::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation"; |
|
#endif |
|
|
|
typedef Attribute<0, Float> Attribute; |
|
|
|
const Float data[] = { 0.0f, -0.7f, Math::normalize<Float, UnsignedByte>(96) }; |
|
Buffer buffer; |
|
buffer.setData(data, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.addVertexBuffer(buffer, 4, Attribute()); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = MultiChecker(FloatShader("float", "vec4(valueInterpolated, 0.0, 0.0, 0.0)"), |
|
mesh).get<UnsignedByte>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, 96); |
|
} |
|
|
|
void MeshGLTest::multiDrawIndexed() { |
|
#ifdef MAGNUM_TARGET_GLES |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) |
|
Debug() << Extensions::GL::EXT::multi_draw_arrays::string() << "not supported, using fallback implementation"; |
|
#endif |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexData, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.addVertexBuffer(vertices, 1*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = MultiChecker(MultipleShader{}, mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
void MeshGLTest::multiDrawBaseVertex() { |
|
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::draw_elements_base_vertex>()) |
|
CORRADE_SKIP(Extensions::GL::ARB::draw_elements_base_vertex::string() + std::string(" is not available.")); |
|
|
|
Buffer vertices; |
|
vertices.setData(indexedVertexDataBaseVertex, BufferUsage::StaticDraw); |
|
|
|
constexpr UnsignedShort indexData[] = { 2, 1, 0 }; |
|
Buffer indices{Buffer::TargetHint::ElementArray}; |
|
indices.setData(indexData, BufferUsage::StaticDraw); |
|
|
|
Mesh mesh; |
|
mesh.setBaseVertex(2) |
|
.addVertexBuffer(vertices, 2*4, MultipleShader::Position(), |
|
MultipleShader::Normal(), MultipleShader::TextureCoordinates()) |
|
.setIndexBuffer(indices, 2, Mesh::IndexType::UnsignedShort); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
|
|
const auto value = MultiChecker(MultipleShader{}, mesh).get<Color4ub>(PixelFormat::RGBA, PixelType::UnsignedByte); |
|
|
|
MAGNUM_VERIFY_NO_ERROR(); |
|
CORRADE_COMPARE(value, indexedResult); |
|
} |
|
#endif |
|
|
|
}} |
|
|
|
MAGNUM_GL_TEST_MAIN(Magnum::Test::MeshGLTest)
|
|
|