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

오늘은 맨 처음 시간에 만들었던 first.sl을 가지고 놀아보죠.

first.sl ( 소스 1 )
----------------------------------------------------------------

surface first()
{
        Oi = Os;
        Ci = Cs * Oi;
}


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

1. 자세히 한 번 보죠.

2. 렌더러에서 micropolygon을 만든다음 각 micropolygon의 vertex단위로 Shader코드를 호출합니다. 이 경우 vertex의 정보를 쉐이더에 넘겨줄 무언가가 있어야 하지 않을까요 ?

현재 vertex의 위치라던지, 색상이라던지...쉐이딩을 위해 쉐이더 코드가 알아야 할 정보가 있을겁니다. 그리고 쉐이딩을 계산한 다음 microplygon vertex의 색상과 투명도를 돌려줄 방법이 필요할 겁니다.

그래서 surface shader에는 미리 지정된 변수를 통해 렌더러와 값을 교환합니다.

여기서 알아볼 변수들은 Os, Oi, Cs, Ci입니다.

Os : 투명도 입력
Oi : 투명도 출력

Cs : 색상 입력
Ci : 색상 출력

각각은 위와 같은 뜻이 있습니다. 즉, 렌더러에서 Cs에 색상값을 넣어주면, 쉐이더에서는 이 값을 가지고 쉐이딩을 계산하고 최종 결과 색상을 Ci에 지정하여 렌더러에 보내줍니다. 그럼 렌더러는 Ci값을 가지고 렌더링을 계속하게 됩니다.


2. 위 소스에서는 투명도는 그대로 입력을 출력으로 보내고, 색상은 투명도와 곱하여 출력값을 내보내고 있습니다. vertex의 위치나 라이트에 관계없이 전체가 뚝같은 색상으로 출력되는 이유가 되겠습니다.

3. 그럼 소스를 조금 수정하여 색상와 투명도를 지정해 봅시다.

first.sl ( 소스 2 )
----------------------------------------------------------------

surface first()
{
        Oi = 1.0;
        Ci = color "rgb" (1, 0, 0) * Oi;
}


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

4. make 로 컴파일, 렌더합니다.

$ make
shader first.sl
first: compiled.
cat test.rib | sed s/XXXX/first/g | prman


5. first.tiff을 열어 보세요. 빨간 원이 나올겁니다.

6. 실제로 RGB 값이 어떤 값이 나오는지 알아볼까요 ?

first.sl ( 소스 3 )
----------------------------------------------------------------

surface first()
{
        Oi = 1.0;
        Ci = color "rgb" (1, 0, 0) * Oi;
        print(Ci);
}


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

7. make를 실행해 봅니다.

8. 윽~~ 결과값이 너무 많군요. 이런 낭패가 있나 ?

9. Ctrl+C로 강제 종료하시고, 다른 방법을 모색해 보죠.

10. 전 시간에 사용했던 test2.rib를 변형해서 사용하는게 좋겠군요.

test.rib ( 소스 4 )
----------------------------------------------------------------

Display "XXXX.tiff" "tiff" "rgb"
Format 16 16 1
Projection "orthographic"
ShadingRate 100

WorldBegin
        Translate 0 0 1
        Surface "XXXX"
        Polygon "P" [0 0 0 1 0 0 1 1 0 0 1 0]
WorldEnd


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

11. 위와 같이 test.rib 파일을 변경하시고, make를 실행합니다.

$ make
cat test.rib | sed s/XXXX/first/g | prman
4 values:
0:1.000000 0.000000 0.000000
1:1.000000 0.000000 0.000000
2:1.000000 0.000000 0.000000
3:1.000000 0.000000 0.000000


12. 깔끔하게 값이 나왔습니다.

13. 예상했던대로 RGB 값중 R값만 1이기때문에 빨간색이 나왔군요.

14. 그럼 좀 더 놀아 볼까요 ?

first.sl ( 소스 5 )
----------------------------------------------------------------

surface first()
{
        Oi = 1.0;
        Ci = 1.0;
        print(Ci);
}


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

15. 이번에는 Ci값에 1.0이라는 값을 하나만 지정했습니다. 결과는 어떻게 될까요 ?

$ make
shader first.sl
first: compiled.
cat test.rib | sed s/XXXX/first/g | prman
4 values:
0:1.000000 1.000000 1.000000
1:1.000000 1.000000 1.000000
2:1.000000 1.000000 1.000000
3:1.000000 1.000000 1.000000


16. 오오~ 이런 전체 값이 1.0으로 흰색이 되었습니다.
그렇다는 것은 값을 하나만 지정하면 RGB 각각에 다 같은 값이 들어간다는 얘기군요.

17. 이번엔 투명도 값을 가지고 놀아봅시다.

first.sl ( 소스 6 )
----------------------------------------------------------------

surface first()
{
        Oi = 0.5;
        Ci = color "rgb" (1, 0, 0) * Oi;
        print(Ci);
}


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

18. 결과는

