아마도 텍스쳐의 텍셀 값들을 만들어 내는 일종의 GPU 프로그램인 듯 하다. 찾아보니 DX10에서는 ID3DX10DataProcessor라는 놈으로 바뀐 듯???
HLSL에서 noise 함수를 쓰려고 했더니 픽셀 셰이더에서 안된다고 한다. 아얘 안써지는게 아니라... 의존적인 코드가 들어가면 안된다. 예를 들면 노이즈 함수 결과를 이용한다던지 하는거...
ID3DXTextureShader 라는 인터페이스로 사용할 수 있고, 텍스쳐 셰이더를 동작 시키는 방법은
HRESULT D3DXFillTextureTX(
LPDIRECT3DTEXTURE9 pTexture,
LPD3DXTEXTURESHADER pTextureShader
);
라는 함수를 사용하면 되는가 보다.
첫 번째 파라메터에는 텍셀이 채워질 텍스쳐 인스턴스이고, 두 번째 파라메터는 텍스쳐 셰이더의 인스턴스... 그리고 HLSL에서 함수 파라메터는 POSITION과 PSIZE가 들어가야 한다. 뭐 POSITION은 텍셀의 좌표이고, PSIZE는 텍셀의 크기. 그리고 반환 값은 당연히 COLOR가 되어야 한다. 텍스쳐 셰이더의 인스턴스를 생성하기 위해서
HRESULT D3DXCreateTextureShader(
CONST DWORD *pFunction,
LPD3DXTEXTURESHADER *ppTextureShader
);
를 사용 한단다. 첫 번째 파라메터는 컴파일된 텍스쳐 셰이더의 바이너리 코드 스트림이고, 두 번째는 생성될 텍스쳐 셰이더 인스턴스를 받을 포인터...
컴파일은 D3DXAssembleShader나 D3DXCompileShader등의 함수를 써서 바이너리 코드를 얻어야 하나부다.실시간으로 노이즈 함수를 사용하기 위해서 미리 텍스쳐 셰이더로 노이즈 텍스쳐를 이걸로 만든다음. 정점 셰이더나 픽셀 셰이더에서는 이 텍스쳐를 사용해야 하는 것 같다.
엔비댜에서 이렇다고 한다.
아주 간단한 펄린 노이즈 생성 함수다.
float4 tx_makePerlinNoise(
float2 vTexCoord : POSITION,
float2 vTexelSize : PSIZE) : COLOR
{
float n = 0.0f;
for (int i = 0; i < 5; ++i)
{
n += noise(vTexCoord);
vTexCoord *= 2.0f;
}
n = n * 0.5f + 0.5f;
return float4(n, n, n, 1.0f);
}
옥타브는 5로 설정해 놓았고, 매 옥타브마다 주파수는 2배씩 증가하도록 해 놓았다.
또한 텍스쳐에는 [0,1) 값만 허용 되므로 (Floating-Point 텍스쳐를 사용하지 않는다면) [-1,1]의 값을 갖는 노이즈 함수를 재 설정 하였다 (<= 뭔 소리야).
위에서 얘기 했지만, vTexCoord : POSITION과 vTexelSize : PSIZE는 필수 항목이다. PSIZE가 있어서 Weighted Sum 연산이 가능할것 같다(추측).
텍스쳐 셰이더를 컴파일 하는 과정에서 약간 애를 먹었는데
HRESULT hRet = D3DXCompileShaderFromFile(
"perlin_noise.hlsl",
NULL,
NULL,
"tx_makePerlinNoise",
"tx_1_0",
0,
&pTSCodeBuf,
&pErrMsgs,
NULL
);
타겟(프로파일)을 tx_1_0 으로 해주어야 한다. 도큐멘트의 함수 설명에는 vs와 ps밖에 안나와 있어서... 나머지 파라메터들은 정점 셰이더와 픽셀 셰이더에서와 같다(모 토큐멘테이션 하기 싫어하는거 공감은 간다).
이렇게 해서 D3DXFillTextureTX로 실행하면 Mipmap 단계들까지 자동으로 채워주는 완벽한 절차적 텍스쳐를 생성할 수 있게 된다. 근데 좀 오래 걸린다. 아무래도 실시간에는 사용 불가능할 듯...
이거 이제 어떻게 써먹냐....