THREE.js - 将属性传递给BufferGeometry而不是ShaderMaterial?

时间:2018-01-01 13:47:19

标签: javascript three.js

我试图获得版本58的THREE.js示例,以便在当前版本的THREE.js上运行 - 这里the original example

我只能通过评论一些东西来摆脱一些错误,但是一个棘手的错误是:

  

THREE.ShaderMaterial:现在应该在THREE.BufferGeometry中定义属性。   THREE.ShaderMaterial:'属性'不属于这种材料的属性。

违规代码是:

var shaderMaterial = new THREE.ShaderMaterial( {
    uniforms:       uniforms,
    attributes:     attributes,
    vertexShader:   document.getElementById( 'vertexshader_lines' ).textContent,
    fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
});

attributes在上面几行定义为:

var attributes = {
    draw:        { type: 'f', value: [] },
    seed:        { type: 'f', value: [] },
    seed2:       { type: 'f', value: [] },
    customColor: { type: 'c', value: [] },
    index2:      { type: 'f', value: [] },
    norm:        { type: 'v3', value: [] },
};

我尝试通过注释传递给attributes构造函数的THREE.ShaderMaterial参数来修复此问题,而是将THREE.Geometry从原始版本(名为lineGeo)转换为THREE.BufferedGeometry然后使用addAttribute方法传递属性,如下所示:

var bufferLineGeo = new THREE.BufferGeometry();
bufferLineGeo.fromGeometry(lineGeo);

var values_bColor = new Float32Array(values_color.length * 3);
var values_bNorm  = new Float32Array(values_norm.length  * 3);
bufferLineGeo.addAttribute('draw',        new THREE.BufferAttribute(new Float32Array(values_draw),  1));
bufferLineGeo.addAttribute('seed',        new THREE.BufferAttribute(new Float32Array(values_seed),  1));
bufferLineGeo.addAttribute('seed2',       new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray(  values_color));
bufferLineGeo.addAttribute('index2',      new THREE.BufferAttribute(new Float32Array(values_index2), 1));
bufferLineGeo.addAttribute('norm',        new THREE.BufferAttribute(values_bNorm,  3).copyVector3sArray(values_norm));

这没有用,我现在处于死路,接下来要尝试什么。它什么都没有 - 我留下黑屏,控制台里没有任何东西告诉我出了什么问题。

最小,完整的示例,它不能与当前版本的THREE.js一起使用

