简体   繁体   English

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

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

I want to create an effect like the undulating sphere described in the Aerotwist Tutorial . 我想创建一种类似于Aerotwist教程中所述的起伏球体的效果。 However, in the tutorial Paul creates a fake GLSL hard-coded light in the fragment shader - instead I want to pass info from a three.js PointLight instance to my shaders, manipulate vertices/normals, then perform Phong shading. 但是,在教程中,Paul在片段着色器中创建了一个伪造的GLSL硬编码光源-相反,我想将信息从Three.js PointLight实例传递给我的着色器,操纵顶点/法线,然后执行Phong着色。

My understanding of the various levels of GPU consideration when shading a scene in three.js is as follows (sticking with Phong, for example): 我对在three.js中的场景进行着色时对GPU考虑的各个级别的理解如下(例如,坚持使用Phong):

  1. No GPU consideration: Use a MeshPhongMaterial and don't worry about shaders. 无需考虑GPU:使用MeshPhongMaterial ,不必担心着色器。 This is super easy but doesn't let you mess around on the GPU side. 这非常简单,但不会让您在GPU方面乱七八糟。
  2. Some GPU consideration: Use a ShaderLib Phong shader. 一些GPU注意事项:使用ShaderLib Phong着色器。 This allows you to push shading calculations to the GPU, but since they're pre-written you can't do any custom modification of vertex positions, normals, or illumination calculations. 这允许您将阴影计算推入GPU,但是由于它们是预先编写的,因此您无法对顶点位置,法线或照明计算进行任何自定义修改。
  3. Full GPU management: Use a ShaderMesh and write your shaders from scratch. 全面的GPU管理:使用ShaderMesh并从头开始编写着色器。 This gives you full customization, but also forces you to explicitly pass the attributes and uniforms your shaders will need. 这为您提供了完全的自定义功能,但也迫使您显式传递着色器所需的属性和制服。

Q1: Is the above understanding accurate? 问题1:以上理解是否正确?

Q2: Is there a way to do something between levels 2 and 3? 问题2:是否有办法在2级和3级之间做某事? I want the ability to customize the shaders to mess with vertex positions/normals, but I don't want to write my own Phong shader when a perfectly good one is included with three.js. 我希望能够自定义着色器以使顶点位置/法线混乱,但是当three.js包含一个非常好的着色器时,我不想编写自己的Phong着色器。

Q3: If there is no such middle ground between levels 2 and 3, and I need to just go for level 3, whats the best way to go about it? 问题3:如果在第2级和第3级之间没有中间立场,而我只需要进入第3级,那么实现这一目标的最佳方法是什么? Do I pass the light's position, intensity, etc. as uniforms, do my vertex/normal modifications, then finally explicitly write the Phong shading calculations? 我是否要以均匀的形式传递灯光的位置,强度等,是否进行顶点/法线修改,然后最后明确编写Phong阴影计算?

It's very straightforward to do what you are asking with three.js 使用three.js来完成您的要求非常简单

I'm not sure where it falls in your Q[] 我不确定它在您的Q []中的位置

Q1 Q1

  1. You are still using the shaders, someone else wrote them for you. 您仍在使用着色器,其他人为您编写了它们。 You only have access to the interface. 您只能访问该界面。 Under the hood, calling something like MeshBasicMaterial can actually compile a different shader based on what you feed into it. 在幕后,调用诸如MeshBasicMaterial之类的东西实际上可以根据您输入的内容编译不同的着色器。 Like, it may not process any UVS and not include them in the shader if there is no map called etc. You still have the power to impact the GPU depending on what you call. 就像,如果没有调用等图,它可能不会处理任何UVS并且不将它们包括在着色器中。根据调用的内容,您仍然可以影响GPU。
  2. If you are referring to the shader chunks, it's possible to hack stuff here, but it's pretty cumbersome. 如果您指的是着色器块,则可以在此处修改内容,但这非常麻烦。 My advice is to study the code, for example the phong shading and start building your own piece by piece, using the chunks. 我的建议是研究代码,例如phong阴影,并开始使用块逐步构建自己的代码。 Look at what goes in, what goes out. 看进去什么,出什么。
  3. No need to pass attributes. 无需传递属性。 THREE.ShaderMaterial is not entirely built from scratch. 三.ShaderMaterial并非完全从头开始构建。 It still provides you with quite a bit of stuff, and has a bunch of properties that you can set to get more. 它仍然为您提供了很多东西,并且具有许多可以设置以获取更多信息的属性。 The basic attributes for one, are setup for you ie. 一个的基本属性是为您设置的。 you don't declare "attribute vec3 position". 您不声明“属性vec3位置”。 You can get an array containing all the lights in the scene if you tick the lighting flag as West illustrated, but you can ignore this if for example, you are building a particle shader, or some screen effect. 如果按West所示勾选照明标志,则可以得到包含场景中所有照明的数组,但是例如,如果您正在构建粒子着色器或某些屏幕效果,则可以忽略此数组。 Pretty much every shader is set up to read some basic attributes like 'position' 'uv' 'normal'. 几乎每个着色器都设置为读取一些基本属性,例如“位置”,“ uv”,“正常”。 You can easily add your own on a procedural mesh, but on an actual model it's not trivial. 您可以轻松地在过程网格上添加您自己的对象,但是在实际模型上并不简单。 You get some uniforms by default, you get the entire set of MVP matrices, 'cameraPosition' etc. Writing a phong shader from there is straightforward. 默认情况下,您会获得一些制服,您将获得整套MVP矩阵,“ cameraPosition”等。从那里编写phong着色器很简单。

Now for how would you do this. 现在,您将如何执行此操作。 Say that you are following this tutorial and you have this shader: 假设您正在遵循本教程,并且拥有此着色器:

// 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

}

Here's what you need to do: 这是您需要做的:

GLSL 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
}

Javascript Java脚本

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

});

Q1: Correct. 问题1:正确。 Although, some users on this board have posted work-arounds for hacking MeshPhongMaterial , but that is not the original intent. 虽然,此板上的某些用户已发布了骇MeshPhongMaterial的变通办法,但这并不是其初衷。

Q2 and Q3: Look at ShaderLib.js and you will see the "Normal Map Shader". Q2和Q3:查看ShaderLib.js ,您将看到“法线贴图着色器”。 This is a perfect template for you. 这是您的理想模板。 Yes, you can duplicate/rename it and modify it to your liking. 是的,您可以复制/重命名并根据自己的喜好对其进行修改。

It uses a Phong-based lighting model, and even accesses the scene lights for you. 它使用基于Phong的照明模型,甚至可以为您访问场景灯。 You call it like so: 您这样称呼它:

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 );

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

For coding patterns to follow, see ShaderLib.js and ShaderChunk.js . 有关要遵循的编码模式,请参见ShaderLib.jsShaderChunk.js

three.js r.67 three.js r.67

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

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