Skip to content

Commit

Permalink
Adds pixelate blur for square, hexagon, and circle 'pixels' (#7)
Browse files Browse the repository at this point in the history
* Adds pixelate blur for square, hexagon, and circle 'pixels'
* Fixes shaders crashing on MacOS, adds Triangle pixelization.
* Fixes non-working tilt-shift box blur on OpenGL/MacOS
* Closes #1
  • Loading branch information
FiniteSingularity committed Aug 23, 2023
1 parent e83cad7 commit dd6b7b8
Show file tree
Hide file tree
Showing 14 changed files with 514 additions and 9 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ else()
cmake_minimum_required(VERSION 3.18)
endif()

project(obs-composite-blur VERSION 0.0.1)
project(obs-composite-blur VERSION 0.0.3)
set(PROJECT_FULL_NAME "OBS Composite Blur")

# Set new UUIDs when you start to create a new plugin.
Expand All @@ -29,6 +29,8 @@ target_sources(${PROJECT_NAME} PRIVATE
src/blur/gaussian.h
src/blur/box.c
src/blur/box.h
src/blur/pixelate.c
src/blur/pixelate.h
src/version.h)

if(BUILD_OUT_OF_TREE)
Expand Down
2 changes: 1 addition & 1 deletion buildspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,5 @@
}
},
"name": "obs-composite-blur",
"version": "0.0.1"
"version": "0.0.3"
}
9 changes: 8 additions & 1 deletion data/locale/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ CompositeBlurFilter.TiltShift.Angle="Angle"
CompositeBlurFilter.Algorithm.Gaussian="Gaussian"
CompositeBlurFilter.Algorithm.Box="Box"
CompositeBlurFilter.Algorithm.Kawase="Kawase"
CompositeBlurFilter.Algorithm.Pixelate="Pixelate"
CompositeBlurFilter.Type.Area="Area"
CompositeBlurFilter.Type.Directional="Directional"
CompositeBlurFilter.Type.Zoom="Zoom"
CompositeBlurFilter.Type.Motion="Motion"
CompositeBlurFilter.Type.TiltShift="Tilt-Shift"
CompositeBlurFilter.Type.TiltShift="Tilt-Shift"
CompositeBlurFilter.PixelateType="Pixelate Type"
CompositeBlurFilter.Pixelate.Square="Square"
CompositeBlurFilter.Pixelate.Hexagonal="Hexagonal"
CompositeBlurFilter.Pixelate.Triakis="Triakis"
CompositeBlurFilter.Pixelate.Circle="Circle"
CompositeBlurFilter.Pixelate.Triangle="Triangle"
12 changes: 10 additions & 2 deletions data/shaders/box_tiltshift.effect
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,16 @@ VertData mainTransform(VertData v_in)
float4 mainImage(VertData v_in) : TARGET
{
// Rotate about angle:
float2x2 rot = float2x2(cos(focus_angle), sin(focus_angle), -sin(focus_angle), cos(focus_angle));
float2 uv_prime = mul(rot, v_in.uv*uv_size - 0.5*uv_size) / uv_size.y + 0.5f - focus_center;
// a matrix multiplication is more readable, but does not work on OpenGL
// for some reason.
//float2x2 rot = float2x2(cos(focus_angle), sin(focus_angle), -sin(focus_angle), cos(focus_angle));
//float2 uv_prime = mul(rot, v_in.uv*uv_size - 0.5*uv_size) / uv_size.y + 0.5f - focus_center;
float2 coord_norm = v_in.uv*uv_size - 0.5*uv_size;
float2 uv_prime = float2(
coord_norm.x * cos(focus_angle) + coord_norm.y * sin(focus_angle),
-coord_norm.x * sin(focus_angle) + coord_norm.y * cos(focus_angle)
)/uv_size.y + 0.5f - focus_center;


float dist = abs(uv_prime.y);

Expand Down
43 changes: 43 additions & 0 deletions data/shaders/pixelate_circle.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size;

uniform float pixel_size;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
// 1. Sample incoming pixel
float2 coord = v_in.uv * uv_size;
float2 coord_prime = (coord - fmod(coord, pixel_size)) + pixel_size/2.0f;
float2 uv_prime = coord_prime / uv_size;

return distance(coord, coord_prime) <= pixel_size/2.0f ? image.Sample(textureSampler, uv_prime) : float4(0.0, 0.0, 0.0, 0.0);
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
102 changes: 102 additions & 0 deletions data/shaders/pixelate_hexagonal.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#define R 2.0f
#define S 2.3094011f
#define T 1.1547005f
#define POINTY 0
#define FLAT 1

uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size;

uniform float pixel_size;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};


