OpenGL won't draw my quad - c++

I've learnt a bit of OpenGL using java. Now I'm trying to transition to C++.
I'm trying to setup a window and render a quad, but its not showing up. I just get a black screen.
I'm using an example from the OpenGL Superbible as a start.
Here is my code:
#include <stdio.h>
#define GLEW_STATIC
#include "include\GL\glew.h"
#include "include\GL\wglew.h"
#pragma comment(lib, "lib\\glew32s.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
HWND g_hWnd;
HGLRC g_hRC;
HDC g_hDC;
HINSTANCE g_hInstance;
WNDCLASS g_windClass;
RECT g_windowRect;
bool g_ContinueRendering;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glVertex3f(-10.0f, -10.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, 5.0f);
glVertex3f(10.0f, 10.0f, 5.0f);
glVertex3f(10.0f, -10.0f, 5.0f);
glEnd();
printf("%s", gluErrorString(glGetError()));
SwapBuffers(g_hDC);
}
///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0f, float(w) / float(h), 1.0f, 500.0f);
}
///////////////////////////////////////////////////////////////////////////////
// Callback functions to handle all window functions this app cares about.
// Once complete, pass message on to next app in the hook chain.
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
unsigned int key = 0;
// Handle relevant messages individually
switch(uMsg)
{
case WM_ACTIVATE:
case WM_SETFOCUS:
RenderScene();
return 0;
case WM_SIZE:
ChangeSize(LOWORD(lParam),HIWORD(lParam));
RenderScene();
break;
case WM_CLOSE:
g_ContinueRendering = false;
PostQuitMessage(0);
return 0;
default:
// Nothing to do now
break;
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
bool setupWindow(int nWidth, int nHeight)
{
bool bRetVal = true;
int nWindowX = 0;
int nWindowY = 0;
int nPixelFormat = -1;
PIXELFORMATDESCRIPTOR pfd;
DWORD dwExtStyle;
DWORD dwWindStyle;
HINSTANCE g_hInstance = GetModuleHandle(NULL);
TCHAR szWindowName[50] = TEXT("Block Redux");
TCHAR szClassName[50] = TEXT("OGL_CLASS");
// setup window class
g_windClass.lpszClassName = szClassName; // Set the name of the Class
g_windClass.lpfnWndProc = (WNDPROC)WndProc;
g_windClass.hInstance = g_hInstance; // Use this module for the module handle
g_windClass.hCursor = LoadCursor(NULL, IDC_ARROW);// Pick the default mouse cursor
g_windClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);// Pick the default windows icons
g_windClass.hbrBackground = NULL; // No Background
g_windClass.lpszMenuName = NULL; // No menu for this window
g_windClass.style = CS_HREDRAW | CS_OWNDC | // set styles for this class, specifically to catch
CS_VREDRAW; // window redraws, unique DC, and resize
g_windClass.cbClsExtra = 0; // Extra class memory
g_windClass.cbWndExtra = 0; // Extra window memory
// Register the newly defined class
if(!RegisterClass( &g_windClass ))
bRetVal = false;
dwExtStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwWindStyle = WS_OVERLAPPEDWINDOW;
ShowCursor(TRUE);
g_windowRect.left = nWindowX;
g_windowRect.right = nWindowX + nWidth;
g_windowRect.top = nWindowY;
g_windowRect.bottom = nWindowY + nHeight;
// Setup window width and height
AdjustWindowRectEx(&g_windowRect, dwWindStyle, FALSE, dwExtStyle);
//Adjust for adornments
int nWindowWidth = g_windowRect.right - g_windowRect.left;
int nWindowHeight = g_windowRect.bottom - g_windowRect.top;
// Create window
g_hWnd = CreateWindowEx(dwExtStyle, // Extended style
szClassName, // class name
szWindowName, // window name
dwWindStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,// window stlye
nWindowX, // window position, x
nWindowY, // window position, y
nWindowWidth, // height
nWindowHeight, // width
NULL, // Parent window
NULL, // menu
g_hInstance, // instance
NULL); // pass this to WM_CREATE
// now that we have a window, setup the pixel format descriptor
g_hDC = GetDC(g_hWnd);
// Set a dummy pixel format so that we can get access to wgl functions
SetPixelFormat( g_hDC, 1,&pfd);
// Create OGL context and make it current
g_hRC = wglCreateContext( g_hDC );
wglMakeCurrent( g_hDC, g_hRC );
if (g_hDC == 0 ||
g_hDC == 0)
{
bRetVal = false;
printf("!!! An error occured creating an OpenGL window.\n");
}
// Setup GLEW which loads OGL function pointers
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
bRetVal = false;
printf("Error: %s\n", glewGetErrorString(err));
}
const GLubyte *oglVersion = glGetString(GL_VERSION);
printf("This system supports OpenGL Version %s.\n", oglVersion);
// Now that extensions are setup, delete window and start over picking a real format.
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
ReleaseDC(g_hWnd, g_hDC);
DestroyWindow(g_hWnd);
// Create the window again
g_hWnd = CreateWindowEx(dwExtStyle, // Extended style
szClassName, // class name
szWindowName, // window name
dwWindStyle |
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN,// window stlye
nWindowX, // window position, x
nWindowY, // window position, y
nWindowWidth, // height
nWindowHeight, // width
NULL, // Parent window
NULL, // menu
g_hInstance, // instance
NULL); // pass this to WM_CREATE
g_hDC = GetDC(g_hWnd);
int nPixCount = 0;
// Specify the important attributes we care about
int pixAttribs[] =
{
WGL_SUPPORT_OPENGL_ARB, 1, // Must support OGL rendering
WGL_DRAW_TO_WINDOW_ARB, 1, // pf that can run a window
WGL_COLOR_BITS_ARB, 24, // 8 bits of each R, G and B
WGL_DEPTH_BITS_ARB, 16, // 16 bits of depth precision for window
WGL_DOUBLE_BUFFER_ARB, GL_TRUE, // Double buffered context
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, // MSAA on
WGL_SAMPLES_ARB, 8, // 8x MSAA
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, // pf should be RGBA type
0 // NULL termination
};
// Ask OpenGL to find the most relevant format matching our attribs
// Only get one format back.
wglChoosePixelFormatARB(g_hDC, &pixAttribs[0], NULL, 1, &nPixelFormat, (UINT*)&nPixCount);
if(nPixelFormat == -1)
{
// Couldn't find a format, perhaps no 3D HW or drivers are installed
g_hDC = 0;
g_hDC = 0;
bRetVal = false;
printf("!!! An error occurred trying to find a pixel format with the requested attribs.\n");
}
else
{
// Got a format, now set it as the current one
SetPixelFormat( g_hDC, nPixelFormat, &pfd );
GLint attribs[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
0 };
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.3 context.\n");
attribs[3] = 2;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.2 context.\n");
attribs[3] = 1;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.1 context.\n");
attribs[3] = 0;
g_hRC = wglCreateContextAttribsARB(g_hDC, 0, attribs);
if (g_hRC == NULL)
{
printf("!!! Could not create an OpenGL 3.0 context.\n");
printf("!!! OpenGL 3.0 and higher are not supported on this system.\n");
}
}
}
}
wglMakeCurrent( g_hDC, g_hRC );
}
if (g_hDC == 0 ||
g_hDC == 0)
{
bRetVal = false;
printf("!!! An error occured creating an OpenGL window.\n");
}
// If everything went as planned, display the window
if( bRetVal )
{
ShowWindow( g_hWnd, SW_SHOW );
SetForegroundWindow( g_hWnd );
SetFocus( g_hWnd );
g_ContinueRendering = true;
}
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Cleanup window, OGL context and related state
// Called on exit and on error
bool KillWindow( )
{
bool bRetVal = true;
//Cleanup OGL RC
if(g_hRC)
{
wglMakeCurrent(NULL, NULL);
wglDeleteContext(g_hRC);
g_hRC = NULL;
}
// release the DC
if(g_hDC)
{
ReleaseDC(g_hWnd, g_hDC);
g_hDC = NULL;
}
// Destroy the window
if(g_hWnd)
{
DestroyWindow(g_hWnd);
g_hWnd = NULL;;
}
// Delete the window class
TCHAR szClassName[50] = TEXT("OGL_CLASS");
UnregisterClass(szClassName, g_hInstance);
g_hInstance = NULL;
ShowCursor(TRUE);
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Main rendering loop
// Check for window messages and handle events, also draw scene
void mainLoop()
{
MSG msg;
// Check for waiting mssgs
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
g_ContinueRendering = false;
}
else
{
// Deal with mssgs
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
RenderScene();
}
}
int main(int argc, char **argv)
{
if(setupWindow(800, 600))
{
ChangeSize(800, 600);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while (g_ContinueRendering)
{
mainLoop();
}
}
KillWindow();
return 0;
}
I'm pretty sure all the window setup stuff is working.
If i change the glClearColor, the windows color changes.
I hope someone can see what's wrong with it.

