Threejs将着色器添加到3d对象

时间:2015-10-31 01:37:32

标签: 3d three.js webgl shader

我正在尝试为Maya生成的3d对象创建着色器。

我可以加载3d对象,但是当我尝试应用着色器时,我收到此错误:

GL错误:GL_INVALID_OPERATION:glDrawElements:尝试访问属性1中超出范围的顶点

根据我的阅读,我理解我需要定义顶点,但我不知道如何做到这一点。

以下是代码:

<html xmlns="http://www.w3.org/1999/xhtml"><head>
<title>3D render</title>
<script src="js/three.min.js"></script>
<script src="js/OBJLoader.js"></script>
</head>

<body onload="start()" >
<script> 
    var gl;
    var camera, cubeCamera, scene, renderer; 
    var intervalProgress;  

    var fov = 70,

        lon = 0, 
        lat = 70,  
        phi = 0, 
        theta = 0;

    init(); 
    animate(); 

    function init() {

        camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 ); 

        scene = new THREE.Scene();

        var mesh = new THREE.Mesh( new THREE.SphereGeometry( 500, 60, 40 ), new THREE.MeshBasicMaterial({color: 0xFFFFFF}) ); 
        mesh.scale.x = -1;

        scene.add( mesh );


        var light = new THREE.PointLight(0xFFFFFF);
        light.position.set(0, 0, 500);
        scene.add(light);

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

        document.body.appendChild( renderer.domElement );


            var material = new THREE.MeshBasicMaterial( { color:0xFFFFFF } );

        var loader = new THREE.OBJLoader();

        loader.load( "mesh/3d.obj", function ( object ) {

                object.traverse(function(child) {
                        if (child instanceof THREE.Mesh) {


                            var vertShader = document.getElementById('vertexShader').innerHTML;
                            var fragShader = document.getElementById('fragmentShader').innerHTML;                           


                            var uniforms = {
                                texture1: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/texture.jpg" ) }
                            };

                            material = new THREE.ShaderMaterial({
                                uniforms: uniforms,
                                vertexShader: vertShader,
                                fragmentShader: fragShader,
                                wrapping: THREE.ClampToEdgeWrapping,
                                shading: THREE.SmoothShading,
                                side: THREE.DoubleSide
                            });


                            child.material = material;
                            child.material.needsUpdate = true;
                            // child.material.color.setRGB (1, 0, 0);


                        }
                    });

                    //SET SCALE, POSITION AND ROTATION OF OBJECT  
                    object.scale.set( 40,40,40 );
                    object.rotation.x = 0;
                    object.rotation.y = 90; 
                    object.position.y = 0;

                    scene.add(object);

              }); 



    }

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

    function render() {

        var time = Date.now(); 
        lon += .15; 
        lat = Math.max( - 85, Math.min( 85, lat ) );
        phi = THREE.Math.degToRad( 90 - lat );
        theta = THREE.Math.degToRad( lon );

        camera.position.x = 100 * Math.sin( phi ) * Math.cos( theta );
        camera.position.y = 100 * Math.cos( phi );
        camera.position.z = 100 * Math.sin( phi ) * Math.sin( theta ); 
        camera.lookAt( scene.position ); 

        renderer.render( scene, camera ); 
    }

    function start() {
      var canvas = document.getElementById("glcanvas");

      gl = initWebGL(canvas);      // Initialize the GL context

      if (gl) {
        gl.clearColor(0.0, 0.0, 0.0, 1.0);                      // Set clear color to black, fully opaque
        gl.enable(gl.DEPTH_TEST);                               // Enable depth testing
        gl.depthFunc(gl.LEQUAL);                                // Near things obscure far things
        gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);      // Clear the color as well as the depth buffer.
      }
    }

    function initWebGL(canvas) {
      gl = null;

      try {
        // Try to grab the standard context. If it fails, fallback to experimental.
        gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
      }
      catch(e) {}

      // If we don't have a GL context, give up now
      if (!gl) {
        alert("Unable to initialize WebGL. Your browser may not support it.");
        gl = null;
      }

      return gl;
    }

</script> 

<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;

void main() {
    vUv = uv;

    gl_Position =   projectionMatrix * 
                    modelViewMatrix * 
                    vec4(position,1.0);
}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
uniform sampler2D texture1;

varying vec2 vUv;

void main() {
    gl_FragColor = vec4(0.5, 0.2, 1.0, 1.0); 
}
</script>
<canvas id="glcanvas" width="1" height="1"></canvas>
<canvas width="1920" height="951"></canvas>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

我发现了问题,它是上面提到的所有组合,所以我清理了代码:这是工作示例:

function loadObj(name, metal){

var material = null;
loadTexture('textures/'+metal+'.jpg', function(texture){
    loadTexture('normal/243-normal.jpg', function(texture2){
        var material = createMetalShader(metal, texture, texture2);
        var loader = new THREE.OBJLoader();

        loader.load( "mesh/"+name+".obj", function ( object ) {


            object.traverse(function(child) {
                if (child instanceof THREE.Mesh) {

                    child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );  
                    child.geometry.mergeVertices(); 

                    //assignUVs(child.geometry);

                    child.material = material;
                    child.verticesNeedUpdate = true;
                    child.normalsNeedUpdate = true;
                    child.uvsNeedUpdate = true;

                    child.material.shading = THREE.SmoothShading;
                    child.geometry.computeVertexNormals(); 

                }

                object.scale.set( 30,30,30 );
                object.rotation.x = 0;
                object.rotation.y = 90; 
                object.position.y = 0;
                scene.add(object);
                currentMetalObject = object;
            });
        });
    });
});


}

function loadTexture(path, callback){
var loader = new THREE.TextureLoader();

// load a resource
loader.load(path,function ( texture ) {
        callback(texture);
    },
    function ( xhr ) {
        console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
    },
    function ( xhr ) {
        console.log( 'An error happened' );
    }
);


}

function createMetalShader(metal, textureMatCap, textureNormal){
var material = new THREE.ShaderMaterial({
    uniforms: {
        tNormal: {
            type: 't',
            value: textureNormal
        },
        tMatCap: {
            type: 't',
            value: textureMatCap
        },
        time: {
            type: 'f',
            value: 0
        },
        bump: {
            type: 'f',
            value: 0
        },
        noise: {
            type: 'f',
            value: .04
        },
        repeat: {
            type: 'v2',
            value: new THREE.Vector2(1, 1)
        },
        useNormal: {
            type: 'f',
            value: 0
        },
        useRim: {
            type: 'f',
            value: 0
        },
        rimPower: {
            type: 'f',
            value: 2
        },
        useScreen: {
            type: 'f',
            value: 0
        },
        normalScale: {
            type: 'f',
            value: .5
        },
        normalRepeat: {
            type: 'f',
            value: 1
        }
    },
    vertexShader: document.getElementById('vertexShader').textContent,
    fragmentShader: document.getElementById('fragmentShader').textContent,
    wrapping: THREE.ClampToEdgeWrapping,
    shading: THREE.SmoothShading,
    side: THREE.DoubleSide
});
material.uniforms.tMatCap.value.wrapS = material.uniforms.tMatCap.value.wrapT = THREE.ClampToEdgeWrapping;
material.uniforms.tNormal.value.wrapS = material.uniforms.tNormal.value.wrapT = THREE.RepeatWrapping;
material.name = name;
return material;
}
相关问题