๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
HLSL

์ปค์Šคํ…€ ๋…ธ๋“œ๋กœ ํ”ฝ์…€ ์ดํŽ™ํŠธ (๋…ธ์ด์ฆˆ ํŒจํ„ด) ๋งŒ๋“ค๊ธฐ

by z03y 2024. 12. 12.

 


 

 

๐ŸŒŒ ํ…์Šค์ฒ˜ ์ขŒํ‘œ (uv) ์ผ์ •ํ•œ ๊ฐ„๊ฒฉ์˜ Grid๋กœ ๋ณ€ํ™˜

๋…ธ๋“œ๋ฅผ ํ†ตํ•œ ๊ตฌํ˜„๊ณผ ์ฝ”๋“œ๋ฅผ ํ†ตํ•œ ๊ตฌํ˜„ ๋น„๊ต

Multiply + floor ๋…ธ๋“œ ์‚ฌ์šฉ
Custom node ์‚ฌ์šฉ

//HLSL

float2 uvGrid = floor(uv * 5.0);
return uvGrid;

 

floor ํ•จ์ˆ˜๋Š” ์†Œ์ˆ˜์ ์„ ๋ฒ„๋ฆฌ๊ณ  ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํ•˜ํ•œ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. uv๊ฐ€ (1.3, 2.7)์ด๋ผ๋ฉด floor(1.3)์€ 1์ด ๋˜๊ณ , floor(2.7)์€ 2๊ฐ€ ๋œ๋‹ค.

 

//HLSL

int gridArray[5][5] = {{ 0, 0, 0, 0, 0},
                       { 0, 1, 0, 1, 0},
                       { 0, 0, 0, 0, 0},
                       { 0, 1, 1, 1, 0},
                       { 0, 0, 0, 0, 0},};

float2 uvGrid = floor(uv *5.0);

return (gridArray[int(uvGrid.y)]
                 [int(uvGrid.x)]);

gridArray 5x5ํฌ๊ธฐ์˜ 2D ์ •์ˆ˜ ๋ฐฐ์—ด์ด๋‹ค. ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋Š” 0 ๋˜๋Š” 1๋กœ ์ดˆ๊ธฐํ™” ๋˜์–ด์žˆ๋‹ค. floor(uv*5.0) ์ขŒํ‘œ์— ๋”ฐ๋ผ ๊ฐ ์…€์˜ ๊ฐ’์„ ๊ฐ€์ ธ์™€ 1์ขŒํ‘œ ๊ฐ’์— ๋Œ€ํ•ด ํ™”์ดํŠธ(1), ๋ธ”๋ž™(0)๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

 

๐ŸŒŒ Pixel effect w.Texture

//HLSL

float2 gridSize = float2(24,24);

float2 uvGrid = floor(uv * gridSize) / gridSize;

float3 result = Texture2DSample(tex, texSampler, uvGrid);

//grayscale ๋ณ€ํ™˜ ๋ฐ ๋ฐ˜ํ™˜
return float(dot(result, float3(.299, .587, .114)));

gridArray ๋Œ€์‹  float2 ํ˜•ํƒœ์˜ gridSize๋กœ ๋ฐ”๊ฟจ๋‹ค. return์˜ ๊ฒฝ์šฐ ๊ฒฐ๊ณผ๋ฌผ์ด grayscale์ด๊ธฐ ๋•Œ๋ฌธ์— r,g,b๊ฐ€ ํšŒ์ƒ‰์œผ๋กœ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์„ ๊ณฑํ•œ๋‹ค. ๋‹ค๋ฅธ ๊ฐ’์„ ๊ณฑํ•˜๋Š” ์ด์œ ๋Š” r,g,b ์ปฌ๋Ÿฌ๋งˆ๋‹ค ๋ฐ๊ธฐ์— ๋Œ€ํ•œ ๋ฏผ๊ฐ๋„๊ฐ€ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ์ˆ˜์น˜ํ™” ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ.

  • uv๋Š” ํ…์Šค์ฒ˜ ์ขŒํ‘œ๋กœ, ์ผ๋ฐ˜์ ์œผ๋กœ (0.0, 0.0)์—์„œ (1.0, 1.0) ๋ฒ”์œ„ ๋‚ด์˜ ๊ฐ’์„ ๊ฐ€์ง„๋‹ค.
  • uv * gridSize๋Š” ํ…์Šค์ฒ˜ ์ขŒํ‘œ๋ฅผ ๊ทธ๋ฆฌ๋“œ ํฌ๊ธฐ๋งŒํผ ํ™•๋Œ€ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, uv๊ฐ€ (0.5, 0.5)๋ผ๋ฉด uv * gridSize๋Š” (12, 12)๊ฐ€ ๋œ๋‹ค.
  • floor(uv * gridSize)๋Š” ํ™•๋Œ€๋œ ์ขŒํ‘œ๋ฅผ ํ•˜ํ•œ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๊ทธ๋ฆฌ๋“œ ์…€์˜ ์ขŒํ‘œ๋ฅผ ๋งŒ๋“ ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, (12.7, 13.3)์€ (12, 13)์ด ๋œ๋‹ค.
  • ๋งˆ์ง€๋ง‰์œผ๋กœ / gridSize๋ฅผ ํ†ตํ•ด ๋‹ค์‹œ 0.0์—์„œ 1.0 ์‚ฌ์ด์˜ ํ…์Šค์ฒ˜ ์ขŒํ‘œ๋กœ ์ •๊ทœํ™”ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, (12, 13)์€ (12/24, 13/24) = (0.5, 0.5417)์ด ๋œ๋‹ค.
  • dot(result, float3(.299, .587, .114)) ํ”ฝ์…€์˜ ์‹ค์ œ ์‹œ๊ฐ์  ๋ฐ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ฆ‰ ํ‘๋ฐฑํ™”ํ•˜๋Š” ๊ฒƒ.

 

 

