Selaa lähdekoodia

review material setup & properties

ncannasse 7 vuotta sitten
vanhempi
commit
d79c63acf1

+ 2 - 2
h3d/mat/BaseMaterial.hx

@@ -2,13 +2,13 @@ package h3d.mat;
 import h3d.mat.Data;
 import h3d.mat.Pass;
 
-class BaseMaterial implements hxd.impl.Serializable {
+class BaseMaterial extends hxd.impl.AnyProps implements hxd.impl.Serializable {
 
 	@:s var passes : Pass;
 	@:s public var name : String;
 	public var mainPass(get, never) : Pass;
 
-	public function new(?shader:hxsl.Shader) {
+	function new(?shader:hxsl.Shader) {
 		if( shader != null )
 			addPass(new Pass("default",null)).addShader(shader);
 	}

+ 121 - 23
h3d/mat/Material.hx

@@ -1,11 +1,25 @@
 package h3d.mat;
 
+@:enum private abstract DefaultKind(String) {
+	var Opaque = "Opaque";
+	var Alpha = "Alpha";
+	var AlphaKill = "AlphaKill";
+	var Add = "Add";
+	var SoftAdd = "SoftAdd";
+}
+
+private typedef DefaultProps = {
+	var kind : DefaultKind;
+	var shadows : Bool;
+	var culling : Bool;
+	var light : Bool;
+}
+
 class Material extends BaseMaterial {
 
 	var mshader : h3d.shader.BaseMesh;
 	var normalShader : h3d.shader.NormalMap;
 
-	public var props(default, set) : Any;
 	public var model : hxd.res.Resource;
 
 	public var shadows(get, set) : Bool;
@@ -23,7 +37,7 @@ class Material extends BaseMaterial {
 	public var specularPower(get, set) : Float;
 	public var blendMode(default, set) : BlendMode;
 
-	public function new(?texture) {
+	function new(?texture) {
 		mshader = new h3d.shader.BaseMesh();
 		blendMode = None;
 		super(mshader);
@@ -115,19 +129,7 @@ class Material extends BaseMaterial {
 			case Alpha:
 				mainPass.depthWrite = true;
 				mainPass.setPassName("alpha");
-			case Add:
-				mainPass.depthWrite = false;
-				mainPass.setPassName("additive");
-			case SoftAdd:
-				mainPass.depthWrite = false;
-				mainPass.setPassName("additive");
-			case Multiply:
-				mainPass.depthWrite = false;
-				mainPass.setPassName("additive");
-			case Erase:
-				mainPass.depthWrite = false;
-				mainPass.setPassName("additive");
-			case Screen:
+			case Add, SoftAdd, Multiply, Erase, Screen:
 				mainPass.depthWrite = false;
 				mainPass.setPassName("additive");
 			}
@@ -195,18 +197,115 @@ class Material extends BaseMaterial {
 		return t;
 	}
 
-	function set_props(p) {
-		this.props = p;
-		refreshProps();
-		return p;
+	// -- PROPS
+
+	/*
+		This is called after a model has been loaded and the material textures setup.
+		It will build the properties for this material, loading them from storage if necessary
+	*/
+	public function getDefaultModelProps() : Any {
+		var props : DefaultProps = getDefaultProps();
+		switch( blendMode ) {
+		case Alpha:
+			props.kind = Alpha;
+		case Add:
+			props.kind = Add;
+			props.culling = false;
+			props.shadows = false;
+			props.light = false;
+		case None:
+			// default
+		default:
+			throw "Unsupported HMD material " + blendMode;
+		}
+		return props;
 	}
 
-	public function refreshProps() {
-		if( props != null && mainPass != null ) MaterialSetup.current.applyProps(this);
+	override function getDefaultProps( ?type : String ) : Any {
+		var props : DefaultProps;
+		switch( type ) {
+		case "particles3D", "trail3D":
+			props = {
+				kind : Alpha,
+				shadows : false,
+				culling : false,
+				light : true,
+			};
+		case "ui":
+			props = {
+				kind : Alpha,
+				shadows : false,
+				culling : false,
+				light : false,
+			};
+		default:
+			props = {
+				kind : Opaque,
+				shadows : true,
+				culling : true,
+				light : true,
+			};
+		}
+		return props;
 	}
 
-	#if hxbit
+	override function refreshProps() {
+		if( props == null || mainPass == null ) return;
+		var props : DefaultProps = props;
+		switch( props.kind ) {
+		case Opaque, AlphaKill:
+			mainPass.setBlendMode(None);
+			mainPass.depthWrite = true;
+			mainPass.setPassName("default");
+		case Alpha:
+			mainPass.setBlendMode(Alpha);
+			mainPass.depthWrite = true;
+			mainPass.setPassName("alpha");
+		case Add:
+			mainPass.setBlendMode(Add);
+			mainPass.depthWrite = false;
+			mainPass.setPassName("additive");
+		case SoftAdd:
+			mainPass.setBlendMode(SoftAdd);
+			mainPass.depthWrite = false;
+			mainPass.setPassName("additive");
+		}
+		var tshader = textureShader;
+		if( tshader != null ) {
+			tshader.killAlpha = props.kind == AlphaKill;
+			tshader.killAlphaThreshold = 0.5;
+		}
+		mainPass.culling = props.culling ? Back : None;
+		mainPass.enableLights = props.light;
+		shadows = props.shadows;
+		if( shadows )
+			getPass("shadow").culling = mainPass.culling;
+	}
 
+	#if js
+	override function editProps() {
+		return new js.jquery.JQuery('
+			<dl>
+				<dt>Kind</dt>
+				<dd>
+					<select field="kind">
+						<option value="Opaque">Opaque</option>
+						<option value="Alpha">Alpha</option>
+						<option value="AlphaKill">AlphaKill</option>
+						<option value="Add">Add</option>
+						<option value="SoftAdd">SoftAdd</option>
+					</select>
+				</dd>
+				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
+				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
+				<dt>Lighted</dt><dd><input type="checkbox" field="lighted"/></dd>
+			</dl>
+		');
+	}
+	#end
+
+
+	#if hxbit
 	function customSerialize( ctx : hxbit.Serializer ) {
 		// other props are serialized in BaseMaterial !
 		ctx.addInt(blendMode.getIndex());
@@ -230,7 +329,6 @@ class Material extends BaseMaterial {
 		props = ctx.getDynamic();
 		passes = old;
 	}
-
 	#end
 
 }

+ 2 - 3
h3d/mat/MaterialDatabase.hx

@@ -62,8 +62,8 @@ class MaterialDatabase {
 		Reflect.deleteField(root, name);
 
 		var currentProps = material.props;
-		setup.initModelMaterial(material); // reset to default
-		if( currentProps == null || Std.string(material.props) == Std.string(currentProps) ) {
+		var defaultProps = material.getDefaultModelProps();
+		if( currentProps == null || Std.string(defaultProps) == Std.string(currentProps) ) {
 			// cleanup
 			while( path.length > 0 ) {
 				var name = path.pop();
@@ -75,7 +75,6 @@ class MaterialDatabase {
 		} else {
 			Reflect.setField(root, name, currentProps);
 		}
-		material.props = currentProps;
 		save();
 	}
 

+ 0 - 94
h3d/mat/MaterialScript.hx

@@ -1,94 +0,0 @@
-package h3d.mat;
-
-class MaterialScript extends MaterialSetup {
-
-	var fileName : String;
-	var variables : Map<String,Dynamic>;
-
-	public function new( ?name = "Script" ) {
-		super(name);
-	}
-
-	public dynamic function onError( msg : String ) {
-		throw msg;
-	}
-
-	override function createRenderer() {
-		if( variables.exists("createRenderer") )
-			return call("createRenderer", []);
-		return super.createRenderer();
-	}
-
-	function getVar( name : String ) {
-		var v = variables.get(name);
-		if( v == null ) onError(fileName + " does not define " + name);
-		return v;
-	}
-
-	function initVars() {
-		variables.set("BlendMode", h3d.mat.BlendMode);
-		variables.set("Blend", h3d.mat.Data.Blend);
-		variables.set("Face", h3d.mat.Data.Face);
-		variables.set("Compare", h3d.mat.Data.Compare);
-		variables.set("Operation", h3d.mat.Data.Operation);
-		variables.set("this", this);
-		#if js
-		variables.set("Element", js.jquery.JQuery);
-		#end
-	}
-
-	function call( name : String, args : Array<Dynamic> ) : Dynamic {
-		#if hscript
-		try {
-			return Reflect.callMethod(this, getVar(name), args);
-		} catch( e : hscript.Expr.Error ) {
-			onError(Std.string(e));
-			return null;
-		}
-		#else
-		throw "Can't call " + name;
-		#end
-	}
-
-	override function initMeshAfterLoad( mesh : h3d.scene.Mesh ) {
-		if( variables.exists("initMeshAfterLoad") )
-			call("initMeshAfterLoad", [mesh]);
-	}
-
-
-	override function getDefaults(?type:String):Any {
-		return call("getDefaults", [type]);
-	}
-
-	override function applyProps(m:Material) {
-		return call("applyProps", [m]);
-	}
-
-	override function initModelMaterial(material:Material) {
-		return call("initModelMaterial", [material]);
-	}
-
-	#if js
-	override function editMaterial( props : Any ) {
-		return call("editMaterial", [props]);
-	}
-	#end
-
-	public function load( script : String, ?fileName : String ) {
-		#if !hscript
-		onError("-lib hscript is required to load script");
-		#else
-		if( fileName == null ) fileName = "Renderer.hx";
-		this.fileName = fileName;
-		var parser = new hscript.Parser();
-		parser.allowTypes = true;
-		var expr = try parser.parseString(script, fileName) catch( e : hscript.Expr.Error ) { onError(hscript.Printer.errorToString(e) #if !hscriptPos +" line "+parser.line #end); return; }
-		var interp = new hscript.Interp();
-		variables = interp.variables;
-		initVars();
-		try interp.execute(expr) catch( e : hscript.Expr.Error ) { onError(hscript.Printer.errorToString(e)); return; }
-		#end
-		name = getVar("name");
-	}
-
-}

+ 15 - 116
h3d/mat/MaterialSetup.hx

@@ -1,24 +1,10 @@
 package h3d.mat;
 
-@:enum private abstract DefaultKind(String) {
-	var Opaque = "Opaque";
-	var Alpha = "Alpha";
-	var AlphaKill = "AlphaKill";
-	var Add = "Add";
-	var SoftAdd = "SoftAdd";
-}
-
-private typedef DefaultProps = {
-	var kind : DefaultKind;
-	var shadows : Bool;
-	var culled : Bool;
-	var lighted : Bool;
-}
-
 class MaterialSetup {
 
 	public var name(default,null) : String;
 	var database : MaterialDatabase;
+	var emptyMat : h3d.mat.Material;
 
 	public function new(name) {
 		if( database == null )
@@ -34,116 +20,29 @@ class MaterialSetup {
 		return new h3d.scene.LightSystem();
 	}
 
-	public function initModelMaterial( material : Material ) {
-		var props = database.loadProps(material, this);
-		if( props == null ) {
-			props = getDefaults();
-			// use hmd material
-			var props : DefaultProps = props;
-			switch( material.blendMode ) {
-			case Alpha:
-				props.kind = Alpha;
-			case Add:
-				props.kind = Add;
-				props.culled = false;
-				props.shadows = false;
-				props.lighted = false;
-			case None:
-			default:
-				throw "Unsupported HMD material " + material.blendMode;
-			}
-		}
-		material.props = props;
-	}
-
-	public function saveModelMaterial( material : Material ) {
-		database.saveProps(material, this);
+	public function createMaterial() {
+		return @:privateAccess new h3d.mat.Material();
 	}
 
-	public function initMeshAfterLoad( mesh : h3d.scene.Mesh ) {
+	public function loadProps( mat : h3d.mat.Material ) {
+		return database.loadProps(mat, this);
 	}
 
-	public function getDefaults( ?type : String ) : Any {
-		var props : DefaultProps;
-		switch( type ) {
-		case "particles3D":
-			props = {
-				kind : Opaque,
-				shadows : false,
-				culled : false,
-				lighted : true,
-			};
-		case "trail3D":
-			props = {
-				kind : Opaque,
-				shadows : false,
-				culled : false,
-				lighted : true,
-			};
-		default:
-			props = {
-				kind : Opaque,
-				shadows : true,
-				culled : true,
-				lighted : true,
-			};
-		}
-		return props;
+	public function getDefaults( ?kind : String ) {
+		if( emptyMat == null ) emptyMat = createMaterial();
+		return emptyMat.getDefaultProps(kind);
 	}
 
-	public function applyProps( m : Material ) {
-		var props : DefaultProps = m.props;
-		var mainPass = m.mainPass;
-		switch( props.kind ) {
-		case Opaque, AlphaKill:
-			mainPass.setBlendMode(None);
-			mainPass.depthWrite = true;
-			mainPass.setPassName("default");
-		case Alpha:
-			mainPass.setBlendMode(Alpha);
-			mainPass.depthWrite = true;
-			mainPass.setPassName("alpha");
-		case Add:
-			mainPass.setBlendMode(Add);
-			mainPass.depthWrite = false;
-			mainPass.setPassName("additive");
-		case SoftAdd:
-			mainPass.setBlendMode(SoftAdd);
-			mainPass.depthWrite = false;
-			mainPass.setPassName("additive");
-		}
-		var tshader = m.textureShader;
-		if( tshader != null ) {
-			tshader.killAlpha = props.kind == AlphaKill;
-			tshader.killAlphaThreshold = 0.5;
-		}
-		mainPass.culling = props.culled ? Back : None;
-		mainPass.enableLights = props.lighted;
-		m.shadows = props.shadows;
-		if( m.shadows ) m.getPass("shadow").culling = mainPass.culling;
+	public function saveModelMaterial( material : Material ) {
+		database.saveProps(material, this);
 	}
 
-	#if js
-	public function editMaterial( props : Any ) {
-		return new js.jquery.JQuery('
-			<dl>
-				<dt>Kind</dt>
-				<dd>
-					<select field="kind">
-						<option value="Opaque">Opaque</option>
-						<option value="Alpha">Alpha</option>
-						<option value="AlphaKill">AlphaKill</option>
-						<option value="Add">Add</option>
-						<option value="SoftAdd">SoftAdd</option>
-					</select>
-				</dd>
-				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
-				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
-				<dt>Lighted</dt><dd><input type="checkbox" field="lighted"/></dd>
-			</dl>
-		');
+	/*
+		Can be used to perform custom mesh initialization such as computing extra buffers
+		when loading it from HSD or displaying it in tools.
+	*/
+	public function customMeshInit( mesh : h3d.scene.Mesh ) {
 	}
-	#end
 
 	public static var current = new MaterialSetup("Default");
 

+ 157 - 0
h3d/mat/PbrMaterial.hx

@@ -0,0 +1,157 @@
+package h3d.mat;
+
+@:enum abstract PbrMode(String) {
+	var PBR = "PBR";
+	var Albedo = "Albedo";
+	var Overlay = "Overlay";
+}
+
+@:enum abstract PbrBlend(String) {
+	var None = "None";
+	var Alpha = "Alpha";
+	var Add = "Add";
+}
+
+typedef PbrProps = {
+	var mode : PbrMode;
+	var blend : PbrBlend;
+	var shadows : Bool;
+	var culling : Bool;
+	var alphaKill : Bool;
+}
+
+class PbrMaterial extends Material {
+
+	override function set_blendMode(b:BlendMode) {
+		if( mainPass != null ) {
+			mainPass.setBlendMode(b);
+			mainPass.depthWrite = b == None;
+		}
+		return b;
+	}
+
+	override function getDefaultProps( ?type : String ) : Any {
+		var props : PbrProps;
+		switch( type ) {
+		case "particles3D", "trail3D":
+			props = {
+				mode : PBR,
+				blend : Alpha,
+				shadows : false,
+				culling : false,
+				alphaKill : false,
+			};
+		case "ui":
+			props = {
+				mode : Overlay,
+				blend : Alpha,
+				shadows : false,
+				culling : false,
+				alphaKill : true,
+			};
+		default:
+			props = {
+				mode : PBR,
+				blend : None,
+				shadows : true,
+				culling : true,
+				alphaKill : false,
+			};
+		}
+		return props;
+	}
+
+	override function getDefaultModelProps() : Any {
+		var props : PbrProps = getDefaultProps();
+		props.blend = switch( blendMode ) {
+		case None: None;
+		case Alpha: Alpha;
+		case Add: Add;
+		default: throw "Unsupported Model blendMode "+blendMode;
+		}
+		return props;
+	}
+
+	override function refreshProps() {
+		var props : PbrProps = props;
+		switch( props.mode ) {
+		case PBR:
+			mainPass.setPassName("default");
+		case Albedo:
+			mainPass.setPassName("albedo");
+		case Overlay:
+			mainPass.setPassName("overlay");
+		}
+		switch( props.blend ) {
+		case None:
+			mainPass.setBlendMode(None);
+			mainPass.depthWrite = true;
+		case Alpha:
+			mainPass.setBlendMode(Alpha);
+			mainPass.depthWrite = false;
+		case Add:
+			mainPass.setBlendMode(Add);
+			mainPass.depthWrite = false;
+		}
+		var tshader = textureShader;
+		if( tshader != null ) {
+			tshader.killAlpha = props.alphaKill;
+			tshader.killAlphaThreshold = 0.5;
+		}
+		mainPass.culling = props.culling ? Back : None;
+		shadows = false;
+		castShadows = props.shadows;
+		if( castShadows ) getPass("shadow").culling = mainPass.culling;
+
+		// get values from specular texture
+		var spec = mainPass.getShader(h3d.shader.pbr.PropsTexture);
+		var def = mainPass.getShader(h3d.shader.pbr.PropsValues);
+		if( specularTexture != null ) {
+			if( spec == null ) {
+				spec = new h3d.shader.pbr.PropsTexture();
+				mainPass.addShader(spec);
+			}
+			spec.texture = specularTexture;
+			if( def != null )
+				mainPass.removeShader(def);
+		} else {
+			mainPass.removeShader(spec);
+			// default values (if no texture)
+			if( def == null ) {
+				def = new h3d.shader.pbr.PropsValues();
+				mainPass.addShader(def);
+			}
+		}
+
+	}
+
+	#if js
+	override function editProps() {
+		var props : PbrProps = props;
+		return new js.jquery.JQuery('
+			<dl>
+				<dt>Kind</dt>
+				<dd>
+					<select field="kind">
+						<option value="PBR">PBR</option>
+						<option value="Albedo">Albedo</option>
+						<option value="Overlay">Overlay</option>
+					</select>
+				</dd>
+				<dt>Blend</dt>
+				<dd>
+					<select field="blend">
+						<option value="None">None</option>
+						<option value="Alpha">Alpha</option>
+						<option value="Add">Add</option>
+					</select>
+				</dd>
+				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
+				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
+				<dt>AlphaKill</dt><dd><input type="checkbox" field="alphaKill"/></dd>
+			</dl>
+		');
+	}
+	#end
+
+}

+ 14 - 162
h3d/mat/PbrMaterialSetup.hx

@@ -1,44 +1,22 @@
 package h3d.mat;
 
-@:enum private abstract DefaultKind(String) {
-	var PBR = "PBR";
-	var Albedo = "Albedo";
-	var Overlay = "Overlay";
-}
-
-@:enum private abstract DefaultBlend(String) {
-	var None = "None";
-	var Alpha = "Alpha";
-	var Add = "Add";
-}
-
-private typedef DefaultProps = {
-	var kind : DefaultKind;
-	var blend : DefaultBlend;
-	var shadows : Bool;
-	var alphaKill : Bool;
-	var culled : Bool;
-}
-
 class PbrMaterialSetup extends MaterialSetup {
 
-	public var env(get,set) : h3d.scene.pbr.Environment;
-
 	public function new(?name="PBR") {
 		super(name);
 	}
 
-	function get_env() : h3d.scene.pbr.Environment {
-		return @:privateAccess h3d.Engine.getCurrent().resCache.get(h3d.scene.pbr.Environment);
-	}
-
-	function set_env( i : h3d.scene.pbr.Environment ) {
-		var cache = @:privateAccess h3d.Engine.getCurrent().resCache;
-		if( i == null )
-			cache.remove(h3d.scene.pbr.Environment);
-		else
-			cache.set(h3d.scene.pbr.Environment, i);
-		return i;
+	function createEnv() {
+		var envMap = new h3d.mat.Texture(4,4,[Cube]);
+		var pix = hxd.Pixels.alloc(envMap.width, envMap.height, RGBA);
+		var COLORS = [0xC08080,0xA08080,0x80C080,0x80A080,0x8080C0,0x808080];
+		for( i in 0...6 ) {
+			pix.clear(COLORS[i]);
+			envMap.uploadPixels(pix,0,i);
+		}
+		var env = new h3d.scene.pbr.Environment(envMap);
+		env.compute();
+		return env;
 	}
 
 	override function createRenderer() : h3d.scene.Renderer {
@@ -49,141 +27,15 @@ class PbrMaterialSetup extends MaterialSetup {
 			return super.createRenderer();
 		}
 		#end
-		var env = env;
-		if( env == null ) {
-			var envMap = new h3d.mat.Texture(4,4,[Cube]);
-			var pix = hxd.Pixels.alloc(envMap.width, envMap.height, RGBA);
-			var COLORS = [0xC08080,0xA08080,0x80C080,0x80A080,0x8080C0,0x808080];
-			for( i in 0...6 ) {
-				pix.clear(COLORS[i]);
-				envMap.uploadPixels(pix,0,i);
-			}
-			env = new h3d.scene.pbr.Environment(envMap);
-			env.compute();
-			this.env = env;
-		}
-		return new h3d.scene.pbr.Renderer(env);
+		return new h3d.scene.pbr.Renderer(createEnv());
 	}
 
 	override function createLightSystem() {
 		return new h3d.scene.pbr.LightSystem();
 	}
 
-	override function initModelMaterial( material : Material ) {
-		var props = database.loadProps(material, this);
-		if( props == null ) {
-			props = getDefaults();
-			// use hmd material
-			var props : DefaultProps = props;
-			// TODO : handle HMD alpha correctly
-		}
-		material.props = props;
-	}
-
-	override function getDefaults( ?type : String ) : Any {
-		var props : DefaultProps;
-		switch( type ) {
-		case "ui":
-			props = {
-				kind : Overlay,
-				blend : Alpha,
-				shadows : false,
-				culled : false,
-				alphaKill : true,
-			};
-		default:
-			props = {
-				kind : PBR,
-				blend : None,
-				shadows : true,
-				culled : true,
-				alphaKill : false,
-			};
-		}
-		return props;
-	}
-
-	override function applyProps( m : Material ) {
-		var props : DefaultProps = m.props;
-		var mainPass = m.mainPass;
-		switch( props.kind ) {
-		case PBR:
-			mainPass.setPassName("default");
-		case Albedo:
-			mainPass.setPassName("albedo");
-		case Overlay:
-			mainPass.setPassName("overlay");
-		}
-		switch( props.blend ) {
-		case None:
-			mainPass.setBlendMode(None);
-			mainPass.depthWrite = true;
-		case Alpha:
-			mainPass.setBlendMode(Alpha);
-			mainPass.depthWrite = false;
-		case Add:
-			mainPass.setBlendMode(Add);
-			mainPass.depthWrite = false;
-		}
-		var tshader = m.textureShader;
-		if( tshader != null ) {
-			tshader.killAlpha = props.alphaKill;
-			tshader.killAlphaThreshold = 0.5;
-		}
-		mainPass.culling = props.culled ? Back : None;
-		m.shadows = false;
-		if( m.shadows ) m.getPass("shadow").culling = mainPass.culling;
-		m.castShadows = props.shadows;
-
-		// get values from specular texture
-		var spec = m.mainPass.getShader(h3d.shader.pbr.PropsTexture);
-		var def = m.mainPass.getShader(h3d.shader.pbr.PropsValues);
-		if( m.specularTexture != null ) {
-			if( spec == null ) {
-				spec = new h3d.shader.pbr.PropsTexture();
-				m.mainPass.addShader(spec);
-			}
-			spec.texture = m.specularTexture;
-			if( def != null )
-				m.mainPass.removeShader(def);
-		} else {
-			m.mainPass.removeShader(spec);
-			// default values (if no texture)
-			if( def == null ) {
-				def = new h3d.shader.pbr.PropsValues();
-				m.mainPass.addShader(def);
-			}
-		}
-
-	}
-
-	#if js
-	override function editMaterial( props : Any ) {
-		var props : DefaultProps = props;
-		return new js.jquery.JQuery('
-			<dl>
-				<dt>Kind</dt>
-				<dd>
-					<select field="kind">
-						<option value="PBR">PBR</option>
-						<option value="Albedo">Albedo</option>
-						<option value="Overlay">Overlay</option>
-					</select>
-				</dd>
-				<dt>Blend</dt>
-				<dd>
-					<select field="blend">
-						<option value="None">None</option>
-						<option value="Alpha">Alpha</option>
-						<option value="Add">Add</option>
-					</select>
-				</dd>
-				<dt>Shadows</dt><dd><input type="checkbox" field="shadows"/></dd>
-				<dt>Culled</dt><dd><input type="checkbox" field="culled"/></dd>
-				<dt>AlphaKill</dt><dd><input type="checkbox" field="alphaKill"/></dd>
-			</dl>
-		');
+	override function createMaterial() : Material {
+		return @:privateAccess new PbrMaterial();
 	}
-	#end
 
 }

+ 1 - 1
h3d/parts/GpuParticles.hx

@@ -510,7 +510,7 @@ class GpuParticles extends h3d.scene.MultiMaterial {
 		if( g.name == null )
 			g.name = "Group#" + (groups.length + 1);
 		if( material == null ) {
-			material = new h3d.mat.Material();
+			material = h3d.mat.MaterialSetup.current.createMaterial();
 			material.mainPass.culling = None;
 			material.mainPass.depthWrite = false;
 			material.blendMode = Alpha;

+ 3 - 3
h3d/prim/HMDModel.hx

@@ -50,7 +50,7 @@ class HMDModel extends MeshPrimitive {
 		dispose();
 		buffer = new h3d.Buffer(data.vertexCount, data.vertexStride);
 
-		var entry = @:privateAccess lib.entry;
+		var entry = lib.resource.entry;
 		entry.open();
 
 		entry.skip(dataPosition + data.vertexPosition);
@@ -163,7 +163,7 @@ class HMDModel extends MeshPrimitive {
 			return collider;
 		var poly = new h3d.col.PolygonBuffer();
 		poly.source = {
-			entry : lib.entry,
+			entry : lib.resource.entry,
 			geometryName : null,
 		};
 		for( h in lib.header.models )
@@ -177,7 +177,7 @@ class HMDModel extends MeshPrimitive {
 
 	#if hxbit
 	override function customSerialize(ctx:hxbit.Serializer) {
-		ctx.addString(@:privateAccess lib.entry.path);
+		ctx.addString(lib.resource.entry.path);
 		for( m in lib.header.models )
 			if( lib.header.geometries[m.geometry] == this.data ) {
 				ctx.addString(m.name);

+ 1 - 6
h3d/prim/ModelCache.hx

@@ -31,12 +31,7 @@ class ModelCache {
 	}
 
 	public function loadModel( res : hxd.res.Model ) : h3d.scene.Object {
-		var obj = loadLibrary(res).makeObject(loadTexture.bind(res));
-		for( m in obj.getMaterials() ) {
-			m.model = res;
-			h3d.mat.MaterialSetup.current.initModelMaterial(m);
-		}
-		return obj;
+		return loadLibrary(res).makeObject(loadTexture.bind(res));
 	}
 
 	public function loadTexture( model : hxd.res.Model, texturePath ) : h3d.mat.Texture {

+ 4 - 1
h3d/scene/Mesh.hx

@@ -8,7 +8,10 @@ class Mesh extends Object {
 	public function new( prim, ?mat, ?parent ) {
 		super(parent);
 		this.primitive = prim;
-		if( mat == null ) mat = new h3d.mat.Material(null);
+		if( mat == null ) {
+			mat = h3d.mat.MaterialSetup.current.createMaterial();
+			mat.props = mat.getDefaultProps();
+		}
 		this.material = mat;
 	}
 

+ 2 - 1
h3d/scene/Renderer.hx

@@ -12,7 +12,7 @@ class PassObjects {
 
 private typedef SMap<T> = #if flash haxe.ds.UnsafeStringMap<T> #else Map<String,T> #end
 
-class Renderer {
+class Renderer extends hxd.impl.AnyProps {
 
 	var defaultPass : h3d.pass.Base;
 	var passObjects : SMap<PassObjects>;
@@ -23,6 +23,7 @@ class Renderer {
 	public function new() {
 		allPasses = [];
 		passObjects = new SMap();
+		props = getDefaultProps();
 	}
 
 	public function dispose() {

+ 12 - 5
hxd/fmt/hmd/Library.hx

@@ -23,15 +23,15 @@ class GeometryBuffer {
 
 class Library {
 
+	public var resource(default,null) : hxd.res.Resource;
 	public var header(default,null) : Data;
-	public var entry(default,null) : hxd.fs.FileEntry;
 	var cachedPrimitives : Array<h3d.prim.HMDModel>;
 	var cachedAnimations : Map<String, h3d.anim.Animation>;
 	var cachedSkin : Map<String, h3d.anim.Skin>;
 	var tmp = haxe.io.Bytes.alloc(4);
 
-	public function new(entry, header) {
-		this.entry = entry;
+	public function new(res,  header) {
+		this.resource = res;
 		this.header = header;
 		cachedPrimitives = [];
 		cachedAnimations = new Map();
@@ -39,6 +39,7 @@ class Library {
 	}
 
 	public function getData() {
+		var entry = resource.entry;
 		var b = haxe.io.Bytes.alloc(entry.size - header.dataPosition);
 		entry.open();
 		entry.skip(header.dataPosition);
@@ -141,6 +142,7 @@ class Library {
 
 		var vsize = geom.vertexCount * geom.vertexStride * 4;
 		var vbuf = hxd.impl.Tmp.getBytes(vsize);
+		var entry = resource.entry;
 		entry.open();
 		entry.skip(header.dataPosition + geom.vertexPosition);
 		entry.read(vbuf, 0, vsize);
@@ -260,7 +262,7 @@ class Library {
 
 	function makeMaterial( model : Model, mid : Int, loadTexture : String -> h3d.mat.Texture ) {
 		var m = header.materials[mid];
-		var mat = new h3d.mat.Material();
+		var mat = h3d.mat.MaterialSetup.current.createMaterial();
 		mat.name = m.name;
 		if( m.diffuseTexture != null ) {
 			mat.texture = loadTexture(m.diffuseTexture);
@@ -271,6 +273,10 @@ class Library {
 		if( m.normalMap != null )
 			mat.normalMap = loadTexture(m.normalMap);
 		mat.blendMode = m.blendMode;
+		mat.model = resource;
+		var props = h3d.mat.MaterialSetup.current.loadProps(mat);
+		if( props == null ) props = mat.getDefaultModelProps();
+		mat.props = props;
 		return mat;
 	}
 
@@ -380,7 +386,7 @@ class Library {
 		}
 
 		var l = makeAnimation(a);
-		l.resPath = entry.path;
+		l.resPath = resource.entry.path;
 		cachedAnimations.set(a.name, l);
 		if( name == null ) cachedAnimations.set("", l);
 		return l;
@@ -394,6 +400,7 @@ class Library {
 		l.loop = a.loop;
 		if( a.events != null ) l.setEvents(a.events);
 
+		var entry = resource.entry;
 		entry.open();
 		entry.skip(header.dataPosition + a.dataPosition);
 

+ 1 - 1
hxd/fmt/hsd/Serializer.hx

@@ -266,7 +266,7 @@ class Serializer extends hxbit.Serializer {
 		}
 		for( o in objs )
 			for( m in o.getMeshes() )
-				h3d.mat.MaterialSetup.current.initMeshAfterLoad(m);
+				h3d.mat.MaterialSetup.current.customMeshInit(m);
 
 		var camera = null;
 		if( getBool() ) {

+ 26 - 0
hxd/impl/AnyProps.hx

@@ -0,0 +1,26 @@
+package hxd.impl;
+
+class AnyProps {
+
+	public var props(default, set) : Any;
+
+	function set_props(p) {
+		this.props = p;
+		refreshProps();
+		return p;
+	}
+
+	public function getDefaultProps( ?kind : String ) : Any {
+		return {};
+	}
+
+	public function refreshProps() {
+	}
+
+	#if js
+	public function editProps() {
+		return new js.jquery.JQuery('<p>No properties for this object</p>');
+	}
+	#end
+
+}

+ 1 - 1
hxd/res/Model.hx

@@ -4,7 +4,7 @@ class Model extends Resource {
 
 	public function toHmd() : hxd.fmt.hmd.Library {
 		var hmd = new hxd.fmt.hmd.Reader(new hxd.fs.FileInput(entry)).readHeader();
-		return new hxd.fmt.hmd.Library(entry, hmd);
+		return new hxd.fmt.hmd.Library(this, hmd);
 	}
 
 }