Updated Post Processing Shaders (markdown)

Sonicadvance1 2014-09-14 22:45:08 -07:00
parent d43c94b0e3
commit fce4da6664

@ -1,310 +1,311 @@
Starting with Dolphin 4.0-2554 there has been work done to improve post processing shaders to allow more user configurability without having to modify the shader sources themselves. In order to take advantage of these features, post processing shaders must be updated to take advantage of these new features. Starting with Dolphin 4.0-2554 there has been work done to improve post processing shaders to allow more user configurability without having to modify the shader sources themselves. In order to take advantage of these features, post processing shaders must be updated to take advantage of these new features.
## Staying Portable ## Staying Portable
--- ---
The first step to making a great user experience is to try and be as neutral as possible for a Direct3D or OpenGL backend. Once the post processing shaders are implemented in Direct3D, users would like their favourite shaders to work in both video backends. The first step to making a great user experience is to try and be as neutral as possible for a Direct3D or OpenGL backend. Once the post processing shaders are implemented in Direct3D, users would like their favourite shaders to work in both video backends.
Some tips for making sure your shader will compile on all backends. Some tips for making sure your shader will compile on all backends.
- Instead of using GLSL vecX types, using HLSL floatX types. Our shader compiler supports floatX in GLSL, but not the other way around. - Instead of using GLSL vecX types, using HLSL floatX types. Our shader compiler supports floatX in GLSL, but not the other way around.
- Use our embedded functions for determining UV location and sampling due to that location. In the future we can work around D3D having a different - Use our embedded functions for determining UV location and sampling due to that location. In the future we can work around D3D having a different
coordinate system using our own functions. coordinate system using our own functions.
- Try to stay away from HLSL only functions, Our shader compiler supports frac and lerp. But nothing else. - Try to stay away from HLSL only functions, Our shader compiler supports frac and lerp. But nothing else.
- We try to support GLSL 1.30 and GLSL ES 3.00 minimum. If you don't have a good reason, try to stay away from using OpenGL shader extensions. These aren't portable and we won't be able to work around them. If the functionality of the extension is absolutely necessary, try to talk with some developers to see if we can implement the functionality in both D3D and OGL in a clean fashion using our own functions. - We try to support GLSL 1.30 and GLSL ES 3.00 minimum. If you don't have a good reason, try to stay away from using OpenGL shader extensions. These aren't portable and we won't be able to work around them. If the functionality of the extension is absolutely necessary, try to talk with some developers to see if we can implement the functionality in both D3D and OGL in a clean fashion using our own functions.
## Configuration Setup ## Configuration Setup
--- ---
The Post Processing shader's configuration sits inside of the actual post processing shader code. It's recommended to have the configuration towards the top of the shader, outside of the main function. The Post Processing shader's configuration sits inside of the actual post processing shader code. It's recommended to have the configuration towards the top of the shader, outside of the main function.
There are two requirements to this There are two requirements to this
- It must be in a comment block - It must be in a comment block
- It must be surrounded by [configuration] and [/configuration] - It must be surrounded by [configuration] and [/configuration]
The configuration inside of of this block is similar to how Windows' INI files work and we have three sections that we support for different options. The configuration inside of of this block is similar to how Windows' INI files work and we have three sections that we support for different options.
- **[OptionBool]** - **[OptionBool]**
- This is a boolean option, this'll show as a checkbox in the GUI - This is a boolean option, this'll show as a checkbox in the GUI
- **[OptionRangeInteger]** or **[OptionRangeFloat]** - **[OptionRangeInteger]** or **[OptionRangeFloat]**
- This is a integer or float range that is anywhere from one to four elements - This is a integer or float range that is anywhere from one to four elements
- This will show up as one to four sliders in the GUI - This will show up as one to four sliders in the GUI
Any of these options *require* all three settings set at all times Any of these options *require* all three settings set at all times
- **GUIName** - **GUIName**
- This is a string that will show up in the GUI for that corresponding option - This is a string that will show up in the GUI for that corresponding option
- **OptionName** - **OptionName**
- This is a case sensitive unique identifier that is used in the post processing shader - This is a case sensitive unique identifier that is used in the post processing shader
- You'll get errors if this isn't unique - You'll get errors if this isn't unique
- **DefaultValue** - **DefaultValue**
- This is the default value that is set prior to any sort of user configuration - This is the default value that is set prior to any sort of user configuration
- For [OptionBool] this can be 'True' or 'False' - For [OptionBool] this can be 'True' or 'False'
- For [OptionRangeInteger] and [OptionRangeFloat] this can be a single value or a vector - For [OptionRangeInteger] and [OptionRangeFloat] this can be a single value or a vector
- How many values in this setting determine how many values show up in the UI - How many values in this setting determine how many values show up in the UI
- Examples - Examples
- DefaultValue = True - DefaultValue = True
- DefaultValue = 1 - DefaultValue = 1
- DefaultValue = 1.0, 1.0, 1.0, 1.0 - DefaultValue = 1.0, 1.0, 1.0, 1.0
There is one optional setting that all three configuration types can have; This is 'DependentOption'. There is one optional setting that all three configuration types can have; This is 'DependentOption'.
This allows options to be children of [OptionBool] options. This allows basic grouping of options, which effects how options will show up in the GUI. If a option has children they will show up in the same tab, if there aren't any children they will show up in a general option tab. This allows options to be children of [OptionBool] options. This allows basic grouping of options, which effects how options will show up in the GUI. If a option has children they will show up in the same tab, if there aren't any children they will show up in a general option tab.
The value of this option must be the 'OptionName' of a [OptionBool] The value of this option must be the 'OptionName' of a [OptionBool]
If you make circular dependencies of options, you reap what you sow. If you make circular dependencies of options, you reap what you sow.
[OptionRangeInteger] and [OptionRangeFloat] have other **required** settings to be set [OptionRangeInteger] and [OptionRangeFloat] have other **required** settings to be set
- **MinValue** - **MinValue**
- This is the minimum value that a integer or float range has - This is the minimum value that a integer or float range has
- In a vector each value can have a different value - In a vector each value can have a different value
- **MaxValue** - **MaxValue**
- This is the maximum value that a integer or float range has - This is the maximum value that a integer or float range has
- In a vector each value can have a different value - In a vector each value can have a different value
- **StepAmount** - **StepAmount**
- This is how much the range changes in the UI per step - This is how much the range changes in the UI per step
- In a vector each value can have a different value - In a vector each value can have a different value
Sample Configuration Sample Configuration
```bash ```bash
/* /*
[configuration] [configuration]
[OptionBool] [OptionBool]
GUIName = Skylight Bevel Shader GUIName = Skylight Bevel Shader
OptionName = BEVEL OptionName = BEVEL
DefaultValue = true DefaultValue = true
[OptionRangeFloat] [OptionRangeFloat]
GUIName = Skylight Amount GUIName = Skylight Amount
OptionName = SKYLIGHT_AMOUNT OptionName = SKYLIGHT_AMOUNT
MinValue = 0.0 MinValue = 0.0
MaxValue = 1.0 MaxValue = 1.0
StepAmount = 0.05, StepAmount = 0.05,
DefaultValue = 0.5 DefaultValue = 0.5
DependentOption = BEVEL DependentOption = BEVEL
[OptionRangeFloat] [OptionRangeFloat]
GUIName = Sky Color GUIName = Sky Color
OptionName = SKY_COLOR OptionName = SKY_COLOR
MinValue = 0.0, 0.0, 0.0 MinValue = 0.0, 0.0, 0.0
MaxValue = 1.0, 1.0, 1.0 MaxValue = 1.0, 1.0, 1.0
StepAmount = 0.05, 0.05, 0.05 StepAmount = 0.05, 0.05, 0.05
DefaultValue = 0.1, 0.1, 0.5 DefaultValue = 0.1, 0.1, 0.5
DependentOption = BEVEL DependentOption = BEVEL
[OptionRangeInteger] [OptionRangeInteger]
GUIName = Ground Color GUIName = Ground Color
OptionName = GROUND_COLOR OptionName = GROUND_COLOR
MinValue = 0, 0, 0 MinValue = 0, 0, 0
MaxValue = 256, 256, 256 MaxValue = 256, 256, 256
StepAmount = 1, 1, 1 StepAmount = 1, 1, 1
DefaultValue = 1, 1, 1 DefaultValue = 1, 1, 1
DependentOption = BEVEL DependentOption = BEVEL
[/configuration] [/configuration]
*/ */
``` ```
## Embedded Functions ## Embedded Functions
--- ---
```c++ ```c++
float4 Sample(); float4 Sample();
``` ```
Samples the current location, returning a vector containing the colour of the current sample Samples the current location, returning a vector containing the colour of the current sample
*** ***
```c++ ```c++
float4 SampleLocation(float2 location); float4 SampleLocation(float2 location);
``` ```
Samples a location that doesn't have to be the current sample location Samples a location that doesn't have to be the current sample location
location is a float vector which contains the X Y coordinates of where to sample from location is a float vector which contains the X Y coordinates of where to sample from
The sample range is 0.0 to 1.0 using the OpenGL coordinate system The sample range is 0.0 to 1.0 using the OpenGL coordinate system
*** ***
```c++ ```c++
float4 SampleOffset(int2 offset); float4 SampleOffset(int2 offset);
``` ```
This samples at a offset of the current location. This samples at a offset of the current location.
The argument is a integer vector containing the X Y offset of where to sample from The argument is a integer vector containing the X Y offset of where to sample from.
The offset is in pixels instead of using UV coordinates. The offset is in pixels instead of using UV coordinates.
This requires the offset to be a compile time constant, if it isn't then compiling will fail This requires the offset to be a compile time constant, if it isn't then compiling will fail.
This is similar to SampleLocation, except the video drivers and hardware can optimize to be faster This is similar to SampleLocation, except the video drivers and hardware can optimize to be faster.
*** This is a limitation in how large the offset can be. To be safe on all platforms, limit the offset from ranges -8 to 7.
```c++ ***
float4 SampleFontLocation(float2 location); ```c++
``` float4 SampleFontLocation(float2 location);
This doesn't sample the framebuffer like the previous functions. ```
This actually samples a location from Dolphin's bitmap font that it uses for on screen text. This doesn't sample the framebuffer like the previous functions.
The best example of how to use this is to look at Dolphin's asciiart PP shader This actually samples a location from Dolphin's bitmap font that it uses for on screen text.
*** The best example of how to use this is to look at Dolphin's asciiart PP shader
```c++ ***
float2 GetResolution(); ```c++
``` float2 GetResolution();
Returns a float vector contain the resolution of the framebuffer ```
*** Returns a float vector contain the resolution of the framebuffer
```c++ ***
float2 GetInvResolution(); ```c++
``` float2 GetInvResolution();
Returns a float vector containing the reciprocal of the framebuffer resolution ```
This can be used to quickly get a float offset from the current sample position Returns a float vector containing the reciprocal of the framebuffer resolution
*** This can be used to quickly get a float offset from the current sample position
```c++ ***
float2 GetCoordinates(); ```c++
``` float2 GetCoordinates();
Returns a float vector containing the UV coordinates where we are currently sampling from ```
This can be used when sampling from a location offset from the current location. Returns a float vector containing the UV coordinates where we are currently sampling from
Tends to be used in conjunction with GetInvResolution() This can be used when sampling from a location offset from the current location.
Recommended to use SampleOffset instead if the offset is a compile time constant Tends to be used in conjunction with GetInvResolution()
*** Recommended to use SampleOffset instead if the offset is a compile time constant
```c++ ***
uint GetTime(); ```c++
``` uint GetTime();
This returns a 32bit unsigned integer of the elapsed time since emulation has started ```
The time is in milliseconds This returns a 32bit unsigned integer of the elapsed time since emulation has started
This allows for shaders that can do certain effects with the passage of time The time is in milliseconds
*** This allows for shaders that can do certain effects with the passage of time
```c++ ***
void SetOutput(float4 colour); ```c++
``` void SetOutput(float4 colour);
The argument is a float vector containing what the resulting output should be at the current sampling location ```
*** The argument is a float vector containing what the resulting output should be at the current sampling location
```c++ ***
bool OptionEnabled(option); ```c++
``` bool OptionEnabled(option);
Returns a boolean for if a boolean option is enabled or not ```
This only works for the Option type configuration option Returns a boolean for if a boolean option is enabled or not
Takes the OptionName that was defined in the configuration This only works for the Option type configuration option
- Example Takes the OptionName that was defined in the configuration
```c++ - Example
if (OptionEnable(BEVEL)) { /* Do Stuff*/ } ```c++
``` if (OptionEnable(BEVEL)) { /* Do Stuff*/ }
*** ```
```c++ ***
genType GetOption(option); ```c++
``` genType GetOption(option);
Returns an options current setting ```
genType is either int, float, float2/3/4, int2/3/4 Returns an options current setting
Depending on what type your option is in the configuration it'll return the correct type here genType is either int, float, float2/3/4, int2/3/4
Takes the OptionName that was defined in the configuration Depending on what type your option is in the configuration it'll return the correct type here
- Example Takes the OptionName that was defined in the configuration
```c++ - Example
float3 colour_boost = GetOption(SKY_COLOR); ```c++
``` float3 colour_boost = GetOption(SKY_COLOR);
## Sample Shader ```
--- ## Sample Shader
```c++ ---
/* ```c++
[configuration] /*
[OptionBool] [configuration]
GUIName = Skylight Bevel Shader [OptionBool]
OptionName = BEVEL GUIName = Skylight Bevel Shader
DefaultValue = true OptionName = BEVEL
DefaultValue = true
[OptionRangeFloat]
GUIName = Skylight Amount [OptionRangeFloat]
OptionName = SKYLIGHT_AMOUNT GUIName = Skylight Amount
MinValue = 0.0 OptionName = SKYLIGHT_AMOUNT
MaxValue = 1.0 MinValue = 0.0
StepAmount = 0.05, MaxValue = 1.0
DefaultValue = 0.5 StepAmount = 0.05,
DependentOption = BEVEL DefaultValue = 0.5
DependentOption = BEVEL
[OptionRangeFloat]
GUIName = Sky Color [OptionRangeFloat]
OptionName = SKY_COLOR GUIName = Sky Color
MinValue = 0.0, 0.0, 0.0 OptionName = SKY_COLOR
MaxValue = 1.0, 1.0, 1.0 MinValue = 0.0, 0.0, 0.0
StepAmount = 0.05, 0.05, 0.05 MaxValue = 1.0, 1.0, 1.0
DefaultValue = 0.1, 0.1, 0.5 StepAmount = 0.05, 0.05, 0.05
DependentOption = BEVEL DefaultValue = 0.1, 0.1, 0.5
DependentOption = BEVEL
[OptionRangeFloat]
GUIName = Base Color [OptionRangeFloat]
OptionName = BASE_COLOR GUIName = Base Color
MinValue = 0.0, 0.0, 0.0 OptionName = BASE_COLOR
MaxValue = 1.0, 1.0, 1.0 MinValue = 0.0, 0.0, 0.0
StepAmount = 0.05, 0.05, 0.05 MaxValue = 1.0, 1.0, 1.0
DefaultValue = 0.0, 0.0, 0.1 StepAmount = 0.05, 0.05, 0.05
DependentOption = BEVEL DefaultValue = 0.0, 0.0, 0.1
DependentOption = BEVEL
[OptionRangeFloat]
GUIName = Ground Color [OptionRangeFloat]
OptionName = GROUND_COLOR GUIName = Ground Color
MinValue = 0.0, 0.0, 0.0 OptionName = GROUND_COLOR
MaxValue = 1.0, 1.0, 1.0 MinValue = 0.0, 0.0, 0.0
StepAmount = 0.05, 0.05, 0.05 MaxValue = 1.0, 1.0, 1.0
DefaultValue = 0.1, 0.4, 0.1 StepAmount = 0.05, 0.05, 0.05
DependentOption = BEVEL DefaultValue = 0.1, 0.4, 0.1
DependentOption = BEVEL
[OptionBool]
GUIName = Sharpen [OptionBool]
OptionName = SHARPNESS GUIName = Sharpen
DefaultValue = true OptionName = SHARPNESS
DefaultValue = true
[OptionRangeFloat]
GUIName = Sharpness Amount [OptionRangeFloat]
OptionName = SHARPNESS_VALUE GUIName = Sharpness Amount
MinValue = 0.0 OptionName = SHARPNESS_VALUE
MaxValue = 10.0 MinValue = 0.0
StepAmount = 0.5 MaxValue = 10.0
DefaultValue = 1.5 StepAmount = 0.5
DependentOption = SHARPNESS DefaultValue = 1.5
DependentOption = SHARPNESS
[OptionBool]
GUIName = Color Boost [OptionBool]
OptionName = COLOR_BOOST GUIName = Color Boost
DefaultValue = true OptionName = COLOR_BOOST
DefaultValue = true
[OptionRangeFloat]
GUIName = Color Boost Red [OptionRangeFloat]
OptionName = RED_BOOST GUIName = Color Boost Red
MinValue = 0.0 OptionName = RED_BOOST
MaxValue = 5.0 MinValue = 0.0
StepAmount = 0.1 MaxValue = 5.0
DefaultValue = 1.0 StepAmount = 0.1
DependentOption = COLOR_BOOST DefaultValue = 1.0
DependentOption = COLOR_BOOST
[OptionRangeFloat]
GUIName = Color Boost Green [OptionRangeFloat]
OptionName = GREEN_BOOST GUIName = Color Boost Green
MinValue = 0.0 OptionName = GREEN_BOOST
MaxValue = 5.0 MinValue = 0.0
StepAmount = 0.1 MaxValue = 5.0
DefaultValue = 1.0 StepAmount = 0.1
DependentOption = COLOR_BOOST DefaultValue = 1.0
DependentOption = COLOR_BOOST
[OptionRangeFloat]
GUIName = Color Boost Blue [OptionRangeFloat]
OptionName = BLUE_BOOST GUIName = Color Boost Blue
MinValue = 0.0 OptionName = BLUE_BOOST
MaxValue = 5.0 MinValue = 0.0
StepAmount = 0.1 MaxValue = 5.0
DefaultValue = 1.0 StepAmount = 0.1
DependentOption = COLOR_BOOST DefaultValue = 1.0
[/configuration] DependentOption = COLOR_BOOST
*/ [/configuration]
*/
void main() {
float3 curr = Sample().xyz; void main() {
float3 curr = Sample().xyz;
if (OptionEnabled(SHARPNESS))
{ if (OptionEnabled(SHARPNESS))
float3 s0 = SampleOffset(int2(-1, -1)).xyz; {
float3 s1 = SampleOffset(int2( 1, -1)).xyz; float3 s0 = SampleOffset(int2(-1, -1)).xyz;
float3 s2 = SampleOffset(int2(-1, 1)).xyz; float3 s1 = SampleOffset(int2( 1, -1)).xyz;
float3 s3 = SampleOffset(int2( 1, 1)).xyz; float3 s2 = SampleOffset(int2(-1, 1)).xyz;
float3 blur = (curr + s0 + s1 + s2 + s3) / 5; float3 s3 = SampleOffset(int2( 1, 1)).xyz;
curr = curr + (curr - blur) * GetOption(SHARPNESS_VALUE); float3 blur = (curr + s0 + s1 + s2 + s3) / 5;
} curr = curr + (curr - blur) * GetOption(SHARPNESS_VALUE);
}
if (OptionEnabled(BEVEL))
{ if (OptionEnabled(BEVEL))
float mid = dot(curr, float3(0.33, 0.33, 0.33)); {
float top = dot(SampleOffset(int2(0, 1)).xyz, float3(0.33, 0.33, 0.33)); float mid = dot(curr, float3(0.33, 0.33, 0.33));
float bot = dot(SampleOffset(int2(0, -1)).xyz, float3(0.33, 0.33, 0.33)); float top = dot(SampleOffset(int2(0, 1)).xyz, float3(0.33, 0.33, 0.33));
float upw = ((top - mid) + (mid - bot)) / 4 + 0.5; float bot = dot(SampleOffset(int2(0, -1)).xyz, float3(0.33, 0.33, 0.33));
float3 col = mix(GetOption(SKY_COLOR), GetOption(GROUND_COLOR), upw); float upw = ((top - mid) + (mid - bot)) / 4 + 0.5;
float3 shde = mix(GetOption(BASE_COLOR), col, clamp(abs(upw * 2.0 - 1.0) * 1, 0.0, 1.0)); float3 col = mix(GetOption(SKY_COLOR), GetOption(GROUND_COLOR), upw);
curr = curr + shde * GetOption(SKYLIGHT_AMOUNT); float3 shde = mix(GetOption(BASE_COLOR), col, clamp(abs(upw * 2.0 - 1.0) * 1, 0.0, 1.0));
} curr = curr + shde * GetOption(SKYLIGHT_AMOUNT);
}
if (OptionEnabled(COLOR_BOOST))
curr = curr * float3(GetOption(RED_BOOST), GetOption(GREEN_BOOST), GetOption(BLUE_BOOST)); if (OptionEnabled(COLOR_BOOST))
curr = curr * float3(GetOption(RED_BOOST), GetOption(GREEN_BOOST), GetOption(BLUE_BOOST));
/* Done */
SetOutput(float4(curr, 1.0)); /* Done */
} SetOutput(float4(curr, 1.0));
``` }
## Translations ```
--- ## Translations
---
**TBD** **TBD**