I'm new to DirectX 11, and I have managed to get the Drawing Triangle chapter in my book.
I have written this code, but I get a runtime error:
"Unhandled exception at 0x00cd14e6 in DirectX 11.exe: 0xc0000005: Access violation reading location 0x00000000."
My compiler show that the error is at the InitPipeline function, but I can't find the error there.
What have I done wrong?
Code:
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <D3DX11.h>
#include <D3DX10.h>
#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"d3dx11.lib")
#pragma comment(lib,"d3dx10.lib")
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
IDXGISwapChain *swapchain;
ID3D11Device *dev;
ID3D11DeviceContext *devcon;
ID3D11InputLayout *pInputLayout;
ID3D11Buffer *pVBuffer;
ID3D11RenderTargetView *backbuffer;
ID3D11VertexShader *pVS;
ID3D11PixelShader *pPS;
// Type
struct VERTEX
{
FLOAT X,Y,Z;
D3DXCOLOR Color;
};
//DirectX
void InitPipeline()
{
// load and compile the two shaders
ID3D10Blob *VS, *PS;
D3DX11CompileFromFile("shaders.hlsl", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile("shaders.hlsl", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);
//debug
if(!dev)
{
MessageBox(NULL, "DEV = NULL", "ERROR", NULL);
}
if(!devcon)
{
MessageBox(NULL, "DEVCON = NULL", "ERROR", NULL);
}
if(!VS)
{
MessageBox(NULL, "VS = NULL", "ERROR", NULL);
}
if(!PS)
{
MessageBox(NULL, "PS = NULL", "ERROR", NULL);
}
// encapsulate both shaders into shader objects
dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
// set the shader objects
devcon->VSSetShader(pVS, 0, 0);
devcon->PSSetShader(pPS, 0, 0);
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,0,D3D11_INPUT_PER_VERTEX_DATA,0},
{"COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pInputLayout);
devcon->IASetInputLayout(pInputLayout);
}
void InitGraphics()
{
VERTEX OurVertices[] =
{
{1,0,0,D3DXCOLOR(1,0,0,1)},
{0,-1,0,D3DXCOLOR(1,0,0,1)},
{0,0,1,D3DXCOLOR(1,0,0,1)},
};
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(D3D11_BUFFER_DESC));
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.ByteWidth = sizeof(VERTEX)*3;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.Usage = D3D11_USAGE_DYNAMIC;
dev->CreateBuffer(&bd, NULL, &pVBuffer);
D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
memcpy(ms.pData, OurVertices, sizeof(OurVertices));
devcon->Unmap(pVBuffer, NULL);
}
void RenderFrame()
{
devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0,0,1,1));
UINT stride = sizeof(VERTEX);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->Draw(3,0);
swapchain->Present(0,0);
}
void InitD3D(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = SCREEN_WIDTH; // set the back buffer width
scd.BufferDesc.Height = SCREEN_HEIGHT; // set the back buffer height
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching
// create a device, device context and swap chain using the information in the scd struct
if(FAILED(D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapchain,
&dev,
NULL,
&devcon)))
{
MessageBox(NULL, "D3D11CreateDeviceAndSwapChain Failed", "ERROR", NULL);
}
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
// Set the viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = SCREEN_WIDTH;
viewport.Height = SCREEN_HEIGHT;
devcon->RSSetViewports(1, &viewport);
InitPipeline();
InitGraphics();
}
void CleanD3D()
{
swapchain->SetFullscreenState(FALSE, NULL);
dev->Release();
devcon->Release();
swapchain->Release();
pInputLayout->Release();
pVBuffer->Release();
backbuffer->Release();
pVS->Release();
pPS->Release();
}
// Window
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
//wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = (HICON)LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "DirectXWindow";
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
"DirectXWindow",
"DirectX 11 (June 2010",
WS_OVERLAPPEDWINDOW,
0,0,
SCREEN_WIDTH, SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
InitD3D(hWnd);
UpdateWindow(hWnd);
MSG msg = {0};
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
RenderFrame();
}
}
CleanD3D();
return msg.wParam;
}
That error basically means that you are using a null pointer somewhere. Check all your pointers. My guess is that some function somewhere is failing to set your pointers (or you have the parameters in the wrong order).
You are using a NULL pointer. You define 8 global D3D interface pointers and you are using dev and devcon within InitPipeline they need to be allocated and initialized before you can call any methods on them.
Try setting the scd.SampleDesc.Count = 1
This value tells Direct3D how much detail should be put into anti-aliasing, the higher the number the better. Direct3D 11 video cards are guaranteed to support up to 4 here, but the minimum is 1.
Perhaps your video card doesn't support Direct3D 11?
Related
I wrote a simple directX9 app (code below) which is working fine for at least 25 Windows 10 setups but on one the background of the window is just black instead of transparent (with the test draw on it).
All the systems are running dedicated NVIDIA GPUs (10 series) so this should not be the problem and they use the latest Windows 10 version with the latest Nvidia drivers.
A workaround is to add LWA_COLORKEY to SetLayeredWindowAttributes but I would like to know how I can fix the system instead of using LWA_COLORKEY. (Because adding LWA_COLORKEY costs a lot of performance).
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA | LWA_COLORKEY);
This is a sample that can replicate the problem:
#pragma once
#include <Windows.h>
#include <string>
#include <iostream>
// DirectX9
#pragma warning( push )
#pragma warning( disable : 4005)
#include <d3d9.h>
#include <d3dx9.h>
#include <Dwmapi.h>
#include <TlHelp32.h>
#include <Directxmath.h>
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "Dwmapi.lib")
#pragma warning( pop )
using namespace std;
using namespace DirectX;
int s_width = 800;
int s_height = 600;
#define CENTERX (GetSystemMetrics(SM_CXSCREEN)/2)-(s_width/2)
#define CENTERY (GetSystemMetrics(SM_CYSCREEN)/2)-(s_height/2)
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 d3ddev;
HWND hWnd;
LPD3DXFONT pFont;
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferWidth = s_width;
d3dpp.BackBufferHeight = s_height;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.FullScreen_RefreshRateInHz = 0;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.MultiSampleQuality = DEFAULT_QUALITY;
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
D3DXCreateFont(d3ddev, 50, 0, FW_BOLD, 1, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &pFont);
}
void DrawString(int x, int y, DWORD color, LPD3DXFONT g_pFont, const char *fmt, ...)
{
RECT FontPos = { x, y, x + 120, y + 16 };
char buf[1024] = { '\0' };
va_list va_alist;
va_start(va_alist, fmt);
vsprintf_s(buf, fmt, va_alist);
va_end(va_alist);
g_pFont->DrawText(NULL, buf, -1, &FontPos, DT_NOCLIP, color);
}
void render()
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
DrawString(10, 50, D3DCOLOR_ARGB(100, 255, 0, 0), pFont, "Test rendering");
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
int main()
{
RECT rc = { 0 };
HINSTANCE hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hInstance = NULL;
wc.lpfnWndProc = WindowProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowExA(WS_EX_LAYERED | WS_EX_TRANSPARENT, "WindowClass", "Title", WS_POPUP | WS_VISIBLE, rc.left, rc.top, s_width, s_height, NULL, NULL, hInstance, NULL);
SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
//DWM_BLURBEHIND bb = { DWM_BB_ENABLE | DWM_BB_BLURREGION, true, CreateRectRgn(0, 0, -1, -1), true };
//if (DwmEnableBlurBehindWindow(hWnd, &bb) != S_OK)
MARGINS margin = { -1 };
DwmExtendFrameIntoClientArea(hWnd, &margin);
initD3D(hWnd);
MSG msg;
while (TRUE)
{
render();
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT)
exit(0);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
}break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This is my first question on stackoverflow, so forgive me if my question is dumb.
I am trying to simply render a triangle in DirectX9 in Visual Studio 2012 following this: www.directxtutorial.com/Lesson.aspx?lessonid=9-4-4.
When I create a CUSTOMVERTEX class with a non-virtual destructor it renders the triangle without any problem. Whereas if I make the destructor virtual the triangle is not rendered.
Here is the code with the virtual destructor:
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
// define the screen resolution
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; // the pointer to the vertex buffer
// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
void init_graphics(void); // 3D declarations
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//************CUSTOMVERTEX CLASS**********/
class CUSTOMVERTEX {
public:
CUSTOMVERTEX( float _X, float _Y, float _Z, float _RHW, DWORD _COLOR )
: X(_X), Y(_Y), Z(_Z), RHW(_RHW), COLOR(_COLOR)
{}
virtual ~CUSTOMVERTEX(){
OutputDebugString("Destructed!!!\n");
}
float X, Y, Z, RHW;
DWORD COLOR;
};
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
"WindowClass",
"Our Direct3D Program",
WS_OVERLAPPEDWINDOW,
0, 0,
SCREEN_WIDTH, SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
// set up and initialize Direct3D
initD3D(hWnd);
// enter the main loop:
MSG msg;
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
render_frame();
}
// clean up DirectX and COM
cleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
// create a device class using this information and the info from the d3dpp struct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // call the function to initialize the triangle
}
// this is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// select the vertex buffer to display
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
// copy the vertex buffer to the back buffer
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
v_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX class
CUSTOMVERTEX vertices[] =
{
CUSTOMVERTEX(400.0f, 62.5f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)),
CUSTOMVERTEX(650.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0)),
CUSTOMVERTEX(150.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0)),
};
// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();
}
Rendered triangle:Rendered Triangle
The code without virtual destructor:
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
// define the screen resolution
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// include the Direct3D Library file
#pragma comment (lib, "d3d9.lib")
#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL; // the pointer to the vertex buffer
// function prototypes
void initD3D(HWND hWnd); // sets up and initializes Direct3D
void render_frame(void); // renders a single frame
void cleanD3D(void); // closes Direct3D and releases memory
void init_graphics(void); // 3D declarations
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//************CUSTOMVERTEX CLASS**********/
class CUSTOMVERTEX {
public:
CUSTOMVERTEX( float _X, float _Y, float _Z, float _RHW, DWORD _COLOR )
: X(_X), Y(_Y), Z(_Z), RHW(_RHW), COLOR(_COLOR)
{}
~CUSTOMVERTEX(){
OutputDebugString("Destructed!!!\n");
}
float X, Y, Z, RHW;
DWORD COLOR;
};
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
"WindowClass",
"Our Direct3D Program",
WS_OVERLAPPEDWINDOW,
0, 0,
SCREEN_WIDTH, SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, nCmdShow);
// set up and initialize Direct3D
initD3D(hWnd);
// enter the main loop:
MSG msg;
while(TRUE)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(msg.message == WM_QUIT)
break;
render_frame();
}
// clean up DirectX and COM
cleanD3D();
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// this function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
// create a device class using this information and the info from the d3dpp struct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // call the function to initialize the triangle
}
// this is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
// select which vertex format we are using
d3ddev->SetFVF(CUSTOMFVF);
// select the vertex buffer to display
d3ddev->SetStreamSource(0, v_buffer, 0, sizeof(CUSTOMVERTEX));
// copy the vertex buffer to the back buffer
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
}
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
v_buffer->Release(); // close and release the vertex buffer
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
// create the vertices using the CUSTOMVERTEX class
CUSTOMVERTEX vertices[] =
{
CUSTOMVERTEX(400.0f, 62.5f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255)),
CUSTOMVERTEX(650.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0)),
CUSTOMVERTEX(150.0f, 500.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0)),
};
// create a vertex buffer interface called v_buffer
d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0,
CUSTOMFVF,
D3DPOOL_MANAGED,
&v_buffer,
NULL);
VOID* pVoid; // a void pointer
// lock v_buffer and load the vertices into it
v_buffer->Lock(0, 0, (void**)&pVoid, 0);
memcpy(pVoid, vertices, sizeof(vertices));
v_buffer->Unlock();
}
Rendered without any triangle: without any triangle
Can anyone please explain to me why this is happening?
In short: Adding the virtual changes the memory layout of the structure, meaning your data is no longer in the correct place for the Vertex Declaration you provided:
struct CUSTOMVERTEX {
CUSTOMVERTEX( float _X, float _Y, float _Z, float _RHW, DWORD _COLOR )
: X(_X), Y(_Y), Z(_Z), RHW(_RHW), COLOR(_COLOR)
{}
float X, Y, Z, RHW;
DWORD COLOR;
};
The size of this structure is 20 bytes.
class CUSTOMVERTEX {
public:
CUSTOMVERTEX( float _X, float _Y, float _Z, float _RHW, DWORD _COLOR )
: X(_X), Y(_Y), Z(_Z), RHW(_RHW), COLOR(_COLOR)
{}
virtual ~CUSTOMVERTEX(){
OutputDebugString("Destructed!!!\n");
}
float X, Y, Z, RHW;
DWORD COLOR;
};
The size of this structure is 24 bytes for x86 (Win32) and 32 bytes for x64 native. This is because there's a pointer to the vtable added at the start of the structure (and on x64 the additional padding pushes it out a little more than 8 bytes).
Furthermore, since you are using the type through a Direct3D Vertex Buffer, it's never going to have it's constructor or destructor executed. It's just allocated from the heap as a "plain old data type". The only time constructors or destructors are invoked for heap-allocated memory is via new, new [], delete, and/or delete []. Internally Direct3D Vertex Buffer is doing something more akin to malloc.
Your constructor is being invoked by the C++ compiler when you create the initialized array vertices, and the destructor is invoked when vertices goes out of scope.
In other words: This doesn't do what you think it does. Don't use virtual in your vertex data structures.
Note that you should consider making using of a smart pointer like Microsoft::WRL::ComPtr for managing the lifetime of your Direct3D COM objects. This takes advantage of the C++ scoping rules for ctors/destructors to properly call Release automatically. Of course, you should also not be spending a lot of time learning legacy Direc3D 9 either.
I'm trying to create a window that uses directx to draw opaque content on top of a transparent view (i.e. the desktop shows through). With DirectX11 I'm trying to do the following, but it's not making the background transparent. In fact, any opacity value I put in gives me the exact same results.
What I'm doing:
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
deviceContext->ClearRenderTargetView(backBuffer, color);
Working repro code (main.cpp):
#include <Windows.h>
#include <windowsx.h>
#pragma comment (lib, "Winmm.lib")
#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")
#include <d3dcompiler.h>
#pragma comment(lib, "D3DCompiler.lib")
#include <dwmapi.h>
#pragma comment (lib, "Dwmapi.lib")
// Globals
IDXGISwapChain *swapChain;
ID3D11Device *device;
ID3D11DeviceContext *deviceContext;
ID3D11RenderTargetView *backBuffer;
ID3D11InputLayout *inputLayout; // the pointer to the input layout
ID3D11VertexShader *vertexShader; // the pointer to the vertex shader
ID3D11PixelShader *pixelShader; // the pointer to the pixel shader
ID3D11Buffer *vertexBuffer; // the pointer to the vertex buffer
void InitializeDirectX(HWND hWnd);
void LoadTriangle();
struct Vertex {
float x, y, z;
float color[4];
};
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// Globals
const LPCWSTR ClassName = L"className";
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
// Pick out window size
int windowHeight = 400;
int windowWidth = 400;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = ClassName;
// register the window class
RegisterClassEx(&wc);
// Window style
DWORD exStyle = WS_EX_LAYERED | WS_EX_TOPMOST;
DWORD style = WS_POPUP;
// create the window and use the result as the handle
hWnd = CreateWindowEx(
exStyle, // extended styles
ClassName, // name of the window class
L"TestOverlay", // title of the window
style, // window style
0, // x-position of the window
0, // y-position of the window
400, // width of the window
400, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
SetWindowPos(hWnd,
HWND_TOPMOST,
0, 0,
windowWidth, windowHeight,
SWP_SHOWWINDOW);
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
// Make the window transparent
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 255, LWA_ALPHA | LWA_COLORKEY);
// NOTE: If I uncomment DwmExtendFrameIntoClientArea then it becomes transparent, otherwise its a black screen
MARGINS dwmMargin = { -1 };
//DwmExtendFrameIntoClientArea(hWnd, &dwmMargin);
// DirectX
InitializeDirectX(hWnd);
LoadTriangle();
// enter the main loop:
MSG msg;
BOOL gotMessage;
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
// DirectX stuff
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
deviceContext->ClearRenderTargetView(backBuffer, color);
// Draw triangle
UINT stride = sizeof(Vertex);
UINT offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
deviceContext->Draw(3, 0);
swapChain->Present(0, 0);
}
}
return msg.wParam;
}
void InitializeDirectX(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapChain,
&device,
NULL,
&deviceContext);
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
device->CreateRenderTargetView(pBackBuffer, NULL, &backBuffer);
pBackBuffer->Release();
// set the render target as the back buffer
deviceContext->OMSetRenderTargets(1, &backBuffer, NULL);
// Set the viewport size
RECT cRect;
GetClientRect(hWnd, &cRect);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = cRect.right - cRect.left;
viewport.Height = cRect.bottom - cRect.top;
deviceContext->RSSetViewports(1, &viewport);
// Initialize pipeline stuff
ID3D10Blob *VS, *PS;
// compile shader
D3DCompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, &VS, 0);
D3DCompileFromFile(L"shaders.shader", 0, 0, "PShader", "ps_4_0", 0, 0, &PS, 0);
// encapsulate both shaders into shader objects
device->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &vertexShader);
device->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pixelShader);
deviceContext->VSSetShader(vertexShader, 0, 0);
deviceContext->PSSetShader(pixelShader, 0, 0);
// create input layout object
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
device->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &inputLayout);
deviceContext->IASetInputLayout(inputLayout);
}
void LoadTriangle()
{
// create a triangle using the VERTEX struct
Vertex OurVertices[] =
{
{ 0.0f, 0.5f, 0.0f, { 1.0f, 0.0f, 0.0f, 1.0f } },
{ 0.45f, -0.5, 0.0f, { 0.0f, 1.0f, 0.0f, 1.0f } },
{ -0.45f, -0.5f, 0.0f, { 0.0f, 0.0f, 1.0f, 1.0f } }
};
// create the vertex buffer
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC; // write access access by CPU and GPU
bd.ByteWidth = sizeof(Vertex)* 3; // size is the VERTEX struct * 3
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; // use as a vertex buffer
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // allow CPU to write in buffer
device->CreateBuffer(&bd, NULL, &vertexBuffer); // create the buffer
// copy the vertices into the buffer
D3D11_MAPPED_SUBRESOURCE ms;
deviceContext->Map(vertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms); // map the buffer
memcpy(ms.pData, OurVertices, sizeof(OurVertices)); // copy the data
deviceContext->Unmap(vertexBuffer, NULL); // unmap the buffer
}
Shader file (shaders.shader):
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
VOut output;
output.position = position;
output.color = color;
return output;
}
float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
If you uncomment the DwmExtendFrameIntoClientArea call on line 119ish, then it gets the effect I'm looking for. I'm wondering if there's a way to get the same effect without the use of dwm (for reasons I won't go into).
Any ideas?
Edit: Added full source code of working example. Found out that if I make a call to DwmExtendFrameIntoClientArea, then I get the effect I want. But I'd still like to know if its possible to do it without using dwm apis.
You can't make a Window transparent with DirectX only, The following code only clear the background color to black.
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
To achieve transparent effect of your window, you need to involve some win32 stuff, SetLayeredWindowAttributes is your choice.
// Show the window
ShowWindow( hWnd, SW_SHOWDEFAULT );
UpdateWindow( hWnd );
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED) ;
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 100, LWA_ALPHA);
UPDATE:
Workable code draw nothing but make the window transparent in green color.
#include <Windows.h>
#include <windowsx.h>
#pragma comment (lib, "Winmm.lib")
#include <d3d11.h>
#pragma comment (lib, "d3d11.lib")
#include <d3dcompiler.h>
#pragma comment(lib, "D3DCompiler.lib")
#include <dwmapi.h>
#pragma comment (lib, "Dwmapi.lib")
// Globals
IDXGISwapChain *swapChain;
ID3D11Device *device;
ID3D11DeviceContext *deviceContext;
ID3D11RenderTargetView *backBuffer;
void InitializeDirectX(HWND hWnd);
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
// Globals
const LPCWSTR ClassName = L"className";
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = ClassName;
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
HWND hWnd = CreateWindowEx(
NULL, // extended styles
ClassName, // name of the window class
L"TestOverlay", // title of the window
WS_OVERLAPPEDWINDOW, // window style
0, // x-position of the window
0, // y-position of the window
400, // width of the window
400, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Make the window transparent
SetWindowLong(hWnd, GWL_EXSTYLE, WS_EX_LAYERED) ;
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 128, LWA_ALPHA);
// DirectX
InitializeDirectX(hWnd);
// enter the main loop:
MSG msg;
BOOL gotMessage;
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
break;
// DirectX stuff
float color[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
deviceContext->ClearRenderTargetView(backBuffer, color);
swapChain->Present(0, 0);
}
}
return msg.wParam;
}
void InitializeDirectX(HWND hWnd)
{
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE; // windowed/full-screen mode
// create a device, device context and swap chain using the information in the scd struct
D3D11CreateDeviceAndSwapChain(NULL,
D3D_DRIVER_TYPE_HARDWARE,
NULL,
NULL,
NULL,
NULL,
D3D11_SDK_VERSION,
&scd,
&swapChain,
&device,
NULL,
&deviceContext);
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
device->CreateRenderTargetView(pBackBuffer, NULL, &backBuffer);
pBackBuffer->Release();
// set the render target as the back buffer
deviceContext->OMSetRenderTargets(1, &backBuffer, NULL);
// Set the viewport size
RECT cRect;
GetClientRect(hWnd, &cRect);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = cRect.right - cRect.left;
viewport.Height = cRect.bottom - cRect.top;
deviceContext->RSSetViewports(1, &viewport);
}
Below is the code I am using and the error happens when I attempt to check for the available tenique within the FX file. I'm not sure if the FX file is bad or what. I am using the default simple.fx that comes with DirectX.
// Include the basic Windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
// Define the screen resolution and keyboard macros
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// Include the Direct3D library files
#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")
// Global declarations
LPDIRECT3D9 d3d; // The pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // The pointer to the device class
// Mesh declarations
LPD3DXMESH meshTeapot; // Define the mesh pointer
// effect declarations
LPD3DXEFFECT effect; // Define the effect pointer
D3DXHANDLE technique; // Define the handle for the best technique
// Function prototypes
void initD3D(HWND hWnd); // Sets up and initializes Direct3D
void render_frame(void); // Renders a single frame
void cleanD3D(void); // Closes Direct3D and releases memory
void init_graphics(void); // 3D declarations
// The WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// The entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program",
WS_EX_TOPMOST | WS_POPUP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
// Set up and initialize Direct3D
initD3D(hWnd);
// Enter the main loop:
MSG msg;
while(TRUE)
{
DWORD starting_point = GetTickCount();
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
render_frame();
// Check the 'escape' key
if(KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
while ((GetTickCount() - starting_point) < 25);
}
// Clean up DirectX and COM
cleanD3D();
return msg.wParam;
}
// This is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
}
return DefWindowProc (hWnd, message, wParam, lParam);
}
// This function initializes and prepares Direct3D for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
// Create a device class using this information and the information from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
init_graphics(); // Call the function to initialize the triangle
LPD3DXBUFFER errorlog; // For storing errors
// Load the effect file
D3DXCreateEffectFromFile(d3ddev, L"simple.fx", 0, 0, 0, 0, &effect, &errorlog);
// Find the best technique
effect->FindNextValidTechnique(NULL, &technique);
return;
}
// This is the function used to render a single frame
void render_frame(void)
{
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
d3ddev->BeginScene();
// Set the view transform
D3DXMATRIX matView; // The view transform matrix
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (0.0f, 3.0f, 6.0f), // The camera position
&D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // The look-at position
&D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // The up direction
effect->SetMatrix("View", &matView);
// Set the projection transform
D3DXMATRIX matProjection; // The projection transform matrix
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(45), // The horizontal field of view
(FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // Aspect ratio
1.0f, // The near view-plane
100.0f); // The far view-plane
effect->SetMatrix("Projection", &matProjection);
// Set the world transform
static float index = 0.0f; // An ever-increasing float value
index+=0.03f;
D3DXMATRIX matRotateY; // A matrix to store the rotation for each triangle
D3DXMatrixRotationY(&matRotateY, index); // The rotation matrix
effect->SetMatrix("World", &matRotateY);
effect->Begin(NULL, NULL); // Begin using the effect
effect->BeginPass(0); // Begin the pass
// Render whatever
meshTeapot->DrawSubset(0);
effect->EndPass(); // End the pass
effect->End(); // End the effect
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
return;
}
// This is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
meshTeapot->Release(); // Close and release the teapot mesh
effect->Release(); // Close and release the effect
d3ddev->Release(); // Close and release the 3D device
d3d->Release(); // Close and release Direct3D
return;
}
// This is the function that puts the 3D models into video RAM
void init_graphics(void)
{
D3DXCreateTeapot(d3ddev, &meshTeapot, NULL); // Create the teapot
return;
}
I presume you have copied the code from www.directxtutorial.com. I had the same problem.
You should keep track of the errors the Effect compiler throws at you. Convert the errorlog variable to a string in order to read the errors properly:
char * Error = (char *)errorlog->GetBufferPointer();
The first error you get is:
error X3539: ps_1_x is no longer supported; use /Gec in fxc to automatically upgrade to ps_2_0
It seems that ps_1_x is not supported. So if you open the simple.fx file, you should find something like this:
PixelShader = compile ps_1_1 PS();
Change ps_1_1 to ps_2_0 and everything should run like a charm.
I forgot to mention that you should only try to get a buffer pointer from the errorlog if it's not NULL, so:
if(errorlog)
{
char * Error = (char *)errorlog->GetBufferPointer();
// And do the output somewhere
}
I had the same problem.This is my code and solution:
//create pixel shader
ID3DXBuffer* codeBuffer = 0;
ID3DXBuffer* errorBuffer = 0;
HRESULT hr = D3DXCompileShaderFromFile("ps.txt",
0,
0,
"PS_Main", // entry point function name
"ps_2_0", //ps_1_1 is error X3539
D3DXSHADER_DEBUG,
&codeBuffer,
&errorBuffer,
&pixelConstTable);
I am currently learning DirectX so I am a starter and I am stuck at one code. I am studying from a book and I have written this code. It should draw a bitmap on the window but its giving me a blank screen. Moreover when I click esc button it gives an error but if I move or stretch the window before pressing esc, it doesnt give an error. Any help appreciated. I am using Visual Studio 2010 and C++. I have one assumption that the error might be at D3DXCreateSurfaceFromFile. Here is the code;
//Header files to include
#include <d3d9.h>
#include <time.h>
#include <d3dx9.h>
//Application title
#define APPTITLE L"Load_Bitmap"
//Screen Resolution
#define WIDTH 640
#define HEIGHT 480
//Forward Declarations
LRESULT WINAPI WinProc( HWND, UINT, WPARAM, LPARAM);
ATOM MyRegisterClass( HINSTANCE);
int GameInit(HWND);
void GameRun(HWND);
void GameEnd(HWND);
//Direct3d objects
LPDIRECT3D9 d3d = NULL;
LPDIRECT3DDEVICE9 d3ddev = NULL;
LPDIRECT3DSURFACE9 backbuffer = NULL;
LPDIRECT3DSURFACE9 surface = NULL;
//Macros to read the keyboard asynchronously
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
//Window Event Callback Function
LRESULT WINAPI WinProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
GameEnd( hWnd);
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam);
}
//Helper function to set up the window properties
ATOM MyRegisterClass( HINSTANCE hInstance)
{
WNDCLASSEX wc;
wc.cbSize = sizeof( WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = APPTITLE;
wc.hIconSm = NULL;
//Set up the window with the class info
return RegisterClassEx(&wc);
}
//Entry point for a windows program
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstancem, LPSTR lpCmdLine, int nCmdShow)
{
//Declare variables
MSG msg;
//Register the class
MyRegisterClass( hInstance);
//Initialize Application
HWND hWnd;
//Create new Window
hWnd = CreateWindow( APPTITLE, APPTITLE, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL, NULL, hInstance, NULL);
if( !hWnd)
return FALSE;
//Display the Window
ShowWindow( hWnd, nCmdShow);
UpdateWindow( hWnd);
//Initialize the Game
if( !GameInit( hWnd))
return FALSE;
//Main Message Loop
int done = 0;
while(!done)
{
if(PeekMessage( &msg, hWnd, 0, 0, PM_REMOVE))
{
//Look for quit message
if( msg.message == WM_QUIT)
done = 1;
//Decode and pass messages on to WndProc
TranslateMessage( &msg);
DispatchMessage( &msg);
}
else
//Process game loop( else prevents running after window is closed)
GameRun(hWnd);
}
return msg.wParam;
}
int GameInit( HWND hWnd)
{
HRESULT result;
//Initialize Direct3d
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if( d3d == NULL)
{
MessageBox( hWnd, L"Error initializing Direct3d", L"Error", MB_OK);
return 0;
}
//Set Direct3D presentation parameters
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = WIDTH;
d3dpp.BackBufferHeight = HEIGHT;
d3dpp.hDeviceWindow = hWnd;
//Create Direct3D device
d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev);
if( d3ddev == NULL)
{
MessageBox( hWnd, L"Error creating Direct3d device", L"Error", MB_OK);
return 0;
}
//Set Random number seed
//srand( time(NULL));
//Clear the backbuffer to black
d3ddev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0,0,0), 1.0f, 0);
//Create pointer to the back buffer
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//Create surface
result = d3ddev->CreateOffscreenPlainSurface( 640, 480, D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT, &surface, NULL);
if( result != D3D_OK)
return 1;
//load surface from file
result = D3DXLoadSurfaceFromFile(
surface, NULL, NULL, L"c.bmp", NULL, D3DX_DEFAULT, 0, NULL);
//Make sure file was loaded okay
if( result != D3D_OK)
return 1;
d3ddev->StretchRect( surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
//Return okay
return 1;
}
void GameRun(HWND hWnd)
{
//Make Sure the Direct3d device is valid
if( d3ddev == NULL)
return;
//Start Rendering
if( d3ddev->BeginScene())
{
//Create pointer to the back buffer
d3ddev->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
//Draw surface to the backbuffer
d3ddev->StretchRect( surface, NULL, backbuffer, NULL, D3DTEXF_NONE);
//StopRendering
d3ddev->EndScene();
}
//Display the back buffer on the screen
d3ddev->Present( NULL, NULL, NULL, NULL);
//Check for escape key( to exit program)
if( KEY_DOWN(VK_ESCAPE))
PostMessage(hWnd, WM_DESTROY, 0, 0);
}
void GameEnd(HWND hWnd)
{
//free the surface
if( surface != NULL)
surface->Release();
//Release the Direct3D device
if( d3ddev != NULL)
d3ddev->Release();
if( d3d != NULL)
d3d->Release();
}
Post WM_QUIT instead of WM_DESTROY when you check the escape key. As it stands now the message-loop will never quit since it depends on WM_QUIT being posted, and it will keep calling GameRun even after the surfaces are deleted.