Forráskód Böngészése

Better post proces docs, added color grading and white balance params, reorganized post process settings

BearishSun 9 éve
szülő
commit
0e505d1e1a

+ 186 - 30
Source/RenderBeast/Include/BsPostProcessing.h

@@ -13,75 +13,221 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
-	/** Settings that control the post-process operation. */
-	struct PostProcessSettings
+	/** Settings that control automatic exposure (eye adaptation) post-process. */
+	struct AutoExposureSettings
 	{
-		PostProcessSettings();
+		AutoExposureSettings();
 
 		/** 
-		 * Determines minimum luminance value in the eye adaptation histogram. In log2 units (-8 = 1/256). In the range
-		 * [-16, 0]. 
+		 * Determines minimum luminance value in the eye adaptation histogram. The histogram is used for calculating the
+		 * average brightness of the scene. Any luminance value below this value will not be included in the histogram and
+		 * ignored in scene brightness calculations. In log2 units (-8 = 1/256). In the range [-16, 0]. 
 		 */
 		float histogramLog2Min; 
 
 		/** 
-		 * Determines maximum luminance value in the eye adaptation histogram. In log2 units (4 = 16). In the range
-		 * [0, 16]. 
+		 * Determines maximum luminance value in the eye adaptation histogram. The histogram is used for calculating the
+		 * average brightness of the scene. Any luminance value above this value will not be included in the histogram and
+		 * ignored in scene brightness calculations. In log2 units (4 = 16). In the range [0, 16]. 
 		 */
 		float histogramLog2Max;
 
-		/** Percentage below which to ignore values in the eye adaptation histogram. In range [0.0f, 1.0f]. */
+		/** 
+		 * Percentage below which to ignore values in the eye adaptation histogram. The histogram is used for calculating
+		 * the average brightness of the scene. Total luminance in the histogram will be summed up and multiplied by this
+		 * value to calculate minimal luminance. Luminance values below the minimal luminance will be ignored and not used
+		 * in scene brightness calculations. This allows you to remove outliers on the lower end of the histogram (e.g. a
+		 * few very dark pixels in an otherwise bright image). In range [0.0f, 1.0f]. 
+		 */
 		float histogramPctLow;
 
-		/** Percentage above which to ignore values in the eye adaptation histogram. In range [0.0f, 1.0f]. */
+		/** 
+		 * Percentage above which to ignore values in the eye adaptation histogram. The histogram is used for calculating
+		 * the average brightness of the scene. Total luminance in the histogram will be summed up and multiplied by this
+		 * value to calculate maximum luminance. Luminance values above the maximum luminance will be ignored and not used
+		 * in scene brightness calculations. This allows you to remove outliers on the high end of the histogram (e.g. a few
+		 * very bright pixels). In range [0.0f, 1.0f]. 
+		 */
 		float histogramPctHigh;
 
-		/** Clamps the minimum eye adaptation scale (pre-exposure scale) to this value. In range [0.0f, 10.0f]. */
+		/** 
+		 * Clamps the minimum eye adaptation scale to this value. This allows you to limit eye adaptation so that exposure
+		 * is never too high (e.g. when in a very dark room you probably do not want the exposure to be so high that
+		 * everything is still visible). In range [0.0f, 10.0f]. 
+		 */
 		float minEyeAdaptation;
 
-		/** Clamps the maximum eye adaptation scale (pre-exposure scale) to this value. In range [0.0f, 10.0f]. */
-		float maxEyeAdaptation;
-
 		/** 
-		 * Log2 value to scale the eye adaptation by. Smaller values yield darker image, while larger yield brighter image. 
-		 * In range [-8, 8].
+		 * Clamps the maximum eye adaptation scale to this value. This allows you to limit eye adaptation so that exposure
+		 * is never too low (e.g. when looking at a very bright light source you probably don't want the exposure to be so
+		 * low that the rest of the scene is all white (overexposed). In range [0.0f, 10.0f]. 
 		 */
-		float exposureScale;
+		float maxEyeAdaptation;
 
-		/** Determines how quickly does the eye adaptation adjust to larger values. In range [0.01f, 20.0f]. */
+		/** 
+		 * Determines how quickly does the eye adaptation adjust to larger values. This affects how quickly does the 
+		 * automatic exposure changes when the scene brightness increases. In range [0.01f, 20.0f]. */
 		float eyeAdaptationSpeedUp;
 
-		/** Determines how quickly does the eye adaptation adjust to smaller values. In range [0.01f, 20.0f]. */
+		/** 
+		 * Determines how quickly does the eye adaptation adjust to smaller values. This affects how quickly does the 
+		 * automatic exposure changes when the scene brightness decreases. In range [0.01f, 20.0f]. 
+		 */
 		float eyeAdaptationSpeedDown;
+	};
+
+	/** Settings that control tonemap post-process. */
+	struct TonemappingSettings
+	{
+		TonemappingSettings();
 
-		/** Value that controls the shoulder (upper non-linear) section of the filmic curve. Affects high-range. */
+		/** 
+		 * Controls the shoulder (upper non-linear) section of the filmic curve used for tonemapping. Mostly affects bright
+		 * areas of the image and allows you to reduce over-exposure. 
+		 */
 		float filmicCurveShoulderStrength;
 
-		/** Value that controls the linear (middle) section of the filmic curve. Affects mid-range. */
+		/** 
+		 * Controls the linear (middle) section of the filmic curve used for tonemapping. Mostly affects mid-range areas of
+		 * the image. 
+		 */
 		float filmicCurveLinearStrength;
 
-		/** Value that controls the linear (middle) section of the filmic curve. Affects mid-range. */
+		/** 
+		 * Controls the linear (middle) section of the filmic curve used for tonemapping. Mostly affects mid-range areas of
+		 * the image and allows you to control how quickly does the curve climb.
+		 */
 		float filmicCurveLinearAngle;
 
-		/** Value that controls the toe (lower non-linear) section of the filmic curve. Affects low-range. */
+		/** 
+		 * Controls the toe (lower non-linear) section of the filmic curve used for tonemapping. Mostly affects dark areas
+		 * of the image and allows you to reduce under-exposure.
+		 */
 		float filmicCurveToeStrength;
 
-		/** Value that controls the toe (lower non-linear) section of the filmic curve. Affects low-range. */
+		/** Controls the toe (lower non-linear) section of the filmic curve. used for tonemapping. Affects low-range. */
 		float filmicCurveToeNumerator;
 
-		/** Value that controls the toe (lower non-linear) section of the filmic curve. Affects low-range. */
+		/** Controls the toe (lower non-linear) section of the filmic curve used for tonemapping. Affects low-range. */
 		float filmicCurveToeDenominator;
 
-		/** Value that controls the white point of the filmic curve. Affects the entire curve. */
+		/** Controls the white point of the filmic curve used for tonemapping. Affects the entire curve. */
 		float filmicCurveLinearWhitePoint;
+	};
+
+	/** Settings that control white balance post-process. */
+	struct WhiteBalanceSettings
+	{
+		WhiteBalanceSettings();
+
+		/** 
+		 * Temperature used for white balancing, in Kelvins. 
+		 *
+		 * Moves along the Planckian locus. In range [1500.0f, 15000.0f]. 
+		 */
+		float temperature;
+
+		/** 
+		 * Additional tint to be applied during white balancing. Can be used to further tweak the white balancing effect by
+		 * modifying the tint of the light. The tint is chosen on the Planckian locus isothermal, depending on the light
+		 * temperature specified by ::whiteTemperature.
+		 *
+		 * In range [-1.0f, 1.0f]. 
+		 */
+		float tint;	
+	};
+
+	/** Settings that control color grading post-process. */
+	struct ColorGradingSettings
+	{
+		ColorGradingSettings();
 
-		/** Determines should the final output be tonemapped. */
-		bool tonemapping;
+		/** 
+		 * Saturation to be applied during color grading. Larger values increase vibrancy of the image. 
+		 * In range [0.0f, 2.0f]. 
+		 */
+		Vector3 saturation;
+
+		/** 
+		 * Contrast to be applied during color grading. Larger values increase difference between light and dark areas of
+		 * the image. In range [0.0f, 2.0f]. */
+		Vector3 contrast;
 
-		/** Determines should automatic exposure be applied to the HDR image. */
-		bool autoExposure;
+		/** 
+		 * Gain to be applied during color grading. Simply increases all color values by an equal scale. 
+		 * In range [0.0f, 2.0f]. 
+		 */
+		Vector3 gain;
 
-		/** Gamma value to adjust the image for. Larger values result in a brighter image. */
+		/** 
+		 * Gain to be applied during color grading. Simply offsets all color values by an equal amount.
+		 * In range [-1.0f, 1.0f].
+		 */
+		Vector3 offset;
+	};
+
+	/** Settings that control the post-process operations. */
+	struct PostProcessSettings
+	{
+		PostProcessSettings();
+
+		/** 
+		 * Determines should automatic exposure be applied to the HDR image. When turned on the average scene brightness
+		 * will be calculated and used to automatically expose the image to the optimal range. Use the parameters provided
+		 * by ::autoExposure to customize the automatic exposure effect. You may also use ::exposureScale to
+		 * manually adjust the automatic exposure. When automatic exposure is turned off you can use ::exposureScale to
+		 * manually set the exposure.
+		 */
+		bool enableAutoExposure;
+
+		/** 
+		 * Parameters used for customizing automatic scene exposure. 
+		 *
+		 * @see	enableAutoExposure
+		 */
+		AutoExposureSettings autoExposure;
+
+		/** 
+		 * Determines should the image be tonemapped. Tonemapping converts an HDR image into LDR image by applying
+		 * a filmic curve to the image, simulating the effect of film cameras. Filmic curve improves image quality by
+		 * tapering off lows and highs, preventing under- and over-exposure. This is useful if an image contains both
+		 * very dark and very bright areas, in which case the global exposure parameter would leave some areas either over-
+		 * or under-exposed. Use ::tonemapping to customize how tonemapping performed.
+		 *
+		 * If this is disabled, then color grading and white balancing will not be enabled either. Only relevant for HDR
+		 * images.
+		 */
+		bool enableTonemapping;
+
+		/** 
+		 * Parameters used for customizing tonemapping.
+		 *
+		 * @see	enableTonemapping
+		 */
+		TonemappingSettings tonemapping;
+
+		/**
+		 * Parameters used for customizing white balancing. White balancing converts a scene illuminated by a light of the
+		 * specified temperature into a scene illuminated by a standard D65 illuminant (average midday light) in order to
+		 * simulate the effects of chromatic adaptation of the human visual system.
+		 */
+		WhiteBalanceSettings whiteBalance;
+
+		/** Parameters used for customizing color grading. */
+		ColorGradingSettings colorGrading;
+
+		/** 
+		 * Log2 value to scale the eye adaptation by (e.g. 2^0 = 1). Smaller values yield darker image, while larger yield
+		 * brighter image. Allows you to customize exposure manually, applied on top of eye adaptation exposure (if 
+		 * enabled). In range [-8, 8].
+		 */
+		float exposureScale;
+
+		/**
+		 * Gamma value to adjust the image for. Larger values result in a brighter image. When tonemapping is turned
+		 * on the best gamma curve for the output device is chosen automatically and this value can by used to merely tweak
+		 * that curve. If tonemapping is turned off this is the exact value of the gamma curve that will be applied.
+		 */
 		float gamma;
 	};
 
