강좌를 보기 전에...
Cygwin 설치방법
REYES
Shader 강좌 1
Shader 강좌 2
Shader 강좌 3
Shader 강좌 4
Shader 강좌 5
Shader 강좌 6
Shader 강좌 7
Shader 강좌 8
안녕하세요. 김대현입니다.

1. 오늘은 Ramp 쉐이더를 통해 텍스쳐 좌표를 사용하는 방법을 배워보겠습니다.


2. 마야나 후디니같은 3D 프로그램을 다뤄보신 분들은 텍스쳐를 붙이기 위해 u,v라는 평면 좌표를 사용한다는 것을 아실 것입니다. 렌더맨에도 똑같은 u,v가 있는데요. 조금 의미가 틀립니다. 렌더맨에서의 u,v는 서피스에서 내가 처리하고 있는 점의 위치를 가리킵니다.

uv라는 평면 좌표로 서피스를 나타낼 수 있는 이유는 렌더맨에서 기본적으로 micropolygon grid로 구성되어 있는 patch기반의 사각형이기 때문입니다.

모델링 프로그램에서 텍스쳐 좌표를 변경했다면, uv도 바뀌는 걸까요 ?

그렇지 않습니다. 모델링 프로그램에서 어떻게 바꾸었던지 관계없이 항상 서피스의 위치만을 고수하고 있습니다. 그렇다면, 모델링 프로그램에서 바뀐 텍스쳐 좌표를 어디를 참조해야 하는 걸까요 ?

바로~바로~~s,t라는 전역 변수를 통해서입니다. 기본적으로 uv좌표와 같은 좌표를 가지지만, 모델링 프로그램에서 변경했다면, 바로 s,t를 변경한 것입니다. 사용자로 하여금 s,t를 통해 서피스가 어떻게 텍스쳐될 것인지 정할 수 있게 하는 것이죠. 특별히 모델링 프로그램에서 지정하지 않고 사용한다면 uv를 그냥 사용해도 무방합니다.




3. 자~ 그럼 s, t를 가지고 Ramp 쉐이더를 만들어 봅시다.

Makefile
--------------------------------------------------------------------------------

RENDER=prman
SLCOMPILER=shader
SLEXT=slo

SHADERNAME=firstRamp

${SHADERNAME}.tiff : ${SHADERNAME}.${SLEXT} test.rib
    cat test.rib | sed s/XXXX/${SHADERNAME}/g | ${RENDER}

${SHADERNAME}.${SLEXT} : ${SHADERNAME}.sl
    ${SLCOMPILER} ${SHADERNAME}.sl

clean :
    rm -f ${SHADERNAME}.tiff ${SHADERNAME}.${SLEXT}


--------------------------------------------------------------------------------



test.rib
--------------------------------------------------------------------------------

Display "XXXX.tiff" "tiff" "rgb"
Format 320 240 1
Projection "perspective" "fov" [45]

LightSource "ambientlight" 1 "intensity" [0.2]
LightSource "spotlight" 2 "from" [-1 1 0 ] "to" [0 0 3] "intensity" [3]

Translate -0.5 -0.5 1.5

WorldBegin
    Color [1 0 0]
    Surface "XXXX"
    Patch "bilinear" "P" [ 0 0 0
                           1 0 0
                           0 1 0
                           1 1 0]
WorldEnd


--------------------------------------------------------------------------------



firstRamp.sl
--------------------------------------------------------------------------------

surface firstRamp ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);

    color Ct = s;

    Oi = Os;
    Ci = Oi * ( Ct * (Ka*ambient() + Kd*diffuse(Nf)) );
}


--------------------------------------------------------------------------------
Pasted Graphic


4. make 를 입력하여 렌더링합니다.
자~ 어떻게 나옵니까 ?
가로로 그라데이션된 그레이스케일 이미지가 나올겁니다.
그럼 세로로 그라데이션을 하고 싶다면...

그렇죠~ color Ct = t;로 하면 되겠군요.

기본적으로 s와 t는 0~1사이의 값입니다. 우리가 만들고 있는 Ramp 쉐이더에서는 텍스쳐의 위치라기보다는 색상의 웨이트값 혹은 s,t 자체를 그레이스케일 색상으로 보는 것이죠. ( 현재 예제에선 s, t가 그레이스케일 색상입니다. )


5. 전에 color에 1개의 값만을 넣으면 어떻게 되는지 말씀드렸습니다.
그렇죠~ 바로 그 값이 전체에 똑같이 복사됩니다. 그렇다는 것은 그레이스케일된다고 보셔도 되겠네요.

이번 기회에 정리하자면, color에 각각의 요소에 값을 대입하면, 칼라값이 되는 것이고, 하나의 값만을 대입한다면, 그레이스케일이 되는 것입니다.




6. 자~ 그럼 좀 더 응용해서 원래 Cs 색상을 적용해 봅시다.

Makefile ( SHADERNAME만 다음과 같이 변경 )
--------------------------------------------------------------------------------

SHADERNAME=secondRamp


--------------------------------------------------------------------------------


secondRamp.sl
--------------------------------------------------------------------------------

surface secondRamp ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);

    color Ct = Cs * s;

    Oi = Os;
    Ci = Oi * ( Ct * (Ka*ambient() + Kd*diffuse(Nf)) );
}


--------------------------------------------------------------------------------




