<commit_before>package h3d.pass;

class DirShadowMap extends Shadows {

	var customDepth : Bool;
	var depth : h3d.mat.DepthBuffer;
	var dshader : h3d.shader.DirShadow;
	var border : Border;
	var mergePass = new h3d.pass.ScreenFx(new h3d.shader.MinMaxShader());

	/**
		Shrink the frustum of the light to the bounds containing all visible objects
	**/
	public var autoShrink = true;
	/**
		For top down lights and cameras, use scene Z min/max to optimize shadowmap. Requires autoShrink
	**/
	public var autoZPlanes = false;
	/**
		Clamp the zFar of the frustum of the camera for bounds calculation
	**/
	public var maxDist = -1.0;
	/**
		Clamp the zNear of the frustum of the camera for bounds calculation
	**/
	public var minDist = -1.0;

	public function new( light : h3d.scene.Light ) {
		super(light);
		lightCamera = new h3d.Camera();
		lightCamera.orthoBounds = new h3d.col.Bounds();
		shader = dshader = new h3d.shader.DirShadow();
		border = new Border(size, size);
		customDepth = h3d.Engine.getCurrent().driver.hasFeature(AllocDepthBuffer);
		if( !customDepth ) depth = h3d.mat.DepthBuffer.getDefault();
	}

	override function set_mode(m:Shadows.RenderMode) {
		dshader.enable = m != None;
		return mode = m;
	}

	override function set_enabled(b:Bool) {
		dshader.enable = b && mode != None;
		return enabled = b;
	}

	override function set_size(s) {
		if( border != null && size != s ) {
			border.dispose();
			border = new Border(s, s);
		}
		return super.set_size(s);
	}

	override function dispose() {
		super.dispose();
		if( customDepth && depth != null ) depth.dispose();
		border.dispose();
	}

	public override function getShadowTex() {
		return dshader.shadowMap;
	}

	public dynamic function calcShadowBounds( camera : h3d.Camera ) {
		var bounds = camera.orthoBounds;
		var zMax = -1e9, zMin = 1e9;
		if( autoShrink ) {
			// add visible casters in light camera position
			var mtmp = new h3d.Matrix();
			var btmp = autoZPlanes ? new h3d.col.Bounds() : null;
			ctx.scene.iterVisibleMeshes(function(m) {
				if( m.primitive == null || !m.material.castShadows ) return;
				var b = m.primitive.getBounds();
				if( b.xMin > b.xMax ) return;

				var absPos = Std.isOfType(m.primitive, h3d.prim.Instanced) ? h3d.Matrix.I() : m.getAbsPos();
				if( autoZPlanes ) {
					btmp.load(b);
					btmp.transform(absPos);
					if( btmp.zMax > zMax ) zMax = btmp.zMax;
					if( btmp.zMin < zMin ) zMin = btmp.zMin;
				}

				mtmp.multiply3x4(absPos, camera.mcam);

				var p = new h3d.col.Point(b.xMin, b.yMin, b.zMin);
				p.transform(mtmp);
				bounds.addPoint(p);
<commit_msg>Can shrink DirShadowMap given a scene subset.<commit_after>package h3d.pass;

class DirShadowMap extends Shadows {

	var customDepth : Bool;
	var depth : h3d.mat.DepthBuffer;
	var dshader : h3d.shader.DirShadow;
	var border : Border;
	var mergePass = new h3d.pass.ScreenFx(new h3d.shader.MinMaxShader());
	var boundingObject : h3d.scene.Object;

	/**
		Shrink the frustum of the light to the bounds containing all visible objects
	**/
	public var autoShrink = true;
	/**
		For top down lights and cameras, use scene Z min/max to optimize shadowmap. Requires autoShrink
	**/
	public var autoZPlanes = false;
	/**
		Clamp the zFar of the frustum of the camera for bounds calculation
	**/
	public var maxDist = -1.0;
	/**
		Clamp the zNear of the frustum of the camera for bounds calculation
	**/
	public var minDist = -1.0;

	public function new( light : h3d.scene.Light ) {
		super(light);
		lightCamera = new h3d.Camera();
		lightCamera.orthoBounds = new h3d.col.Bounds();
		shader = dshader = new h3d.shader.DirShadow();
		border = new Border(size, size);
		customDepth = h3d.Engine.getCurrent().driver.hasFeature(AllocDepthBuffer);
		if( !customDepth ) depth = h3d.mat.DepthBuffer.getDefault();
	}

	override function set_mode(m:Shadows.RenderMode) {
		dshader.enable = m != None;
		return mode = m;
	}

	override function set_enabled(b:Bool) {
		dshader.enable = b && mode != None;
		return enabled = b;
	}

	override function set_size(s) {
		if( border != null && size != s ) {
			border.dispose();
			border = new Border(s, s);
		}
		return super.set_size(s);
	}

	override function dispose() {
		super.dispose();
		if( customDepth && depth != null ) depth.dispose();
		border.dispose();
	}

	public override function getShadowTex() {
		return dshader.shadowMap;
	}

	public dynamic function calcShadowBounds( camera : h3d.Camera ) {
		var bounds = camera.orthoBounds;
		var zMax = -1e9, zMin = 1e9;
		if( autoShrink ) {
			// add visible casters in light camera position
			var mtmp = new h3d.Matrix();
			var btmp = autoZPlanes ? new h3d.col.Bounds() : null;
			var obj = boundingObject != null ? boundingObject : ctx.scene;
			obj.iterVisibleMeshes(function(m) {
				if( m.primitive == null || !m.material.castShadows ) return;
				var b = m.primitive.getBounds();
				if( b.xMin > b.xMax ) return;

				var absPos = Std.isOfType(m.primitive, h3d.prim.Instanced) ? h3d.Matrix.I() : m.getAbsPos();
				if( autoZPlanes ) {
					btmp.load(b);
					btmp.transform(absPos);
					if( btmp.zMax > zMax ) zMax = btmp.zMax;
					if( btmp.zMin < zMin ) zMin = btmp.zMin;
				}

				mtmp.multiply3x4(absPos, camera.mcam);

				var p = new h3d.col.Point(b.xMin, b.yMin, b.zMin);
				p.transform(mtmp);
				bounds.addPoint(p);

{'fraction_non_alphanumeric': 0.12707078313253012, 'fraction_numerical': 0.010353915662650603, 'mean_word_length': 3.3981788079470197, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2325685', 'n_tokens_mistral': 2108, 'n_tokens_neox': 1923, 'n_words': 501}