@@ -228,6 +374,15 @@ namespace BansheeEngine
 		BS_PARAM_BLOCK_ENTRY_ARRAY(Vector4, gTonemapParams, 2)
 		BS_PARAM_BLOCK_ENTRY(float, gGammaAdjustment)
 		BS_PARAM_BLOCK_ENTRY(int, gGammaCorrectionType)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gSaturation)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gContrast)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gGain)
+		BS_PARAM_BLOCK_ENTRY(Vector3, gOffset)
+	BS_PARAM_BLOCK_END
+
+	BS_PARAM_BLOCK_BEGIN(WhiteBalanceParams)
+		BS_PARAM_BLOCK_ENTRY(float, gWhiteTemp)
+		BS_PARAM_BLOCK_ENTRY(float, gWhiteOffset)
 	BS_PARAM_BLOCK_END
 
 	/** 
@@ -251,6 +406,7 @@ namespace BansheeEngine
 		static const UINT32 LUT_SIZE = 32;
 	private:
 		CreateTonemapLUTParams mParams;
+		WhiteBalanceParams mWhiteBalanceParams;
 	};
 
 	BS_PARAM_BLOCK_BEGIN(TonemappingParams)

+ 51 - 26
Source/RenderBeast/Source/BsPostProcessing.cpp

@@ -8,13 +8,27 @@
 
 namespace BansheeEngine
 {
-	PostProcessSettings::PostProcessSettings()
+	AutoExposureSettings::AutoExposureSettings()
 		: histogramLog2Min(-8.0f), histogramLog2Max(4.0f), histogramPctLow(0.8f), histogramPctHigh(0.985f)
-		, minEyeAdaptation(0.3f), maxEyeAdaptation(2.0f), exposureScale(0.0f), eyeAdaptationSpeedUp(3.0f)
-		, eyeAdaptationSpeedDown(3.0f), filmicCurveShoulderStrength(0.22f), filmicCurveLinearStrength(0.3f)
-		, filmicCurveLinearAngle(0.1f), filmicCurveToeStrength(0.2f), filmicCurveToeNumerator(0.01f)
-		, filmicCurveToeDenominator(0.3f), filmicCurveLinearWhitePoint(11.2f), tonemapping(true), autoExposure(true)
-		, gamma(2.2f)
+		, minEyeAdaptation(0.3f), maxEyeAdaptation(2.0f), eyeAdaptationSpeedUp(3.0f), eyeAdaptationSpeedDown(3.0f)
+	{ }
+
+	TonemappingSettings::TonemappingSettings()
+		: filmicCurveShoulderStrength(0.22f), filmicCurveLinearStrength(0.3f), filmicCurveLinearAngle(0.1f)
+		, filmicCurveToeStrength(0.2f), filmicCurveToeNumerator(0.01f), filmicCurveToeDenominator(0.3f)
+		, filmicCurveLinearWhitePoint(11.2f)
+	{ }
+
+	WhiteBalanceSettings::WhiteBalanceSettings()
+		: temperature(6500.0f), tint(0.0f)
+	{ }
+
+	ColorGradingSettings::ColorGradingSettings()
+		: saturation(Vector3::ONE), contrast(Vector3::ONE), gain(Vector3::ONE), offset(Vector3::ZERO)
+	{ }
+
+	PostProcessSettings::PostProcessSettings()
+		: enableAutoExposure(true), enableTonemapping(true), exposureScale(0.0f), gamma(2.2f)
 	{ }
 
 	DownsampleMat::DownsampleMat()
@@ -146,9 +160,9 @@ namespace BansheeEngine
 	{
 		const PostProcessSettings& settings = ppInfo.settings;
 
-		float diff = settings.histogramLog2Max - settings.histogramLog2Min;
+		float diff = settings.autoExposure.histogramLog2Max - settings.autoExposure.histogramLog2Min;
 		float scale = 1.0f / diff;
-		float offset = -settings.histogramLog2Min * scale;
+		float offset = -settings.autoExposure.histogramLog2Min * scale;
 
 		return Vector2(scale, offset);
 	}
@@ -247,16 +261,16 @@ namespace BansheeEngine
 		eyeAdaptationParams[0].x = histogramScaleAndOffset.x;
 		eyeAdaptationParams[0].y = histogramScaleAndOffset.y;
 
-		float histogramPctHigh = Math::clamp01(settings.histogramPctHigh);
+		float histogramPctHigh = Math::clamp01(settings.autoExposure.histogramPctHigh);
 
-		eyeAdaptationParams[0].z = std::min(Math::clamp01(settings.histogramPctLow), histogramPctHigh);
+		eyeAdaptationParams[0].z = std::min(Math::clamp01(settings.autoExposure.histogramPctLow), histogramPctHigh);
 		eyeAdaptationParams[0].w = histogramPctHigh;
 
-		eyeAdaptationParams[1].x = std::min(settings.minEyeAdaptation, settings.maxEyeAdaptation);
-		eyeAdaptationParams[1].y = settings.maxEyeAdaptation;
+		eyeAdaptationParams[1].x = std::min(settings.autoExposure.minEyeAdaptation, settings.autoExposure.maxEyeAdaptation);
+		eyeAdaptationParams[1].y = settings.autoExposure.maxEyeAdaptation;
 
-		eyeAdaptationParams[1].z = settings.eyeAdaptationSpeedUp;
-		eyeAdaptationParams[1].w = settings.eyeAdaptationSpeedDown;
+		eyeAdaptationParams[1].z = settings.autoExposure.eyeAdaptationSpeedUp;
+		eyeAdaptationParams[1].w = settings.autoExposure.eyeAdaptationSpeedDown;
 
 		eyeAdaptationParams[2].x = Math::pow(2.0f, settings.exposureScale);
 		eyeAdaptationParams[2].y = frameDelta;
@@ -280,6 +294,7 @@ namespace BansheeEngine
 	CreateTonemapLUTMat::CreateTonemapLUTMat()
 	{
 		mMaterial->setParamBlockBuffer("Input", mParams.getBuffer());
+		mMaterial->setParamBlockBuffer("WhiteBalanceInput", mWhiteBalanceParams.getBuffer());
 	}
 
 	void CreateTonemapLUTMat::_initDefines(ShaderDefines& defines)
@@ -297,19 +312,29 @@ namespace BansheeEngine
 		mParams.gGammaCorrectionType.set(0);
 
 		Vector4 tonemapParams[2];
-		tonemapParams[0].x = ppInfo.settings.filmicCurveShoulderStrength;
-		tonemapParams[0].y = ppInfo.settings.filmicCurveLinearStrength;
-		tonemapParams[0].z = ppInfo.settings.filmicCurveLinearAngle;
-		tonemapParams[0].w = ppInfo.settings.filmicCurveToeStrength;
-
-		tonemapParams[1].x = ppInfo.settings.filmicCurveToeNumerator;
-		tonemapParams[1].y = ppInfo.settings.filmicCurveToeDenominator;
-		tonemapParams[1].z = ppInfo.settings.filmicCurveLinearWhitePoint;
+		tonemapParams[0].x = ppInfo.settings.tonemapping.filmicCurveShoulderStrength;
+		tonemapParams[0].y = ppInfo.settings.tonemapping.filmicCurveLinearStrength;
+		tonemapParams[0].z = ppInfo.settings.tonemapping.filmicCurveLinearAngle;
+		tonemapParams[0].w = ppInfo.settings.tonemapping.filmicCurveToeStrength;
+
+		tonemapParams[1].x = ppInfo.settings.tonemapping.filmicCurveToeNumerator;
+		tonemapParams[1].y = ppInfo.settings.tonemapping.filmicCurveToeDenominator;
+		tonemapParams[1].z = ppInfo.settings.tonemapping.filmicCurveLinearWhitePoint;
 		tonemapParams[1].w = 0.0f; // Unused
 
 		mParams.gTonemapParams.set(tonemapParams[0], 0);
 		mParams.gTonemapParams.set(tonemapParams[1], 1);
 
+		// Set color grading params
+		mParams.gSaturation.set(ppInfo.settings.colorGrading.saturation);
+		mParams.gContrast.set(ppInfo.settings.colorGrading.contrast);
+		mParams.gGain.set(ppInfo.settings.colorGrading.gain);
+		mParams.gOffset.set(ppInfo.settings.colorGrading.offset);
+
+		// Set white balance params
+		mWhiteBalanceParams.gWhiteTemp.set(ppInfo.settings.whiteBalance.temperature);
+		mWhiteBalanceParams.gWhiteOffset.set(ppInfo.settings.whiteBalance.tint);
+
 		// Set output
 		POOLED_RENDER_TEXTURE_DESC outputDesc = POOLED_RENDER_TEXTURE_DESC::create3D(PF_B8G8R8X8, 
 			LUT_SIZE, LUT_SIZE, LUT_SIZE, TU_RENDERTARGET);
@@ -390,7 +415,7 @@ namespace BansheeEngine
 	void PostProcessing::postProcess(const SPtr<RenderTextureCore>& sceneColor, const SPtr<ViewportCore>& outputViewport, 
 		PostProcessInfo& ppInfo, float frameDelta)
 	{
-		if(ppInfo.settings.autoExposure)
+		if(ppInfo.settings.enableAutoExposure)
 		{
 			mDownsample.execute(sceneColor, ppInfo);
 			mEyeAdaptHistogram.execute(ppInfo);
@@ -403,12 +428,12 @@ namespace BansheeEngine
 			mEyeAdaptHistogramReduce.release(ppInfo);
 		}
 
-		if (ppInfo.settings.tonemapping)
+		if (ppInfo.settings.enableTonemapping)
 		{
 			// TODO - No need to generate LUT every frame, instead perhaps check for changes and only modify when needed?
 			mCreateLUT.execute(ppInfo);
 
-			if (ppInfo.settings.autoExposure)
+			if (ppInfo.settings.enableAutoExposure)
 				mTonemapping_AE.execute(sceneColor, outputViewport, ppInfo);
 			else
 				mTonemapping.execute(sceneColor, outputViewport, ppInfo);
@@ -417,7 +442,7 @@ namespace BansheeEngine
 		}
 		else
 		{
-			if (ppInfo.settings.autoExposure)
+			if (ppInfo.settings.enableAutoExposure)
 				mTonemapping_AE_GO.execute(sceneColor, outputViewport, ppInfo);
 			else
 				mTonemapping_GO.execute(sceneColor, outputViewport, ppInfo);