- 외곽선 찾기
// 외곽선이란?
3D 공간을 2D 이미지에 그려넣으면 물체 개념이 없다.
외곽선 정확히 찾기 힘들다.
그러나 명암이나 색조가 다르면 외곽선을 인식할 수 있다.
명암이 확 바뀌는 픽셀을 찾아 외곽선이라 해주자.
비교할 대상이 필요해진다.
주위 픽셀들을 모두 살펴야한다.
살펴보는 픽셀 많아지면 느려진다.
상하 좌우 대각선 한단계만 찾아보는 것을 3x3
두단계 살펴보는 것을 5x5 텍셀을 살펴본다고 표현하겠다.
// 컨벌루젼 사용
3x3, 5x5 픽셀 한번에 계산하기 편하게끔 컨벌루션을 사용한다. (convolution)
현재 픽셀 중심으로 그 주위에 있는 픽셀마다 가중치를 곱한다.
그 결과를 모두 더한다.
이 값으로 현재 픽셀의 값을 변경하는 연산이다.
행렬 형태로 저장한 가중치의 집합을 커널이라고 한다. (kernel)
2D 영상처리 기법에서 컨벌루션 사용 매우 많다.
포토샵의 블러, 샤프닝도 컨벌루션이다.
// 소벨 연산자
외곽선 찾기에서 컨벌루션 사용해보자.
외곽선 찾기에 사용할 커널 여러가지가 있을 수 있다.
그 중 소벨 연산자 사용해보자. (sobel operator)
위키피디아 참고해보자.
Kx Ky
-1 0 +1 +1 +2 +1
-2 0 +2 0 0 0
-1 0 +1 -1 -2 -1
Kx는 좌우 검출,
Ky는 상하 외곽선 검출한다.
// Lx 설명
Kx의 결과를 Lx라고 한다.
인접한 픽셀 값이 모두 같다면 0이 된다.
오른쪽이 왼쪽에 비해 명암이 크다면 양수가 된다.
명암차가 클수록 값이 더 커진다.
왼쪽이 오른쪽에 비해 크다면 음수가 된다.
명암차가 클수록 값이 더 작아진다.
Ly도 원리는 동일하다.
// 쉽게 정리
0에서 값이 멀어질수록,
양수 값이 클수록 음수 값이 작을수록
외곽선을 확실하게 보여준다.
따라서 Lx Ly의 절대값을 구해서 외곽선 보여주면 된다.
한번에 계산하려면 더해서 한다.
L = |Lx| + |Ly|
위처럼 해도 되지만,
소벨 연산자는 빗변의 길이를 구하는 피타고라스 정의를 사용하였다.
// 기초설정
챕터11의 설정과 다 동일하다.
픽셀셰이더만 바꿀 것이다.
픽셀셰이더
struct PS_INPUT
{
float2 mUV: TEXCOORD0;
};
sampler2D SceneSampler; // render target texture sampler
float3x3 Kx = {-1, 0, 1,
-2, 0, 2,
-1, 0, 1};
float3x3 Ky = {1, 2, 1,
0, 0, 0,
-1, -2, -1};
float2 gPixelOffset; // 1/texture width, 1/texture height
float4 ps_main(PS_INPUT Input) : COLOR
{
float Lx = 0;
float Ly = 0;
for(int y = -1; y <= 1; ++y)
{
for(int x = -1; x <= 1; ++x)
{
float2 offset = float2(x, y) * gPixelOffset;
float3 tex = tex2D(SceneSampler, Input.mUV + offset).rgb;
float luminance = dot(tex, float3(0.3, 0.59, 0.11)); // same grayscale
Lx += luminance * Kx[y+1][x+1];
Ly += luminance * Ky[y+1][x+1];
}
}
float L = sqrt((Lx * Ly) + (Ly * Ly)); // Pythagorean theorem.
return float4(L.xxx, 1);
}
위에서 얘기한 Kx, Ky 커널 2개를 선언한다.
for루프 돌리면서 주변 픽셀마다 Kx, Ky 곱한다.
누적 시킬 변수 Lx, Ly 만든다.
현재 픽셀을 중앙에 맞추고 주위 픽셀 찾는다.
-1 ~ 1 범위로 루프 돌린다.
루프가 돌 때마다 픽셀 하나씩 불러온다.
바로 옆 픽셀과 현재 픽셀 차이는?
UV는 0~1이다.
U는 1/텍스쳐너비
V는 1/텍스쳐높이 만큼 차이가 난다.
셰이더 안에서 알 수 있는 방법은 없다.
전역 변수로 넘겨 받는다.
어차피 넘겨 받을거면
1/텍스쳐너비, 1/텍스쳐높이로 넘겨받아 나누기 연산을 피한다.
텍스쳐를 읽어온다.
명암값의 차이로 외곽선을 찾는다.
명암이라 하면 흑백이라는 말이다.
따라서 흑백과 동일 공식 사용한다.
여기까지 주변 픽셀들에 커널 곱해서 그 값을 더했다.
이제 Lx와 Ly를 합친다.
피타고라스 정리 이용한다.
명암 변화 없으면 검정색, 많으면 흰색이 된다.
- 양각효과 (embossing)
올록볼록한 느낌 내는 것이다.
명암 변화가 없는 곳은 중간회색이 된다.
튀어나오는 곳은 밝은 회색이나 흰색
들어가는 곳은 어두운 회색이나 검정색이 된다.
// 튀어나오는 느낌이란?
왼쪽 위 하이라이트를 준다.
오른쪽 아래 그림자를 준다.
// 컨벌루전 사용
인접한 픽셀 살펴봐야한다.
컨벌루션 사용한다.
따라서 커널이 필요하다.
왼쪽 위 픽셀보다 오른쪽 아래 픽셀이 밝다면 하이라이트
왼쪽 위 픽셀이 오른쪽 아래 픽셀보다 밝다면 그림자를 준다.
커널은 다음과 같다.
-2 -1 0
-1 0 1
0 1 2
이 커널이 커버하는 픽셀들의 값이 모두 같으면 0이 된다.
이럴 때는 0.5가 되어야한다.
따라서 +0.5를 한다.
따라서 컨벌루션 결과가 0이상이면 0.5이상의 하이라이트 등장한다.
0이하면 0.5이하의 그림자가 보인다.
픽셀셰이더
struct PS_INPUT
{
float2 mUV : TEXCOORD0;
};
sampler2D SceneSampler;
float3x3 K = { -2, -1, 0,
-1, 0, 1,
0, 1, 2};
float2 gPixelOffset;
float4 ps_main( PS_INPUT Input ) : COLOR
{
float res = 0;
for ( int y = -1; y <= 1; ++y )
{
for (int x = -1; x <=1 ; ++x )
{
float2 offset = float2(x,y) * gPixelOffset;
float3 tex = tex2D(SceneSampler, Input.mUV+offset).rgb;
float luminance = dot(tex, float3(0.3, 0.59, 0.11));
res += luminance * K[y+1][x+1];
}
}
res += 0.5f;
return float4(res.xxx, 1);
}
컨벌루젼을 누적할 변수는 res이다.
루프 끝난 후 0.5를 더한다.
명암에 아무 변화가 없는 경우 중간회색이 된다.
- 기타 고급 포스트이펙트 기법
// 색상보정 (color correction)
말그대로 색상보정
// HDR (high dynamic range)
HDR은 블룸과 톤매핑을 포함한다.
나뭇가지 사이 태양보면 빛이 너무 강렬하게 뿜어진다. 이게 블룸이다.
톤매핑은 사람 눈처럼 어두운 곳과 밝은 곳을 모두 잘 보이게 만드는 것을 말한다.
카메라는 그렇지 않다. 밝거나 어두운 곳 하나만 제대로 보인다.
// 비니엣 (vignette)
가장자리 검정테두리
// DOF (depth of field)
초점 가까우면 멀리있는 물체 흐릿해진다. 반대도 된다.
// SSAQ (screen space ambient occlusion)
법선과 깊이 등을 렌더타깃에 저장한다. 이를 사용해 주변광 차폐 정도를 계산한다.
// 잔상효과 (motion blur)
저번 프레임, 현재 프레임 블렌딩 기법이다.
// 추가 참고사항
외곽선 찾기 기법은 안티에일리어싱에 사용하기도 한다.
- 고급 셰이더 기법 찾기
// GPU 젬스 시리즈
온라인에 공짜
// 셰이더 X / GPU 프로 시리즈
매년 발매, 셰이더X 7편까지 나온 후 이름 GPU 프로로 바꿔서 나오는 중이다.
// 컨퍼런스
최신기술은 컨퍼런스가 최고이다.
비디오와 파워포인트가 웹에 많이 공개된다.
// 시그래프
매년 북미 개최
시그래프 아시아 지역별 개최
시그래프 연회비 5만원 내면 시그래프 온라인 도서관 엄청난 양의 자료 열람 가능
// 게임 개발자 컨퍼런스 (GDC)
북미 매년 한 번
게임에서 실제사용 수많은 기법 접할 수 있다.
// 게임페스트
마이크로소프트사가 매년 주체한다.
다른 컨퍼런스에 비해 양은 적다.
이 컨퍼런스의 자료는 마이크로소프트사 웹사이트에 잘 올라온다.
// 인터넷
교수님, 석박사 학위 학생들의 홈페이지.
그리고 구글신.
'셰이더 (Shader) > 셰이더 프로그래밍 입문 - Pope Kim (완)' 카테고리의 다른 글
[HLSL] 챕터11 - 흑백/세피아 사진 만들기 (0) | 2023.03.21 |
---|---|
[HLSL] 챕터10 - 그림자매핑 (0) | 2023.03.20 |
[HLSL] 챕터9 - UV애니메이션과 울렁효과 (0) | 2023.03.20 |
[HLSL] 챕터8 - 환경매핑 (0) | 2023.03.20 |
[HLSL] 챕터7 - 법선매핑 (1) | 2023.03.19 |
댓글