如何使顶点和片段着色器在three.js中工作

时间:2013-01-02 23:19:57

标签: javascript three.js webgl

我已经开始通过一本名为WebGL的书:Up and Running,它使用我首选的THREE.js解决方案在浏览器中渲染3D对象。我试图模仿书中引入着色器的部分来制作一个动态的,点亮的太阳,但是当我尝试时我得到的只是一个黑色的球体。使着色器更简单(如Lampert着色器)工作正常,因此它似乎不是照明 - 只是着色器的实现方式。

那么我做错了什么?我设置场景的javascript代码是

var renderer, scene, camera, sunMesh, clock, uniforms;

$(function(){          

    //set scene size
    var WIDTH = 1200,
            HEIGHT = 800;

    //set some camera attributes
    var VIEW_ANGLE = 45,
        ASPECT = WIDTH / HEIGHT,
        NEAR = 0.1,
        FAR = 10000;

    // get the DOM element to attach to
    // - assume we've got jQuery to hand
    var $container = $('#container');

    // create a WebGL renderer, camera
    // and a scene
    renderer = new THREE.WebGLRenderer();
    camera = new THREE.PerspectiveCamera(  VIEW_ANGLE,
                                    ASPECT,
                                    NEAR,
                                    FAR  );
    scene = new THREE.Scene();

    // the camera starts at 0,0,0 so pull it back
    camera.position.z = 300;

    // start the renderer
    renderer.setSize(WIDTH, HEIGHT);

    // attach the render-supplied DOM element
    $container.append(renderer.domElement);

    // Create a group to hold our sun mesh and light
    var sunGroup = new THREE.Object3D();
    var SUNMAP = "./images/lavatile.jpg";
    var NOISEMAP = "./images/cloud.png";
    uniforms = {
            time: { type: "f", value: 1.0 },
            texture1: { type: "t", value: 0, texture: THREE.ImageUtils.loadTexture( NOISEMAP ) },
            texture2: { type: "t", value: 1, texture: THREE.ImageUtils.loadTexture( SUNMAP ) }
    };

    uniforms.texture1.texture.wrapS = uniforms.texture1.texture.wrapT = THREE.Repeat;
    uniforms.texture2.texture.wrapS = uniforms.texture2.texture.wrapT = THREE.Repeat;
    var material = new THREE.ShaderMaterial( {
            uniforms: uniforms,
            vertexShader: document.getElementById( 'vertexShader' ).textContent,
            fragmentShader: document.getElementById( 'fragmentShader' ).textContent
    } );

    //USING THIS MATERIAL WORKS, SO ITS DEFINITELY THE SHADER!
    //var material = new THREE.MeshLambertMaterial(
    //{
    //    color: 0x5B92E5
    //});


    // Create our sun mesh
    var geometry = new THREE.SphereGeometry(50, 64, 64);
    sunMesh = new THREE.Mesh( geometry, material );
    // Tuck away the uniforms so that we can animate them over time
    // Set up a clock to drive the animation
    clock = new THREE.Clock();
    // Create a point light to show off our solar system
    var light = new THREE.PointLight( 0xffffff );
    light.position.set(0,0,100);
    sunGroup.add(sunMesh);
    sunGroup.add(light);
    scene.add(sunGroup);
    // and the camera
    scene.add(camera);

    renderer.render(scene, camera);

    // setup an interval to loop the game loop
    setInterval(gameloop, 50);     

});

function gameloop() {  
    var delta = clock.getDelta();
    uniforms.time.value += delta;
    renderer.render(scene, camera);
}

我将保存完整的HTML(在http://pastebin.com/PGLXkzkA列出)但包含我的着色器,我已经从WebGL书籍的源代码中提取了这些着色器。这可能是错误的,但我怀疑这是我使用着色器的方式。根据我的理解,我应该看到一个太阳,纹理根据噪声遮挡图而变化,在顶点位置有一些运动来产生太阳脉冲。正如我所说,我可以看到一个球体,但它没有点亮和黑色。

我哪里出错?

1 个答案:

答案 0 :(得分:2)

真可惜。这本书似乎已经过时了。

Three.js处于alpha状态,并且正在快速变化。 转而学习three.js示例。它们始终是最新的。

查看Migration Wiki以获取有关升级到当前版本的帮助。

代码中的一些明显错误:

texture1: { type: "t", value: 0, texture: THREE.ImageUtils.loadTexture( NOISEMAP ) },

应该是

texture1: { type: "t", value: THREE.ImageUtils.loadTexture( NOISEMAP ) },

THREE.Repeat应为THREE.RepeatWrappinguniforms.texture1.texture应为uniforms.texture1.value

抱歉,您可能还有其他问题,但我只能帮助您使用当前版本的three.js。

three.js r.54