[3D게임 수학&물리] 직선 그라데이션 그리기

Herring·2021년 4월 4일
0
post-thumbnail

개인적으로 공부한 내용을 작성한 것으로 틀린 부분이 있을 수 있습니다.
혹 틀린 부분이 있다면 말씀해주시면 감사하겠습니다.🙏

1. 가로/세로 직선 그라데이션

현재 일반적인 디스플레이는 한 픽셀당 24bit를 사용한다(R,G,B 각각 8bit씩). 즉 R,G,B 각 색상마다 0~255 사이의 값을 갖는다.
이때 위와 같은 그라데이션을 만든다고 생각해보자.
위 이미지에서 색상의 변화를 x, y좌표에 따라 RGB 수치로 나타내보면,
y=0일때 (0, 0, 255), y=255일때 (255, 255, 255)이다. x값은 영향을 주지 않는다(*DirectX에서는 좌표의 시작점이 왼쪽 위이다).
즉 R,G값이 y값에 비례하는 것을 알 수 있다.

소스 코드

// 스캔라인 알고리즘에 의한 렌더링
int RenderScanLine(void)
{
    int	x, y;
    int	nBright;

    for (y = 0; y < VIEW_HEIGHT; y++) {		// y 방향 루프
        for (x = 0; x < VIEW_WIDTH; x++) {	// x 방향 루프
            nBright = y & 0xff;					// 밝기가 y 좌표에 연동
            DrawPoints(x, y, nBright, nBright, 255);	//1픽셀 그리기 함수(x,y,r,g,b)
        }
        FlushDrawingPictures();	//그리기 대기 행렬 플러시 함수
    }

    return 0;
}

nBright = y & 0xff; <- 여기가 핵심 라인이다.
y를 x로 바꾸면 그라데이션이 x값을 따라 그려지게 될 것이다.
0xff(=255)와 AND 연산하는 것은 y값이 255보다 커지더라도 nBright가 색상 표현 범위(0~255)를 넘어가지 않도록 하기 위함이다.
예를 들어 y=256인 경우
0000 0001 0000 0000 (256)
0000 0000 1111 1111 (255)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ &
0000 0000 0000 0000 (0) 이므로
nBright = 0 이 된다.
그래서 위 이미지에서처럼 점점 흰색이 되다가 중간쯤(256px)부터 다시 완전한 파란색이 되는 것이다.

(*DrawPoints()FlushDrawingPictures() 는 저자가 제공하는 코드에서 정의된 사용자 정의 함수이다.
DrawPoints(): 정점의 좌표와 색상을 XMFLOAT4 형식으로 정점 버퍼에 저장함.
FlushDrawingPictures(): DeviceContext를 통해 화면에 출력하는 함수인 것 같은데, 자세한건 따로 공부해야될듯.)

2. 45도 경사진 사선 그라데이션

사선 그라데이션은 이미지처럼 x, y값 모두 밝기에 영향을 미친다.
그리고 x, y값에 따른 가로의 밝기 변화량과 세로의 밝기 변화량이 같으므로, 코드로 작성하면
nBright = (x+y) & 0xff; 와 같다.
이때 '&0xff' 부분을 제외하면 nBright = x+y 인데, 좌변과 우변을 바꾸고 x를 이항하면
y = -x + nBright
즉, 기울기가 -1이고 절편이 nBright인 직선의 방정식이 된다는 것을 알 수 있다!
(*실제 출력된 그라데이션은 기울기가 1인데, 이는 아까도 말했듯 D2D의 좌표계는 y축이 아래를 향하기 때문이다)
이를 응용하여 그라데이션의 기울기를 조정할 수 있다.
또 x와 y에 동일한 값을 곱하거나 나눠줌으로써 기울기는 같되 간격을 달리할 수도 있다.

3. 두 색상이 부드럽게 교차되는 그라데이션

위의 식을 조금 바꿔서 두 색상이 부드럽게 교차되는 그라데이션을 만든다고 생각해보자.
일단 2번의 이미지와 비교해봤을 때,
기울기는 그대로이고(x+y), 색상 간격은 2배 가까워졌음을 알 수 있다.(2*(x+y))

밝기 값을 그래프로 나타내기

2(x+y) & 0xff 의 이미지② 만들고자 하는 최종 이미지 에서의 밝기 값을 그래프로 나타내면 다음과 같다.

그래프 변환 과정

①의 그래프를 ②처럼 만드는 방법을 생각해보자.

0) 2(x+y) & 0xff 의 밝기 값 그래프이다. -> 범위: 0~255
1) 밝기 범위를 0x1ff (=(256*2)-1) 로 설정한다. -> 범위: 0~511
2) 0x1ff의 절반만큼을 마이너스한다. -> 범위: -255~256
3) 절댓값을 취하여 마이너스 영역을 플러스로 반전시킨다. -> 범위: 255~0, 0~256

따라서 최종 이미지의 밝기 값은 nBright = abs(((2*(x+y)) & 0x1ff)-255); 이 된다.

실제 색의 밝기 범위는 255까지이므로 색의 범위가 1만큼 오버되었지만, 지정된 범위를 넘어섰을 경우 최대한 가까운 값의 색으로 조정하기 때문에 255로 조정된다.

0개의 댓글