在过去的两个月中,我学到了很多关于three.js和javascript的知识。我现在已经更深入地处理着色器,并且我曾经看到一个在网络上创建程序化行星的好例子。我发现球形几何体很有趣,因为它们的非欧几里德几何体使它们成为对纹理的很好挑战。
我在这里显示了主要代码。我的问题是纹理渲染不起作用。
我已经测试了程序的各个组件。着色器和行星类,所有功能均正常工作。
问题是渲染器。我需要这个不仅可以显示场景,还可以创建纹理。在功能中
textureGeneratorMaterial
(下)renderer.render(textureScene, textureCamera, texture, true);
被激活,我只得到黑屏。在调用函数renderer.render(scene, camera);
之后,我的意思是应该看到正常的场景。程序是否仍留在纹理场景中?如果在renderer.render(scene, camera)
中也调用了渲染器,为什么textureGeneratorMaterial
不起作用?
我已经尝试创建第二个渲染器,但这也不起作用。目前,我不知道该怎么办,因为我不了解原因。有人知道为什么渲染器不想要我想要的方式吗?
var camera, controls, scene, renderer, container;
var sunLight, ambientlight;
var test1, test2, test3, test4;
function main() {
init();
animate();
}
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
container = document.getElementById('container');
renderer.setSize(container.clientWidth, container.clientHeight);
container.appendChild( renderer.domElement );
var aspect = container.clientWidth / container.clientHeight;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
camera = new THREE.PerspectiveCamera( 45, container.clientWidth / container.clientHeight, 1, 10000 );
camera.position.set(0, 0, 20);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = true;
controls.enabled = true;
controls.target.set(0, 0, 0);
//-------------
sunLight = new THREE.PointLight(new THREE.Color(0xffffff), 1.0);
sunLight.position.set(100, 0, 0);
scene.add(sunLight);
ambientlight = new THREE.AmbientLight( 0xF0F0F0 ); // soft white light
scene.add( ambientlight );
var maps = generateTextures(); //--here is the problem---
/* -----used ro check "function textureGeneratorMaterial(index)" works------
var plane = new THREE.Mesh(
new THREE.PlaneGeometry(1024, 1024),
textureGeneratorMaterial(0)
);
scene.add( plane );
*/
/*-----used ro check "Planet class" works------
for(var i = 0; i <6;i++){
maps.textureMaps[i].texture = new THREE.TextureLoader().load("img/Cay_sand.jpeg");
maps.bumpMaps[i].texture = new THREE.TextureLoader().load("img/Cay_sand.jpeg");
}
*/
scene.add(new Planet(5, maps.textureMaps, maps.bumpMaps)); // works correct
}//-------End init----------
function animate() {
requestAnimationFrame( animate );
render();
}//-------End animate----------
function render() {
document.getElementById("demo1").innerHTML = test1;
document.getElementById("demo2").innerHTML = test2;
document.getElementById("demo3").innerHTML = test3;
document.getElementById("demo4").innerHTML = test4;
camera.updateMatrixWorld();
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}//-------End render----------
function generateTextures() {
var textureMaps = [];
var bumpMaps = [];
var resolution = 1024;
for (var index = 0; index < 6; index++) {
var texture = new THREE.WebGLRenderTarget(resolution, resolution, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat});
var textureCamera = new THREE.OrthographicCamera(-resolution/2, resolution/2, resolution/2, -resolution/2, -100, 100);
textureCamera.position.z = 10;
var textureScene = new THREE.Scene();
var plane = new THREE.Mesh(
new THREE.PlaneGeometry(resolution, resolution),
textureGeneratorMaterial(index)
);
plane.position.z = -10;
textureScene.add(plane);
// renderer.render(textureScene, textureCamera, texture, true);
var buffer = new Uint8Array(resolution * resolution * 4);
var gl = renderer.getContext();
gl.readPixels( 0, 0, resolution, resolution, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
textureMaps.push(texture);
bumpMaps.push({image: {data: buffer, height: resolution, width: resolution}});
}
return {textureMaps: textureMaps, bumpMaps: bumpMaps};
}
答案 0 :(得分:0)
好的,我找到了解决方案。我坚信这取决于渲染器,并且在首次调用它时,它仍将被困在纹理目标中。 在three.js中,可以重置渲染目标,如果这样做,Three.js似乎将其视为需要初始化,并接受对渲染器的调用以渲染主场景。
我添加了以下这一行:renderer.setRenderTarget(null);
见下文
function generateTextures() {
var textureMaps = [];
var bumpMaps = [];
var resolution = 2048;
for (var index = 0; index < 6; index++) {
var texture = new THREE.WebGLRenderTarget(resolution, resolution, {minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat});
var textureCamera = new THREE.OrthographicCamera(-resolution/2, resolution/2, resolution/2, -resolution/2, -100, 100);
textureCamera.position.z = 10;
var textureScene = new THREE.Scene();
var plane = new THREE.Mesh(
new THREE.PlaneGeometry(resolution, resolution),
textureGeneratorMaterial(index)
);
plane.position.z = -10;
textureScene.add(plane);
renderer.render(textureScene, textureCamera, texture, true);
var buffer = new Uint8Array(resolution * resolution * 4);
var gl = renderer.getContext();
gl.readPixels( 0, 0, resolution, resolution, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
textureMaps.push(texture);
bumpMaps.push({image: {data: buffer, height: resolution, width: resolution}});
renderer.setRenderTarget(null);
}
return {textureMaps: textureMaps, bumpMaps: bumpMaps};
}
在像我看到的示例这样的旧版本中,这不是必需的。但这并不意味着批评。这是一个干净的解决方案。因此,三个人总是知道需要进行渲染器操作。