<!doctype html>
<html lang="en">
    <head>
        <title>Long hair</title>
        <style type="text/css">
            body {
                background:#000000;
            }
        </style>
    </head>
    <body>
        <!--<script src="../build_r58/three.min.js"></script>-->
        <script src="../js/three.min.js"></script>
        <script type="x-shader/x-vertex" id="vertexshader_lines">
            uniform float globalTime;
            uniform vec3 gravity;
            uniform vec3 gravity2;
            uniform float spacing;

            attribute vec3 customColor;
            attribute float seed;
            attribute float seed2;
            attribute float draw;
            attribute float index2;
            attribute vec3 norm;

            varying vec3 vColor;
            varying float vDraw;
            varying vec3 vNormal;

            void main() {
                vDraw = draw;
                vColor = customColor;

                vec3 displacement = vec3(0.0,0.0,0.0);
                vec3 forceDirection = vec3(0.0,0.0,0.0);

                float displacementFactor = pow(index2, 1.2);
                float displacementFactor2 = pow(index2, 2.5);
                float displacementFactor3 = pow(1.0-index2, 1.0);

                // "gravity"
                vec3 g = gravity;
                g.x *= displacementFactor2*seed2;

                // "wind"
                forceDirection.x = sin(globalTime*0.1+seed2*5.0+index2*1.0) * 0.1*displacementFactor;
                forceDirection.y = cos(globalTime*0.7+seed2*5.0+index2*1.0) * 0.1*displacementFactor3;
                forceDirection.z = sin(globalTime*0.7+seed2*5.0+index2*4.0) * 0.1*displacementFactor2;

                displacement = g + forceDirection + ((1.0-index2)*gravity2)*seed;

                vec3 aNormal = norm;
                aNormal.xyz += displacement*displacementFactor;

                vNormal = norm*(1.0-index2);
                vNormal += (gravity2-gravity)*0.05;

                vec3 animated = position;

                // curl it slightly
                animated.x += aNormal.x*index2*30.0*displacementFactor3;

                animated += aNormal*index2*(spacing*seed);

                if (animated.y < -150.0+seed2*20.0) {
                    animated.y = -150.0+seed2*20.0;
                    vDraw = 0.0;
                }

                vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );
                gl_Position = projectionMatrix * mvPosition;
            }
        </script>
        <script type="x-shader/x-fragment" id="fragmentshader_lines">
            uniform vec3 color;

            varying vec3 vColor;
            varying float vDraw;
            varying vec3 vNormal;

            void main() {
                if (vDraw == 0.0) {
                    discard;
                }

                float depth = gl_FragCoord.z / gl_FragCoord.w;
                float fogFactor = smoothstep( 450.0, 300.0, depth );        

                // light
                vec3 light = vec3(0.5,1.0,0.8);
                float d = pow(max(0.25,dot(vNormal.xyz, light))*2.0, 1.5);

                gl_FragColor = vec4( (color * vColor) * d * fogFactor, 1.0 );
            }
        </script>
        <script>
            var camera, scene, renderer;
            var delta;
            var time;
            var oldTime;
            var uniforms;
            var hair;
            var gravity = new THREE.Vector3(0,-5,0);
            var gravity2 = new THREE.Vector3(0,-5,0);
            init();
            render();

            function init() {
                scene = new THREE.Scene();

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.z = 400;
                camera.lookAt(scene.position);
                scene.add( camera );

                var attributes = {
                    draw:        { type: 'f', value: [] },
                    seed:        { type: 'f', value: [] },
                    seed2:       { type: 'f', value: [] },
                    customColor: { type: 'c', value: [] },
                    index2:      { type: 'f', value: [] },
                    norm:        { type: 'v3', value: [] },
                };

                uniforms = {
                    color:      { type: "c", value: new THREE.Color( 0xe4b67b ) },
                    globalTime: { type: "f", value: 0.0 },
                    gravity:    { type: "v3", value: gravity },
                    gravity2:   { type: "v3", value: gravity2 },
                    spacing:    { type: "f", value: 25.0 },
                };

                var shaderMaterial = new THREE.ShaderMaterial( {
                    uniforms:       uniforms,
                    //attributes:     attributes,
                    vertexShader:   document.getElementById( 'vertexshader_lines' ).textContent,
                    fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
                });

                shaderMaterial.linewidth = 1;

                var lineGeo = new THREE.Geometry();
                var radius = 15;

                var num = 70;

                var baseGeo = new THREE.SphereGeometry(radius, num, num, undefined, undefined, 0.2, Math.PI*0.8);

                for (var i = 0; i < baseGeo.vertices.length; i++) {
                    baseGeo.vertices[i].x += Math.random()*4-2;
                    baseGeo.vertices[i].y += Math.random()*4-2;
                    baseGeo.vertices[i].z += Math.random()*4-2;
                }

                var seedArray = [];
                var seedArray2 = [];
                var colorArray = [];
                var drawArray = [];
                var index2Array = [];
                var normArray = [];

                for (var i = 0; i < baseGeo.vertices.length; i++) {
                    var num = 30;

                    var base = baseGeo.vertices[i];
                    var seed = 1+Math.random()*0.5;
                    var seed2 = 0.25 + Math.random()*0.75;

                    var norm = new THREE.Vector3().copy(base).normalize();
                    norm = norm.normalize();

                    var black = 0.65+Math.random()*0.75;

                    for (var j = 0; j < num; j++) {
                        var vertex = new THREE.Vector3().copy(base);
                        var color = new THREE.Color(0xffffff);
                        color.setRGB(1.0*black,1.0*black,1.0*black);

                        lineGeo.vertices.push( vertex );
                        colorArray.push( color );
                        seedArray.push( seed );
                        seedArray2.push( seed2 );
                        index2Array.push( j/num );
                        normArray.push( norm );

                        if (j == num-1 || j == 0) {
                            drawArray.push( 0 );
                        } else {
                            drawArray.push( 1 );
                        }   
                    }
                }

                var vertices = lineGeo.vertices;
                var values_color = attributes.customColor.value;
                var values_seed = attributes.seed.value;
                var values_seed2 = attributes.seed2.value;
                var values_draw = attributes.draw.value;
                var values_index2 = attributes.index2.value;
                var values_norm = attributes.norm.value;

                for( var v = 0; v < vertices.length; v++ ) {
                    values_seed[ v ] = seedArray[v];
                    values_seed2[ v ] = seedArray2[v];
                    values_draw[ v ] = drawArray[v];
                    values_color[ v ] = colorArray[v];
                    values_index2[ v ] = index2Array[v];
                    values_norm[ v ] = normArray[v];

                }

                var bufferLineGeo = new THREE.BufferGeometry();
                bufferLineGeo.fromGeometry(lineGeo);

                var values_bColor = new Float32Array(values_color.length * 3);
                var values_bNorm  = new Float32Array(values_norm.length  * 3);
                bufferLineGeo.addAttribute('draw',        new THREE.BufferAttribute(new Float32Array(values_draw),  1));
                bufferLineGeo.addAttribute('seed',        new THREE.BufferAttribute(new Float32Array(values_seed),  1));
                bufferLineGeo.addAttribute('seed2',       new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
                bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray(  values_color));
                bufferLineGeo.addAttribute('index2',      new THREE.BufferAttribute(new Float32Array(values_index2), 1));
                bufferLineGeo.addAttribute('norm',        new THREE.BufferAttribute(values_bNorm,  3).copyVector3sArray(values_norm));

                hair = new THREE.Line(bufferLineGeo,
                    //lineGeo,
                    shaderMaterial, THREE.LineStrip );
                scene.add(hair);

                renderer = new THREE.WebGLRenderer({antialias: true});
                renderer.setSize(window.innerWidth, window.innerHeight);
                document.body.appendChild(renderer.domElement);
            }

            function render() {
                requestAnimationFrame(render);
                time = new Date().getTime();
                delta = time - oldTime;
                oldTime = time;

                if (isNaN(delta) || delta > 1000 || delta == 0 ) {
                    delta = 1000/60;
                }

                uniforms.globalTime.value += delta * 0.005;
                renderer.render( scene, camera );
            }
        </script>
    </body>
