HeapsIO / heaps

Heaps : Haxe Game Framework
http://heaps.io
MIT License
3.2k stars 339 forks source link

h3d.scene.MeshBatch instances missing shadows #841

Open seanpringle opened 4 years ago

seanpringle commented 4 years ago

Why does only one instance of a mesh batch render shadows?

heaps-meshbatch-shadows

Ubuntu 20.04 / Haxe 4.1.1 / Heaps 1.8.0 / Hashlink 1.11 hlsdl

Sample code is below. If I change it to use either separate mesh objects or single-instance mesh batches, then all shadows appear as expected.

Looking at #801 I tried adjusting DirShadowMap.calcShadowBounds and the light camera camera.orthoBounds and managed to get some additional shadows appearing, but never everything on every visible instance. Also, my naive expansion of the camera.orthoBounds volume messed up shadow intensity and radius so I'm guessing that's the wrong approach for a zooming out on large scene?

The instances are being emitted in update() rather than init() because the game that shows this problem is using procedural generation, so most of the scene/world doesn't exist unless it's being viewed by the camera.

class Main extends hxd.App {

  private var batchCube:h3d.scene.MeshBatch;
  private var batchPlatform:h3d.scene.MeshBatch;

  public static function main() {
    return new Main();
  }

  public function new() {
    super();
  }

  override function init() {
    super.init();

    hxd.Window.getInstance().resize(1000,600);

    var cube = new h3d.prim.Cube(1,1,1,true);
    cube.unindex();
    cube.addNormals();
    cube.addUVs();

    var platform = new h3d.prim.Cube(10,10,1,true);
    platform.unindex();
    platform.addNormals();
    platform.addUVs();

    batchCube = new h3d.scene.MeshBatch(cube, s3d);
    batchPlatform = new h3d.scene.MeshBatch(platform, s3d);

    var dirlight = new h3d.scene.fwd.DirLight(new h3d.Vector(0.5,0,-1), s3d);
    dirlight.color.load(new h3d.Vector(0.5,0.5,0.5));

    s3d.lightSystem.ambientLight.set(0.75,0.75,0.75);

    var shadow = s3d.renderer.getPass(h3d.pass.DefaultShadowMap);
    shadow.power /= 15;

    s3d.camera.zNear = 1;
    s3d.camera.zFar = 1000;
    s3d.camera.pos.set(0, 15, 30);
    s3d.camera.target.set(0, 0, 0);

    new h3d.scene.CameraController(s3d).loadFromCamera();
  }

  override function update(dt:Float) {
    batchCube.begin(2);

    batchCube.x = -6;
    batchCube.y = 0;
    batchCube.z = 0.5;
    batchCube.material.color.load(new h3d.Vector(0.75,0,0));
    batchCube.material.mainPass.enableLights = true;
    batchCube.material.shadows = true;
    batchCube.material.castShadows = true;
    batchCube.material.receiveShadows = true;
    batchCube.emitInstance();

    batchCube.x = 6;
    batchCube.y = 0;
    batchCube.z = 0.5;
    batchCube.material.color.load(new h3d.Vector(0.75,0,0));
    batchCube.material.mainPass.enableLights = true;
    batchCube.material.shadows = true;
    batchCube.material.castShadows = true;
    batchCube.material.receiveShadows = true;
    batchCube.emitInstance();

    batchPlatform.begin(2);

    batchPlatform.x = -6;
    batchPlatform.y = 0;
    batchPlatform.z = -0.5;
    batchPlatform.material.color.load(new h3d.Vector(0.5,0.5,0.5));
    batchPlatform.material.mainPass.enableLights = true;
    batchPlatform.material.shadows = true;
    batchPlatform.material.castShadows = true;
    batchPlatform.material.receiveShadows = true;
    batchPlatform.emitInstance();

    batchPlatform.x = 6;
    batchPlatform.y = 0;
    batchPlatform.z = -0.5;
    batchPlatform.material.color.load(new h3d.Vector(0.5,0.5,0.5));
    batchPlatform.material.mainPass.enableLights = true;
    batchPlatform.material.shadows = true;
    batchPlatform.material.castShadows = true;
    batchPlatform.material.receiveShadows = true;
    batchPlatform.emitInstance();
  }
}
ncannasse commented 4 years ago

I think the problem might be related to MeshBatch not returning correct result on its getBounds()