$ make
shader first.sl
first: compiled.
cat test.rib | sed s/XXXX/first/g | prman
4 values:
0:0.500000 0.000000 0.000000
1:0.500000 0.000000 0.000000
2:0.500000 0.000000 0.000000
3:0.500000 0.000000 0.000000


19. R 값 1.0 * 0.5, G 값 0.0 * 0.5 ... 하여 R 값만 0.5가 되었네요.

20. 좀 더 변형해 보죠.

first.sl ( 소스 7 )
----------------------------------------------------------------

surface first()
{
        Oi = color "rgb" (0.5, 0.6, 0.7);
        Ci = color "rgb" (1, 1, 1) * Oi;
        print(Ci);
}


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

21. 이번에 Oi에 색상값을 대입해 보았습니다.
결과는...

$ make
cat test.rib | sed s/XXXX/first/g | prman
4 values:
0:0.500000 0.600000 0.700000
1:0.500000 0.600000 0.700000
2:0.500000 0.600000 0.700000
3:0.500000 0.600000 0.700000


R:1.0 * 0.5 = 0.5
G:1.0 * 0.6 = 0.6
B:1.0 * 0.7 = 0.7

각 요소별로 곱하기가 되었군요. 거참 신기합니다. ^^

22. 자~ 그럼 마무리로 투명도에 대해 좀 더 얘기해 봅시다.

23. opacity란 무엇일까요 ?

그것을 알고 싶다면 우선 렌더러가 투명한 물체의 색상을 어떻게 계산하는지 알고 있어야 합니다.

예를 들어 봅시다.

뒤에 불투명한 빨간색 물체가 있고, 위에 투명한 파란색 물체가 있다고 합시다.

투명한 파란색 물체의 색상은 어떻게 결정되는 걸까요 ?

좀 더 구체적으로 예를 만들어 봅시다.

빨간색 물체는 색상이 color (1 0 0) 이고 opacity는 1.0으로 불투명합니다.

파란색 물체는 색상이 color (0 0 1)이고 opacity는 0.3입니다. 이럴 경우 파란색 물체와 빨간색 물체가 겹치는 부분의 색상은 어떻게 결정될까요 ?

이 경우 두 물체의 색상을 적절히 혼합하여 투명한 색상을 결정하게 되는데, 두 색상을 홉합하는 비율을 결정하는 것이 Opacity값입니다.

원래 색상이 가장 선명할때를 100%라고 봤을때, opacity가 0.3라는 것은 색상을 30%로 줄이는 것입니다. 즉 opacity 값은 두 색상의 웨이트값을 결정하는 역활을 하는 것입니다.

위의 경우 파란색 물체의 opacity가 0.3이므로 파란색 30%를 적용하고, 곁치는 곳의 색상 70%를 혼합하여 최종 색상을 얻어내게 됩니다.

좀 더 구체적으로 보자면,

파란 물체 색상 * 0.3 + 바탕 물체 색상 * (1.0 - 0.3)

로서 최종 opacity의 비율에 따라 색상을 혼합하게 됩니다.

24. 역시 설명으로는 이해가 어려운 점이 있겠네요.

25. 구체적인 예제입니다.

test.rib ( 소스 8 )
----------------------------------------------------------------

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

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

Translate 0 0 3

WorldBegin
        Color [1 0 0]
        Surface "XXXX"
        Sphere 1 -1 1 360

        Translate 0 -0.5 0
        Color [0 0 1]
        Opacity [0.3 0.3 0.3]
        Surface "XXXX"
        Sphere 1 -1 1 360
WorldEnd


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

first.sl ( 소스 9 )
----------------------------------------------------------------

surface first()
{
        Oi = Os;
        Ci = Cs * Os;
}


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

26. make를 실행합니다.
Pasted Graphic


27. 첫번째 스피어는 빨간색이고 불투명합니다. 두번째 스피어는 파란색이고 opacity는 0.3입니다.

28. 이젠 포토샵등의 이미지 프로세스 프로그램으로 first.tiff를 열어 보세요. 그리고 스포이드 툴로 두 스피어가 겹치는 부분의 색상을 봅니다.



29. 결과는
R : 179
G : 0
B : 76
입니다. 이걸 1.0기준 값으로 만들려면 각각 255로 나누어 주면 됩니다. 해 봅시다.

R : 179 / 255 = 0.70196078431372549019607843137255
G : 0
B : 76 / 255 = 0.29803921568627450980392156862745

파란색 값에 0.3이 적용되었고, 나머지 바탕의 빨간색은 0.7이 적용되었습니다.

즉 파란색 30%와 빨간색 70%가 섞인 색이 최종 색상이 되었습니다.

우리가 원하는 100% 색상중 30%을 파란색, 70%을 빨간색에서 가져와 사용한 것입니다.

1.0 기반으로 한 웨이트 기법은 자주 사용되는 기법으로 앞으로도 종종 보시게 될겁니다.

자~ 결론을 내보죠.

opacity라는 것은 자신과 배경 색과의 블랜딩을 조절하는 factor로 사용되는 값입니다.

깔끔하네요 ^^

그럼 다음 시간에 또 뵙죠.



에제소스 : shader_3.zip