Where can I find the source code examples for "Introduction to 3D game programming with DirectX 9.0c"? - c++

I have a book : "Introduction to 3D game programming with DirectX 9.0c– a shader approach" by Frank Luna.
The official site is dead and I can't seem to find 3 main files used for all the projects.
d3dApp.h
d3dApp.cpp
d3dUtil.h
Does someone know where can I get them?
All I have found was this :
http://www.d3dcoder.net/
http://www.d3dcoder.net/phpBB/
But there is no source there.
Also I've found some fragments
//A sample directX demo outputting some flashing color text
#include "d3dApp.h"
#include <tchar.h>
#include <crtdbg.h>
//Our application is derived from the D3DAPP class, making setup for a game
//or other program easier in the long run
class HelloD3DApp : public D3DApp
{
public:
HelloD3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP);
~HelloD3DApp();
bool checkDeviceCaps();
void onLostDevice();
void onresetDevice();
void updateScene(float dt);
void drawScene();
private:
ID3DXFont* mFont;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
HelloD3DApp app(hInstance, "Hello Direct3D", D3DDEVTYPE_HAL, D3DCREATE_HARDWARE_VERTEXPROCESSING);
gd3dApp = &app;
return gd3dApp->run();
}
HelloD3DApp::HelloD3DApp(HINSTANCE hInstance, std::string winCaption, D3DDEVTYPE devType, DWORD requestedVP)
: D3DApp(hInstance, winCaption, devType, requestedVP)
{
srand(time_t(0));
if(!checkDeviceCaps())
{
MessageBox(0, "checkDeviceCaps() Failed", 0, 0);
PostQuitMessage(0);
}
LOGFONTA font;
font.lfHeight = 80;
font.lfWidth = 40;
font.lfEscapement = 0;
font.lfOrientation = 0;
font.lfWeight = FW_BOLD;
font.lfItalic = true;
font.lfUnderline = false;
font.lfStrikeOut = false;
font.lfCharSet = DEFAULT_CHARSET;
font.lfOutPrecision = OUT_DEFAULT_PRECIS;
font.lfClipPrecision = CLIP_CHARACTER_PRECIS;
font.lfQuality = DEFAULT_QUALITY;
font.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
_tcscpy(font.lfFaceName, _T("Times New Roman"));
HR(D3DXCreateFontIndirect(gd3dDevice, &font, &mFont));
}
HelloD3DApp::~HelloD3DApp()
{
ReleaseCOM(mFont);
}
bool HelloD3DApp::checkDeviceCaps()
{
// Nothing to check.
return true;
}
void HelloD3DApp::onLostDevice()
{
HR(mFont->OnLostDevice());
}
void HelloD3DApp::onresetDevice()
{
HR(mFont->onresetDevice());
}
void HelloD3DApp::updateScene(float dt)
{
}
void HelloD3DApp::drawScene()
{
HR(gd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(255, 255, 255), 1.0f, 0));
RECT formatRect;
GetClientRect(mhMainWnd, &formatRect);
HR(gd3dDevice->BeginScene());
mFont->DrawText(TEXT("Hello </DIC>!"), -1,
&formatRect, DT_CENTER | DT_VCENTER,
D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256));
HR(gd3dDevice->EndScene());
HR(gd3dDevice->Present(0, 0, 0, 0));
}
But these does not help me either.

d3dApp.h
d3dApp.cpp
d3dUtil.h
These are the same files as in the zip file.

Related

LNK2019 DirectX unresolved external symbol; file dxerr.lib

