2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2006 Blender Foundation.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): Benoit Bolsee.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/python/intern/gpu.c
29 * \ingroup pythonintern
31 * This file defines the 'gpu' module, used to get GLSL shader code and data
32 * from blender materials.
35 /* python redefines */
36 #ifdef _POSIX_C_SOURCE
37 #undef _POSIX_C_SOURCE
42 #include "GPU_material.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_image_types.h"
46 #include "DNA_material_types.h"
47 #include "DNA_lamp_types.h"
48 #include "DNA_object_types.h"
50 #include "DNA_customdata_types.h"
52 #include "BLI_listbase.h"
53 #include "BLI_utildefines.h"
55 #include "RNA_access.h"
61 #define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
63 PyDoc_STRVAR(M_gpu_doc,
64 "This module provides access to the GLSL shader.");
66 static struct PyModuleDef gpumodule = {
67 PyModuleDef_HEAD_INIT,
68 "gpu", /* name of module */
69 M_gpu_doc, /* module documentation */
70 -1, /* size of per-interpreter state of the module,
71 or -1 if the module keeps state in global variables. */
72 NULL, NULL, NULL, NULL, NULL
80 m = PyModule_Create(&gpumodule);
85 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
86 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
87 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
88 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
89 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
90 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE);
91 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
92 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
93 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
94 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNPERSMAT);
95 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNENERGY);
96 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCOL);
97 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
98 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
99 PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
101 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
102 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
103 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_2F);
104 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_3F);
105 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4F);
106 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_9F);
107 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
108 PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
110 PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
111 PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
112 PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
113 PY_MODULE_ADD_CONSTANT(m, CD_MCOL);
117 #define PY_DICT_ADD_STRING(d,s,f) \
118 val = PyUnicode_FromString(s->f); \
119 PyDict_SetItemString(d, #f, val); \
122 #define PY_DICT_ADD_LONG(d,s,f) \
123 val = PyLong_FromLong(s->f); \
124 PyDict_SetItemString(d, #f, val); \
127 #define PY_DICT_ADD_ID(d,s,f) \
128 RNA_id_pointer_create((struct ID*)s->f, &tptr); \
129 val = pyrna_struct_CreatePyObject(&tptr); \
130 PyDict_SetItemString(d, #f, val); \
133 #define PY_OBJ_ADD_ID(d,s,f) \
134 val = PyUnicode_FromString(&s->f->id.name[2]); \
135 PyObject_SetAttrString(d, #f, val); \
138 #define PY_OBJ_ADD_LONG(d,s,f) \
139 val = PyLong_FromLong(s->f); \
140 PyObject_SetAttrString(d, #f, val); \
143 #define PY_OBJ_ADD_STRING(d,s,f) \
144 val = PyUnicode_FromString(s->f); \
145 PyObject_SetAttrString(d, #f, val); \
148 static PyObject* GPU_export_shader(PyObject* UNUSED(self), PyObject *args, PyObject *kwds)
152 PyObject* as_pointer;
163 GPUShaderExport *shader;
164 GPUInputUniform *uniform;
165 GPUInputAttribute *attribute;
167 static const char *kwlist[] = {"scene", "material", NULL};
169 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO:export_shader", (char**)(kwlist), &pyscene, &pymat))
172 if (!strcmp(Py_TYPE(pyscene)->tp_name, "Scene") &&
173 (as_pointer = PyObject_GetAttrString(pyscene, "as_pointer")) != NULL &&
174 PyCallable_Check(as_pointer)) {
175 // must be a scene object
176 pointer = PyObject_CallObject(as_pointer, NULL);
178 PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
181 scene = (Scene*)PyLong_AsVoidPtr(pointer);
184 PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
188 PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type");
192 if (!strcmp(Py_TYPE(pymat)->tp_name, "Material") &&
193 (as_pointer = PyObject_GetAttrString(pymat, "as_pointer")) != NULL &&
194 PyCallable_Check(as_pointer)) {
195 // must be a material object
196 pointer = PyObject_CallObject(as_pointer, NULL);
198 PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
201 material = (Material*)PyLong_AsVoidPtr(pointer);
204 PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
208 PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type");
211 // we can call our internal function at last:
212 shader = GPU_shader_export(scene, material);
214 PyErr_SetString(PyExc_RuntimeError, "cannot export shader");
217 // build a dictionary
218 result = PyDict_New();
219 if (shader->fragment) {
220 PY_DICT_ADD_STRING(result,shader,fragment);
222 if (shader->vertex) {
223 PY_DICT_ADD_STRING(result,shader,vertex);
225 seq = PyList_New(BLI_countlist(&shader->uniforms));
226 for (i=0, uniform=shader->uniforms.first; uniform; uniform=uniform->next, i++) {
228 PY_DICT_ADD_STRING(dict,uniform,varname);
229 PY_DICT_ADD_LONG(dict,uniform,datatype);
230 PY_DICT_ADD_LONG(dict,uniform,type);
232 PY_DICT_ADD_ID(dict,uniform,lamp);
234 if (uniform->image) {
235 PY_DICT_ADD_ID(dict,uniform,image);
237 if (uniform->type == GPU_DYNAMIC_SAMPLER_2DBUFFER ||
238 uniform->type == GPU_DYNAMIC_SAMPLER_2DIMAGE ||
239 uniform->type == GPU_DYNAMIC_SAMPLER_2DSHADOW) {
240 PY_DICT_ADD_LONG(dict,uniform,texnumber);
242 if (uniform->texpixels) {
243 val = PyByteArray_FromStringAndSize((const char *)uniform->texpixels, uniform->texsize * 4);
244 PyDict_SetItemString(dict, "texpixels", val);
246 PY_DICT_ADD_LONG(dict,uniform,texsize);
248 PyList_SET_ITEM(seq, i, dict);
250 PyDict_SetItemString(result, "uniforms", seq);
253 seq = PyList_New(BLI_countlist(&shader->attributes));
254 for (i=0, attribute=shader->attributes.first; attribute; attribute=attribute->next, i++) {
256 PY_DICT_ADD_STRING(dict,attribute,varname);
257 PY_DICT_ADD_LONG(dict,attribute,datatype);
258 PY_DICT_ADD_LONG(dict,attribute,type);
259 PY_DICT_ADD_LONG(dict,attribute,number);
260 if (attribute->name) {
261 if (attribute->name[0] != 0) {
262 PY_DICT_ADD_STRING(dict,attribute,name);
264 val = PyLong_FromLong(0);
265 PyDict_SetItemString(dict, "name", val);
269 PyList_SET_ITEM(seq, i, dict);
271 PyDict_SetItemString(result, "attributes", seq);
274 GPU_free_shader_export(shader);
279 static PyMethodDef meth_export_shader[] = {{ "export_shader", (PyCFunction)GPU_export_shader, METH_VARARGS | METH_KEYWORDS,
280 "export_shader(scene,material)\n\n"
281 "Returns the GLSL shader that produces the visual effect of material in scene.\n\n"
282 ":return: Dictionary defining the shader, uniforms and attributes.\n"
285 PyObject* GPU_initPython(void)
287 PyObject* module = PyInit_gpu();
288 PyModule_AddObject(module, "export_shader", (PyObject *)PyCFunction_New(meth_export_shader, NULL));
289 PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);