04 챕터 Draw Circle을 구현해봤습니다.
- https://graphicsimon.tistory.com/11?category=1119246
조금더 응용버전으로 작성해 보겠습니다.
먼저 frag 함수에서 position * 2를 해서 -1 ~ 1 좌표계 범위로 만들어 보겠습니다.
다시 말씀드리면 -0.5 ~ 0.5 좌표계에서 2를 곱한 것 입니다.
radius는 0.5로 주어졌다고 가정합니다.
1) 기본 원 렌더링
lenght 함수는 벡터의 크기(길이)를 구합니다.
pt - center를 해서 벡터를 구한 뒤, 길이를 구하면
l각 픽셀과 center과의 거리 (len)가 나옵니다.
len 값과 주어진 raidus과 비교하여, len이 거리가 작으면 0을 리턴하게 됩니다.
1을 빼주게 되니, 원 내부픽셀들은 전부 1의 값을 가지게 됩니다.
float circle(float2 pt, float2 center, float radius)
{
float len = length(pt - center);
return 1.0 - step(radius, len);
}
2) 경계가 스무스한 원 렌더링
smoothstep(a, b, x) 리턴 값은 다음과 같습니다.
a < x 경우 return 0
x > b 경우 return 1
a < x < b 경우 return 0 ~ 1
smoothstep 결과 값은
radius - edge의 distance보다 작은 픽셀의 거리의 경우 0 (초록색)
radius + edge의 distance보다 큰 픽셀의 거리의 경우 1 (원 밖 흰색)
radius - edge < len < radius + edge 경우는 0 ~ 1 리턴하게 됩니다.
그래서 1을 빼게 되면 원의 내부는 1이 되고,
edge * 2 영역 만큼은 보간이 되어 흐려지게 보이게 됩니다.
float circle(float2 pt, float2 center, float radius, bool soften)
{
float len = length(pt - center);
float edge = (soften) ? radius * 0.05 : 0.0;
return 1.0 - smoothstep(radius - edge, radius + edge, len);
}
3) 겹선형 원 렌더링
이번에는 아래 그림처럼 겹선형 원을 렌더링 해봅시다.
생각을 해보면 큰 원에서 작은 원을 빼면 될 것 같습니다.
2번에서 smoothstep 적용한 비슷한 원리 입니다.
안쪽 파랑색 원 밖의 부분은 전부 1, 내부는 1
연한색 파랑색 원 밖의 부분은 전부 1, 내부는 1
안쪽 파랑색 영역 - 연한색 파랑색 영역을 하게되면,
- 배경 흰색 부분은 둘다 1이기 때문에 0 됩니다.
- 연한색 부분만 1 - 0 = 1로 1이 됩니다.
float circle(float2 pt, float2 center, float radius, float line_width)
{
float len = length(pt - center);
return step(radius - line_width / 2, len) - step(radius + line_width / 2, len);
}
Shader "SimonLee/Shader14Unlit"
{
Properties
{
_Color("Color", Color) = (1.0,1.0,0,1.0)
_Radius("Radius", Float) = 0.3
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
float4 position : TEXCOORD1;
float2 uv: TEXCOORD0;
};
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.position = v.vertex;
o.uv = v.texcoord;
return o;
}
fixed4 _Color;
float _Radius;
float circle(float2 pt, float2 center, float radius)
{
float len = length(pt - center);
return 1.0 - step(radius, len);
}
float circle(float2 pt, float2 center, float radius, bool soften)
{
float len = length(pt - center);
float edge = (soften) ? radius * 0.05 : 0.0;
return 1.0 - smoothstep(radius - edge, radius + edge, len);
}
float circle(float2 pt, float2 center, float radius, float line_width)
{
float len = length(pt - center);
return step(radius - line_width / 2, len) - step(radius + line_width / 2, len);
}
fixed4 frag (v2f i) : SV_Target
{
float2 pos = i.position * 2;
float2 center = (0, 0);
//fixed3 color = _Color * circle(pos, center, _Radius);
//fixed3 color = _Color * circle(pos, center, _Radius, true);
fixed3 color = _Color * circle(pos, center, _Radius, 0.05);
return fixed4(color, 1.0);
}
ENDCG
}
}
}
'Shader CG' 카테고리의 다른 글
2.1 Noise TV 화면 만들어보기 (0) | 2023.08.06 |
---|---|
1.6 도형 - 라인 그려보기 (0) | 2023.07.20 |
1.4 도형 - 타일링 (0) | 2023.07.13 |
1.3 도형 - Rotation & Scailing Rect (0) | 2023.07.11 |
1.2 도형 - Draw Rectangle - 2 (0) | 2023.07.09 |