Got a LINK2019 error that I can't figure out. Error code: Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol __vsnprintf referenced in function "long __stdcall StringVPrintfWorkerA(char *,unsigned int,unsigned int *,char const *,char *)" (?StringVPrintfWorkerA##YGJPADIPAIPBD0#Z) Direct X C:\Visual Studio Programs\Direct X\Direct X\dxerr.lib(dxerra.obj) 1
main.cpp:
#include <Windows.h>
#include <memory>
#include "BlankDemo.h"
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
LPWSTR cmdLine, int cmdShow)
{
UNREFERENCED_PARAMETER(prevInstance);
UNREFERENCED_PARAMETER(cmdLine);
WNDCLASSEX wndClass = { 0 };
wndClass.cbSize = sizeof(WNDCLASS);
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "DX11BookWindowClass";
if (!RegisterClassEx(&wndClass))
return -1;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect(&rc, WS_EX_OVERLAPPEDWINDOW, FALSE);
HWND hwnd = CreateWindowA("DX11BookWindowClass", "BlankWin32Window",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left,
rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
if (!hwnd)
return -1;
ShowWindow(hwnd, cmdShow);
std::auto_ptr<Dx11DemoBase> demo(new BlankDemo());
// Demo Initialize
bool result = demo->Initialize(hInstance, hwnd);
// Error reporting if there is an issue
if (result == false)
return -1;
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Update and Draw
demo->Update(0.0f);
demo->Render();
}
}
// Demo Shutdown
demo->Shutdown();
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT paintStruct;
HDC hDC;
switch (message)
{
case WM_PAINT:
hDC = BeginPaint(hwnd, &paintStruct);
EndPaint(hwnd, &paintStruct);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
defualt:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
// implementation of the BlankDemo class
BlankDemo::BlankDemo()
{
}
BlankDemo::~BlankDemo()
{
}
bool BlankDemo::LoadContent()
{
return true;
}
void BlankDemo::UnloadContent()
{
}
void BlankDemo::Update(float dt)
{
}
void BlankDemo::Render()
{
if (d3dContext_ == 0)
return;
float clearColor[4] = { 0.0f, 0.0f, 0.25f, 1.0f };
d3dContext_->ClearRenderTargetView(backBufferTarget_, clearColor);
swapChain_->Present(0, 0);
}
BlankDemo.h file:
#pragma once
#ifndef _BLANK_DEMO_H_
#define _BLANK_DEMO_H_
#include "Dx11DemoBase.h"
class BlankDemo : public Dx11DemoBase
{
public:
BlankDemo();
virtual ~BlankDemo();
bool LoadContent();
void UnloadContent();
void Update(float dt);
void Render();
};
#endif // !_BLANK_DEMO_H_
Dx11DemoBase::Dx11DemoBase() : driverType_(D3D_DRIVER_TYPE_NULL),
featureLevel_(D3D_FEATURE_LEVEL_11_0), d3dDevice_(0), d3dContext_(0),
swapChain_(0), backBufferTarget_(0)
{
}
Dx11DemoBase::~Dx11DemoBase()
{
Shutdown();
}
bool Dx11DemoBase::LoadContent()
{
// Override with demo specifics, if any...
return true;
}
void Dx11DemoBase::UnloadContent()
{
// Override with demo specifics, if any...
}
void Dx11DemoBase::Shutdown()
{
UnloadContent();
if (backBufferTarget_) backBufferTarget_->Release();
if (swapChain_) swapChain_->Release();
if (d3dContext_) d3dContext_->Release();
if (d3dDevice_) d3dDevice_->Release();
d3dDevice_ = 0;
d3dContext_ = 0;
swapChain_ = 0;
backBufferTarget_ = 0;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
bool Dx11DemoBase::Initialize(HINSTANCE hInstance, HWND hwnd)
{
hInstance_ = hInstance;
hwnd_ = hwnd;
RECT dimensions;
GetClientRect(hwnd, &dimensions);
unsigned int width = dimensions.right - dimensions.left;
unsigned int height = dimensions.bottom - dimensions.top;
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_SOFTWARE
};
unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.Windowed = true;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
unsigned int creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
HRESULT result;
unsigned int driver = 0;
for (driver = 0; driver < totalDriverTypes; ++driver)
{
result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0,
creationFlags, featureLevels, totalFeatureLevels, D3D11_SDK_VERSION,
&swapChainDesc, &swapChain_, &d3dDevice_, &featureLevel_, &d3dContext_);
if (SUCCEEDED(result))
{
driverType_ = driverTypes[driver];
break;
}
}
if (FAILED(result))
{
DXTRACE_MSG("Failed to create the Direct3d device!");
return false;
}
ID3D11Texture2D* backBufferTexture;
result = swapChain_->GetBuffer(0, _uuidof(ID3D11Texture2D), (LPVOID*)&backBufferTexture);
if (FAILED(result))
{
DXTRACE_MSG("Failed to get the swap chain back buffer!");
return false;
}
result = d3dDevice_->CreateRenderTargetView(backBufferTexture, 0, &backBufferTarget_);
if (backBufferTexture)
backBufferTexture->Release();
if (FAILED(result))
{
DXTRACE_MSG("Failed to create the render target view!");
return false;
}
d3dContext_->OMSetRenderTargets(1, &backBufferTarget_, 0);
D3D11_VIEWPORT viewport;
viewport.Width = static_cast<float>(width);
viewport.Height = static_cast<float>(height);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
d3dContext_->RSSetViewports(1, &viewport);
return LoadContent();
}
And lastly, the Dx11DemoBase.h header:
#pragma once
#ifndef _DEMO_BASE_H_
#define _DEMO_BASE_H_
#include <d3d11.h>
#include <D3DX11.h>
#include <dxerr.h>
class Dx11DemoBase
{
public:
Dx11DemoBase();
virtual ~Dx11DemoBase();
bool Initialize(HINSTANCE hInstance, HWND hwnd);
void Shutdown();
virtual bool LoadContent();
virtual void UnloadContent();
virtual void Update(float dt) = 0;
virtual void Render() = 0;
protected:
HINSTANCE hInstance_;
HWND hwnd_;
D3D_DRIVER_TYPE driverType_;
D3D_FEATURE_LEVEL featureLevel_;
ID3D11Device* d3dDevice_;
ID3D11DeviceContext* d3dContext_;
IDXGISwapChain* swapChain_;
ID3D11RenderTargetView* backBufferTarget_;
};
#endif // !_DEMO_BASE_H_
Add legacy_stdio_definitions.lib to Additional dependencies list in the Project properties > Configuration Properties > Linker > Input as recommended in this answer: https://stackoverflow.com/a/34230122/6693304
The legacy DirectX SDK is deprecated, so it hasn't been officially updated since the release of Visual Studio 2010 RTM (June 2010). See Microsoft Docs
This has a few specific implications:
The Windows 8.0 SDK, Windows 8.1 SDK, and Windows 10 SDK all have newer headers than the legacy DirectX SDK where they overlap. You can still make use of it with VS 2012, 2013, 2015, or 2017 but you need to reverse the traditional include/lib path order in the VC++ Directories settings. There are a few other quirks covered at the bottom of this Microsoft Docs topic page. See also The Zombie DirectX SDK.
The DLL import libraries in the legacy DirectX SDK are missing some of the imports that are present in the Windows 8.x or Windows 10 SDK. They generally work fine with all C/C++ compilers because they are fairly standard Win32 without any version-specific CRT references.
Static libraries, however, are not guaranteed to be binary compatible from version to version of the C/C++ compiler. dxguid.lib just has some data in it, so it generally works, but dxerr.lib has actual code. Hence with the major changes in the C/C++ Runtime in VS 2015, it no longer works without link errors.
There are two basic solutions to the dxerr.lib problem:
Build your own copy of the code. It's available here. This is the most robust as it will always match your compiler toolset.
You can add legacy_stdio_definitions.lib, but keep in mind that you are already relying on very out-dated files so you should work to remove/minimize use of the legacy DirectX SDK over time.
Many online tutorials for DirectX 11 and books are outdated w.r.t. to the DirectX SDK and still use d3dx11 which is also deprecated. There are numerous open source replacements available for this functionality. See Living without D3DX.
All that said, this question has already been answered on StackOverflow and would have shown up if you just searched dxerr.

Initializing OpenGL without libraries