๐ŸŒŒ ๊ฐ ํ”ฝ์…€ ์ฃผ์œ„์— ์—ฃ์ง€ ๋„ฃ๊ธฐ (borderThickness)

ํ…์Šค์ฒ˜ ์ขŒํ‘œ๋ฅผ ์ผ์ •ํ•œ ๊ทธ๋ฆฌ๋“œ ํฌ๊ธฐ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๊ทธ๋ฆฌ๋“œ ๊ฒฝ๊ณ„ ์˜์—ญ์„ ๊ฐ•์กฐํ•œ๋‹ค. ๊ฐ ๊ทธ๋ฆฌ๋“œ ๋ธ”๋Ÿญ์€ ์—ฃ์ง€ ๋‚ด์— ์žˆ๋Š” ํ”ฝ์…€์€ ์œ ์ง€ํ•˜๊ณ  ์—ฃ์ง€ ์™ธ๋ถ€์— ์žˆ๋Š” ํ”ฝ์…€์€ ์ œ๊ฑฐํ•œ๋‹ค.

//HLSL

float2 uvGrid = floor(uv * gridSize) / gridSize;
float2 gridBlock = 1 / gridSize;

//๊ทธ๋ฆฌ๋“œ ๋ธ”๋ก์˜ ํ…Œ๋‘๋ฆฌ ๋‘๊ป˜ ์„ค์ •
float borderThickness = 0.25;

//๊ทธ๋ฆฌ๋“œ ์—ฃ์ง€ ๊ณ„์‚ฐ
float2 blockBorder = step(0.5 - borderThickness, frac(uv / gridBlock)) *
                    step(frac(uv / gridBlock), 0.5 + borderThickness);

//uvGrid ์ขŒํ‘œ์—์„œ ํ…์Šค์ฒ˜ ์ƒ‰์ƒ ๊ฐ’์„ ์ƒ˜ํ”Œ๋งํ•œ๋‹ค                   
float3 result = Texture2DSample(tex, texSampler, uvGrid);

//๋ธ”๋ก์˜ ์—ฃ์ง€ ๋ถ€๋ถ„์—์„œ๋งŒ ํ…์Šค์ฒ˜ ์ƒ‰์ƒ์ด ๋‚˜ํƒ€๋‚˜๋„๋ก ํ•จ
//์—ฃ์ง€ ๋ฐ– ์˜์—ญ์€ ๊ฒ€์€์ƒ‰(0)
result *= float(blockBorder.x * blockBorder.y);

return float(dot(result, float3(.299, .587, .114)));

gridSize๋Š” float2 ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๋Š” ์ƒ๋žตํ–ˆ๋‹ค. ์ƒˆ ๋ณ€์ˆ˜ gridBlock์€ gridSize๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ๋ธ”๋ก์€ ํ…์Šค์ฒ˜์˜ 1/24 ํฌ๊ธฐ์ด๋‹ค.

  • frac ํ•จ์ˆ˜๋Š” ์†Œ์ˆ˜ ๋ถ€๋ถ„์„ ์ทจํ•˜์—ฌ [0.0, 1.0]๋ฒ”์œ„๋กœ ๋งŒ๋“ ๋‹ค.
  • step ํ•จ์ˆ˜๋Š” ๋‘ ๊ฐœ ๊ฐ’์„ ๋น„๊ตํ•˜์—ฌ Edge๋ฅผ ํ˜•์„ฑํ•œ๋‹ค. step(edge, x)๋Š” x๊ฐ€ edge๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์œผ๋ฉด 1.0, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด 0.0์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ๋‘ step ํ•จ์ˆ˜์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ณฑํ•˜์—ฌ Edge ์˜์—ญ์„ ์ •์˜ํ•œ๋‹ค. Edge ์˜์—ญ์€ ๊ทธ๋ฆฌ๋“œ ๋ธ”๋ก์˜ ์ค‘์‹ฌ์„ ๊ธฐ์ค€์œผ๋กœ 0.5 - borderThickness์—์„œ 0.5 + borderThickness ์‚ฌ์ด์— ์œ„์น˜ํ•œ๋‹ค.

 

