// 비디오 모드 전환 BOOL SetDisplayMode( HWND hWnd, DWORD Width, DWORD Height, DWORD BPP ) { // Set Cooperative Level smTextureBPP = BPP; if ( WindowMode ) return SetDisplayModeWin( hWnd , Width , Height , BPP ); HRESULT hresult = lpDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX ); if ( hresult != DD_OK ) { MESSAGE( "lpDD->SetCooperativeLevel" ); return FALSE; } // 풀화면 모드로 전환 hresult = lpDD->SetDisplayMode( Width, Height, BPP, 0, 0 ); if ( hresult != DD_OK ) { MESSAGE( "lpDD3->SetDisplayMode" ); return FALSE; } // Primary Surface 생성 DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize = sizeof(ddsd); ddsd.dwBackBufferCount = 1; ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; // Primary surface 생성 hresult = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); if ( hresult != DD_OK ) { MESSAGE( "lpDD->CreateSurface(lpDDSPrimary)" ); return FALSE; } // Back Surface 생성(?) DDSCAPS2 ddscaps; ddscaps.dwCaps = DDSCAPS_BACKBUFFER; hresult = lpDDSPrimary->GetAttachedSurface( &ddscaps, &lpDDSBack ); if ( hresult != DD_OK ) { MESSAGE( "lpDDSPrimary->GetAttachedSurface" ); return FALSE; } //////////// 클리퍼 생성 //////////////////////// lpDD->CreateClipper( 0, &lpDDClipper , NULL ); lpDDClipper->SetHWnd( 0, hWnd ); lpDDSPrimary->SetClipper( lpDDClipper ); lpDDClipper->Release(); // z-buffer Surface 생성 ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ddsd.dwWidth = Width; ddsd.dwHeight = Height; lpD3D->EnumZBufferFormats( IID_IDirect3DHALDevice , EnumZBufferCallback , (VOID *)&ddsd.ddpfPixelFormat ); //###################################################################################### //작 성 자 : 오 영 석 ::CopyMemory( &g_ddpfPixelFormatZ, &ddsd.ddpfPixelFormat, sizeof(g_ddpfPixelFormatZ) ); //###################################################################################### // 하드웨어 이면 z-buffer를 비디오 메모리에 만든다. if ( lpD3DDeviceDesc->bIsHardware ) ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY; else ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY; // Create the ZBuffer surface. hresult = lpDD->CreateSurface( &ddsd, &lpDDSZBuffer, NULL ); if ( hresult != DD_OK ) { MESSAGE( "lpDD2->CreateSurface(lpDDSZBuffer)" ); return FALSE; } // Back Surface에 Z-buffer를 붙인다. hresult = lpDDSBack->AddAttachedSurface( lpDDSZBuffer ); if ( hresult != DD_OK ) { MESSAGE( "lpDDSBack->AddAttachedSurface" ); return FALSE; } // Direct3D Device 생성 hresult = lpD3D->CreateDevice( lpD3DDeviceDesc->guid, lpDDSBack, &lpD3DDevice, NULL ); if ( hresult != D3D_OK ) { MESSAGE( "lpD3D->CreateDevice" ); return FALSE; } // Viewport 크기 설정 D3DRect.x1 = 0; D3DRect.y1 = 0; D3DRect.x2 = Width; D3DRect.y2 = Height; smScreenWidth = Width; smScreenHeight = Height; return TRUE; }
// 비디오 모드 전환 BOOL SetDisplayModeWin( HWND hWnd, DWORD Width, DWORD Height, DWORD BPP ) { // Set Cooperative Level HRESULT hresult = lpDD->SetCooperativeLevel( hWnd,DDSCL_NORMAL ); if ( hresult != DD_OK ) { MESSAGE( "lpDD->SetCooperativeLevel" ); return FALSE; } // Primary Surface 생성 DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof( ddsd ) ); ddsd.dwSize = sizeof(ddsd); ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; // Primary surface 생성 hresult = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ); if ( hresult != DD_OK ) { MESSAGE( "lpDD2->CreateSurface(lpDDSPrimary)" ); return FALSE; } int w,h; RECT lpRect; GetWindowRect( GetDesktopWindow() , &lpRect ); w = lpRect.right - lpRect.left; h = lpRect.bottom - lpRect.top; // 백 버퍼 1 생성 ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize=sizeof(ddsd); ddsd.dwFlags=DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_3DDEVICE| DDSCAPS_VIDEOMEMORY; ddsd.dwWidth = w; ddsd.dwHeight = h; lpDD->CreateSurface(&ddsd,&lpDDSBack,NULL); lpDD->CreateClipper( 0, &lpDDClipper , NULL ); lpDDClipper->SetHWnd( 0, hWnd ); lpDDSPrimary->SetClipper( lpDDClipper ); lpDDClipper->Release(); DDPIXELFORMAT ddpx; // z-buffer Surface 생성 ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT| DDSD_PIXELFORMAT; ddsd.dwWidth = w; ddsd.dwHeight = h; lpD3D->EnumZBufferFormats( lpD3DDeviceDesc->guid , EnumZBufferCallback , (VOID *)&ddpx ); memcpy( &ddsd.ddpfPixelFormat , &ddpx , sizeof( DDPIXELFORMAT ) ); //###################################################################################### //작 성 자 : 오 영 석 ::CopyMemory( &g_ddpfPixelFormatZ, &ddsd.ddpfPixelFormat, sizeof(g_ddpfPixelFormatZ) ); //###################################################################################### // 하드웨어 이면 z-buffer를 비디오 메모리에 만든다. if ( lpD3DDeviceDesc->bIsHardware ) ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY; else ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY; // Create the ZBuffer surface. hresult = lpDD->CreateSurface( &ddsd, &lpDDSZBuffer, NULL ); if ( hresult != DD_OK ) { MESSAGE( "lpDD2->CreateSurface(lpDDSZBuffer)" ); return FALSE; } // Back Surface에 Z-buffer를 붙인다. hresult = lpDDSBack->AddAttachedSurface( lpDDSZBuffer ); if ( hresult != DD_OK ) { MESSAGE( "lpDDSBack->AddAttachedSurface" ); return FALSE; } // Direct3D Device 생성 hresult = lpD3D->CreateDevice( lpD3DDeviceDesc->guid, lpDDSBack, &lpD3DDevice, NULL ); if ( hresult != D3D_OK ) { MESSAGE( "lpD3D->CreateDevice" ); return FALSE; } // Viewport 크기 설정 D3DRect.x1 = 0; D3DRect.y1 = 0; D3DRect.x2 = w; D3DRect.y2 = h; smScreenWidth = Width; smScreenHeight = Height; return TRUE; }
/***************************************************************************\ Initializes Direct3D. \***************************************************************************/ int IMR_DirectXInterface::InitDirect3D(LPDIRECTDRAWSURFACE4 Target) { int err; D3DVIEWPORT2 PortInitData; DDPIXELFORMAT ZBufferPixelFormat; DDSURFACEDESC2 ZBufferDesc, TargetDesc; D3DDEVICEDESC HALDesc, HELDesc; int DeviceFound = FALSE, FormatFound = FALSE; // Make sure DirectDraw is active: if (!Flags.DirectDrawActive) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): DirectDraw not initialized!"); return IMRERR_NOTREADY; } // Make sure we have a target surface: if (!Target) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): NULL target specified!"); return IMRERR_NODATA; } // Get target size info: TargetDesc.dwSize = sizeof(TargetDesc); Target->GetSurfaceDesc(&TargetDesc); // Release all Direct3D interfaces: if (Direct3DViewport) { Direct3DViewport->Release(); Direct3DViewport = NULL; } if (Direct3DDevice) { Direct3DDevice->Release(); Direct3DDevice = NULL; } if (Direct3D) { Direct3D->Release(); Direct3D = NULL; } Flags.Direct3DActive = 0; // Now get a new Direct3D3 interface: DirectDraw->QueryInterface(IID_IDirect3D3, (void **)&Direct3D); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 1 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Enumerate the devices and find one to use: err = Direct3D->EnumDevices(DeviceCallback, &DeviceFound); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 2 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } if (!DeviceFound) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): No usable rendering devices!"); return IMRERR_DIRECTX; } // Find a pixel format for our z-buffer and verify that it worked: Direct3D->EnumZBufferFormats(Direct3DDeviceInfo.Guid, ZBufferCallback, (void *)&ZBufferPixelFormat); if (ZBufferPixelFormat.dwSize != sizeof(DDPIXELFORMAT)) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): Couldn't find Z-Buffer pixel format!"); return IMRERR_DIRECTX; } // Create a Z-Buffer: ZeroMemory((void *)&ZBufferDesc, sizeof(ZBufferDesc)); ZBufferDesc.dwSize = sizeof(ZBufferDesc); ZBufferDesc.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ZBufferDesc.ddsCaps.dwCaps = DDSCAPS_ZBUFFER; ZBufferDesc.dwWidth = TargetDesc.dwWidth; ZBufferDesc.dwHeight = TargetDesc.dwHeight; memcpy(&ZBufferDesc.ddpfPixelFormat, &ZBufferPixelFormat, sizeof(DDPIXELFORMAT)); if (IsEqualIID(Direct3DDeviceInfo.Guid, IID_IDirect3DHALDevice)) ZBufferDesc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; else ZBufferDesc.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; err = DirectDraw->CreateSurface(&ZBufferDesc, &DDZBuffer, NULL); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 3 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Now attach the Z-buffer to the target surface: err = Target->AddAttachedSurface(DDZBuffer); if (err != DD_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 4 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Now create the device: err = Direct3D->CreateDevice(Direct3DDeviceInfo.Guid, Target, &Direct3DDevice, NULL); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 5 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Setup the device: Direct3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, D3DZB_TRUE); Direct3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD); Direct3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); Direct3DDevice->SetLightState(D3DLIGHTSTATE_MATERIAL, NULL); // Make sure this device can handle our textures: Direct3DDevice->EnumTextureFormats(TextureFormatCallback, (void *)&FormatFound); if (!FormatFound) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): No acceptable texture formats found!"); return IMRERR_DIRECTX; } // Now create a viewport init structure: ZeroMemory(&PortInitData, sizeof(D3DVIEWPORT2)); PortInitData.dwSize = sizeof(D3DVIEWPORT2); PortInitData.dwX = 0; PortInitData.dwY = 0; PortInitData.dwWidth = TargetDesc.dwWidth; PortInitData.dwHeight = TargetDesc.dwHeight; PortInitData.dvClipX = 0; PortInitData.dvClipY = 0; PortInitData.dvClipWidth = TargetDesc.dwWidth; PortInitData.dvClipHeight = TargetDesc.dwHeight; PortInitData.dvMinZ = 0.0f; PortInitData.dvMaxZ = 1.0f; // Create the viewport: err = Direct3D->CreateViewport(&Direct3DViewport, NULL); if (err != D3D_OK) { IMR_SetErrorText("IMR_DirectXInterface::InitDirect3D(): 6 DXERR: %s", IMR_MsgFromDXErr(err)); return IMRERR_DIRECTX; } // Associate the viewport with the device: Direct3DDevice->AddViewport(Direct3DViewport); // Set the parameters for the new viewport: Direct3DViewport->SetViewport2(&PortInitData); // Set the current viewport for the device: Direct3DDevice->SetCurrentViewport(Direct3DViewport); // Flag that Direct3D is up and running: Flags.Direct3DActive = 1; // Whew! That's done, so return success: return IMR_OK; }