Every tutorial I find Online uses SDL or GLAD or other libraries to initialize OpenGL. Is there a way of initializing OpenGL with no extra libraries (like DirectX)?
The reason for that, Is that I am building a Game Engine and I want to minimize the external libraries as possible and to be able to handle more error messages.
Initializing OpenGL differs from one operating system to another, that's why people made these libraries to ease other developers work.
Some tutorials that will help you.
For Windows (WGL)
https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context
http://www.rastertek.com/gl40tut03.html
For Linux (GLX)
https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
There isn't much quality information about doing this. I found a great piece of code called windows_modern_opengl_context.c on github by the user nickrolfe. I thought I'd share it here to make it easier for others to find. If you link -lopengl32 and make sure you have -mwindows flag up it should compile fine with a modern c compiler. I'm using gcc -std=c11. If you want to use C++ you may have to edit the code to not use designated initializers when initializing the structs. I'm not sure.
EDIT:
This code creates an empty window using the win32 api with a modern opengl context (Version 3.3). You will still need to load the appropriate gl extensions in order to call functions such as glCreateShader(...); I recommend using glad to do this. If you use glad like I said you should use gladLoadGL() instead of gladLoadGLLoader() to load the extensions.
// Sample code showing how to create a modern OpenGL window and rendering context on Win32.
#include <windows.h>
#include <gl/gl.h>
#include <stdbool.h>
typedef HGLRC WINAPI wglCreateContextAttribsARB_type(HDC hdc, HGLRC hShareContext, const int *attribList);
wglCreateContextAttribsARB_type *wglCreateContextAttribsARB;
// See https://www.opengl.org/registry/specs/ARB/wgl_create_context.txt for all values
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
typedef BOOL WINAPI wglChoosePixelFormatARB_type(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
wglChoosePixelFormatARB_type *wglChoosePixelFormatARB;
// See https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt for all values
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_TYPE_RGBA_ARB 0x202B
static void
fatal_error(char *msg)
{
MessageBoxA(NULL, msg, "Error", MB_OK | MB_ICONEXCLAMATION);
exit(EXIT_FAILURE);
}
static void
init_opengl_extensions(void)
{
// Before we can load extensions, we need a dummy OpenGL context, created using a dummy window.
// We use a dummy window because you can only set the pixel format for a window once. For the
// real window, we want to use wglChoosePixelFormatARB (so we can potentially specify options
// that aren't available in PIXELFORMATDESCRIPTOR), but we can't load and use that before we
// have a context.
WNDCLASSA window_class = {
.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
.lpfnWndProc = DefWindowProcA,
.hInstance = GetModuleHandle(0),
.lpszClassName = "Dummy_WGL_djuasiodwa",
};
if (!RegisterClassA(&window_class)) {
fatal_error("Failed to register dummy OpenGL window.");
}
HWND dummy_window = CreateWindowExA(
0,
window_class.lpszClassName,
"Dummy OpenGL Window",
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
window_class.hInstance,
0);
if (!dummy_window) {
fatal_error("Failed to create dummy OpenGL window.");
}
HDC dummy_dc = GetDC(dummy_window);
PIXELFORMATDESCRIPTOR pfd = {
.nSize = sizeof(pfd),
.nVersion = 1,
.iPixelType = PFD_TYPE_RGBA,
.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
.cColorBits = 32,
.cAlphaBits = 8,
.iLayerType = PFD_MAIN_PLANE,
.cDepthBits = 24,
.cStencilBits = 8,
};
int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
if (!pixel_format) {
fatal_error("Failed to find a suitable pixel format.");
}
if (!SetPixelFormat(dummy_dc, pixel_format, &pfd)) {
fatal_error("Failed to set the pixel format.");
}
HGLRC dummy_context = wglCreateContext(dummy_dc);
if (!dummy_context) {
fatal_error("Failed to create a dummy OpenGL rendering context.");
}
if (!wglMakeCurrent(dummy_dc, dummy_context)) {
fatal_error("Failed to activate dummy OpenGL rendering context.");
}
wglCreateContextAttribsARB = (wglCreateContextAttribsARB_type*)wglGetProcAddress("wglCreateContextAttribsARB");
wglChoosePixelFormatARB = (wglChoosePixelFormatARB_type*)wglGetProcAddress("wglChoosePixelFormatARB");
wglMakeCurrent(dummy_dc, 0);
wglDeleteContext(dummy_context);
ReleaseDC(dummy_window, dummy_dc);
DestroyWindow(dummy_window);
}
static HGLRC
init_opengl(HDC real_dc)
{
init_opengl_extensions();
// Now we can choose a pixel format the modern way, using wglChoosePixelFormatARB.
int pixel_format_attribs[] = {
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0
};
int pixel_format;
UINT num_formats;
wglChoosePixelFormatARB(real_dc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
if (!num_formats) {
fatal_error("Failed to set the OpenGL 3.3 pixel format.");
}
PIXELFORMATDESCRIPTOR pfd;
DescribePixelFormat(real_dc, pixel_format, sizeof(pfd), &pfd);
if (!SetPixelFormat(real_dc, pixel_format, &pfd)) {
fatal_error("Failed to set the OpenGL 3.3 pixel format.");
}
// Specify that we want to create an OpenGL 3.3 core profile context
int gl33_attribs[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
0,
};
HGLRC gl33_context = wglCreateContextAttribsARB(real_dc, 0, gl33_attribs);
if (!gl33_context) {
fatal_error("Failed to create OpenGL 3.3 context.");
}
if (!wglMakeCurrent(real_dc, gl33_context)) {
fatal_error("Failed to activate OpenGL 3.3 rendering context.");
}
return gl33_context;
}
static LRESULT CALLBACK
window_callback(HWND window, UINT msg, WPARAM wparam, LPARAM lparam)
{
LRESULT result = 0;
switch (msg) {
case WM_CLOSE:
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
result = DefWindowProcA(window, msg, wparam, lparam);
break;
}
return result;
}
static HWND
create_window(HINSTANCE inst)
{
WNDCLASSA window_class = {
.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
.lpfnWndProc = window_callback,
.hInstance = inst,
.hCursor = LoadCursor(0, IDC_ARROW),
.hbrBackground = 0,
.lpszClassName = "WGL_fdjhsklf",
};
if (!RegisterClassA(&window_class)) {
fatal_error("Failed to register window.");
}
// Specify a desired width and height, then adjust the rect so the window's client area will be
// that size.
RECT rect = {
.right = 1024,
.bottom = 576,
};
DWORD window_style = WS_OVERLAPPEDWINDOW;
AdjustWindowRect(&rect, window_style, false);
HWND window = CreateWindowExA(
0,
window_class.lpszClassName,
"OpenGL",
window_style,
CW_USEDEFAULT,
CW_USEDEFAULT,
rect.right - rect.left,
rect.bottom - rect.top,
0,
0,
inst,
0);
if (!window) {
fatal_error("Failed to create window.");
}
return window;
}
int WINAPI
WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd_line, int show)
{
HWND window = create_window(inst);
HDC gldc = GetDC(window);
HGLRC glrc = init_opengl(gldc);
ShowWindow(window, show);
UpdateWindow(window);
bool running = true;
while (running) {
MSG msg;
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
running = false;
} else {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Do OpenGL rendering here
SwapBuffers(gldc);
}
return 0;
}

OpenGL on a custom made win32 window, using cygwin compiler, doesn't work

I wrote a bit of code, based on NeHe's first tutorial, which creates a window and initializes gl context. this worked exactly as it should in vc++. Then I've tried to replicate the same code in eclipse c++ environment using cygwin compiler and the problems began.
The window compiles without any errors (A number of warnings but no errors), the exe opens a win32 window as it should, all of the functionality that I've coded into the window works too (e.g. full screen mode, change resolution) the only problem is that instead of refreshing the background of the window with red colour as it should I'm getting a black square and that's it.
To me this looks like an opengl initialization problem. Been trying to solve this problem for two days but I can't find any solution I hope somebody can see what I'm doing wrong.
Below are the code extracts.
Initial method
#include <iostream>
#include <windows.h>
#include <gl/glew.h>
#include <string>
#define GLEW_STATIC
using namespace std;
#include <glWindow.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MSG msg;
GLboolean Exit = FALSE;
glWindow screen("Dark Light", 640, 480, 16);
while(!Exit){
if (screen.LastError() == errNone && screen.WndState() != glExit){
// Is There A Message Waiting?
if (PeekMessage(&msg, screen.Handles().Window(), 0, 0, PM_REMOVE)){
// Have We Received A Quit Message?
if (msg.message == WM_QUIT){
screen.WndState() = glExit;
}
// If Not, Deal With Window Messages
else{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
// If There Are No Messages
else{
if (screen.WndState() == glActive){
if (screen.KeysState(VK_ESCAPE)){
screen.WndState() = glExit;
}
else{
// Draw The Scene
screen.Draw();
}
}
if (screen.KeysState(VK_F1)){
screen.KeysState(VK_F1) = FALSE;
screen.ToggleFullscreen();
}
if (screen.KeysState(VK_SPACE)){
screen.KeysState(VK_SPACE) = FALSE;
screen.SetResolution(800, 600);
}
}
}
else{
Exit = true;
}
}
// Shutdown
return 0;
}
glWindow.h
#ifndef GLWINDOW_H
#define GLWINDOW_H
#include <string>
using namespace std;
enum glWndState
{
glActive = 0, glPaused = 1, glExit = 2
};
enum glWndErrors
{
errNone = 0, errCreateWC = 1, errCreateWnd = 2, errCreateDC = 3, errMatchPixelFormat = 4,
errSetPixelFormat = 5, errCreateRC = 6, errActivateRC = 7, errInitGL = 8, errChangeRC = 9,
errReleaseRC = 10, errReleaseDC = 11, errDestroyWnd = 12, errDestroyWC = 13, errGoToFullscreen = 14,
errGoToWindowed = 15, errGetInstance = 16
};
class glWndSettings
{
private:
GLsizei _width;
GLsizei _height;
GLboolean _fullscreen;
GLint _bits;
PIXELFORMATDESCRIPTOR _pfd;
DEVMODE _screenSettings;
public:
glWndSettings(GLsizei width, GLsizei height, GLint bits);
glWndErrors glSetStyle(HWND hWnd);
glWndErrors glSetStyle(HWND hWnd, GLboolean fullscreen, GLboolean save = TRUE);
glWndErrors glSetResolution(HWND hWnd, GLsizei width, GLsizei height);
GLsizei& Width();
GLsizei& Height();
GLboolean& Fullscreen();
GLint& Bits();
PIXELFORMATDESCRIPTOR& PixelFormatDescription();
};
class glWndHandles
{
private:
string _className;
HINSTANCE _hInstance;
WNDCLASS _wc;
HWND _hWnd;
HDC _hDC;
HGLRC _hRC;
GLuint _pixelFormat;
public:
glWndHandles(HICON icon, string title, WNDPROC wndProc);
~glWndHandles();
glWndErrors glDefWindow(PIXELFORMATDESCRIPTOR pfd);
HINSTANCE& Instance();
WNDCLASS& WinClass();
HWND& Window();
HDC& DeviceContext();
HGLRC& RenderContext();
};
class glWndFPS
{
GLint _framesCounter;
GLint _fps;
public:
glWndFPS();
GLvoid NewFrame();
GLvoid ResetFrames();
GLint FPS();
};
class glWindow
{
glWndHandles _handles;
glWndSettings _settings;
glWndFPS _fps;
glWndErrors _error;
glWndState _state;
bool _keys[256];
string _title;
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
glWindow(string title, int width, int height, int bits);
~glWindow();
int InitGL();
GLvoid Draw();
GLvoid DisplayFPS();
GLvoid SetTitle(string title);
GLvoid SetResolution(GLsizei width, GLsizei height);
GLvoid SetFullscreen(GLboolean fullscreen);
GLvoid ToggleFullscreen();
glWndHandles& Handles();
glWndSettings& Settings();
glWndFPS& fpsInfo();
glWndErrors& LastError();
glWndState& WndState();
bool& KeysState(int key);
GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
};
#endif /* GLWINDOW_H_ */
glWindow.cpp
#include <stdio.h>
#include <windows.h>
#include <GL/glew.h>
#include <glm/gtc/matrix_transform.hpp>
using namespace std;
#include "glWindow.h"
glWndSettings::glWndSettings(GLsizei width, GLsizei height, GLint bits){
_fullscreen = FALSE;
_width = width;
_height = height;
_bits = bits;
_pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Size Of This Pixel Format Descriptor
_pfd.nVersion = 1; // Version Number
_pfd.dwFlags = PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER; // Must Support Double Buffering
_pfd.iPixelType = PFD_TYPE_RGBA; // Request An RGBA Format
_pfd.cColorBits = bits; // Select Our Color Depth
_pfd.cRedBits = 0; _pfd.cRedShift = 0;
_pfd.cGreenBits = 0; _pfd.cGreenShift = 0;
_pfd.cBlueBits = 0; _pfd.cBlueShift = 0; // Color Bits Ignored
_pfd.cAlphaBits = 0; _pfd.cAlphaShift = 0; // No Alpha Buffer
_pfd.cAccumBits = 0;
_pfd.cAccumRedBits = 0;
_pfd.cAccumGreenBits = 0;
_pfd.cAccumBlueBits = 0;
_pfd.cAccumAlphaBits = 0;
_pfd.cDepthBits = 16; // 16Bit Z-Buffer (Depth Buffer)
_pfd.cStencilBits = 0; // No Stencil Buffer
_pfd.cAuxBuffers = 0; // No Auxiliary Buffer
_pfd.iLayerType = PFD_MAIN_PLANE; // Main Drawing Layer
_pfd.bReserved = 0; // Reserved
_pfd.dwLayerMask = 0;
_pfd.dwVisibleMask = 0;
_pfd.dwDamageMask = 0; // Layer Masks Ignored
}
glWndErrors glWndSettings::glSetStyle(HWND hWnd){
GLboolean fullscreen = !_fullscreen;
return glSetStyle(hWnd, fullscreen);
}
glWndErrors glWndSettings::glSetStyle(HWND hWnd, GLboolean fullscreen, GLboolean save){
DWORD dwExStyle = 0;
DWORD dwStyle = 0;
if (save)
_fullscreen = fullscreen;
if (fullscreen){
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
memset(&_screenSettings, 0, sizeof(_screenSettings)); // Makes Sure Memory's Cleared
_screenSettings.dmSize = sizeof(_screenSettings); // Size Of The Devmode Structure
_screenSettings.dmPelsWidth = _width; // Selected Screen Width
_screenSettings.dmPelsHeight = _height; // Selected Screen Height
_screenSettings.dmBitsPerPel = _bits; // Selected Bits Per Pixel
_screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&_screenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){
return errGoToFullscreen;
}
while(ShowCursor(FALSE) >= 0);
}
else{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (ChangeDisplaySettings(NULL, 0) != DISP_CHANGE_SUCCESSFUL){
return errGoToWindowed;
}
while(ShowCursor(TRUE) < 0);
}
RECT windowRect;
windowRect.left=(long)0; // Set Left Value To 0
windowRect.right=(long)_width; // Set Right Value To Requested Width
windowRect.top=(long)0; // Set Top Value To 0
windowRect.bottom=(long)_height; // Set Bottom Value To Requested Height
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
ShowWindow(hWnd, SW_HIDE);
DWORD oldExStyle = SetWindowLongPtr(hWnd, GWL_EXSTYLE, dwExStyle);
DWORD oldStyle = SetWindowLongPtr(hWnd, GWL_STYLE, dwStyle);
SetWindowPos(hWnd, HWND_TOP, 0, 0, windowRect.right, windowRect.bottom, SWP_NOZORDER);
ShowWindow(hWnd, SW_SHOW);
return errNone;
}
glWndErrors glWndSettings::glSetResolution(HWND hWnd, GLsizei width, GLsizei height){
_width = width; _height = height;
glSetStyle(hWnd, _fullscreen);
return errNone;
}
GLsizei& glWndSettings::Width(){
return _width;
}
GLsizei& glWndSettings::Height(){
return _height;
}
GLboolean& glWndSettings::Fullscreen(){
return _fullscreen;
}
GLint& glWndSettings::Bits(){
return _bits;
}
PIXELFORMATDESCRIPTOR& glWndSettings::PixelFormatDescription(){
return _pfd;
}
glWndHandles::glWndHandles(HICON icon, string title, WNDPROC wndProc){
_hInstance = NULL;
_hWnd = NULL;
_hDC = NULL;
_hRC = NULL;
_pixelFormat = NULL;
_className = title;
_wc.style = CS_HREDRAW | CS_VREDRAW | // Redraw On Size
CS_OWNDC; // Own DC For Window.
_wc.lpfnWndProc = wndProc; // WndProc Handles Messages
_wc.cbClsExtra = NULL; // No Extra Window Data
_wc.cbWndExtra = NULL; // No Extra Window Data
_wc.hInstance = NULL; // Set The Instance
_wc.hIcon = icon; // Load The Default Icon
_wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
_wc.hbrBackground = NULL; // No Background Required For GL
_wc.lpszMenuName = NULL; // We Don't Want A Menu
_wc.lpszClassName = _className.c_str(); // Set The Class Name
}
glWndHandles::~glWndHandles(){
// Are We Able To Release The DC And RC Contexts?
if (_hRC){
if (!wglMakeCurrent(NULL, NULL))
MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Delete The RC?
if (!wglDeleteContext(_hRC))
MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
// Are We Able To Release The DC
if (_hDC && !ReleaseDC(_hWnd, _hDC))
MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Destroy The Window?
if (_hWnd && !DestroyWindow(_hWnd))
MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
// Are We Able To Unregister Class
if (!UnregisterClass(_className.c_str(), _hInstance))
MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
glWndErrors glWndHandles::glDefWindow(PIXELFORMATDESCRIPTOR pfd){
if ((_hInstance = GetModuleHandle(NULL))){
_wc.hInstance = _hInstance;
}
else{
MessageBox(NULL, "Failed To Get Window's Instance.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return errGetInstance;
}
if (!RegisterClass(&_wc)){
MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
return errCreateWC;
}
if (!(_hWnd=CreateWindowEx( NULL, // Extended Style For The Window
_wc.lpszClassName, // Class Name
_className.c_str(), // Window Title
NULL, // Style For The Window
0, 0, 300, 300, // Window's Position and Size
NULL, // No Parent Window
NULL, // No Menu
_hInstance, // Instance
NULL))){
MessageBox(NULL, "Window Creation Error.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateWnd;
}
//Get Window's Device Context
if (!(_hDC = GetDC(_hWnd))){
MessageBox(NULL, "Can't Create A GL Device Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateDC;
}
// Did Windows Find A Matching Pixel Format?
if (!(_pixelFormat = ChoosePixelFormat(_hDC, &pfd))){
MessageBox(NULL, "Can't Find A Suitable PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errMatchPixelFormat;
}
// Are We Able To Set The Pixel Format?
if(!SetPixelFormat(_hDC, _pixelFormat, &pfd)){
MessageBox(NULL, "Can't Set The PixelFormat.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errSetPixelFormat;
}
if (!(_hRC=wglCreateContext(_hDC))){
MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errCreateRC;
}
if(!wglMakeCurrent(_hDC,_hRC)){
MessageBox(NULL, "Can't Activate The GL Rendering Context.", "ERROR",MB_OK|MB_ICONEXCLAMATION);
return errActivateRC;
}
// GLenum err = glewInit();
//
// if (err != GLEW_OK){
// MessageBox(NULL, (char*)glewGetErrorString(err), "ERROR", MB_OK|MB_ICONEXCLAMATION);
// return errInitGL;
// }
return errNone;
}
HINSTANCE& glWndHandles::Instance(){
return _hInstance;
}
WNDCLASS& glWndHandles::WinClass(){
return _wc;
}
HDC& glWndHandles::DeviceContext(){
return _hDC;
}
HGLRC& glWndHandles::RenderContext(){
return _hRC;
}
HWND& glWndHandles::Window(){
return _hWnd;
}
glWndFPS::glWndFPS(){
_framesCounter = 0; _fps = 0;
}
GLvoid glWndFPS::NewFrame(){
_framesCounter++;
}
GLvoid glWndFPS::ResetFrames(){
_fps = _framesCounter; _framesCounter = 0;
}
GLint glWndFPS::FPS(){
return _fps;
}
glWindow* owner;
LRESULT CALLBACK glWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
// Check For Windows Messages
switch (uMsg){
// Watch For Window Activate Message
case WM_ACTIVATE:{
// Check Minimization State
if (!HIWORD(wParam)){
// Program Is Active
owner->_state = glActive;
}
else{
// Program Is No Longer Active
owner->_state = glPaused;
}
// Return To The Message Loop
return 0;
}
// Intercept System Commands
case WM_SYSCOMMAND:{
// Check System Calls
switch (wParam){
// Screensaver Trying To Start?
case SC_SCREENSAVE:
// Monitor Trying To Enter Powersave?
case SC_MONITORPOWER:
// Prevent From Happening
return 0;
}
break;
}
// Did We Receive A Close Message?
case WM_CLOSE:{
// Send A Quit Message
PostQuitMessage(0);
return 0;
}
// Is A Key Being Held Down?
case WM_KEYDOWN:{
// If So, Mark It As TRUE
owner->_keys[wParam] = TRUE;
return 0;
}
// Has A Key Been Released?
case WM_KEYUP:{
// If So, Mark It As FALSE
owner->_keys[wParam] = FALSE;
return 0;
}
// Resize The OpenGL Window
case WM_SIZE:{
if (owner->Settings().Fullscreen() && IsWindowVisible(hWnd)){
if (wParam == SIZE_MINIMIZED)
owner->Settings().glSetStyle(hWnd, FALSE, FALSE);
else if (wParam == SIZE_RESTORED)
owner->Settings().glSetStyle(hWnd, TRUE, FALSE);
}
// LoWord=Width, HiWord=Height
owner->ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));
return 0;
}
case WM_KILLFOCUS:{
if (IsWindowVisible(hWnd) && owner->Settings().Fullscreen())
ShowWindow(hWnd, SW_MINIMIZE);
return 0;
}
case WM_TIMER:{
if (wParam == 1)
owner->DisplayFPS();
return 0;
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
glWindow::glWindow(string title, int width, int height, int bits)
:_settings(width, height, bits), _handles(LoadIcon(NULL, IDI_WINLOGO), title, (WNDPROC)WndProc)
{
for (int i = 0; i < 256; i++){
_keys[i] = false;
}
_error = errNone; _state = glActive; owner = this;
_title = title;
if ((_error = _handles.glDefWindow(_settings.PixelFormatDescription())) != errNone){
return;
}
_settings.glSetStyle(_handles.Window(), false);
SetForegroundWindow(_handles.Window()); // Slightly Higher Priority
SetFocus(_handles.Window()); // Sets Keyboard Focus To The Window
// Initialize Our Newly Created GL Window
if (!InitGL()){
MessageBox(NULL, "Initialization Failed.", "ERROR", MB_OK|MB_ICONEXCLAMATION);
_error = errInitGL;
return;
}
SetTimer(_handles.Window(), 1, 1000, NULL);
}
glWindow::~glWindow(void){
if (_settings.Fullscreen()){
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}
}
int glWindow::InitGL(){
glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
// Really Nice Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
return TRUE; // Initialization Went OK
}
GLvoid glWindow::Draw(){
//Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); // Reset The Current Modelview Matrix
SwapBuffers(_handles.DeviceContext());
fpsInfo().NewFrame();
}
glWndErrors& glWindow::LastError(){
return _error;
}
glWndState& glWindow::WndState(){
return _state;
}
glWndHandles& glWindow::Handles(){
return _handles;
}
glWndSettings& glWindow::Settings(){
return _settings;
}
glWndFPS& glWindow::fpsInfo(){
return _fps;
}
bool& glWindow::KeysState(int key){
return _keys[key];
}
GLvoid glWindow::DisplayFPS(){
fpsInfo().ResetFrames();
char fps[100];
sprintf(fps, "%d", fpsInfo().FPS());
SetTitle(_title + " : ");
SetTimer(_handles.Window(), 1, 1000, NULL);
}
GLvoid glWindow::SetTitle(string title){
SetWindowText(_handles.Window(), title.c_str());
}
GLvoid glWindow::SetResolution(GLsizei width, GLsizei height){
_settings.glSetResolution(_handles.Window(), width, height);
}
GLvoid glWindow::SetFullscreen(GLboolean fullscreen){
_settings.glSetStyle(_handles.Window(), fullscreen);
}
GLvoid glWindow::ToggleFullscreen(){
_settings.glSetStyle(_handles.Window());
}
GLvoid glWindow::ReSizeGLScene(GLsizei width, GLsizei height){
if (height == 0 && width == 0){
return;
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
glm::perspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
Compiler output
g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\glWindow.o" "..\\src\\glWindow.cpp"
g++ -ID:/DarkLight/hello/header -ID:/DarkLight/externals/include -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\hello.o" "..\\src\\hello.cpp"
g++ -mwindows -o hello.exe "src\\hello.o" "src\\glWindow.o" -lgl -lglew32 -lglu32 -lopengl32 -lgdi32
How did you compile the Cygwin build? Specifically which libraries did you link?
Cygwin can be compiled for the native GUI system (Win32) or to make use of X11. But OpenGL goes through two very different stacks between the two cases. In case of Win32 it goes through WGL and in case of X11 it goes through GLX. Now if you accidently linked the GLX based OpenGL API (-lGL) then all the OpenGL symbols are there, so things seem to work superficially, but there's no output. You have to link against opengl32.lib, i.e. -lopengl32 so that the WGL based bindings are used.

How to reset my DirectX 9 device?

Recently, I've found a bug in my 3D application that uses DirectX 9. The bug is that everytime I alt-tab or ctrl-alt-delete, the program freezes or seems to do nothing. I've looked around and found out that I need to reset my device by using IDirect3DDevice9::TestCooperativeLevel and IDirect3DDevice9::Reset. But what I'm struggling on at the moment is that (as far as I know) before I Reset the device, I need to release the resouce in D3DPOOL_MANAGE before I reset the device and reallocate the resource back to it after the Reset? How do I do this? Below is the code I've got for the reset of my device (in the IsDeviceLost() function).
DirectX.h
#pragma once
#pragma comment(lib, "d3d9.lib")
#include<d3d9.h>
#include<d3dx9math.h>
#include"Window.h"
#include"Vertex.h"
#include"Shader.h"
#define VERTEXFORMAT (D3DFVF_XYZ | D3DFVF_TEX1) //Flags for the Flexible Vertex Format (FVF)
class Shader;
class DirectX
{
public:
DirectX(std::string windowTitle, int x, int y, unsigned int windowWidth, unsigned int windowHeight, bool fullscreen);
virtual ~DirectX();
static LPDIRECT3D9 direct3D;
static LPDIRECT3DDEVICE9 device;
static IDirect3DVertexDeclaration9* vertexDec;
static ID3DXEffect* currentShaderEffect;
void CheckShaderVersion();
bool IsDeviceLost();
protected:
D3DPRESENT_PARAMETERS direct3DPresPara;
Window *window;
unsigned int width;
unsigned int height;
D3DXMATRIX projMatrix;
private:
void Initialize(bool fullscreenMode);
};
Direct.cpp
#include"DirectX.h"
LPDIRECT3D9 DirectX::direct3D = NULL;
LPDIRECT3DDEVICE9 DirectX::device = NULL;
IDirect3DVertexDeclaration9* DirectX::vertexDec = NULL;
ID3DXEffect* DirectX::currentShaderEffect = NULL;
DirectX::DirectX(std::string windowTitle, int x, int y, unsigned int windowWidth, unsigned int windowHeight, bool fullscreen)
{
width = windowWidth;
height = windowHeight;
window = new Window(windowTitle.c_str(), windowWidth, windowHeight, x, y, fullscreen);
Initialize(fullscreen);
D3DXMatrixPerspectiveFovLH( &projMatrix,
D3DXToRadian(45),
(float)width/(float)height,
1.0f,
15000.0f);
//device->SetTransform(D3DTS_PROJECTION, &projMatrix);
}
DirectX::~DirectX()
{
direct3D->Release();
device->Release();
vertexDec->Release();
delete vertexDec;
delete currentShaderEffect;
delete window;
}
void DirectX::Initialize(bool fullscreenMode)
{
direct3D = Direct3DCreate9(D3D_SDK_VERSION);
ZeroMemory(&direct3DPresPara, sizeof(direct3DPresPara));
switch(fullscreenMode)
{
case true:
direct3DPresPara.Windowed = false;
break;
case false:
direct3DPresPara.Windowed = true;
}
direct3DPresPara.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //turns off VSync, comment this line of code to turn VSync back on
direct3DPresPara.SwapEffect = D3DSWAPEFFECT_DISCARD;
direct3DPresPara.hDeviceWindow = window->GetHandle();
direct3DPresPara.BackBufferFormat = D3DFMT_X8R8G8B8;
direct3DPresPara.BackBufferWidth = width;
direct3DPresPara.BackBufferHeight = height;
direct3DPresPara.EnableAutoDepthStencil = TRUE;
direct3DPresPara.AutoDepthStencilFormat = D3DFMT_D16;
direct3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window->GetHandle(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &direct3DPresPara, &device);
D3DVERTEXELEMENT9 vertexElement[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()};
device->CreateVertexDeclaration(vertexElement, &vertexDec);
//currentShaderEffect = 0;
}
void DirectX::CheckShaderVersion()
{
D3DCAPS9 caps;
device->GetDeviceCaps(&caps);
bool stop = false;
int i = 6;
while(!stop)
{
if(caps.VertexShaderVersion < D3DVS_VERSION(i, 0))
{
i--;
}
else
{
std::cout << "you are using shader model " << i << std::endl;
stop = true;
}
}
//std::cout << caps.VertexShaderVersion << std::endl;
//std::cout << D3DVS_VERSION(3, 0) << std::endl;
}
bool DirectX::IsDeviceLost()
{
HRESULT result = device->TestCooperativeLevel();
if(result == D3DERR_DEVICELOST)
{
Sleep(20); //Sleep for a little bit then try again.
return true;
}
else if(result == D3DERR_DRIVERINTERNALERROR)
{
MessageBox(0, "Internal Driver Error. The program will now exit.", 0, 0);
PostQuitMessage(0);
return true;
}
else if(result == D3DERR_DEVICENOTRESET)
{
device->Reset(&direct3DPresPara);
return false;
}
else
{
return false;
}
}
Any help or advice will be greatly appreciated. Thanks
You don't need to release resources in D3DPOOL_MANAGED. You need to release resources in D3DPOOL_DEFAULT.
If you're using D3DX objects (ID3DXFont, ID3DXMesh, ID3DXSprite), they typically have "OnLostDevice" and "OnResetDevice" methods. You should call those methods in appropriate situations.
If an object does not have any methods for dealing with "DeviceLost" state, and they should be released, simply destroy the object before resetting the device, and reload it afterwards.
Please note that D3DPOOL_MANAGED objects are reloaded automatically by the driver and don't need any "help" from you to deal with reset/devicelost. YOu do need to take care about all other objects.
In addition to what I said/wrote, you should obviously read DirectX SDK documentation. They cover lost devices in their documentation, and DirectX examples normally survive device reset just fine.

Drawing a jpg in MFC

I've been trying to show a jpg image in MFC, but I can't get it drawn. I'm a complete MFC newbie an everything I got up until now is mostly adapted from things I found on the net. Currently I have this:
Picture.h:
#pragma once
#include <afxwin.h>
class Picture
{
public:
Picture();
bool load(LPCTSTR filePath);
bool draw( CDC* deviceContext
, CRect clientRect
, LPCRECT prcMFBounds);
CSize getSize(CDC* pDC);
private:
LPPICTURE m_picture;
};
Picture.cpp:
#include "Picture.h"
Picture::Picture()
: m_picture(0)
{
}
bool Picture::load(LPCTSTR szFile)
{
HANDLE hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return false;
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == (DWORD)-1)
{
CloseHandle(hFile);
return false;
}
LPVOID pvData = NULL;
// alloc memory based on file size
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize);
if (hGlobal == NULL)
{
CloseHandle(hFile);
return false;
}
pvData = GlobalLock(hGlobal);
if (pvData == NULL)
{
GlobalUnlock(hGlobal);
CloseHandle(hFile);
return false;
}
DWORD dwBytesRead = 0;
// read file and store in global memory
bool bRead = ReadFile(hFile, pvData, dwFileSize, &dwBytesRead, NULL) != 0;
GlobalUnlock(hGlobal);
CloseHandle(hFile);
if (!bRead)
return false;
LPSTREAM pstm = NULL;
// create IStream* from global memory
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pstm);
if (!(SUCCEEDED(hr)))
{
if (pstm != NULL)
pstm->Release();
return false;
}
else if (pstm == NULL)
return false;
// Create IPicture from image file
if (m_picture)
m_picture->Release();
hr = ::OleLoadPicture(pstm, dwFileSize, FALSE, IID_IPicture, (LPVOID *)&(m_picture));
if (!(SUCCEEDED(hr)))
{
pstm->Release();
return false;
}
else if (m_picture == NULL)
{
pstm->Release();
return false;
}
pstm->Release();
return true;
}
bool Picture::draw(CDC* deviceContext, CRect clientRect, LPCRECT prcMFBounds)
{
if (clientRect.IsRectNull())
{
CSize imageSize = getSize(deviceContext);
clientRect.right = imageSize.cx;
clientRect.bottom = imageSize.cy;
}
long pictureWidth = 0;
long pictureHeigth = 0;
m_picture->get_Width(&pictureWidth);
m_picture->get_Height(&pictureHeigth);
m_picture->Render( *deviceContext
, clientRect.left
, clientRect.top
, clientRect.Width()
, clientRect.Height()
, 0
, pictureHeigth
, pictureWidth
, -pictureHeigth
, prcMFBounds);
return true;
}
CSize Picture::getSize(CDC* deviceContext)
{
if (!m_picture)
return CSize(0,0);
LONG width, height; // HIMETRIC units
m_picture->get_Width(&width);
m_picture->get_Height(&height);
CSize size(width, height);
if (deviceContext==NULL)
{
CWindowDC dc(NULL);
dc.HIMETRICtoDP(&size); // convert to pixels
}
else
{
deviceContext->HIMETRICtoDP(&size);
}
return size;
}
PictureView.h:
#pragma once
#include <afxwin.h>
#include <string>
class Picture;
class PictureView : public CStatic
{
public:
PictureView(std::string path);
protected:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
private:
Picture* m_picture;
};
PictureView.cpp:
#include "PictureView.h"
#include "Picture.h"
PictureView::PictureView(std::string path)
{
m_picture = new Picture();
m_picture->load(path.c_str());
}
void PictureView::DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
{
CRect rect;
GetClientRect(&rect);
m_picture->draw(GetDC(), rect, rect);
}
Constructor call:
CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId)
{
PictureView* image = new PictureView(path);
image->Create("", SS_OWNERDRAW, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId);
return image;
}
The problem is that I can't get the DrawItem function to be called. What am I doing wrong?
Any help will be appreciated.
Here's an easy way to draw an image in an MFC dialog box:
link with gdiplus.dll
#include "atlimage.h>
#include "gdiplus.h>
using namespace Gdiplus
.
.
.
CImage ci;
ci.Load((CString)"D:\\Pictures\\mycat.jpg");
CDC *dc = AfxGetMainWnd()->GetDC();
HDC hdc = *dc;
ci.Draw(hdc,10,10);
Hope it works!
with the help of a colleague of mine I've found the answer. He told me it's not possible to have an ownerdrawn CStatic. So when I now inherit PictureView from CButton and make it BS_OWNERDRAW my image is rendered.
Personally I think this is an ugly solution but I'm so tired of this problem now that I don't really care that much. These are the changes I've made to make it work:
Constructor call:
CWnd* GenericChildWidget::addImage(std::string path, int horizontalPos, int width, int verticalPos, int height, int childId)
{
PictureView* image = new PictureView(path);
image->Create("", BS_OWNERDRAW | WS_CHILD | WS_VISIBLE, CRect(horizontalPos, verticalPos, width + horizontalPos, height + verticalPos), this, childId);
return image;
}
PictureView.h:
#pragma once
#include <afxwin.h>
#include <string>
class Picture;
class PictureView : public CButton
{
public:
PictureView(std::string path);
protected:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
private:
Picture* m_picture;
};
Thank's everybody for all the help.
I'm not sure that the GetDC in the call to m_picture->draw will necessarily refer to the same DC that's given in the CREATESTRUCT. What I've done is:
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
EDIT: Since I can't comment, hopefully an edit will suffice. I think your colleague is mistaken, as I just recently implemented a CStatic control using SS_OWNERDRAW. I'm guessing that the addition of WS_CHILD | WS_VISIBLE on the Create call is key.
I've never used MFC but a quick perusal of the CStatic::DrawItem documentation says that it must be created with the SS_OWNERDRAW style for DrawItem to get called. You haven't shown the Create line for your PictureView so perhaps it's that?