pythreejs中如何将vec4向量数组作为uniform传入着色器
实现方法
Three.js(及其Python绑定如pythreejs)原生支持vec4类型的uniform数组,你只需要按照以下规则构造uniform值即可:
语法修正
首先你给出的材质代码有个小语法错误,myVectorSize=(dict(value=10),多了多余的左括号,修正为:
myVectorSize=dict(value=10)
两种传值方案
你可以任选以下两种方案之一给myVector赋值:
方案1:扁平化Float32数组(性能最优,适合大数组)
vec4数组可以直接序列化为长度为向量数量 * 4的Float32数组,每个vec4的4个分量按顺序连续存储即可。
示例代码:
import numpy as np from pythreejs import ShaderMaterial, UniformsLib # 声明需要传入的vec4数量,不得超过着色器中定义的数组长度(你的代码里是50) vector_count = 10 # 构造示例数据:10个随机RGBA颜色的vec4,flatten为一维float32数组 my_vector_data = np.random.rand(vector_count, 4).astype(np.float32).flatten() # 构造材质 fragment_shader = """ uniform int myVectorSize; uniform vec4 myVector[50]; void main() { // 示例:取第一个vec4作为片元输出颜色 gl_FragColor = myVector[0]; } """ material = ShaderMaterial( uniforms=dict( myVectorSize=dict(value=10), myVector=dict(value=my_vector_data), **UniformsLib['common'] ), fragmentShader=fragment_shader, )
方案2:vec4实例列表(写法直观,适合小数组)
你也可以直接传一个由Vector4实例组成的列表作为value,Three.js会自动处理序列化:
from pythreejs import Vector4 vector_count = 10 my_vector_data = [] for i in range(vector_count): # 构造每个vec4实例 my_vector_data.append(Vector4( np.random.rand(), # r np.random.rand(), # g np.random.rand(), # b 1.0 # a ))
注意事项
- WebGL1环境下不支持动态长度的uniform数组,你需要在着色器中预先声明足够大的固定长度(如你的代码里的
myVector[50]),实际传入的数组长度不得超过该声明值。 - WebGL2环境下可以将着色器中的数组声明改为
uniform vec4 myVector[];,支持动态传入任意长度的数组。 - 后续需要更新数组内容时,直接修改
myVector对应的value数组即可,无需重新赋值uniform对象,Three.js会自动检测数据变更。
内容的提问来源于stack exchange,提问作者Leo Abalckin
相关产品推荐
相关产品推荐

