繁体   English   中英

使用three.js将PointLight信息传递到自定义着色器

[英]Passing PointLight Info to a custom Shader with three.js

我想创建一种类似于Aerotwist教程中所述的起伏球体的效果。 但是,在教程中,Paul在片段着色器中创建了一个伪造的GLSL硬编码光源-相反,我想将信息从Three.js PointLight实例传递给我的着色器,操纵顶点/法线,然后执行Phong着色。

我对在three.js中的场景进行着色时对GPU考虑的各个级别的理解如下(例如,坚持使用Phong):

  1. 无需考虑GPU:使用MeshPhongMaterial ,不必担心着色器。 这非常简单,但不会让您在GPU方面乱七八糟。
  2. 一些GPU注意事项:使用ShaderLib Phong着色器。 这允许您将阴影计算推入GPU,但是由于它们是预先编写的,因此您无法对顶点位置,法线或照明计算进行任何自定义修改。
  3. 全面的GPU管理:使用ShaderMesh并从头开始编写着色器。 这为您提供了完全的自定义功能,但也迫使您显式传递着色器所需的属性和制服。

问题1:以上理解是否正确?

问题2:是否有办法在2级和3级之间做某事? 我希望能够自定义着色器以使顶点位置/法线混乱,但是当three.js包含一个非常好的着色器时,我不想编写自己的Phong着色器。

问题3:如果在第2级和第3级之间没有中间立场,而我只需要进入第3级,那么实现这一目标的最佳方法是什么? 我是否要以均匀的形式传递灯光的位置,强度等,是否进行顶点/法线修改,然后最后明确编写Phong阴影计算?

使用three.js来完成您的要求非常简单

我不确定它在您的Q []中的位置

Q1

  1. 您仍在使用着色器,其他人为您编写了它们。 您只能访问该界面。 在幕后,调用诸如MeshBasicMaterial之类的东西实际上可以根据您输入的内容编译不同的着色器。 就像,如果没有调用等图,它可能不会处理任何UVS并且不将它们包括在着色器中。根据调用的内容,您仍然可以影响GPU。
  2. 如果您指的是着色器块,则可以在此处修改内容,但这非常麻烦。 我的建议是研究代码,例如phong阴影,并开始使用块逐步构建自己的代码。 看进去什么,出什么。
  3. 无需传递属性。 三.ShaderMaterial并非完全从头开始构建。 它仍然为您提供了很多东西,并且具有许多可以设置以获取更多信息的属性。 一个的基本属性是为您设置的。 您不声明“属性vec3位置”。 如果按West所示勾选照明标志,则可以得到包含场景中所有照明的数组,但是例如,如果您正在构建粒子着色器或某些屏幕效果,则可以忽略此数组。 几乎每个着色器都设置为读取一些基本属性,例如“位置”,“ uv”,“正常”。 您可以轻松地在过程网格上添加您自己的对象,但是在实际模型上并不简单。 默认情况下,您会获得一些制服,您将获得整套MVP矩阵,“ cameraPosition”等。从那里编写phong着色器很简单。

现在,您将如何执行此操作。 假设您正在遵循本教程,并且拥有此着色器:

// same name and type as VS
varying vec3 vNormal;

void main() {


//this is hardcoded you want to pass it from your environment
vec3 light = vec3(0.5, 0.2, 1.0);//it needs to be a uniform

// ensure it's normalized
light = normalize(light);//you can normalize it outside of the shader, since it's a directional light

// calculate the dot product of
// the light to the vertex normal
float dProd = max(0.0,
                dot(vNormal, light));

// feed into our frag colour
gl_FragColor = vec4(dProd, // R
                  dProd, // G
                  dProd, // B
                  1.0);  // A

}

这是您需要做的:

GLSL

uniform vec3 myLightPos;//comes in
void main(){
    vec3 light = normalize(myLightPos);//but you better do this in javascript and just pass the normalized vec3
}

Java脚本

new THREE.ShaderMaterial({
   uniforms:{
      myLightPos:{
         type:"v3",
         value: new THREE.Vector3()
      }
   },
   vertexShader: yourVertShader,
   fragmentShader: yourFragmentShader

});

问题1:正确。 虽然,此板上的某些用户已发布了骇MeshPhongMaterial的变通办法,但这并不是其初衷。

Q2和Q3:查看ShaderLib.js ,您将看到“法线贴图着色器”。 这是您的理想模板。 是的,您可以复制/重命名并根据自己的喜好对其进行修改。

它使用基于Phong的照明模型,甚至可以为您访问场景灯。 您这样称呼它:

var shader = THREE.ShaderLib[ "normalmap" ];

var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

. . .

var parameters = {
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: uniforms,
    lights: true // set this flag and you have access to scene lights
};

var material = new THREE.ShaderMaterial( parameters );

请参阅以下示例: http : //threejs.org/examples/webgl_materials_normalmap.htmlhttp://threejs.org/examples/webgl_materials_normalmap2.html

有关要遵循的编码模式,请参见ShaderLib.jsShaderChunk.js

three.js r.67

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM