HLSL

Posted 2007/02/27 14:51 by J2L

HLSL(DirectX)

HLSL DirectX 9.0과 함께 발표된 기술이다. 기존의 셰이더 기술이 어셈블리 수준에서 작성되어야 했던 것을 획기적으로 발전시켰다고 하겠다. HLSL은 일단 C언어를 모태로 하고 있기 때문에 C언어를 알고 있는 개발자라면 기본적인 문법은 상당히 쉽게 이해 할 수 있다. 다만, C언어에서는 사용하지 않는 특별한 자료형(float3, float4x4)들을 다루고 있으며, switch-case등의 명령은 사용할 수 없다. 그러나, 포인터와 동적 메모리할당 기능이 없기 때문에알고리즘만 잘 적용하면, 치명적인 오류(NULL 포인터)는 애초에 발생할 수가 없다.

아키텍처(구조) 다이어그램

사용자 삽입 이미지

<그림 2-1> DirectX 9.0셰이더의 구조도 <arch-hlsl.ppt>

<그림 2-1> DirectX 9.0셰이더의 구조도 이다. 정점셰이더와 픽셀셰이더로 나뉘어져 있음을 잘 알 수 있다. 또한 아직까지는 정점셰이더에서 텍스처에대한 접근이 허용되고 있지 않고 있다.

사용자 삽입 이미지

<그림 2-2> HLSL의 실행과정 <pipe-hlsl.ppt>

<그림 2-2> HLSL 소스가 어떤 과정을 거쳐서 셰이더로 작동하는가를 보여주고 있다. HLSL코드는 일단 D3DX ID3DXEffectCompiler인터페이스의 CompileShader() CompileEffect()함수를 통해서 컴파일 된다. 이렇게 컴파일된 소스는 2진파일 형태로 DirectX 9.0런타임에 전달된다. 런타임에서는 셰이더 2진파일을 드라이버를 통해서 그래픽카드에 전달하여 실행하게 된다.

특징

GLSL이나 Cg의 경우에는 플랫폼 독립적인 기술이므로, 리눅스나 솔라리스 등에서도 사용할 수 있다. 이것은 최근 컨솔게임시장을 기반으로 멀티플랫폼 지원이 세계적인 추세라는 것을 생각해보면 대단히 중요한 기능이 될 것이다. 그러나, DirectX HLSL은 철저하게 윈도우에서만 작동하는 것이 단점이다. 향후 DirectX기술이 플랫폼 독립적인 기술이된다면 모르겠지만, 당분간은 PC기반 기술의 표준으로 만족해야 할 것이다.

OpenGL ARB에서 표준으로 정한 OpenGL전용 셰이더가 GLSL(혹은 GLSlang)이다. 최근 까지도 GLSL을 하드웨어적으로 제대로 지원하는 그래픽카드는 대단히 고가의 장비였으나, ATI Catalyst드라이버 3.10버전(20031220)부터 GLSL을 지원하기 시작했다. 덕분에DirectX9.0을 지원하는 대부분의 ATI그래픽 카드에서 GLSL프로그래밍이 가능해졌다.

정점셰이더(Vertex Shader)

이제 우리는 정점셰이더를 직접 구현해볼 것이다. 먼저 정점셰이더에 대한 간단한 구조를 이해하고, 구현된 정점셰이더를 직접 사용하는방법에 대해서도 알아 볼 것이다.

정점셰이더(VS)의 역할

VS는 정점에 대한 처리만을 담당한다. VS 3.0에서는 정점셰이더에서 텍스처나 Z버퍼에대한 접근까지도 허용한다고 하는데, 아직까지는 하드웨어적인 지원이 불가능 하므로, 당분간은 정점에 대한 처리만 담당한다고 생각하자. VS의 가장 큰 특징은 입력과 출력이 반드시 1:1이라는 점이다. , 입력되는정점은 반드시 하나이고, 출력되는 정점도 반드시 하나라는 것이다. VS는 결코 정점을 생성하거나 소멸시킬 수 없는 것이다. 물론 VS기법중에는 정점들의 위치좌표를 겹치게해서 마치 정점이 소멸된 것처럼 속여서 실시간 LOD를 구현하는 경우도있지만, 이것은 어디까지나 속이는 것이지 실제로 소멸되는 것은 아니다. 또한 정점셰이더나 픽셀셰이더나 프로그래밍 가능한 크기에 제한이 있으며, 사용할 수 있는 메모리 공간도제한이 있다.

