多次调用渲染器无效

时间:2020-08-18 00:23:21

标签: javascript three.js

在过去的两个月中,我学到了很多关于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};
}

1 个答案:

答案 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};
}

在像我看到的示例这样的旧版本中,这不是必需的。但这并不意味着批评。这是一个干净的解决方案。因此,三个人总是知道需要进行渲染器操作。