Skip to content

Commit

Permalink
cCircles: Use per-channel dot generation
Browse files Browse the repository at this point in the history
  • Loading branch information
papadanku committed Jul 14, 2024
1 parent f774b3d commit 38d7c8c
Showing 1 changed file with 90 additions and 87 deletions.
177 changes: 90 additions & 87 deletions shaders/cCircles.fx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

#include "shared/cGraphics.fxh"
#include "shared/cMacros.fxh"
#include "shared/cColorSpaces.fxh"

sampler2D CShade_SampleColorTexMirror
{
Expand All @@ -20,20 +19,6 @@ sampler2D CShade_SampleColorTexMirror

#define MAX_CIRCLES GET_MIN(BUFFER_WIDTH, BUFFER_HEIGHT) / 10

uniform int _Select <
ui_label = "Search Feature";
ui_type = "combo";
ui_items = "HSV: Hue\0HSV: Saturation\0HSV: Value\0HSL: Hue\0HSL: Saturation\0HSL: Lightness\0HSI: Hue\0HSI: Saturation\0HSI: Intensity\0";
> = 2;

uniform float2 _Offset <
ui_category = "Circles";
ui_label = "Offset";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;

uniform int _CircleAmount <
ui_category = "Circles";
ui_label = "Number";
Expand All @@ -42,6 +27,30 @@ uniform int _CircleAmount <
ui_max = MAX_CIRCLES;
> = MAX_CIRCLES / 2;

uniform float2 _RedChannel_Offset <
ui_category = "Offset";
ui_label = "Red Channel";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;

uniform float2 _GreenChannel_Offset <
ui_category = "Offset";
ui_label = "Green Channel";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;

uniform float2 _BlueChannel_Offset <
ui_category = "Offset";
ui_label = "Blue Channel";
ui_type = "slider";
ui_min = -1.0;
ui_max = 1.0;
> = 0.0;

uniform float3 _FrontColor <
ui_category = "Output";
ui_label = "Foreground Color";
Expand All @@ -58,105 +67,99 @@ uniform float3 _BackColor <
ui_max = 1.0;
> = float3(0.0, 0.0, 0.0);

uniform int4 _Crop <
ui_category = "Output";
ui_label = "Crop (Left, Right, Top, Bottom)";
ui_type = "slider";
ui_min = 0;
ui_max = 10;
> = 0;

/*
[Pixel Shaders]
[Textures and Samplers]
*/

CREATE_TEXTURE_POOLED(TempTex0_RGB10A2, BUFFER_SIZE_0, RGB10A2, 8)
CREATE_SAMPLER(SampleTempTex0, TempTex0_RGB10A2, LINEAR, MIRROR)

float4 PS_Blit(VS2PS_Quad Input) : SV_TARGET0
/*
[Pixel Shaders]
*/

struct Tile
{
return float4(tex2D(CShade_SampleGammaTex, Input.Tex0).rgb, 1.0);
}
float2 Value;
float2 Index;
float2 Frac;
};

float4 PS_Circles(VS2PS_Quad Input) : SV_TARGET0
Tile GetTiles(float2 Tex, float2 Translation)
{
// Optional offset
Input.Tex0.xy += _Offset;
Tile Output;

// Shrink the UV so [-1, 1] fills a square
float2 Tiles = (Input.Tex0.xy * _CircleAmount);
float2 Tiles = Tex + Translation;

// Get tiles
Output.Value = Tiles * _CircleAmount;

// Shift the tiles so they are ~0.5 units apart from each-other
Tiles.x = (GetMod(trunc(Tiles.y), 2.0) == 1.0) ? Tiles.x + 0.25: Tiles.x - 0.25;
Output.Value.x = (GetMod(trunc(Output.Value.y), 2.0) == 1.0) ? Output.Value.x + 0.25: Output.Value.x - 0.25;

// Create pixelated texcoords
float2 Tex = floor(Tiles) / _CircleAmount;
// Get tile index
Output.Index = floor(Output.Value);

// Get pixelated color information
float2 TexSize = GetScreenSizeFromTex(Input.Tex0);
float LOD = max(0.0, log2(max(TexSize.x, TexSize.y) / _CircleAmount));
// Get fractional variant of file
Output.Frac = frac(Output.Value);

// Get texture information
float4 Color = tex2Dlod(SampleTempTex0, float4(Tex, 0.0, LOD));
float Feature = 0.0;
return Output;
}

