我正在尝试将天空盒分配给播放器相机。 当相机移动时(天空箱随之移动),纹理会变得拉长。 如何摆脱这个?
代码:
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);
答案 0 :(得分:2)
因此,在深入研究Three.js示例之后,我找到了一种方法。 http://learningthreejs.com/blog/2011/08/15/lets-do-a-sky/已过时。示例中使用的方法是使用固定摄像头将天空盒添加到第二个场景中,并渲染两个场景。请查看webgl_materials_cars.html示例。
另外,因为我使用分配给角色的第三人称相机,我必须从角色相机到天空盒相机进行世界旋转。这可以在渲染时完成:
function render(){
<...>
skyboxCamera.rotation.setEulerFromRotationMatrix( new THREE.Matrix4().extractRotation( camera.matrixWorld ), skyboxCamera.eulerOrder );
renderer.render(skyboxScene, skyboxCamera);
renderer.render(scene, camera);
<...>
}
答案 1 :(得分:0)
我知道这是一个封闭的问题,但我想为未来的寻求者提供一个不需要额外场景的替代方案:
首先阅读并阅读本教程:http://learningthreejs.com/blog/2011/08/15/lets-do-a-sky/
现在创建以下着色器(我将其添加到three.js ShaderLib中,但如果您不想用三个源代码添加它,请将其添加到外部):
'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")
},
像这样创建你的天空盒:
// urls is a list of textures to use
var cubemap = THREE.ImageUtils.loadTextureCube(urls);
cubemap.format = THREE.RGBFormat;
var shader = THREE.ShaderLib['skybox']; // init the skybox shader we created above
shader.uniforms['tCube'].value = cubemap; // apply textures to shader
// create shader material
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
});
// create skybox mesh
var skybox = new THREE.Mesh(
new THREE.CubeGeometry(1000, 1000, 1000),
skyBoxMaterial
);
// THIS IS IMPORTANT! or the skybox will get culled after you move the camera too far..
skybox.frustumCulled = false;