Looking at your code, you're using OpenGL 3.x.
Try triangles, as GL_QUADS is deprecated.
Also, you should pass CreateContextAttrib the minimum version you require, you will automatically get a newer version if available.

You're drawing them behind you. The z-value of your quad is +5, but in OpenGL, forward is negative in the z direction. Change the z-value to -5 and I think you'll see something.
Or add:
glPushMatrix();
glTranslatef(0,0,-20.0f);
//Your code for drawing.
glBegin(GL_QUADS);
...
glEnd();
//Added
glPopMatrix();

I'm just shooting from the hip here, but have you tried changing the order of the vertices? This could be the culprit of backface culling.

Related

Why is D2D drawing under D3D11?

My intuition is that if X is drawn before Y then X will be under Y. However, my code seems to always draw things drawn by D2D under things drawn by D3D11. This happens regardless of whether I'm using a depth buffer or not. Why is it doing this and how can I make D2D draw over D3D11 so that I can use D2D to create a GUI overlay?
Here is the smallest reproducible sample I could make:
#include <Windows.h>
#include <string>
#include <d3d11.h>
#include <d2d1.h>
#include <wrl.h>
#include <d3dcompiler.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "d3dcompiler.lib")
using namespace std;
using namespace Microsoft::WRL;
// Globals
HWND g_hWnd;
// D3D11
ComPtr<ID3D11Device> g_device;
ComPtr<ID3D11DeviceContext> g_context;
ComPtr<IDXGISwapChain> g_swapChain;
ComPtr<ID3D11RenderTargetView> g_renderTarget;
ComPtr<ID3D11Buffer> g_triangleVertexBuffer;
// D2D
ComPtr<ID2D1RenderTarget> g_renderTarget2D;
ComPtr<ID2D1Factory> g_factory2D;
// Utilities
constexpr const char* VERTEX_SHADER_CODE =
R"(
float4 main(float2 pos : POSITION) : SV_Position
{
return float4(pos, 0.0f, 1.0f);
}
)";
constexpr const char* PIXEL_SHADER_CODE =
R"(
float4 main() : SV_Target
{
return float4(1.0f, 0.0f, 0.0f, 1.0f);
}
)";
struct Vector2f
{
float x, y;
Vector2f() : x(0.0f), y(0.0f) { }
Vector2f(float x, float y) : x(x), y(y) { }
};
void AssertHResult(HRESULT hr, string errorMsg)
{
if (FAILED(hr))
throw std::exception(errorMsg.c_str());
}
void CompileShaderFromString(string code, string shaderType, ID3DBlob** output)
{
AssertHResult(D3DCompile(
code.c_str(),
code.length(),
nullptr,
nullptr,
nullptr,
"main",
shaderType.c_str(),
#ifdef _DEBUG
D3DCOMPILE_DEBUG |
#else
D3DCOMPILE_OPTIMIZATION_LEVEL3 |
#endif
D3DCOMPILE_ENABLE_STRICTNESS,
NULL,
output,
nullptr
), "Failed to compile shader");
}
// Graphics stuff
void InitializeD2D()
{
// Get swap chain surface
ComPtr<IDXGISurface> surface;
AssertHResult(g_swapChain->GetBuffer(
0,
__uuidof(IDXGISurface),
static_cast<void**>(&surface)
), "Failed to get surface of swap chain");
// Create factory
AssertHResult(D2D1CreateFactory<ID2D1Factory>(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&g_factory2D
), "Failed to create factory");
// Create render target
D2D1_RENDER_TARGET_PROPERTIES rtDesc = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_HARDWARE,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)
);
AssertHResult(g_factory2D->CreateDxgiSurfaceRenderTarget(
surface.Get(),
&rtDesc,
&g_renderTarget2D
), "Failed to create D2D render target");
}
void InitializeD3D()
{
// Get window dimensions
RECT rect{};
GetClientRect(g_hWnd, &rect);
float width = static_cast<float>(rect.right - rect.left);
float height = static_cast<float>(rect.bottom - rect.top);
// Create device, context, and swapchain
DXGI_SWAP_CHAIN_DESC scDesc{};
scDesc.BufferCount = 1;
scDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
scDesc.BufferDesc.Width = static_cast<UINT>(width);
scDesc.BufferDesc.Height = static_cast<UINT>(height);
scDesc.BufferDesc.RefreshRate.Numerator = 0;
scDesc.BufferDesc.RefreshRate.Denominator = 0;
scDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
scDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scDesc.Flags = NULL;
scDesc.OutputWindow = g_hWnd;
scDesc.SampleDesc.Count = 1;
scDesc.SampleDesc.Quality = 0;
scDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
scDesc.Windowed = true;
AssertHResult(D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
#ifdef _DEBUG
D3D11_CREATE_DEVICE_DEBUG |
#endif
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
nullptr,
NULL,
D3D11_SDK_VERSION,
&scDesc,
&g_swapChain,
&g_device,
nullptr,
&g_context
), "Failed to create device and swapchain");
// Create render target
ComPtr<ID3D11Resource> backBuffer;
AssertHResult(g_swapChain->GetBuffer(
0,
__uuidof(ID3D11Resource),
static_cast<void**>(&backBuffer)
), "Failed to get back buffer of swapchain");
AssertHResult(g_device->CreateRenderTargetView(
backBuffer.Get(),
nullptr,
&g_renderTarget
), "Failed to create render target view");
// Bind render target
g_context->OMSetRenderTargets(
1,
g_renderTarget.GetAddressOf(),
nullptr
);
// Bind viewport
D3D11_VIEWPORT viewport{};
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = width;
viewport.Height = height;
g_context->RSSetViewports(
1,
&viewport
);
}
void InitializeD3DTriangle()
{
// Create vertex buffer
Vector2f vertices[3] =
{
Vector2f(-0.5f, -0.5f),
Vector2f(0.0f, 0.5f),
Vector2f(0.5f, -0.5f)
};
D3D11_BUFFER_DESC vbDesc{};
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbDesc.ByteWidth = static_cast<UINT>(sizeof(Vector2f) * 3);
vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
vbDesc.MiscFlags = NULL;
vbDesc.StructureByteStride = sizeof(Vector2f);
vbDesc.Usage = D3D11_USAGE_DYNAMIC;
D3D11_SUBRESOURCE_DATA vbData{};
vbData.pSysMem = vertices;
AssertHResult(g_device->CreateBuffer(
&vbDesc,
&vbData,
&g_triangleVertexBuffer
), "Failed to create vertex buffer");
// Bind vertex buffer
const UINT offset = 0;
const UINT stride = sizeof(Vector2f);
g_context->IASetVertexBuffers(
0,
1,
g_triangleVertexBuffer.GetAddressOf(),
&stride,
&offset
);
// Create and bind vertex shader
ComPtr<ID3DBlob> vsBlob;
ComPtr<ID3D11VertexShader> vertexShader;
CompileShaderFromString(
VERTEX_SHADER_CODE,
"vs_4_0",
&vsBlob
);
AssertHResult(g_device->CreateVertexShader(
vsBlob->GetBufferPointer(),
vsBlob->GetBufferSize(),
nullptr,
&vertexShader
), "Failed to create vertex shader");
g_context->VSSetShader(
vertexShader.Get(),
nullptr,
NULL
);
// Create and bind pixel shader
ComPtr<ID3DBlob> pxBlob;
ComPtr<ID3D11PixelShader> pixelShader;
CompileShaderFromString(
PIXEL_SHADER_CODE,
"ps_4_0",
&pxBlob
);
AssertHResult(g_device->CreatePixelShader(
pxBlob->GetBufferPointer(),
pxBlob->GetBufferSize(),
nullptr,
&pixelShader
), "Failed to create pixel shader");
g_context->PSSetShader(
pixelShader.Get(),
nullptr,
NULL
);
// Set topology
g_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY::D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Create input layout
ComPtr<ID3D11InputLayout> inputLayout;
D3D11_INPUT_ELEMENT_DESC ilDesc{};
ilDesc.AlignedByteOffset = 0;
ilDesc.Format = DXGI_FORMAT_R32G32_FLOAT;
ilDesc.SemanticName = "POSITION";
ilDesc.SemanticIndex = 0;
ilDesc.InputSlot = 0;
ilDesc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
ilDesc.InstanceDataStepRate = 0;
AssertHResult(g_device->CreateInputLayout(
&ilDesc,
1,
vsBlob->GetBufferPointer(),
vsBlob->GetBufferSize(),
&inputLayout
), "Failed to create input layout");
// Bind input layout
g_context->IASetInputLayout(inputLayout.Get());
}
// Windows
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, msg, wParam, lParam);
}
return 0;
}
void InitializeWindow(HINSTANCE hInst, int width, int height)
{
// Register window class
WNDCLASSEXW wc{};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.hInstance = hInst;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"MainWindow";
wc.style = CS_OWNDC;
RegisterClassExW(&wc);
// Adjust width and height to be client area instead of window area
RECT rc{};
rc.left = 0;
rc.top = 0;
rc.right = width;
rc.bottom = height;
constexpr auto ws = WS_OVERLAPPEDWINDOW;
AdjustWindowRectEx(
&rc,
ws,
false,
NULL
);
// Instantiate and show window
g_hWnd = CreateWindowExW(
NULL,
L"MainWindow",
L"Window Title",
ws,
CW_USEDEFAULT,
CW_USEDEFAULT,
static_cast<int>(rc.right - rc.left),
static_cast<int>(rc.bottom - rc.top),
NULL,
NULL,
hInst,
nullptr
);
ShowWindow(g_hWnd, SW_SHOW);
}
// Driver code
void Update()
{
// Begin frame
g_renderTarget2D->BeginDraw();
// Clear screen to black
D2D1_COLOR_F bgColour = { 0.0f, 0.0f, 0.0f, 1.0f };
g_renderTarget2D->Clear(bgColour);
// Draw D3D triangle
g_context->Draw(
3,
0
);
// Draw D2D rectangle
D2D_RECT_F rect{};
rect.bottom = 500;
rect.top = 300;
rect.left = 100;
rect.right = 700;
D2D1_COLOR_F rectColour = { 0.0f, 1.0f, 0.0f, 1.0f };
ComPtr<ID2D1SolidColorBrush> brush;
g_renderTarget2D->CreateSolidColorBrush(
rectColour,
&brush
);
g_renderTarget2D->FillRectangle(
rect,
brush.Get()
);
// End frame
AssertHResult(g_swapChain->Present(
1,
NULL
), "Failed to present swapchain");
g_renderTarget2D->EndDraw();
}
int APIENTRY wWinMain(HINSTANCE hInst, HINSTANCE prevInst, LPWSTR cmdArgs, int cmdShow)
{
InitializeWindow(hInst, 800, 600);
InitializeD3D();
InitializeD2D();
InitializeD3DTriangle();
// Run message loop
while (true)
{
// Handle windows messages
MSG msg{};
PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE);
TranslateMessage(&msg);
DispatchMessageW(&msg);
if (msg.message == WM_QUIT)
break;
// Quit is escape is pressed
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
break;
// Do frame
Update();
}
return 0;
}
If you want to control the draw order, then you shouldn't be drawing both at the same time. Call Draw, then BeginDraw / EndDraw. Don't mix them as you have no idea when Direct2D is actually flushing commands to the context in your code, and you have no explicit indication of when Direct3D is done drawing to the render target.
You can of course call Direct3D's Flush which will force all work on the GPU to complete, but it's horribly inefficient to call it every frame.

