Procházet zdrojové kódy

added specular lighting

bstouls před 10 roky
rodič
revize
da87ea910f

+ 32 - 1
h3d/mat/MeshMaterial.hx

@@ -4,9 +4,12 @@ class MeshMaterial extends Material {
 
 	var mshader : h3d.shader.BaseMesh;
 	public var textureShader(default, null) : h3d.shader.Texture;
-	public var texture(get,set) : h3d.mat.Texture;
+	public var specularShader(default, null) : h3d.shader.SpecularTexture;
+	public var texture(get, set) : h3d.mat.Texture;
+	public var specularTexture(get,set) : h3d.mat.Texture;
 
 	public var color(get, set) : Vector;
+	public var specularPower(get, set) : Float;
 	public var blendMode(default, set) : BlendMode;
 
 	public function new(?texture) {
@@ -16,6 +19,14 @@ class MeshMaterial extends Material {
 		this.texture = texture;
 	}
 
+	inline function get_specularPower() {
+		return mshader.specularPower;
+	}
+
+	inline function set_specularPower(v) {
+		return mshader.specularPower = v;
+	}
+
 	inline function get_color() {
 		return mshader.color;
 	}
@@ -68,6 +79,10 @@ class MeshMaterial extends Material {
 		return blendMode = v;
 	}
 
+	function get_specularTexture() {
+		return specularShader == null ? null : specularShader.texture;
+	}
+
 	function get_texture() {
 		return textureShader == null ? null : textureShader.texture;
 	}
@@ -88,4 +103,20 @@ class MeshMaterial extends Material {
 		return t;
 	}
 
+	function set_specularTexture(t) {
+		if( t == null ) {
+			if( specularShader != null ) {
+				mainPass.removeShader(specularShader);
+				specularShader = null;
+			}
+		} else {
+			if( specularShader == null ) {
+				specularShader = new h3d.shader.SpecularTexture();
+				mainPass.addShader(specularShader);
+			}
+			specularShader.texture = t;
+		}
+		return t;
+	}
+
 }

+ 14 - 0
h3d/pass/LightSystem.hx

@@ -14,12 +14,26 @@ class LightSystem {
 	public var ambientLight : h3d.Vector;
 	public var perPixelLighting : Bool = true;
 
+	/**
+		In the old lighting model, the lights are added after the ambient.
+		In the new one (by default), the lights will be modulated against the ambient, so an ambient of 1 will turn off all lights
+	**/
+	public var oldModel(get, set) : Bool;
+
 	public function new() {
 		shadowDirection = new h3d.Vector(0, 0, -1);
 		ambientLight = new h3d.Vector(0.5, 0.5, 0.5);
 		ambientShader = new h3d.shader.AmbientLight();
 	}
 
+	function get_oldModel() {
+		return Std.instance(ambientShader,h3d.shader.AmbientLight).oldModel;
+	}
+
+	function set_oldModel(b) {
+		return Std.instance(ambientShader,h3d.shader.AmbientLight).oldModel = b;
+	}
+
 	public function initLights( globals : hxsl.Globals, ctx : h3d.scene.RenderContext ) {
 		lightCount = 0;
 		this.ctx = ctx;

+ 6 - 1
h3d/scene/DirLight.hx

@@ -16,8 +16,13 @@ class DirLight extends Light {
 		return dshader.color;
 	}
 
+	override function set_enableSpecular(b) {
+		dshader.enableSpecular = b;
+		return false;
+	}
+
 	override function emit(ctx) {
-		dshader.direction.set(-direction.x, -direction.y, -direction.z);
+		dshader.direction.set(direction.x, direction.y, direction.z);
 		dshader.direction.normalize();
 		super.emit(ctx);
 	}

+ 10 - 0
h3d/scene/Light.hx

@@ -9,6 +9,7 @@ class Light extends Object {
 
 	public var color(get, never) : h3d.Vector;
 	public var priority : Int = 0;
+	public var enableSpecular(get, set) : Bool;
 
 	function new(shader,?parent) {
 		super(parent);
@@ -20,6 +21,15 @@ class Light extends Object {
 		return new h3d.Vector();
 	}
 
+	function get_enableSpecular() {
+		return false;
+	}
+
+	function set_enableSpecular(b) {
+		if( b ) throw "Not implemented for this light";
+		return false;
+	}
+
 	override function emit(ctx:RenderContext) {
 		ctx.emitLight(this);
 	}

+ 10 - 4
h3d/shader/AmbientLight.hx

@@ -13,20 +13,26 @@ class AmbientLight extends hxsl.Shader {
 		var lightPixelColor : Vec3;
 		var lightColor : Vec3;
 
+		@const var oldModel : Bool;
+
 		function __init__() {
-			lightColor = global.ambientLight;
+			lightColor = oldModel ? global.ambientLight : vec3(0.);
 		}
 
 		function __init__fragment() {
-			lightPixelColor = global.ambientLight;
+			lightPixelColor = oldModel ? global.ambientLight : vec3(0.);
+		}
+
+		function calcLight( lightColor : Vec3 ) : Vec3 {
+			return oldModel ? lightColor : (global.ambientLight + (1 - global.ambientLight).max(0.) * lightColor);
 		}
 
 		function vertex() {
-			if( !global.perPixelLighting ) pixelColor.rgb *= lightColor;
+			if( !global.perPixelLighting ) pixelColor.rgb *= calcLight(lightColor);
 		}
 
 		function fragment() {
-			if( global.perPixelLighting ) pixelColor.rgb *= lightPixelColor;
+			if( global.perPixelLighting ) pixelColor.rgb *= calcLight(lightPixelColor);
 		}
 
 	}

+ 12 - 0
h3d/shader/BaseMesh.hx

@@ -40,8 +40,13 @@ class BaseMesh extends hxsl.Shader {
 		var projectedPosition : Vec4;
 		var pixelColor : Vec4;
 		var depth : Float;
+		var screenUV : Vec2;
+		var specPower : Float;
+		var specAmount : Float;
 
 		@param var color : Vec4;
+		@param var specularPower : Float;
+		@param var specularAmount : Float;
 
 		// each __init__ expr is out of order dependency-based
 		function __init__() {
@@ -52,10 +57,15 @@ class BaseMesh extends hxsl.Shader {
 			camera.dir = (camera.position - transformedPosition).normalize();
 			pixelColor = color;
 			depth = projectedPosition.z / projectedPosition.w;
+			screenUV = (projectedPosition.xy / projectedPosition.w) * vec2(0.5, -0.5) + 0.5;
+			specPower = specularPower;
+			specAmount = specularAmount;
 		}
 
 		function __init__fragment() {
 			transformedNormal = transformedNormal.normalize();
+			specPower = specularPower;
+			specAmount = specularAmount;
 		}
 
 		function vertex() {
@@ -74,6 +84,8 @@ class BaseMesh extends hxsl.Shader {
 	public function new() {
 		super();
 		color.set(1, 1, 1);
+		specularPower = 50;
+		specularAmount = 1;
 	}
 
 }

+ 18 - 2
h3d/shader/DirLight.hx

@@ -5,17 +5,33 @@ class DirLight extends hxsl.Shader {
 	static var SRC = {
 		@param var color : Vec3;
 		@param var direction : Vec3;
+		@const var enableSpecular : Bool;
+		@global var camera : {
+			var position : Vec3;
+		};
 
 		var lightColor : Vec3;
 		var lightPixelColor : Vec3;
 		var transformedNormal : Vec3;
+		var transformedPosition : Vec3;
+		var specAmount : Float;
+		var specPower : Float;
+
+		function calcLighting() : Vec3 {
+			var diff = transformedNormal.dot(-direction).max(0.);
+			if( !enableSpecular )
+				return color * diff;
+			var r = reflect(direction, transformedNormal).normalize();
+			var specValue = r.dot((camera.position - transformedPosition).normalize()).max(0.);
+			return color * (diff + specAmount * pow(specValue, specPower));
+		}
 
 		function vertex() {
-			lightColor.rgb += color * transformedNormal.dot(direction).max(0.);
+			lightColor.rgb += calcLighting();
 		}
 
 		function fragment() {
-			lightPixelColor.rgb += color * transformedNormal.dot(direction).max(0.);
+			lightPixelColor.rgb += calcLighting();
 		}
 
 	}

+ 20 - 0
h3d/shader/SpecularTexture.hx

@@ -0,0 +1,20 @@
+package h3d.shader;
+
+class SpecularTexture extends hxsl.Shader {
+
+	static var SRC = {
+		@param var texture : Sampler2D;
+		var calculatedUV : Vec2;
+		var specAmount : Float;
+
+		function fragment() {
+			specAmount *= texture.get(calculatedUV).x;
+		}
+	}
+
+	public function new(?tex) {
+		super();
+		this.texture = tex;
+	}
+
+}