Răsfoiți Sursa

Add color grading

ShiroSmith 6 ani în urmă
părinte
comite
f2b9c2b428
2 a modificat fișierele cu 47 adăugiri și 3 ștergeri
  1. 23 2
      h3d/scene/pbr/Renderer.hx
  2. 24 1
      h3d/shader/pbr/ToneMapping.hx

+ 23 - 2
h3d/scene/pbr/Renderer.hx

@@ -38,6 +38,8 @@ package h3d.scene.pbr;
 typedef RenderProps = {
 	var mode : DisplayMode;
 	var env : String;
+	var colorGradingLUT : String;
+	var colorGradingLUTSize : Int;
 	var envPower : Float;
 	var exposure : Float;
 	var sky : SkyMode;
@@ -72,6 +74,8 @@ class Renderer extends h3d.scene.Renderer {
 
 	public var skyMode : SkyMode = Hide;
 	public var toneMode : TonemapMap = Reinhard;
+	public var colorgGradingLUT : h3d.mat.Texture;
+	public var colorGradingLUTSize : Int;
 	public var displayMode : DisplayMode = Pbr;
 	public var env : Environment;
 	public var exposure(get,set) : Float;
@@ -327,11 +331,17 @@ class Renderer extends h3d.scene.Renderer {
 
 		var ldr = allocTarget("ldrOutput");
 		setTarget(ldr);
+		ctx.setGlobal("hdr", hdr);
 		var bloom = ctx.getGlobal("bloom");
 		tonemap.shader.bloom = bloom;
 		tonemap.shader.hasBloom = bloom != null;
 		tonemap.shader.distortion = distortion;
 		tonemap.shader.hasDistortion = distortion != null;
+		tonemap.shader.hasColorGrading = colorgGradingLUT != null;
+		if( colorgGradingLUT != null  ){
+			tonemap.shader.colorGradingLUT = colorgGradingLUT;
+			tonemap.shader.lutSize = colorGradingLUTSize;
+		}
 		tonemap.shader.pixelSize = new Vector(1.0/ctx.engine.width, 1.0/ctx.engine.height);
 		tonemap.shader.mode =	switch( toneMode ) {
 									case Linear: 0;
@@ -345,7 +355,6 @@ class Renderer extends h3d.scene.Renderer {
 		apply(Final);
 		resetTarget();
 
-
 		switch( displayMode ) {
 
 		case Pbr, Env, MatCap:
@@ -367,7 +376,6 @@ class Renderer extends h3d.scene.Renderer {
 				hasDebugEvent = true;
 				hxd.Window.getInstance().addEventTarget(onEvent);
 			}
-
 		}
 
 		if( hasDebugEvent && displayMode != Debug ) {
@@ -400,6 +408,8 @@ class Renderer extends h3d.scene.Renderer {
 		var props : RenderProps = {
 			mode : Pbr,
 			env : null,
+			colorGradingLUT : null,
+			colorGradingLUTSize : 1,
 			envPower : 1.,
 			emissive : 1.,
 			exposure : 0.,
@@ -429,6 +439,12 @@ class Renderer extends h3d.scene.Renderer {
 		exposure = props.exposure;
 		env.power = props.envPower;
 		shadows = props.shadows;
+
+		if( props.colorGradingLUT != null )
+			colorgGradingLUT = hxd.res.Loader.currentInstance.load(props.colorGradingLUT).toTexture();
+		else
+			colorgGradingLUT = null;
+		colorGradingLUTSize = props.colorGradingLUTSize;
 	}
 
 	#if editor
@@ -444,6 +460,10 @@ class Renderer extends h3d.scene.Renderer {
 						<option value="Reinhard">Reinhard</option>
 					</select>
 				</dd>
+
+				<dt>Color Grading LUT</dt><input type="texturepath" field="colorGradingLUT" style="width:165px"/>
+				<dt>LUT Size</dt><dd><input step="1" type="range" min="0" max="32" field="colorGradingLUTSize"></dd>
+
 				<dt>Mode</dt>
 				<dd>
 					<select field="mode">
@@ -454,6 +474,7 @@ class Renderer extends h3d.scene.Renderer {
 						<option value="Distortion">Distortion</option>
 					</select>
 				</dd>
+
 				<dt>Env</dt>
 				<dd>
 					<input type="texturepath" field="env" style="width:165px"/>

+ 24 - 1
h3d/shader/pbr/ToneMapping.hx

@@ -12,13 +12,19 @@ class ToneMapping extends ScreenShader {
 
 		@const var hasBloom : Bool;
 		@param var bloom : Sampler2D;
+
 		@const var hasDistortion : Bool;
 		@param var distortion : Sampler2D;
+
+		@const var hasColorGrading : Bool;
+		@param var colorGradingLUT : Sampler2D;
+		@param var lutSize : Float;
+
 		@param var pixelSize : Vec2;
 
 		function fragment() {
 
-			if(hasDistortion){
+			if( hasDistortion)  {
 				var baseUV = calculatedUV;
 				var distortionVal = distortion.get(baseUV).rg;
 				calculatedUV = baseUV + distortionVal ;
@@ -41,6 +47,23 @@ class ToneMapping extends ScreenShader {
 			// gamma correct
 			if( !isSRBG ) color.rgb = color.rgb.sqrt();
 
+			if( hasColorGrading ) {
+				var uv = color.rgb;
+				var sliceSize = 1.0 / lutSize;
+				var slicePixelSize = sliceSize / lutSize;
+				var sliceInnerSize = slicePixelSize * (lutSize - 1.0);
+				var blueSlice0 = min(floor(uv.b * lutSize), lutSize - 1.0);
+				var blueSlice1 = min(blueSlice0 + 1.0, lutSize - 1.0);
+				var xOffset = slicePixelSize * 0.5 + uv.r * sliceInnerSize;
+				var s0 = xOffset + (blueSlice0 * sliceSize);
+				var s1 = xOffset + (blueSlice1 * sliceSize);
+				var slice0Color = texture(colorGradingLUT, vec2(s0, uv.y)).rgb;
+				var slice1Color = texture(colorGradingLUT, vec2(s1, uv.y)).rgb;
+				var bOffset = mod(uv.b * lutSize, 1.0);
+				var result = mix(slice0Color, slice1Color, bOffset);
+				color.rgb = result;
+			}
+
 			pixelColor = color;
 		}
 	}