forked from Themaister/slang-shaders
-
Notifications
You must be signed in to change notification settings - Fork 96
/
annotated_passthru.slang
159 lines (142 loc) · 7.66 KB
/
annotated_passthru.slang
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#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);
}