我试图重写WebGL一书的example3-3:在不使用sim.js的情况下启动并运行(http://shop.oreilly.com/product/0636920024729.do)。但是我在纹理上遇到了问题。

我只是无法使用ShaderMaterial来获得正常和镜面效果,我与MeshPhongMaterial具有几乎相同的功能,并且可以正常工作,但是现在这是我正在使用ShaderMaterial获得的渲染:http://imgur.com/vts9X3k

这是我的代码:

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();


我认为灯光不是问题,它看起来确实像是带有纹理的东西。

最佳答案

我正在处理同一个问题,并且找到了解决方案,因为我正在处理本书中的相同示例。

您有几个问题:


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;

10-08 01:30