Skip to content

Instantly share code, notes, and snippets.

@polerin
Created May 13, 2022 22:55
Show Gist options
  • Save polerin/be9a5fbaff9f0f086b1b2c3377394761 to your computer and use it in GitHub Desktop.
Save polerin/be9a5fbaff9f0f086b1b2c3377394761 to your computer and use it in GitHub Desktop.
Simple overlay/camera blend shader for OBS
// yeaaaah
#include "includes/streamfx.effect"
uniform float minPass<
string name = "Minimum alpha to let through";
string field_type = "slider";
float minimum = 0.0;
float maximum = 1.0;
float step = 0.001;
> = 0.01;
uniform bool renderOver<
string name = "Render Over Camera";
> = false;
uniform texture2d cameraInput<
string name = "Camera input";
>;
uniform bool displayDebugBounds<
string name = "Display Debug bounds";
> = false;
uniform float cameraScale<
string name = "Camera scale";
string field_type = "slider";
float minimum = 0.1;
float maximum = 1.0;
float step = 0.001;
> = 0.2;
uniform float cameraOffsetX<
string name = "Camera Offset X";
string field_type = "slider";
float minimum = -1;
float maximum = 1;
float step = 0.001;
> = 0;
uniform float cameraOffsetY<
string name = "Camera Offset Y";
string field_type = "slider";
float minimum = -1;
float maximum = 1;
float step = 0.001;
> = 0;
uniform float cameraSizeX<
string name = "Camera Size X";
string field_type = "slider";
float minimum = .1;
float maximum = 1;
float step = 0.001;
> = 0.4;
uniform float cameraSizeY<
string name = "Camera Size Y";
string field_type = "slider";
float minimum = .1;
float maximum = 1;
float step = 0.001;
> = 0.4;
uniform float cameraPosX<
string name = "Camera Position X";
string field_type = "slider";
float minimum = 0;
float maximum = .9;
float step = 0.001;
> = 0.0;
uniform float cameraPosY<
string name = "Camera Position Y";
string field_type = "slider";
float minimum = 0;
float maximum = .9;
float step = 0.001;
> = 0;
sampler_state pixelSamplerMain {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
sampler_state texturePixelSampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
sampler_state pixelSamplerSecondary {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
// returns true if the supplied uv is within the supplied bounds
bool uvInCameraBounds(float2 uv, float4 cameraBounds) {
return (uv.x > cameraBounds.x && uv.x < cameraBounds.z
&& uv.y > cameraBounds.y && uv.y < cameraBounds.w
);
}
// returns the camera pixel that corresponds to the supplied uv
// after scaling and translating the coordinate
float4 getCameraPixel(float2 incomingUv)
{
// ensure we are on the lower right side of the camera bounds
float2 cameraOffset = float2(
cameraPosX + cameraOffsetX,
cameraPosY + cameraOffsetY);
if (cameraSizeX > cameraScale) {
cameraOffset.x += cameraSizeX - cameraScale;
}
if (cameraSizeY > cameraScale) {
cameraOffset.y += cameraSizeY - cameraScale;
}
float2 targetUv = float2(
(incomingUv.x - cameraOffset.x) / cameraScale,
(incomingUv.y - cameraOffset.y) / cameraScale
);
if (targetUv.x < -1 || targetUv.x > 1 || targetUv.y < 0 || targetUv.y > 1) {
return float4(0,0,0,0);
}
return cameraInput.Sample(pixelSamplerSecondary, targetUv);
}
float4 blendPixels(float4 top, float4 bottom)
{
float aDiff = (1 - top.a) * bottom.a;
return clamp(float4(
top.r * top.a + bottom.r * aDiff,
top.g * top.a + bottom.g * aDiff,
top.b * top.a + bottom.b * aDiff,
top.a + aDiff
), 0, 1);
}
// Main pixel logic
float4 PSOverlay(VertData v_in) : TARGET {
float4 currentPixel = InputA.Sample(pixelSamplerMain, v_in.uv);
float4 cameraBounds = float4(
cameraPosX, //xMin
cameraPosY, //yMin
clamp(cameraPosX + cameraSizeX, 0, 1), // x Max
clamp(cameraPosY + cameraSizeY, 0, 1) // y Max
);
bool inBounds = uvInCameraBounds(v_in.uv, cameraBounds);
// check if we are in the camera bounding window
if (!inBounds) {
return currentPixel;
}
float4 cameraPixel = getCameraPixel(v_in.uv);
if (cameraPixel.a > minPass) {
return blendPixels(cameraPixel, currentPixel);
}
// DEBUG
if (displayDebugBounds) {
return float4(.3, .3, .3, .5);
}
// DEBUG
return currentPixel;
}
technique Draw
{
pass
{
vertex_shader = VSDefault(v_in);
pixel_shader = PSOverlay(v_in);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment