DXUT实战1:CG+D3D9+DXUT(june_2010)

走完DXUT三步曲,下面就可以正式开始学习shader了,这里主要讲解如何搭建Shader的框架:

 

这个实例先用CG,后面我会尝试用HLSL试试

 

当我把这个例子写出来的时候小兴奋了把,DXUT太强大了,还有微软的文档及sample和NVIDIA的文档及sample真是不可多得的财富,从此坚定了我紧跟微软和英伟达脚步的决心,哈哈!

 

废话不多说了,直接上源码:

 

//--------------------------------------------------------------------------------------
// File: control_color_by_using_CG_DXUT(june_2010)_D3D9.cpp
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "DXUT.h"
#include "DXUTgui.h"//CDXUTDialogResourceManager需要
#include "resource.h"

#pragma comment(lib, "cg.lib")
#pragma comment(lib, "cgd3d9.lib")


#define	IDC_SLIDER_RED			1
#define	IDC_SLIDER_GREEN		2
#define	IDC_SLIDER_BLUE			3

#define IDC_STATIC_RED			4
#define IDC_STATIC_GREEN		5
#define IDC_STATIC_BLUE			6


// Global variable
static CGcontext myCgContext;//环境,中间层
static CGprofile myCgVertexProfile;//格式
static CGprogram myCgVertexProgram;//目标文件

static IDirect3DVertexBuffer9* myVertexBuffer = NULL;

static const WCHAR* myProgramNameW = L"MyProgram";//程序名字,输出错误时用
static const char	*myProgramName = "MyProgram",
					*myVertexProgramFileName = "myVertex.cg",//shader源文件
					*myVertexProgramEntryFunctionName = "myVertexEntry"; //顶点shader的入口函数名
static CGparameter myCgVertexParam_r,
				   myCgVertexParam_g,
				   myCgVertexParam_b;

int r,g,b;


CDXUTDialogResourceManager g_dlg_resource_manager;
CDXUTDialog g_control_dlg;

static void checkForCgError(const char *situation)
{
  char buffer[4096];
  CGerror error;
  const char *string = cgGetLastErrorString(&error);
  //error  A pointer to a CGerror variable for returning the last error code.
  if (error != CG_NO_ERROR) {
    if (error == CG_COMPILER_ERROR) {
      sprintf(buffer,
              "Program: %s\n"
              "Situation: %s\n"
              "Error: %s\n\n"
              "Cg compiler output...\n",
              myProgramName, situation, string);
      OutputDebugStringA(buffer);
      OutputDebugStringA(cgGetLastListing(myCgContext));
	  /*
			Each Cg context maintains a null-terminated string containing warning and error messages generated by the Cg compiler,
			state managers and the like. cgGetLastListing allows applications and custom state managers to query the listing text. 
			cgGetLastListing returns the current listing string for the given CGcontext. When a Cg runtime error occurs, applications 
			can use the listing text from the appropriate context to provide the user with detailed information about the error. 
	  */
      sprintf(buffer,
              "Program: %s\n"
              "Situation: %s\n"
              "Error: %s\n\n"
              "Check debug output for Cg compiler output...",
              myProgramName, situation, string);
      MessageBoxA(0, buffer,
                  "Cg compilation error", MB_OK | MB_ICONSTOP | MB_TASKMODAL);
    } else {
      sprintf(buffer,
              "Program: %s\n"
              "Situation: %s\n"
              "Error: %s",
              myProgramName, situation, string);
      MessageBoxA(0, buffer,
                  "Cg runtime error", MB_OK | MB_ICONSTOP | MB_TASKMODAL);
    }
    exit(1);
  }
}

//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
                                      bool bWindowed, void* pUserContext )
{
    // Typically want to skip back buffer formats that don't support alpha blending
    IDirect3D9* pD3D = DXUTGetD3D9Object();
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                                         AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
                                         D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
    return true;
}


//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext )
{
	HRESULT hr;
	V_RETURN(g_dlg_resource_manager.OnD3D9CreateDevice(pd3dDevice));
    return S_OK;
}

