Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/449.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用three.js将点光源信息传递给自定义着色器_Javascript_Three.js_Glsl_Webgl - Fatal编程技术网

Javascript 使用three.js将点光源信息传递给自定义着色器

Javascript 使用three.js将点光源信息传递给自定义着色器,javascript,three.js,glsl,webgl,Javascript,Three.js,Glsl,Webgl,我想创建一个效果,如中所述。但是,在教程中,Paul在片段着色器中创建了一个伪GLSL硬编码灯光-相反,我希望将信息从three.js PointLight实例传递到我的着色器,操纵顶点/法线,然后执行Phong着色 我对在three.js中为场景着色时GPU考虑的各个级别的理解如下(例如,坚持使用Phong): 无需考虑GPU:使用一个图形处理器,不必担心着色器。这是超级容易,但不让你在GPU方面乱搞 一些GPU注意事项:使用Phong着色器。这允许您将着色计算推送到GPU,但由于它们是预先编

我想创建一个效果,如中所述。但是,在教程中,Paul在片段着色器中创建了一个伪GLSL硬编码灯光-相反,我希望将信息从three.js PointLight实例传递到我的着色器,操纵顶点/法线,然后执行Phong着色

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

  • 无需考虑GPU:使用一个图形处理器,不必担心着色器。这是超级容易,但不让你在GPU方面乱搞
  • 一些GPU注意事项:使用Phong着色器。这允许您将着色计算推送到GPU,但由于它们是预先编写的,因此无法对顶点位置、法线或照明计算进行任何自定义修改
  • 完整的GPU管理:使用一个新的工具,从头开始编写着色器。这提供了完整的自定义,但也强制您显式传递着色器所需的属性和一致性
  • 问题1:上述理解是否准确

    问题2:在第2级和第3级之间有没有办法做点什么?我希望能够自定义着色器以处理顶点位置/法线,但我不想在three.js中包含一个非常好的Phong着色器时编写自己的Phong着色器


    问题3:如果在2级和3级之间没有这样的中间地带,我只需要进入3级,那么最好的方法是什么?我是否将灯光的位置、强度等作为制服传递,进行顶点/法线修改,然后最终明确写入Phong着色计算?

    Q1:正确。尽管该网站上的一些用户发布了黑客破解的解决方案,但这并不是他们的初衷

    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 );
    
    参见以下示例:和

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


    three.js r.67

    使用three.js做你想做的事情非常简单

    我不确定它落在你的Q[]

    Q1

  • 您仍在使用着色器,其他人为您编写了着色器。您只能访问该接口。在引擎盖下,调用诸如MeshBasicMaterial之类的东西实际上可以根据输入的内容编译不同的着色器。例如,如果没有调用贴图,它可能不会处理任何UV,也不会将它们包含在着色器中。根据调用的内容,您仍然有能力影响GPU
  • 如果你指的是着色器块,可以在这里进行黑客攻击,但这相当麻烦。我的建议是研究代码,例如phong着色,然后开始使用块一块一块地构建自己的代码。看看什么进去了,什么出去了
  • 不需要传递属性。ShaderMaterial并非完全从头开始构建。它仍然为您提供了相当多的东西,并且有一系列属性,您可以设置这些属性以获得更多。其中一个的基本属性是为您设置的,即您不需要声明“属性向量3位置”。如果如图所示勾选照明标志,则可以获得包含场景中所有灯光的阵列,但如果正在构建粒子着色器或某些屏幕效果,则可以忽略该阵列。几乎每个着色器都设置为读取一些基本属性,如“位置”“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

    Javascript

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

    非常感谢您和@pailhead的详细解释!我最终使用了更简单的“phong”ShaderLib对象作为模板。我对vertexShader做了一些轻微的修改,以扰动每个顶点,并使用fragmentShader未作更改,将“lights”标志设置为true,如您所建议的。
    new THREE.ShaderMaterial({
       uniforms:{
          myLightPos:{
             type:"v3",
             value: new THREE.Vector3()
          }
       },
       vertexShader: yourVertShader,
       fragmentShader: yourFragmentShader
    
    });