Blender ShaderでUniform変数

blender-shader-uniform.png

最も簡単なUniform変数利用例

まずは最も簡単な実験を試してみましょう

#coding: UTF-8
import bge#<- short for "Blender Game Engine"
VertexShader = """
void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
"""
 
FragmentShader = """
uniform vec4 u_color;
 void main()
 { 
    gl_FragColor = u_color; 
 }
"""
 
cont = bge.logic.getCurrentController()
mesh = cont.owner.meshes[0]
for mat in mesh.materials:
    shader = mat.getShader()
    if shader != None:
        if not shader.isValid():
            shader.setSource( VertexShader, FragmentShader, 1 )
shader.setUniform4f('u_color',1.0,0.0,0.0,1.0)

真っ赤に塗られた3Dオブジェクトがレンダリング出来たら成功です。
ここでユニフォーム変数の値を渡しています

shader.setUniform4f('u_color',1.0,0.0,0.0,1.0)

これが出来たら次はBlenderのどこかから値を渡してみたいですね

キーボード入力からユニフォーム変数へ何か値を設定するには

まずBlenderからPropertyを追加します
ここではcolormodeという名前で作りました
property.png
そして、このlogicでいけました
logic.png
何かキーを押したらpythonスクリプトが呼ばれる、
何かキーを押したらcolormodeの値が+1される
自分が作ったpropertyであるcolormodeの値が変わってもpythonスクリプトが呼ばれる
という仕組みになっているものです。
プラスmiffyshader.pyにはこう書いておきます
W,A,S,Dのどれかを押すとCubeの色が変わるというスクリプトです
#coding: UTF-8
import bge#<- short for "Blender Game Engine"
VertexShader = """
void main() {
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
"""
 
FragmentShader = """
uniform vec4 u_color;
 void main()
 { 
    gl_FragColor = u_color; 
 }
"""
cont = bge.logic.getCurrentController()
mesh = cont.owner.meshes[0]
for mat in mesh.materials:
    shader = mat.getShader()
    if shader != None:
        if not shader.isValid():
            shader.setSource( VertexShader, FragmentShader, 1 )
print('Hello world!!')
bge.render.makeScreenshot('/Users/myamahir/Pictures/Blender/miffyshot.png')
# 'Keyboard' is a keyboard sensor
print(cont.sensors)
sensor = cont.sensors["Keyboard"]
 
for key,status in sensor.events:
        # key[0] == bge.events.keycode, key[1] = status
        if status == bge.logic.KX_INPUT_JUST_ACTIVATED:
                if key == bge.events.WKEY:
                        print('W')
                        shader.setUniform4f('u_color',1.0,0.0,0.0,1.0)
                if key == bge.events.SKEY:
                        print('S')
                        shader.setUniform4f('u_color',1.0,1.0,0.0,1.0)
                if key == bge.events.AKEY:
                        print('A')
                        shader.setUniform4f('u_color',1.0,0.5,0.5,1.0)
                if key == bge.events.DKEY:
                        print('D')
                        shader.setUniform4f('u_color',0.1,0.3,0.5,0.5)

Propertyの値をpythonの中で知るには

cont = bge.logic.getCurrentController()
cont.owner['プロパティーの名前']

これでそのまま値が返ってきます。しかもint,float,と設定した型に応じてそのままの型が返ってきます
このownerというのはKX_GameObject[3]というものだそうです
何かキーを押すたびにプロパティーの値が0.1増えるロジックを作って、
そのプロパティーの値をキューブの色の赤成分に反映させるもののコードはこんな風になります。
bge.logic.getCurrentController()
shader.setUniform4f('u_color',cont.owner['プロパティーの名前'],0.0,0.0,1.0)
Bibliography
2. BL_Shader関数一覧

サポートサイト Wikidot.com