mesh 생성
이전 작업이 파일로부터 mesh를 읽어들이는 것이었다면 이번 작업은
mesh를 구성하는것이다.
기본적으로는 dx9 같이 몇몇개의 서브셋으로 구성되어져 있다.
하지만 생성하는 절차와 사용하는 api가 조금 다르다.
ID3DX10Mesh* mesh = NULL; // 메시 - (정점, 인덱스, 속성버퍼를 가진다)
1. 정점 구조체의 형식을 결정하고 d3d10_input_element_desc 구조체를 준비하고 입력레이아웃을 생성
D3D10_INPUT_ELEMENT_DESC elements[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};
// 입력레이아웃을 생성한다.
D3D10_PASS_DESC passDesc;
UINT numElements = COUNT_ARR(elements);
pkTechnique->GetPassByIndex(0)->GetDesc(&passDesc);
hr = pkDevice->CreateInputLayout(elements, numElements, passDesc.pIAInputSignature, passDesc.IAInputSignatureSize, &inputLayout);
2. d3dx10createmesh를 호출하여 비어있는 메시를 생성.
HRESULT hr = D3DX10CreateMesh(pkDevice, elements, numElements, "POSITION", 24, 12, 0, &mesh);
3. 정점, 인덱스 속성버퍼에 데이터를 채운다.
SimpleVertex vertices[] = { // 박스를 생성함.
.....
}
esh->GetVertexBuffer(0, &pVBuffer10)
pVBuffer10->Map(reinterpret_cast<void**>(&pRawVertices10), &stRawVertices10)
memcpy_s(pRawVertices10, stRawVertices10, (const void*)&vertices[0], sizeof(SimpleVertex)*24);
pVBuffer10->Unmap();
SAFE_RELEASE(pVBuffer10);
WORD indices[] =
{
....
};
ID3DX10MeshBuffer* pIBuffer10 = NULL;
if(FAILED(mesh->GetIndexBuffer(&pIBuffer10)))
{
MessageBox( NULL, TEXT("Unable to retrieve D3DX10 mesh's index buffer."), TEXT("Error"), MB_OK );
return false;
}
SIZE_T stRawIndices10 = 0;
unsigned __int16* pRawIndices10 = NULL;
if( FAILED( pIBuffer10->Map( reinterpret_cast< void** >( &pRawIndices10 ), &stRawIndices10 ) ) )
{
MessageBox( NULL, TEXT("Unable to Map() D3DX10's index buffer!"), TEXT("Error"), MB_OK );
return false;
}
memcpy_s( pRawIndices10, stRawIndices10, (const void *) &indices[0], 36 * sizeof( unsigned __int16 ) );
pIBuffer10->Unmap();
SAFE_RELEASE(pIBuffer10);
4. 속성버퍼를 편리하게 생성하기 위해 속성버퍼에 대응하는 정보를 가지는 속성표를 만든다.
DWORD dwInputTableSize = numSubsets;
D3DX10_ATTRIBUTE_RANGE* pNewAttrTable = new D3DX10_ATTRIBUTE_RANGE[dwInputTableSize];
for(DWORD i=0; i<dwInputTableSize; i++)
{
pNewAttrTable[i].AttribId = i; // 속성 ID
pNewAttrTable[i].FaceStart = i*4; // 현재 서브셋에 속한 삼각형들의 시작 삼각형에 대한 인덱스 버퍼에서의 오프셋
pNewAttrTable[i].FaceCount = 4; // 서브셋 내의 삼각형 갯수
pNewAttrTable[i].VertexStart = i*8; // 서현재 서브셋과 연결된 정점들의 시작 정덤에 대한 정점버퍼에서의 오프셋
pNewAttrTable[i].VertexCount = 8; // 현재 서브셋 내의 정점의 갯수
}
// 속성표로부터 속성버퍼를 만든다.
hr = mesh->SetAttributeTable(pNewAttrTable, static_cast<UINT>(dwInputTableSize));
hr = mesh->GenerateAttributeBufferFromTable();
5. 선택적으로 메시의 인접정보를 생성하고 최적화를 수행한다.
esh->GenerateAdjacencyAndPointReps(0.0f)
mesh->Optimize(D3DX10_MESHOPT_COMPACT | D3DX10_MESHOPT_ATTR_SORT | D3DX10_MESHOPT_VERTEX_CACHE, NULL, NULL)
6. 텍스쳐 로드
WCHAR* textureFilenames[numSubsets] = { L"brick0.jpg", L"brick1.jpg", L"brick2.jpg" };
materials = new Material10[numSubsets];
for (int i=0; i<numSubsets; i++)
{
materials[i].ambient=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].diffuse=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].specular=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].emissive=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].sharpness=10.0f;
7. 텍스처를 로드한다.
WCHAR* textureFilenames[numSubsets] = { L"brick0.jpg", L"brick1.jpg", L"brick2.jpg" };
materials = new Material10[numSubsets];
for (int i=0; i<numSubsets; i++)
{
materials[i].ambient=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].diffuse=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].specular=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].emissive=D3DXVECTOR4(1,1,1,1); //RGBA
materials[i].sharpness=10.0f;
// 텍스처를 로드한다.
hr = D3DX10CreateShaderResourceViewFromFile(pkDevice, textureFilenames[i], NULL, NULL, &materials[i].tex, NULL);
}
8. mesh를 장치에 제출. - 메시데이터 수정시 다시 제출해야 한다.
mesh->CommitToDevice();
.fx
fx에서는 그다지 볼게 없다.
텍스쳐 처리를 위해 추가된 부분만을 보면 된다.
Texture2D texDiffuse;
RasterizerState Culling {
FillMode = SOLID; // WIREFRAME이면 와이어 프레임
CullMode = BACK;
FrontCounterClockwise = false; // dx에서 사용하는 시계반대방향.
};
SamplerState samLinear {
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
float4 PS( PS_INPUT input ) : SV_Target
{
float fLighting = saturate( dot( input.normal, vLightDir ) );
float4 cAmbient = float4(0.3f, 0.3f, 0.3f, 1.0f);
fLighting += cAmbient;
float4 cDiffuse = texDiffuse.Sample( samLinear, input.tex ) * fLighting;
cDiffuse.a = 1;
return cDiffuse;
}
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
SetRasterizerState( Culling );
}
}
'Study > Directx 10' 카테고리의 다른 글
경계볼륨 - 경계구, 경계상자 (0) | 2010.05.11 |
---|---|
3ds mesh file load (0) | 2010.05.11 |
3ds 로드, 가상트랙볼 (0) | 2010.05.09 |
카메라 클래스 - 쿼터니온 (5) | 2010.05.08 |
카메라 클래스 - 오일러 (0) | 2010.05.07 |