Created
May 13, 2022 22:55
-
-
Save polerin/be9a5fbaff9f0f086b1b2c3377394761 to your computer and use it in GitHub Desktop.
Simple overlay/camera blend shader for OBS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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