Почему мой элемент canvas показывает только черный экран?

#javascript #three.js

#javascript #three.js

Вопрос:

Я настраиваю средство просмотра 3D-ресурсов в Three.js. Я запускаю код на сервере Plesk, предоставленном университетом, и связываю его через Dreamweaver. Я абсолютный новичок в JS, и во многих темах и публикациях предлагалось, чтобы я заключал свой код в 'init();' функцию. После этого и устранения всех ошибок, которые были в коде, теперь отображается черный экран, а не 3D-модель, которую он показывал бы раньше.

Я потратил целый день на проверку ошибок, устраняя проблемы, которые у меня возникали, которые включали в себя ‘canvas’, не созданный внутри 'container' div, и 'onWindowResize' функцию. Все эти проблемы были решены, и, по-видимому, ошибок в коде нет. У меня есть окружающее освещение в коде, и там был рабочий скайбокс, так что я уверен, что это не проблема с положением камеры или отсутствием освещения.

Я знаю, что вам нужно как можно меньше кода, но я понятия не имею, откуда берется проблема, поэтому большая часть кода на странице находится здесь :

 <div id="container" ></div>
    <script>
    let container;
    let camera;
    let controls;
    let scene;
    let renderer;

    init();
    animate;

    function init(){

    // Renderer - WebGL is primary Renderer for Three.JS
    var renderer = new THREE.WebGLRenderer({antialias : true});
            renderer.setClearColor(0xEEEEEE, 0.5);


    // Selects and applies parameters to the 'Container' div
    var container = document.querySelector("#container");
            container.appendChild(renderer.domElement);
            renderer.setSize(container.clientWidth, container.clientHeight);

    // Perspective Camera (FOV, aspect ratio based on container, near, far)
    var camera = new THREE.PerspectiveCamera( 75, container.clientWidth / container.clientHeight, 0.1, 1000);
        camera.position.x = 750;
    camera.position.y = 500;
    camera.position.z = 1250;

    // Scene will contain all objects in the world
    var scene =  new THREE.Scene();

    //Lighting (Colour, intensity)
    var light1Ambient = new THREE.AmbientLight(0xffffff , 0.3);
            scene.add(light1Ambient);

    var light1Point = new THREE.PointLight(0xfff2c1, 0.5, 0, 2);
            scene.add(light1Point);

    var light2Point = new THREE.PointLight(0xd6e3ff, 0.4, 0, 2);
            scene.add(light2Point);

    // All basic Geomety

    var newPlane = new THREE.PlaneGeometry(250,250,100,100);

        const mesh = new THREE.Mesh(
    new THREE.BoxGeometry(1, 1, 1),
    new THREE.MeshBasicMaterial( {color: 0x00ff00} )
                );
        scene.add(mesh);

    // Water
    water = new THREE.Water(newPlane,
            {
                textureWidth: 512,
                textureHeight: 512,
                waterNormals: new THREE.TextureLoader().load( 'http://up826703.ct.port.ac.uk/CTPRO/textures/waternormals.jpg', function ( texture ) {

                texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

                } ),
                alpha: 1.0,
                sunDirection: light1Point.position.clone().normalize(),
                sunColor: 0xffffff,
                waterColor: 0x001e0f,
                distortionScale: 0.5,
                fog: scene.fog !== undefined
                }
            );

            water.rotation.x = - Math.PI / 2;
            scene.add( water );


    // All Materials (Normal for Debugging) (Lambert: color)
    var material = new THREE.MeshLambertMaterial({color: 0xF3FFE2});
    var materialNew = new THREE.MeshBasicMaterial( {color: 0x00ff00} );



    // Skybox
    var skybox = new THREE.BoxGeometry(1000,1000, 1000);
    var skyboxMaterials =
            [
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_ft.jpg"), side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_bk.jpg"), side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_up.jpg"), side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_dn.jpg"), side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_rt.jpg"), side: THREE.DoubleSide }),
                new THREE.MeshBasicMaterial({map: new THREE.TextureLoader().load("http://up826703.ct.port.ac.uk/CTPRO/skybox/blue/bluecloud_lf.jpg"), side: THREE.DoubleSide }),
            ];

    var skyboxMaterial = new THREE.MeshFaceMaterial(skyboxMaterials);
    var skyMesh = new THREE.Mesh (skybox, skyboxMaterial);
    scene.add(skyMesh);

    //Grid Helper Beneath Ship
        scene.add(new THREE.GridHelper(250, 250));



    //OBJ Model Loading
    var objLoader = new THREE.OBJLoader();

    objLoader.load('http://up826703.ct.port.ac.uk/CTPRO/models/ship1.obj', function(object){
            scene.add(object);

    });

    // Object positioning

            water.position.y = -2.5;


    // Misc Positioning

            light1Point.position.z =20;
            light1Point.position.x = 25;


        // z - front-back position
            light2Point.position.z = -400;
        // x - left-right
            light2Point.position.x = -25;
        // y - up- down
            light2Point.position.y = 250;


            window.addEventListener("resize", onWindowResize, false);


        function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize(container.clientWidth, container.clientHeight);
    };


    };


    // Canvas adapts size based on changing windows size


    //Render loop

    var animate = function(){

        water.material.uniforms[ "time" ].value  = 1.0 / 120.0;
        function drawFrame(ts){
                var center = new THREE.Vector2(0,0);
            window.requestAnimationFrame(drawFrame);
                var vLength = newPlane.geometry.vertices.length;
                for (var i = 0; i < vLength; i  ) {
                var v = newPlane.geometry.vertices[i];
                var dist = new THREE.Vector2(v.x, v.y).sub(center);
                var size = 2.0;
                var magnitude = 8;
                v.z = Math.sin(dist.length()/-size   (ts/900)) * magnitude;
            }
    newPlane.geometry.verticesNeedUpdate = true;
    };
        requestAnimationFrame(animate)
        renderer.render(scene, camera);
        controls.update();

    }



    </script>


  