static void createCgPrograms()
{
	const char** profileOpts;
	myCgVertexProfile = cgD3D9GetLatestVertexProfile();//返回最新版本
	checkForCgError("getting latest profile");

	profileOpts = cgD3D9GetOptimalOptions(myCgVertexProfile);//得到该版本对应的最佳选项
	checkForCgError("getting latest profile option");

  myCgVertexProgram =
    cgCreateProgramFromFile(
      myCgContext,              /* Cg runtime context */
      CG_SOURCE,                /* Program in human-readable form */
      myVertexProgramFileName,  /* Name of file containing program */
      myCgVertexProfile,        /* Profile: OpenGL ARB vertex program */
      myVertexProgramEntryFunctionName,      /* Entry function name */
      profileOpts);             /* Pass optimal compiler options */
  checkForCgError("creating vertex program from file");		

  myCgVertexParam_r =
    cgGetNamedParameter(myCgVertexProgram, "r");
  checkForCgError("could not get r parameter");

    myCgVertexParam_g =
    cgGetNamedParameter(myCgVertexProgram, "g");
  checkForCgError("could not get g parameter");

    myCgVertexParam_b =
    cgGetNamedParameter(myCgVertexProgram, "b");
  checkForCgError("could not get b parameter");


}
struct MY_V3F
{
	FLOAT x, y, z;
};
static HRESULT initVertexBuffer(IDirect3DDevice9* pDev)
{
  /* Initialize three vertices for rendering a triangle. */
  static const MY_V3F triangleVertices[] = {
    { -0.8f,  0.8f, 0.0f },
    {  0.0f,  0.8f, 0.0f },
    { -0.4f,  0.0f, 0.0f }
  };

  if (FAILED(pDev->CreateVertexBuffer(sizeof(triangleVertices),
                                      0, D3DFVF_XYZ,
                                      D3DPOOL_DEFAULT,
                                      &myVertexBuffer, NULL))) {
    return E_FAIL;
  }

  void* pVertices;
  if (FAILED(myVertexBuffer->Lock(0, 0, /* map entire buffer */
                                  &pVertices, 0))) {
    return E_FAIL;
  }
  memcpy(pVertices, triangleVertices, sizeof(triangleVertices));
  myVertexBuffer->Unlock();

  return S_OK;
}

//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT) 
// or that are tied to the back buffer size 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                    void* pUserContext )
{

	HRESULT hr;
	V_RETURN(g_dlg_resource_manager.OnD3D9ResetDevice());

	  g_control_dlg.SetLocation(pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 350);
	g_control_dlg.SetSize(170, 300);

	// setup view matrix
	D3DXMATRIX mat_view;
	D3DXVECTOR3 eye(0.0f, 0.0f, -5.0f);
	D3DXVECTOR3 at(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);

	D3DXMatrixLookAtLH(&mat_view, &eye, &at, &up);
	pd3dDevice->SetTransform(D3DTS_VIEW, &mat_view);

	// set projection matrix
	D3DXMATRIX mat_proj;
	float aspect = (float)pBackBufferSurfaceDesc->Width / pBackBufferSurfaceDesc->Height;
	D3DXMatrixPerspectiveFovLH(&mat_proj, D3DX_PI/4, aspect, 1.0f, 100.0f);
	pd3dDevice->SetTransform(D3DTS_PROJECTION, &mat_proj);
	cgD3D9SetDevice(pd3dDevice);
	checkForCgError("setting Direct3D device");
	  static int firstTime = 1;
  if (firstTime) {
    /* Cg runtime resources such as CGprogram and CGparameter handles
       survive a device reset so we just need to compile a Cg program
       just once.  We do however need to unload Cg programs with
       cgD3DUnloadProgram upon when a Direct3D device is lost and load
       Cg programs every Direct3D device reset with cgD3D9UnloadProgram. */
    createCgPrograms();
    firstTime = 0;
  }
    /* false below means "no parameter shadowing" */
  cgD3D9LoadProgram(myCgVertexProgram, false, 0);
  checkForCgError("loading vertex program");


   return initVertexBuffer(pd3dDevice);
}