switch(_Select)
{
case 0:
Feature = GetHSVfromRGB(Color.rgb).r;
break;
case 1:
Feature = GetHSVfromRGB(Color.rgb).g;
break;
case 2:
Feature = GetHSVfromRGB(Color.rgb).b;
break;
case 3:
Feature = GetHSLfromRGB(Color.rgb).r;
break;
case 4:
Feature = GetHSLfromRGB(Color.rgb).g;
break;
case 5:
Feature = GetHSLfromRGB(Color.rgb).b;
break;
case 6:
Feature = GetHSIfromRGB(Color.rgb).r;
break;
case 7:
Feature = GetHSIfromRGB(Color.rgb).g;
break;
case 8:
Feature = GetHSIfromRGB(Color.rgb).b;
break;
default:
Feature = 0.0;
break;
}
float4 PS_Blit(VS2PS_Quad Input) : SV_TARGET0
{
return tex2D(CShade_SampleGammaTex, Input.Tex0);
}

float2 GetBlockTex(float2 TileIndex)
{
return TileIndex / _CircleAmount;
}

float GetTileCircleLength(Tile Input)
{
// Create the UV for the circles
float2 CircleTiles = frac(Tiles) * 2.0 - 1.0;
float2 CircleTiles = (Input.Frac * 2.0) - 1.0;
// Shrink the UV so [-1, 1] fills a square
#if BUFFER_WIDTH > BUFFER_HEIGHT
CircleTiles.x *= ASPECT_RATIO;
#else
CircleTiles.y *= ASPECT_RATIO;
#endif
float CircleDist = length(CircleTiles);

// Create the circle
float FeatureFactor = lerp(0.5, 1.0, Feature);
float Circles = smoothstep(0.8 * (1.0 - FeatureFactor), 0.5, CircleDist * FeatureFactor);
return length(CircleTiles);
}

// Mix colors together
float3 OutputColor = lerp(_FrontColor, _BackColor, Circles);
OutputColor = lerp(OutputColor, _BackColor, saturate(Feature));
float4 PS_Circles(VS2PS_Quad Input) : SV_TARGET0
{
// Precalculate our needed LOD for all channels
float2 TexSize = GetScreenSizeFromTex(Input.Tex0);
float LOD = max(0.0, log2(max(TexSize.x, TexSize.y) / _CircleAmount));

// Create per-channel tiles
Tile RedChannel_Tiles = GetTiles(Input.Tex0.xy, _RedChannel_Offset);
Tile GreenChannel_Tiles = GetTiles(Input.Tex0.xy, _GreenChannel_Offset);
Tile BlueChannel_Tiles = GetTiles(Input.Tex0.xy, _BlueChannel_Offset);

// Generate per-channel blocks
float4 Blocks = 0.0;
Blocks.r = tex2Dlod(SampleTempTex0, float4(GetBlockTex(RedChannel_Tiles.Index), 0.0, LOD)).r;
Blocks.g = tex2Dlod(SampleTempTex0, float4(GetBlockTex(GreenChannel_Tiles.Index), 0.0, LOD)).g;
Blocks.b = tex2Dlod(SampleTempTex0, float4(GetBlockTex(BlueChannel_Tiles.Index), 0.0, LOD)).b;

// Crop the image
OutputColor = lerp(_BackColor, OutputColor, Tiles.x > _Crop.x);
OutputColor = lerp(_BackColor, OutputColor, Tiles.x < (_CircleAmount - _Crop.y));
OutputColor = lerp(_BackColor, OutputColor, Tiles.y > _Crop.z * 2.0);
OutputColor = lerp(_BackColor, OutputColor, Tiles.y < (_CircleAmount - _Crop.w * 2.0));
// Generate per-channel, circle-shaped lengths of each channel blocks' texture coordinates
float3 CircleDist = 0.0;
CircleDist.r = GetTileCircleLength(RedChannel_Tiles);
CircleDist.g = GetTileCircleLength(GreenChannel_Tiles);
CircleDist.b = GetTileCircleLength(BlueChannel_Tiles);

// Generate the per-color circle
float3 FeatureFactor = lerp(0.5, 1.0, Blocks.rgb);
float3 Circles = smoothstep(0.8 * (1.0 - FeatureFactor), 0.5, CircleDist * FeatureFactor);

// Process OutputColor
float3 OutputColor = lerp(_FrontColor, _BackColor, Circles);
OutputColor = lerp(OutputColor, _BackColor, saturate(Blocks.rgb));

return float4(OutputColor.rgb, 1.0);
}
Expand Down

0 comments on commit 38d7c8c

Please sign in to comment.