Pasted Graphic 1
~ 검정색에서 우리가 test.rib에서 지정한 빨간색으로 그라데이션되는 군요.

이번 예제에선 s,t 색상의 웨이트값으로 사용되었습니다.
s값이 0이면 색상이 없음에서 1 원래 색상입니다. ( Cs * 0 = 0, Cs * 1 = Cs 임을 상기하세요. )





7.
그럼 좌우를 바꾸어 보죠~

Makefile ( SHADERNAME
다음과 같이 변경 )
--------------------------------------------------------------------------------

SHADERNAME=thirdRamp


--------------------------------------------------------------------------------


thirdRamp.sl
--------------------------------------------------------------------------------

surface thirdRamp ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);

    color Ct = Cs * (1-s);

    Oi = Os;
    Ci = Oi * ( Ct * (Ka*ambient() + Kd*diffuse(Nf)) );
}


--------------------------------------------------------------------------------



Pasted Graphic 2
멋지지 않습니까? 1-s로 바로 값을 반전해 버렸습니다.





8. 자~그럼 6번과 7번 예제를 맛나게 비벼 보죠~

Makefile ( SHADERNAME만 다음과 같이 변경 )
--------------------------------------------------------------------------------

SHADERNAME=colorRamp


--------------------------------------------------------------------------------


colorRamp.sl
--------------------------------------------------------------------------------

surface colorRamp ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);

    color Blue = color "rgb" (0, 0, 1);
    color Ct = Cs * (1-s) + Blue * s;

    Oi = Os;
    Ci = Oi * ( Ct * (Ka*ambient() + Kd*diffuse(Nf)) );
}


--------------------------------------------------------------------------------



Pasted Graphic 3
비비셨는지 모르겠네요. ^^

빨간색에서 파란색으로 그라데이션이 되었습니다.

이렇게 유용한 공식을 픽사아저씨들이 그냥 둘리가 없죠. 바로 mix라는 함수입니다.





9.
mix 함수로 고쳐보죠.

colorRamp.sl
--------------------------------------------------------------------------------

surface colorRamp ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);

    color Blue = color "rgb" (0, 0, 1);
    color Ct = mix(Cs, Blue, s);

    Oi = Os;
    Ci = Oi * ( Ct * (Ka*ambient() + Kd*diffuse(Nf)) );
}


--------------------------------------------------------------------------------

mix(첫번째색상, 두번째색상, 웨이트값)

=

첫번째색상 * (1-s) + 두번째색상 * s;

같은 역활을 하지만 참으로 깔끔 자체 아니겠습니까 ?




10.
그럼 이번엔 색상이 급격하게 변하는 Ramp 쉐이더를 만들어 보겠습니다.

Makefile ( SHADERNAME
다음과 같이 변경 )
--------------------------------------------------------------------------------

SHADERNAME=checker1


--------------------------------------------------------------------------------


checker1.sl
--------------------------------------------------------------------------------

surface checker1 ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);
    color Ct;

    if(s < 0.5)
        Ct = color "rgb" (1, 1, 1);
    else
        Ct = color "rgb" (0, 0, 0);


    Oi = Os;
    Ci = Oi * ( Ct * ( Ka*ambient() + Kd*diffuse(Nf) ) );
}


--------------------------------------------------------------------------------

Pasted Graphic 4
결과가 어떻습니까 ?

흰색이다가 중간에 갑자기 검정색으로 바뀝니다. 색상이 바뀐건 좋은데, 흰색에서 검정색으로 바뀌는 곳이 너무 급격하게 색상이 변화하기 때문에, aliasing 생깁니다. 이건 정말 않좋군요.

색상이 변화하는 엣지 부분에 색상이 섞이는 부분이 조금 있으면 좋겠네요.





Makefile ( SHADERNAME
다음과 같이 변경 )
--------------------------------------------------------------------------------

SHADERNAME=checker2


--------------------------------------------------------------------------------


checker2.sl
--------------------------------------------------------------------------------

surface checker2 ( float Ka = 1; float Kd = .5; )
{
    normal Nf = faceforward (normalize(N),I);
    color Ct;

    color White = color "rgb" (1,1,1);
    color Black = color "rgb" (0,0,0);

    float weight = smoothstep(0.5, 0.6, s);

    Ct = mix(White, Black, weight);


    Oi = Os;
    Ci = Oi * ( Ct * ( Ka*ambient() + Kd*diffuse(Nf) ) );
}

--------------------------------------------------------------------------------



Pasted Graphic 5
s값이 0.5에서 0.6 사이가 부드럽게 그라데이션된 것을 볼 수 있습니다. 이 간격을 좀 더 작게하여 두 색이 변하는 부분의 엣지에 aliasing을 제거할 수 있습니다.



Pasted Graphic 6
지금 보시고 계신 그래프가 바로 smoothstep이 해주는 역활입니다.

바로 지정한 영역을 부드럽게 블랜딩해주는 것이죠.

각 인자의 뜻은, smoothstep(최소값, 최대값, 값)으로, 값이 최소값보다 작으면 0, 최대값보다 크거나 같으면 1, 그리고, 최소값최대값 사이의 값은 Hermite 보간에 의해 부드러운 곡선값을 돌려줍니다.





복잡한 Ramp를 만든다고 해도 결국을 지금까지 말씀드린 기본 바탕위에 만들어 지는 것입니다.

오늘은 여기까지입니다. 수고하셨습니다.~! 다음 시간에 뵙죠.