Should I use Direct3D or just Windows GDI for a fancy/high-perf Win32 app UI? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Looking for the right general approach for making a UI really snappy.
I'm thinking of developing a UI tool that might go beyond just some "in house" tool. It would involve elaborate and custom 2d elements and would need to support fast scrolling of a big virtual surface, which would likely entail redrawing tons of custom things really quickly.
I've done some GDI programming back when XP was new, and I ran into some perf issues with lots of full screen blitting (it was a slow computer anyway). I understand GDI has some degree of acceleration, but I have difficulty ascertaining what exactly I can expect to be accelerated here.
I've only used Direct3D in games. Is it reasonable to make D3D to power a windowed GUI application? Also, if I use D3D, do I have to do everything from scratch, or can I make some kind of GDI/D3D hybrid, for example, using Direct3D calls inside WM_PAINT or something, in order to leverage some Win32 stuff like menu bars or listboxes side-by-side with a panel full of D3D rendered stuff? Does anyone have an example of mixing D3D with Win32 gui junk? Or is this not really the right approach?
What do programs like AutoCad or 3ds Max or Photoshop, or other major Win32 applications with similarly elaborate UI's do?
If your GUI involves 3D manipulation of 3D scenes, Direct3D or OpenGL would probably be a win. If you are just trying to give your GUI a "non-boring" look where the controls are stylized and drawn with alpha blended bitmaps and so-on, then you're best sticking to the traditional windowing system (i.e. GDI) as the bottom-most rendering layer. However, the easiest way to achieve such a "look and feel" is to use a higher-level toolkit like wxWidgets or Qt in order to achieve the theming and customization that will make your GUI look "modern" and not like a boring corporate application.
Another option is to use XAML/WPF from a native application and use the tools that are available for creating XAML-based GUIs like Microsoft's Expression. I haven't explored that myself, but it should be feasible using the technique from this article in the March, 2013 issue of MSDN Magazine.
Simple C style D3D9 app code (display mesh).
////////////////////////////////////////////////////////////////
// Defines main Direct3D rendering funcions
#include <windows.h>
#include <mmsystem.h>
#include <d3d9.h>
#include "d3dx9.h"
#include "cube_prim.h"
#ifndef __D3D_RENDERER_H__
#define __D3D_RENDERER_H__
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"winmm.lib")
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
LPDIRECT3D9 pDirect3D = NULL;
LPDIRECT3DDEVICE9 pDirect3DDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 pDirect3DVertexBuffer = NULL;
LPDIRECT3DINDEXBUFFER9 pDirect3DIndexBuffer = NULL;
LPDIRECT3DTEXTURE9 pDirect3DTexture01 = NULL;
LPDIRECT3DTEXTURE9 pDirect3DTexture02 = NULL;
LPD3DXMESH pD3DXMesh = NULL;
D3DMATERIAL9* pDirect3DMaterial = NULL;
LPDIRECT3DTEXTURE9* pDirect3DTexture = NULL;
DWORD Subsets = 0;
FLOAT XRot = 0.0f;
FLOAT YRot = 0.0f;
HRESULT InitializeD3D(HWND hWnd)
{
D3DDISPLAYMODE dispMode;
D3DPRESENT_PARAMETERS parameters;
pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
if (pDirect3D == NULL)
return E_FAIL;
if (FAILED(pDirect3D->GetAdapterDisplayMode(
D3DADAPTER_DEFAULT,&dispMode)))
return E_FAIL;
ZeroMemory(&parameters,sizeof(D3DPRESENT_PARAMETERS));
parameters.Windowed = FALSE;
parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
parameters.BackBufferFormat = dispMode.Format;
parameters.BackBufferWidth = dispMode.Width;
parameters.BackBufferHeight = dispMode.Height;
parameters.BackBufferCount = 2;
parameters.EnableAutoDepthStencil = TRUE;
parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
if (FAILED(pDirect3D->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,hWnd,D3DCREATE_HARDWARE_VERTEXPROCESSING,
&parameters,&pDirect3DDevice)))
return E_FAIL;
pDirect3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
pDirect3DDevice->SetRenderState(D3DRS_AMBIENT,RGB(180,180,180));
pDirect3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CCW);
pDirect3DDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
//pDirect3DDevice->SetRenderState(D3DRS_AMBIENTMATERIALSOURCE,D3DMCS_COLOR2);
//pDirect3DDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE,D3DMCS_COLOR2);
pDirect3DDevice->SetRenderState(D3DRS_SPECULARENABLE,TRUE);
return S_OK;
}
HRESULT InitializeD3DBufferObject(void)
{
VOID* pVertices = NULL;
VOID* pIndicies = NULL;
if (pDirect3DDevice != NULL)
{
if (FAILED(pDirect3DDevice->CreateVertexBuffer(
sizeof(vertices),0,D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT,&pDirect3DVertexBuffer,NULL)))
return E_FAIL;
if (FAILED(pDirect3DVertexBuffer->Lock(0,
sizeof(vertices),(void**)&pVertices,NULL)))
return E_FAIL;
memcpy(pVertices,vertices,sizeof(vertices));
pDirect3DVertexBuffer->Unlock();
if (FAILED(pDirect3DDevice->CreateIndexBuffer(
sizeof(indices),0,D3DFMT_INDEX32,D3DPOOL_DEFAULT,
&pDirect3DIndexBuffer,NULL)))
return E_FAIL;
if (FAILED(pDirect3DIndexBuffer->Lock(0,
sizeof(indices),(void**)&pIndicies,NULL)))
return E_FAIL;
memcpy(pIndicies,indices,sizeof(indices));
pDirect3DIndexBuffer->Unlock();
if (FAILED(D3DXCreateTextureFromFile(pDirect3DDevice,
_T("wood.tga"),&pDirect3DTexture01)))
return E_FAIL;
if (FAILED(D3DXCreateTextureFromFile(pDirect3DDevice,
_T("stripes.tga"),&pDirect3DTexture02)))
return E_FAIL;
return S_OK;
}
else
return E_FAIL;
}
HRESULT InitialMesh(void)
{
LPD3DXBUFFER pMeshObj = NULL;
LPD3DXMATERIAL pMaterial = NULL;
char buffer[255];
if (pDirect3DDevice != NULL)
{
if (FAILED(D3DXLoadMeshFromX(_T("Dwarf\\Dwarf.x"),
D3DXMESH_SYSTEMMEM,
pDirect3DDevice,
NULL,
&pMeshObj,
NULL,
&Subsets,
&pD3DXMesh)))
return E_FAIL;
pMaterial = (D3DXMATERIAL*)pMeshObj->GetBufferPointer();
pDirect3DMaterial = new D3DMATERIAL9[Subsets];
pDirect3DTexture = new LPDIRECT3DTEXTURE9[Subsets];
for (INT i = 0; i < Subsets; i++)
{
pDirect3DMaterial[i] = pMaterial[i].MatD3D;
sprintf(buffer,"Dwarf\\");
strcat(buffer,pMaterial[i].pTextureFilename);
if (FAILED(D3DXCreateTextureFromFileA(
pDirect3DDevice,buffer,&pDirect3DTexture[i])))
return E_FAIL;
}
pMeshObj->Release();
return S_OK;
}
else
return E_FAIL;
}
VOID ChangeSize(INT cx,INT cy)
{
D3DXMATRIX projMatrix;
if (pDirect3DDevice != NULL)
{
if (cy == 0)
cy = 1;
FLOAT aspectRatio = static_cast<FLOAT>(cx) /
static_cast<FLOAT>(cy);
D3DXMatrixPerspectiveFovLH(&projMatrix,45.0f,
aspectRatio,1.0f,150.0f);
pDirect3DDevice->SetTransform(D3DTS_PROJECTION,&projMatrix);
}
}
VOID RotateScene(void)
{
if (GetAsyncKeyState(VK_ESCAPE))
exit(0);
if (GetAsyncKeyState(VK_UP))
XRot -= 0.1f;
if (GetAsyncKeyState(VK_DOWN))
XRot += 0.1f;
if (GetAsyncKeyState(VK_LEFT))
YRot -= 0.1f;
if (GetAsyncKeyState(VK_RIGHT))
YRot += 0.1f;
}
VOID RenderScene(void)
{
D3DXMATRIX worldMatrix;
D3DMATERIAL9 material;
D3DLIGHT9 light;
D3DCAPS9 caps;
D3DCOLORVALUE ambientLight = { 0.0f, 0.0f, 0.0f, 1.0f };
D3DCOLORVALUE diffuseLight = { 0.7f, 0.7f, 0.7f, 1.0f };
D3DCOLORVALUE specularLight = { 1.0f, 1.0f, 1.0f, 1.0f };
D3DCOLORVALUE materialColor = { 1.0f, 1.0f, 1.0f, 1.0f };
ZeroMemory(&material,sizeof(D3DMATERIAL9));
material.Ambient = materialColor;
material.Diffuse = materialColor;
material.Specular = specularLight;
material.Power = 20.0f;
ZeroMemory(&light,sizeof(D3DLIGHT9));
light.Ambient = ambientLight;
light.Diffuse = diffuseLight;
light.Specular = specularLight;
light.Range = 300.0f;
light.Position = D3DXVECTOR3(-30,150,-10);
light.Type = D3DLIGHT_POINT;
light.Attenuation0 = 1.0f;
if (pDirect3DDevice != NULL)
{
D3DXMatrixIdentity(&worldMatrix);
pDirect3DDevice->SetTransform(D3DTS_WORLD,&worldMatrix);
D3DXMatrixTranslation(&worldMatrix,0.0f,0.0f,4.0f);
pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
D3DXMatrixRotationX(&worldMatrix,XRot);
pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
D3DXMatrixRotationY(&worldMatrix,YRot);
pDirect3DDevice->MultiplyTransform(D3DTS_WORLD,&worldMatrix);
pDirect3DDevice->Clear(0,0,D3DCLEAR_TARGET |
D3DCLEAR_ZBUFFER,D3DCOLOR_ARGB(255,0,0,0),1.0f,0);
pDirect3DDevice->SetMaterial(&material);
pDirect3DDevice->SetLight(0,&light);
pDirect3DDevice->LightEnable(0,TRUE);
pDirect3DDevice->SetTexture(0,pDirect3DTexture01);
//pDirect3DDevice->SetTexture(1,pDirect3DTexture02);
pDirect3DDevice->SetTextureStageState(0,
D3DTSS_COLORARG1,D3DTA_TEXTURE);
pDirect3DDevice->SetTextureStageState(0,
D3DTSS_COLORARG2,D3DTA_DIFFUSE);
pDirect3DDevice->SetTextureStageState(0,
D3DTSS_COLOROP,D3DTOP_MODULATE);
pDirect3DDevice->SetTextureStageState(1,
D3DTSS_TEXCOORDINDEX,0);
pDirect3DDevice->SetTextureStageState(1,
D3DTSS_COLORARG1,D3DTA_TEXTURE);
pDirect3DDevice->SetTextureStageState(1,
D3DTSS_COLORARG1,D3DTA_TEXTURE);
pDirect3DDevice->SetTextureStageState(1,
D3DTSS_COLOROP,D3DTOP_MODULATE);
pDirect3DDevice->GetDeviceCaps(&caps);
pDirect3DDevice->SetSamplerState(0,D3DSAMP_MAXANISOTROPY,caps.MaxAnisotropy);
pDirect3DDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->SetSamplerState(1,D3DSAMP_MAXANISOTROPY,caps.MaxAnisotropy);
pDirect3DDevice->SetSamplerState(1,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->SetSamplerState(1,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->SetSamplerState(1,D3DSAMP_MIPFILTER,D3DTEXF_ANISOTROPIC);
pDirect3DDevice->BeginScene();
{
pDirect3DDevice->SetStreamSource(0,pDirect3DVertexBuffer,0,
sizeof(CUSTOMVERTEX));
pDirect3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
pDirect3DDevice->SetIndices(pDirect3DIndexBuffer);
/*pDirect3DDevice->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST,0,0,36,0,12);*/
for (int i = 0; i < Subsets; i++)
{
pDirect3DDevice->SetMaterial(&pDirect3DMaterial[i]);
pDirect3DDevice->SetTexture(0,pDirect3DTexture[i]);
pD3DXMesh->DrawSubset(i);
}
}
pDirect3DDevice->EndScene();
pDirect3DDevice->Present(NULL,NULL,NULL,NULL);
}
}
VOID ReleaseD3D(void)
{
if (pDirect3DTexture)
{
for (int i = 0; i < 0; i++)
pDirect3DTexture[i]->Release();
}
if (pDirect3DMaterial)
{
delete [] pDirect3DMaterial;
}
if (pD3DXMesh)
pD3DXMesh->Release();
if (pDirect3DTexture02)
pDirect3DTexture02->Release();
if (pDirect3DTexture01)
pDirect3DTexture01->Release();
if (pDirect3DIndexBuffer)
pDirect3DIndexBuffer->Release();
if (pDirect3DVertexBuffer)
pDirect3DVertexBuffer->Release();
if (pDirect3DDevice)
pDirect3DDevice->Release();
if (pDirect3D)
pDirect3D->Release();
}
#endif
App use simple Win32 framework with WinMain etc...
Sample code in MFC classes
#include "MainWnd.h"
#include "d3d_renderer.h"
CMainWnd::CMainWnd(void)
{
}
CMainWnd::~CMainWnd(void)
{
}
BEGIN_MESSAGE_MAP(CMainWnd, CWnd)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_PAINT()
END_MESSAGE_MAP()
// WM_CREATE
int CMainWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (FAILED(InitializeD3D(m_hWnd)))
exit(0);
if (FAILED(InitializeD3DBufferObject()))
exit(0);
if (FAILED(InitialMesh()))
exit(0);
SetTimer(33,1,NULL);
return 0;
}
// WM_DESTROY
void CMainWnd::OnDestroy()
{
CWnd::OnDestroy();
KillTimer(101);
ReleaseD3D();
}
// WM_SIZE
void CMainWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
ChangeSize(cx,cy);
}
// WM_TIMER
void CMainWnd::OnTimer(UINT_PTR nIDEvent)
{
InvalidateRect(NULL,FALSE);
CWnd::OnTimer(nIDEvent);
}
// WM_PAINT
void CMainWnd::OnPaint()
{
RotateScene();
RenderScene();
ValidateRect(NULL);
}
so decide what you want to use (D3D is significaly faster than GDI)
you can also use OpenGL to draw accelerated graphics (little bit slower than D3D) with less code amount.
Displaying 3D text with OpenGL and pure Win32 UI
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
// Palette Handle
HPALETTE hPalette = NULL;
static LPCTSTR lpszAppName = "Text3D";
GLint nFontList;
// Light values and coordinates
GLfloat whiteLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat specular[] = { 0.9f, 0.9f, 0.9f, 1.0f};
GLfloat lightPos[] = { -100.0f, 200.0f, 50.0f, 1.0f };
// Declaration for Window procedure
LRESULT CALLBACK WndProc( HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// Set Pixel Format function - forward declaration
void SetDCPixelFormat(HDC hDC);
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat nRange = 100.0f;
GLfloat fAspect;
// Prevent a divide by zero
if(h == 0)
h = 1;
fAspect = (GLfloat)w/(GLfloat)h;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
// Reset coordinate system
glLoadIdentity();
// Setup perspective for viewing
gluPerspective(17.5f,fAspect,1,300);
// Viewing transformation
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1.8f, 0.0f, -15.0f);
glRotatef(-20.0f, 0.0f, 1.0f,0.0f);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
}
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Blue 3D Text
glColor3ub(0, 0, 255);
glPushMatrix();
glListBase(nFontList);
glCallLists (6, GL_UNSIGNED_BYTE, "OpenGL");
glPopMatrix();
}
void SetupRC(HDC hDC)
{
// Setup the Font characteristics
HFONT hFont;
GLYPHMETRICSFLOAT agmf[128]; // Throw away
LOGFONT logfont;
logfont.lfHeight = -10;
logfont.lfWidth = 0;
logfont.lfEscapement = 0;
logfont.lfOrientation = 0;
logfont.lfWeight = FW_BOLD;
logfont.lfItalic = FALSE;
logfont.lfUnderline = FALSE;
logfont.lfStrikeOut = FALSE;
logfont.lfCharSet = ANSI_CHARSET;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy(logfont.lfFaceName,"Arial");
// Create the font and display list
hFont = CreateFontIndirect(&logfont);
SelectObject (hDC, hFont);
//create display lists for glyphs 0 through 128 with 0.1 extrusion
// and default deviation.
nFontList = glGenLists(128);
wglUseFontOutlines(hDC, 0, 128, nFontList, 0.0f, 0.5f,
WGL_FONT_POLYGONS, agmf);
DeleteObject(hFont);
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glEnable(GL_COLOR_MATERIAL);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0,GL_AMBIENT,whiteLight);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
glEnable(GL_LIGHT0);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glMaterialfv(GL_FRONT, GL_SPECULAR,specular);
glMateriali(GL_FRONT,GL_SHININESS,128);
}
// If necessary, creates a 3-3-2 palette for the device context listed.
HPALETTE GetOpenGLPalette(HDC hDC)
{
HPALETTE hRetPal = NULL; // Handle to palette to be created
PIXELFORMATDESCRIPTOR pfd; // Pixel Format Descriptor
LOGPALETTE *pPal; // Pointer to memory for logical palette
int nPixelFormat; // Pixel format index
int nColors; // Number of entries in palette
int i; // Counting variable
BYTE RedRange,GreenRange,BlueRange;
// Range for each color entry (7,7,and 3)
// Get the pixel format index and retrieve the pixel format description
nPixelFormat = GetPixelFormat(hDC);
DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
// Does this pixel format require a palette? If not, do not create a
// palette and just return NULL
if(!(pfd.dwFlags & PFD_NEED_PALETTE))
return NULL;
// Number of entries in palette. 8 bits yeilds 256 entries
nColors = 1 << pfd.cColorBits;
// Allocate space for a logical palette structure plus all the palette entries
pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY));
// Fill in palette header
pPal->palVersion = 0x300; // Windows 3.0
pPal->palNumEntries = nColors; // table size
// Build mask of all 1's. This creates a number represented by having
// the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
// pfd.cBlueBits.
RedRange = (1 << pfd.cRedBits) -1;
GreenRange = (1 << pfd.cGreenBits) - 1;
BlueRange = (1 << pfd.cBlueBits) -1;
// Loop through all the palette entries
for(i = 0; i < nColors; i++)
{
// Fill in the 8-bit equivalents for each component
pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
pPal->palPalEntry[i].peRed = (unsigned char)(
(double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
pPal->palPalEntry[i].peGreen = (unsigned char)(
(double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);
pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
pPal->palPalEntry[i].peBlue = (unsigned char)(
(double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);
pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
}
// Create the palette
hRetPal = CreatePalette(pPal);
// Go ahead and select and realize the palette for this device context
SelectPalette(hDC,hRetPal,FALSE);
RealizePalette(hDC);
// Free the memory used for the logical palette structure
free(pPal);
// Return the handle to the new palette
return hRetPal;
}
// Select the pixel format for a given device context
void SetDCPixelFormat(HDC hDC)
{
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
1, // Version of this structure
PFD_DRAW_TO_WINDOW | // Draw to Window (not to bitmap)
PFD_SUPPORT_OPENGL | // Support OpenGL calls in window
PFD_DOUBLEBUFFER, // Double buffered mode
PFD_TYPE_RGBA, // RGBA Color mode
32, // Want 32 bit color
0,0,0,0,0,0, // Not used to select mode
0,0, // Not used to select mode
0,0,0,0,0, // Not used to select mode
16, // Size of depth buffer
0, // Not used to select mode
0, // Not used to select mode
0, // Draw in main plane
0, // Not used to select mode
0,0,0 }; // Not used to select mode
// Choose a pixel format that best matches that described in pfd
nPixelFormat = ChoosePixelFormat(hDC, &pfd);
// Set the pixel format for the device context
SetPixelFormat(hDC, nPixelFormat, &pfd);
}
// Entry point of all Windows programs
int APIENTRY WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg; // Windows message structure
WNDCLASS wc; // Windows class structure
HWND hWnd; // Storeage for window handle
// Register Window style
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
// No need for background brush for OpenGL window
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = lpszAppName;
// Register the window class
if(RegisterClass(&wc) == 0)
return FALSE;
// Create the main application window
hWnd = CreateWindow(
lpszAppName,
lpszAppName,
// OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
// Window position and size
100, 100,
250, 250,
NULL,
NULL,
hInstance,
NULL);
// If window was not created, quit
if(hWnd == NULL)
return FALSE;
// Display the window
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
// Process application messages until the application closes
while( GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// Window procedure, handles all messages for this program
LRESULT CALLBACK WndProc( HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
static HGLRC hRC; // Permenant Rendering context
static HDC hDC; // Private GDI Device context
switch (message)
{
// Window creation, setup for OpenGL
case WM_CREATE:
// Store the device context
hDC = GetDC(hWnd);
// Select the pixel format
SetDCPixelFormat(hDC);
// Create the rendering context and make it current
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
// Create the palette
hPalette = GetOpenGLPalette(hDC);
SetupRC(hDC);
break;
// Window is being destroyed, cleanup
case WM_DESTROY:
// Kill the timer that we created
KillTimer(hWnd,101);
glDeleteLists(nFontList, 128);
// Deselect the current rendering context and delete it
wglMakeCurrent(hDC,NULL);
wglDeleteContext(hRC);
// Delete the palette
if(hPalette != NULL)
DeleteObject(hPalette);
// Tell the application to terminate after the window
// is gone.
PostQuitMessage(0);
break;
// Window is resized.
case WM_SIZE:
// Call our function which modifies the clipping
// volume and viewport
ChangeSize(LOWORD(lParam), HIWORD(lParam));
break;
// The painting function. This message sent by Windows
// whenever the screen needs updating.
case WM_PAINT:
{
// Call OpenGL drawing code
RenderScene();
// Call function to swap the buffers
SwapBuffers(hDC);
ValidateRect(hWnd,NULL);
}
break;
// Windows is telling the application that it may modify
// the system palette. This message in essance asks the
// application for a new palette.
case WM_QUERYNEWPALETTE:
// If the palette was created.
if(hPalette)
{
int nRet;
// Selects the palette into the current device context
SelectPalette(hDC, hPalette, FALSE);
// Map entries from the currently selected palette to
// the system palette. The return value is the number
// of palette entries modified.
nRet = RealizePalette(hDC);
// Repaint, forces remap of palette in current window
InvalidateRect(hWnd,NULL,FALSE);
return nRet;
}
break;
// This window may set the palette, even though it is not the
// currently active window.
case WM_PALETTECHANGED:
// Don't do anything if the palette does not exist, or if
// this is the window that changed the palette.
if((hPalette != NULL) && ((HWND)wParam != hWnd))
{
// Select the palette into the device context
SelectPalette(hDC,hPalette,FALSE);
// Map entries to system palette
RealizePalette(hDC);
// Remap the current colors to the newly realized palette
UpdateColors(hDC);
return 0;
}
break;
default: // Passes it on if unproccessed
return (DefWindowProc(hWnd, message, wParam, lParam));
}
return (0L);
}
can work without reseting palette
AS window handle you may use every legal window handles (panel, listbox, buttons etc...) so you can display 3d content almost everywhere
Photoshop use OpenGL, 3DS Max optional (OpenGL, Direct3D), AutoCad it is hard to say: GDI older versions, newest using .NET too.

Showing Wrong Language in window title and messagebox : win32 application, opengl

I was trying to create a basic window with opengl and win32 application in visual studio 2013.
Everything works fine except the window title and messages in messagebox are not showing English. My code is given below:
#include "stdafx.h"
#include "ThesisProject.h"
#define MAX_LOADSTRING 100
// ================================= Variable Region : All the global variables will be declared here with categorization =========================== //
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
HDC hDC = NULL; // Private GDI Device Context. GDI : http://en.wikipedia.org/wiki/Graphics_Device_Interface
HWND hWnd = NULL; // holds our window handle.
HINSTANCE hInstance; // holds the instance of the application
HGLRC hRC = NULL; // Permanent Rendering Context
bool keys[256]; // Array Used for the keyboard routine. this will help us to track multiple key press, like : "Ctrl + s"
bool active = TRUE; // window active flag. set to true by default.
bool fullscreen = TRUE; // fullscreen flag. set to true by default. indicates whether the screen should be windowed or fullscreen.
// ================================================================================================================================================== //
// ================================ Function prototype declaration region : all the function prototype declaration will go here. ====================== //
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // a call back function to process window action.
int InitGL(GLvoid); // this function is used for setting up opengl components.
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag); // creates the window.
int DrawGLScene(GLvoid); // this is where all the drawing goes.
GLvoid ReSizeGLScene(GLsizei width, GLsizei height); // this function is used to handle the properties when the window is resized when full screen mode is not used.
GLvoid KillGLWindow(GLvoid); // this function is called before closing the window.
// =================================================================================================================================================== //
// this function is the entry point of this project . what ever this program does, it starts from here.
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
MSG msg; // Windows Message Structure
BOOL done = FALSE; // Bool Variable To Exit Loop
// Create Our OpenGL Window
if (!CreateGLWindow("OpenGL Testing", 640, 480, 16, fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while (!done) // Loop That Runs Until done=TRUE
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message == WM_QUIT) // Have We Received A Quit Message?
{
done = TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done = TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1] = FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen = !fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("Aqib", 640, 480, 16, fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
// this function is used to initialize all the opengl components.
int InitGL(GLvoid){
glShadeModel(GL_SMOOTH); // enabling smooth shader
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // black background
glClearDepth(1.0f); // depth buffer setup
glEnable(GL_DEPTH_TEST); // enable depth testing
glDepthFunc(GL_LEQUAL); // the type of depth test to do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // really nice perspective calculations
return TRUE; // initialization went ok
}
// this function creates and registers the window to the OS.
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag){
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
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
fullscreen = fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // 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 = (LPCWSTR)"OpenGLTesting"; // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL, (LPCWSTR)"Failed To Register The Window Class.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Exit And Return FALSE
}
if (fullscreen){ // Attempt Fullscreen Mode?
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize = sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.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(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){
// If The Mode Fails, Offer Two Options. Quit Or Run In A Window.
fullscreen = FALSE;
}
}
if (fullscreen){ // Are We Still In Fullscreen Mode?
dwExStyle = WS_EX_APPWINDOW; // Window Extended Style
dwStyle = WS_POPUP; // Windows Style
ShowCursor(TRUE); // Hide Mouse Pointer
}
else{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle = WS_OVERLAPPEDWINDOW; // Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
if (!(hWnd = CreateWindowEx(dwExStyle, // Extended Style For The Window
(LPCWSTR)"OpenGLTesting", // Class Name
(LPCWSTR)title, // Window Title
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN | // Required Window Style
dwStyle, // Selected Window Style
0, 0, // Window Position
WindowRect.right - WindowRect.left, // Calculate Adjusted Window Width
WindowRect.bottom - WindowRect.top, // Calculate Adjusted Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL)))
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Window Creation Error.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE;
}
static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC = GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Can't Create A GL Device Context.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Can't Find A Suitable PixelFormat.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!SetPixelFormat(hDC, PixelFormat, &pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Can't Set The PixelFormat.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC = wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Can't Create A GL Rendering Context.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!wglMakeCurrent(hDC, hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Can't Activate The GL Rendering Context.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd, SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL, (LPCWSTR)"Initialization Failed.", (LPCWSTR)"ERROR", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
// this function is used to draw objects in the scene.
int DrawGLScene(GLvoid){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(-1.5f, 0.0f, -6.0f); // Move into space 6 units and -1.5 to the left
glColor3f(0.0f, 0.0f, 1.0f);
glBegin(GL_TRIANGLES); // Begin drawing triagle
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glEnd(); // Finished Drawing The Triangle
glTranslatef(3.0f, 0.0f, 0.0f); // Move Right 3 Units
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS); // Draw A Quad
glColor3f(1.0f, 1.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glEnd(); // Done Drawing The Quad
return TRUE; // Everything Went OK
}
// this function resizes and reinitializes the property of the opengl window when window is resized.
GLvoid ReSizeGLScene(GLsizei width, GLsizei height){
if (height == 0){ // prevent a divide by zero
height = 1; // Making height equal one
}
glViewport(0, 0, width, height); // Resize the current viewport
glMatrixMode(GL_PROJECTION); // select the projection matrix
glLoadIdentity(); // reset the projection matrix
// Calculate theaspect ratio of the window
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW); // select the model view matrix
glLoadIdentity(); // reset the modelview matrix
}
// this function is called before closing the application to properly close the window.
GLvoid KillGLWindow(GLvoid)
{
if (fullscreen)
{
ChangeDisplaySettings(NULL, 0); // If so Switch back to the Desktop.
ShowCursor(TRUE); // Show the mouse pointer.
}
if (hRC)
{
if (!wglMakeCurrent(NULL, NULL))
{
MessageBox(NULL, (LPCWSTR)"Release of DC and RC Failed", (LPCWSTR)"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are we able to delete the rendering context?
{
MessageBox(NULL, (LPCWSTR)"Release of Rendering Context Failed", (LPCWSTR)"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
}
hRC = NULL; // set rendering context to null.
}
if (hDC && !ReleaseDC(hWnd, hDC)) // Are We Able To Release The DC
{
MessageBox(NULL, (LPCWSTR)"Release Device Context Failed.", (LPCWSTR)"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hDC = NULL; // Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL, (LPCWSTR)"Could Not Release hWnd.", (LPCWSTR)"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hWnd = NULL; // Set hWnd To NULL
}
if (!UnregisterClass((LPCWSTR)"OpenGL", hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL, (LPCWSTR)"Could Not Unregister Class.", (LPCWSTR)"SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
hInstance = NULL; // Set hInstance To NULL
}
}
LRESULT CALLBACK WndProc(HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active = TRUE; // Program Is Active
}
else
{
active = FALSE; // Program Is No Longer Active
}
return 0; // Return To The Message Loop
}
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam), HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
The problem you're most likely running into is, that the Windows APIs you use expect wide character strings, but the string literals you have in your source code are standard (narrow) characters. So for every 2 consecutive characters in your strings, Windows interprets it as a single wide character; which will very likely end up in some asian script if every two bytes of a wchar are nonzero.
Solution: Use the _TEXT(…) macro to surround your string literals, turning them into wide character strings.

OpenGL Quad not drawing

I am using visual c++ 2012 and opengl and I can't get my quad to draw, I haven't been getting any errors. Is it because I don't have an update method? Here is my code:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <gl/GL.h>
HWND hwnd;
int clientWidth = 800;
int clientHeight = 600;
bool InitMainWindow(HINSTANCE hInstance);
LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if(!InitMainWindow(hInstance))
{
return 1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 0, 600, 1, -1);
glMatrixMode(GL_MODELVIEW);
MSG msg = {0};
while(WM_QUIT != msg.message)
{
if(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(0.5f,0.5f,1.0f);
glPushMatrix();
glTranslatef(0,0,-20.0f);
glBegin(GL_QUADS);
glVertex3f(-10.0f, -10.0f, 5.0f);
glVertex3f(-10.0f, 10.0f, 5.0f);
glVertex3f(10.0f, 10.0f, 5.0f);
glVertex3f(10.0f, -10.0f, 5.0f);
glEnd();
glPopMatrix();
}
}
return static_cast<int>(msg.wParam);
}
bool InitMainWindow(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.hInstance = hInstance;
wcex.lpfnWndProc = MsgProc;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszClassName = "Project2DClass";
wcex.lpszMenuName = NULL;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wcex))
{
MessageBox(NULL, "Failed to register window class", NULL, NULL);
return false;
}
RECT r = { 0, 0, clientWidth, clientHeight };
DWORD style = WS_OVERLAPPEDWINDOW;
AdjustWindowRect(&r, style, false);
int width = r.right - r.left;
int height = r.bottom - r.top;
int x = GetSystemMetrics(SM_CXSCREEN)/2 - width/2;
int y = GetSystemMetrics(SM_CYSCREEN)/2 - height/2;
hwnd = CreateWindow("Project2DClass", "Project 2D", style, x, y, width, height, NULL, NULL, hInstance, NULL);
if(!hwnd)
{
MessageBox(NULL, "Failed to create window", NULL, NULL);
return false;
}
ShowWindow(hwnd, SW_SHOW);
return true;
}
LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
How can I fix this and what have I done wrong?
Also how do I create an update and sync method?
I fixed it!!!
Here is my code:
/*
* This Code Was Created By Jeff Molofee 2000
* A HUGE Thanks To Fredric Echols For Cleaning Up
* And Optimizing This Code, Making It More Flexible!
* If You've Found This Code Useful, Please Let Me Know.
* Visit My Site At nehe.gamedev.net
*/
#include <windows.h> // Header File For Windows
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}
glViewport(0,0,width,height); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
return TRUE; // Initialization Went OK
}
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
//glClearColor(0.5f, 0.5f, 0, 0);
glColor3f(0.5f,0.5f,0);
glPushMatrix();
glTranslatef(0,0,-20.0f);
glBegin(GL_QUADS);
glVertex3f(-5.0f, -5.0f, 2.5f);
glVertex3f(-5.0f, 5.0f, 2.5f);
glVertex3f(5.0f, 5.0f, 2.5f);
glVertex3f(5.0f, -5.0f, 2.5f);
glEnd();
glPopMatrix();
return TRUE; // Everything Went OK
}
GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}
if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}
if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}
if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
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
fullscreen=fullscreenflag; // Set The Global Fullscreen Flag
hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // 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 = "OpenGL"; // Set The Class Name
if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.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(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}
if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size
// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};
if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen
if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}
return TRUE; // Success
}
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}
return 0; // Return To The Message Loop
}
case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}
case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}
case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}
case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop
// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}
// Create Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
http://nehe.gamedev.net/tutorial/creating_an_opengl_window_%28win32%29/13001/

