http://www.mystic24.com/zboard/data/idle/Q.zip

실행결과는 그냥 거멓게 나옵니다.

무엇이 문제일지.. 참으로 알수가 없게 되버렸다는...

다음은 소스 내용입니다. 텍스처인 banana.bmp는 Q.zip안에 있어요.
진하게 된 부분이 원래 텍스처 예제에서 추가만 시킨겁니다.
어디서 문제가 있었을까요??


/**-------------------------------------------------------------------------------
*        brief 텍스쳐 맵핑
*        파일 : textures.cpp
*
* 설명:        3차원 오브젝트는 텍스처와 결합 될 때 더욱 현실감 있게 된다. 텍스처란 마치
*                벽지 같은 것으로, 적당하게 늘이거나 줄여서 면에 붙이게 된다. 일반적으로
*                텍스처는 이미지 파일(JPG, BMP, TGA 등)을 D3DX 계열의 함수를
*                사용하여 읽어들인 후 사용하게 된다. 정정 버퍼와 마찬가지로 Lock(),
*                Unlock() 함수를 사용하여 메모리에 직접 접근할 수도 있다. 이렇게 생성한
*                텍스처를 면에 붙이는 행위를 텍스처 맵핑이라고 한다.
*
*                텍스처는 기하 정보와 연결되기 위해서 텍스처 좌표계를 갖게 되는데, 각각의
*                정점은 이러한 텍스처 좌표를 포함하고 있어야 한다. 일반적으로는 (u, v)
*                좌표계를 사용하고 u, v의 값은 0.0 ~ 1.0 사이의 값이다. 텍스처 좌표는
*                최초에 설정될 수도 있지만, 실시간으로 직접 계산하여 더 다양한 효과를 낼
*                수도 있다.(mirror, sphere 맵핑 등).
*------------------------------------------------------------------------------*/
#include <windows.h>
#include <mmsystem.h>
#include <d3dx9.h>

/// SHOW_HOW_TO_USE_TCI 가 선언된 것과 선언되지 않은 것의 컴파일 결과를 반드시 비교해 보자.
/// #define SHOW_HOW_TO_USE_TCI

/// 전역변수
LPDIRECT3D9                                g_pD3D                        = NULL;        /// D3D 디바이스를 생성할 D3D 객체 변수
LPDIRECT3DDEVICE9                g_pd3dDevice        = NULL;        /// 랜더링에 사용될 D3D 디바이스
LPDIRECT3DVERTEXBUFFER9        g_pVB                        = NULL;        /// 정점을 보관할 정점버퍼
LPDIRECT3DTEXTURE9                g_pTexture                = NULL;        /// 텍스처 정보

/// 사용자 정점을 정의할 구조체
/// 텍스처 좌표가 추가되었다는 것을 알 수 있다.

struct CUSTOMVERTEX
{
        D3DXVECTOR3 position;        /// 3차원 좌표
        D3DCOLOR        color;                /// 색깔
#ifndef SHOW_HOW_TO_USE_TCI
        FLOAT tu, tv;                        /// 텍스처 좌표
#endif
};

/// 사용자 정점 구조체에 관한 정보를 나타내는 FVF 값
#ifdef SHOW_HOW_TO_USE_TCI
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE)
#else
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
#endif

/// Direct3D 초기화
HRESULT InitD3D(HWND hWnd)
{
        /// 디바이스를 생성하기 위한 D3D 객체 생성
        if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
                return E_FAIL;

        /// 디바이스를 생성할 구조체
        /// 복잡한 오브젝트를 그릴 것이므로 이 번에는 Z 버퍼가 필요하다.
        D3DPRESENT_PARAMETERS d3dpp;
        ZeroMemory(&d3dpp, sizeof(d3dpp));
        d3dpp.Windowed = TRUE;
        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
        d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
        d3dpp.EnableAutoDepthStencil = TRUE;
        d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

        /// 디바이스 생성
        if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice)))
        {
                return E_FAIL;
        }

        /// 컬렁 기능을 끈다.
        g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
        
        /// 조명 기능을 끈다
        g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

        /// Z 버퍼 기능을 켠다.
        g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);

        return S_OK;
}

