McNolan... --->
I thought I'd explain how I port a simple shader to ReShade 3.0.
Take the old Reinhard Linear 1.0 shader as an example:
Code:
float4 ReinhardLinearToneMapping(float4 colorInput)
{
float3 x = colorInput.rgb;
const float W = ReinhardLinearWhitepoint; // Linear White Point Value
const float L = ReinhardLinearPoint; // Linear point
const float C = ReinhardLinearSlope; // Slope of the linear section
const float K = (1 - L * C) / C; // Scale (fixed so that the derivatives of the Reinhard and linear functions are the same at x = L)
float3 reinhard = L * C + (1 - L * C) * (1 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);
// gamma space or not?
colorInput.rgb = (x > L) ? reinhard : C * x;
return colorInput;
}
And now we compare it with another simple shader found in 3.0:
Code:
/**
* Tonemap version 1.1
* by Christian Cann Schuldt Jensen ~ CeeJay.dk
*/
uniform float Gamma <
ui_type = "drag";
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "Adjust midtones. 1.000 is neutral. This setting does exactly the same as the one in Lift Gamma Gain, only with less control.";
> = 1.0;
uniform float Exposure <
ui_type = "drag";
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "Adjust exposure";
> = 0.0;
uniform float Saturation <
ui_type = "drag";
ui_min = -1.0; ui_max = 1.0;
ui_tooltip = "Adjust saturation";
> = 0.0;
uniform float Bleach <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "Brightens the shadows and fades the colors";
> = 0.0;
uniform float Defog <
ui_type = "drag";
ui_min = 0.0; ui_max = 1.0;
ui_tooltip = "How much of the color tint to remove";
> = 0.0;
uniform float3 FogColor <
ui_type = "color";
ui_label = "Defog Color";
ui_tooltip = "Which color tint to remove";
> = float3(0.0, 0.0, 1.0);
#include "ReShade.fxh"
float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
color = saturate(color - Defog * FogColor * 2.55); // Defog
color *= pow(2.0f, Exposure); // Exposure
color = pow(color, Gamma); // Gamma
const float3 coefLuma = float3(0.2126, 0.7152, 0.0722);
float lum = dot(coefLuma, color);
float L = saturate(10.0 * (lum - 0.45));
float3 A2 = Bleach * color;
float3 result1 = 2.0f * color * lum;
float3 result2 = 1.0f - 2.0f * (1.0f - lum) * (1.0f - color);
float3 newColor = lerp(result1, result2, L);
float3 mixRGB = A2 * newColor;
color += ((1.0f - A2) * mixRGB);
float3 middlegray = dot(color, (1.0 / 3.0));
float3 diffcolor = color - middlegray;
color = (color + diffcolor * Saturation) / (1 + (diffcolor * Saturation)); // Saturation
return color;
}
technique Tonemap
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TonemapPass;
}
}
The first 3 sections of code are what we use to tweak in the GUI - so called GUI annotations. They need to be in a shader if we want to tweak the shader settings in the 3.0 GUI.
So lets start by copying one GUI annotation to the new shader as we need it later...
Code:
uniform float Gamma < ui_type = "drag";
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "Adjust midtones. 1.000 is neutral. This setting does exactly the same as the one in Lift Gamma Gain, only with less control.";
> = 1.0;
Now, we copy 3 lines of code...
Code:
float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
return color;
}
The space in the middle is where the actual stuff happens.
So lets take the corresponding part of code in the first Reinhard shader and paste it:
Code:
float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 x = colorInput.rgb;
const float W = ReinhardLinearWhitepoint; // Linear White Point Value
const float L = ReinhardLinearPoint; // Linear point
const float C = ReinhardLinearSlope; // Slope of the linear section
const float K = (1 - L * C) / C; // Scale (fixed so that the derivatives of the Reinhard and linear functions are the same at x = L)
float3 reinhard = L * C + (1 - L * C) * (1 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);
// gamma space or not?
colorInput.rgb = (x > L) ? reinhard : C * x;
return color;
}
The line float3 x = colorInput.rgb; is searching for the function colorInput but we only have a color.rgb line so delete Input and we have float3 x = color.rgb;.
Next up are the three const floats with the Reinhard lines. These functions are searching for its buddies, so lets add those here:
Code:
uniform float ReinhardLinearSlope <
ui_type = "drag";
ui_min = 1.0; ui_max = 5.0;
ui_tooltip = "how steep the color curve is at linear point";
> = 1.250;
uniform float ReinhardLinearWhitepoint <
ui_type = "drag";
ui_min = 0.0; ui_max = 20.0;
ui_tooltip = "...";
> = 1.250;
uniform float ReinhardLinearPoint <
ui_type = "drag";
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "...";
> = 0.150;
The order of these functions doesn't matter as long as they're on top in the shader.
Last one is colorInput.rgb = (x > L) ? reinhard : C * x;, but remember that we didn't had colorInput.rgb in the shader, only color.rgb. So again, delete Input...
Be sure to rename stuff like in the technique pass and functions, like this:
Code:
float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
...to...
Code:
float3 ReinhardLinearPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
And:
Code:
technique Tonemap
{
pass
{
VertexShader = PostProcessVS;
PixelShader = TonemapPass;
}
}
...to...
Code:
technique ReinhardLinear
{
pass
{
VertexShader = PostProcessVS;
PixelShader = ReinhardLinearPass;
}
}
We should now have a shader that should look like this:
Code:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//LICENSE AGREEMENT AND DISTRIBUTION RULES:
//1 Copyrights of the Master Effect exclusively belongs to author - Gilcher Pascal aka Marty McFly.
//2 Master Effect (the SOFTWARE) is DonateWare application, which means you may or may not pay for this software to the author as donation.
//3 If included in ENB presets, credit the author (Gilcher Pascal aka Marty McFly).
//4 Software provided "AS IS", without warranty of any kind, use it on your own risk.
//5 You may use and distribute software in commercial or non-commercial uses. For commercial use it is required to warn about using this software (in credits, on the box or other places). Commercial distribution of software as part of the games without author permission prohibited.
//6 Author can change license agreement for new versions of the software.
//7 All the rights, not described in this license agreement belongs to author.
//8 Using the Master Effect means that user accept the terms of use, described by this license agreement.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//For more information about license agreement contact me:
//https://www.facebook.com/MartyMcModding
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Copyright (c) 2009-2015 Gilcher Pascal aka Marty McFly
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Credits :: Ubisoft
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Amateur port by Insomnia
uniform float ReinhardLinearSlope <
ui_type = "drag";
ui_min = 1.0; ui_max = 5.0;
ui_tooltip = "how steep the color curve is at linear point";
> = 1.250;
uniform float ReinhardLinearWhitepoint <
ui_type = "drag";
ui_min = 0.0; ui_max = 20.0;
ui_tooltip = "...";
> = 1.250;
uniform float ReinhardLinearPoint <
ui_type = "drag";
ui_min = 0.0; ui_max = 2.0;
ui_tooltip = "...";
> = 0.150;
#include "ReShade.fxh"
float3 ReinhardLinearPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target
{
float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb;
float3 x = color.rgb;
const float W = ReinhardLinearWhitepoint; // Linear White Point Value
const float L = ReinhardLinearPoint; // Linear point
const float C = ReinhardLinearSlope; // Slope of the linear section
const float K = (1 - L * C) / C; // Scale (fixed so that the derivatives of the Reinhard and linear functions are the same at x = L)
float3 reinhard = L * C + (1 - L * C) * (1 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);
// gamma space or not?
color.rgb = (x > L) ? reinhard : C * x;
return color;
}
technique ReinhardLinear
{
pass
{
VertexShader = PostProcessVS;
PixelShader = ReinhardLinearPass;
}
}
Hope I explained decently lol.
Cheers!