Multiple full-screen windows with DirectX 9.0

This is a bit of an edge case but I am developing a game which uses multiple monitors. For reasons outside the scope of this question, I am using a 'multi-device method' rather than swap chains. My code is similar to the following sample:
http://www.codesampler.com/dx9src/dx9src_1.htm#dx9_multiple_devices
What I'm struggling with, and what I can find no documentation about, is whether it's possible to run both windows in true full-screen (i.e d3dpp.Windowed = FALSE;). Currently I'm getting an 'invalid params' HRESULT when calling CreateDevice the second time. It works fine if one of the windows is full-screen, but not both. I'm hoping there's a setting to make this work though...
Cheers in advance
According to the Direct3D 9 documentation (Working with Multiple Monitor Systems): "The practical implication is that a multiple monitor application can place several devices in full-screen mode, but only if all these devices are for different adapters, were created by the same Direct3D9 object, and all share the same focus window."
You'll notice that there are two window handles per device initialization; the presentation window, and the focus window. The focus window (passed in to IDirect3D9::CreateDevice) is used for handling events such as switching from foreground to background, or Alt+Tab. The presentation window is passed in to the D3DPRESENT_PARAMETERS structure and is used solely as a canvas for Direct3D.
You should mark one of the windows you create (probably the first one) as the focus window. Share the focus window across devices but keep the "canvas" (presentation) windows separate.
EDIT: This may help you as well.
create a focus window for both devices.
(optionally) create a device window for the first adapter.
create a device window for the second adapter.
create a direct3d9 context.
use this to create both devices.
create the first fullscreen device using the shared focus window and (optionally) the first device window.
create the second fullscreen device using the shared focus window and the second device window.
reset the first device.
the shared focus window is passed directly as a parameter to CreateDevice.
the device windows are passed in the presentation parameters structure.
Q> Currently I'm getting an 'invalid params' HRESULT when calling CreateDevice the second time. It works fine if one of the windows is
full-screen, but not both.
Because you were creating two different devices using a same adapter id 0. Use the adater id as 1 for the second create device call !
Important step to be done after the creation of device 2 or 3 or 4... is to reset the device one (default device id 0).
Create Device 1
Create Device 2
........
........
Create Device n
Reset Device 1
For to make your and another's life easier I have added a working code for supporting Multiple Monitors in Full Screen (Directx 9). Please note that I have added/changed few lines of code from the sample code took from the web link you have mentioned in your question.
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "resource.h"
// define the screen resolution
#define SCREEN_WIDTH 1920
#define SCREEN_HEIGHT 1080
//-----------------------------------------------------------------------------
// GLOBALS
//-----------------------------------------------------------------------------
LPDIRECT3D9 g_pD3D = NULL;
HWND g_hWnd_0 = NULL; // Handle to the first window
HWND g_hWnd_1 = NULL; // Handle to the second window
LPDIRECT3DDEVICE9 g_pd3dDevice_0 = NULL; // Direct3d device for the first window
LPDIRECT3DDEVICE9 g_pd3dDevice_1 = NULL; // Direct3d device for the second window
LPD3DXMESH g_pTeapotMesh_0 = NULL; // The two devices can't share resources, so we'll
LPD3DXMESH g_pTeapotMesh_1 = NULL; // have to create two meshes... one for each device
D3DMATERIAL9 g_teapotMtrl;
D3DLIGHT9 g_pLight0;
LPD3DXFONT g_pd3dxFont = NULL;
DWORD g_dwBackBufferWidth = 0;
DWORD g_dwBackBufferHeight = 0;
bool windowed = false;
float g_fSpinX = 0.0f;
float g_fSpinY = 0.0f;
double g_dElpasedFrameTime = 0.0f;
double g_dElpasedAppTime = 0.0f;
double g_dCurrentTime = 0.0f;
double g_dLastTime = 0.0f;
struct Vertex
{
float x, y, z; // Position of vertex in 3D space
float nx, ny, nz; // Normal for lighting calculations
DWORD diffuse; // Diffuse color of vertex
enum FVF
{
FVF_Flags = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE
};
};
#define TWO
//-----------------------------------------------------------------------------
// PROTOTYPES
//-----------------------------------------------------------------------------
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
void CreateFont(void);
void init_0(void);
void init_1(void);
void shutDown_0(void);
void shutDown_1(void);
void render_0(void);
void render_1(void);
void LoadModels(void);
void ResetDevice(void);
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
WNDCLASSEX winClass;
MSG uMsg;
bool deviceReset = FALSE;
memset(&uMsg,0,sizeof(uMsg));
winClass.lpszClassName = "MY_WINDOWS_CLASS";
winClass.cbSize = sizeof(WNDCLASSEX);
winClass.style = CS_HREDRAW | CS_VREDRAW;
winClass.lpfnWndProc = WindowProc;
winClass.hInstance = hInstance;
winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
if(!RegisterClassEx( &winClass) )
return E_FAIL;
//
// Create window #0...
//
g_hWnd_0 = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
"Direct3D (DX9) - Multiple Devices (Window #0)",
WS_EX_TOPMOST | WS_POPUP, // fullscreen values /* WS_OVERLAPPEDWINDOW | WS_VISIBLE,*/
0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL );
if( g_hWnd_0 == NULL )
return E_FAIL;
ShowWindow( g_hWnd_0, nCmdShow );
UpdateWindow( g_hWnd_0 );
#ifdef TWO
//
// Create window #1...
//
g_hWnd_1 = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
"Direct3D (DX9) - Multiple Devices (Window #1)",
WS_EX_TOPMOST | WS_POPUP, // fullscreen values /* WS_OVERLAPPEDWINDOW | WS_VISIBLE,*/
1920, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL );
if( g_hWnd_1 == NULL )
return E_FAIL;
ShowWindow( g_hWnd_1, nCmdShow );
UpdateWindow( g_hWnd_1 );
#endif
//
// Init Direct3D usage on both windows...
//
init_0();
#ifdef TWO
init_1();
#endif
ResetDevice(); // Important !!!
LoadModels();
while( uMsg.message != WM_QUIT )
{
if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &uMsg );
DispatchMessage( &uMsg );
}
else
{
g_dCurrentTime = timeGetTime();
g_dElpasedFrameTime = g_dCurrentTime - g_dLastTime; // How much time has passed since the last frame?
g_dElpasedAppTime += g_dElpasedFrameTime; // How much time has passed overall for the application?
g_dLastTime = g_dCurrentTime;
render_0();
#ifdef TWO
render_1();
#endif
}
}
//
// Cleanup Direct3D usage on both windows...
//
#ifdef TWO
shutDown_1();
#endif
shutDown_0();
UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );
return uMsg.wParam;
}
void ResetDevice(void)
{
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = windowed;
d3dpp.hDeviceWindow = g_hWnd_0;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH; // set the width of the buffer
d3dpp.BackBufferHeight = SCREEN_HEIGHT; // set the height of the buffer
d3dpp.BackBufferCount = 1;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
g_pd3dDevice_0->Reset(&d3dpp);
}
void LoadModels(void)
{
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian(45.0f), 1920.0f / 1080.0f, 0.1f, 100.0f );
g_pd3dDevice_0->SetTransform( D3DTS_PROJECTION, &matProj );
g_pd3dDevice_0->SetRenderState( D3DRS_ZENABLE, TRUE );
g_pd3dDevice_0->SetRenderState( D3DRS_LIGHTING, TRUE );
g_pd3dDevice_0->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
// Setup a material for the teapot
ZeroMemory( &g_teapotMtrl, sizeof(D3DMATERIAL9) );
g_teapotMtrl.Diffuse.r = 1.0f;
g_teapotMtrl.Diffuse.g = 1.0f;
g_teapotMtrl.Diffuse.b = 1.0f;
g_teapotMtrl.Diffuse.a = 1.0f;
// Setup a simple directional light and some ambient...
g_pLight0.Type = D3DLIGHT_DIRECTIONAL;
g_pLight0.Direction = D3DXVECTOR3( 1.0f, 0.0f, 1.0f );
g_pLight0.Diffuse.r = 1.0f;
g_pLight0.Diffuse.g = 1.0f;
g_pLight0.Diffuse.b = 1.0f;
g_pLight0.Diffuse.a = 1.0f;
g_pLight0.Specular.r = 1.0f;
g_pLight0.Specular.g = 1.0f;
g_pLight0.Specular.b = 1.0f;
g_pLight0.Specular.a = 1.0f;
g_pd3dDevice_0->SetLight( 0, &g_pLight0 );
g_pd3dDevice_0->LightEnable( 0, TRUE );
g_pd3dDevice_0->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );
// Load up the teapot mesh...
D3DXLoadMeshFromX( "teapot.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice_0, NULL, NULL, NULL, NULL, &g_pTeapotMesh_0 );
CreateFont();
#ifndef TWO
return;
#endif
D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian(45.0f), 1920.0f / 1080.0f, 0.1f, 100.0f );
g_pd3dDevice_1->SetTransform( D3DTS_PROJECTION, &matProj );
g_pd3dDevice_1->SetRenderState( D3DRS_ZENABLE, TRUE );
g_pd3dDevice_1->SetRenderState( D3DRS_LIGHTING, TRUE );
g_pd3dDevice_1->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
// Setup a material for the teapot
ZeroMemory( &g_teapotMtrl, sizeof(D3DMATERIAL9) );
g_teapotMtrl.Diffuse.r = 1.0f;
g_teapotMtrl.Diffuse.g = 1.0f;
g_teapotMtrl.Diffuse.b = 1.0f;
g_teapotMtrl.Diffuse.a = 1.0f;
// Setup a simple directional light and some ambient...
g_pLight0.Type = D3DLIGHT_DIRECTIONAL;
g_pLight0.Direction = D3DXVECTOR3( 1.0f, 0.0f, 1.0f );
g_pLight0.Diffuse.r = 1.0f;
g_pLight0.Diffuse.g = 1.0f;
g_pLight0.Diffuse.b = 1.0f;
g_pLight0.Diffuse.a = 1.0f;
g_pLight0.Specular.r = 1.0f;
g_pLight0.Specular.g = 1.0f;
g_pLight0.Specular.b = 1.0f;
g_pLight0.Specular.a = 1.0f;
g_pd3dDevice_1->SetLight( 0, &g_pLight0 );
g_pd3dDevice_1->LightEnable( 0, TRUE );
g_pd3dDevice_1->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );
// Load up the teapot mesh...
D3DXLoadMeshFromX( "teapot.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice_1, NULL, NULL, NULL, NULL, &g_pTeapotMesh_1 );
}
//-----------------------------------------------------------------------------
// Name: WindowProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
static POINT ptLastMousePosit;
static POINT ptCurrentMousePosit;
static bool bMousing;
switch( msg )
{
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
}
break;
case WM_LBUTTONDOWN:
{
ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
bMousing = true;
}
break;
case WM_LBUTTONUP:
{
bMousing = false;
}
break;
case WM_MOUSEMOVE:
{
ptCurrentMousePosit.x = LOWORD (lParam);
ptCurrentMousePosit.y = HIWORD (lParam);
if( bMousing )
{
g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
}
ptLastMousePosit.x = ptCurrentMousePosit.x;
ptLastMousePosit.y = ptCurrentMousePosit.y;
}
break;
case WM_CLOSE:
{
PostQuitMessage(0);
}
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc( hWnd, msg, wParam, lParam );
}
break;
}
return 0;
}
void CreateFont( void )
{
HRESULT hr;
HDC hDC;
//HFONT hFont;
int nHeight;
int nPointSize = 9;
//char strFontName[] = "Arial";
hDC = GetDC( NULL );
nHeight = -( MulDiv( nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ) );
ReleaseDC( NULL, hDC );
// Create a font for statistics and help output
hr = D3DXCreateFont( g_pd3dDevice_0, nHeight, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &g_pd3dxFont );
if( FAILED( hr ) ) MessageBox(NULL, "Call to D3DXCreateFont failed!", "ERROR", MB_OK | MB_ICONEXCLAMATION);
}
//-----------------------------------------------------------------------------
// Name: init_0()
// Desc:
//-----------------------------------------------------------------------------
void init_0( void )
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = windowed;
d3dpp.hDeviceWindow = g_hWnd_0;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH; // set the width of the buffer
d3dpp.BackBufferHeight = SCREEN_HEIGHT; // set the height of the buffer
d3dpp.BackBufferCount = 1;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd_0, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice_0 );
}
//-----------------------------------------------------------------------------
// Name: init_1()
// Desc:
//-----------------------------------------------------------------------------
void init_1( void )
{
HWND window;
if(!windowed)
{
window = g_hWnd_0;
}
else
{
window = g_hWnd_1;
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = windowed;
d3dpp.hDeviceWindow = window;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH; // set the width of the buffer
d3dpp.BackBufferHeight = SCREEN_HEIGHT; // set the height of the buffer
d3dpp.BackBufferCount = 1;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
g_pD3D->CreateDevice( 1, D3DDEVTYPE_HAL, window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice_1 );
}
//-----------------------------------------------------------------------------
// Name: shutDown()
// Desc:
//-----------------------------------------------------------------------------
void shutDown_0( void )
{
if( g_pTeapotMesh_0 != NULL )
g_pTeapotMesh_0->Release();
if( g_pd3dDevice_0 != NULL )
g_pd3dDevice_0->Release();
if( g_pD3D != NULL )
g_pD3D->Release();
}
//-----------------------------------------------------------------------------
// Name: shutDown()
// Desc:
//-----------------------------------------------------------------------------
void shutDown_1( void )
{
if( g_pTeapotMesh_1 != NULL )
g_pTeapotMesh_1->Release();
if( g_pd3dDevice_1 != NULL )
g_pd3dDevice_1->Release();
}
//-----------------------------------------------------------------------------
// Name: render_0()
// Desc:
//-----------------------------------------------------------------------------
void render_0( void )
{
D3DXMATRIX matView;
D3DXMATRIX matWorld;
D3DXMATRIX matRotation;
D3DXMATRIX matTranslation;
static int nFrameCount = 0;
static double nTimeOfLastFPSUpdate = 0.0;
static char fpsString[50] = "Frames Per Second = ";
RECT destRect;
// Now we can clear just view-port's portion of the buffer to red...
g_pd3dDevice_0->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ), 1.0f, 0 );
g_pd3dDevice_0->BeginScene();
// For the left view-port, leave the view at the origin...
D3DXMatrixIdentity( &matView );
g_pd3dDevice_0->SetTransform( D3DTS_VIEW, &matView );
// ... and use the world matrix to spin and translate the teapot
// out where we can see it...
D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 5.0f );
matWorld = matRotation * matTranslation;
g_pd3dDevice_0->SetTransform( D3DTS_WORLD, &matWorld );
g_pd3dDevice_0->SetMaterial( &g_teapotMtrl );
g_pTeapotMesh_0->DrawSubset(0);
g_pd3dDevice_0->EndScene();
// Report frames per second and the number of objects culled...
++nFrameCount;
if( g_dElpasedAppTime - nTimeOfLastFPSUpdate > 1000 ) // Update once a second
{
sprintf( fpsString, "Frames Per Second = %4.2f", nFrameCount*1000.0/(g_dElpasedAppTime - nTimeOfLastFPSUpdate) );
nTimeOfLastFPSUpdate = g_dElpasedAppTime;
nFrameCount = 0;
}
SetRect( &destRect, 5, 5, 0, 0 );
g_pd3dxFont->DrawText( NULL, fpsString, -1, &destRect, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
g_pd3dDevice_0->Present( NULL, NULL, NULL, NULL );
}
//-----------------------------------------------------------------------------
// Name: render_1()
// Desc:
//-----------------------------------------------------------------------------
void render_1( void )
{
D3DXMATRIX matView;
D3DXMATRIX matWorld;
D3DXMATRIX matRotation;
D3DXMATRIX matTranslation;
// Now we can clear just view-port's portion of the buffer to green...
g_pd3dDevice_1->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ), 1.0f, 0 );
g_pd3dDevice_1->BeginScene();
// For the left view-port, leave the view at the origin...
D3DXMatrixIdentity( &matView );
g_pd3dDevice_1->SetTransform( D3DTS_VIEW, &matView );
// ... and use the world matrix to spin and translate the teapot
// out where we can see it...
D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 5.0f );
matWorld = matRotation * matTranslation;
g_pd3dDevice_1->SetTransform( D3DTS_WORLD, &matWorld );
g_pd3dDevice_1->SetMaterial( &g_teapotMtrl );
g_pTeapotMesh_1->DrawSubset(0);
g_pd3dDevice_1->EndScene();
// We're done! Now, we just call Present()
g_pd3dDevice_1->Present( NULL, NULL, NULL, NULL );
}