Hey all,
I need some help with binding my shader to my original simple 3D program.
This is my C++ code:
// include the basic windows header files and the Direct3D header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dinput.h>
#include <Cg/cg.h>
#include <Cg/cgGL.h>
#include <Cg/cgD3D9.h>
// define the screen resolution and keyboard macros
#define SCREEN_WIDTH 1680
#define SCREEN_HEIGHT 1050
#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")
#pragma comment (lib, "dinput.lib")
#pragma comment (lib, "dinput8.lib")
#pragma comment (lib, "dxguid.lib")
// global declarations
LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer
LPDIRECT3DSURFACE9 z_buffer = NULL; // the pointer to the z-buffer
LPDIRECTINPUT8 din; // the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8 dinkeyboard; // the pointer to the keyboard device
float XAngle, YAngle, ZAngle, XPos, YPos, ZPos = 0.0f;
static const char *myProgramFileName = "testshader.cg";
// mesh declarations
LPD3DXMESH meshGround, meshBox; // define the mesh pointer
D3DMATERIAL9* materialGround; // define the material of the ground
D3DMATERIAL9* materialBox; // define the material of the box
DWORD numGroundMaterials, numBoxMaterials; // stores the number of materials in the mesh
// 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
void init_light(void); // sets up the light and the material
void initDInput(HINSTANCE hInstance, HWND hWnd); // sets up and initializes DirectInput
void detect_keys(void); // gets the current keys being pressed
// 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"WindowClass1";
RegisterClassEx(&wc);
hWnd = CreateWindowEx(NULL,
L"WindowClass1",
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);
initDInput(hInstance, hWnd);
// CG
static CGprofile myCgVertexProfile;
const char **profileOpts;
myCgVertexProfile = cgD3D9GetLatestVertexProfile();
profileOpts = cgD3D9GetOptimalOptions(myCgVertexProfile);
CGcontext myCgContext = cgCreateContext();
CGprogram myCgVertexProgram =
cgCreateProgramFromFile(
myCgContext, /* Cg runtime context */
CG_SOURCE, /* Program in human-readable form */
myProgramFileName, /* Name of file containing program */
myCgVertexProfile, /* Profile: OpenGL ARB vertex program */
"main", /* Entry function name */
profileOpts); /* Pass optimal compiler options */
//CGprogram MyCGProgram = cgCreateProgram(context, CG_SOURCE, myProgramFileName, CG_PROFILE_ARBVP1, "main", NULL);
// 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, COM and DirectX Input
cleanD3D();
return msg.wParam;
}
// this is the function that initializes DirectInput
void initDInput(HINSTANCE hInstance, HWND hWnd)
{
// create the DirectInput interface
DirectInput8Create(hInstance, // the handle to the application
DIRECTINPUT_VERSION, // the compatible version
IID_IDirectInput8, // the DirectInput interface version
(void**)&din, // the pointer to the interface
NULL); // COM stuff, so we'll set it to NULL
// create the keyboard device
din->CreateDevice(GUID_SysKeyboard, // the default keyboard ID being used
&dinkeyboard, // the pointer to the device interface
NULL); // COM stuff, so we'll set it to NULL
dinkeyboard->SetDataFormat(&c_dfDIKeyboard); // set the data format to keyboard format
// set the control you will have over the keyboard
dinkeyboard->SetCooperativeLevel(hWnd,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
return; // return to WinMain()
}
// this is the function that detects keystrokes and displays them in a message box
void detect_keys(void)
{
static BYTE keystate[256]; // create a static storage for the key-states
dinkeyboard->Acquire(); // get access if we don't have it already
dinkeyboard->GetDeviceState(256, (LPVOID)keystate); // fill keystate with values
if(keystate[DIK_LEFT] & 0x80)
XAngle += 0.03f;
if(keystate[DIK_RIGHT] & 0x80)
XAngle -= 0.03f;
if(keystate[DIK_UP] & 0x80)
YAngle += 0.03f;
if(keystate[DIK_DOWN] & 0x80)
YAngle -= 0.03f;
return;
}
// 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 = FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.BackBufferWidth = SCREEN_WIDTH;
d3dpp.BackBufferHeight = SCREEN_HEIGHT;
d3dpp.EnableAutoDepthStencil = TRUE; // automatically run the z-buffer for us
d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 16-bit pixel format for the z-buffer
// create a device class using this information and the info 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
init_light(); // call the function to initialize the light and material
d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE); // turn on the 3D lighting
d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer
d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(50, 50, 50)); // ambient light
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 UP THE TRANSFORMS
// Declaring all the variables needed for the transform
D3DXMATRIX matView, matRotX, matRotY, matRotZ, matTrans, matWorld;
//static float XAngle, YAngle, ZAngle, XPos, YPos, ZPos = 0.0f;
D3DXMatrixLookAtLH(&matView,
&D3DXVECTOR3 (0.0f, 4.0f, 8.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
d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView
D3DXMATRIX matProjection; // the projection transform matrix
D3DXMatrixPerspectiveFovLH(&matProjection,
D3DXToRadian(70), // the horizontal field of view
SCREEN_WIDTH / SCREEN_HEIGHT, // the aspect ratio
1.0f, // the near view-plane
100.0f); // the far view-plane
d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection
detect_keys();
D3DXMatrixRotationX(&matRotX, XAngle);
D3DXMatrixRotationY(&matRotY, YAngle);
D3DXMatrixRotationZ(&matRotZ, ZAngle);
D3DXMatrixTranslation(&matTrans, ZAngle, XAngle, YAngle);
D3DXMatrixIdentity(&matWorld);
D3DXMatrixMultiply(&matWorld, &matWorld, &matTrans);
D3DXMatrixMultiply(&matWorld, &matWorld, &matRotZ);
D3DXMatrixMultiply(&matWorld, &matWorld, &matRotY);
D3DXMatrixMultiply(&matWorld, &matWorld, &matRotX);
d3ddev->SetTransform(D3DTS_WORLD, &(matWorld));
// draw the spaceship
for(DWORD i = 0; i < numBoxMaterials; i++) // loop through each subset
{
d3ddev->SetMaterial(&materialBox); // set the material for the subset
meshBox->DrawSubset(i); // draw the subset
}
// draw the spaceship
for(DWORD i = 0; i < numGroundMaterials; i++) // loop through each subset
{
d3ddev->SetMaterial(&materialGround); // set the material for the subset
meshGround->DrawSubset(i); // draw the subset
}
d3ddev->EndScene();
d3ddev->Present(NULL, NULL, NULL, NULL);
return;
}
// this is the function that puts the 3D models into video RAM
void init_graphics(void)
{
LPD3DXBUFFER bufGroundMaterial, bufBoxMaterial;
D3DXLoadMeshFromX(L"ground.x", // load this file
D3DXMESH_SYSTEMMEM, // load the mesh into system memory
d3ddev, // the Direct3D Device
NULL, // we aren't using adjacency
&bufGroundMaterial, // put the materials here
NULL, // we aren't using effect instances
&numGroundMaterials, // the number of materials in this model
&meshGround); // put the mesh here
D3DXLoadMeshFromX(L"box.x", // load this file
D3DXMESH_SYSTEMMEM, // load the mesh into system memory
d3ddev, // the Direct3D Device
NULL, // we aren't using adjacency
&bufBoxMaterial, // put the materials here
NULL, // we aren't using effect instances
&numBoxMaterials, // the number of materials in this model
&meshBox); // put the mesh here
// retrieve the pointer to the buffer containing the material information
D3DXMATERIAL* tempGroundMaterials = (D3DXMATERIAL*)bufGroundMaterial->GetBufferPointer();
D3DXMATERIAL* tempBoxMaterials = (D3DXMATERIAL*)bufBoxMaterial->GetBufferPointer();
// create a new material buffer for each material in the mesh
materialGround = new D3DMATERIAL9[numGroundMaterials];
for(DWORD i = 0; i < numGroundMaterials; i++) // for each material...
{
materialGround = tempGroundMaterials.MatD3D; // get the material info
materialGround.Ambient = materialGround.Diffuse; // make ambient the same as diffuse
}
materialBox = new D3DMATERIAL9[numBoxMaterials];
for(DWORD i = 0; i < numBoxMaterials; i++) // for each material...
{
materialBox = tempBoxMaterials.MatD3D; // get the material info
materialBox.Ambient = materialBox.Diffuse; // make ambient the same as diffuse
}
return;
}
// this is the function that sets up the lights and materials
void init_light(void)
{
D3DLIGHT9 light; // create the light struct
ZeroMemory(&light, sizeof(light)); // clear out the light struct for use
light.Type = D3DLIGHT_SPOT; // make the light type spot light'
light.Diffuse.r = 0.5f; // .5 red
light.Diffuse.g = 0.5f; // .5 green
light.Diffuse.b = 0.5f; // .5 blue
light.Diffuse.a = 1.0f; // full alpha (we'll get to that soon)
light.Range = 500.0f; // a range of 500
light.Attenuation0 = 0.0f; // no constant inverse attenuation
light.Attenuation1 = 0.125f; // only .125 inverse attenuation
light.Attenuation2 = 0.0f; // no square inverse attenuation
light.Phi = D3DXToRadian(40.0f); // set the outer cone to 30 degrees
light.Theta = D3DXToRadian(20.0f); // set the inner cone to 10 degrees
light.Falloff = 0.0f; // use the typical falloff
D3DVECTOR vecPosition = {0.0f, 0.0f, 30.0f}; // the position of the light
light.Position = vecPosition; // set the position
D3DVECTOR vecDirection = {0.0f, 0.0f, -1.0f}; // the direction of the light
light.Direction = vecDirection; // set the direction
d3ddev->SetLight(0, &light); // send the light struct properties to light #0
d3ddev->LightEnable(0, TRUE); // turn on light #0
return;
}
// this is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
meshGround->Release(); // close and release the ground mesh
meshBox->Release(); // close and release the box mesh
d3ddev->Release(); // close and release the 3D device
d3d->Release(); // close and release Direct3D
// Clean Direct-Input
dinkeyboard->Unacquire(); // make sure the keyboard is unacquired
din->Release(); // close DirectInput before exiting
return;
}
And I have also added this Cg file named "testshader.cg" to my Visual Studio project:
Does anyone know what I am doing wrong?
Thanks :)
Greetings, Vincent.