//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    // Clear the render target and the zbuffer 
    V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
		V(g_control_dlg.OnRender(fElapsedTime));

		 cgD3D9BindProgram(myCgVertexProgram);
    checkForCgError("binding vertex program");

    /* Render the triangle. */
    pd3dDevice->SetStreamSource(0, myVertexBuffer, 0, sizeof(MY_V3F));
    pd3dDevice->SetFVF(D3DFVF_XYZ);

	 cgSetParameter1f(myCgVertexParam_r, (float)r/255);

		 cgSetParameter1f(myCgVertexParam_g, (float)g/255);
		 cgSetParameter1f(myCgVertexParam_b, (float)b/255);
    cgUpdateProgramParameters(myCgVertexProgram);
    pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
	*pbNoFurtherProcessing = g_dlg_resource_manager.MsgProc(hWnd, uMsg, wParam, lParam);
	if(*pbNoFurtherProcessing)
		return 0;
	*pbNoFurtherProcessing = g_control_dlg.MsgProc(hWnd, uMsg, wParam, lParam);
	if(*pbNoFurtherProcessing)
		return 0;
    return 0;
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
	g_dlg_resource_manager.OnD3D9LostDevice();
	 myVertexBuffer->Release();
	 cgD3D9SetDevice(NULL);
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
	g_dlg_resource_manager.OnD3D9DestroyDevice();
}
void CALLBACK OnGUIEvent(UINT event, int control_id, CDXUTControl* control, void* user_context)
{
	switch(control_id)
	{
	case IDC_SLIDER_RED:
		{
		r = g_control_dlg.GetSlider(IDC_SLIDER_RED)->GetValue();
		CDXUTStatic* pStatic = g_control_dlg.GetStatic(IDC_STATIC_RED);
		if(pStatic)
		{
			WCHAR wszText[128];
			swprintf_s( wszText, 128, L"R:%3d", r );
			pStatic->SetText( wszText );
		}
		break;
		}
	case IDC_SLIDER_GREEN:
		{
		g = g_control_dlg.GetSlider(IDC_SLIDER_GREEN)->GetValue();
		CDXUTStatic* pStatic = g_control_dlg.GetStatic(IDC_STATIC_GREEN);
		if(pStatic)
		{
			WCHAR wszText[128];
			swprintf_s( wszText, 128, L"G:%3d", g );
			pStatic->SetText( wszText );
		}
		break;
		}
	case IDC_SLIDER_BLUE:
		b = g_control_dlg.GetSlider(IDC_SLIDER_BLUE)->GetValue();
		CDXUTStatic* pStatic = g_control_dlg.GetStatic(IDC_STATIC_BLUE);
		if(pStatic)
		{
			WCHAR wszText[128];
			swprintf_s( wszText, 128, L"B:%3d", b );
			pStatic->SetText( wszText );
		}
		break;
	}
}
void InitDialogs()
{

	g_control_dlg.Init(&g_dlg_resource_manager);

	int  y = 10,  height = 22;

	g_control_dlg.SetCallback(OnGUIEvent);
	g_control_dlg.AddStatic(IDC_STATIC_RED,L"R:100",10, y+24, 30, height);
	g_control_dlg.AddSlider(IDC_SLIDER_RED, 50, y += 24, 100, height);
	g_control_dlg.GetSlider(IDC_SLIDER_RED)->SetRange(0, 255);
	g_control_dlg.GetSlider(IDC_SLIDER_RED)->SetValue(100);
	r = 100;
	g_control_dlg.AddStatic(IDC_STATIC_GREEN,L"G:100",10, y+24, 30, height);
	g_control_dlg.AddSlider(IDC_SLIDER_GREEN, 50, y += 24, 100, height);
	g_control_dlg.GetSlider(IDC_SLIDER_GREEN)->SetRange(0, 255);
	g_control_dlg.GetSlider(IDC_SLIDER_GREEN)->SetValue(100);
	g = 100;
	g_control_dlg.AddStatic(IDC_STATIC_BLUE,L"B:100",10, y+24, 30, height);
	g_control_dlg.AddSlider(IDC_SLIDER_BLUE, 50, y += 24, 100, height);
	g_control_dlg.GetSlider(IDC_SLIDER_BLUE)->SetRange(0, 255);
	g_control_dlg.GetSlider(IDC_SLIDER_BLUE)->SetValue(100);
	b = 100;


}
//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
	myCgContext = cgCreateContext();//创建环境
	checkForCgError("creating context");
	cgSetParameterSettingMode(myCgContext, CG_DEFERRED_PARAMETER_SETTING);
	/*
	CG_IMMEDIATE_PARAMETER_SETTING 
	Non-erroneous cgSetParameter commands immediately update the corresponding 3D API parameter. This is the default mode. 
	CG_DEFERRED_PARAMETER_SETTING 
	Non-erroneous cgSetParameter commands record the updated parameter value but do not immediately update the corresponding 3D API parameter.
	These updates will happen during the next program bind. The updates can be explicitly forced to occur by using cgUpdateProgramParameters 
	or cgUpdatePassParameters. 
	*/

    // Set the callback functions
    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameMove( OnFrameMove );

    // TODO: Perform any application-level initialization here
	InitDialogs();
    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true ); // Parse the command line and show msgboxes
    DXUTSetHotkeyHandling( true, true, true );  // handle the default hotkeys
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"control_color_by_using_CG_DXUT(june_2010)_D3D9" );
    DXUTCreateDevice( true, 400, 400 );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here
	cgDestroyProgram(myCgVertexProgram);
	checkForCgError("destroying vertex program");
	cgDestroyContext(myCgContext);
	checkForCgError("destroying context");
    return DXUTGetExitCode();
}



 

对应的cg文件

/*--------------------------------------------------------------------------
	myVertex.cg -- the vertex shader controling the color of the triangle  
						(c) Seamanj.2013/7/10
--------------------------------------------------------------------------*/
struct Output {
  float4 position : POSITION;
  float3 color    : COLOR;
};

Output myVertexEntry(float2 position : POSITION, uniform float r, uniform float g, uniform float b)
{	
  Output OUT;

  OUT.position = float4(position,0,1);
  OUT.color = float3(r,g,b);
  return OUT;	
}



最终的运行效果:

 

可以通过三个滚动条改变三角形的颜色

OK,睡觉,明天任务搞个HLSL版本出来,另外<<Pro OGRE 3D Programming>>第4章搞定,OGRE的学习正式提上日程,争取月底OGRE毕业,到时候专心研究Hydrax源码.不然太对不起老何了!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值