OBS Shading Language (OBS-SL)
(Original source: obs-StreamFX documentation under CC BY)
Execution context
The baseline for the shader language libOBS uses is HLSL, for which you can find documentation here. libOBS modifies this so it works across all of its supported graphics APIs, sacrificing functionality and versatility for compatibility. As a result, some effects that would be possible with ease in GLSL or HLSL directly do not work in libOBS's shader language. For the sake of all future documentation, the language will be referred to as OBS-SL, since it mixes and matches many different language constructs into one.
When libobs-opengl
is in use, the OBS-SL shader is transpiled into GLSL. It will create an intermediate source-code with:
- a fixed first line with
#version 330
(so OBS requests GLSL 3.30) since OBS 24.0, in 2019. - different line numbers than the original ones...
... making life harder when a compilation errors came from your shader.
OBS do a HLSL to GLSL function mapping
As a rule of thumb, always use the HLSL native function, OBS will replace occurences with the GLSL one, the reverse assumption is mostly false.
To give simple examples, you will have to use lerp()
instead of mix()
and frac()
instead of fract()
in your OBS-SL code to make OBS happy.
See syntax/shader-transpilation.md to have a list of what is defined and translated by OBS and Shadertastic.
Data Storage
Similar to HLSL, OBS-SL supports storage, transfer and modification of data.
Storage Specifiers
Storage specifiers seem to only be used by the OpenGL backend.
Name | DirectX | OpenGL | Notes |
---|---|---|---|
uniform |
uniform |
||
const |
const |
||
inout |
inout |
||
out |
out |
Types
Name | DirectX | OpenGL |
---|---|---|
bool |
bool |
bool |
float |
float |
float |
float2 |
float2 |
vec2 |
float3 |
float3 |
vec3 |
float4 |
float4 |
vec4 |
int |
int |
int |
int2 |
int2 |
ivec2 |
int3 |
int3 |
ivec3 |
int4 |
int4 |
ivec4 |
string |
string |
string |
float3x3 |
float3x3 |
mat3x3 |
float3x4 |
float3x4 |
mat3x4 |
float4x4 |
float4x4 |
mat4x4 |
texture2d |
Texture2D |
sampler2D |
texture3d |
Texture3D |
sampler3D |
texture_cube |
TextureCube |
samplerCube |
texture_rect |
N/A | sampler2DRect |
sampler_state |
SamplerState |
Metadata only |
Notes:
float2x2
(rotation) matrix is supported by OBS-SL parser but not translated, only float3x3, 3x4 and 4x4 are usable.- despite the
string
type availability, there is no string-handling functions at all, andint c = 'a';
is not a usable thing neither.
Operators
They are much like in C. But as HLSL official documentation says: unlike short-circuit evaluation of &&, ||, and ?: in C, HLSL expressions never short-circuit an evaluation because they are vector operations. All sides of the expression are always evaluated.
Arrays
At the time of writing this, uniform
s as arrays are only supported when DirectX is being used by libOBS. The patch to make it available in OpenGL was retracted at the request of the current OBS Project team.
So you can't really use uniform float[20] something;
from the CPU to the GPU world, but some const
or static
fixed tables in the shader source-code is fine. You may need to use some #ifdef
for initialisation :
#define POW10_TABLE_VALUES 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000
#ifdef _OPENGL
const int pow10_table[10] = int[10](POW10_TABLE_VALUES);
#else
static int pow10_table[10] = {POW10_TABLE_VALUES};
#endif
Keywords
A limited subset of keywords are supported, other keywords may work if they match across both langauges.
Name | DirectX | OpenGL |
---|---|---|
POSITION |
SV_Position |
gl_FragCoord |
TARGET |
SV_Target |
N/A |
VERTEXID |
SV_VertexID |
uint(gl_VertexID) |
Input/Output Semantics
A limited subset of semantics are supported, other keywords will not work.
Name | DirectX | OpenGL | Notes |
---|---|---|---|
POSITION |
SV_Position |
Metadata only | Provided as float32[4] |
NORMAL |
NORMAL |
Metadata only | Provided as float32[4] |
COLOR |
COLOR |
Metadata only | Provided as uint8_unorm[4] |
TANGENT |
TANGENT |
Metadata only | Provided as float32[4] |
TEXCOORD |
TEXCOORD |
Metadata only | Either float32 , float32[2] or float32[4] . |
VERTEXID |
VERTEXID |
Metadata only |
Sampler States
A sampler state controls how a texture is sampled by future operations on it. Sampler States are global and can't be passed as parameters or modified while the vertex or fragment shader run. Sampler Sates have the following settings:
Filter
Name | Magnification | Minification | Mip-Mapping |
---|---|---|---|
Point , MIN_MAG_MIP_POINT |
Point | Point | Point |
Linear , MIN_MAG_MIP_LINEAR |
Linear | Linear | Linear |
MIN_MAG_POINT_MIP_LINEAR |
Point | Point | Linear |
MIN_POINT_MAG_LINEAR_MIP_POINT |
Linear | Point | Point |
MIN_POINT_MAG_MIP_LINEAR |
Linear | Point | Linear |
MIN_LINEAR_MAG_MIP_POINT |
Point | Linear | Point |
MIN_LINEAR_MAG_POINT_MIP_LINEAR |
Point | Linear | Linear |
MIN_MAG_LINEAR_MIP_POINT |
Linear | Linear | Point |
Anisotropy |
Anisotropic | Anisotropic | Anisotropic |
AddressU
, AddressV
and AddressW
Name | Description |
---|---|
Wrap , Repeat |
Wrap the UVW coordinates to be within 0..1. |
Clamp , None |
Clamp the UVW coordinates to within 0..1. |
Mirror |
Mirror the UVW coordinates when one of them goes out of the 0..1 range. |
Border |
Fill everything outside of UVW 0..1 with the BorderColor. (Not available on OpenGL) |
MirrorOnce |
Mirror the UVW coordinates once when one of them goes out of the 0..1 range. |
MinLOD
and MaxLOD
Minimum and maximum LOD available to sample operations. Must be a number in the range 0..255.
MaxAnisotropy
Maximum anisotropy to allow for sampling, as a number in the range of 1..16.
BorderColor
Border color when the AddressU/V/W mode is set to Border. Only applicable on DirectX, as the BorderColor is not set on OpenGL.
Other reserved/special meaning keywords
-
ViewProj
andWorld
- all Vertex shaders are prepended with
uniform float4x4 ViewProj;
- Seen at
libobs/graphics/effect-parse.c:ep_makeshaderstring()
- Seen at
ViewProj
andWorld
are treated as special parameters (hint stored in parser state)- Seen at
libobs/graphics/effect-parse.c:ep_compile_param()
- Seen at
- all Vertex shaders are prepended with
-
Parameters annotations
uniform type param_name<annotations...> = initializer;
- not used in Shadertastic, information stored in
meta.json
- Seen at
libobs/graphics/effect-parse.c:ep_compile_annotations()
- Seen at
- Allows hinting like this:
- not used in Shadertastic, information stored in
Various warnings we already seen at least once
Reserved double underscore in functions names
On OpenGL with linux Intel driver at least, you should not use double-underscore as part of functions names.
Various obscure errors we already seen at least once
int('-')
or int c = '-';
on GLSL on Intel driver on Debian 12
This code:
Or this code: Produces this message with a wrong line number:error: Error compiling shader:
0:87(22): error: syntax error, unexpected invalid token, expecting ')'
debug: Compiler warnings/errors for try2.hlsl (Pixel shader, technique Draw, pass 0):
0:87(22): error: syntax error, unexpected invalid token, expecting ')'
error: device_pixelshader_create (GL) failed
This variant:
Produces this message with a wrong line number: