really weird ghosty shadows using three.js

2k views Asked by At

I'm using three.js to make some solar system, all my objects are sphere (suns and planets), but I found this really weird and ghosty square shadow: enter image description here enter image description here

Another ghost shadow seems to be that, the shadow that sphere A casts on sphere B, appears on both the front and back side of sphere B, like this: enter image description here

I am so confused since I don't really remember create any square stuff and I've checked my code for like million times without any finding.

Finally, I dismissed all the lights in the world, and set the background to light color, it appears: enter image description here

But when I move my camera to the back of it, it just disappears, like a "1-dimension" square created by some high-level creature from the universe. enter image description here

This is my final project which is due next week, I really don't know how to explain this to my professor.

Appreciate any help! Thanks a lot!

below is my code that creates objects:

function init() {
    container = document.createElement('div');
    document.body.appendChild(container);
    renderer    = new THREE.WebGLRenderer({
        antialias   : true, alpha: true
    });
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    renderer.shadowMapEnabled   = true;
    container.appendChild(renderer.domElement);

    scene   = new THREE.Scene();
    scene.updateMatrixWorld(true);

    camera  = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000 );
    camera.position.set(5,5,5);

    controls = new THREE.TrackballControls( camera );
    controls.rotateSpeed = 1.0;
    controls.zoomSpeed = 1.2;
    controls.panSpeed = 0.8;
    controls.noZoom = false;
    controls.staticMoving = false;
    controls.dynamicDampingFactor = 0.2;

    var light   = new THREE.AmbientLight( 0x222222 );
    scene.add( light );  // this is the light I tried to close

    var light   = new THREE.DirectionalLight( 0xffffff, 0 );
    light.position.set(0,0,5);
    scene.add( light ); // this is the light I tried to close
    light.castShadow    = true;
    light.shadowCameraNear  = 0.01;
    light.shadowCameraFar   = 15;
    light.shadowCameraFov   = 45;

    light.shadowCameraLeft  = -1;
    light.shadowCameraRight =  1;
    light.shadowCameraTop   =  1;
    light.shadowCameraBottom= -1;
    //light.shadowCameraVisible = true

    light.shadowBias    = 0.001;
    light.shadowDarkness    = 0.2;

    light.shadowMapWidth    = 1024;
    light.shadowMapHeight   = 1024;
    //////////////////////////////////////////////////////////////////////////////////
    //      render the scene                        //
    //////////////////////////////////////////////////////////////////////////////////
    onRenderFcts.push(function(){
        controls.update();
        renderer.render( scene, camera );       
    });
    window.addEventListener('keydown', onKeyDown, false);
    renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
    renderer.domElement.addEventListener( 'click', onMouseClick, false );
}
function createSun (){
    var geometry    = new THREE.SphereGeometry(0.5, 32, 32)
    var texture = THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/sunmap.jpg')
    var material    = new THREE.MeshPhongMaterial({
        map : texture,
        bumpMap : texture,
        bumpScale: 0.05,
        emissive: new THREE.Color('#ff9933'),
        specular: new THREE.Color('#ffff66'),
        shininess: 800,
        wireframeLinewidth: 500

    })
    var mesh    = new THREE.Mesh(geometry, material)
    mesh.receiveShadow = true;
    mesh.castShadow = true;
    mesh.matrixWorldNeedsUpdate = true;
    return mesh 
}
function createMoon (){
    var geometry    = new THREE.SphereGeometry(0.5, 32, 32)
    var material    = new THREE.MeshPhongMaterial({
        map : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonmap1k.jpg'),
        bumpMap : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonbump1k.jpg'),
        bumpScale: 0.002,
    })
    var mesh    = new THREE.Mesh(geometry, material)
    return mesh 
}
function add_objects() {
    // star field
    var geometry    = new THREE.SphereGeometry(900, 32, 32);
    var material    = new THREE.MeshBasicMaterial({
        map : THREE.ImageUtils.loadTexture('images/earthcloudmap.jpg'),
        side    : THREE.BackSide
    });
    var starSphere  = new THREE.Mesh(geometry, material);
    scene.add(starSphere);

    // reference points
    originPoint = new THREE.Object3D();
    scene.add(originPoint);
    onRenderFcts.push(function (delta, now) {
        originPoint.rotation.x += rotateFactor * delta;
        originPoint.rotation.z += rotateFactor * delta;
    });

    sunsBasePoint = new THREE.Object3D();
    originPoint.add(sunsBasePoint);
    onRenderFcts.push(function (delta, now) {
        sunsBasePoint.rotation.y += rotateFactor * delta;
        sunsBasePoint.rotation.z += rotateFactor * delta;
    });
    // stars
    sun1 = createSun();
    sun1.name = 'sun1';
    sun1.position.set(0,0,-1.5);
    sunsBasePoint.add(sun1);
    onRenderFcts.push(function (delta, now) {
        sun1.rotation.y -= 1/2 * delta;
        sun1.rotation.z += 1/4 * delta;
    });
    objects.push(sun1);
    sun2 = createSun();
    sun2.name = 'sun2';
    sun2.position.set(1,-1.5,0);
    sun2.scale.multiplyScalar(0.8)
    sunsBasePoint.add(sun2);
    onRenderFcts.push(function (delta, now) {
        sun2.rotation.x -= 1/4 * delta;
        sun2.rotation.y += 1/8 * delta;
    });
    objects.push(sun2);
    sun3 = createSun();
    sun3.name = 'sun3';
    sun3.position.set(-1,1,1.5);
    sun3.scale.multiplyScalar(1.5);
    sunsBasePoint.add(sun3);
    onRenderFcts.push(function (delta, now) {
        sun3.rotation.y -= 1/8 * delta;
        sun3.rotation.x += 1/4 * delta;
    });
    objects.push(sun3);
    threeBodyPlanet = createMoon();
    threeBodyPlanet.name = "Three Body Planet";
    threeBodyPlanet.position.set(0.5,-0.5,0.5);
    threeBodyPlanet.scale.multiplyScalar(1/5);
    threeBodyPlanet.receiveShadow   = true;
    threeBodyPlanet.castShadow  = true;
    originPoint.add(threeBodyPlanet);
    objects.push(threeBodyPlanet);
}
function debug() {
    var debugaxis = function(axisLength){
        //Shorten the vertex function
        function v(x,y,z){ 
                return new THREE.Vertex(new THREE.Vector3(x,y,z)); 
        }

        //Create axis (point1, point2, colour)
        function createAxis(p1, p2, color){
                var line, lineGeometry = new THREE.Geometry(),
                lineMat = new THREE.LineBasicMaterial({color: color, lineWidth: 1});
                lineGeometry.vertices.push(p1, p2);
                line = new THREE.Line(lineGeometry, lineMat);
                scene.add(line);
        }

        createAxis(v(-axisLength/25, 0, 0), v(axisLength, 0, 0), 0xFF0000);
        createAxis(v(0, -axisLength/25, 0), v(0, axisLength, 0), 0x00FF00);
        createAxis(v(0, 0, -axisLength/25), v(0, 0, axisLength), 0x0000FF);
    };

    //To use enter the axis length
    debugaxis(100);
    // lens flares

    var textureFlare0 = THREE.ImageUtils.loadTexture( "lensflare0.png" );
    var textureFlare2 = THREE.ImageUtils.loadTexture( "lensflare2.png" );
    var textureFlare3 = THREE.ImageUtils.loadTexture( "lensflare3.png" );

    addLight( 0.55, 0.9, 0.5, 0, 0, 100 );
    //addLight( 0.08, 0.8, 0.5,    0, 0, -10 );
    //addLight( 0.995, 0.5, 0.9, 50, 50, -10 );

    function addLight( h, s, l, x, y, z ) {

        var light = new THREE.PointLight( 0xffffff, 1.5, 4500 );
        light.color.setHSL( h, s, l );
        light.position.set( x, y, z );
        scene.add( light );

        var flareColor = new THREE.Color( 0xffffff );
        flareColor.setHSL( h, s, l + 0.5 );

        var lensFlare = new THREE.LensFlare( textureFlare0, 700, -0.1, THREE.AdditiveBlending, flareColor );

        lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
        lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
        lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );

        lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending );
        lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending );
        lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending );
        lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending );

        lensFlare.customUpdateCallback = lensFlareUpdateCallback;
        lensFlare.position = light.position;
        lensFlare.size = 70;
        scene.add( lensFlare );

    }
    function lensFlareUpdateCallback( object ) {

    var f, fl = object.lensFlares.length;
    var flare;
    var vecX = -object.positionScreen.x * 2;
    var vecY = -object.positionScreen.y * 2;
    //var size = object.size ? object.size : 1000;

    for( f = 0; f < fl; f++ ) {

           flare = object.lensFlares[ f ];

           flare.x = object.positionScreen.x + vecX * flare.distance;
           flare.y = object.positionScreen.y + vecY * flare.distance;

           //flare.scale = size / camera.distance;
           flare.rotation = 0;

    }

    object.lensFlares[ 2 ].y += 0.025;
    object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 );

    };
}

-------------updating-------------

Thanks for yaku's help, I found that the weird square is indeed because of the camera shadow,like in the pics below: enter image description here enter image description here

After I increased the shadow parameters, the square shadow seems to be gone, but the remaining shadows on the back of the spheres are still kind of weird in its texture, like this: enter image description here enter image description here

It looks like very low resolution shadow made of small squares, why?

Thanks a lot!

------one more question------

All yaku said works!

But I found out there's no shadows of the spheres themselves. enter image description here

I called

mesh.castShadow = mesh.receiveShadow = true;

every time I create the spheres.

I remember there were these shadows now they are gone...

What might the reason of it?

Thanks!

1

There are 1 answers

4
yaku On BEST ANSWER

Not sure, but have you checked the shadow camera dimensions? Looks like the frustum of the shadow camera could be too small, and what you are seeing could be everything inside the frustum is in shadow and the rest unaffected. The light square could be some weird remnant of the shadow camera, shadow maps can be unwieldy..

Set light.shadowCameraVisible = true; and adjust the other shadow parameters so that the box encapsulates the whole scene.