기능

DX 8.1

DX 9.0

최대 명령 개수

128

1024

최대 상수레지스터 개수

96

256

< 1-1> 정점셰이더의 제한사항

VS가 내부적으로 하는 역할을 도식화한 그림을 보면서VS의 역할을 이해하도록 하자. 정점셰이더는 크게 4개의 레지스터군과 중앙의 연산장치(ALU=Arithmetic Logic Unit)로 이루어져 있는데, <그림 1-1>을 보면 입력레지스터가 16, 외부에서 설정가능한 상수레지스터가 c0~255까지의 256개 있음을 알수있다. 그리고 연산시에 사용되는 범용 임시레지스터가 r0~r11까지 12개있다. 마지막으로 출력에 사용하는 레지스터가 있다. 출력용 레지스터는 VS에서 출력할 필요가 있는 것들만 출력하면 되는데, oPos만큼은 반드시 출력해야 한다. 정점 셰이더에서 사용가능 한 명령어들 중에서 중요한 것을 몇 가지 나열하면 < 1-3>과 같다.

사용자 삽입 이미지

<그림 1-1> 정점 셰이더의 구조 <vs-arch.ppt>

명령

역할

vs

버전지정

def

상수값 정의

nop

no operation(아무것도 하지않고 그냥 1클럭을 소모한다)

mov

값의 대입

add

두개의 벡터의 덧셈, 뺄셈(sub) add에 음수값을 더해서 구현한다

mul

두개의 벡터의 곱셈, 나눗셈(div)은 역수를 구해서 곱한다.

mad

곱하고 더한다

rcp

역수

rsq

역수의 제곱근

dp3/dp4

벡터의 내적

dst

거리값

exp/expp

exp

log/logpp

log

sge

greater equal, 같거나 크면 1

Slt

less than 작으면 1

dst

거리값, 광원의 감쇄(attenuation)연산

lit

조명연산

< 1-2> 정점셰이더의 주요 어셈를리 명령들

이외에도 sincos이나 m4x4같은 확장명령어들이 있다. 이런 명령들은 기본명령어들을 조합해서 만든 명령이기 때문에 컴파일시 자동적으로 확장 되게 된다. 예를 들어서 정점과 행렬을 곱하는 연산인 m4x4는 다음과 같이 확장된다.

m4x4 r0.xyzw, r1, c0

dp4 r0.x, r1, c0

dp4 r0.y, r1, c1

dp4 r0.z, r1, c2

dp4 r0.w, r1, c3

픽셀셰이더(Pixel Shader)

정점셰이더로부터 넘어온 정보를 기준으로 출력할 폴리곤을 만든다. 이렇게 만들어진 폴리곤이 실제로 화면상에 출력되기 전에 픽셀셰이더를 거쳐서 최종적으로 출력될 색깔값을 갖게 된다. 이러한 픽셀셰이더의 작동과정을 살펴보도록 하자.

픽셀셰이더의 역할

픽셀셰이더의 특징은 화면에 출력될 모든 점에 대한 정보를 연산하는 것이 아니라, 정점연산을 거쳐서 생성된 폴리곤의 픽셀들에 대해서만 연산이 이루어진다는 것이다.

사용자 삽입 이미지

<그림 2-1> 픽셀셰이더의 파이프라인 <PS-pipe.ppt>

또한 실제로 픽셀셰이더에서 입력과 출력으로 사용할수 있는 레지스터는 정점셰이더에 비해서 좀더 제한적이다.

사용자 삽입 이미지

<그림 2-2> 픽셀 셰이더의 구조 <pss-arch.ppt>

입력되는 값은 2개의 색깔값 v0, v1 8개의 텍스처좌표 t0~t7까지이다. 그리고 텍스처좌표와 결합되어 실제로 텍셀 정보를 얻어올 수 있는 샘플러 레지스터 s0~s15가 있다. 임시레지스터는 r0~r11까지의 12개이지만, 상수레지스터는 c0~c31 32개뿐이다. 게다가 정점셰이더보다 사용할 수 있는 명령슬롯의 개수도 적다.