/// 기하정보 초기화
/// 정점 버퍼와 텍스처 생성
HRESULT InitGeometry()
{
        /// D3DX 계열 함수를 사용하여 파일로부터 텍스처 생성(banana.bmp)
        if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, "banana.bmp", &g_pTexture)))
        {
                /// 현재 폴더에 파일이 없으면 상위 폴더 검색
                if(FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, "..banana.bmp", &g_pTexture)))
                {
                        /// 텍스처 생성 실패
                        MessageBox(NULL, "Could not find banana.bmp", "Textures.exe", MB_OK);
                        return E_FAIL;
                }
        }

        /// 정점 버퍼 생성
        if(FAILED(g_pd3dDevice->CreateVertexBuffer(50*2*sizeof(CUSTOMVERTEX),
                0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL)))
        {
                return E_FAIL;
        }

        /// 정점 버퍼를 값으로 채운다
        /// 텍스처의 u, v 좌표값을 0.0 ~ 1.0 사이의 값으로 채워넣고 있다.
        CUSTOMVERTEX *pVertices;
        if(FAILED(g_pVB->Lock(0, 0, (void **)&pVertices, 0)))
                return E_FAIL;
        for(DWORD i=0; i<50; ++i)
        {
                FLOAT theta = (2*D3DX_PI*i)/(50-1);

                pVertices[2*i+0].position = D3DXVECTOR3(sinf(theta), -1.0f, cosf(theta));
                pVertices[2*i+0].color = 0xffffffff;
#ifndef SHOW_HOW_TO_USE_TCI
                /// SHOW_HOW_TO_USE_TCI가 선언되어 있으면 텍스처 좌표를 생성하지 않는다.
                pVertices[2*i+0].tu = ((FLOAT)i)/(50-1);        /// 텍스처의 u좌표 0/49, 1/49, 2/49 ... 49/49 (즉 0.0 ~ 1.0)
                pVertices[2*i+0].tv = 1.0f;                                        /// 텍스처의 v좌표 1.0
#endif

                pVertices[2*i+1].position = D3DXVECTOR3(sinf(theta), 1.0f, cosf(theta));
                pVertices[2*i+1].color = 0xff808080;
#ifndef SHOW_HOW_TO_USE_TCI
                /// SHOW_HOW_TO_USE_TCI가 선언도어 있으면 텍스처 좌표를 생성하지 않는다.
                pVertices[2*i+1].tu = ((FLOAT)i)/(50-1);        /// 텍스처의 u좌표 0/49, 1/49, 2/49 ... 49/49 (즉 0.0 ~ 1.0)
                pVertices[2*i+1].tv = 0.0f;                                        /// 텍스처의 v좌표 0.0
#endif
        }
        g_pVB->Unlock();

        return S_OK;
}

/// 광원 설정
VOID SetupLights()
{
        /// 재질 설정
        /// 재질은 디바이스에 단 하나만 설정될 수 있다.
        D3DMATERIAL9 mtrl;
        ZeroMemory(&mtrl, sizeof(D3DMATERIAL9));
        mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
        mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
        mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
        mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
        g_pd3dDevice->SetMaterial(&mtrl);

        /// 광원 설정
        D3DXVECTOR3 vecDir;
        /// 방향성 광원(directional light)이 향할 빛의 방향
        D3DLIGHT9 light;
        /// 광원 구조체
        ZeroMemory(&light, sizeof(D3DLIGHT9));        /// 구조체를 0으로 지운다
        light.Type = D3DLIGHT_DIRECTIONAL;                /// 광원의 종류(점 광원, 방향성 광원, 점적 광원)
        light.Diffuse.r = 1.0f;
        light.Diffuse.g = 1.0f;
        light.Diffuse.b = 1.0f;
        vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f), 1.0f, sinf(timeGetTime()/350.0f));        /// 광원의 방향
        D3DXVec3Normalize((D3DXVECTOR3 *)&light.Direction, &vecDir);        /// 광원의 방향을 단위 벡터로 만든다.
        light.Range = 1000.0f;        /// 광원이 다다를 수 있는 최대 거리
        g_pd3dDevice->SetLight(0, &light);        /// 디바이스에 0번 광원 설치
        g_pd3dDevice->LightEnable(0, TRUE);        /// 0번 광원을 켠다
        g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);        /// 광원 설정을 켠다

        g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0x00202020);        /// 환경 광원(ambient light)의 값 설정
}

/// 초기화된 객체들 소거
VOID Cleanup()
{
        if(g_pTexture != NULL)
                g_pTexture->Release();

        if(g_pVB != NULL)
                g_pVB->Release();

        if(g_pd3dDevice != NULL)
                g_pd3dDevice->Release();

        if(g_pD3D != NULL)
                g_pD3D->Release();
}