Я не профессионал, поэтому прошу прощения, если это слишком грубо для тех из вас, у кого есть опыт!
Я должен указать, что перед тем, как обернуть все это в init(); функцию, она работала идеально.

При работе я должен видеть грубо смоделированный корабль, сидящий в воде, с облачным скайбоксом. Элементы управления работали, и он автоматически поворачивался.

Прямо сейчас он ничего этого не делает. Загрузчик obj работает, как показано в журнале консоли Chrome OBJLoader: 1661.970703125ms но опять же, на самом деле ничего не отображается, это просто черный экран.

Спасибо всем, кто может мне помочь с этим!

Ответ №1:

эта строка

 animate;
  

требуется вызов функции

 animate();
  

Также вам, вероятно, нужно изменить приведенный ниже код, из которого вы создаете функцию animate

 var animate = function(){
  

К этому

 function animate(){
  

Причина в том, что именованные функции определяются при загрузке кода, но переменные var создаются при выполнении кода. Итак, с таким кодом, как этот

 init();
animate();

var animate = function(){ ...
  

animate на самом деле не существует в тот момент, когда код пытается его вызвать, тогда как с этим

 init();
animate();

function animate(){ ...
  

он существует

Вы также могли бы изменить порядок кода, чтобы, например, определить, animate прежде чем использовать, он должен работать.

 var animate = function(){ 
   ...
};

init();
animate();
  

Также кажется, что некоторые из них объявлены внутри, init что означает, что они недоступны для animate . Так, например

  var renderer = new THREE.WebGLRenderer({antialias : true});
  

объявляет новую переменную, renderer которую может видеть только init пользователь. Вы хотели установить renderer переменную, которая находится за пределами init , поэтому измените код на

  renderer = new THREE.WebGLRenderer({antialias : true});
  

controls никогда не определяется, поэтому вам, вероятно, нужно определить его или закомментировать

  controls.update();
  

Для

  // controls.update();
  

примечание: вы можете найти эти руководства полезными, хотя, если вы новичок в JavaScript, вам, вероятно, следует потратить время на изучение JavaScript

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

1. Привет, спасибо, что так быстро ответили! Я внедрил предложенные вами изменения, и теперь я вижу, что эта ошибка отображается для каждого кадра. Есть идеи относительно того, почему это может быть? Uncaught TypeError: Cannot read property 'render' of undefined

2. похоже, что в animate нет ссылок на контейнер и камеру, но да, код в беспорядке. Надеюсь, спрашивающий воспользуется советом прочитать несколько руководств по JavaScript. 😉

3. Спасибо за обновления, чувак. После того, что вы упомянули об удалении слова ‘var’, чтобы его можно было прочитать вне init, после этого возник ряд проблем, из-за которых я делал это на протяжении всего документа (следуя руководству). Кроме того, элементы управления orbit, у меня было кое-что для этого, что означало ‘update();’ должно работать, но я случайно удалил это. Но теперь это работает, большое спасибо за помощь, приятель, я действительно ценю это!