ShaderMaterial渲染three.js

时间:2013-10-09 19:31:45

标签: javascript three.js webgl

我正在尝试重写WebGL的示例3-3:启动并运行(http://shop.oreilly.com/product/0636920024729.do)而不使用sim.js.但我的纹理问题。

我只是无法使用ShaderMaterial来获得正常和镜面反射效果,我对MeshPhongMaterial几乎完全相同并且它工作正常,但是现在这是我使用ShaderMaterial渲染的渲染:{{ 3}}

这是我的代码:

var camera,
    scene,
    renderer,
    sunLight,
    earthMesh,
    cloudsMesh,
    earthGroup;

function init() {
    var fieldOfView = 60,
        aspectRatio = window.innerWidth/window.innerHeight,
        near = 1,
        far = 4000;

    // Renderer
    renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth,window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // Scene
    scene = new THREE.Scene();

    // Earth group
    earthGroup = new THREE.Object3D();

    // Camera
    camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, near, far);
    camera.position.set( 0, 0, 3.5 );
    scene.add(camera);

    // Earths creation
    var surfaceMap = THREE.ImageUtils.loadTexture( "earth_surface_2048.jpg" );
    var normalMap = THREE.ImageUtils.loadTexture( "earth_normal_2048.jpg" );
    var specularMap = THREE.ImageUtils.loadTexture( "earth_specular_2048.jpg" );

    var shader = THREE.ShaderUtils.lib[ "normal" ],
        uniforms = THREE.UniformsUtils.clone( shader.uniforms );

    uniforms[ "tNormal" ].texture = normalMap;
    uniforms[ "tDiffuse" ].texture = surfaceMap;
    uniforms[ "tSpecular" ].texture = specularMap;
    uniforms[ "enableDiffuse" ].value = true;
    uniforms[ "enableSpecular" ].value = true;

    var shaderMaterial = new THREE.ShaderMaterial({
        fragmentShader: shader.fragmentShader,
        vertexShader: shader.vertexShader,
        uniforms: uniforms,
        lights: true
    });

    var geometry = new THREE.SphereGeometry(1, 32, 32);
    geometry.computeTangents();

    earthMesh = new THREE.Mesh( geometry, shaderMaterial );

    earthGroup.add(earthMesh);

    // Clouds
    var cloudsMap = THREE.ImageUtils.loadTexture( "earth_clouds_1024.png" );
    var cloudsMaterial = new THREE.MeshLambertMaterial({
        color: 0xffffff,
        map: cloudsMap,
        transparent:true 
    });

    var cloudsGeometry = new THREE.SphereGeometry(1.1, 32, 32);

    cloudsMesh = new THREE.Mesh( cloudsGeometry, cloudsMaterial );

    earthGroup.add(cloudsMesh);

    earthGroup.rotation.x = 0.5;

    // Add earth and clouds to the scene
    scene.add(earthGroup);

    // Lights
    // Basic ambient light
    scene.add( new THREE.AmbientLight("rgb(35,35,35)") ); 

    // Sun light
    sunLight = new THREE.PointLight( "rgb(255,230,200)", 2, 100 );
    sunLight.position.set(-10, 0, 20);
    scene.add(sunLight);

    // Render
    run();
}

function run() {
    // Render
    renderer.render( scene, camera );

    // Rotating earth and clouds for the next frame
    earthMesh.rotation.y += 0.005;
    cloudsMesh.rotation.y += 0.003;

    // Ask for another frame
    requestAnimationFrame(run);
}

init();

我认为灯光不是问题,它看起来就像纹理一样。

1 个答案:

答案 0 :(得分:1)

我刚刚处理了同样的问题并找到了解决方案,因为我正在研究本书中的相同示例。

你有几个问题:

  • THREE.ShaderUtils.lib现在是THREE.ShaderLib
  • 为着色器使用“normalmap”而不是“normal”
  • 制服的.texturetNormaltDiffuse属性中没有tSpecular属性。通过调整.value属性直接设置纹理。

因此,受影响的代码应该是这样的:

var shader = THREE.ShaderLib[ "normalmap" ];
var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

uniforms[ "tNormal" ].value = normalMap;
uniforms[ "tDiffuse" ].value = surfaceMap;
uniforms[ "tSpecular" ].value = specularMap;

uniforms[ "enableDiffuse" ].value = true;
uniforms[ "enableSpecular" ].value = true;