forked from bartvdbraak/blender
GPU: add gpu python module with export_shader() function to export GLSL shader.
shader = gpu.export_shader(scene,material) Returns the GLSL shader that blender generates to produce the visual effect of material in scene for the purpose of reusing the shader in an external engine. This function is meant to be used in a material exporter so that the GLSL shader can be exported entirely. The return value is a dictionary containing the shader source code and all associated data. The full documentation is under sphinx. Warning: there has been an API between the patch and this commit: uniform['lamp'] and uniform['image'] now return python reference to ID block instead of ID name as before. The X3D exporter that uses this function must be adapted.
This commit is contained in:
parent
2b33c6b0b2
commit
01744abd81
531
doc/python_api/rst/gpu.rst
Normal file
531
doc/python_api/rst/gpu.rst
Normal file
@ -0,0 +1,531 @@
|
|||||||
|
|
||||||
|
GPU functions (gpu)
|
||||||
|
===================
|
||||||
|
|
||||||
|
*****
|
||||||
|
Intro
|
||||||
|
*****
|
||||||
|
|
||||||
|
Module to provide functions concerning the GPU implementation in Blender, in particular
|
||||||
|
the GLSL shaders that blender generates automatically to render materials in the 3D view
|
||||||
|
and in the game engine.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
The API provided by this module should be consider unstable. The data exposed by the API
|
||||||
|
are are closely related to Blender's internal GLSL code and may change if the GLSL code
|
||||||
|
is modified (e.g. new uniform type).
|
||||||
|
|
||||||
|
.. module:: gpu
|
||||||
|
|
||||||
|
*********
|
||||||
|
Constants
|
||||||
|
*********
|
||||||
|
|
||||||
|
--------------
|
||||||
|
GLSL data type
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. _data-type:
|
||||||
|
|
||||||
|
Type of GLSL data.
|
||||||
|
For shader uniforms, the data type determines which glUniform function
|
||||||
|
variant to use to send the uniform value to the GPU.
|
||||||
|
For vertex attributes, the data type determines which glVertexAttrib function
|
||||||
|
variant to use to send the vertex attribute to the GPU.
|
||||||
|
|
||||||
|
See export_shader_
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_1I
|
||||||
|
|
||||||
|
one integer
|
||||||
|
|
||||||
|
:value: 1
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_1F
|
||||||
|
|
||||||
|
one float
|
||||||
|
|
||||||
|
:value: 2
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_2F
|
||||||
|
|
||||||
|
two floats
|
||||||
|
|
||||||
|
:value: 3
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_3F
|
||||||
|
|
||||||
|
three floats
|
||||||
|
|
||||||
|
:value: 4
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_4F
|
||||||
|
|
||||||
|
four floats
|
||||||
|
|
||||||
|
:value: 5
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_9F
|
||||||
|
|
||||||
|
matrix 3x3 in column-major order
|
||||||
|
|
||||||
|
:value: 6
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_16F
|
||||||
|
|
||||||
|
matrix 4x4 in column-major order
|
||||||
|
|
||||||
|
:value: 7
|
||||||
|
|
||||||
|
.. data:: GPU_DATA_4UB
|
||||||
|
|
||||||
|
four unsigned byte
|
||||||
|
|
||||||
|
:value: 8
|
||||||
|
|
||||||
|
-----------------
|
||||||
|
GLSL uniform type
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. _uniform-type:
|
||||||
|
|
||||||
|
Constants that specify the type of uniform used in a GLSL shader.
|
||||||
|
The uniform type determines the data type, origin and method
|
||||||
|
of calculation used by Blender to compute the uniform value.
|
||||||
|
|
||||||
|
The calculation of some of the uniforms is based on matrices available in the scene:
|
||||||
|
|
||||||
|
.. _mat4_cam_to_world:
|
||||||
|
.. _mat4_world_to_cam:
|
||||||
|
|
||||||
|
*mat4_cam_to_world*
|
||||||
|
Model matrix of the camera. OpenGL 4x4 matrix that converts
|
||||||
|
camera local coordinates to world coordinates. In blender this is obtained from the
|
||||||
|
'matrix_world' attribute of the camera object.
|
||||||
|
|
||||||
|
Some uniform will need the *mat4_world_to_cam*
|
||||||
|
matrix computed as the inverse of this matrix.
|
||||||
|
|
||||||
|
.. _mat4_object_to_world:
|
||||||
|
.. _mat4_world_to_object:
|
||||||
|
|
||||||
|
*mat4_object_to_world*
|
||||||
|
Model matrix of the object that is being rendered. OpenGL 4x4 matric that converts
|
||||||
|
object local coordinates to world coordinates. In blender this is obtained from the
|
||||||
|
'matrix_world' attribute of the object.
|
||||||
|
|
||||||
|
Some uniform will need the *mat4_world_to_object* matrix, computed as the inverse of this matrix.
|
||||||
|
|
||||||
|
.. _mat4_lamp_to_world:
|
||||||
|
.. _mat4_world_to_lamp:
|
||||||
|
|
||||||
|
*mat4_lamp_to_world*
|
||||||
|
Model matrix of the lamp lighting the object. OpenGL 4x4 matrix that converts lamp
|
||||||
|
local coordinates to world coordinates. In blender this is obtained from the
|
||||||
|
'matrix_world' attribute of the lamp object.
|
||||||
|
|
||||||
|
Some uniform will need the *mat4_world_to_lamp* matrix
|
||||||
|
computed as the inverse of this matrix.
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_OBJECT_VIEWMAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts world coordinates to
|
||||||
|
camera coordinates (see mat4_world_to_cam_). Can be set once per frame.
|
||||||
|
There is at most one uniform of that type per shader.
|
||||||
|
|
||||||
|
:value: 1
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_OBJECT_MAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts object coordinates
|
||||||
|
to world coordinates (see mat4_object_to_world_). Must be set before drawing the object.
|
||||||
|
There is at most one uniform of that type per shader.
|
||||||
|
|
||||||
|
:value: 2
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_OBJECT_VIEWIMAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts coordinates
|
||||||
|
in camera space to world coordinates (see mat4_cam_to_world_).
|
||||||
|
Can be set once per frame.
|
||||||
|
There is at most one uniform of that type per shader.
|
||||||
|
|
||||||
|
:value: 3
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_OBJECT_IMAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts world coodinates
|
||||||
|
to object coordinates (see mat4_world_to_object_).
|
||||||
|
Must be set before drawing the object.
|
||||||
|
There is at most one uniform of that type per shader.
|
||||||
|
|
||||||
|
:value: 4
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_OBJECT_COLOR
|
||||||
|
|
||||||
|
The uniform is a vector of 4 float representing a RGB color + alpha defined at object level.
|
||||||
|
Each values between 0.0 and 1.0. In blender it corresponds to the 'color' attribute of the object.
|
||||||
|
Must be set before drawing the object.
|
||||||
|
There is at most one uniform of that type per shader.
|
||||||
|
|
||||||
|
:value: 5
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNVEC
|
||||||
|
|
||||||
|
The uniform is a vector of 3 float representing the direction of light in camera space.
|
||||||
|
In Blender, this is computed by
|
||||||
|
|
||||||
|
mat4_world_to_cam_ * (-vec3_lamp_Z_axis)
|
||||||
|
|
||||||
|
as the lamp Z axis points to the opposite direction of light.
|
||||||
|
The norm of the vector should be unity. Can be set once per frame.
|
||||||
|
There is one uniform of that type per lamp lighting the material.
|
||||||
|
|
||||||
|
:value: 6
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNCO
|
||||||
|
|
||||||
|
The uniform is a vector of 3 float representing the position of the light in camera space.
|
||||||
|
Computed as
|
||||||
|
|
||||||
|
mat4_world_to_cam_ * vec3_lamp_pos
|
||||||
|
|
||||||
|
Can be set once per frame.
|
||||||
|
There is one uniform of that type per lamp lighting the material.
|
||||||
|
|
||||||
|
:value: 7
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNIMAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts vector in camera space to lamp space.
|
||||||
|
Computed as
|
||||||
|
|
||||||
|
mat4_world_to_lamp_ * mat4_cam_to_world_
|
||||||
|
|
||||||
|
Can be set once per frame.
|
||||||
|
There is one uniform of that type per lamp lighting the material.
|
||||||
|
|
||||||
|
:value: 8
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNPERSMAT
|
||||||
|
|
||||||
|
The uniform is a 4x4 GL matrix that converts a vector in camera space to shadow buffer depth space.
|
||||||
|
Computed as
|
||||||
|
|
||||||
|
mat4_perspective_to_depth_ * mat4_lamp_to_perspective_ * mat4_world_to_lamp_ * mat4_cam_to_world_.
|
||||||
|
|
||||||
|
.. _mat4_perspective_to_depth:
|
||||||
|
|
||||||
|
*mat4_perspective_to_depth* is a fixed matrix defined as follow::
|
||||||
|
|
||||||
|
0.5 0.0 0.0 0.5
|
||||||
|
0.0 0.5 0.0 0.5
|
||||||
|
0.0 0.0 0.5 0.5
|
||||||
|
0.0 0.0 0.0 1.0
|
||||||
|
|
||||||
|
This uniform can be set once per frame. There is one uniform of that type per lamp casting shadow in the scene.
|
||||||
|
|
||||||
|
:value: 9
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNENERGY
|
||||||
|
|
||||||
|
The uniform is a single float representing the lamp energy. In blender it corresponds
|
||||||
|
to the 'energy' attribute of the lamp data block.
|
||||||
|
There is one uniform of that type per lamp lighting the material.
|
||||||
|
|
||||||
|
:value: 10
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_LAMP_DYNCOL
|
||||||
|
|
||||||
|
The uniform is a vector of 3 float representing the lamp color.
|
||||||
|
Color elements are between 0.0 and 1.0. In blender it corresponds
|
||||||
|
to the 'color' attribute of the lamp data block.
|
||||||
|
There is one uniform of that type per lamp lighting the material.
|
||||||
|
|
||||||
|
:value: 11
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_SAMPLER_2DBUFFER
|
||||||
|
|
||||||
|
The uniform is an integer representing an internal texture used for certain effect
|
||||||
|
(color band, etc).
|
||||||
|
|
||||||
|
:value: 12
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_SAMPLER_2DIMAGE
|
||||||
|
|
||||||
|
The uniform is an integer representing a texture loaded from an image file.
|
||||||
|
|
||||||
|
:value: 13
|
||||||
|
|
||||||
|
.. data:: GPU_DYNAMIC_SAMPLER_2DSHADOW
|
||||||
|
|
||||||
|
The uniform is an integer representing a shadow buffer corresponding to a lamp
|
||||||
|
casting shadow.
|
||||||
|
|
||||||
|
:value: 14
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
GLSL attribute type
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
.. _attribute-type:
|
||||||
|
|
||||||
|
Type of the vertex attribute used in the GLSL shader. Determines the mesh custom data
|
||||||
|
layer that contains the vertex attribute.
|
||||||
|
|
||||||
|
.. data:: CD_MTFACE
|
||||||
|
|
||||||
|
Vertex attribute is a UV layer. Data type is vector of 2 float.
|
||||||
|
|
||||||
|
There can be more than one attribute of that type, they are differenciated by name.
|
||||||
|
In blender, you can retrieve the attribute data with:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
mesh.uv_textures[attribute['name']]
|
||||||
|
|
||||||
|
:value: 5
|
||||||
|
|
||||||
|
.. data:: CD_MCOL
|
||||||
|
|
||||||
|
Vertex attribute is color layer. Data type is vector 4 unsigned byte (RGBA).
|
||||||
|
|
||||||
|
There can be more than one attribute of that type, they are differenciated by name.
|
||||||
|
In blender you can retrieve the attribute data with:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
mesh.vertex_colors[attribute['name']]
|
||||||
|
|
||||||
|
:value: 6
|
||||||
|
|
||||||
|
.. data:: CD_ORCO
|
||||||
|
|
||||||
|
Vertex attribute is original coordinates. Data type is vector 3 float.
|
||||||
|
|
||||||
|
There can be only 1 attribute of that type per shader.
|
||||||
|
In blender you can retrieve the attribute data with:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
mesh.vertices
|
||||||
|
|
||||||
|
:value: 14
|
||||||
|
|
||||||
|
.. data:: CD_TANGENT
|
||||||
|
|
||||||
|
Vertex attribute is the tangent vector. Data type is vector 4 float.
|
||||||
|
|
||||||
|
There can be only 1 attribute of that type per shader.
|
||||||
|
There is currently no way to retrieve this attribute data via the RNA API but a standalone
|
||||||
|
C function to compute the tangent layer from the other layers can be obtained from
|
||||||
|
blender.org.
|
||||||
|
|
||||||
|
:value: 18
|
||||||
|
|
||||||
|
*********
|
||||||
|
Functions
|
||||||
|
*********
|
||||||
|
|
||||||
|
.. _export_shader:
|
||||||
|
|
||||||
|
.. function:: export_shader(scene,material)
|
||||||
|
|
||||||
|
Extracts the GLSL shader producing the visual effect of material in scene for the purpose of
|
||||||
|
reusing the shader in an external engine. This function is meant to be used in material exporter
|
||||||
|
so that the GLSL shader can be exported entirely. The return value is a dictionary containing the
|
||||||
|
shader source code and all associated data.
|
||||||
|
|
||||||
|
:arg scene: the scene in which the material in rendered.
|
||||||
|
:type scene: :class:`bpy.types.Scene`
|
||||||
|
:arg material: the material that you want to export the GLSL shader
|
||||||
|
:type material: :class:`bpy.types.Material`
|
||||||
|
:return: the shader source code and all associated data in a dictionary
|
||||||
|
:rtype: dictionary
|
||||||
|
|
||||||
|
The dictionary contains the following elements:
|
||||||
|
|
||||||
|
* ['fragment'] : string
|
||||||
|
fragment shader source code.
|
||||||
|
|
||||||
|
* ['vertex'] : string
|
||||||
|
vertex shader source code.
|
||||||
|
|
||||||
|
* ['uniforms'] : sequence
|
||||||
|
list of uniforms used in fragment shader, can be empty list. Each element of the
|
||||||
|
sequence is a dictionary with the following elements:
|
||||||
|
|
||||||
|
* ['varname'] : string
|
||||||
|
name of the uniform in the fragment shader. Always of the form 'unf<number>'.
|
||||||
|
|
||||||
|
* ['datatype'] : integer
|
||||||
|
data type of the uniform variable. Can be one of the following:
|
||||||
|
|
||||||
|
* :data:`gpu.GPU_DATA_1I` : use glUniform1i
|
||||||
|
* :data:`gpu.GPU_DATA_1F` : use glUniform1fv
|
||||||
|
* :data:`gpu.GPU_DATA_2F` : use glUniform2fv
|
||||||
|
* :data:`gpu.GPU_DATA_3F` : use glUniform3fv
|
||||||
|
* :data:`gpu.GPU_DATA_4F` : use glUniform4fv
|
||||||
|
* :data:`gpu.GPU_DATA_9F` : use glUniformMatrix3fv
|
||||||
|
* :data:`gpu.GPU_DATA_16F` : use glUniformMatrix4fv
|
||||||
|
|
||||||
|
* ['type'] : integer
|
||||||
|
type of uniform, determines the origin and method of calculation. See uniform-type_.
|
||||||
|
Depending on the type, more elements will be be present.
|
||||||
|
|
||||||
|
* ['lamp'] : :class:`bpy.types.Object`
|
||||||
|
Reference to the lamp object from which the uniforms value are extracted. Set for the following uniforms types:
|
||||||
|
|
||||||
|
.. hlist::
|
||||||
|
:columns: 3
|
||||||
|
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL`
|
||||||
|
* :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
* The uniforms :data:`gpu.GPU_DYNAMIC_LAMP_DYNVEC`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNCO`, :data:`gpu.GPU_DYNAMIC_LAMP_DYNIMAT` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT`
|
||||||
|
refer to the lamp object position and orientation, both of can be derived from the object world matrix:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
obmat = uniform['lamp'].matrix_world
|
||||||
|
|
||||||
|
where obmat is the mat4_lamp_to_world_ matrix of the lamp as a 2 dimensional array,
|
||||||
|
the lamp world location location is in obmat[3].
|
||||||
|
|
||||||
|
* The uniform types :data:`gpu.GPU_DYNAMIC_LAMP_DYNENERGY` and :data:`gpu.GPU_DYNAMIC_LAMP_DYNCOL` refer to the lamp data bloc that you get from:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
la = uniform['lamp'].data
|
||||||
|
|
||||||
|
from which you get la.energy and la.color
|
||||||
|
|
||||||
|
* Lamp duplication is not supported: if you have duplicated lamps in your scene
|
||||||
|
(i.e. lamp that are instantiated by dupligroup, etc), this element will only
|
||||||
|
give you a reference to the orignal lamp and you will not know which instance
|
||||||
|
of the lamp it is refering too. You can still handle that case in the exporter
|
||||||
|
by distributing the uniforms amongst the duplicated lamps.
|
||||||
|
|
||||||
|
* ['image'] : :class:`bpy.types.Image`
|
||||||
|
Reference to the image databloc. Set for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE`. You can get the image data from:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# full path to image file
|
||||||
|
uniform['image'].filepath
|
||||||
|
# image size as a 2-dimensional array of int
|
||||||
|
uniform['image'].size
|
||||||
|
|
||||||
|
* ['texnumber'] : integer
|
||||||
|
Channel number to which the texture is bound when drawing the object.
|
||||||
|
Set for uniform types :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`, :data:`gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE` and :data:`gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW`.
|
||||||
|
|
||||||
|
This is provided for information only: when reusing the shader outside blencer,
|
||||||
|
you are free to assign the textures to the channel of your choice and to pass
|
||||||
|
that number channel to the GPU in the uniform.
|
||||||
|
|
||||||
|
* ['texpixels'] : byte array
|
||||||
|
texture data for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`. Although
|
||||||
|
the corresponding uniform is a 2D sampler, the texture is always a 1D texture
|
||||||
|
of n x 1 pixel. The texture size n is provided in ['texsize'] element.
|
||||||
|
These texture are only used for computer generated texture (colorband, etc).
|
||||||
|
The texture data is provided so that you can make a real image out of it in the
|
||||||
|
exporter.
|
||||||
|
|
||||||
|
* ['texsize'] : integer
|
||||||
|
horizontal size of texture for uniform type :data:`gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER`.
|
||||||
|
The texture data is in ['texpixels'].
|
||||||
|
|
||||||
|
* ['attributes'] : sequence
|
||||||
|
list of attributes used in vertex shader, can be empty. Blender doesn't use
|
||||||
|
standard attributes except for vertex position and normal. All other vertex
|
||||||
|
attributes must be passed using the generic glVertexAttrib functions.
|
||||||
|
The attribute data can be found in the derived mesh custom data using RNA.
|
||||||
|
Each element of the sequence is a dictionary containing the following elements:
|
||||||
|
|
||||||
|
* ['varname'] : string
|
||||||
|
name of the uniform in the vertex shader. Always of the form 'att<number>'.
|
||||||
|
|
||||||
|
* ['datatype'] : integer
|
||||||
|
data type of vertex attribute, can be one of the following:
|
||||||
|
|
||||||
|
* :data:`gpu.GPU_DATA_2F` : use glVertexAttrib2fv
|
||||||
|
* :data:`gpu.GPU_DATA_3F` : use glVertexAttrib3fv
|
||||||
|
* :data:`gpu.GPU_DATA_4F` : use glVertexAttrib4fv
|
||||||
|
* :data:`gpu.GPU_DATA_4UB` : use glVertexAttrib4ubv
|
||||||
|
|
||||||
|
* ['number'] : integer
|
||||||
|
generic attribute number. This is provided for information only. Blender
|
||||||
|
doesn't use glBindAttribLocation to place generic attributes at specific location,
|
||||||
|
it lets the shader compiler place the attributes automatically and query the
|
||||||
|
placement with glGetAttribLocation. The result of this placement is returned in
|
||||||
|
this element.
|
||||||
|
|
||||||
|
When using this shader in a render engine, you should either use
|
||||||
|
glBindAttribLocation to force the attribute at this location or use
|
||||||
|
glGetAttribLocation to get the placement chosen by the compiler of your GPU.
|
||||||
|
|
||||||
|
* ['type'] : integer
|
||||||
|
type of the mesh custom data from which the vertex attribute is loaded.
|
||||||
|
See attribute-type_.
|
||||||
|
|
||||||
|
* ['name'] : string or integer
|
||||||
|
custom data layer name, used for attribute type :data:`gpu.CD_MTFACE` and :data:`gpu.CD_MCOL`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import gpu
|
||||||
|
# get GLSL shader of material Mat.001 in scene Scene.001
|
||||||
|
scene = bpy.data.scenes['Scene.001']
|
||||||
|
material = bpy.data.materials['Mat.001']
|
||||||
|
shader = gpu.export_shader(scene,material)
|
||||||
|
# scan the uniform list and find the images used in the shader
|
||||||
|
for uniform in shader['uniforms']:
|
||||||
|
if uniform['type'] == gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE:
|
||||||
|
print("uniform {0} is using image {1}".format(uniform['varname'], uniform['image'].filepath))
|
||||||
|
# scan the attribute list and find the UV layer used in the shader
|
||||||
|
for attribute in shader['attributes']:
|
||||||
|
if attribute['type'] == gpu.CD_MTFACE:
|
||||||
|
print("attribute {0} is using UV layer {1}".format(attribute['varname'], attribute['name']))
|
||||||
|
|
||||||
|
*****
|
||||||
|
Notes
|
||||||
|
*****
|
||||||
|
|
||||||
|
.. _mat4_lamp_to_perspective:
|
||||||
|
|
||||||
|
1. Calculation of the *mat4_lamp_to_perspective* matrix for a spot lamp.
|
||||||
|
|
||||||
|
The following pseudo code shows how the *mat4_lamp_to_perspective* matrix is computed
|
||||||
|
in blender for uniforms of :data:`gpu.GPU_DYNAMIC_LAMP_DYNPERSMAT` type::
|
||||||
|
|
||||||
|
#Get the lamp datablock with:
|
||||||
|
lamp=bpy.data.objects[uniform['lamp']].data
|
||||||
|
|
||||||
|
#Compute the projection matrix:
|
||||||
|
# You will need these lamp attributes:
|
||||||
|
# lamp.clipsta : near clip plane in world unit
|
||||||
|
# lamp.clipend : far clip plane in world unit
|
||||||
|
# lamp.spotsize : angle in degree of the spot light
|
||||||
|
|
||||||
|
#The size of the projection plane is computed with the usual formula:
|
||||||
|
wsize = lamp.clista * tan(lamp.spotsize/2)
|
||||||
|
|
||||||
|
#And the projection matrix:
|
||||||
|
mat4_lamp_to_perspective = glFrustum(-wsize,wsize,-wsize,wsize,lamp.clista,lamp.clipend)
|
||||||
|
|
||||||
|
2. Creation of the shadow map for a spot lamp.
|
||||||
|
|
||||||
|
The shadow map is the depth buffer of a render performed by placing the camera at the
|
||||||
|
spot light position. The size of the shadow map is given by the attribute lamp.bufsize :
|
||||||
|
shadow map size in pixel, same size in both dimensions.
|
@ -126,6 +126,7 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
|
|||||||
int GPU_texture_target(GPUTexture *tex);
|
int GPU_texture_target(GPUTexture *tex);
|
||||||
int GPU_texture_opengl_width(GPUTexture *tex);
|
int GPU_texture_opengl_width(GPUTexture *tex);
|
||||||
int GPU_texture_opengl_height(GPUTexture *tex);
|
int GPU_texture_opengl_height(GPUTexture *tex);
|
||||||
|
int GPU_texture_opengl_bindcode(GPUTexture *tex);
|
||||||
|
|
||||||
/* GPU Framebuffer
|
/* GPU Framebuffer
|
||||||
- this is a wrapper for an OpenGL framebuffer object (FBO). in practice
|
- this is a wrapper for an OpenGL framebuffer object (FBO). in practice
|
||||||
@ -179,6 +180,7 @@ typedef struct GPUVertexAttribs {
|
|||||||
int type;
|
int type;
|
||||||
int glindex;
|
int glindex;
|
||||||
int gltexco;
|
int gltexco;
|
||||||
|
int attribid;
|
||||||
char name[32];
|
char name[32];
|
||||||
} layer[GPU_MAX_ATTRIB];
|
} layer[GPU_MAX_ATTRIB];
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
#ifndef __GPU_MATERIAL__
|
#ifndef __GPU_MATERIAL__
|
||||||
#define __GPU_MATERIAL__
|
#define __GPU_MATERIAL__
|
||||||
|
|
||||||
|
#include "DNA_listBase.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -46,6 +48,7 @@ struct ImageUser;
|
|||||||
struct Material;
|
struct Material;
|
||||||
struct Object;
|
struct Object;
|
||||||
struct Lamp;
|
struct Lamp;
|
||||||
|
struct Image;
|
||||||
struct bNode;
|
struct bNode;
|
||||||
struct LinkNode;
|
struct LinkNode;
|
||||||
struct Scene;
|
struct Scene;
|
||||||
@ -72,7 +75,6 @@ typedef enum GPUType {
|
|||||||
GPU_VEC4 = 4,
|
GPU_VEC4 = 4,
|
||||||
GPU_MAT3 = 9,
|
GPU_MAT3 = 9,
|
||||||
GPU_MAT4 = 16,
|
GPU_MAT4 = 16,
|
||||||
GPU_TEX1D = 1001,
|
|
||||||
GPU_TEX2D = 1002,
|
GPU_TEX2D = 1002,
|
||||||
GPU_SHADOW2D = 1003,
|
GPU_SHADOW2D = 1003,
|
||||||
GPU_ATTRIB = 3001
|
GPU_ATTRIB = 3001
|
||||||
@ -107,10 +109,10 @@ typedef struct GPUNodeStack {
|
|||||||
|
|
||||||
GPUNodeLink *GPU_attribute(int type, const char *name);
|
GPUNodeLink *GPU_attribute(int type, const char *name);
|
||||||
GPUNodeLink *GPU_uniform(float *num);
|
GPUNodeLink *GPU_uniform(float *num);
|
||||||
GPUNodeLink *GPU_dynamic_uniform(float *num);
|
GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data);
|
||||||
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
|
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
|
||||||
GPUNodeLink *GPU_texture(int size, float *pixels);
|
GPUNodeLink *GPU_texture(int size, float *pixels);
|
||||||
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex);
|
GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data);
|
||||||
GPUNodeLink *GPU_socket(GPUNodeStack *sock);
|
GPUNodeLink *GPU_socket(GPUNodeStack *sock);
|
||||||
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
|
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
|
||||||
|
|
||||||
@ -153,6 +155,72 @@ typedef struct GPUShadeResult {
|
|||||||
void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi);
|
void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi);
|
||||||
void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
|
void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
|
||||||
|
|
||||||
|
/* Export GLSL shader */
|
||||||
|
|
||||||
|
typedef enum GPUDynamicType {
|
||||||
|
GPU_DYNAMIC_NONE = 0,
|
||||||
|
GPU_DYNAMIC_OBJECT_VIEWMAT = 1,
|
||||||
|
GPU_DYNAMIC_OBJECT_MAT = 2,
|
||||||
|
GPU_DYNAMIC_OBJECT_VIEWIMAT = 3,
|
||||||
|
GPU_DYNAMIC_OBJECT_IMAT = 4,
|
||||||
|
GPU_DYNAMIC_OBJECT_COLOR = 5,
|
||||||
|
GPU_DYNAMIC_LAMP_FIRST = 6,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNVEC = 6,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNCO = 7,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNIMAT = 8,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNPERSMAT = 9,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNENERGY = 10,
|
||||||
|
GPU_DYNAMIC_LAMP_DYNCOL = 11,
|
||||||
|
GPU_DYNAMIC_LAMP_LAST = 11,
|
||||||
|
GPU_DYNAMIC_SAMPLER_2DBUFFER = 12,
|
||||||
|
GPU_DYNAMIC_SAMPLER_2DIMAGE = 13,
|
||||||
|
GPU_DYNAMIC_SAMPLER_2DSHADOW = 14,
|
||||||
|
} GPUDynamicType;
|
||||||
|
|
||||||
|
typedef enum GPUDataType {
|
||||||
|
GPU_DATA_NONE = 0,
|
||||||
|
GPU_DATA_1I = 1, // 1 integer
|
||||||
|
GPU_DATA_1F = 2,
|
||||||
|
GPU_DATA_2F = 3,
|
||||||
|
GPU_DATA_3F = 4,
|
||||||
|
GPU_DATA_4F = 5,
|
||||||
|
GPU_DATA_9F = 6,
|
||||||
|
GPU_DATA_16F = 7,
|
||||||
|
GPU_DATA_4UB = 8,
|
||||||
|
} GPUDataType;
|
||||||
|
|
||||||
|
/* this structure gives information of each uniform found in the shader */
|
||||||
|
typedef struct GPUInputUniform {
|
||||||
|
struct GPUInputUniform *next, *prev;
|
||||||
|
char varname[32]; /* name of uniform in shader */
|
||||||
|
GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
|
||||||
|
GPUDataType datatype; /* type of uniform data */
|
||||||
|
struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
|
||||||
|
struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
|
||||||
|
int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
|
||||||
|
unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
|
||||||
|
int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
|
||||||
|
} GPUInputUniform;
|
||||||
|
|
||||||
|
typedef struct GPUInputAttribute {
|
||||||
|
struct GPUInputAttribute *next, *prev;
|
||||||
|
char varname[32]; /* name of attribute in shader */
|
||||||
|
int type; /* from CustomData.type, data type derives from it */
|
||||||
|
GPUDataType datatype; /* type of attribute data */
|
||||||
|
const char *name; /* layer name */
|
||||||
|
int number; /* generic attribute number */
|
||||||
|
} GPUInputAttribute;
|
||||||
|
|
||||||
|
typedef struct GPUShaderExport {
|
||||||
|
ListBase uniforms;
|
||||||
|
ListBase attributes;
|
||||||
|
char *vertex;
|
||||||
|
char *fragment;
|
||||||
|
} GPUShaderExport;
|
||||||
|
|
||||||
|
GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
|
||||||
|
void GPU_free_shader_export(GPUShaderExport *shader);
|
||||||
|
|
||||||
/* Lamps */
|
/* Lamps */
|
||||||
|
|
||||||
GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
|
GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
|
||||||
|
@ -64,101 +64,9 @@ extern char datatoc_gpu_shader_vertex_glsl[];
|
|||||||
|
|
||||||
/* structs and defines */
|
/* structs and defines */
|
||||||
|
|
||||||
typedef enum GPUDataSource {
|
|
||||||
GPU_SOURCE_VEC_UNIFORM,
|
|
||||||
GPU_SOURCE_BUILTIN,
|
|
||||||
GPU_SOURCE_TEX_PIXEL,
|
|
||||||
GPU_SOURCE_TEX,
|
|
||||||
GPU_SOURCE_ATTRIB
|
|
||||||
} GPUDataSource;
|
|
||||||
|
|
||||||
static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
|
static const char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
|
||||||
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
|
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
|
||||||
|
|
||||||
struct GPUNode {
|
|
||||||
struct GPUNode *next, *prev;
|
|
||||||
|
|
||||||
const char *name;
|
|
||||||
int tag;
|
|
||||||
|
|
||||||
ListBase inputs;
|
|
||||||
ListBase outputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GPUNodeLink {
|
|
||||||
GPUNodeStack *socket;
|
|
||||||
|
|
||||||
int attribtype;
|
|
||||||
const char *attribname;
|
|
||||||
|
|
||||||
int image;
|
|
||||||
|
|
||||||
int texture;
|
|
||||||
int texturesize;
|
|
||||||
|
|
||||||
void *ptr1, *ptr2;
|
|
||||||
|
|
||||||
int dynamic;
|
|
||||||
|
|
||||||
int type;
|
|
||||||
int users;
|
|
||||||
|
|
||||||
GPUTexture *dynamictex;
|
|
||||||
|
|
||||||
GPUBuiltin builtin;
|
|
||||||
|
|
||||||
struct GPUOutput *output;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct GPUOutput {
|
|
||||||
struct GPUOutput *next, *prev;
|
|
||||||
|
|
||||||
GPUNode *node;
|
|
||||||
int type; /* data type = length of vector/matrix */
|
|
||||||
GPUNodeLink *link; /* output link */
|
|
||||||
int id; /* unique id as created by code generator */
|
|
||||||
} GPUOutput;
|
|
||||||
|
|
||||||
typedef struct GPUInput {
|
|
||||||
struct GPUInput *next, *prev;
|
|
||||||
|
|
||||||
GPUNode *node;
|
|
||||||
|
|
||||||
int type; /* datatype */
|
|
||||||
int source; /* data source */
|
|
||||||
|
|
||||||
int id; /* unique id as created by code generator */
|
|
||||||
int texid; /* number for multitexture */
|
|
||||||
int attribid; /* id for vertex attributes */
|
|
||||||
int bindtex; /* input is responsible for binding the texture? */
|
|
||||||
int definetex; /* input is responsible for defining the pixel? */
|
|
||||||
int textarget; /* GL_TEXTURE_* */
|
|
||||||
int textype; /* datatype */
|
|
||||||
|
|
||||||
struct Image *ima; /* image */
|
|
||||||
struct ImageUser *iuser;/* image user */
|
|
||||||
float *dynamicvec; /* vector data in case it is dynamic */
|
|
||||||
GPUTexture *tex; /* input texture, only set at runtime */
|
|
||||||
int shaderloc; /* id from opengl */
|
|
||||||
char shadername[32]; /* name in shader */
|
|
||||||
|
|
||||||
float vec[16]; /* vector data */
|
|
||||||
GPUNodeLink *link;
|
|
||||||
int dynamictex; /* dynamic? */
|
|
||||||
int attribtype; /* attribute type */
|
|
||||||
char attribname[32]; /* attribute name */
|
|
||||||
int attribfirst; /* this is the first one that is bound */
|
|
||||||
GPUBuiltin builtin; /* builtin uniform */
|
|
||||||
} GPUInput;
|
|
||||||
|
|
||||||
struct GPUPass {
|
|
||||||
struct GPUPass *next, *prev;
|
|
||||||
|
|
||||||
ListBase inputs;
|
|
||||||
struct GPUOutput *output;
|
|
||||||
struct GPUShader *shader;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* GLSL code parsing for finding function definitions.
|
/* GLSL code parsing for finding function definitions.
|
||||||
* These are stored in a hash for lookup when creating a material. */
|
* These are stored in a hash for lookup when creating a material. */
|
||||||
|
|
||||||
@ -245,8 +153,6 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
|
|||||||
|
|
||||||
if(!type && gpu_str_prefix(code, "sampler2DShadow"))
|
if(!type && gpu_str_prefix(code, "sampler2DShadow"))
|
||||||
type= GPU_SHADOW2D;
|
type= GPU_SHADOW2D;
|
||||||
if(!type && gpu_str_prefix(code, "sampler1D"))
|
|
||||||
type= GPU_TEX1D;
|
|
||||||
if(!type && gpu_str_prefix(code, "sampler2D"))
|
if(!type && gpu_str_prefix(code, "sampler2D"))
|
||||||
type= GPU_TEX2D;
|
type= GPU_TEX2D;
|
||||||
|
|
||||||
@ -298,9 +204,7 @@ static char *gpu_generate_function_prototyps(GHash *hash)
|
|||||||
else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
|
else if(function->paramqual[a] == FUNCTION_QUAL_INOUT)
|
||||||
BLI_dynstr_append(ds, "inout ");
|
BLI_dynstr_append(ds, "inout ");
|
||||||
|
|
||||||
if(function->paramtype[a] == GPU_TEX1D)
|
if(function->paramtype[a] == GPU_TEX2D)
|
||||||
BLI_dynstr_append(ds, "sampler1D");
|
|
||||||
else if(function->paramtype[a] == GPU_TEX2D)
|
|
||||||
BLI_dynstr_append(ds, "sampler2D");
|
BLI_dynstr_append(ds, "sampler2D");
|
||||||
else if(function->paramtype[a] == GPU_SHADOW2D)
|
else if(function->paramtype[a] == GPU_SHADOW2D)
|
||||||
BLI_dynstr_append(ds, "sampler2DShadow");
|
BLI_dynstr_append(ds, "sampler2DShadow");
|
||||||
@ -542,7 +446,6 @@ static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
|
|||||||
/* create exactly one sampler for each texture */
|
/* create exactly one sampler for each texture */
|
||||||
if (codegen_input_has_texture(input) && input->bindtex)
|
if (codegen_input_has_texture(input) && input->bindtex)
|
||||||
BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
|
BLI_dynstr_appendf(ds, "uniform %s samp%d;\n",
|
||||||
(input->textype == GPU_TEX1D)? "sampler1D":
|
|
||||||
(input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
|
(input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow",
|
||||||
input->texid);
|
input->texid);
|
||||||
}
|
}
|
||||||
@ -947,6 +850,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
|||||||
input->textarget = GL_TEXTURE_2D;
|
input->textarget = GL_TEXTURE_2D;
|
||||||
input->textype = type;
|
input->textype = type;
|
||||||
input->dynamictex = 1;
|
input->dynamictex = 1;
|
||||||
|
input->dynamicdata = link->ptr2;
|
||||||
MEM_freeN(link);
|
MEM_freeN(link);
|
||||||
}
|
}
|
||||||
else if(link->texture) {
|
else if(link->texture) {
|
||||||
@ -955,14 +859,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
|||||||
input->source = GPU_SOURCE_TEX;
|
input->source = GPU_SOURCE_TEX;
|
||||||
input->textype = type;
|
input->textype = type;
|
||||||
|
|
||||||
if (type == GPU_TEX1D) {
|
//input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
|
||||||
input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1, NULL);
|
input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
|
||||||
input->textarget = GL_TEXTURE_1D;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
|
|
||||||
input->textarget = GL_TEXTURE_2D;
|
input->textarget = GL_TEXTURE_2D;
|
||||||
}
|
|
||||||
|
|
||||||
MEM_freeN(link->ptr1);
|
MEM_freeN(link->ptr1);
|
||||||
MEM_freeN(link);
|
MEM_freeN(link);
|
||||||
@ -993,8 +892,11 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
|
|||||||
input->source = GPU_SOURCE_VEC_UNIFORM;
|
input->source = GPU_SOURCE_VEC_UNIFORM;
|
||||||
|
|
||||||
memcpy(input->vec, link->ptr1, type*sizeof(float));
|
memcpy(input->vec, link->ptr1, type*sizeof(float));
|
||||||
if(link->dynamic)
|
if(link->dynamic) {
|
||||||
input->dynamicvec= link->ptr1;
|
input->dynamicvec= link->ptr1;
|
||||||
|
input->dynamictype= link->dynamictype;
|
||||||
|
input->dynamicdata= link->ptr2;
|
||||||
|
}
|
||||||
MEM_freeN(link);
|
MEM_freeN(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1102,12 +1004,12 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a
|
|||||||
input->attribfirst = 1;
|
input->attribfirst = 1;
|
||||||
|
|
||||||
attribs->layer[a].type = input->attribtype;
|
attribs->layer[a].type = input->attribtype;
|
||||||
attribs->layer[a].glindex = input->attribid;
|
attribs->layer[a].attribid = input->attribid;
|
||||||
BLI_strncpy(attribs->layer[a].name, input->attribname,
|
BLI_strncpy(attribs->layer[a].name, input->attribname,
|
||||||
sizeof(attribs->layer[a].name));
|
sizeof(attribs->layer[a].name));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
input->attribid = attribs->layer[a].glindex;
|
input->attribid = attribs->layer[a].attribid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1148,13 +1050,15 @@ GPUNodeLink *GPU_uniform(float *num)
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUNodeLink *GPU_dynamic_uniform(float *num)
|
GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
|
||||||
{
|
{
|
||||||
GPUNodeLink *link = GPU_node_link_create(0);
|
GPUNodeLink *link = GPU_node_link_create(0);
|
||||||
|
|
||||||
link->ptr1= num;
|
link->ptr1= num;
|
||||||
link->ptr2= NULL;
|
link->ptr2= data;
|
||||||
link->dynamic= 1;
|
link->dynamic= 1;
|
||||||
|
link->dynamictype = dynamictype;
|
||||||
|
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
@ -1181,12 +1085,14 @@ GPUNodeLink *GPU_texture(int size, float *pixels)
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex)
|
GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
|
||||||
{
|
{
|
||||||
GPUNodeLink *link = GPU_node_link_create(0);
|
GPUNodeLink *link = GPU_node_link_create(0);
|
||||||
|
|
||||||
link->dynamic = 1;
|
link->dynamic = 1;
|
||||||
link->dynamictex = tex;
|
link->dynamictex = tex;
|
||||||
|
link->dynamictype = dynamictype;
|
||||||
|
link->ptr2 = data;
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
@ -1389,8 +1295,6 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
|
|||||||
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
|
fragmentcode = code_generate_fragment(nodes, outlink->output, name);
|
||||||
vertexcode = code_generate_vertex(nodes);
|
vertexcode = code_generate_vertex(nodes);
|
||||||
shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
|
shader = GPU_shader_create(vertexcode, fragmentcode, datatoc_gpu_shader_material_glsl); /*FUNCTION_LIB);*/
|
||||||
MEM_freeN(fragmentcode);
|
|
||||||
MEM_freeN(vertexcode);
|
|
||||||
|
|
||||||
/* failed? */
|
/* failed? */
|
||||||
if (!shader) {
|
if (!shader) {
|
||||||
@ -1405,6 +1309,9 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
|
|||||||
|
|
||||||
pass->output = outlink->output;
|
pass->output = outlink->output;
|
||||||
pass->shader = shader;
|
pass->shader = shader;
|
||||||
|
pass->fragmentcode = fragmentcode;
|
||||||
|
pass->vertexcode = vertexcode;
|
||||||
|
pass->libcode = datatoc_gpu_shader_material_glsl;
|
||||||
|
|
||||||
/* extract dynamic inputs and throw away nodes */
|
/* extract dynamic inputs and throw away nodes */
|
||||||
GPU_nodes_extract_dynamic_inputs(pass, nodes);
|
GPU_nodes_extract_dynamic_inputs(pass, nodes);
|
||||||
@ -1417,6 +1324,10 @@ void GPU_pass_free(GPUPass *pass)
|
|||||||
{
|
{
|
||||||
GPU_shader_free(pass->shader);
|
GPU_shader_free(pass->shader);
|
||||||
GPU_inputs_free(&pass->inputs);
|
GPU_inputs_free(&pass->inputs);
|
||||||
|
if (pass->fragmentcode)
|
||||||
|
MEM_freeN(pass->fragmentcode);
|
||||||
|
if (pass->vertexcode)
|
||||||
|
MEM_freeN(pass->vertexcode);
|
||||||
MEM_freeN(pass);
|
MEM_freeN(pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +39,15 @@
|
|||||||
#define __GPU_CODEGEN_H__
|
#define __GPU_CODEGEN_H__
|
||||||
|
|
||||||
#include "DNA_listBase.h"
|
#include "DNA_listBase.h"
|
||||||
|
#include "GPU_material.h"
|
||||||
|
#include "GL/glew.h"
|
||||||
|
|
||||||
struct ListBase;
|
struct ListBase;
|
||||||
struct GPUShader;
|
struct GPUShader;
|
||||||
struct GPUOutput;
|
struct GPUOutput;
|
||||||
struct GPUNode;
|
struct GPUNode;
|
||||||
struct GPUVertexAttribs;
|
struct GPUVertexAttribs;
|
||||||
|
struct GPUFrameBuffer;
|
||||||
|
|
||||||
#define MAX_FUNCTION_NAME 64
|
#define MAX_FUNCTION_NAME 64
|
||||||
#define MAX_PARAMETER 32
|
#define MAX_PARAMETER 32
|
||||||
@ -68,7 +71,105 @@ GPUFunction *GPU_lookup_function(const char *name);
|
|||||||
at the end if used.
|
at the end if used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct GPUPass;
|
typedef enum GPUDataSource {
|
||||||
|
GPU_SOURCE_VEC_UNIFORM,
|
||||||
|
GPU_SOURCE_BUILTIN,
|
||||||
|
GPU_SOURCE_TEX_PIXEL,
|
||||||
|
GPU_SOURCE_TEX,
|
||||||
|
GPU_SOURCE_ATTRIB
|
||||||
|
} GPUDataSource;
|
||||||
|
|
||||||
|
struct GPUNode {
|
||||||
|
struct GPUNode *next, *prev;
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
int tag;
|
||||||
|
|
||||||
|
ListBase inputs;
|
||||||
|
ListBase outputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GPUNodeLink {
|
||||||
|
GPUNodeStack *socket;
|
||||||
|
|
||||||
|
int attribtype;
|
||||||
|
const char *attribname;
|
||||||
|
|
||||||
|
int image;
|
||||||
|
|
||||||
|
int texture;
|
||||||
|
int texturesize;
|
||||||
|
|
||||||
|
void *ptr1, *ptr2;
|
||||||
|
|
||||||
|
int dynamic;
|
||||||
|
int dynamictype;
|
||||||
|
|
||||||
|
int type;
|
||||||
|
int users;
|
||||||
|
|
||||||
|
GPUTexture *dynamictex;
|
||||||
|
|
||||||
|
GPUBuiltin builtin;
|
||||||
|
|
||||||
|
struct GPUOutput *output;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct GPUOutput {
|
||||||
|
struct GPUOutput *next, *prev;
|
||||||
|
|
||||||
|
GPUNode *node;
|
||||||
|
int type; /* data type = length of vector/matrix */
|
||||||
|
GPUNodeLink *link; /* output link */
|
||||||
|
int id; /* unique id as created by code generator */
|
||||||
|
} GPUOutput;
|
||||||
|
|
||||||
|
typedef struct GPUInput {
|
||||||
|
struct GPUInput *next, *prev;
|
||||||
|
|
||||||
|
GPUNode *node;
|
||||||
|
|
||||||
|
int type; /* datatype */
|
||||||
|
int source; /* data source */
|
||||||
|
|
||||||
|
int id; /* unique id as created by code generator */
|
||||||
|
int texid; /* number for multitexture */
|
||||||
|
int attribid; /* id for vertex attributes */
|
||||||
|
int bindtex; /* input is responsible for binding the texture? */
|
||||||
|
int definetex; /* input is responsible for defining the pixel? */
|
||||||
|
int textarget; /* GL_TEXTURE_* */
|
||||||
|
int textype; /* datatype */
|
||||||
|
|
||||||
|
struct Image *ima; /* image */
|
||||||
|
struct ImageUser *iuser;/* image user */
|
||||||
|
float *dynamicvec; /* vector data in case it is dynamic */
|
||||||
|
int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */
|
||||||
|
void *dynamicdata; /* data source of the dynamic uniform */
|
||||||
|
GPUTexture *tex; /* input texture, only set at runtime */
|
||||||
|
int shaderloc; /* id from opengl */
|
||||||
|
char shadername[32]; /* name in shader */
|
||||||
|
|
||||||
|
float vec[16]; /* vector data */
|
||||||
|
GPUNodeLink *link;
|
||||||
|
int dynamictex; /* dynamic? */
|
||||||
|
int attribtype; /* attribute type */
|
||||||
|
char attribname[32]; /* attribute name */
|
||||||
|
int attribfirst; /* this is the first one that is bound */
|
||||||
|
GPUBuiltin builtin; /* builtin uniform */
|
||||||
|
} GPUInput;
|
||||||
|
|
||||||
|
struct GPUPass {
|
||||||
|
struct GPUPass *next, *prev;
|
||||||
|
|
||||||
|
ListBase inputs;
|
||||||
|
struct GPUOutput *output;
|
||||||
|
struct GPUShader *shader;
|
||||||
|
char *fragmentcode;
|
||||||
|
char *vertexcode;
|
||||||
|
const char *libcode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct GPUPass GPUPass;
|
typedef struct GPUPass GPUPass;
|
||||||
|
|
||||||
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
|
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
|
||||||
|
@ -423,7 +423,7 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
|
|||||||
|
|
||||||
if (tex->target != GL_TEXTURE_1D) {
|
if (tex->target != GL_TEXTURE_1D) {
|
||||||
/* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
|
/* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
|
||||||
GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
|
GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
|
||||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
|
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
|
||||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
|
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
|
||||||
|
|
||||||
@ -685,6 +685,11 @@ int GPU_texture_opengl_height(GPUTexture *tex)
|
|||||||
return tex->h;
|
return tex->h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GPU_texture_opengl_bindcode(GPUTexture *tex)
|
||||||
|
{
|
||||||
|
return tex->bindcode;
|
||||||
|
}
|
||||||
|
|
||||||
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
|
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
|
||||||
{
|
{
|
||||||
return tex->fb;
|
return tex->fb;
|
||||||
|
@ -175,7 +175,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
|
|||||||
* removed by the glsl compiler by dead code elimination */
|
* removed by the glsl compiler by dead code elimination */
|
||||||
|
|
||||||
for(a=0, b=0; a<attribs->totlayer; a++) {
|
for(a=0, b=0; a<attribs->totlayer; a++) {
|
||||||
sprintf(name, "att%d", attribs->layer[a].glindex);
|
sprintf(name, "att%d", attribs->layer[a].attribid);
|
||||||
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
|
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
|
||||||
|
|
||||||
if(attribs->layer[a].glindex >= 0) {
|
if(attribs->layer[a].glindex >= 0) {
|
||||||
@ -386,12 +386,12 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
|
|||||||
/* from get_lamp_visibility */
|
/* from get_lamp_visibility */
|
||||||
if(lamp->type==LA_SUN || lamp->type==LA_HEMI) {
|
if(lamp->type==LA_SUN || lamp->type==LA_HEMI) {
|
||||||
mat->dynproperty |= DYN_LAMP_VEC;
|
mat->dynproperty |= DYN_LAMP_VEC;
|
||||||
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac);
|
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
|
||||||
return visifac;
|
return visifac;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mat->dynproperty |= DYN_LAMP_CO;
|
mat->dynproperty |= DYN_LAMP_CO;
|
||||||
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac);
|
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
|
||||||
|
|
||||||
if(lamp->type==LA_AREA)
|
if(lamp->type==LA_AREA)
|
||||||
return visifac;
|
return visifac;
|
||||||
@ -426,11 +426,11 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
|
|||||||
if(lamp->type == LA_SPOT) {
|
if(lamp->type == LA_SPOT) {
|
||||||
if(lamp->mode & LA_SQUARE) {
|
if(lamp->mode & LA_SQUARE) {
|
||||||
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
|
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT;
|
||||||
GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr);
|
GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), GPU_dynamic_uniform((float*)lamp->dynimat, GPU_DYNAMIC_LAMP_DYNIMAT, lamp->ob), *lv, &inpr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mat->dynproperty |= DYN_LAMP_VEC;
|
mat->dynproperty |= DYN_LAMP_VEC;
|
||||||
GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr);
|
GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), *lv, &inpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac);
|
GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac);
|
||||||
@ -646,7 +646,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
|||||||
float area[4][4]= {{0.0f}}, areasize= 0.0f;
|
float area[4][4]= {{0.0f}}, areasize= 0.0f;
|
||||||
|
|
||||||
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
|
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
|
||||||
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), GPU_dynamic_uniform(lamp->dynvec), vn, GPU_uniform((float*)area),
|
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area),
|
||||||
GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
|
GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,13 +684,13 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
|||||||
|
|
||||||
GPU_link(mat, "test_shadowbuf",
|
GPU_link(mat, "test_shadowbuf",
|
||||||
GPU_builtin(GPU_VIEW_POSITION),
|
GPU_builtin(GPU_VIEW_POSITION),
|
||||||
GPU_dynamic_texture(lamp->tex),
|
GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
|
||||||
GPU_dynamic_uniform((float*)lamp->dynpersmat),
|
GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
|
||||||
GPU_uniform(&lamp->bias), inp, &shadfac);
|
GPU_uniform(&lamp->bias), inp, &shadfac);
|
||||||
|
|
||||||
if(lamp->mode & LA_ONLYSHADOW) {
|
if(lamp->mode & LA_ONLYSHADOW) {
|
||||||
GPU_link(mat, "shade_only_shadow", i, shadfac,
|
GPU_link(mat, "shade_only_shadow", i, shadfac,
|
||||||
GPU_dynamic_uniform(&lamp->dynenergy), &shadfac);
|
GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), &shadfac);
|
||||||
|
|
||||||
if(!(lamp->mode & LA_NO_DIFF))
|
if(!(lamp->mode & LA_NO_DIFF))
|
||||||
GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb,
|
GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb,
|
||||||
@ -719,7 +719,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
|||||||
if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
|
if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) {
|
||||||
if(!(lamp->mode & LA_NO_DIFF)) {
|
if(!(lamp->mode & LA_NO_DIFF)) {
|
||||||
GPUNodeLink *rgb;
|
GPUNodeLink *rgb;
|
||||||
GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb);
|
GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &rgb);
|
||||||
add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
|
add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -729,7 +729,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
|||||||
(GPU_link_changed(shi->spec) || ma->spec != 0.0f)) {
|
(GPU_link_changed(shi->spec) || ma->spec != 0.0f)) {
|
||||||
if(lamp->type == LA_HEMI) {
|
if(lamp->type == LA_HEMI) {
|
||||||
GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
|
GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t);
|
||||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
|
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
|
||||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -752,11 +752,11 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
|
|||||||
if(ma->mode & MA_RAMP_SPEC) {
|
if(ma->mode & MA_RAMP_SPEC) {
|
||||||
GPUNodeLink *spec;
|
GPUNodeLink *spec;
|
||||||
do_specular_ramp(shi, specfac, t, &spec);
|
do_specular_ramp(shi, specfac, t, &spec);
|
||||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol);
|
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), spec, &outcol);
|
||||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol);
|
GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), shi->specrgb, &outcol);
|
||||||
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1676,3 +1676,187 @@ int GPU_lamp_shadow_layer(GPULamp *lamp)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* export the GLSL shader */
|
||||||
|
|
||||||
|
GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
|
||||||
|
{
|
||||||
|
static struct {
|
||||||
|
GPUBuiltin gputype;
|
||||||
|
GPUDynamicType dynamictype;
|
||||||
|
GPUDataType datatype;
|
||||||
|
} builtins[] = {
|
||||||
|
{ GPU_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWMAT, GPU_DATA_16F },
|
||||||
|
{ GPU_INVERSE_VIEW_MATRIX, GPU_DYNAMIC_OBJECT_VIEWIMAT, GPU_DATA_16F },
|
||||||
|
{ GPU_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_MAT, GPU_DATA_16F },
|
||||||
|
{ GPU_INVERSE_OBJECT_MATRIX, GPU_DYNAMIC_OBJECT_IMAT, GPU_DATA_16F },
|
||||||
|
{ GPU_OBCOLOR, GPU_DYNAMIC_OBJECT_COLOR, GPU_DATA_4F },
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
GPUShaderExport *shader = NULL;
|
||||||
|
GPUPass *pass;
|
||||||
|
GPUInput *input;
|
||||||
|
GPUMaterial *mat;
|
||||||
|
GPUInputUniform *uniform;
|
||||||
|
GPUInputAttribute *attribute;
|
||||||
|
GLint lastbindcode;
|
||||||
|
int i, liblen, fraglen;
|
||||||
|
|
||||||
|
if(!GPU_glsl_support())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mat = GPU_material_from_blender(scene, ma);
|
||||||
|
pass = (mat)? mat->pass: NULL;
|
||||||
|
|
||||||
|
if(pass && pass->fragmentcode && pass->vertexcode) {
|
||||||
|
shader = MEM_callocN(sizeof(GPUShaderExport), "GPUShaderExport");
|
||||||
|
|
||||||
|
for(input = pass->inputs.first; input; input = input->next) {
|
||||||
|
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
|
||||||
|
|
||||||
|
if(input->ima) {
|
||||||
|
/* image sampler uniform */
|
||||||
|
uniform->type = GPU_DYNAMIC_SAMPLER_2DIMAGE;
|
||||||
|
uniform->datatype = GPU_DATA_1I;
|
||||||
|
uniform->image = input->ima;
|
||||||
|
uniform->texnumber = input->texid;
|
||||||
|
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||||
|
}
|
||||||
|
else if(input->tex) {
|
||||||
|
/* generated buffer */
|
||||||
|
uniform->texnumber = input->texid;
|
||||||
|
uniform->datatype = GPU_DATA_1I;
|
||||||
|
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||||
|
|
||||||
|
switch(input->textype) {
|
||||||
|
case GPU_SHADOW2D:
|
||||||
|
uniform->type = GPU_DYNAMIC_SAMPLER_2DSHADOW;
|
||||||
|
uniform->lamp = input->dynamicdata;
|
||||||
|
break;
|
||||||
|
case GPU_TEX2D:
|
||||||
|
if(GPU_texture_opengl_bindcode(input->tex)) {
|
||||||
|
uniform->type = GPU_DYNAMIC_SAMPLER_2DBUFFER;
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(input->tex));
|
||||||
|
uniform->texsize = GPU_texture_opengl_width(input->tex) * GPU_texture_opengl_height(input->tex);
|
||||||
|
uniform->texpixels = MEM_mallocN(uniform->texsize*4, "RGBApixels");
|
||||||
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, uniform->texpixels);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, lastbindcode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uniform->type = input->dynamictype;
|
||||||
|
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
|
||||||
|
switch(input->type) {
|
||||||
|
case 1:
|
||||||
|
uniform->datatype = GPU_DATA_1F;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
uniform->datatype = GPU_DATA_2F;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
uniform->datatype = GPU_DATA_3F;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
uniform->datatype = GPU_DATA_4F;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
uniform->datatype = GPU_DATA_9F;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
uniform->datatype = GPU_DATA_16F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST)
|
||||||
|
uniform->lamp = input->dynamicdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(uniform->type != GPU_DYNAMIC_NONE)
|
||||||
|
BLI_addtail(&shader->uniforms, uniform);
|
||||||
|
else
|
||||||
|
MEM_freeN(uniform);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* process builtin uniform */
|
||||||
|
for(i=0; builtins[i].gputype; i++) {
|
||||||
|
if(mat->builtins & builtins[i].gputype) {
|
||||||
|
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
|
||||||
|
uniform->type = builtins[i].dynamictype;
|
||||||
|
uniform->datatype = builtins[i].datatype;
|
||||||
|
BLI_strncpy(uniform->varname, GPU_builtin_name(builtins[i].gputype), sizeof(uniform->varname));
|
||||||
|
BLI_addtail(&shader->uniforms, uniform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now link fragement shader with library shader
|
||||||
|
// TBD: remove the function that are not used in the main function
|
||||||
|
liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
|
||||||
|
fraglen = strlen(pass->fragmentcode);
|
||||||
|
shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader");
|
||||||
|
if(pass->libcode)
|
||||||
|
memcpy(shader->fragment, pass->libcode, liblen);
|
||||||
|
memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
|
||||||
|
shader->fragment[liblen+fraglen] = 0;
|
||||||
|
|
||||||
|
// export the attribute
|
||||||
|
for(i=0; i<mat->attribs.totlayer; i++) {
|
||||||
|
attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
|
||||||
|
attribute->type = mat->attribs.layer[i].type;
|
||||||
|
attribute->number = mat->attribs.layer[i].glindex;
|
||||||
|
BLI_snprintf(attribute->varname, sizeof(attribute->varname), "att%d", mat->attribs.layer[i].attribid);
|
||||||
|
|
||||||
|
switch(attribute->type) {
|
||||||
|
case CD_TANGENT:
|
||||||
|
attribute->datatype = GPU_DATA_4F;
|
||||||
|
break;
|
||||||
|
case CD_MTFACE:
|
||||||
|
attribute->datatype = GPU_DATA_2F;
|
||||||
|
attribute->name = mat->attribs.layer[i].name;
|
||||||
|
break;
|
||||||
|
case CD_MCOL:
|
||||||
|
attribute->datatype = GPU_DATA_4UB;
|
||||||
|
attribute->name = mat->attribs.layer[i].name;
|
||||||
|
break;
|
||||||
|
case CD_ORCO:
|
||||||
|
attribute->datatype = GPU_DATA_3F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(attribute->datatype != GPU_DATA_NONE)
|
||||||
|
BLI_addtail(&shader->attributes, attribute);
|
||||||
|
else
|
||||||
|
MEM_freeN(attribute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// export the vertex shader
|
||||||
|
shader->vertex = BLI_strdup(pass->vertexcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPU_free_shader_export(GPUShaderExport *shader)
|
||||||
|
{
|
||||||
|
GPUInputUniform *uniform;
|
||||||
|
|
||||||
|
if(shader == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(uniform = shader->uniforms.first; uniform; uniform=uniform->next)
|
||||||
|
if(uniform->texpixels)
|
||||||
|
MEM_freeN(uniform->texpixels);
|
||||||
|
|
||||||
|
BLI_freelistN(&shader->uniforms);
|
||||||
|
BLI_freelistN(&shader->attributes);
|
||||||
|
|
||||||
|
if(shader->vertex)
|
||||||
|
MEM_freeN(shader->vertex);
|
||||||
|
if(shader->fragment)
|
||||||
|
MEM_freeN(shader->fragment);
|
||||||
|
|
||||||
|
MEM_freeN(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -308,22 +308,22 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
|
|||||||
outdot = -dot(dir, nor);
|
outdot = -dot(dir, nor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void curves_vec(float fac, vec3 vec, sampler1D curvemap, out vec3 outvec)
|
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
|
||||||
{
|
{
|
||||||
outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x;
|
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
|
||||||
outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y;
|
outvec.y = texture2D(curvemap, vec2((vec.y + 1.0)*0.5, 0.0)).y;
|
||||||
outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z;
|
outvec.z = texture2D(curvemap, vec2((vec.z + 1.0)*0.5, 0.0)).z;
|
||||||
|
|
||||||
if (fac != 1.0)
|
if (fac != 1.0)
|
||||||
outvec = (outvec*fac) + (vec*(1.0-fac));
|
outvec = (outvec*fac) + (vec*(1.0-fac));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void curves_rgb(float fac, vec4 col, sampler1D curvemap, out vec4 outcol)
|
void curves_rgb(float fac, vec4 col, sampler2D curvemap, out vec4 outcol)
|
||||||
{
|
{
|
||||||
outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r;
|
outcol.r = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.r, 0.0)).a, 0.0)).r;
|
||||||
outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g;
|
outcol.g = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.g, 0.0)).a, 0.0)).g;
|
||||||
outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b;
|
outcol.b = texture2D(curvemap, vec2(texture2D(curvemap, vec2(col.b, 0.0)).a, 0.0)).b;
|
||||||
|
|
||||||
if (fac != 1.0)
|
if (fac != 1.0)
|
||||||
outcol = (outcol*fac) + (col*(1.0-fac));
|
outcol = (outcol*fac) + (col*(1.0-fac));
|
||||||
@ -635,9 +635,9 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
|
|||||||
outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
|
outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha)
|
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
|
||||||
{
|
{
|
||||||
outcol = texture1D(colormap, fac);
|
outcol = texture2D(colormap, vec2(fac, 0.0));
|
||||||
outalpha = outcol.a;
|
outalpha = outcol.a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1320,9 +1320,9 @@ void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out
|
|||||||
visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
|
visifac *= lampdistkw/(lampdistkw + ld2*dist*dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac)
|
void lamp_falloff_curve(float lampdist, sampler2D curvemap, float dist, out float visifac)
|
||||||
{
|
{
|
||||||
visifac = texture1D(curvemap, dist/lampdist).x;
|
visifac = texture2D(curvemap, vec2(dist/lampdist, 0.0)).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
|
void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
Import ('env')
|
Import ('env')
|
||||||
|
|
||||||
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
|
incs = '. ../editors/include ../makesdna ../makesrna ../blenlib ../blenkernel ../nodes'
|
||||||
incs += ' ../imbuf ../blenloader ../render/extern/include ../windowmanager'
|
incs += ' ../imbuf ../blenloader ../gpu ../render/extern/include ../windowmanager'
|
||||||
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
|
incs += ' #intern/guardedalloc #intern/memutil #extern/glew/include'
|
||||||
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
|
incs += ' #intern/audaspace/intern ' + env['BF_PYTHON_INC']
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ set(INC
|
|||||||
../../makesdna
|
../../makesdna
|
||||||
../../makesrna
|
../../makesrna
|
||||||
../../windowmanager
|
../../windowmanager
|
||||||
|
../../gpu
|
||||||
../../../../intern/guardedalloc
|
../../../../intern/guardedalloc
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ set(INC_SYS
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(SRC
|
set(SRC
|
||||||
|
gpu.c
|
||||||
bpy.c
|
bpy.c
|
||||||
bpy_app.c
|
bpy_app.c
|
||||||
bpy_app_handlers.c
|
bpy_app_handlers.c
|
||||||
@ -58,6 +60,7 @@ set(SRC
|
|||||||
bpy_util.c
|
bpy_util.c
|
||||||
stubs.c
|
stubs.c
|
||||||
|
|
||||||
|
gpu.h
|
||||||
bpy.h
|
bpy.h
|
||||||
bpy_app.h
|
bpy_app.h
|
||||||
bpy_app_handlers.h
|
bpy_app_handlers.h
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "RNA_types.h"
|
#include "RNA_types.h"
|
||||||
|
|
||||||
#include "bpy.h"
|
#include "bpy.h"
|
||||||
|
#include "gpu.h"
|
||||||
#include "bpy_rna.h"
|
#include "bpy_rna.h"
|
||||||
#include "bpy_util.h"
|
#include "bpy_util.h"
|
||||||
#include "bpy_traceback.h"
|
#include "bpy_traceback.h"
|
||||||
@ -181,6 +182,7 @@ static struct _inittab bpy_internal_modules[]= {
|
|||||||
#ifdef WITH_AUDASPACE
|
#ifdef WITH_AUDASPACE
|
||||||
{(char *)"aud", AUD_initPython},
|
{(char *)"aud", AUD_initPython},
|
||||||
#endif
|
#endif
|
||||||
|
{(char *)"gpu", GPU_initPython},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
291
source/blender/python/intern/gpu.c
Normal file
291
source/blender/python/intern/gpu.c
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): Benoit Bolsee.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/python/intern/gpu.c
|
||||||
|
* \ingroup pythonintern
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* python redefines */
|
||||||
|
#ifdef _POSIX_C_SOURCE
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
#include "GPU_material.h"
|
||||||
|
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_image_types.h"
|
||||||
|
#include "DNA_material_types.h"
|
||||||
|
#include "DNA_lamp_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_ID.h"
|
||||||
|
#include "DNA_customdata_types.h"
|
||||||
|
#include "BLI_listbase.h"
|
||||||
|
#include "RNA_access.h"
|
||||||
|
|
||||||
|
#include "bpy_rna.h"
|
||||||
|
|
||||||
|
#define PY_MODULE_ADD_CONSTANT(module, name) PyModule_AddIntConstant(module, #name, name)
|
||||||
|
|
||||||
|
PyDoc_STRVAR(M_gpu_doc,
|
||||||
|
"This module provides access to the GLSL shader.");
|
||||||
|
|
||||||
|
static struct PyModuleDef gpumodule = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"gpu", /* name of module */
|
||||||
|
M_gpu_doc, /* module documentation */
|
||||||
|
-1, /* size of per-interpreter state of the module,
|
||||||
|
or -1 if the module keeps state in global variables. */
|
||||||
|
NULL, NULL, NULL, NULL, NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit_gpu(void)
|
||||||
|
{
|
||||||
|
PyObject* m;
|
||||||
|
|
||||||
|
m = PyModule_Create(&gpumodule);
|
||||||
|
if(m == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// device constants
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWMAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_MAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_VIEWIMAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_IMAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_OBJECT_COLOR);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNVEC);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCO);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNIMAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNPERSMAT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNENERGY);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_LAMP_DYNCOL);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DBUFFER);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DIMAGE);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DYNAMIC_SAMPLER_2DSHADOW);
|
||||||
|
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1I);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_1F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_2F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_3F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_9F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_16F);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, GPU_DATA_4UB);
|
||||||
|
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, CD_MTFACE);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, CD_ORCO);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, CD_TANGENT);
|
||||||
|
PY_MODULE_ADD_CONSTANT(m, CD_MCOL);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PY_DICT_ADD_STRING(d,s,f) \
|
||||||
|
val = PyUnicode_FromString(s->f); \
|
||||||
|
PyDict_SetItemString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
#define PY_DICT_ADD_LONG(d,s,f) \
|
||||||
|
val = PyLong_FromLong(s->f); \
|
||||||
|
PyDict_SetItemString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
#define PY_DICT_ADD_ID(d,s,f) \
|
||||||
|
RNA_id_pointer_create((struct ID*)s->f, &tptr); \
|
||||||
|
val = pyrna_struct_CreatePyObject(&tptr); \
|
||||||
|
PyDict_SetItemString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
#define PY_OBJ_ADD_ID(d,s,f) \
|
||||||
|
val = PyUnicode_FromString(&s->f->id.name[2]); \
|
||||||
|
PyObject_SetAttrString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
#define PY_OBJ_ADD_LONG(d,s,f) \
|
||||||
|
val = PyLong_FromLong(s->f); \
|
||||||
|
PyObject_SetAttrString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
#define PY_OBJ_ADD_STRING(d,s,f) \
|
||||||
|
val = PyUnicode_FromString(s->f); \
|
||||||
|
PyObject_SetAttrString(d, #f, val); \
|
||||||
|
Py_DECREF(val)
|
||||||
|
|
||||||
|
static PyObject* GPU_export_shader(PyObject* self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject* pyscene;
|
||||||
|
PyObject* pymat;
|
||||||
|
PyObject* as_pointer;
|
||||||
|
PyObject* pointer;
|
||||||
|
PyObject* noargs;
|
||||||
|
PyObject* result;
|
||||||
|
PyObject* dict;
|
||||||
|
PyObject* val;
|
||||||
|
PyObject* seq;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
Scene *scene;
|
||||||
|
PointerRNA tptr;
|
||||||
|
Material *material;
|
||||||
|
GPUShaderExport *shader;
|
||||||
|
GPUInputUniform *uniform;
|
||||||
|
GPUInputAttribute *attribute;
|
||||||
|
|
||||||
|
static const char *kwlist[] = {"scene", "material", NULL};
|
||||||
|
|
||||||
|
if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO:export_shader", (char**)(kwlist), &pyscene, &pymat))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!strcmp(Py_TYPE(pyscene)->tp_name, "Scene") &&
|
||||||
|
(as_pointer = PyObject_GetAttrString(pyscene, "as_pointer")) != NULL &&
|
||||||
|
PyCallable_Check(as_pointer)) {
|
||||||
|
// must be a scene object
|
||||||
|
noargs = PyTuple_New(0);
|
||||||
|
pointer = PyObject_CallObject(as_pointer, noargs);
|
||||||
|
Py_DECREF(noargs);
|
||||||
|
if (!pointer) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
scene = (Scene*)PyLong_AsVoidPtr(pointer);
|
||||||
|
Py_DECREF(pointer);
|
||||||
|
if (!scene) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() first argument should be of Scene type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(Py_TYPE(pymat)->tp_name, "Material") &&
|
||||||
|
(as_pointer = PyObject_GetAttrString(pymat, "as_pointer")) != NULL &&
|
||||||
|
PyCallable_Check(as_pointer)) {
|
||||||
|
// must be a material object
|
||||||
|
noargs = PyTuple_New(0);
|
||||||
|
pointer = PyObject_CallObject(as_pointer, noargs);
|
||||||
|
Py_DECREF(noargs);
|
||||||
|
if (!pointer) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
material = (Material*)PyLong_AsVoidPtr(pointer);
|
||||||
|
Py_DECREF(pointer);
|
||||||
|
if (!material) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "scene.as_pointer() failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "gpu.export_shader() second argument should be of Material type");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// we can call our internal function at last:
|
||||||
|
shader = GPU_shader_export(scene, material);
|
||||||
|
if (!shader) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "cannot export shader");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
// build a dictionary
|
||||||
|
result = PyDict_New();
|
||||||
|
if (shader->fragment) {
|
||||||
|
PY_DICT_ADD_STRING(result,shader,fragment);
|
||||||
|
}
|
||||||
|
if (shader->vertex) {
|
||||||
|
PY_DICT_ADD_STRING(result,shader,vertex);
|
||||||
|
}
|
||||||
|
seq = PyList_New(BLI_countlist(&shader->uniforms));
|
||||||
|
for (i=0, uniform=shader->uniforms.first; uniform; uniform=uniform->next, i++) {
|
||||||
|
dict = PyDict_New();
|
||||||
|
PY_DICT_ADD_STRING(dict,uniform,varname);
|
||||||
|
PY_DICT_ADD_LONG(dict,uniform,datatype);
|
||||||
|
PY_DICT_ADD_LONG(dict,uniform,type);
|
||||||
|
if (uniform->lamp) {
|
||||||
|
PY_DICT_ADD_ID(dict,uniform,lamp);
|
||||||
|
}
|
||||||
|
if (uniform->image) {
|
||||||
|
PY_DICT_ADD_ID(dict,uniform,image);
|
||||||
|
}
|
||||||
|
if (uniform->type == GPU_DYNAMIC_SAMPLER_2DBUFFER ||
|
||||||
|
uniform->type == GPU_DYNAMIC_SAMPLER_2DIMAGE ||
|
||||||
|
uniform->type == GPU_DYNAMIC_SAMPLER_2DSHADOW) {
|
||||||
|
PY_DICT_ADD_LONG(dict,uniform,texnumber);
|
||||||
|
}
|
||||||
|
if (uniform->texpixels) {
|
||||||
|
val = PyByteArray_FromStringAndSize(uniform->texpixels, uniform->texsize);
|
||||||
|
PyDict_SetItemString(dict, "texpixels", val);
|
||||||
|
Py_DECREF(val);
|
||||||
|
PY_DICT_ADD_LONG(dict,uniform,texsize);
|
||||||
|
}
|
||||||
|
PyList_SET_ITEM(seq, i, dict);
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(result, "uniforms", seq);
|
||||||
|
Py_DECREF(seq);
|
||||||
|
|
||||||
|
seq = PyList_New(BLI_countlist(&shader->attributes));
|
||||||
|
for (i=0, attribute=shader->attributes.first; attribute; attribute=attribute->next, i++) {
|
||||||
|
dict = PyDict_New();
|
||||||
|
PY_DICT_ADD_STRING(dict,attribute,varname);
|
||||||
|
PY_DICT_ADD_LONG(dict,attribute,datatype);
|
||||||
|
PY_DICT_ADD_LONG(dict,attribute,type);
|
||||||
|
PY_DICT_ADD_LONG(dict,attribute,number);
|
||||||
|
if (attribute->name) {
|
||||||
|
if (attribute->name[0] != 0) {
|
||||||
|
PY_DICT_ADD_STRING(dict,attribute,name);
|
||||||
|
} else {
|
||||||
|
val = PyLong_FromLong(0);
|
||||||
|
PyDict_SetItemString(dict, "name", val);
|
||||||
|
Py_DECREF(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PyList_SET_ITEM(seq, i, dict);
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(result, "attributes", seq);
|
||||||
|
Py_DECREF(seq);
|
||||||
|
|
||||||
|
GPU_free_shader_export(shader);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef meth_export_shader[] = {{ "export_shader", (PyCFunction)GPU_export_shader, METH_VARARGS | METH_KEYWORDS,
|
||||||
|
"export_shader(scene,material)\n\n"
|
||||||
|
"Returns the GLSL shader that produces the visual effect of material in scene.\n\n"
|
||||||
|
":return: Dictionary defining the shader, uniforms and attributes.\n"
|
||||||
|
":rtype: Dict"}};
|
||||||
|
|
||||||
|
PyObject* GPU_initPython()
|
||||||
|
{
|
||||||
|
PyObject* module = PyInit_gpu();
|
||||||
|
PyModule_AddObject(module, "export_shader", (PyObject *)PyCFunction_New(meth_export_shader, NULL));
|
||||||
|
PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module);
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
41
source/blender/python/intern/gpu.h
Normal file
41
source/blender/python/intern/gpu.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
||||||
|
*
|
||||||
|
* This shader is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version. The Blender
|
||||||
|
* Foundation also sells licenses for use in proprietary software under
|
||||||
|
* the Blender License. See http://www.blender.org/BL/ for information
|
||||||
|
* about this.
|
||||||
|
*
|
||||||
|
* This shader is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this shader; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* The Original Code is Copyright (C) 2005 Blender Foundation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* The Original Code is: all of this file.
|
||||||
|
*
|
||||||
|
* Contributor(s): Benoit Bolsee.
|
||||||
|
*
|
||||||
|
* ***** END GPL LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file blender/python/intern/gpu.h
|
||||||
|
* \ingroup pythonintern
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initalizes the gpu Python module.
|
||||||
|
*/
|
||||||
|
PyObject* GPU_initPython(void);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user