//HLSL

//๋…ธ์ด์ฆˆ ์ƒ์„ฑ
struct pixelPlot
{
   float noise(float2 uvCoord)
   {
     return frac(sin(dot(uvCoord, float2(12.34, 56.78))) * 91011.1213);
   }
};

//pixelPlot ๊ตฌ์กฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
pixelPlot plot;

float2 uvGrid = floor(uv * gridSize) / gridSize;
float2 gridBlock = 1 / gridSize;

float borderThickness = 0.25;

float2 blockBorder = step(0.5 - borderThickness, frac(uv / gridBlock)) *
                     step(frac(uv / gridBlock), 0.5 + borderThickness);

float3 result = Texture2DSample(tex, texSampler, uvGrid);

result *= float(blockBorder.x * blockBorder.y);

//ํ˜„์žฌ ํ”ฝ์…€์˜ ๋ฐ๊ธฐ๊ฐ€ 0๋ณด๋‹ค ํฌ๋‹ค๋ฉด, ์ฆ‰ ๊ฒ€์ •์ด ์•„๋‹ˆ๋ผ๋ฉด ๋…ธ์ด์ฆˆ๋ฅผ ์ถ”๊ฐ€
if (dot(result, float3(.299, .587, .114)) > 0.0)
{
    //๊ฐ ๋…ธ์ด์ฆˆ ๊ฐ’์€ ์ž„์˜์˜ ์˜คํ”„์…‹์„ ๋”ํ•ด ์ฐจ์ด๋ฅผ ์คŒ
    result = float3(plot.noise(uvGrid +frac(1.23)),
                    plot.noise(uvGrid +frac(4.56)),
                    plot.noise(uvGrid +frac(7.89)));
}

return result;

๊ตฌ์กฐ์ฒด struct pixelPlot์€ 2D์ขŒํ‘œ(uvCoord)๋ฅผ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์•„ ๋‚œ์ˆ˜ ๋…ธ์ด์ฆˆ ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค. dot์€ ๋‘ ๋ฒกํ„ฐ์˜ ๋ฐฉํ–ฅ๊ณผ ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ๋‹จ์ผ ์Šค์นผ๋ผ ๊ฐ’์„ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ sin ํ•จ์ˆ˜์— ์ ์šฉํ•œ ํ›„ ํฐ ์ˆซ์ž๋ฅผ ๊ณฑํ•ด ์ดํ›„ ์—ฐ์‚ฐ์—์„œ ๋…ธ์ด์ฆˆ๋ฅผ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ฆ๊ณ  frac์œผ๋กœ ์ž…๋ ฅ ๊ฐ’์„ 0๊ณผ 1 ์‚ฌ์ด๋กœ ์ œํ•œํ•œ๋‹ค.

  • dot(result, float3(.299, .587, .114)): ํ”ฝ์…€์˜ ๋ฐ๊ธฐ๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค. ์ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ๊ธฐ๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ฐ€์ค‘์น˜์ด๋‹ค.

 

 

๐ŸŒŒ Time ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฌด์ž‘์œ„ ํ”ฝ์…€ ์ปฌ๋Ÿฌ ๋ณ€ํ•˜๊ธฐ

result = float3(plot.noise(uvGrid +frac(time/1.23)),
plot.noise(uvGrid +frac(time/4.56)),
plot.noise(uvGrid +frac(time/7.89)));

time์„ ๋„ฃ์–ด์„œ ๋ฌด์ž‘์œ„๋กœ ํ”ฝ์…€ ์ปฌ๋Ÿฌ๊ฐ€ ๋ณ€ํ•˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

 

๐ŸŒŒ Ref.

https://www.youtube.com/watch?v=0fnHLMp0m7k

 

๋ฐ˜์‘ํ˜•

'HLSL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

HLSL ๋ฐ์ดํ„ฐ ํƒ€์ž… Struct  (0) 2024.12.12
๋ฃจํ”„ ํŒจํ„ด ๋งŒ๋“ค๊ธฐ  (0) 2024.10.29
์› ๊ทธ๋ฆฌ๊ธฐ + ํƒ€์ผ๋ง  (0) 2024.10.28