// Converts cartesian coordinates to hexagonal
// index coordinates.
float2 cartToHex(float2 coord){
// float2x2 Xm = { 1./(2.*R), -1./S,
// 1./R, 0. };
// float2x2 Ym = { 1./(2.*R), 1./S,
// -1./(2.*R), 1./S };
// float2 Mi = floor(mul(Xm, coord));
// float2 Mj = floor(mul(Ym, coord));
float2 Mi = floor(float2(1.0f/(2.0f*R) * coord.x - 1.0/S * coord.y, 1.0f/R * coord.x));
float2 Mj = floor(float2(1.0f/(2.0f*R) * coord.x + 1.0/S * coord.y, -1.0f/(2.0f*R)*coord.x + 1.0f/S * coord.y));
return float2(
floor((Mi.x + Mi.y + 2.0f)/3.0f),
floor((Mj.x + Mj.y + 2.0f)/3.0f)
);
}

// Converts hexagonal index coordinates to
// cartesian coordinates.
float2 hexToCart(float2 hex_coord) {
return float2(
hex_coord.x*(2.0f*R) + hex_coord.y*R,
hex_coord.y*(S+T)
);
}

// Returns the cartesian coordinate of the center
// of the hexagon containing the coordinate coord
// given a regular hexagon grid size, real_r
float2 coordToHexCenter(float2 coord, float real_r) {
float scale = real_r/R;
float2 hex_coord = cartToHex(coord/scale);
return hexToCart(hex_coord) * scale;
}

float2 reverseCoords(float2 coord) {
return float2(coord.y, coord.x);
}

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
int orientation = POINTY;
// // 1. Sample incoming pixel
float2 coord = v_in.uv * uv_size;
// float2 uv_prime = (coord - fmod(coord, pixel_size)) / uv_size;

float2 local_coord = coord;
if(orientation == FLAT) {
local_coord = reverseCoords(coord);
}

float2 local_nearest = coordToHexCenter(local_coord, pixel_size);
float2 frame_nearest = local_nearest;
if(orientation == FLAT) {
frame_nearest = reverseCoords(local_nearest);
}

float2 uv_prime = (local_nearest) / uv_size;

return image.Sample(textureSampler, uv_prime);
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
41 changes: 41 additions & 0 deletions data/shaders/pixelate_square.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size;

uniform float pixel_size;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
// 1. Sample incoming pixel
float2 coord = v_in.uv * uv_size;
float2 uv_prime = (coord - fmod(coord, pixel_size) + pixel_size/2.0f) / uv_size;
return image.Sample(textureSampler, uv_prime);
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
59 changes: 59 additions & 0 deletions data/shaders/pixelate_triangle.effect
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#define SQRT3 1.732050807568877

uniform float4x4 ViewProj;
uniform texture2d image;
uniform float2 uv_size;

uniform float pixel_size;

sampler_state textureSampler{
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
MinLOD = 0;
MaxLOD = 0;
};

struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};

float3 getTriangle(float2 coord) {
return float3(
ceil(( 1.0f * coord.x - SQRT3 / 3.0f * coord.y) / pixel_size),
floor((SQRT3 * 2.0f / 3.0f * coord.y) / pixel_size) + 1.0f,
ceil((-coord.x - SQRT3 / 3.0f * coord.y) / pixel_size)
);
}

float2 triangleCenter(float3 triCoord) {
return float2(
(0.5f * triCoord.x -0.5f * triCoord.z) * pixel_size,
(-SQRT3 / 6.0f * triCoord.x + SQRT3 / 3.0f * triCoord.y - SQRT3 / 6.0f * triCoord.z) * pixel_size
);
}

VertData mainTransform(VertData v_in)
{
v_in.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
return v_in;
}

float4 mainImage(VertData v_in) : TARGET
{
// 1. Sample incoming pixel
float2 coord = v_in.uv * uv_size;
float2 sample_coord = triangleCenter(getTriangle(coord));
float2 uv_prime = sample_coord/uv_size;
return image.Sample(textureSampler, uv_prime);
}

technique Draw
{
pass
{
vertex_shader = mainTransform(v_in);
pixel_shader = mainImage(v_in);
}
}
4 changes: 2 additions & 2 deletions src/blur/box.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ static void box_area_blur(composite_blur_filter_data_t *data)
}

texture = blend_composite(texture, data);

for (int i = 0; i < data->passes; i++) {
const int passes = data->passes < 1 ? 1 : data->passes;
for (int i = 0; i < passes; i++) {
data->render2 = create_or_reset_texrender(data->render2);

gs_eparam_t *image =
Expand Down
Loading

0 comments on commit dd6b7b8

Please sign in to comment.