기능

DX 8.1

DX 9.0

최대 입력 텍스처 개수

6

16

최대 주소명령 개수

8

32

최대 컬러명령 개수

8

64

데이터 타입

integer

float

정밀도

32비트

128비트

< 2-1> 픽셀셰이더 제한사항

정점셰이더가 1024개의 명령슬롯을 가지고있는데 비해서 픽셀셰이더는 96개가 한계이다. 물론 NVIDIA CineFX는 정점셰이더가 64k, 픽셀셰이더가 1024개의 영역을 가질수 있고, ATI RadeOn9800 F-Buffer기능을 사용하면 픽셀셰이더를 무한대로 확장하는것도 가능하다. 그러나, 이러한 기능들은 모두 DX9.0의 표준이 아니기 때문에 특정 그래픽카드에서만 작동하는 비표준 시스템이므로 사용시 주의를 필요로 한다. 그리고 가장 중요한 정점셰이더와 픽셀셰이더의 결합 파이프라인을 그림으로 설명해놓았으니 자세히 봐두기 바란다. 렌더링 파이프라인의 이해야말로, 셰이더 프로그래밍의 가장 핵심이다.

사용자 삽입 이미지

<그림 2-3> 셰이더 파이프라인 <shader-pipe.ppt>

< 2-2>는 픽셀셰이더의 중요한 명령어들을 나열한 것이다. 어셈블리 프로그래밍으로 픽셀셰이더를 개발할 경우에는 < 2-2>의 명령어들을 사용해야 한다. 물론 이보다 훨씬 많은 명령들이 있으나, 가장 기초가 되는 명령들만 나열한 것이다.

명령

역할

ps

버전지정

def

상수값 정의

nop

no operation(아무것도 하지않고 그냥 1클럭을 소모한다)

mov

값의 대입

add

두개의 벡터의 덧셈, 뺄셈(sub) add에 음수값을 더해서 구현한다

mul

두개의 벡터의 곱셈, 나눗셈(div)은 역수를 구해서 곱한다.

mad

곱하고 더한다

rcp

역수

rsq

역수의 제곱근

dp3/dp4

벡터의 내적

dst

거리값

exp

exp

log

log

lrp

선형보간

texld

텍셀 샘플링

texldb

w값을 기반으로 LOD텍셀 샘플링

texldp

w값으로 나눈 투영 샘플링

< 2-2> 픽셀셰이더의 주요명령들

이펙트(Effect)

Direct3D에는 8.0부터 이펙트 프레임워크라는 것이 도입되었다. 그러나 대다수의 사람들이 8.0의 이펙트 프레임워크의 존재자체를 모르거나, 거의 사용하지 않았다. 그러나 9.0부터는 얘기가 달라졌다.

이팩트 파일인 fx 파일은 출력효과를 설정하는 명령들을 나열한 파일이라고 생각하면 된다. 먼저 technique라는 명령으로 사용하려는 출력효과명을 정해주고, {}로 감싼 블록내부에 출력효과 설정명령들을 나열하면 된다. technique명령 뒤에는 반드시 하나 이상의pass가 오게 되어있다. , 여러 번의 멀티패스 랜더링이 가능하다는 얘기다.

사용자 삽입 이미지

<그림 4-1> fx 파일의 일반적인 구조 <effect-struct.ppt>

크리에이티브 커먼즈 라이선스
Creative Commons License

'C#' 카테고리의 다른 글

■ 값타입과 참조타입의 메모리 형성의 차이 ■  (0) 2007/04/04
닷넷 프레임워크 3.0 런타임 설치  (0) 2007/03/14
HLSL  (0) 2007/02/27
Direct3D 메시의 크기 설정  (0) 2007/02/14
C# 이미지에 글쓰기..  (0) 2007/02/13
Direct3D 메시의 회전  (0) 2007/02/02

Tag : , ,

« PREV : 1 : ... 67 : 68 : 69 : 70 : 71 : 72 : 73 : 74 : 75 : ... 85 : NEXT »