three.js - 将顶点颜色传递给片段着色器

Gor*_*tić 7 three.js

我在three.js中搜索了简单到复杂的着色器示例,但似乎找不到将顶点保持的颜色传递给片段着色器的简单示例.我做了一个简单的例子,其中顶点着色器只是将顶点留在它们所在的位置,但也通过"vColor"变化将"颜色"均匀(我认为我看到某处但未使用过)传递给片段着色器,然后在片段着色器中,我只想返回相同的颜色.浏览器呈现三角形黑色,我猜测颜色是空的.我知道这很简单,但我无法弄清楚自己,我无法弄清楚ShaderMaterial传递给我可以在那里玩的着色器.有人可以解释一下吗?

这是代码:

<script id="vertexShader" type="x-shader/x-vertex">
    uniform vec3 color;

    varying vec3 vColor;

    void main(){
        vColor = color;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
    varying vec3 vColor;

    void main(){
        gl_FragColor = vec4( vColor.rgb, 1.0 );
    }
</script>
<script>
    var container,
        camera,
        controls,
        scene,
        renderer,
        model;

    init();
    animate();

    function init() {
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.y = 150;
        camera.position.z = 500;

        scene = new THREE.Scene();

        var geometry = new THREE.Geometry();
        geometry.vertices.push(
            new THREE.Vector3(0, 0, 0),
            new THREE.Vector3(-120, -200, 0),
            new THREE.Vector3(120, -200, 0));

        geometry.faces.push(new THREE.Face3(0, 1, 2));

        geometry.faces[0].vertexColors[0] = new THREE.Color("rgb(255,0,0)");
        geometry.faces[0].vertexColors[1] = new THREE.Color("rgb(0,255,0)");
        geometry.faces[0].vertexColors[2] = new THREE.Color("rgb(0,0,255)");

        var materialShader = new THREE.ShaderMaterial({
            vertexShader: document.getElementById('vertexShader').textContent,
            fragmentShader: document.getElementById('fragmentShader').textContent
        });

        var materialBasic = new THREE.LineBasicMaterial({
            vertexColors: THREE.VertexColors,
            linewidth: 1
        });

        var model = new THREE.Mesh(geometry, materialShader);
        model.position.y = 150;
        scene.add(model);

        renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xf0f0f0);
        renderer.setSize(window.innerWidth, window.innerHeight);

        container = document.createElement('div');
        document.body.appendChild(container);
        container.appendChild(renderer.domElement);
        window.addEventListener('resize', onWindowResize, false);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    function render() {
        renderer.render(scene, camera);
    }

</script>
Run Code Online (Sandbox Code Playgroud)

请注意,我有两种类型的材料用于测试 - materialShader用于着色器,而materialBasic用作可正常工作的控件材质.我没有足够的声誉来发布图像,但如果堆栈溢出保持上传的图像,你应该在这里看到渲染的例子:http://i.stack.imgur.com/tjdSt.png

Gor*_*tić 15

我通过玩变量来解决这个问题.我犯的第一个错误是认为顶点着色器代码中的颜色(均匀的vec3颜色;)是一致的,但它实际上是一个属性.其次,我没有定义它,它已经定义了,我发现在接收顶点着色器的堆栈跟踪时,我发现了最终着色器GLSL代码是如何构建的:

1: precision highp float;
2: precision highp int;
3: 
4: #define VERTEX_TEXTURES
5: 
6: 
7: #define MAX_DIR_LIGHTS 0
8: #define MAX_POINT_LIGHTS 0
9: #define MAX_SPOT_LIGHTS 0
10: #define MAX_HEMI_LIGHTS 0
11: #define MAX_SHADOWS 0
12: #define MAX_BONES 58
13: 
      //a lot of blank space was printed in here, i skipped the lines
33: 
34: uniform mat4 modelMatrix;
35: uniform mat4 modelViewMatrix;
36: uniform mat4 projectionMatrix;
37: uniform mat4 viewMatrix;
38: uniform mat3 normalMatrix;
39: uniform vec3 cameraPosition;
40: attribute vec3 position;
41: attribute vec3 normal;
42: attribute vec2 uv;
43: attribute vec2 uv2;
44: #ifdef USE_COLOR
45:     attribute vec3 color;
46: #endif
47: #ifdef USE_MORPHTARGETS
48:     attribute vec3 morphTarget0;
49:     attribute vec3 morphTarget1;
50:     attribute vec3 morphTarget2;
51:     attribute vec3 morphTarget3;
52:     #ifdef USE_MORPHNORMALS
53:         attribute vec3 morphNormal0;
54:         attribute vec3 morphNormal1;
55:         attribute vec3 morphNormal2;
56:         attribute vec3 morphNormal3;
57:     #else
58:         attribute vec3 morphTarget4;
59:         attribute vec3 morphTarget5;
60:         attribute vec3 morphTarget6;
61:         attribute vec3 morphTarget7;
62:     #endif
63: #endif
64: #ifdef USE_SKINNING
65:     attribute vec4 skinIndex;
66:     attribute vec4 skinWeight;
67: #endif
68: 
69:         
70: 
71:         varying vec3 vColor;
72: 
73:         void main(){
74:             vColor = color;
75:             gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
76:         }
77:      
Run Code Online (Sandbox Code Playgroud)

这意味着我不必定义颜色属性.此外,这可以在Three.js文件中看到,但它是一个连接的字符串,因此很难通读.

我需要做的最后一件事是在ShaderMaterial中定义vertexColors:THREE.VertexColors,就像在LineBasicMaterial中一样,我偶然发现(在"让我们看看会发生什么"的方式).

这是最终的代码:

<script id="vertexShader" type="x-shader/x-vertex">


    varying vec3 vColor;

    void main(){
        vColor = color;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
    varying vec3 vColor;

    void main(){
        gl_FragColor = vec4( vColor.rgb, 1.0 );
    }
</script>
<script>
    var container,
        camera,
        controls,
        scene,
        renderer,
        model;

    init();
    animate();

    function init() {
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.y = 150;
        camera.position.z = 500;

        scene = new THREE.Scene();

        var geometry  = new THREE.Geometry();
        geometry.vertices.push(
            new THREE.Vector3(0, 0, 0),
            new THREE.Vector3(-120, -200, 0),
            new THREE.Vector3(120, -200, 0));

        geometry.faces.push(new THREE.Face3(0, 1, 2));

        geometry.faces[0].vertexColors[0] = new THREE.Color("rgb(255,0,0)");
        geometry.faces[0].vertexColors[1] = new THREE.Color("rgb(0,255,0)");
        geometry.faces[0].vertexColors[2] = new THREE.Color("rgb(0,0,255)");

        var materialShader = new THREE.ShaderMaterial({
            vertexShader: document.getElementById('vertexShader').textContent,
            vertexColors: THREE.VertexColors,
            fragmentShader: document.getElementById('fragmentShader').textContent
        });

        var materialBasic = new THREE.LineBasicMaterial({
            vertexColors: THREE.VertexColors,
            linewidth: 1
        });

        var model = new THREE.Mesh(geometry, materialShader);
        model.position.y = 150;
        scene.add(model);

        renderer = new THREE.WebGLRenderer();
        renderer.setClearColor(0xf0f0f0);
        renderer.setSize(window.innerWidth, window.innerHeight);

        container = document.createElement('div');
        document.body.appendChild(container);
        container.appendChild(renderer.domElement);
        window.addEventListener('resize', onWindowResize, false);
    }

    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
        requestAnimationFrame(animate);
        render();
    }

    function render() {
        renderer.render(scene, camera);
    }

</script>
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助其他人理解着色器中的变量.干杯.

  • 还有一件事,在堆栈跟踪中,你可以看到一行:`#ifdef USE_COLOR`然后颜色被定义为`属性vec3颜色;`.我猜这只有在你在材料中添加`vertexColors:THREE.VertexColors`时才有可能,我只是在猜测,因为我不知道如何复制堆栈跟踪. (2认同)