</html>

上面几乎相同的代码,但在THREE.js的第58版上成功运行

<!doctype html>
<html lang="en">
    <head>
        <title>Long hair</title>
        <style type="text/css">
            body {
                background:#000000;
            }
        </style>
    </head>
    <body>
        <script src="../build_r58/three.min.js"></script>
        <!--<script src="../js/three.min.js"></script>-->
        <script type="x-shader/x-vertex" id="vertexshader_lines">
            uniform float globalTime;
            uniform vec3 gravity;
            uniform vec3 gravity2;
            uniform float spacing;

            attribute vec3 customColor;
            attribute float seed;
            attribute float seed2;
            attribute float draw;
            attribute float index2;
            attribute vec3 norm;

            varying vec3 vColor;
            varying float vDraw;
            varying vec3 vNormal;

            void main() {
                vDraw = draw;
                vColor = customColor;

                vec3 displacement = vec3(0.0,0.0,0.0);
                vec3 forceDirection = vec3(0.0,0.0,0.0);

                float displacementFactor = pow(index2, 1.2);
                float displacementFactor2 = pow(index2, 2.5);
                float displacementFactor3 = pow(1.0-index2, 1.0);

                // "gravity"
                vec3 g = gravity;
                g.x *= displacementFactor2*seed2;

                // "wind"
                forceDirection.x = sin(globalTime*0.1+seed2*5.0+index2*1.0) * 0.1*displacementFactor;
                forceDirection.y = cos(globalTime*0.7+seed2*5.0+index2*1.0) * 0.1*displacementFactor3;
                forceDirection.z = sin(globalTime*0.7+seed2*5.0+index2*4.0) * 0.1*displacementFactor2;

                displacement = g + forceDirection + ((1.0-index2)*gravity2)*seed;

                vec3 aNormal = norm;
                aNormal.xyz += displacement*displacementFactor;

                vNormal = norm*(1.0-index2);
                vNormal += (gravity2-gravity)*0.05;

                vec3 animated = position;

                // curl it slightly
                animated.x += aNormal.x*index2*30.0*displacementFactor3;

                animated += aNormal*index2*(spacing*seed);

                if (animated.y < -150.0+seed2*20.0) {
                    animated.y = -150.0+seed2*20.0;
                    vDraw = 0.0;
                }

                vec4 mvPosition = modelViewMatrix * vec4( animated, 1.0 );
                gl_Position = projectionMatrix * mvPosition;
            }
        </script>
        <script type="x-shader/x-fragment" id="fragmentshader_lines">
            uniform vec3 color;

            varying vec3 vColor;
            varying float vDraw;
            varying vec3 vNormal;

            void main() {
                if (vDraw == 0.0) {
                    discard;
                }

                float depth = gl_FragCoord.z / gl_FragCoord.w;
                float fogFactor = smoothstep( 450.0, 300.0, depth );        

                // light
                vec3 light = vec3(0.5,1.0,0.8);
                float d = pow(max(0.25,dot(vNormal.xyz, light))*2.0, 1.5);

                gl_FragColor = vec4( (color * vColor) * d * fogFactor, 1.0 );
            }
        </script>
        <script>
            var camera, scene, renderer;
            var delta;
            var time;
            var oldTime;
            var uniforms;
            var hair;
            var gravity = new THREE.Vector3(0,-5,0);
            var gravity2 = new THREE.Vector3(0,-5,0);
            init();
            render();

            function init() {
                scene = new THREE.Scene();

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.z = 400;
                camera.lookAt(scene.position);
                scene.add( camera );

                var attributes = {
                    draw:        { type: 'f', value: [] },
                    seed:        { type: 'f', value: [] },
                    seed2:       { type: 'f', value: [] },
                    customColor: { type: 'c', value: [] },
                    index2:      { type: 'f', value: [] },
                    norm:        { type: 'v3', value: [] },
                };

                uniforms = {
                    color:      { type: "c", value: new THREE.Color( 0xe4b67b ) },
                    globalTime: { type: "f", value: 0.0 },
                    gravity:    { type: "v3", value: gravity },
                    gravity2:   { type: "v3", value: gravity2 },
                    spacing:    { type: "f", value: 25.0 },
                };

                var shaderMaterial = new THREE.ShaderMaterial( {
                    uniforms:       uniforms,
                    attributes:     attributes,
                    vertexShader:   document.getElementById( 'vertexshader_lines' ).textContent,
                    fragmentShader: document.getElementById( 'fragmentshader_lines' ).textContent,
                });

                shaderMaterial.linewidth = 1;

                var lineGeo = new THREE.Geometry();
                var radius = 15;

                var num = 70;

                var baseGeo = new THREE.SphereGeometry(radius, num, num, undefined, undefined, 0.2, Math.PI*0.8);

                for (var i = 0; i < baseGeo.vertices.length; i++) {
                    baseGeo.vertices[i].x += Math.random()*4-2;
                    baseGeo.vertices[i].y += Math.random()*4-2;
                    baseGeo.vertices[i].z += Math.random()*4-2;
                }

                var seedArray = [];
                var seedArray2 = [];
                var colorArray = [];
                var drawArray = [];
                var index2Array = [];
                var normArray = [];

                for (var i = 0; i < baseGeo.vertices.length; i++) {
                    var num = 30;

                    var base = baseGeo.vertices[i];
                    var seed = 1+Math.random()*0.5;
                    var seed2 = 0.25 + Math.random()*0.75;

                    var norm = new THREE.Vector3().copy(base).normalize();
                    norm = norm.normalize();

                    var black = 0.65+Math.random()*0.75;

                    for (var j = 0; j < num; j++) {
                        var vertex = new THREE.Vector3().copy(base);
                        var color = new THREE.Color(0xffffff);
                        color.setRGB(1.0*black,1.0*black,1.0*black);

                        lineGeo.vertices.push( vertex );
                        colorArray.push( color );
                        seedArray.push( seed );
                        seedArray2.push( seed2 );
                        index2Array.push( j/num );
                        normArray.push( norm );

                        if (j == num-1 || j == 0) {
                            drawArray.push( 0 );
                        } else {
                            drawArray.push( 1 );
                        }   
                    }
                }

                var vertices = lineGeo.vertices;
                var values_color = attributes.customColor.value;
                var values_seed = attributes.seed.value;
                var values_seed2 = attributes.seed2.value;
                var values_draw = attributes.draw.value;
                var values_index2 = attributes.index2.value;
                var values_norm = attributes.norm.value;

                for( var v = 0; v < vertices.length; v++ ) {
                    values_seed[ v ] = seedArray[v];
                    values_seed2[ v ] = seedArray2[v];
                    values_draw[ v ] = drawArray[v];
                    values_color[ v ] = colorArray[v];
                    values_index2[ v ] = index2Array[v];
                    values_norm[ v ] = normArray[v];

                }

                /*var bufferLineGeo = new THREE.BufferGeometry();
                bufferLineGeo.fromGeometry(lineGeo);

                var values_bColor = new Float32Array(values_color.length * 3);
                var values_bNorm  = new Float32Array(values_norm.length  * 3);
                bufferLineGeo.addAttribute('draw',        new THREE.BufferAttribute(new Float32Array(values_draw),  1));
                bufferLineGeo.addAttribute('seed',        new THREE.BufferAttribute(new Float32Array(values_seed),  1));
                bufferLineGeo.addAttribute('seed2',       new THREE.BufferAttribute(new Float32Array(values_seed2), 1));
                bufferLineGeo.addAttribute('customColor', new THREE.BufferAttribute(values_bColor, 3).copyColorsArray(  values_color));
                bufferLineGeo.addAttribute('index2',      new THREE.BufferAttribute(new Float32Array(values_index2), 1));
                bufferLineGeo.addAttribute('norm',        new THREE.BufferAttribute(values_bNorm,  3).copyVector3sArray(values_norm));*/

                hair = new THREE.Line(//bufferLineGeo,
                    lineGeo,
                    shaderMaterial, THREE.LineStrip );
                scene.add(hair);

                renderer = new THREE.WebGLRenderer({antialias: true});
                renderer.setSize(window.innerWidth, window.innerHeight);
                document.body.appendChild(renderer.domElement);
            }

            function render() {
                requestAnimationFrame(render);
                time = new Date().getTime();
                delta = time - oldTime;
                oldTime = time;

                if (isNaN(delta) || delta > 1000 || delta == 0 ) {
                    delta = 1000/60;
                }

                uniforms.globalTime.value += delta * 0.005;
                renderer.render( scene, camera );
            }
        </script>
    </body>
</html>

你可以get a copy of three.min.js for version 58 here

你可以get the current version of three.min.js from here

1 个答案:

答案 0 :(得分:2)

这一行

bufferLineGeo.fromGeometry( lineGeo );
如果没有定义面,

将不会填充位置属性。

改为

var positions = new Float32Array( vertices.length * 3 );
bufferLineGeo.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ).copyVector3sArray( vertices ) );

three.js r.89