Browse Source

python: bind also the vector shaders.

Last missing piece for the Python text example.
pull/16/head
Vladimír Vondruš 4 years ago
parent
commit
f4b5d915d9
  1. 24
      doc/python/conf.py
  2. 30
      doc/python/magnum.shaders.rst
  3. 3
      doc/python/pages/changelog.rst
  4. 114
      src/python/magnum/shaders.cpp
  5. 52
      src/python/magnum/test/test_shaders_gl.py

24
doc/python/conf.py

@ -72,6 +72,14 @@ magnum.__annotations__ = {
magnum.gl.__annotations__ = {
'default_framebuffer': magnum.gl.DefaultFramebuffer
}
magnum.shaders.DistanceFieldVectorGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.DistanceFieldVectorGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.FlatGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute,
@ -110,15 +118,27 @@ magnum.shaders.PhongGL.__annotations__ = {
'TRANSFORMATION_MATRIX': magnum.gl.Attribute,
'TEXTURE_OFFSET': magnum.gl.Attribute,
}
magnum.shaders.VectorGL2D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
magnum.shaders.VectorGL3D.__annotations__ = {
'POSITION': magnum.gl.Attribute,
'TEXTURE_COORDINATES': magnum.gl.Attribute
}
# An extremely hacky way to remove noise for shader docs. It doesn't hide
# those, but at least puts them way down in the page, removing all docs.
# TODO needs a better solution directly in m.css
for shader in [magnum.shaders.FlatGL2D,
for shader in [magnum.shaders.DistanceFieldVectorGL2D,
magnum.shaders.DistanceFieldVectorGL3D,
magnum.shaders.FlatGL2D,
magnum.shaders.FlatGL3D,
magnum.shaders.VertexColorGL2D,
magnum.shaders.VertexColorGL3D,
magnum.shaders.PhongGL]:
magnum.shaders.PhongGL,
magnum.shaders.VectorGL2D,
magnum.shaders.VectorGL3D]:
shader.attach_shader = DoNotPrintValue()
shader.bind_attribute_location = DoNotPrintValue()
shader.bind_fragment_data_location = DoNotPrintValue()

30
doc/python/magnum.shaders.rst

@ -23,6 +23,21 @@
DEALINGS IN THE SOFTWARE.
..
.. py:class:: magnum.shaders.DistanceFieldVectorGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:class:: magnum.shaders.DistanceFieldVectorGL3D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:property:: magnum.shaders.DistanceFieldVectorGL2D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.DistanceFieldVectorGL3D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:class:: magnum.shaders.FlatGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
@ -115,3 +130,18 @@
:raise AttributeError: If the shader was not created with any of
:ref:`Flags.AMBIENT_TEXTURE`, :ref:`Flags.DIFFUSE_TEXTURE`,
:ref:`Flags.SPECULAR_TEXTURE` or :ref:`Flags.NORMAL_TEXTURE`
.. py:class:: magnum.shaders.VectorGL2D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:class:: magnum.shaders.VectorGL3D
:data POSITION: Vertex position
:data TEXTURE_COORDINATES: 2D texture coordinates
.. py:property:: magnum.shaders.VectorGL2D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`
.. py:property:: magnum.shaders.VectorGL3D.texture_matrix
:raise AttributeError: If the shader was not created with
:ref:`Flags.TEXTURE_TRANSFORMATION`

3
doc/python/pages/changelog.rst

@ -60,6 +60,9 @@ Changelog
lighting features in :ref:`shaders.PhongGL`
- Exposed new instancing and texture transformation features in
:ref:`shaders.FlatGL2D` and :ref:`shaders.FlatGL3D`
- Exposed :ref:`shaders.DistanceFieldVectorGL2D`,
:ref:`shaders.DistanceFieldVectorGL3D`, :ref:`shaders.VectorGL2D` and
:ref:`shaders.VectorGL3D` shaders
- Renamed all helper ``Python.h`` headers to ``PythonBindings.h`` to avoid
issues with shitty IDE indexers such as Eclipse, confusing these with
Python's ``<Python.h>``

114
src/python/magnum/shaders.cpp

@ -31,9 +31,11 @@
#include <Magnum/Math/Color.h>
#include <Magnum/Math/Matrix3.h>
#include <Magnum/Math/Matrix4.h>
#include <Magnum/Shaders/DistanceFieldVectorGL.h>
#include <Magnum/Shaders/FlatGL.h>
#include <Magnum/Shaders/PhongGL.h>
#include <Magnum/Shaders/VertexColorGL.h>
#include <Magnum/Shaders/VectorGL.h>
#include "Corrade/PythonBindings.h"
@ -44,6 +46,41 @@ namespace magnum {
namespace {
template<UnsignedInt dimensions> void distanceFieldVector(PyNonDestructibleClass<Shaders::DistanceFieldVectorGL<dimensions>, GL::AbstractShaderProgram>& c) {
/* Attributes */
c.attr("POSITION") = GL::DynamicAttribute{typename Shaders::DistanceFieldVectorGL<dimensions>::Position{}};
c.attr("TEXTURE_COORDINATES") = GL::DynamicAttribute{typename Shaders::DistanceFieldVectorGL<dimensions>::TextureCoordinates{}};
/* Methods */
c
.def(py::init<typename Shaders::DistanceFieldVectorGL<dimensions>::Flag>(), "Constructor",
py::arg("flags") = typename Shaders::DistanceFieldVectorGL<dimensions>::Flag{})
/* Using lambdas to avoid method chaining getting into signatures */
.def_property_readonly("flags", [](Shaders::DistanceFieldVectorGL<dimensions>& self) {
return typename Shaders::DistanceFieldVectorGL<dimensions>::Flag(UnsignedByte(self.flags()));
}, "Flags")
.def_property("transformation_projection_matrix", nullptr, &Shaders::DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix,
"Transformation and projection matrix")
.def_property("texture_matrix", nullptr, [](Shaders::DistanceFieldVectorGL<dimensions>& self, const Matrix3& matrix) {
if(!(self.flags() & Shaders::DistanceFieldVectorGL<dimensions>::Flag::TextureTransformation)) {
PyErr_SetString(PyExc_AttributeError, "the shader was not created with texture transformation enabled");
throw py::error_already_set{};
}
self.setTextureMatrix(matrix);
}, "Texture matrix")
.def_property("color", nullptr, &Shaders::DistanceFieldVectorGL<dimensions>::setColor, "Color")
.def_property("outline_color", nullptr, &Shaders::DistanceFieldVectorGL<dimensions>::setOutlineColor, "Outline color")
.def_property("outline_range", nullptr, [](Shaders::DistanceFieldVectorGL<dimensions>& self, const std::pair<Float, Float>& startEnd) {
self.setOutlineRange(startEnd.first, startEnd.second);
}, "Outline range start and end")
.def_property("smoothness", nullptr, &Shaders::DistanceFieldVectorGL<dimensions>::setSmoothness, "Smoothness")
.def("bind_vector_texture", [](Shaders::DistanceFieldVectorGL<dimensions>& self, GL::Texture2D& texture) {
self.bindVectorTexture(texture);
}, "Bind a vector texture");
}
template<UnsignedInt dimensions> void flat(PyNonDestructibleClass<Shaders::FlatGL<dimensions>, GL::AbstractShaderProgram>& c) {
/* Attributes */
c.attr("POSITION") = GL::DynamicAttribute{typename Shaders::FlatGL<dimensions>::Position{}};
@ -91,6 +128,37 @@ template<UnsignedInt dimensions> void flat(PyNonDestructibleClass<Shaders::FlatG
}, "Bind a color texture");
}
template<UnsignedInt dimensions> void vector(PyNonDestructibleClass<Shaders::VectorGL<dimensions>, GL::AbstractShaderProgram>& c) {
/* Attributes */
c.attr("POSITION") = GL::DynamicAttribute{typename Shaders::VectorGL<dimensions>::Position{}};
c.attr("TEXTURE_COORDINATES") = GL::DynamicAttribute{typename Shaders::VectorGL<dimensions>::TextureCoordinates{}};
/* Methods */
c
.def(py::init<typename Shaders::VectorGL<dimensions>::Flag>(), "Constructor",
py::arg("flags") = typename Shaders::VectorGL<dimensions>::Flag{})
/* Using lambdas to avoid method chaining getting into signatures */
.def_property_readonly("flags", [](Shaders::VectorGL<dimensions>& self) {
return typename Shaders::VectorGL<dimensions>::Flag(UnsignedByte(self.flags()));
}, "Flags")
.def_property("transformation_projection_matrix", nullptr, &Shaders::VectorGL<dimensions>::setTransformationProjectionMatrix,
"Transformation and projection matrix")
.def_property("texture_matrix", nullptr, [](Shaders::VectorGL<dimensions>& self, const Matrix3& matrix) {
if(!(self.flags() & Shaders::VectorGL<dimensions>::Flag::TextureTransformation)) {
PyErr_SetString(PyExc_AttributeError, "the shader was not created with texture transformation enabled");
throw py::error_already_set{};
}
self.setTextureMatrix(matrix);
}, "Texture matrix")
.def_property("color", nullptr, &Shaders::VectorGL<dimensions>::setColor, "Fill color")
.def_property("background_color", nullptr, &Shaders::VectorGL<dimensions>::setBackgroundColor, "Background color")
.def("bind_vector_texture", [](Shaders::VectorGL<dimensions>& self, GL::Texture2D& texture) {
self.bindVectorTexture(texture);
}, "Bind a vector texture");
}
template<UnsignedInt dimensions> void vertexColor(PyNonDestructibleClass<Shaders::VertexColorGL<dimensions>, GL::AbstractShaderProgram>& c) {
/* Attributes */
c.attr("POSITION") = GL::DynamicAttribute{typename Shaders::VertexColorGL<dimensions>::Position{}};
@ -118,6 +186,29 @@ void shaders(py::module_& m) {
py::module_::import("magnum.gl");
#endif
/* 2D/3D distance field vector shader */
{
PyNonDestructibleClass<Shaders::DistanceFieldVectorGL2D, GL::AbstractShaderProgram> distanceFieldVectorGL2D{m,
"DistanceFieldVectorGL2D", "2D distance field vector OpenGL shader"};
PyNonDestructibleClass<Shaders::DistanceFieldVectorGL3D, GL::AbstractShaderProgram> distanceFieldVectorGL3D{m,
"DistanceFieldVectorGL3D", "3D distance field vector OpenGL shader"};
/* 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_<Shaders::DistanceFieldVectorGL2D::Flag> flags{distanceFieldVectorGL2D, "Flags", "Flags"};
flags
.value("TEXTURE_TRANSFORMATION", Shaders::DistanceFieldVectorGL2D::Flag::TextureTransformation)
.value("NONE", Shaders::DistanceFieldVectorGL2D::Flag{})
;
distanceFieldVectorGL3D.attr("Flags") = flags;
distanceFieldVector(distanceFieldVectorGL2D);
distanceFieldVector(distanceFieldVectorGL3D);
corrade::enumOperators(flags);
}
/* 2D/3D flat shader */
{
PyNonDestructibleClass<Shaders::FlatGL2D, GL::AbstractShaderProgram> flatGL2D{m,
@ -315,6 +406,29 @@ void shaders(py::module_& m) {
}, "Bind textures", py::arg("ambient") = nullptr, py::arg("diffuse") = nullptr, py::arg("specular") = nullptr, py::arg("normal") = nullptr)
;
}
/* 2D/3D vector shader */
{
PyNonDestructibleClass<Shaders::VectorGL2D, GL::AbstractShaderProgram> vectorGL2D{m,
"VectorGL2D", "2D vector OpenGL shader"};
PyNonDestructibleClass<Shaders::VectorGL3D, GL::AbstractShaderProgram> vectorGL3D{m,
"VectorGL3D", "3D vector OpenGL shader"};
/* 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_<Shaders::VectorGL2D::Flag> flags{vectorGL2D, "Flags", "Flags"};
flags
.value("TEXTURE_TRANSFORMATION", Shaders::VectorGL2D::Flag::TextureTransformation)
.value("NONE", Shaders::VectorGL2D::Flag{})
;
vectorGL3D.attr("Flags") = flags;
vector(vectorGL2D);
vector(vectorGL3D);
corrade::enumOperators(flags);
}
}
}

52
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 DistanceFieldGL(GLTestCase):
def test_init(self):
a = shaders.DistanceFieldVectorGL3D()
self.assertEqual(a.flags, shaders.DistanceFieldVectorGL3D.Flags.NONE)
b = shaders.DistanceFieldVectorGL3D(shaders.DistanceFieldVectorGL3D.Flags.TEXTURE_TRANSFORMATION)
self.assertEqual(b.flags, shaders.DistanceFieldVectorGL3D.Flags.TEXTURE_TRANSFORMATION)
def test_uniforms_bindings(self):
a = shaders.DistanceFieldVectorGL3D(shaders.DistanceFieldVectorGL3D.Flags.TEXTURE_TRANSFORMATION)
a.color = (0.5, 1.0, 0.9)
a.outline_color = (1.0, 0.5, 0.9, 0.3)
a.outline_range = (0.5, 0.8)
a.smoothness = 0.1
a.transformation_projection_matrix = Matrix4.translation(Vector3.x_axis())
a.texture_matrix = Matrix3()
texture = gl.Texture2D()
texture.set_storage(1, gl.TextureFormat.R8, Vector2i(8))
a.bind_vector_texture(texture)
def test_uniforms_bindings_errors(self):
a = shaders.DistanceFieldVectorGL2D()
with self.assertRaisesRegex(AttributeError, "the shader was not created with texture transformation enabled"):
a.texture_matrix = Matrix3()
class FlatGL(GLTestCase):
def test_init(self):
a = shaders.FlatGL3D()
@ -136,3 +163,28 @@ class PhongGL(GLTestCase):
a.bind_normal_texture(texture)
with self.assertRaisesRegex(AttributeError, "the shader was not created with any textures enabled"):
a.bind_textures(diffuse=texture)
class DistanceFieldGL(GLTestCase):
def test_init(self):
a = shaders.VectorGL3D()
self.assertEqual(a.flags, shaders.VectorGL3D.Flags.NONE)
b = shaders.VectorGL3D(shaders.VectorGL3D.Flags.TEXTURE_TRANSFORMATION)
self.assertEqual(b.flags, shaders.VectorGL3D.Flags.TEXTURE_TRANSFORMATION)
def test_uniforms_bindings(self):
a = shaders.VectorGL3D(shaders.VectorGL3D.Flags.TEXTURE_TRANSFORMATION)
a.color = (0.5, 1.0, 0.9)
a.background_color = (1.0, 0.5, 0.9, 0.3)
a.transformation_projection_matrix = Matrix4.translation(Vector3.x_axis())
a.texture_matrix = Matrix3()
texture = gl.Texture2D()
texture.set_storage(1, gl.TextureFormat.R8, Vector2i(8))
a.bind_vector_texture(texture)
def test_uniforms_bindings_errors(self):
a = shaders.VectorGL2D()
with self.assertRaisesRegex(AttributeError, "the shader was not created with texture transformation enabled"):
a.texture_matrix = Matrix3()

Loading…
Cancel
Save