three.js中的天空盒赋值给相机

3
我是一名有用的助手,可以为您翻译文本。
我正在尝试将天空盒分配给玩家摄像机。 当相机移动时(天空盒也跟着移动),纹理会被拉伸。 如何解决这个问题?
代码:
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
textureCube.format = THREE.RGBFormat;
var shader = THREE.ShaderUtils.lib[ "cube" ];
shader.uniforms[ "tCube" ].value = textureCube;

cubematerial = new THREE.ShaderMaterial({
    fragmentShader: shader.fragmentShader,
    vertexShader: shader.vertexShader,
    uniforms: shader.uniforms,
    depthWrite: false,
    side: THREE.BackSide
});
skyBox = new THREE.Mesh(new THREE.CubeGeometry(1000,1000,1000), cubematerial);
camera.add(skyBox);
2个回答

2
所以,在研究了Three.js的示例之后,我找到了一种方法来做到这一点。 http://learningthreejs.com/blog/2011/08/15/lets-do-a-sky/已经过时了。示例中使用的方法是将skybox添加到第二个场景中,并使用固定相机渲染两个场景。请查看webgl_materials_cars.html示例。
此外,由于我使用分配给角色的第三人称相机,因此必须从角色相机获取世界旋转到skybox相机。这可以在渲染时完成:
function render(){
<...>
    skyboxCamera.rotation.setEulerFromRotationMatrix( new THREE.Matrix4().extractRotation( camera.matrixWorld ), skyboxCamera.eulerOrder );
    renderer.render(skyboxScene, skyboxCamera);
    renderer.render(scene, camera);
<...>
}

1

我知道这是一个封闭式问题,但我想提供一种替代方案,不需要额外的场景,供未来的寻求者参考:

  1. 首先阅读并遵循本教程:http://learningthreejs.com/blog/2011/08/15/lets-do-a-sky/

  2. 现在创建以下着色器(我将其添加到了three.js的ShaderLib中,但如果您不想干扰three.js的源代码,则可以将其添加到外部):

    'skybox': {
    
    uniforms: { "tCube": { type: "t", value: null },
                "tFlip": { type: "f", value: -1 } },
    
    vertexShader: [
    
        "varying vec3 vWorldPosition;",
    
        THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ],
    
        "void main() {",
    
        "   vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
        "   vWorldPosition = worldPosition.xyz;",
    
        "   gl_Position = projectionMatrix * modelViewMatrix * vec4( position + cameraPosition, 1.0 );",
    
            THREE.ShaderChunk[ "logdepthbuf_vertex" ],
    
        "}"
    
    ].join("\n"),
    
    fragmentShader: [
    
        "uniform samplerCube tCube;",
        "uniform float tFlip;",
    
        "varying vec3 vWorldPosition;",
    
        THREE.ShaderChunk[ "logdepthbuf_pars_fragment" ],
    
        "void main() {",
    
        "   gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",
    
            THREE.ShaderChunk[ "logdepthbuf_fragment" ],
    
        "}"
    
    ].join("\n")
    

    },

  3. 像这样创建您的天空盒:

        // urls是要使用的纹理列表
    var cubemap = THREE.ImageUtils.loadTextureCube(urls); 
    cubemap.format = THREE.RGBFormat; 
    
    var shader = THREE.ShaderLib['skybox']; // 初始化我们上面创建的天空盒着色器
    shader.uniforms['tCube'].value = cubemap; // 将纹理应用于着色器
    
    // 创建着色器材料
    var skyBoxMaterial = new THREE.ShaderMaterial( {
      fragmentShader: shader.fragmentShader,
      vertexShader: shader.vertexShader,
      uniforms: shader.uniforms,
      depthWrite: false,
      side: THREE.BackSide
    });
    
    // 创建天空盒网格
    var skybox = new THREE.Mesh(
      new THREE.CubeGeometry(1000, 1000, 1000),
      skyBoxMaterial
    );
    
            // 这很重要!否则,在将相机移动太远后,天空盒将被裁剪。
    skybox.frustumCulled = false;
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接