GLSL - how to pass a variable from a script to a shader ?

is it possible to pass game engine values, for example the value of a property, to a shader ?

my goal is to change the diffuse color of an object, depending on some value modified by user (keyboard etc), or by an object position etc.

I don’t know how to pass the value to the C functions, the one with gl_FragColor. I’m able to change the color from one to another, (no need for a variable inside the C thing in this case) but I can’t produce a transition for example.

I’m reading the examples in the API and the amazing shaders made by martinsh, but it’s a bit hard to understand at the beginning… :confused: and I don’t find something similar to this need.


edit : found ! Focus_U and Focus_V use props from the FX empty (owner) :slight_smile:

here’s something that work, but I don’t know if it’s the right way :

the object linked to the following has 3 props :
that represent the diffuse values of the object ‘ciel’

# define the main part of the program
def main():
	# get the current scene
	sc = GameLogic.getCurrentScene()
	objlist = sc.objects
	ob = objlist["OBciel"]
	mesh = ob.meshes[0]
	mat = mesh.materials[0]
	# Using Blender GLSL Materials or Blender Multitexture Materials?
	if hasattr(mat, "getMaterialIndex") == True:
		shader = mat.getShader()
		if shader != None:
			shader.setSource(VertexProgram,FragmentProgram, True)

co = GameLogic.getCurrentController()
own = co.owner

# Import OpenGL code as a string
VertexProgram = "void main() {gl_Position = ftransform();}"
# Import OpenGL code as a string
<b>FragmentProgram = "void main() {gl_FragColor = vec4(%s,%s,%s,1.0);}"%(own['cielR'],own['cielG'],own['cielB'])</b>


so I can play with the prop to fade a sky.
is it the right way ? as in this case the C code is a python string - whereas the 2d filter custom which looks like directly written in C - Iused a simple %s to pass values.
(I’m getting old, talking to myself, on public areas)

The way you did it works and I think it’s ok. But if you had to change the values that you’re passing to the shader then I think it would be better to pass the values using .setUniform() instead of inserting them in the source string like you’re doing. Because while you could just change the source string and use .setSource() every time you changed it. That would require the video card to recompile both vertex and fragment programs which takes an additional time.

So I think it would be more efficient to pass the values by changing uniforms instead.

There’s an example in the docs showing how to do it:
Here he uses an uniform variable called ‘orange’ which he assigns FragColor to. Then he uses the bge python .setUniform to set what ‘orange’ means. You could change that uniform for every game tick for every object without needing to recompile the whole program.

So in your case where you want the objects to fade, you could calculate the fading in python in the bge then just pass the final value to the uniform on the shader. Or you could opt to calculate the fading inside the shader code, if you do this then you can keep passing the properties directly in the source string since you wouldn’t need to change it later. The first method would weight heavier on cpu while the second would weight more on the gpu. So I think you should choose whatever the rest of your game isn’t pushing too much.