18 #include "../generic/py_capi_utils.h"
19 #include "../mathutils/mathutils.h"
32 #define PYDOC_BUILTIN_SHADER_DESCRIPTION \
33 "``2D_FLAT_COLOR``\n" \
34 " :Attributes: vec2 pos, vec4 color\n" \
35 " :Uniforms: none\n" \
37 " :Attributes: vec2 pos, vec2 texCoord\n" \
38 " :Uniforms: sampler2D image\n" \
39 "``2D_SMOOTH_COLOR``\n" \
40 " :Attributes: vec2 pos, vec4 color\n" \
41 " :Uniforms: none\n" \
42 "``2D_UNIFORM_COLOR``\n" \
43 " :Attributes: vec2 pos\n" \
44 " :Uniforms: vec4 color\n" \
45 "``3D_FLAT_COLOR``\n" \
46 " :Attributes: vec3 pos, vec4 color\n" \
47 " :Uniforms: none\n" \
49 " :Attributes: vec3 pos, vec2 texCoord\n" \
50 " :Uniforms: sampler2D image\n" \
51 "``3D_SMOOTH_COLOR``\n" \
52 " :Attributes: vec3 pos, vec4 color\n" \
53 " :Uniforms: none\n" \
54 "``3D_UNIFORM_COLOR``\n" \
55 " :Attributes: vec3 pos\n" \
56 " :Uniforms: vec4 color\n" \
57 "``3D_POLYLINE_FLAT_COLOR``\n" \
58 " :Attributes: vec3 pos, vec4 color\n" \
59 " :Uniforms: vec2 viewportSize, float lineWidth\n" \
60 "``3D_POLYLINE_SMOOTH_COLOR``\n" \
61 " :Attributes: vec3 pos, vec4 color\n" \
62 " :Uniforms: vec2 viewportSize, float lineWidth\n" \
63 "``3D_POLYLINE_UNIFORM_COLOR``\n" \
64 " :Attributes: vec3 pos\n" \
65 " :Uniforms: vec2 viewportSize, float lineWidth\n"
90 const char *error_prefix)
95 PyErr_Format(PyExc_ValueError,
"%s: uniform %.32s not found", error_prefix, name);
112 const char *vertexcode;
113 const char *fragcode;
120 static const char *_keywords[] = {
121 "vertexcode",
"fragcode",
"geocode",
"libcode",
"defines",
"name",
NULL};
122 static _PyArg_Parser _parser = {
130 ":GPUShader.__new__",
134 if (!_PyArg_ParseTupleAndKeywordsFast(args,
153 if (shader ==
NULL) {
154 PyErr_SetString(PyExc_Exception,
"Shader Compile Error, see console for more details");
162 pygpu_shader_bind_doc,
163 ".. method:: bind()\n"
165 " Bind the shader object. Required to be able to change uniforms of this shader.\n");
173 ".. method:: uniform_from_name(name)\n"
175 " Get uniform location by name.\n"
177 " :param name: Name of the uniform variable whose location is to be queried.\n"
179 " :return: Location of the uniform variable.\n"
183 const char *name = PyUnicode_AsUTF8(arg);
189 self->shader, name,
"GPUShader.get_uniform");
195 return PyLong_FromLong(uniform);
199 pygpu_shader_uniform_block_from_name_doc,
200 ".. method:: uniform_block_from_name(name)\n"
202 " Get uniform block location by name.\n"
204 " :param name: Name of the uniform block variable whose location is to be queried.\n"
206 " :return: The location of the uniform block variable.\n"
210 const char *name = PyUnicode_AsUTF8(arg);
218 PyErr_Format(PyExc_ValueError,
"GPUShader.get_uniform_block: uniform %.32s not found", name);
222 return PyLong_FromLong(uniform);
230 Py_buffer *r_pybuffer)
235 if (!PyArg_ParseTuple(
236 args,
"iOi|i:GPUShader.uniform_vector_*", r_location, &
buffer, r_length, r_count)) {
240 if (PyObject_GetBuffer(
buffer, r_pybuffer, PyBUF_SIMPLE) == -1) {
245 if (r_pybuffer->len < (*r_length * *r_count * elem_size)) {
246 PyErr_SetString(PyExc_OverflowError,
247 "GPUShader.uniform_vector_*: buffer size smaller than required.");
255 ".. method:: uniform_vector_float(location, buffer, length, count)\n"
257 " Set the buffer to fill the uniform.\n"
259 " :param location: Location of the uniform variable to be modified.\n"
260 " :type location: int\n"
261 " :param buffer: The data that should be set. Can support the buffer protocol.\n"
262 " :type buffer: sequence of floats\n"
263 " :param length: Size of the uniform data type:\n\n"
265 " - 2: vec2 or float[2]\n"
266 " - 3: vec3 or float[3]\n"
267 " - 4: vec4 or float[4]\n"
270 " :type length: int\n"
271 " :param count: Specifies the number of elements, vector or matrices that are to "
273 " :type count: int\n");
281 args,
sizeof(
float), &location, &
length, &
count, &pybuffer)) {
287 PyBuffer_Release(&pybuffer);
293 ".. method:: uniform_vector_int(location, buffer, length, count)\n"
295 " See GPUShader.uniform_vector_float(...) description.\n");
303 args,
sizeof(
int), &location, &
length, &
count, &pybuffer)) {
309 PyBuffer_Release(&pybuffer);
315 ".. method:: uniform_bool(name, seq)\n"
317 " Specify the value of a uniform variable for the current program object.\n"
319 " :param name: Name of the uniform variable whose value is to be changed.\n"
321 " :param seq: Value that will be used to update the specified uniform variable.\n"
322 " :type seq: sequence of bools\n");
325 const char *error_prefix =
"GPUShader.uniform_bool";
332 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_bool", &
params.id, &
params.seq)) {
340 PyObject *seq_fast = PySequence_Fast(
params.seq, error_prefix);
341 if (seq_fast ==
NULL) {
342 PyErr_Format(PyExc_TypeError,
343 "%s: expected a sequence, got %s",
345 Py_TYPE(
params.seq)->tp_name);
349 length = PySequence_Fast_GET_SIZE(seq_fast);
351 PyErr_Format(PyExc_TypeError,
352 "%s: invalid sequence length. expected 1..4, got %d",
359 values,
sizeof(*values), seq_fast,
length, &PyLong_Type, error_prefix);
370 if (location == -1) {
380 ".. method:: uniform_float(name, value)\n"
382 " Specify the value of a uniform variable for the current program object.\n"
384 " :param name: Name of the uniform variable whose value is to be changed.\n"
386 " :param value: Value that will be used to update the specified uniform variable.\n"
387 " :type value: single number or sequence of numbers\n");
390 const char *error_prefix =
"GPUShader.uniform_float";
397 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_float", &
params.id, &
params.seq)) {
404 if (PyFloat_Check(
params.seq)) {
408 else if (PyLong_Check(
params.seq)) {
418 PyErr_SetString(PyExc_ValueError,
"Expected 3x3 or 4x4 matrix");
422 memcpy(values, mat->matrix,
sizeof(
float) *
length);
432 PyErr_SetString(PyExc_TypeError,
433 "Expected a single float or a sequence of floats of length 1..4, 9 or 16.");
439 if (location == -1) {
449 ".. method:: uniform_int(name, seq)\n"
451 " Specify the value of a uniform variable for the current program object.\n"
453 " :param name: name of the uniform variable whose value is to be changed.\n"
455 " :param seq: Value that will be used to update the specified uniform variable.\n"
456 " :type seq: sequence of numbers\n");
459 const char *error_prefix =
"GPUShader.uniform_int";
466 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_int", &
params.id, &
params.seq)) {
474 if (PyLong_Check(
params.seq)) {
475 values[0] = PyC_Long_AsI32(
params.seq);
480 PyObject *seq_fast = PySequence_Fast(
params.seq, error_prefix);
481 if (seq_fast ==
NULL) {
482 PyErr_Format(PyExc_TypeError,
483 "%s: expected a sequence, got %s",
485 Py_TYPE(
params.seq)->tp_name);
489 length = PySequence_Fast_GET_SIZE(seq_fast);
491 PyErr_Format(PyExc_TypeError,
492 "%s: invalid sequence length. expected 1..4, got %d",
499 values,
sizeof(*values), seq_fast,
length, &PyLong_Type, error_prefix);
510 if (location == -1) {
520 ".. method:: uniform_sampler(name, texture)\n"
522 " Specify the value of a texture uniform variable for the current GPUShader.\n"
524 " :param name: name of the uniform variable whose texture is to be specified.\n"
526 " :param texture: Texture to attach.\n"
527 " :type texture: :class:`gpu.types.GPUTexture`\n");
532 if (!PyArg_ParseTuple(
545 pygpu_shader_uniform_block_doc,
546 ".. method:: uniform_block(name, ubo)\n"
548 " Specify the value of an uniform buffer object variable for the current GPUShader.\n"
550 " :param name: name of the uniform variable whose UBO is to be specified.\n"
552 " :param ubo: Uniform Buffer to attach.\n"
553 " :type texture: :class:`gpu.types.GPUUniformBuf`\n");
558 if (!PyArg_ParseTuple(
567 "GPUShader.uniform_block: uniform block not found, make sure the name is correct");
577 pygpu_shader_attr_from_name_doc,
578 ".. method:: attr_from_name(name)\n"
580 " Get attribute location by name.\n"
582 " :param name: The name of the attribute variable whose location is to be queried.\n"
584 " :return: The location of an attribute variable.\n"
588 const char *name = PyUnicode_AsUTF8(arg);
596 PyErr_Format(PyExc_ValueError,
"GPUShader.attr_from_name: attribute %.32s not found", name);
600 return PyLong_FromLong(attr);
604 ".. method:: calc_format()\n"
606 " Build a new format based on the attributes of the shader.\n"
608 " :return: vertex attribute format for the shader\n"
609 " :rtype: :class:`gpu.types.GPUVertFormat`\n");
614 return (PyObject *)
ret;
619 {
"uniform_from_name",
622 pygpu_shader_uniform_from_name_doc},
623 {
"uniform_block_from_name",
626 pygpu_shader_uniform_block_from_name_doc},
627 {
"uniform_vector_float",
630 pygpu_shader_uniform_vector_float_doc},
631 {
"uniform_vector_int",
634 pygpu_shader_uniform_vector_int_doc},
638 pygpu_shader_uniform_bool_doc},
642 pygpu_shader_uniform_float_doc},
646 pygpu_shader_uniform_int_doc},
650 pygpu_shader_uniform_sampler_doc},
654 pygpu_shader_uniform_block_doc},
658 pygpu_shader_attr_from_name_doc},
662 pygpu_shader_calc_format_doc},
667 "The name of the shader object for debugging purposes (read-only).\n\n:type: str");
674 pygpu_shader_program_doc,
675 "The name of the program object for use by the OpenGL API (read-only).\n\n:type: int");
689 if (
self->is_builtin ==
false) {
692 Py_TYPE(
self)->tp_free((PyObject *)
self);
696 pygpu_shader__tp_doc,
697 ".. class:: GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None, "
698 "name='pyGPUShader')\n"
700 " GPUShader combines multiple GLSL shaders into a program used for drawing.\n"
701 " It must contain at least a vertex and fragment shaders.\n"
703 " The GLSL ``#version`` directive is automatically included at the top of shaders,\n"
704 " and set to 330. Some preprocessor directives are automatically added according to\n"
705 " the Operating System or availability: ``GPU_ATI``, ``GPU_NVIDIA`` and ``GPU_INTEL``.\n"
707 " The following extensions are enabled by default if supported by the GPU:\n"
708 " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array``\n"
709 " and ``GL_ARB_shader_draw_parameters``.\n"
711 " For drawing user interface elements and gizmos, use\n"
712 " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``\n"
713 " to transform the output sRGB colors to the frame-buffer color-space.\n"
715 " :param vertexcode: Vertex shader code.\n"
716 " :type vertexcode: str\n"
717 " :param fragcode: Fragment shader code.\n"
718 " :type value: str\n"
719 " :param geocode: Geometry shader code.\n"
720 " :type value: str\n"
721 " :param libcode: Code with functions and presets to be shared between shaders.\n"
722 " :type value: str\n"
723 " :param defines: Preprocessor directives.\n"
724 " :type value: str\n"
725 " :param name: Name of shader code, for debugging purposes.\n"
726 " :type value: str\n");
728 PyVarObject_HEAD_INIT(
NULL, 0).tp_name =
"GPUShader",
731 .tp_flags = Py_TPFLAGS_DEFAULT,
732 .tp_doc = pygpu_shader__tp_doc,
745 ".. function:: unbind()\n"
747 " Unbind the bound shader object.\n");
755 pygpu_shader_from_builtin_doc,
756 ".. function:: from_builtin(shader_name, config='DEFAULT')\n"
758 " Shaders that are embedded in the blender internal code (see :ref:`built-in-shaders`).\n"
759 " They all read the uniform ``mat4 ModelViewProjectionMatrix``,\n"
760 " which can be edited by the :mod:`gpu.matrix` module.\n"
762 " You can also choose a shader configuration that uses clip_planes by setting the "
763 "``CLIPPED`` value to the config parameter. Note that in this case you also need to "
764 "manually set the value of ``mat4 ModelMatrix``.\n"
766 " :param shader_name: One of the builtin shader names.\n"
767 " :type shader_name: str\n"
768 " :param config: One of these types of shader configuration:\n"
772 " :type config: str\n"
773 " :return: Shader object corresponding to the given name.\n"
774 " :rtype: :class:`bpy.types.GPUShader`\n");
782 static const char *_keywords[] = {
"shader_name",
"config",
NULL};
783 static _PyArg_Parser _parser = {
791 if (!_PyArg_ParseTupleAndKeywordsFast(args,
808 ".. function:: create_from_info(shader_info)\n"
810 " Create shader from a GPUShaderCreateInfo.\n"
812 " :param shader_info: GPUShaderCreateInfo\n"
813 " :type shader_info: :class:`bpy.types.GPUShaderCreateInfo`\n"
814 " :return: Shader object corresponding to the given name.\n"
815 " :rtype: :class:`bpy.types.GPUShader`\n");
820 PyErr_Format(PyExc_TypeError,
"Expected a GPUShaderCreateInfo, got %s", Py_TYPE(o)->tp_name);
826 PyErr_SetString(PyExc_Exception,
error);
832 PyErr_SetString(PyExc_Exception,
"Shader Compile Error, see console for more details");
843 METH_VARARGS | METH_KEYWORDS,
844 pygpu_shader_from_builtin_doc},
848 pygpu_shader_create_from_info_doc},
853 "This module provides access to GPUShader internal functions.\n"
855 ".. _built-in-shaders:\n"
857 ".. rubric:: Built-in shaders\n"
859 "All built-in shaders have the ``mat4 ModelViewProjectionMatrix`` uniform.\n"
861 "Its value must be modified using the :class:`gpu.matrix` module.\n"
864 PyModuleDef_HEAD_INIT,
865 .m_name =
"gpu.shader",
866 .m_doc = pygpu_shader_module__tp_doc,
881 self->shader = shader;
884 return (PyObject *)
self;
typedef float(TangentPoint)[2]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
void GPU_shader_unbind(void)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length, int arraysize, const int *value)
GPUShader * GPU_shader_create_from_python(const char *vertcode, const char *fragcode, const char *geomcode, const char *libcode, const char *defines, const char *name)
struct GPUShader GPUShader
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
GPUShader * GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg)
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, const float *value)
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name)
int GPU_shader_get_program(GPUShader *shader)
void GPU_shader_bind(GPUShader *shader)
const char * GPU_shader_get_name(GPUShader *shader)
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
@ GPU_SHADER_3D_SMOOTH_COLOR
@ GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_SHADER_2D_SMOOTH_COLOR
@ GPU_SHADER_2D_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_FLAT_COLOR
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
@ GPU_SHADER_2D_FLAT_COLOR
int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
void GPU_shader_free(GPUShader *shader)
bool GPU_shader_create_info_check_error(const GPUShaderCreateInfo *_info, char r_error[128])
GPUShader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
void GPU_texture_bind(GPUTexture *tex, int unit)
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
static PyObject * pygpu_shader_bind(BPyGPUShader *self)
#define PYDOC_BUILTIN_SHADER_DESCRIPTION
static PyObject * pygpu_shader__tp_new(PyTypeObject *UNUSED(type), PyObject *args, PyObject *kwds)
static PyObject * pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_from_builtin(PyObject *UNUSED(self), PyObject *args, PyObject *kwds)
static struct PyMethodDef pygpu_shader__tp_methods[]
static PyObject * pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_program_get(BPyGPUShader *self, void *UNUSED(closure))
static PyObject * pygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg)
static const struct PyC_StringEnumItems pygpu_shader_config_items[]
static PyObject * pygpu_shader_create_from_info(BPyGPUShader *UNUSED(self), BPyGPUShaderCreateInfo *o)
static PyObject * pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args)
PyTypeObject BPyGPUShader_Type
static struct PyMethodDef pygpu_shader_module__tp_methods[]
static PyObject * pygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_name(BPyGPUShader *self)
static PyObject * pygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
static bool pygpu_shader_uniform_vector_impl(PyObject *args, int elem_size, int *r_location, int *r_length, int *r_count, Py_buffer *r_pybuffer)
static PyObject * pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args)
static void pygpu_shader__tp_dealloc(BPyGPUShader *self)
static PyObject * pygpu_shader_unbind(BPyGPUShader *UNUSED(self))
PyObject * bpygpu_shader_init(void)
PyObject * BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin)
static PyModuleDef pygpu_shader_module_def
PyDoc_STRVAR(pygpu_shader_bind_doc, ".. method:: bind()\n" "\n" " Bind the shader object. Required to be able to change uniforms of this shader.\n")
static const struct PyC_StringEnumItems pygpu_shader_builtin_items[]
static PyGetSetDef pygpu_shader__tp_getseters[]
static int pygpu_shader_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix)
struct BPyGPUShader BPyGPUShader
#define BPyGPUShaderCreateInfo_Check(v)
PyTypeObject BPyGPUTexture_Type
ccl_global float * buffer
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
#define BaseMath_ReadCallback(_self)
#define MatrixObject_Check(v)
static void error(const char *str)
bool is_builtin(const void *UNUSED(owner), const AttributeIDRef &attribute_id)
T length(const vec_base< T, Size > &a)
int PyC_ParseStringEnum(PyObject *o, void *p)
int PyC_AsArray_FAST(void *array, const size_t array_item_size, PyObject *value_fast, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix)
PyObject_VAR_HEAD struct GPUShaderCreateInfo * info
PyObject_HEAD struct GPUTexture * tex