Need help to bind my shader

Started by
5 comments, last by Vinniee 16 years, 9 months ago
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:
// This is C2E1v_green from "The Cg Tutorial" (Addison-Wesley, ISBN
// 0321194969) by Randima Fernando and Mark J. Kilgard.  See page 38.

struct C2E1v_Output {
  float4 position : POSITION;
  float3 color    : COLOR;
};

C2E1v_Output C2E1v_green(float2 position : POSITION)
{	
  C2E1v_Output OUT;

  OUT.position = float4(position,0,1);
  OUT.color = float3(0,1,0);

  return OUT;	
}
But when I compile my program it gives me these errors:
Quote:1>C++ File.obj : error LNK2019: unresolved external symbol __imp__cgCreateProgramFromFile referenced in function _WinMain@16 1>C++ File.obj : error LNK2019: unresolved external symbol __imp__cgCreateContext referenced in function _WinMain@16 1>C++ File.obj : error LNK2019: unresolved external symbol __imp__cgD3D9GetOptimalOptions referenced in function _WinMain@16 1>C++ File.obj : error LNK2019: unresolved external symbol __imp__cgD3D9GetLatestVertexProfile referenced in function _WinMain@16 1>C:\Users\Vincent\Documents\Visual Studio 2005\Projects\3D Scene\Debug\3D Scene.exe : fatal error LNK1120: 4 unresolved externals 1>Build log was saved at "file://c:\Users\Vincent\Documents\Visual Studio 2005\Projects\3D Scene\3D Scene\Debug\BuildLog.htm"
Does anyone know what I am doing wrong? Thanks :) Greetings, Vincent.
Advertisement
I don't use Cg myself, but surely there is a Cg.lib you have to link against (as you do with your #pragma comment's for d3d etc).

Regards,
ViLiO
Richard 'ViLiO' Thomasv.net | Twitter | YouTube
Thanks mate, I do not have the error anymore.

I do have these errors right now though:

Quote:'3D Scene.exe': Loaded 'C:\Users\Vincent\Documents\Visual Studio 2005\Projects\3D Scene\debug\3D Scene.exe', Symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\System32\ntdll.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\user32.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\gdi32.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\advapi32.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\rpcrt4.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\secur32.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\d3d9.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\msvcrt.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\version.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\d3d8thk.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\dwmapi.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\d3dx9_33.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Windows\SysWOW64\dinput8.dll', No symbols loaded.
'3D Scene.exe': Loaded 'C:\Program Files (x86)\Autodesk\Maya8.5\bin\cg.dll', Binary was not built with debug information.
'3D Scene.exe': Loaded 'C:\Program Files (x86)\NVIDIA Corporation\Cg\bin\cgD3D9.dll', Binary was not built with debug information.
Debugger:: An unhandled non-continuable exception was thrown during process load
The program '[4052] 3D Scene.exe: Native' has exited with code -1073741511 (0xc0000139).


And when my program starts it gives me this error:

http://img393.imageshack.us/img393/2865/naamloosbn5.jpg

I noticed that Visual Studio is including the cg.dll file from my Maya directory, I guess that is the problem.

So how do I fix this? Thanks :)
I reckon there are a couple of ways you could stop your Maya Cg.dll being used in this situation.

One would be to make sure the nVidia Cg bin folder is before the Maya folder in your "Path" Environment Variable. This may be a good step to take if you are doing a lot of development with Cg but may break your Maya as it will might find the nVidia Cg.dll before the one in its own bin folder.

The other option is to put the necessary Cg dlls in the same folder as your binaries. I think Windows goes looking for dependencies in the execution folder first before consulting the "Path". The problem with this is that you will end up with copies of the Cg dlls all over the place depending on how many projects you are making that use Cg [smile]

All The Best,
ViLiO
Richard 'ViLiO' Thomasv.net | Twitter | YouTube
Ah, where do I find those "path" variables?

Thanks for the great help mate! I've rated you as a very good user :)
If you right click on My Computer and select Properties. Then go to the Advanced tab there should be a button for Environment Variables. In there "Path" should be listed.

I'd advise having a quick Google for what it looks like and how to change it before touching it as you could mess a lot of stuff up if you make a mistake [smile]

Also, I think you've (hopefully accidentially) rated me as a very bad user [lol]

All The Best,
ViLiO
Richard 'ViLiO' Thomasv.net | Twitter | YouTube
Quote:Original post by ViLiO
If you right click on My Computer and select Properties. Then go to the Advanced tab there should be a button for Environment Variables. In there "Path" should be listed.

I'd advise having a quick Google for what it looks like and how to change it before touching it as you could mess a lot of stuff up if you make a mistake [smile]

Also, I think you've (hopefully accidentially) rated me as a very bad user [lol]

All The Best,
ViLiO


LOL! You got to be kidding me! I have rated you as a very good user, I think :D Oh well, at least that was what I wanted to rate you. Can I delete my rate and rate you again?

EDIT - Hmmm, I know what you mean. But I can not find the Maya directory in the Environment Variable list.

[Edited by - Vinniee on June 24, 2007 12:38:12 PM]

This topic is closed to new replies.

Advertisement