diff --git a/doc/python/conf.py b/doc/python/conf.py index 7112b0a..1c37f9b 100644 --- a/doc/python/conf.py +++ b/doc/python/conf.py @@ -71,6 +71,18 @@ magnum.__annotations__ = { magnum.gl.__annotations__ = { 'default_framebuffer': magnum.gl.DefaultFramebuffer } +magnum.shaders.Flat2D.__annotations__ = { + 'POSITION': magnum.gl.Attribute, + 'TEXTURE_COORDINATES': magnum.gl.Attribute, + 'COLOR3': magnum.gl.Attribute, + 'COLOR4': magnum.gl.Attribute +} +magnum.shaders.Flat3D.__annotations__ = { + 'POSITION': magnum.gl.Attribute, + 'TEXTURE_COORDINATES': magnum.gl.Attribute, + 'COLOR3': magnum.gl.Attribute, + 'COLOR4': magnum.gl.Attribute +} magnum.shaders.VertexColor2D.__annotations__ = { 'POSITION': magnum.gl.Attribute, 'COLOR3': magnum.gl.Attribute, diff --git a/doc/python/magnum.shaders.rst b/doc/python/magnum.shaders.rst index c0fbafc..4e9826e 100644 --- a/doc/python/magnum.shaders.rst +++ b/doc/python/magnum.shaders.rst @@ -23,6 +23,28 @@ DEALINGS IN THE SOFTWARE. .. +.. py:class:: magnum.shaders.Flat2D + :data POSITION: Vertex position + :data TEXTURE_COORDINATES: 2D texture coordinates + :data COLOR3: Three-component vertex color + :data COLOR4: Four-component vertex color + +.. py:class:: magnum.shaders.Flat3D + :data POSITION: Vertex position + :data TEXTURE_COORDINATES: 2D texture coordinates + :data COLOR3: Three-component vertex color + :data COLOR4: Four-component vertex color + +.. py:property:: magnum.shaders.Flat2D.alpha_mask + :raise AttributeError: If the shader was not created with `Flags.ALPHA_MASK` +.. py:property:: magnum.shaders.Flat3D.alpha_mask + :raise AttributeError: If the shader was not created with `Flags.ALPHA_MASK` + +.. py:function:: magnum.shaders.Flat2D.bind_texture + :raise AttributeError: If the shader was not created with `Flags.TEXTURED` +.. py:function:: magnum.shaders.Flat3D.bind_texture + :raise AttributeError: If the shader was not created with `Flags.TEXTURED` + .. py:class:: magnum.shaders.VertexColor2D :data POSITION: Vertex position :data COLOR3: Three-component vertex color diff --git a/src/python/magnum/shaders.cpp b/src/python/magnum/shaders.cpp index 8a5a616..657ac78 100644 --- a/src/python/magnum/shaders.cpp +++ b/src/python/magnum/shaders.cpp @@ -27,6 +27,7 @@ #include /* for vector arguments */ #include #include +#include #include #include @@ -39,6 +40,42 @@ namespace magnum { namespace { +template void flat(PyNonDestructibleClass, GL::AbstractShaderProgram>& c) { + /* Attributes */ + c.attr("TEXTURE_COORDINATES") = GL::DynamicAttribute{typename Shaders::Flat::TextureCoordinates{}}; + c.attr("COLOR3") = GL::DynamicAttribute{typename Shaders::Flat::Color3{}}; + c.attr("COLOR4") = GL::DynamicAttribute{typename Shaders::Flat::Color4{}}; + + /* Methods */ + c + .def(py::init::Flag>(), "Constructor", + py::arg("flags") = typename Shaders::Flat::Flag{}) + + /* Using lambdas to avoid method chaining getting into signatures */ + .def_property_readonly("flags", [](Shaders::Flat& self) { + return typename Shaders::Flat::Flag(UnsignedByte(self.flags())); + }, "Flags") + .def_property("transformation_projection_matrix", nullptr, &Shaders::Flat::setTransformationProjectionMatrix, + "Transformation and projection matrix") + .def_property("color", nullptr, &Shaders::Flat::setColor, "Color") + .def_property("alpha_mask", nullptr, [](Shaders::Flat& self, Float mask) { + if(!(self.flags() & Shaders::Flat::Flag::AlphaMask)) { + PyErr_SetString(PyExc_AttributeError, "the shader was not created with alpha mask enabled"); + throw py::error_already_set{}; + } + + self.setAlphaMask(mask); + }, "Alpha mask") + .def("bind_texture", [](Shaders::Flat& self, GL::Texture2D& texture) { + if(!(self.flags() & Shaders::Flat::Flag::Textured)) { + PyErr_SetString(PyExc_AttributeError, "the shader was not created with texturing enabled"); + throw py::error_already_set{}; + } + + self.bindTexture(texture); + }, "Bind a color texture"); +} + template void vertexColor(PyNonDestructibleClass, GL::AbstractShaderProgram>& c) { /* Attributes */ c.attr("COLOR3") = GL::DynamicAttribute{typename Shaders::VertexColor::Color3{}}; @@ -65,6 +102,35 @@ void shaders(py::module& m) { py::module::import("magnum.gl"); #endif + /* 2D/3D flat shader */ + { + PyNonDestructibleClass flat2D{m, + "Flat2D", "2D flat shader"}; + PyNonDestructibleClass flat3D{m, + "Flat3D", "3D flat shader"}; + flat2D.attr("POSITION") = GL::DynamicAttribute{Shaders::Flat2D::Position{}}; + flat3D.attr("POSITION") = GL::DynamicAttribute{Shaders::Flat3D::Position{}}; + + /* The flags are currently the same type for both 2D and 3D and pybind + doesn't want to have a single type registered twice, so doing it + this way instead */ + py::enum_ flags{flat2D, "Flags", "Flags"}; + flags + .value("TEXTURED", Shaders::Flat2D::Flag::Textured) + .value("ALPHA_MASK", Shaders::Flat2D::Flag::AlphaMask) + .value("VERTEX_COLOR", Shaders::Flat3D::Flag::AlphaMask) + .value("NONE", Shaders::Flat3D::Flag{}) + /* TODO: OBJECT_ID, once multiple FB outputs and mapDraw is exposed */ + ; + flat3D.attr("Flags") = flags; + + flat(flat2D); + flat(flat3D); + + corrade::enumOperators(flags); + + } + /* 2D/3D vertex color shader */ { PyNonDestructibleClass vertexColor2D{m, diff --git a/src/python/magnum/test/test_shaders_gl.py b/src/python/magnum/test/test_shaders_gl.py index c3e94ab..24bbb7c 100644 --- a/src/python/magnum/test/test_shaders_gl.py +++ b/src/python/magnum/test/test_shaders_gl.py @@ -32,6 +32,33 @@ from . import GLTestCase, setUpModule from magnum import * from magnum import gl, shaders +class Flat(GLTestCase): + def test_init(self): + a = shaders.Flat3D() + self.assertEqual(a.flags, shaders.Flat3D.Flags.NONE) + + b = shaders.Flat3D(shaders.Flat3D.Flags.TEXTURED|shaders.Flat3D.Flags.ALPHA_MASK) + self.assertEqual(b.flags, shaders.Flat3D.Flags.TEXTURED|shaders.Flat3D.Flags.ALPHA_MASK) + + def test_uniforms_bindings(self): + a = shaders.Flat3D(shaders.Flat3D.Flags.TEXTURED|shaders.Flat3D.Flags.ALPHA_MASK) + a.color = (0.5, 1.0, 0.9) + a.transformation_projection_matrix = Matrix4.translation(Vector3.x_axis()) + a.alpha_mask = 0.3 + + texture = gl.Texture2D() + texture.set_storage(1, gl.TextureFormat.RGBA8, Vector2i(8)) + a.bind_texture(texture) + + def test_uniforms_bindings_errors(self): + a = shaders.Flat2D() + with self.assertRaisesRegex(AttributeError, "the shader was not created with alpha mask enabled"): + a.alpha_mask = 0.3 + + texture = gl.Texture2D() + with self.assertRaisesRegex(AttributeError, "the shader was not created with texturing enabled"): + a.bind_texture(texture) + class VertexColor(GLTestCase): def test_init(self): a = shaders.VertexColor2D()