#version 450 /* Annotated Passthru slang shader by hunterk license: public domain */ /* This is a good spot for license blocks and other misc information */ /*-------------------- Pass Characteristics --------------------*/ /* Most of the pass characteristics/metadata is controlled by shader presets, but we can set a few things directly here via pragmas. The 'format' pragma sets the output format for the framebuffer. These are the most common. 8-bit UNORM is the default but integer and float formats can be useful for calculating values in one pass and then using the results in another */ #pragma format R8G8B8A8_UNORM /* 8-bit R8G8B8A8_UNORM R8G8B8A8_UINT R8G8B8A8_SINT R8G8B8A8_SRGB 10-bit A2B10G10R10_UNORM_PACK32 A2B10G10R10_UINT_PACK32 16-bit R16G16B16A16_UINT R16G16B16A16_SINT R16G16B16A16_SFLOAT 32-bit R32G32B32A32_UINT R32G32B32A32_SINT R32G32B32A32_SFLOAT */ /* See the spec document for any additional, more esoteric formats. */ /* We can use the 'name' pragma to declare a name (called an 'alias' in the presets) for the pass, which can make it easier for other shaders to reference it. The alias/name can be used to refer to this pass specifically in other passes--FooSize, texture(Foo, coord), etc.--regardless of position/order. */ #pragma name Foo /*------------- Parameters and Variable Structs --------------*/ /* This "push_constant" struct contains fast-access uniform data, which may provide better performance vs regular UBOs. It has a max capacity of 192 bytes, which equates to 48 single-component vectors of float. We usually use them for runtime parameters, hence the struct name, but you can change that if you like. */ layout(push_constant) uniform Push { float runtime_parameter, user_toggle_parameter, red, green, blue; } params; /* We can use a pragma to call out "parameters", which are exposed in RetroArch's shader menu for users to modify values on-the-fly without touching code directly. These parameters are adjustable at runtime. The values are: default, minimum, maximum and step. */ #pragma parameter runtime_parameter "Human-readable Parameter Name" 0.0 -10.0 10.0 0.01 /* Some authors like to macro the struct name for easier code compatibility with other shader formats (i.e., so you don't need to prepend the struct name on each use): */ #define runtime_parameter params.runtime_parameter /* Sometimes a basic float isn't what your code calls for, so you may want to cast parameters like this: */ #pragma parameter user_toggle_parameter "A Simple Toggle" 0.0 0.0 1.0 1.0 bool user_toggle = bool(params.user_toggle_parameter); /* or combine parameters like this into a multi-parameter vector of float: */ #pragma parameter red "Red Channel Intensity" 1.0 0.0 2.0 0.01 #pragma parameter green "Green Channel Intensity" 1.0 0.0 2.0 0.01 #pragma parameter blue "Blue Channel Intensity" 1.0 0.0 2.0 0.01 vec3 colorChannels = vec3(params.red, params.green, params.blue); /*-------------------- Include Statements --------------------*/ /* You can use include statements, which will copy the contents of the included file directly into this one at compile time. If there's a possibility of recursive include statements, it's a good idea to wrap that code in an 'ifndef/define' block. */ //#include "shared_parameters.inc" /*-------------------- Built-in Uniforms --------------------*/ /* This "global" struct has no size limit, so if you run out of space in the push_constants struct, you can move things here. We also typically store our built-in uniforms here. */ layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; /* A NOTE ABOUT 'FooSize': The size of a built-in or aliased texture (e.g., Source, Original or, in this case, Foo) can be accessed as a 4-parameter vector of float that includes the width, height and the reciprocal of the width and height. Ideally, you can also access the size of a LUT texture that has an alias set in the preset file, but not all video drivers in RetroArch play nicely with this, so it's safer--but slower--to use TextureSize() for that. */ /* The size of the input framebuffer as presented to this stage in the shader pipeline */ vec4 SourceSize; /* The size of the raw input framebuffer as presented to the shader pipeline */ vec4 OriginalSize; /* The size of the outgoing framebuffer of the current pass */ vec4 OutputSize; /* The size of the outgoing framebuffer of the final shader pass, which should always be the size of the user's viewport. */ vec4 FinalViewportSize; /* The number of frames generated by the core. Used for animated effects. */ uint FrameCount; /* Which way the FrameCount is currently going. A negative value means the content is being "rewound". This is usually used for VCR or "Braid"-like effects. */ uint FrameDirection; /* If RetroArch's "subframe" feature is enabled, this ticks up on each subframe and resets on the next full frame. FrameCount is not affected by subframes. */ uint CurrentSubFrame; /* The total number of subframes. This number should stay consistent. The ratio of CurrentSubFrame / TotalSubFrames is frequently used. */ uint TotalSubFrames; /* The rotation status of the framebuffer. This is used to determine whether content is currently being rotated by the frontend for "TATE" mode (e.g., many arcade games, especially shmups) */ uint Rotation; } global; /* This is a good spot for common functions that may be used by both the vertex and fragment, since it is accessible in both stages. */ /*------------------------- Vertex Shader -------------------------*/ /* We use pragmas to separate the stages of the shader into vertex and fragment in the same file: */ #pragma stage vertex /*--------------------- Vertex Inputs/Outputs ---------------------*/ layout(location = 0) in vec4 Position; layout(location = 1) in vec2 TexCoord; layout(location = 0) out vec2 vTexCoord; layout(location = 1) out float calc_val; /* This is a good spot for vertex-specific functions. */ void main() { gl_Position = global.MVP * Position; vTexCoord = TexCoord; /* It's usually best to conduct expensive calculations in the vertex stage, where it's only performed once per vertex vs per-pixel in the fragment stage, and then pass that value to the fragment, though this isn't possible with all calculations: */ calc_val = (user_toggle) ? min(colorChannels.x, min(colorChannels.y, colorChannels.z)) : max(colorChannels.x, max(colorChannels.y, colorChannels.z)); } /*--------------------- Fragment/Pixel Shader ---------------------*/ #pragma stage fragment /*-------------------- Fragment Inputs/Outputs --------------------*/ layout(location = 0) in vec2 vTexCoord; layout(location = 1) in float calc_val; layout(location = 0) out vec4 FragColor; /*------------------------ Texture Binding ------------------------*/ /* Source is a built-in alias for the input framebuffer as presented to this stage in the shader pipeline. */ layout(set = 0, binding = 2) uniform sampler2D Source; /* PassFeedback* is a built-in alias for the shaded output of the selected pass; used for FIR effects. This can also be aliased, e.g., FooFeedback */ layout(set = 0, binding = 3) uniform sampler2D PassFeedback0; /* Original is a built-in alias for the raw input framebuffer as presented to the shader pipeline. */ layout(set = 0, binding = 4) uniform sampler2D Original; /* OriginalHistory* is a built-in alias for the input framebuffer from previous frames, working backward. */ layout(set = 0, binding = 5) uniform sampler2D OriginalHistory1; /* This is a good spot for fragment-specific functions. */ void main() { vec3 img = texture(Source, vTexCoord).rgb; img *= colorChannels; FragColor = vec4(img, 1.0); }