несколько вызовов средства визуализации не работают

#javascript #three.js

#javascript #three.js

Вопрос:

За последние два месяца я многое узнал о three.js и javascript. теперь я углубился в обработку шейдеров, и однажды я видел хороший пример создания процедурных планет в Интернете. Я нахожу сферические геометрии интересными, потому что их неевклидова геометрия делает их хорошей проблемой для текстур.

Я показал здесь основной код. моя проблема в том, что рендеринг текстур не работает. Я протестировал отдельные компоненты моей программы. Шейдер и класс planet, все функции работают корректно. проблема в средстве визуализации. Мне это нужно для отображения сцены, а также для создания текстур. Когда в функции 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. Вы проверяли, что сцена в generateTexrures отображается сама по себе, не будучи в текстуре? Вы пробовали заменить текстуру изображением, чтобы посмотреть, сработало ли это?

2. да, у меня есть, и все это работает

Ответ №1:

Хорошо, я нашел решение. Я был убежден, что это зависит от средства визуализации и что оно останется заблокированным в целевой текстуре при первом вызове. В 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};
}
  

В более старых версиях, подобных примеру, который я видел, в этом не было необходимости. Но это не критика. Это чистое решение. Таким образом, three всегда знает, что существует необходимость в действии средства визуализации.

Комментарии:

1. Да, параметр render target в render() был удален несколько выпусков назад, поэтому теперь необходимо определить через setRenderTarget() , следует ли использовать цель рендеринга или нет.