void Graphics::setBlendingMode(BlendingOperation source, BlendingOperation destination) { device->SetRenderState(D3DRS_SRCBLEND, convert(source)); device->SetRenderState(D3DRS_DESTBLEND, convert(destination)); }
////////////////////////////////////////////////////////////////////////// // 버텍스 버퍼 생성 // // CreateVertexBuffer() 함수를 이용해 만들어진 버텍스 버퍼는 위치가 고정되어 있지 않다. // 사용 할 때에는 반드시 Lock()으로 주소를 얻어 온 후, 버퍼에 내용을 써 넣고 Unlock() 해야 한다. // // 버텍스 버퍼나 인덱스 버퍼는 기본 시스템 메모리 외에도 디바이스 메모리(그래픽 카드 메모리)에 생성 될 수 있다. // 대부분의 그래픽 카드에서는 이렇게 할 경우 속도가 매우 향상 된다. ////////////////////////////////////////////////////////////////////////// HRESULT InitVB() { // 삼각형을 렌더링 하기 위해 세 개의 버텍스 선언 CUSTOMVERTEX vertices[] = { { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, }; // 버텍스 버퍼 생성 // 3개의 사용자 버텍스를 보관할 메모리를 할당 // FVF를 지정하여 버텍스의 형식을 지정한다 if ( FAILED( g_pd3dDevice->CreateVertexBuffer( // 생성 할 버텍스 버퍼의 바이트 단위 크기 3 * sizeof( CUSTOMVERTEX ), // 버텍스 버퍼 종류, 처리 방식(SW, HW) 지정 0, // 커스텀 버텍스 구조체 FVF 플래그 값 D3DFVF_CUSTOMVERTEX, // 버텍스 버퍼가 저장 될 메모리의 위치(그래픽 카드, 시스템 메모리)와 관리 방식 D3DPOOL_DEFAULT, // 리턴 받을 버텍스 버퍼 변수 &g_pVB, // 예약 되었음 NULL ) ) ) { return E_FAIL; } // 버텍스 버퍼를 값으로 채운다. // 버텍스 버퍼의 Lock()함수를 호출하여 포인터를 가져온다. VOID* pVertices; if ( FAILED( g_pVB->Lock( // Lock 버퍼 시작점 // 다음 인자와 함께 모두 0이면 전체 버퍼 0, // Lock을 할 버퍼 크기 // 이전 인자와 함께 모두 0이면 전체 버퍼 sizeof( vertices ), // Lock으로 받아오는 메모리 영역의 포인터를 담을 변수 (void**)&pVertices, // Lock을 수행할 때 함께 사용할 플래그 0 ) ) ) { return E_FAIL; } memcpy( pVertices, vertices, sizeof( vertices ) ); // 반드시 Unlock 해야 한다. Unlock을 하지 않을 경우 그래픽카드가 다운 될 수 있음! - 교재에서 // // 교수님 말씀에 따르면 실제 해 봐도 다운이 되지 않는다고 함 g_pVB->Unlock(); return S_OK; }
//------------------------------------------------------------- // ȭ�鷻�� //------------------------------------------------------------- void CBigSquare::Render( LPDIRECT3DDEVICE9 pd3dDevice ) { pd3dDevice->SetFVF( FVF ); pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(SHADOWVERTEX)); pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 ); }
// `使用Direct3D9來繪圖` void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); // `消除畫面` device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); // `開始下繪圖指令` device->BeginScene(); // `設定資料格式` device->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL); // `套用shader` device->SetVertexShader(g_pSelected_VS); device->SetPixelShader(g_pVertexColor_PS); // `設定光源` SetupLightingDX9(); // `設定轉換矩陣` Matrix4x4 world_view_proj_matrix = g_world_matrix * g_view_proj_matrix; device->SetVertexShaderConstantF(0, &world_view_proj_matrix[0][0], 4); device->SetVertexShaderConstantF(4, &g_world_matrix[0][0], 4); // `鏡頭位置, 計算Specular會用到.` device->SetVertexShaderConstantF(8, &g_eye[0], 1); // `畫出格子` device->DrawIndexedPrimitiveUP(D3DPT_TRIANGLESTRIP, 0, g_iNumGridVertices, g_iNumGridTriangles, g_pGridIndices, D3DFMT_INDEX16, g_pGridVertices, sizeof(Vertex_V3N3) ); // `宣告所有的繪圖指令都下完了` device->EndScene(); // `把背景backbuffer的畫面呈現出來` device->Present( NULL, NULL, NULL, NULL ); }
ID3D11Texture2D * #endif TextureGPU::gfxLoadDDSTexture(char *filename, bool genMips /*= true*/) { DDS::DDSTextureInSystemMemory dds; uint32_t test = loadDDSIntoSystemMemory(filename,&dds); if(test==false) { printf("failed to load\n"); exit(0); } bool haveMips = dds.mips > 1; bool needToGenerateMips = !haveMips && genMips; bool willHaveMips = haveMips || genMips; if (false) { int32_t w = dds.width; int32_t h = dds.height; for (uint32_t i = 0; i < dds.mips; i++) { unsigned char r = i % 3 ? 0x00 : 0xFF; unsigned char g = (i+2) % 3 ? 0x00 : 0xFF; unsigned char b = (i+1) % 3 ? 0x00 : 0xFF; if (dds.uncompressedFormat && dds.components == 4) { unsigned char *data = dds.image[0].pixels[i]; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { unsigned char solid = ((x % 8) > 3) ^ ((y % 8) > 3); *data++ = b * solid; *data++ = g * solid; *data++ = r * solid; *data++ = 0; } } // we use componets == 3 becasue on IOS we dont have GL_BGR flag at all. event to use is as temp variable for storing dds format if (dds.uncompressedFormat && dds.components == 3) { unsigned char *data = dds.image[0].pixels[i]; for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { *data++ = r; *data++ = g; *data++ = b; } } w/=2; h/=2; if (w == 0) w = 1; if (h == 0) h = 1; } } assert(m_samplerState != SamplerState_INVALID); SamplerState &ss = SamplerStateManager::getInstance()->getSamplerState(m_samplerState); if (willHaveMips) { //check that we want t use existing mips if (!ss.needsMipMaps()) { PEWARN("Mipmap filtering is disabled while mipams exist and are loaded. Texture: %s", filename); } } else { //check that we dont want a value that assumes mip map existance if (ss.needsMipMaps()) { PEWARN("Trying to enable mip map filtering when no mipmaps exist. Texture: %s", filename); } } int32_t w = dds.width; int32_t h = dds.height; #if APIABSTRACTION_D3D9 D3D9Renderer *pD3D9Renderer = static_cast<D3D9Renderer *>(m_pContext->getGPUScreen()); LPDIRECT3DDEVICE9 pDevice = pD3D9Renderer->m_pD3D9Device; //choose api format best suited for loaded texture D3DFORMAT destApiFormat = D3DFMT_UNKNOWN; if (dds.compressedFormat) { assert(!"Dont support compressed textures yet!"); } else { if (dds.components == 1) { if (dds.uncompressedFormat == DDSF_L) destApiFormat = D3DFMT_L8; else assert(!"Unknown format!"); } else if (dds.components == 3) { assert(!"Need to add support for this format!"); } else if (dds.components == 4) { if (dds.uncompressedFormat == DDSF_RGBA) destApiFormat = D3DFMT_A8R8G8B8; else if (dds.uncompressedFormat == DDSF_RGB) destApiFormat = D3DFMT_X8R8G8B8; } else { assert(!"Unknown texture format!"); } } if (!destApiFormat) return NULL; IDirect3DTexture9 * pTexture = NULL; pDevice->CreateTexture( dds.width, dds.height, /*Levels = 0 - generate space for all mips, otherwise use provided number*/ haveMips ? 0 : 1, // if we have source mipmaps set to 0 (will have mips) otherwise set to 1 becasue mips will be generated on gpu memory texture) 0, // potentially could use D3DUSAGE_AUTOGENMIPMAP on a gpu texture, not on SYSTEMMEM, destApiFormat, D3DPOOL_SYSTEMMEM, // set it to sys mem to be able to set pixels // D3DPOOL_DEFAULT, &pTexture, // result NULL); // set to null printf("file %s dds surfaces %d mips %d w %d h %d \n",filename,dds.surfaces,dds.mips,w,h); if(dds.surfaces!=1) //its a cube map { printf("ERROR: this is a cubemap\n"); exit(0); } if(dds.compressedFormat == FOURCC_DXT1) printf("FOURCC_DXT1\n"); if(dds.compressedFormat == FOURCC_DXT3) printf("FOURCC_DXT3\n"); if(dds.compressedFormat == FOURCC_DXT5) printf("FOURCC_DXT5\n"); D3DFORMAT destGpuFormatEnum = (D3DFORMAT)(DDS::getDestGPUFormatFromComponents(dds.components)); D3DFORMAT sourceCpuFormatEnum = (D3DFORMAT)(DDS::getSourceCPUFormatFromComponents(dds.components)); //load a compressed texture if(dds.compressedFormat) { assert(!"Compressed textures are not yet supported!"); } else // load a non compressed texture { for (uint32_t i = 0; i < dds.mips; i++) { IDirect3DSurface9 *pSurface = NULL; HRESULT hr = pTexture->GetSurfaceLevel(i, &pSurface); assert(SUCCEEDED(hr)); D3DLOCKED_RECT lockedRect; hr = pSurface->LockRect(&lockedRect, NULL, 0); assert(SUCCEEDED(hr)); unsigned char *data = dds.image[0].pixels[i]; char *destData = (char*)(lockedRect.pBits); for (int y = 0; y < h; y++) { memcpy(&destData[lockedRect.Pitch * y], &data[dds.components * w * y], dds.components * w); } hr = pSurface->UnlockRect(); assert(SUCCEEDED(hr)); w/=2; h/=2; if (w == 0) w = 1; if (h == 0) h = 1; } //restore to default } free(dds.buffer); // at this point the file buffer is no longer needed int d3dUsage = 0; #if PE_PLAT_IS_XBOX360 if (needToGenerateMips) PEWARN("On XBOX 360 we can't autogen mipmaps!\n"); #else d3dUsage = needToGenerateMips ? D3DUSAGE_AUTOGENMIPMAP: 0; // potentially could use D3DUSAGE_AUTOGENMIPMAP, but we do not want to support it now, since we only support mipmaps that are in dds already #endif //create GPU texture that wills tore the data IDirect3DTexture9 *pDestTexture = NULL; pDevice->CreateTexture( dds.width, dds.height, willHaveMips ? 0 : 1, // 0: will create mipmap surfaces too d3dUsage, destApiFormat, D3DPOOL_DEFAULT, &pDestTexture, // result NULL); // set to null #if PE_PLAT_IS_XBOX360 PEASSERT(false, "Right now we load textures on xbox360 trhough helper in d3dx. Need some reasearch to see how to load it ourselves from raw data and update the texture"); #else pDevice->UpdateTexture(pTexture, pDestTexture); #endif pTexture->Release(); // release sys memory texture return pDestTexture; // return the texture name #else //choose api format best suited for loaded texture DXGI_FORMAT destApiFormat = DXGI_FORMAT_UNKNOWN; if (dds.compressedFormat) { assert(!"Dont support compressed textures yet!"); } else { if (dds.components == 1) { if (dds.uncompressedFormat == DDSF_L) destApiFormat = DXGI_FORMAT_R8_UNORM; else assert(!"Unknown format!"); } else if (dds.components == 3) { assert(!"Need to add support for this format!"); } else if (dds.components == 4) { if (dds.uncompressedFormat == DDSF_RGBA) destApiFormat = DXGI_FORMAT_B8G8R8A8_UNORM; else if (dds.uncompressedFormat == DDSF_RGB) destApiFormat = DXGI_FORMAT_B8G8R8X8_UNORM; } else { assert(!"Unknown texture format!"); } } if (!destApiFormat) return NULL; ID3D11Texture2D* pTexture = NULL; D3D11_TEXTURE2D_DESC desc; desc.Width = dds.width; desc.Height = dds.height; desc.MipLevels = willHaveMips ? 0 : 1; desc.ArraySize = 1; desc.Format = destApiFormat; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_IMMUTABLE; // immutable since data wont change desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA datas[32]; //in case mips are already loaded (and not generated) we need to pass in array of the datas for (uint32_t i = 0; i < dds.mips; i++) { D3D11_SUBRESOURCE_DATA &data = datas[i]; data.pSysMem = dds.image[0].pixels[/*mip=*/i]; data.SysMemPitch = dds.components * w; data.SysMemSlicePitch = 0; // unused since 2d texture w/=2; h/=2; if (w == 0) w = 1; if (h == 0) h = 1; } D3D11Renderer *pD3D11Renderer = static_cast<D3D11Renderer *>(m_pContext->getGPUScreen()); ID3D11Device *pDevice = pD3D11Renderer->m_pD3DDevice; ID3D11DeviceContext *pDeviceContext = pD3D11Renderer->m_pD3DContext; pDevice->CreateTexture2D( &desc, datas, &pTexture); return pTexture; #endif }
/* =============== */ virtual void leave () { m_devcs->EndScene(); }
bool ReadModelFile( const string &fileName, LPDIRECT3DVERTEXBUFFER9 &vtxBuff, int &vtxSize, LPDIRECT3DINDEXBUFFER9 &idxBuff, int &faceSize ) { using namespace std; ifstream fin(fileName.c_str()); if (!fin.is_open()) return false; string vtx, vtx_eq; int numVertices; fin >> vtx >> vtx_eq >> numVertices; if (numVertices <= 0) return false; vtxSize = numVertices; // 버텍스 버퍼 생성. if (FAILED(g_pDevice->CreateVertexBuffer( numVertices * sizeof(Vertex), D3DUSAGE_WRITEONLY, Vertex::FVF, D3DPOOL_MANAGED, &vtxBuff, NULL))) { return false; } // 버텍스 버퍼 초기화. Vertex* vertices; if (FAILED(vtxBuff->Lock( 0, sizeof(Vertex), (void**)&vertices, 0))) return false; float num1, num2, num3; for (int i = 0; i < numVertices; i++) { fin >> num1 >> num2 >> num3; vertices[i] = Vertex(num1, num2, num3); } vtxBuff->Unlock(); string norm, norm_eq; int numNormal; fin >> norm >> norm_eq >> numNormal; if (numNormal <= 0) return false; if (FAILED(vtxBuff->Lock( 0, sizeof(Vertex), (void**)&vertices, 0))) return false; for (int i = 0; i < numVertices; i++) { fin >> num1 >> num2 >> num3; vertices[i].n = Vector3(num1, num2, num3); } vtxBuff->Unlock(); string idx, idx_eq; int numIndices; fin >> idx >> idx_eq >> numIndices; if (numIndices <= 0) return false; faceSize = numIndices; if (FAILED(g_pDevice->CreateIndexBuffer(numIndices*3*sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &idxBuff, NULL))) { return false; } WORD *indices = NULL; idxBuff->Lock(0, 0, (void**)&indices, 0); int num4, num5, num6; for (int i = 0; i < numIndices*3; i+=3) { fin >> num4 >> num5 >> num6; indices[ i] = num4; indices[ i+1] = num5; indices[ i+2] = num6; } idxBuff->Unlock(); //ComputeNormals(vtxBuff, vtxSize, idxBuff, faceSize); return true; }
int RGetApproxVMem() { if(g_pd3dDevice==0) return 0; return g_pd3dDevice->GetAvailableTextureMem()*0.5f;}
/* =============== */ virtual void enter () { m_devcs->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); m_devcs->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); m_devcs->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); }
bool InitVertexBuffer() { HRESULT hr; ID3DXBuffer *adjBuff = NULL; ID3DXBuffer *mtrlBuff = NULL; DWORD numMtrls = 0; // 메쉬 정보 로드 hr = D3DXLoadMeshFromXA( "../../media/bigship1.x", D3DXMESH_MANAGED, g_pDevice, &adjBuff, &mtrlBuff, 0, &numMtrls, &g_pMesh ); if (FAILED(hr)) return false; ///////////////////////////////////////////////////////////////////////////// // 매터리얼 설정 if( mtrlBuff && numMtrls > 0 ) { D3DXMATERIAL *mtrls = (D3DXMATERIAL*)mtrlBuff->GetBufferPointer(); for( int i=0; i < (int)numMtrls; ++i ) { mtrls[ i].MatD3D.Ambient = mtrls[ i].MatD3D.Diffuse; g_Mtrls.push_back( mtrls[ i].MatD3D ); if( mtrls[ i].pTextureFilename ) { IDirect3DTexture9 *tex = NULL; string filePath = "../../media/"; filePath += mtrls[ i].pTextureFilename; D3DXCreateTextureFromFileA( g_pDevice, filePath.c_str(), &tex ); g_Texture.push_back( tex ); } else { g_Texture.push_back( 0 ); } } } mtrlBuff->Release(); // 메쉬 최적화 hr = g_pMesh->OptimizeInplace( D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, (DWORD*)adjBuff->GetBufferPointer(), (DWORD*)adjBuff->GetBufferPointer(), 0, 0 ); if (FAILED(hr)) return false; // 프로그레시브 메쉬 생성. hr = D3DXGeneratePMesh(g_pMesh, (DWORD*)adjBuff->GetBufferPointer(), 0, 0, 1, D3DXMESHSIMP_FACE, &g_pPMesh ); g_pMesh->Release(); g_pMesh = NULL; adjBuff->Release(); if (FAILED(hr)) return false; //DWORD maxFaces = g_pPMesh->GetMaxFaces(); //g_pPMesh->SetNumFaces( maxFaces ); D3DXCOLOR color(1,1,1,1); ZeroMemory(&g_Light, sizeof(g_Light)); g_Light.Type = D3DLIGHT_DIRECTIONAL; g_Light.Ambient = color * 0.4f; g_Light.Diffuse = color; g_Light.Specular = color * 0.6f; g_Light.Direction = *(D3DXVECTOR3*)&Vector3(0,-1,0); Matrix44 V; Vector3 camPos(0,0,-20); Vector3 lookAtPos(0,0,0); Vector3 dir = lookAtPos - camPos; dir.Normalize(); V.SetView(camPos, dir, Vector3(0,1,0)); g_pDevice->SetTransform(D3DTS_VIEW, (D3DXMATRIX*)&V); Matrix44 proj; proj.SetProjection(D3DX_PI * 0.5f, (float)WINSIZE_X / (float) WINSIZE_Y, 1.f, 1000.0f) ; g_pDevice->SetTransform(D3DTS_PROJECTION, (D3DXMATRIX*)&proj) ; g_pDevice->SetLight(0, &g_Light); // 광원 설정. g_pDevice->LightEnable( 0, // 활성화/ 비활성화 하려는 광원 리스트 내의 요소 true); // true = 활성화 , false = 비활성화 g_pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true); g_pDevice->SetRenderState(D3DRS_SPECULARENABLE, true); return true; }
// @brief : 描画が無効のときの挙動 //-------------------------------------------------------------------- void DirectionalLightDx9::OnDisable( void ) { LPDIRECT3DDEVICE9 device = DirectX9::Instance().Device; device->LightEnable(m_Index,FALSE); }
void clsDXDevice::CreateBackBuffer(LPDIRECT3DDEVICE9 ldd) { ldd->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&backbuffer); }
void DrawBillboard() { // 알파채널을 사용해서 투명텍스처 효과를 낸다 g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 ); g_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); struct MYVERTEX { enum { FVF = D3DFVF_XYZ | D3DFVF_TEX1 }; float px, py, pz; float tu, tv; }; // 빌보드 정점 MYVERTEX vtx[4] = { { -1, 0, 0, 0, 1 }, { -1, 4, 0, 0, 0 }, { 1, 0, 0, 1, 1 }, { 1, 4, 0, 1, 0 } }; D3DXMATRIXA16 matBillboard; D3DXMatrixIdentity( &matBillboard ); // 0번 텍스처에 빌보드 텍스처를 올린다 g_pd3dDevice->SetTexture( 1, NULL ); g_pd3dDevice->SetFVF( MYVERTEX::FVF ); if ( g_bBillboard ) { // Y축 회전행렬은 _11, _13, _31, _33번 행렬에 회전값이 들어간다 // 카메라의 Y축 회전행렬값을 읽어서 역행렬을 만들면 X,Z축이 고정된 // Y축 회전 빌보드 행렬을 만들수 있다 matBillboard._11 = g_pCamera->GetViewMatrix()->_11; matBillboard._13 = g_pCamera->GetViewMatrix()->_13; matBillboard._31 = g_pCamera->GetViewMatrix()->_31; matBillboard._33 = g_pCamera->GetViewMatrix()->_33; D3DXMatrixInverse( &matBillboard, NULL, &matBillboard ); } // 빌보드의 좌표를 바꿔가며 찍는다 for ( int z = 0; z <= 40; z += 5 ) { for ( int x = 0; x <= 40; x += 5 ) { matBillboard._41 = static_cast<float>( x - 20 ); matBillboard._42 = 0; matBillboard._43 = static_cast<float>( z - 20 ); g_pd3dDevice->SetTexture( 0, g_pTexBillboard[( x + z ) % 4] ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matBillboard ); g_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, vtx, sizeof( MYVERTEX ) ); } } g_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &g_matWorld ); }
//============================================================================= // 描画処理 //============================================================================= void DrawModel(LPDIRECT3DDEVICE9 pDevice) { //LPDIRECT3DDEVICE9 pDevice = GetDevice(); D3DXMATERIAL * pD3DXMat; D3DMATERIAL9 matDef; D3DXMATRIX mtxScale,mtxRot,mtxTrans; pDevice->SetFVF(Player.pD3DXMeshModel->GetFVF()); //ワールドマトリクスの初期化 D3DXMatrixIdentity(&Player.mtxWorld); // Identity:単位○○ //現在のマテリアルを取得 pDevice->GetMaterial(&matDef); // スケールを反映 D3DXMatrixScaling( &mtxScale, //格納先 Player.scaleModel.x, Player.scaleModel.y, Player.scaleModel.z ); D3DXMatrixMultiply( &Player.mtxWorld, //格納先(A*B) &Player.mtxWorld, //A &mtxScale //B ); // 回転を反映 D3DXMatrixRotationYawPitchRoll( &mtxRot, //格納先 Player.rotModel.y, //ヨー(左右) Player.rotModel.x, //ピッチ(前後) Player.rotModel.z //ロール(回転) ); D3DXMatrixMultiply( &Player.mtxWorld, //格納先(A*B) &Player.mtxWorld, //A &mtxRot //B ); // 移動を反映 D3DXMatrixTranslation( &mtxTrans, //格納先 Player.posModel.x, // Player.posModel.y, // Player.posModel.z // ); D3DXMatrixMultiply( &Player.mtxWorld, //格納先(A*B) &Player.mtxWorld, //A &mtxTrans //B ); //ワールドマトリクスの設定 pDevice->SetTransform(D3DTS_WORLD,&Player.mtxWorld); //マテリアル情報に対するポインタを取得 pD3DXMat = (D3DXMATERIAL*)Player.pD3DXBuffMatModel->GetBufferPointer(); for(int nCntMat = 0; nCntMat < (int)Player.nNumMatModel; nCntMat ++){ //マテリアルの設定 pDevice->SetMaterial(&pD3DXMat[nCntMat].MatD3D); //テクスチャの設定 pDevice->SetTexture(0, Player.pMeshTex[nCntMat]); //描画 Player.pD3DXMeshModel->DrawSubset(nCntMat); } //マテリアルを元に戻す pDevice->SetMaterial(&matDef); }
/* =============== */ virtual void leave () { for (uint_t idx = m_enter; idx < m_leave; idx += 3) m_devcs->SetTextureStageState(m_value[idx], (D3DTEXTURESTAGESTATETYPE)m_value[idx + 1], m_value[idx + 2]); }
/* =============== */ virtual void leave () { m_devcs->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE); m_devcs->SetRenderState(D3DRS_LIGHTING, FALSE); }
/* =============== */ virtual void enter () { m_devcs->Clear(0, NULL, m_flags, m_color, 1.0f, 0); m_devcs->BeginScene(); m_devcs->SetTransform(D3DTS_VIEW, &m_main3d->get_tran()->view); }
/* =============== */ virtual void enter () { m_devcs->SetRenderState(D3DRS_SPECULARENABLE, TRUE); }
/* =============== */ virtual void enter () { m_devcs->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); m_devcs->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); }
/* =============== */ virtual void leave () { m_devcs->SetRenderState(D3DRS_SPECULARENABLE, FALSE); }
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { wchar_t className[32] = L"Sample"; wchar_t windowName[32] = L"Sample"; //윈도우 클레스 정보 생성 //내가 이러한 윈도를 만들겠다 라는 정보 WNDCLASS WndClass; WndClass.cbClsExtra = 0; //윈도우에서 사용하는 여분의 메모리설정( 그냥 0 이다 신경쓰지말자 ) WndClass.cbWndExtra = 0; //윈도우에서 사용하는 여분의 메모리설정( 그냥 0 이다 신경쓰지말자 ) WndClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); //윈도우 배경색상 WndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); //윈도우의 커서모양 결정 WndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION ); //윈도우아이콘모양 결정 WndClass.hInstance = hInstance; //프로그램인스턴스핸들 WndClass.lpfnWndProc = (WNDPROC)WndProc; //윈도우 프로시져 함수 포인터 WndClass.lpszMenuName = NULL; //메뉴이름 없으면 NULL WndClass.lpszClassName = className; //지금 작성하고 있는 윈도우 클레스의 이름 WndClass.style = CS_HREDRAW | CS_VREDRAW; //윈도우 그리기 방식 설정 ( 사이즈가 변경될때 화면갱신 CS_HREDRAW | CS_VREDRAW ) //위에서 작성한 윈도우 클레스정보 등록 RegisterClass( &WndClass ); //윈도우 생성 //생성된 윈도우 핸들을 전역변수 g_hWnd 가 받는다. HWND hWnd = CreateWindow( className, //생성되는 윈도우의 클래스이름 windowName, //윈도우 타이틀바에 출력되는 이름 WS_OVERLAPPEDWINDOW, //윈도우 스타일 WS_OVERLAPPEDWINDOW WINPOS_X, //윈도우 시작 위치 X WINPOS_Y, //윈도우 시작 위치 Y WINSIZE_X, //윈도우 가로 크기 ( 작업영역의 크기가 아님 ) WINSIZE_Y, //윈도우 세로 크기 ( 작업영역의 크기가 아님 ) GetDesktopWindow(), //부모 윈도우 핸들 ( 프로그램에서 최상위 윈도우면 NULL 또는 GetDesktopWindow() ) NULL, //메뉴 ID ( 자신의 컨트롤 객체의 윈도우인경우 컨트롤 ID 가 된 hInstance, //이 윈도우가 물릴 프로그램 인스턴스 핸들 NULL //추가 정보 NULL ( 신경끄자 ) ); //윈도우를 정확한 작업영역 크기로 맞춘다 RECT rcClient = { 0, 0, WINSIZE_X, WINSIZE_Y }; AdjustWindowRect( &rcClient, WS_OVERLAPPEDWINDOW, FALSE ); //rcClient 크기를 작업 영영으로 할 윈도우 크기를 rcClient 에 대입되어 나온다. //윈도우 크기와 윈도우 위치를 바꾸어준다. SetWindowPos( hWnd, NULL, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, SWP_NOZORDER | SWP_NOMOVE ); if (!InitDirectX(hWnd)) { return 0; } InitVertexBuffer(); ShowWindow( hWnd, nCmdShow ); //메시지 구조체 MSG msg; ZeroMemory( &msg, sizeof( MSG ) ); int oldT = GetTickCount(); while (msg.message != WM_QUIT) { //PeekMessage 는 메시지 큐에 메시지가 없어도 프로그램이 멈추기 않고 진행이 된다. //이때 메시지큐에 메시지가 없으면 false 가 리턴되고 메시지가 있으면 true 가 리턴이된다. if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage( &msg ); //눌린 키보드 의 문자를 번역하여 WM_CHAR 메시지를 발생시킨다. DispatchMessage( &msg ); //받아온 메시지 정보로 윈도우 프로시져 함수를 실행시킨다. } else { const int curT = GetTickCount(); const int elapseT = curT - oldT; if (elapseT > 15) { oldT = curT; Render(elapseT); } } } if (g_pDevice) g_pDevice->Release(); if (g_pVB) g_pVB->Release(); if (g_pIB) g_pIB->Release(); return 0; }
/* =============== */ virtual void enter () { m_devcs->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); m_devcs->SetRenderState(D3DRS_ALPHAREF, m_value); m_devcs->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER); }
static void SetupLightingDX9(void) { // `取得Direct3D9裝置` LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); int base = 12; Vector4 vShininess = g_fMaterialShininess; Vector4 vAmbient, vDiffuse, vSpecular, vSpotLightCoeff; // `設定環境光` device->SetVertexShaderConstantF(base, &g_vAmbientLight[0], 1); // `設定光源` switch(g_iSelectedLight) { // `方向光` default: case 0: g_pSelected_VS = g_pDirLight_VS; vAmbient = g_vMaterialAmbient * g_Lights[0].m_vAmbientColor; vDiffuse = g_vMaterialDiffuse * g_Lights[0].m_vDiffuseColor; vSpecular = g_vMaterialSpecular * g_Lights[0].m_vSpecularColor; device->SetVertexShaderConstantF(base + 1, &g_Lights[0].m_vDirection.x, 1); device->SetVertexShaderConstantF(base + 2, &vAmbient.x, 1); device->SetVertexShaderConstantF(base + 3, &vDiffuse.x, 1); device->SetVertexShaderConstantF(base + 4, &vSpecular.x, 1); device->SetVertexShaderConstantF(base + 5, &vShininess.x, 1); break; // `點光源` case 1: g_pSelected_VS = g_pPointLight_VS; vAmbient = g_vMaterialAmbient * g_Lights[1].m_vAmbientColor; vDiffuse = g_vMaterialDiffuse * g_Lights[1].m_vDiffuseColor; vSpecular = g_vMaterialSpecular * g_Lights[1].m_vSpecularColor; device->SetVertexShaderConstantF(base + 1, &g_Lights[1].m_vPosition.x, 1); device->SetVertexShaderConstantF(base + 2, &g_Lights[1].m_vAttenuation.x, 1); device->SetVertexShaderConstantF(base + 3, &vAmbient.x, 1); device->SetVertexShaderConstantF(base + 4, &vDiffuse.x, 1); device->SetVertexShaderConstantF(base + 5, &vSpecular.x, 1); device->SetVertexShaderConstantF(base + 6, &vShininess.x, 1); break; // `聚光燈` case 2: g_pSelected_VS = g_pSpotLight_VS; vAmbient = g_vMaterialAmbient * g_Lights[2].m_vAmbientColor; vDiffuse = g_vMaterialDiffuse * g_Lights[2].m_vDiffuseColor; vSpecular = g_vMaterialSpecular * g_Lights[2].m_vSpecularColor; float spotlight_cutoff_cosine = FastMath::Cos( FastMath::DegreeToRadian(g_Lights[2].m_fSpotlightCutoff * 0.5f) ); vSpotLightCoeff.Set(spotlight_cutoff_cosine, g_Lights[2].m_fSpotlightExponent, 0.0f, 0.0f); device->SetVertexShaderConstantF(base + 1, &g_Lights[2].m_vPosition.x, 1); device->SetVertexShaderConstantF(base + 2, &g_Lights[2].m_vDirection.x, 1); device->SetVertexShaderConstantF(base + 3, &g_Lights[2].m_vAttenuation.x, 1); device->SetVertexShaderConstantF(base + 4, &vSpotLightCoeff.x, 1); device->SetVertexShaderConstantF(base + 5, &vAmbient.x, 1); device->SetVertexShaderConstantF(base + 6, &vDiffuse.x, 1); device->SetVertexShaderConstantF(base + 7, &vSpecular.x, 1); device->SetVertexShaderConstantF(base + 8, &vShininess.x, 1); break; } }
/* =============== */ virtual void leave () { m_devcs->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); }
//---------------------------------------------------------------------------------- // //---------------------------------------------------------------------------------- void MainLoop() { for(;;) { MSG msg; if (PeekMessage (&msg,NULL,0,0,PM_NOREMOVE)) { if( msg.message == WM_QUIT ) { return ; } GetMessage (&msg,NULL,0,0); TranslateMessage(&msg); DispatchMessage(&msg); } else { // サーバーの更新を行う。 g_server->Update(); if( g_timer % 120 == 0 ) { // エフェクトの停止 g_manager->StopEffect( g_handle ); // エフェクトの再生 g_handle = g_manager->Play( g_effect, 0, 0, 0 ); } // エフェクトの移動処理を行う。 g_manager->AddLocation( g_handle, ::Effekseer::Vector3D( 0.2f, 0.0f, 0.0f ) ); // エフェクトの更新処理を行う。 g_manager->Update(); g_d3d_device->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); g_d3d_device->BeginScene(); // エフェクトの描画開始処理を行う。 g_renderer->BeginRendering(); // エフェクトの描画を行う。 g_manager->Draw(); // エフェクトの描画終了処理を行う。 g_renderer->EndRendering(); g_d3d_device->EndScene(); g_timer++; { HRESULT hr; hr = g_d3d_device->Present( NULL, NULL, NULL, NULL ); // デバイスロスト処理 switch ( hr ) { // デバイスロスト case D3DERR_DEVICELOST: while ( FAILED( hr = g_d3d_device->TestCooperativeLevel() ) ) { switch ( hr ) { // デバイスロスト case D3DERR_DEVICELOST: ::SleepEx( 1000, true ); break; // デバイスロスト:リセット可 case D3DERR_DEVICENOTRESET: // デバイスロストの処理を行う前に実行する g_renderer->OnLostDevice(); D3DPRESENT_PARAMETERS d3dp; ZeroMemory(&d3dp, sizeof(d3dp)); d3dp.BackBufferWidth = g_window_width; d3dp.BackBufferHeight = g_window_height; d3dp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dp.BackBufferCount = 1; d3dp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dp.Windowed = TRUE; d3dp.hDeviceWindow = g_window_handle; d3dp.EnableAutoDepthStencil = TRUE; d3dp.AutoDepthStencilFormat = D3DFMT_D16; g_d3d_device->Reset( &d3dp ); // デバイスロストの処理の後に実行する g_renderer->OnResetDevice(); break; } } break; } } } } }
/* =============== */ virtual void leave () { for (uint_t idx = m_enter; idx < m_leave; idx += 2) m_devcs->SetRenderState((D3DRENDERSTATETYPE)m_value[idx], m_value[idx + 1]); }
bool DirectXTextureManager::loadTileSetFromTexture( Game *game, wstring dir, wstring sourceImageFileName, int tileWidth, int tileHeight) { // CONVERT THE FILE NAME INTO A WINDOW LONG CHAR wchar_t (LPCWSTR) wstring sourcePath = dir + sourceImageFileName; LPDIRECT3DTEXTURE9 textureToDivide; LPDIRECT3DSURFACE9 surfaceToDivide; unsigned int result = fillTexture(sourcePath, &textureToDivide); textureToDivide->GetSurfaceLevel(0, &surfaceToDivide); if (result != S_OK) return false; // DETERMINE THE NUMBER OF TILE ROWS AND COLUMNS D3DSURFACE_DESC surfaceDesc; surfaceToDivide->GetDesc(&surfaceDesc); int textureWidth = surfaceDesc.Width; int textureHeight = surfaceDesc.Height; int columns = textureWidth/tileWidth; int rows = textureHeight/tileHeight; DirectXGraphics *dxg = (DirectXGraphics*)graphics; LPDIRECT3DDEVICE9 graphicsDevice = ((DirectXGraphics*)graphics)->getGraphicsDevice(); // THE TILE SET IMAGE LOADED SUCCESSFULLY, SO LET'S CUT IT UP for (int row = 0; row < rows; row++) { for (int column = 0; column < columns; column++) { LPDIRECT3DTEXTURE9 extractedTexture; LPDIRECT3DSURFACE9 extractedSurface; result = graphicsDevice->CreateRenderTarget(tileWidth, tileHeight, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, false, &extractedSurface, NULL); if (result != S_OK) return false; RECT sourceRect; sourceRect.left = column * tileWidth; sourceRect.right = tileWidth + (column * tileWidth) - 1; sourceRect.top = row * tileHeight; sourceRect.bottom = tileHeight + (row * tileHeight) - 1; graphicsDevice->StretchRect(surfaceToDivide, &sourceRect, extractedSurface, NULL, D3DTEXF_NONE); // BUILD A UNIQUE FILE NAME FOR THIS TEXTURE wstring textureFilename = sourceImageFileName; unsigned int id = wstringTable.getNumWStringsInTable(); wchar_t dot = '.'; int dotIndex = textureFilename.rfind(dot); textureFilename = textureFilename.substr(0, dotIndex); wstringstream idWss; idWss << id; wstring idText; idWss >> idText; textureFilename = textureFilename + idText + L".png"; textureFilename = wstring(dir.begin(), dir.end()) + textureFilename; // LET'S PUT THE SURFACE IN AN IMAGE FILE D3DXSaveSurfaceToFileW(textureFilename.c_str(), D3DXIFF_PNG, extractedSurface, NULL, NULL); D3DXIMAGE_INFO info; HRESULT result = D3DXGetImageInfoFromFile(textureFilename.c_str(), &info); if (result != S_OK) return false; // AND THEN LOAD IT BACK IN AS A TEXTURE result = D3DXCreateTextureFromFileEx( graphicsDevice, // GPU textureFilename.c_str(), // BITMAP FILE PATH/NAME tileWidth, // BITMAP IMAGE WIDTH tileHeight, // BITMAP IMAGE HEIGHT 1, // MIP-MAP LEVELS (1 FOR NO CHAIN) D3DPOOL_DEFAULT, // THE TYPE OF SURFACE (STANDARD) D3DFMT_UNKNOWN, // SURFACE FORMAT (DEFAULT) D3DPOOL_DEFAULT, // MEMORY CLASS FOR THE TEXTURE D3DX_DEFAULT, // IMAGE FILTER D3DX_DEFAULT, // MIP FILTER NULL, // COLOR KEY &info, // BITMAP FILE INFO NULL, // COLOR PALETTE &extractedTexture ); // THE TEXTURE WE ARE CREATING AND LOADING if (result != S_OK) return false; // ADD IT TO THE STRING TABLE wstringTable.putWStringInTable(textureFilename); // AND ADD IT TO THE TEXTURES textures[textureFilename] = extractedTexture; //Delete File After Use int length; int slength = (int)textureFilename.length() + 1; length = WideCharToMultiByte(CP_ACP, 0, textureFilename.c_str(), slength, 0, 0, 0, 0); char* buffer = new char[length]; WideCharToMultiByte(CP_ACP, 0, textureFilename.c_str(), slength, buffer, length, 0, 0); std::string file(buffer); delete[] buffer; if (remove(file.c_str()) != 0) throw exception ("Error deleting file\n"); } } return true; }
/* =============== */ virtual void leave () { for (uint_t idx = m_enter; idx < m_leave; idx += 3) m_devcs->SetSamplerState(m_value[idx], (D3DSAMPLERSTATETYPE)m_value[idx + 1], m_value[idx + 2]); }
// 使用Direct3D9來繪圖 void RenderFrameDX9(void) { LPDIRECT3DDEVICE9 device = GutGetGraphicsDeviceDX9(); // `消除畫面` device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); // `開始下繪圖指令` device->BeginScene(); // `設定矩陣` Matrix4x4 view_matrix = g_Control.GetViewMatrix(); Matrix4x4 object_matrix = g_Control.GetObjectMatrix(); device->SetTransform(D3DTS_VIEW, (D3DMATRIX *) &view_matrix); device->SetTransform(D3DTS_WORLD, (D3DMATRIX *) &object_matrix); // `設定資料格式` device->SetFVF(D3DFVF_XYZ|D3DFVF_TEX1); // `套用貼圖` device->SetTexture(0, g_pTexture); device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); switch(g_iFilterMode) { case 1: // linear filtering // `貼圖被放大時, 取最接近4個點來內插.` device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // `貼圖被縮小時, 取最接近4個點來平均.` device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); // `不使用Mipmap` device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE); break; case 2: // bilinear filtering // `貼圖被放大時, 取最接近4個點來內插.` device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // `貼圖被縮小時, 取最接近4個點來平均.` device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); // `取最接近大小的圖層` device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); break; case 3: // trilinear filtering // `貼圖被放大時, 取最接近4個點來內插.` device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // `貼圖被縮小時, 取最接近4個點來平均.` device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); // `取最接近大小的兩個圖層, 然後再內插.` device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); break; case 4: // anisotropic filtering // `會根據縮放的長寬比例來取用貼圖, 不固定是取哪幾個圖.` device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); device->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 8); // `取最接近大小的兩個圖層, 然後再內插.` device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); break; } // `畫出矩形` device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_Quad, sizeof(Vertex_VT)); // `宣告所有的繪圖指令都下完了` device->EndScene(); // `把背景backbuffer的畫面呈現出來` device->Present( NULL, NULL, NULL, NULL ); }
void Graphics::begin() { device->BeginScene(); }