/// 행렬설정
VOID SetupMatrices()
{
        /// 월드 행렬
        D3DXMATRIXA16 matWorld;
        D3DXMatrixIdentity(&matWorld);
        D3DXMatrixRotationX(&matWorld, timeGetTime()/1000.0f);
        g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);

        /// 뷰 행렬 설정
        D3DXVECTOR3 vEyePt(0.0f, 3.0f, -5.0f);
        D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
        D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
        D3DXMATRIXA16 matView;
        D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
        g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);

        /// 프로젝션 행렬 설정
        D3DXMATRIXA16 matProj;
        D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f);
        g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}

/// 화면 그리기
VOID Render()
{
        /// 후면 버퍼와 Z 버퍼를 지운다.
        g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

        /// 랜더링 시작
        if(SUCCEEDED(g_pd3dDevice->BeginScene()))
        {

                /// 광원과 재질 설정
                SetupLights();


                /// 월드, 뷰, 프로젝션 행렬을 설정한다.
                SetupMatrices();

                /// 생성한 텍스처를 0번 텍스처 스테이지에 올린다.
                /// 텍스처 스테이지는 여러 장의 텍스처와 색깔 정보를 섞어서 출력할 때 사용된다
                /// 여기서는 텍스처의 색깔과 정점의 색깔 정보를 modulate 연산으로 섞어서 출력한다.
                g_pd3dDevice->SetTexture(0, g_pTexture);        /// 0번 스테이지에 텍스처 고정
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);        /// MODULATE 연산으로 색깔을 섞음
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);        /// 첫번째 섞을 색은 텍스처 색
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);        /// 두번째 섞을 색은 정점 색
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);        /// alpha 연산은 사용하지 않음

#ifdef SHOW_HOW_TO_USE_TCI
                /// D3D의 텍스처 좌표 생성 기능을 사용하는 예를 보여준다.
                /// 여기서는 카메라 좌표계에서의 정점 정보를 이용하여 텍스처 좌표를 생성한다.
                /// 4x4 크기의 텍스처 변환 행렬을 텍스처 좌표 인덱스(TCI = Texture Coord Index) 전달 인자를
                /// 사용하여 x, y, z TCI 좌표를 u, v 텍스처 좌표로 변환한다.

                /// 사용한 것은 단순히 (-1.0 ~ +1.0) 값을 (0.0 ~ 1.0) 사이의 값으로 변환하는 행렬이다
                /// 월드, 뷰, 프로젝션 변환을 거친 정점은 (-1.0 ~ +1.0) 사이의 값을 갖게 된다.
                /// tu = 0.5x + 0.5
                /// tv = -0.5y + 0.5
                D3DXMATRIXA16 mat;
                mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;
                mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;
                mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;
                mat._41 = 0.50f; mat._42 = 0.50f; mat._42 = 0.00f; mat._44 = 1.00f;

                g_pd3dDevice->SetTransform(D3DTS_TEXTURE0, &mat);        /// 텍스처 변환 행렬
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);        /// 2차원 텍스처 사용
                g_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);        /// 카메라 좌표계 변환
#endif

                /// 정점 버퍼의 내용을 그린다.
                g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
                g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
                g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2*50-2);

                /// 랜더링 종료
                g_pd3dDevice->EndScene();
        }

        /// 후면 버퍼를 보이는 화면으로
        g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}


/// 윈도우 프로시저
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
        switch(msg)
        {
        case WM_DESTROY:
                Cleanup();
                PostQuitMessage(0);
                return 0;
        }

        return DefWindowProc(hWnd, msg, wParam, lParam);
}

/// 프로그램 시작점
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
        /// 윈도우 클래스 등록
        WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                "D3D Tutorial", NULL };
        RegisterClassEx(&wc);

        /// 윈도우 생성
        HWND hWnd = CreateWindow("D3D Tutorial", "D3D Tutorial 05: Textures",
                WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                GetDesktopWindow(), NULL, wc.hInstance, NULL);

        /// Direct3D 초기화
        if(SUCCEEDED(InitD3D(hWnd)))
        {
                /// 기하 정보 초기화
                if(SUCCEEDED(InitGeometry()))
                {
                        /// 윈도우 출력
                        ShowWindow(hWnd, SW_SHOWDEFAULT);
                        UpdateWindow(hWnd);

                        /// 메시지 루프
                        MSG msg;
                        ZeroMemory(&msg, sizeof(msg));
                        while(msg.message != WM_QUIT)
                        {
                                if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
                                {
                                        TranslateMessage(&msg);
                                        DispatchMessage(&msg);
                                }
                                else
                                        Render();
                        }
                }
        }

        UnregisterClass("D3D Tutorial", wc.hInstance);
        return 0;
}