37#define PYDOC_BUILTIN_SHADER_DESCRIPTION \
39 " :Attributes: vec3 pos, vec4 color\n" \
40 " :Uniforms: none\n" \
42 " :Attributes: vec3 pos, vec2 texCoord\n" \
43 " :Uniforms: sampler2D image\n" \
45 " :Attributes: vec3 pos, vec2 texCoord\n" \
46 " :Uniforms: sampler2D image, vec4 color\n" \
47 "``SMOOTH_COLOR``\n" \
48 " :Attributes: vec3 pos, vec4 color\n" \
49 " :Uniforms: none\n" \
50 "``UNIFORM_COLOR``\n" \
51 " :Attributes: vec3 pos\n" \
52 " :Uniforms: vec4 color\n" \
53 "``POLYLINE_FLAT_COLOR``\n" \
54 " :Attributes: vec3 pos, vec4 color\n" \
55 " :Uniforms: vec2 viewportSize, float lineWidth\n" \
56 "``POLYLINE_SMOOTH_COLOR``\n" \
57 " :Attributes: vec3 pos, vec4 color\n" \
58 " :Uniforms: vec2 viewportSize, float lineWidth\n" \
59 "``POLYLINE_UNIFORM_COLOR``\n" \
60 " :Attributes: vec3 pos\n" \
61 " :Uniforms: vec2 viewportSize, float lineWidth\n"
83 const char *error_prefix)
88 PyErr_Format(PyExc_ValueError,
"%s: uniform %.32s not found", error_prefix, name);
105 const char *vertexcode;
106 const char *fragcode;
113 static const char *_keywords[] = {
114 "vertexcode",
"fragcode",
"geocode",
"libcode",
"defines",
"name",
nullptr};
115 static _PyArg_Parser _parser = {
124 ":GPUShader.__new__",
128 if (!_PyArg_ParseTupleAndKeywordsFast(args,
148 if (shader ==
nullptr) {
149 PyErr_SetString(PyExc_Exception,
"Shader Compile Error, see console for more details");
158 pygpu_shader_bind_doc,
159 ".. method:: bind()\n"
161 " Bind the shader object. Required to be able to change uniforms of this shader.\n");
170 pygpu_shader_uniform_from_name_doc,
171 ".. method:: uniform_from_name(name)\n"
173 " Get uniform location by name.\n"
175 " :arg name: Name of the uniform variable whose location is to be queried.\n"
177 " :return: Location of the uniform variable.\n"
181 const char *name = PyUnicode_AsUTF8(arg);
182 if (name ==
nullptr) {
187 self->shader, name,
"GPUShader.get_uniform");
193 return PyLong_FromLong(uniform);
198 pygpu_shader_uniform_block_from_name_doc,
199 ".. method:: uniform_block_from_name(name)\n"
201 " Get uniform block location by name.\n"
203 " :arg name: Name of the uniform block variable whose location is to be queried.\n"
205 " :return: The location of the uniform block variable.\n"
209 const char *name = PyUnicode_AsUTF8(arg);
210 if (name ==
nullptr) {
217 PyErr_Format(PyExc_ValueError,
"GPUShader.get_uniform_block: uniform %.32s not found", name);
221 return PyLong_FromLong(uniform);
229 Py_buffer *r_pybuffer)
234 if (!PyArg_ParseTuple(
235 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.");
256 pygpu_shader_uniform_vector_float_doc,
257 ".. method:: uniform_vector_float(location, buffer, length, count)\n"
259 " Set the buffer to fill the uniform.\n"
261 " :arg location: Location of the uniform variable to be modified.\n"
262 " :type location: int\n"
263 " :arg buffer: The data that should be set. Can support the buffer protocol.\n"
264 " :type buffer: Sequence[float]\n"
265 " :arg length: Size of the uniform data type:\n"
268 " - 2: vec2 or float[2]\n"
269 " - 3: vec3 or float[3]\n"
270 " - 4: vec4 or float[4]\n"
273 " :type length: int\n"
274 " :arg count: Specifies the number of elements, vector or matrices that are to "
276 " :type count: int\n");
284 args,
sizeof(
float), &location, &length, &
count, &pybuffer))
291 self->shader, location, length,
count,
static_cast<const float *
>(pybuffer.buf));
293 PyBuffer_Release(&pybuffer);
300 pygpu_shader_uniform_vector_int_doc,
301 ".. method:: uniform_vector_int(location, buffer, length, count)\n"
303 " See GPUShader.uniform_vector_float(...) description.\n");
317 self->shader, location, length,
count,
static_cast<const int *
>(pybuffer.buf));
319 PyBuffer_Release(&pybuffer);
326 pygpu_shader_uniform_bool_doc,
327 ".. method:: uniform_bool(name, value)\n"
329 " Specify the value of a uniform variable for the current program object.\n"
331 " :arg name: Name of the uniform variable whose value is to be changed.\n"
333 " :arg value: Value that will be used to update the specified uniform variable.\n"
334 " :type value: bool | Sequence[bool]\n");
337 const char *error_prefix =
"GPUShader.uniform_bool";
344 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_bool", &
params.id, &
params.seq)) {
351 if (PySequence_Check(
params.seq)) {
352 PyObject *seq_fast = PySequence_Fast(
params.seq, error_prefix);
353 if (seq_fast ==
nullptr) {
354 PyErr_Format(PyExc_TypeError,
355 "%s: expected a sequence, got %s",
357 Py_TYPE(
params.seq)->tp_name);
360 length = PySequence_Fast_GET_SIZE(seq_fast);
361 if (length == 0 || length > 4) {
362 PyErr_Format(PyExc_TypeError,
363 "%s: invalid sequence length. expected 1..4, got %d",
369 values,
sizeof(*values), seq_fast, length, &PyLong_Type, error_prefix);
374 else if (((values[0] =
int(PyLong_AsLong(
params.seq))) != -1) &&
ELEM(values[0], 0, 1)) {
380 PyExc_ValueError,
"expected a bool or sequence, got %s", Py_TYPE(
params.seq)->tp_name);
389 if (location == -1) {
401 pygpu_shader_uniform_float_doc,
402 ".. method:: uniform_float(name, value)\n"
404 " Specify the value of a uniform variable for the current program object.\n"
406 " :arg name: Name of the uniform variable whose value is to be changed.\n"
408 " :arg value: Value that will be used to update the specified uniform variable.\n"
409 " :type value: float | Sequence[float]\n");
412 const char *error_prefix =
"GPUShader.uniform_float";
419 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_float", &
params.id, &
params.seq)) {
426 if (PyFloat_Check(
params.seq)) {
430 else if (PyLong_Check(
params.seq)) {
440 PyErr_SetString(PyExc_ValueError,
"Expected 3x3 or 4x4 matrix");
444 memcpy(values, mat->matrix,
sizeof(
float) * length);
453 if (!
ELEM(length, 1, 2, 3, 4, 9, 16)) {
454 PyErr_SetString(PyExc_TypeError,
455 "Expected a single float or a sequence of floats of length 1..4, 9 or 16.");
461 if (location == -1) {
473 pygpu_shader_uniform_int_doc,
474 ".. method:: uniform_int(name, seq)\n"
476 " Specify the value of a uniform variable for the current program object.\n"
478 " :arg name: name of the uniform variable whose value is to be changed.\n"
480 " :arg seq: Value that will be used to update the specified uniform variable.\n"
481 " :type seq: Sequence[int]\n");
484 const char *error_prefix =
"GPUShader.uniform_int";
491 if (!PyArg_ParseTuple(args,
"sO:GPUShader.uniform_int", &
params.id, &
params.seq)) {
499 if (PyLong_Check(
params.seq)) {
500 values[0] = PyC_Long_AsI32(
params.seq);
505 PyObject *seq_fast = PySequence_Fast(
params.seq, error_prefix);
506 if (seq_fast ==
nullptr) {
507 PyErr_Format(PyExc_TypeError,
508 "%s: expected a sequence, got %s",
510 Py_TYPE(
params.seq)->tp_name);
514 length = PySequence_Fast_GET_SIZE(seq_fast);
515 if (length == 0 || length > 4) {
516 PyErr_Format(PyExc_TypeError,
517 "%s: invalid sequence length. expected 1..4, got %d",
524 values,
sizeof(*values), seq_fast, length, &PyLong_Type, error_prefix);
535 if (location == -1) {
547 pygpu_shader_uniform_sampler_doc,
548 ".. method:: uniform_sampler(name, texture)\n"
550 " Specify the value of a texture uniform variable for the current GPUShader.\n"
552 " :arg name: name of the uniform variable whose texture is to be specified.\n"
554 " :arg texture: Texture to attach.\n"
555 " :type texture: :class:`gpu.types.GPUTexture`\n");
560 if (!PyArg_ParseTuple(
576 pygpu_shader_image_doc,
577 ".. method:: image(name, texture)\n"
579 " Specify the value of an image variable for the current GPUShader.\n"
581 " :arg name: Name of the image variable to which the texture is to be bound.\n"
583 " :arg texture: Texture to attach.\n"
584 " :type texture: :class:`gpu.types.GPUTexture`\n");
589 if (!PyArg_ParseTuple(args,
"sO!:GPUShader.image", &name, &
BPyGPUTexture_Type, &py_texture)) {
595 if (image_unit == -1) {
596 PyErr_Format(PyExc_ValueError,
"Image '%s' not found in shader", name);
607 pygpu_shader_uniform_block_doc,
608 ".. method:: uniform_block(name, ubo)\n"
610 " Specify the value of an uniform buffer object variable for the current GPUShader.\n"
612 " :arg name: name of the uniform variable whose UBO is to be specified.\n"
614 " :arg ubo: Uniform Buffer to attach.\n"
615 " :type texture: :class:`gpu.types.GPUUniformBuf`\n");
620 if (!PyArg_ParseTuple(
630 "GPUShader.uniform_block: uniform block not found, make sure the name is correct");
642 pygpu_shader_attr_from_name_doc,
643 ".. method:: attr_from_name(name)\n"
645 " Get attribute location by name.\n"
647 " :arg name: The name of the attribute variable whose location is to be queried.\n"
649 " :return: The location of an attribute variable.\n"
653 const char *name = PyUnicode_AsUTF8(arg);
654 if (name ==
nullptr) {
661 PyErr_Format(PyExc_ValueError,
"GPUShader.attr_from_name: attribute %.32s not found", name);
665 return PyLong_FromLong(attr);
670 pygpu_shader_format_calc_doc,
671 ".. method:: format_calc()\n"
673 " Build a new format based on the attributes of the shader.\n"
675 " :return: vertex attribute format for the shader\n"
676 " :rtype: :class:`gpu.types.GPUVertFormat`\n");
681 return (PyObject *)
ret;
686 pygpu_shader_attrs_info_get_doc,
687 ".. method:: attrs_info_get()\n"
689 " Information about the attributes used in the Shader.\n"
691 " :return: tuples containing information about the attributes in order (name, type)\n"
692 " :rtype: tuple[tuple[str, str | None], ...]\n");
696 int location_test = 0, attrs_added = 0;
698 PyObject *
ret = PyTuple_New(attr_len);
699 while (attrs_added < attr_len) {
707 py_type = PyUnicode_InternFromString(
715 PyObject *attr_info = PyTuple_New(2);
717 PyTuple_SetItem(
ret, attrs_added, attr_info);
723#if (defined(__GNUC__) && !defined(__clang__))
724# pragma GCC diagnostic push
725# pragma GCC diagnostic ignored "-Wcast-function-type"
730 {
"uniform_from_name",
733 pygpu_shader_uniform_from_name_doc},
734 {
"uniform_block_from_name",
737 pygpu_shader_uniform_block_from_name_doc},
738 {
"uniform_vector_float",
741 pygpu_shader_uniform_vector_float_doc},
742 {
"uniform_vector_int",
745 pygpu_shader_uniform_vector_int_doc},
749 pygpu_shader_uniform_bool_doc},
753 pygpu_shader_uniform_float_doc},
757 pygpu_shader_uniform_int_doc},
761 pygpu_shader_uniform_sampler_doc},
766 pygpu_shader_uniform_block_doc},
770 pygpu_shader_attr_from_name_doc},
774 pygpu_shader_format_calc_doc},
778 pygpu_shader_attrs_info_get_doc},
779 {
nullptr,
nullptr, 0,
nullptr},
782#if (defined(__GNUC__) && !defined(__clang__))
783# pragma GCC diagnostic pop
788 pygpu_shader_name_doc,
789 "The name of the shader object for debugging purposes (read-only).\n"
799 pygpu_shader_program_doc,
800 "The name of the program object for use by the OpenGL API (read-only).\n"
812 pygpu_shader_program_doc,
814 {
"name", (getter)
pygpu_shader_name, (setter)
nullptr, pygpu_shader_name_doc,
nullptr},
815 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
820 if (
self->is_builtin ==
false) {
823 Py_TYPE(
self)->tp_free((PyObject *)
self);
828 pygpu_shader__tp_doc,
829 ".. class:: GPUShader(vertexcode, fragcode, geocode=None, libcode=None, defines=None, "
830 "name='pyGPUShader')\n"
832 " GPUShader combines multiple GLSL shaders into a program used for drawing.\n"
833 " It must contain at least a vertex and fragment shaders.\n"
835 " The GLSL ``#version`` directive is automatically included at the top of shaders,\n"
836 " and set to 330. Some preprocessor directives are automatically added according to\n"
837 " the Operating System or availability: ``GPU_ATI``, ``GPU_NVIDIA`` and ``GPU_INTEL``.\n"
839 " The following extensions are enabled by default if supported by the GPU:\n"
840 " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array``\n"
841 " and ``GL_ARB_shader_draw_parameters``.\n"
843 " For drawing user interface elements and gizmos, use\n"
844 " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``\n"
845 " to transform the output sRGB colors to the frame-buffer color-space.\n"
847 " :arg vertexcode: Vertex shader code.\n"
848 " :type vertexcode: str\n"
849 " :arg fragcode: Fragment shader code.\n"
850 " :type value: str\n"
851 " :arg geocode: Geometry shader code.\n"
852 " :type value: str\n"
853 " :arg libcode: Code with functions and presets to be shared between shaders.\n"
854 " :type value: str\n"
855 " :arg defines: Preprocessor directives.\n"
856 " :type value: str\n"
857 " :arg name: Name of shader code, for debugging purposes.\n"
858 " :type value: str\n");
860 PyVarObject_HEAD_INIT(
nullptr, 0)
880 pygpu_shader__tp_doc,
919 pygpu_shader_unbind_doc,
920 ".. function:: unbind()\n"
922 " Unbind the bound shader object.\n");
931 pygpu_shader_from_builtin_doc,
932 ".. function:: from_builtin(shader_name, config='DEFAULT')\n"
934 " Shaders that are embedded in the blender internal code (see :ref:`built-in-shaders`).\n"
935 " They all read the uniform ``mat4 ModelViewProjectionMatrix``,\n"
936 " which can be edited by the :mod:`gpu.matrix` module.\n"
938 " You can also choose a shader configuration that uses clip_planes by setting the "
939 "``CLIPPED`` value to the config parameter. Note that in this case you also need to "
940 "manually set the value of ``mat4 ModelMatrix``.\n"
942 " :arg shader_name: One of the builtin shader names.\n"
943 " :type shader_name: str\n"
944 " :arg config: One of these types of shader configuration:\n"
948 " :type config: str\n"
949 " :return: Shader object corresponding to the given name.\n"
950 " :rtype: :class:`gpu.types.GPUShader`\n");
958 static const char *_keywords[] = {
"shader_name",
"config",
nullptr};
959 static _PyArg_Parser _parser = {
968 if (!_PyArg_ParseTupleAndKeywordsFast(args,
988 pygpu_shader_create_from_info_doc,
989 ".. function:: create_from_info(shader_info)\n"
991 " Create shader from a GPUShaderCreateInfo.\n"
993 " :arg shader_info: GPUShaderCreateInfo\n"
994 " :type shader_info: :class:`bpy.types.GPUShaderCreateInfo`\n"
995 " :return: Shader object corresponding to the given name.\n"
996 " :rtype: :class:`gpu.types.GPUShader`\n");
1002 PyErr_Format(PyExc_TypeError,
"Expected a GPUShaderCreateInfo, got %s", Py_TYPE(o)->tp_name);
1008 PyErr_SetString(PyExc_Exception,
error);
1014 PyErr_SetString(PyExc_Exception,
"Shader Compile Error, see console for more details");
1021#if (defined(__GNUC__) && !defined(__clang__))
1022# pragma GCC diagnostic push
1023# pragma GCC diagnostic ignored "-Wcast-function-type"
1030 METH_VARARGS | METH_KEYWORDS,
1031 pygpu_shader_from_builtin_doc},
1032 {
"create_from_info",
1035 pygpu_shader_create_from_info_doc},
1036 {
nullptr,
nullptr, 0,
nullptr},
1039#if (defined(__GNUC__) && !defined(__clang__))
1040# pragma GCC diagnostic pop
1045 pygpu_shader_module__tp_doc,
1046 "This module provides access to GPUShader internal functions.\n"
1048 ".. _built-in-shaders:\n"
1050 ".. rubric:: Built-in shaders\n"
1052 "All built-in shaders have the ``mat4 ModelViewProjectionMatrix`` uniform.\n"
1054 "Its value must be modified using the :class:`gpu.matrix` module.\n"
1057 PyModuleDef_HEAD_INIT,
1059 pygpu_shader_module__tp_doc,
1079 self->shader = shader;
1080 self->is_builtin = is_builtin;
1082 return (PyObject *)
self;
1087 PyObject *submodule;
int GPU_shader_get_sampler_binding(GPUShader *shader, const char *name)
int GPU_shader_get_uniform(GPUShader *shader, const char *name)
bool GPU_shader_get_attribute_info(const GPUShader *shader, int attr_location, char r_name[256], int *r_type)
const char * GPU_shader_get_name(GPUShader *shader)
void GPU_shader_uniform_1i(GPUShader *sh, const char *name, int value)
int GPU_shader_get_ubo_binding(GPUShader *shader, const char *name)
void GPU_shader_uniform_int_ex(GPUShader *shader, int location, int length, int array_size, 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)
unsigned int GPU_shader_get_attribute_len(const GPUShader *shader)
int GPU_shader_get_attribute(const GPUShader *shader, const char *name)
void GPU_shader_uniform_float_ex(GPUShader *shader, int location, int length, int array_size, const float *value)
int GPU_shader_get_program(GPUShader *shader)
void GPU_shader_bind(GPUShader *shader)
GPUShader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
int GPU_shader_get_uniform_block(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_get_builtin_shader_with_config(eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg)
@ GPU_SHADER_3D_SMOOTH_COLOR
@ GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR
@ GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR
@ GPU_SHADER_3D_UNIFORM_COLOR
@ GPU_SHADER_3D_FLAT_COLOR
@ GPU_SHADER_3D_POLYLINE_FLAT_COLOR
@ GPU_SHADER_3D_IMAGE_COLOR
void GPU_texture_bind(GPUTexture *texture, int unit)
void GPU_texture_image_bind(GPUTexture *texture, int unit)
struct GPUShader GPUShader
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
draw_view in_light_buf[] float
#define BPYGPU_IS_INIT_OR_ERROR_OBJ
#define PYDOC_BUILTIN_SHADER_DESCRIPTION
PyObject * BPyGPUShader_CreatePyObject(GPUShader *shader, bool is_builtin)
static const PyC_StringEnumItems pygpu_shader_builtin_items[]
static PyMethodDef pygpu_shader__tp_methods[]
static PyObject * pygpu_shader_unbind(BPyGPUShader *)
static PyObject * pygpu_shader_uniform_block(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_program_get(BPyGPUShader *self, void *)
static PyObject * pygpu_shader_uniform_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_uniform_int(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_create_from_info(BPyGPUShader *, BPyGPUShaderCreateInfo *o)
static PyObject * pygpu_shader_name(BPyGPUShader *self, void *)
PyTypeObject BPyGPUShader_Type
static PyObject * pygpu_shader_bind(BPyGPUShader *self)
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)
PyObject * bpygpu_shader_init()
static PyObject * pygpu_shader_uniform_bool(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_image(BPyGPUShader *self, PyObject *args)
static const PyC_StringEnumItems pygpu_shader_config_items[]
static PyObject * pygpu_shader__tp_new(PyTypeObject *, PyObject *args, PyObject *kwds)
static void pygpu_shader__tp_dealloc(BPyGPUShader *self)
static PyObject * pygpu_shader_from_builtin(PyObject *, PyObject *args, PyObject *kwds)
static PyObject * pygpu_shader_attr_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_format_calc(BPyGPUShader *self, PyObject *)
static PyObject * pygpu_shader_uniform_sampler(BPyGPUShader *self, PyObject *args)
static PyMethodDef pygpu_shader_module__tp_methods[]
static PyObject * pygpu_shader_uniform_float(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_vector_float(BPyGPUShader *self, PyObject *args)
static PyObject * pygpu_shader_uniform_block_from_name(BPyGPUShader *self, PyObject *arg)
static PyObject * pygpu_shader_attrs_info_get(BPyGPUShader *self, PyObject *)
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 PyGetSetDef pygpu_shader__tp_getseters[]
static int pygpu_shader_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix)
const struct PyC_StringEnumItems pygpu_attrtype_items[]
struct BPyGPUShader BPyGPUShader
#define BPyGPUShaderCreateInfo_Check(v)
PyTypeObject BPyGPUTexture_Type
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)
int PyC_ParseStringEnum(PyObject *o, void *p)
const char * PyC_StringEnum_FindIDFromValue(const PyC_StringEnumItems *items, const int value)
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)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
#define PyTuple_SET_ITEMS(op_arg,...)
PyObject_VAR_HEAD GPUShaderCreateInfo * info
PyObject_HEAD GPUTexture * tex