Thinking in Shader(5)

Thinking in Shader(5)

 

开发环境

Window7

CgToolkit

VS2008

 

 

        羽化的第二十二篇博客,据说Unity3D官网注册超过了70万,是去年的3倍,再者网上的教程也慢慢变多,各种质量的教程也相继出现,但大多数都是英文版,貌似看过中文视频一个做坦克的,只可借鉴,制作方法实在不敢恭维。。。羽化认为Unity作为一款引擎来说还不算成熟,在开发过程中也许会遇到各种奇怪问题,而且稳定性无法保证,但作为像羽化这种新手来说,开发简单很适合用来学习,而且新版本也许会改进很多问题,希望Unity3D越做越好。最近腾讯在大力宣传一款叫做《艾尔之光》的游戏,在公司看到有人在玩,看了看貌似做得不错,3D横版卡通渲染漫画风格的游戏,有点看到《龙之谷》的感觉,可惜物是人非,提不起劲来- -这种游戏若没喜欢的朋友一起玩,也就3分钟热度,韩国很适合做这类休闲游戏,可能是因为没文化底蕴又不受文化约束。。。游戏在推动世界进步,推荐大家去看看“[道兰][NHK纪录片]世界游戏革命”,可以对比自己心中的游戏,感觉还差多远。

 

Parameter Shadowing参数映射

       当一个统一的参数通过一些OpenGL Cgruntime功能允许的时候,通常会被保存在内存,这样每次使用时就不需要重新设置,这种行为就叫做参数映射,缺点在于消耗内存大小,但依然值得使用,其允许所有参数设置在纹理状态阶段和纹理模式下。

 

OpenGL Cg Runtime

      这里介绍一些基本参数,一般有两个版本,一个是float操作的标为“f”,另一个是以double操作的,设为“d”。

//设置统一标量和统一向量参数,通过cgGLSetParameter功能:
void cgGLSetParameter1f(CGparameter parameter, float x);
void cgGLSetParameter1fv(CGparameter parameter, const float* array);
void cgGLSetParameter1d(CGparameter parameter, double x);
void cgGLSetParameter1dv(CGparameter parameter, const double* array);
void cgGLSetParameter2f(CGparameter parameter, float x, float y);
void cgGLSetParameter2fv(CGparameter parameter, const float* array);
void cgGLSetParameter2d(CGparameter parameter, double x, double y);
void cgGLSetParameter2dv(CGparameter parameter, const double* array);
void cgGLSetParameter3f(CGparameter parameter, float x, float y, float z);
void cgGLSetParameter3fv(CGparameter parameter, const float* array);
void cgGLSetParameter3d(CGparameter parameter, double x, double y, double z);
void cgGLSetParameter3dv(CGparameter parameter, const double* array);
void cgGLSetParameter4f(CGparameter parameter, float x, float y, float z, float w);
void cgGLSetParameter4fv(CGparameter parameter, const float* array);
void cgGLSetParameter4d(CGparameter parameter, double x, double y, double z, double w);
void cgGLSetParameter4dv(CGparameter parameter, const double* array);


//相对应的检索功能
cgGLGetParameter1f(CGparameter parameter, float* array);
cgGLGetParameter1d(CGparameter parameter, double* array);
cgGLGetParameter2f(CGparameter parameter, float* array);
cgGLGetParameter2d(CGparameter parameter, double* array);
cgGLGetParameter3f(CGparameter parameter, float* array);
cgGLGetParameter3d(CGparameter parameter, double* array);
cgGLGetParameter4f(CGparameter parameter, double* array);
cgGLGetParameter4d(CGparameter parameter, type* array);

//设置统一的矩阵参数
void cgGLSetMatrixParameterfr(CGparameter parameter, const float* matrix);
void cgGLSetMatrixParameterfc(CGparameter parameter, const float* matrix);
void cgGLSetMatrixParameterdr(CGparameter parameter, const double* matrix);
void cgGLSetMatrixParameterdc(CGparameter parameter, const double* matrix);

//相应矩阵的检索功能
void cgGLGetMatrixParameterfr(CGparameter parameter, float* matrix);
void cgGLGetMatrixParameterfc(CGparameter parameter, float* matrix);
void cgGLGetMatrixParameterdr(CGparameter parameter, double* matrix);
void cgGLGetMatrixParameterdc(CGparameter parameter, double* matrix);

//获得4X4的矩阵
void cgGLSetStateMatrixParameter(CGparameter parameter, GLenum stateMatrixType, GLenum transform);
//这里的stateMatrixType,可能为CG_GL_MODELVIEW_MATRIX、CG_GL_PROJECTION_MATRIX、CG_GL_TEXTURE_MATRIX、CG_GL_MODELVIEW_PROJECTION_MATRIX
//后面的transform可能为CG_GL_MATRIX_IDENTITY、CG_GL_MATRIX_TRANSPOSE、CG_GL_MATRIX_INVERSE、CG_GL_MATRIX_INVERSE_TRANSPOSE

//设置统一标量数组,向量,和矩阵参数
void cgGLSetParameterArray1f(CGparameter parameter, long startIndex, long numberOfElements,
const float* array);
void cgGLSetParameterArray1d(CGparameter parameter, long startIndex, long numberOfElements, const double* array);
void cgGLSetParameterArray2f(CGparameter parameter, long startIndex, long numberOfElements, const float* array);
void cgGLSetParameterArray2d(CGparameter parameter, long startIndex, long numberOfElements, const double* array);
void cgGLSetParameterArray3f(CGparameter parameter, long startIndex, long numberOfElements, const float* array);
void cgGLSetParameterArray3d(CGparameter parameter, long startIndex, long numberOfElements, const double* array);
void cgGLSetParameterArray4f(CGparameter parameter, long startIndex, long numberOfElements, const float* array);
void cgGLSetParameterArray4d(CGparameter parameter, long startIndex, long numberOfElements, const double* array);

//相应的检索
void cgGLGetParameterArray1f(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetParameterArray1d(CGparameter parameter, long startIndex, long numberOfElements, double* array);
void cgGLGetParameterArray2f(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetParameterArray2d(CGparameter parameter, long startIndex, long numberOfElements, double* array);
void cgGLGetParameterArray3f(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetParameterArray3d(CGparameter parameter, long startIndex, long numberOfElements, double* array);
void cgGLGetParameterArray4f(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetParameterArray4d(CGparameter parameter, long startIndex, long numberOfElements, double* array);

//类似的功能设置矩阵数组
void cgGLSetMatrixParameterArrayfr(CGparameter parameter, long startIndex, long numberOfElements, const float* array);
void cgGLSetMatrixParameterArrayfc(CGparameter parameter, long startIndex, long numberOfElements, const float* array);
void cgGLSetMatrixParameterArraydc(CGparameter parameter, long startIndex, long numberOfElements, const double* array);
void cgGLSetMatrixParameterArraydc(CGparameter parameter, long startIndex, long numberOfElements, const double* array);

//检索
void cgGLGetMatrixParameterArrayfr(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetMatrixParameterArrayfc(CGparameter parameter, long startIndex, long numberOfElements, float* array);
void cgGLGetMatrixParameterArraydc(CGparameter parameter, long startIndex, long numberOfElements, double* array);
void cgGLGetMatrixParameterArraydc(CGparameter parameter, long startIndex, long numberOfElements, double* array);
//这里的c和r后缀其实是行column和列row

//设置不同的参数
void cgGLSetParameterPointer(CGparameter parameter, GLint size, GLenum type, GLsizei stride, GLvoid* array);  //第一步
void cgGLEnableClientState(CGparameter parameter); //第二步
void cgGLDisableClientState(CGparameter parameter); //逆第二步。。。

//设置单一参数
void cgGLSetTextureParameter(CGparameter parameter, GLuint textureName);//第一步
void cgGLSetManageTextureParameters(CGcontext context, CGbool enable); //第二步
void cgGLEnableTextureParameter(CGparameter parameter);//第三步
void cgGLDisableTextureParameter(CGparameter parameter);//逆第三步
GLuint cgGLGetTextureParameter(CGparameter parameter);//检索物件
GLenum cgGLGetTextureEnum(CGparameter parameter); //检索枚举器

OpenGL Profile Support配置文件支持

        一个方便的方法拿最有用的属性文件针对顶点或者片段程序:

CGprofile cgGLGetLatestProfile(CGGLenum profileType);
void cgGLSetOptimalOptions(CGprofile profile);//优化编译

OpenGL Program Execution程序运行

       过程很简单如下:(*为可选项)

void cgGLLoadProgram(CGprogram program); //所以程序先必须读取
void cgGLEnableProfile(CGprofile profile); // 配置文件启用
void cgGLDisableProfile(CGprofile profile);//配置文件不启用*
void cgGLBindProgram(CGprogram program); //绑定配置文件
CGbool cgGLIsProfileSupported(CGprofile profile);//判断配置文件是否支持*

OpenGL Program Examples程序实例

// VertexProgram.cg 顶点程序
void VertexProgram(in float4 position : POSITION,  in float4 color : COLOR0,
				in float4 texCoord : TEXCOORD0,  out float4 positionO : POSITION,
				out float4 colorO : COLOR0, out float4 texCoordO : TEXCOORD0,
				const uniform float4x4 ModelViewMatrix )
{
	positionO = mul(position, ModelViewMatrix);
	colorO = color;
	texCoordO = texCoord;
}

// FragmentProgram.cg 片段程序
void FragmentProgram(in float4 color : COLOR0, in float4 texCoord : TEXCOORD0,
					out float4 colorO : COLOR0, const uniform sampler2D BaseTexture,
					const uniform float4 SomeColor)
{
	colorO = color * tex2D(BaseTexture, texCoord) + SomeColor;
}

// OpenGL Application OpenGL应用
#include <cg/cg.h>
#include <cg/cgGL.h>
float* vertexPositions; // Initialized somewhere else别的地方初始化
float* vertexColors; // Initialized somewhere else
float* vertexTexCoords; // Initialized somewhere else
GLuint texture; // Initialized somewhere else
float constantColor[]; // Initialized somewhere else
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
CGprofile vertexProfile, fragmentProfile;
CGparameter position, color, texCoord, baseTexture, someColor,
			modelViewMatrix;
// Called at initialization初始化
void CgGLInit()
{
	// Create context 创建连接
	context = cgCreateContext();

	// Initialize profiles and compiler options初始化配置文件和编译器
	vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);
	cgGLSetOptimalOptions(vertexProfile);
	fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);
	cgGLSetOptimalOptions(fragmentProfile);

	// Create the vertex program创建顶点程序
	vertexProgram = cgCreateProgramFromFile(context, CG_SOURCE, "VertexProgram.cg", vertexProfile, "VertexProgram", 0);
	// Load the program读取程序
	cgGLLoadProgram(vertexProgram);

	// Create the fragment program创建片段程序
	fragmentProgram = cgCreateProgramFromFile(context, CG_SOURCE, "FragmentProgram.cg", fragmentProfile, "FragmentProgram", 0);
	// Load the program读取程序
	cgGLLoadProgram(fragmentProgram);

	// Grab some parameters.抓取一些参数
	position = cgGetNamedParameter(vertexProgram, "position");
	color = cgGetNamedParameter(vertexProgram, "color");
	texCoord = cgGetNamedParameter(vertexProgram, "texCoord");
	modelViewMatrix = cgGetNamedParameter(vertexProgram,"ModelViewMatrix");
	baseTexture = cgGetNamedParameter(fragmentProgram,	"BaseTexture");
	someColor = cgGetNamedParameter(fragmentProgram, "SomeColor");
	
	// Set parameters that don't change:设置参数不再改变
	// They can be set only once because of parameter shadowing.设置映射
	cgGLSetTextureParameter(baseTexture, texture);
	cgGLSetParameter4fv(someColor, constantColor);
}

// Called to render the scene 打开渲染场景
void Display()
{
	// Set the varying parameters设置不同参数
	cgGLEnableClientState(position);
	cgGLSetParameterPointer(position, 3, GL_FLOAT, 0, vertexPositions);
	cgGLEnableClientState(color);
	cgGLSetParameterPointer(color, 1, GL_FLOAT, 0, vertexColors);
	cgGLEnableClientState(texCoord);
	cgGLSetParameterPointer(texCoord, 2, GL_FLOAT, 0, vertexTexCoords);

	// Set the uniform parameters that change every frame设置统一参数每帧变化
	cgGLSetStateMatrixParameter(modelViewMatrix,CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	// Enable the profiles打开配置文件
	cgGLEnableProfile(vertexProfile);
	cgGLEnableProfile(fragmentProfile);
	// Bind the programs绑定配置文件
	cgGLBindProgram(vertexProgram);
	cgGLBindProgram(fragmentProgram);
	// Enable texture纹理可用
	cgGLEnableTextureParameter(baseTexture);
	// Draw scene 画场景
	// ...
	// Disable texture纹理不可用
	cgGLDisableTextureParameter(baseTexture);
	// Disable the profiles关闭配置文件
	cgGLDisableProfile(vertexProfile);
	cgGLDisableProfile(fragmentProfile);

	// Set the varying parameters设置不同参数状态
	cgGLDisableClientState(position);
	cgGLDisableClientState(color);
	cgGLDisableClientState(texCoord);
}

// Called before application shuts down 当程序关闭时响应
void CgShutdown()
{
	// This frees any runtime resource.释放所有资源
	cgDestroyContext(context);
}

OpenGL Error Reporting错误报告

         通过glGetError()方法得到错误报告,一般返回错误有:

         CG_PROGRAM_LOAD_ERROR

         CG_PROGRAM_BIND_ERROR

         CG_PROGRAM_NOT_LOADED_ERROR

         CG_UNSUPPORTED_GL_EXTENSION_ERROR



Direct3D Cg Runtime

         这个Direct3D Cgruntime包含两个接口:

         低配:此接口没有Direct3D自称,当你喜欢保持Direct3D代码在应用中。

         高配:此接口提供了所需的提高程序,参数管理,当你喜欢用Cg runtime 管理Direct3D着色器的时候。

         羽化个人认为高低配置比较适合这两个接口的区别。

 

Direct3D Minimal Interface低配接口

       提供一些方便的功能,把一些信息数据提供给核心运算,再把信息特征送到Direct3D。

Vertex Declaration 顶点声明

         在Direct3D中你必须提供一个顶点声明用来映射一张表在顶点着色器输入寄存器和应用程序数据流之间。

         一个数据流是一个基础的数组数据结构,每一个结构是一个特殊的类型称为顶点格式流,这里有一个顶点声明的例子,对应Direct3D 9:

//Direct3D 9
const D3DVERTEXELEMENT9 declaration[] = {
{ 	0, 0 * sizeof(float),
	D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
	D3DDECLUSAGE_POSITION, 0 }, // Position
{ 	0, 3 * sizeof(float),
	D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
	D3DDECLUSAGE_NORMAL, 0 }, // Normal
{ 	0, 8 * sizeof(float),
	D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
	D3DDECLUSAGE_TEXCOORD, 0 }, // Base texture
{ 	1, 0 * sizeof(float),
	D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
	D3DDECLUSAGE_TEXCOORD, 1 }, // Tangent
	D3DD3CL_END()
};

         两个声明都告诉Direct3Druntime去寻找:

(1)      顶点坐标在“流0”中,作为第一个3个浮点值的顶点格式

(2)      法线座位下一个3个浮点值紧随“流0”的3个浮点值。

(3)      贴图坐标作为两个浮点数据用作偏移量相当于一个DWORD的两倍尺寸,在法线数据结尾,在“流0”中。

切线提供在“流1”中作为第二个贴图坐标,被作为第一个3个浮点值的顶点格式。

//Direct3D 9
CGbool cgD3D9GetVertexDeclaration(CGprogram program,
						D3DVERTEXELEMENT9 declaration[MAXD3DDECLLENGTH]);
//MAXD3DDECLLENGTH 是Direct3D 9的常量,给Direct3 0声明的最大长度,如果程序中没有得到声明,会返回一个CG_FALSE

//返回值对于以下程序
void main(in float4 position : POSITION,
		in float4 color : COLOR0,
		in float4 texCoord : TEXCOORD0,
		out float4 hpos : POSITION)
{ }

//等同于 Direct3D 9 Cg runtime
const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
{ 0, 4 * sizeof(float),
D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0 },
{ 0, 8 * sizeof(float),
D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0 },
D3DD3CL_END()
};

//测试是否兼容程序
CGbool cgD3D9ValidateVertexDeclaration(CGprogram program,
const D3DVERTEXELEMENT9* declaration);   //Direct 9 
CGbool cgD3D8ValidateVertexDeclaration(CGprogram program,
const DWORD* declaration);  			//Direct 8 

//有效声明例如:
void main(float4 position : POSITION,
	float4 color : COLOR0,
	float4 texCoord : TEXCOORD0)
{ }

//等同于 Derect3D 9
const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
{ 0, 3 * sizeof(float),
D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0 },
{ 1, 4 * sizeof(float),
D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0 },
D3DD3CL_END()
};

//以上声明也可以写为
const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(CG_POSITION), 0 },
{ 0, 3 * sizeof(float),
D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(CG_COLOR0), 0 },
{ 1, 4 * sizeof(float),
D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(CG_TEXCOORD0), 0 },
D3DD3CL_END()
};

//如果这么做的话 这个将一个CGresource枚举到一个输入缓存器中
BYTE cgD3D9ResourceToDeclUsage(CGresource resource);

//写顶点说明必须根据程序参数来,减少引用语义
CGparameter position = cgGetNamedParameter(program, "position");
CGparameter color = cgGetNamedParameter(program, "color");
CGparameter texCoord = cgGetNamedParameter(program, "texCoord");

const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(
cgGetParameterResource(position)),
cgGetParameterResourceIndex(position) },
{ 0, 3 * sizeof(float),
D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(cgGetParameterResource(color)),
cgGetParameterResourceIndex(color) },
{ 1, 4 * sizeof(float),
D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
cgD3D9ResourceToDeclUsage(
cgGetParameterResource(texCoord)),
cgGetParameterResourceIndex(texCoord) },
D3DD3CL_END()
};

//检索
DWORD cgD3D9TypeToSize(CGtype type);

Minimal Interface ProgramExamples 低端接口程序实例

//Vertex Program 顶点程序
void VertexProgram(
	in float4 position : POSITION,
	in float4 color : COLOR0,
	in float4 texCoord : TEXCOORD0,
	out float4 positionO : POSITION,
	out float4 colorO : COLOR0,
	out float4 texCoordO : TEXCOORD0,
	const uniform float4x4 ModelViewMatrix)
{
	positionO = mul(position, ModelViewMatrix);
	colorO = color;
	texCoordO = texCoord;
}

//Fragment Program 片段程序
void FragmentProgram(
	in float4 color : COLOR0,
	in float4 texCoord : TEXCOORD0,
	out float4 colorO : COLOR0,
	const uniform sampler2D BaseTexture,
	const uniform float4 SomeColor)
{
	colorO = color * tex2D(BaseTexture, texCoord) + SomeColor;
}

//Direct3D 9 Application DX9应用
#include <cg/cg.h>
#include <cg/cgD3D9.h>
IDirect3DDevice9* device; // Initialized somewhere else 别处初始化
IDirect3DTexture9* texture; // Initialized somewhere else
D3DXMATRIX matrix; // Initialized somewhere else
D3DXCOLOR constantColor; // Initialized somewhere else
CGcontext context;
CGprogram vertexProgram, fragmentProgram;
IDirect3DVertexDeclaration9* vertexDeclaration;
IDirect3DVertexShader9* vertexShader;
IDirect3DPixelShader9* pixelShader;
CGparameter baseTexture, someColor, modelViewMatrix;
// Called at application startup 应用启动
void OnStartup()
{
	// Create context 创建context
	context = cgCreateContext();
}

// Called whenever the Direct3D device needs to be created 启动当Direct3D设备需要创建的时候
void OnCreateDevice()
{
// Create the vertex shader 创建顶点着色器
vertexProgram = cgCreateProgramFromFile(context, CG_SOURCE,
"VertexProgram.cg", CG_PROFILE_VS_2_0, "VertexProgram", 0);
CComPtr<ID3DXBuffer> byteCode;
const char* progSrc = cgGetProgramString(vertexProgram, CG_COMPILED_PROGRAM);
D3DXAssembleShader(progSrc, strlen(progSrc), 0, 0, 0, &byteCode, 0);

// If your program uses explicit binding semantics (like this one), you can create a vertex declaration using those semantics.如果程序使用明确的约束语义,可以创建一个顶点声明来使用这些语义
const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
{ 0, 3 * sizeof(float),
D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0 },
{ 0, 4 * sizeof(float),
D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0 },
D3DD3CL_END()
};

// Make sure the resulting declaration is compatible with the shader. This is really just a sanity check. 确保创建的声明是兼容的,这里是一个健全的检查
assert(cgD3D9ValidateVertexDeclaration(vertexProgram, declaration));
device->CreateVertexDeclaration(declaration, &vertexDeclaration);
device->CreateVertexShader(byteCode->GetBufferPointer(), &vertexShader);

// Create the pixel shader.创建像素着色器
fragmentProgram = cgCreateProgramFromFile(context,
CG_SOURCE, "FragmentProgram.cg",
CG_PROFILE_PS_2_0, "FragmentProgram", 0);
{
	CComPtr<ID3DXBuffer> byteCode;
const char* progSrc = cgGetProgramString(fragmentProgram, CG_COMPILED_PROGRAM);
D3DXAssembleShader(progSrc, strlen(progSrc), 0, 0, 0, &byteCode, 0);
device->CreatePixelShader(byteCode->GetBufferPointer(), &pixelShader)
}

// Grab some parameters. 获取一些参数
modelViewMatrix = cgGetNamedParameter(vertexProgram, "ModelViewMatrix");
baseTexture = cgGetNamedParameter(fragmentProgram, "BaseTexture");
someColor = cgGetNamedParameter(fragmentProgram, "SomeColor");

// Sanity check that parameters have the expected size 检查参数的预期大小
assert(cgD3D9TypeToSize(cgGetParameterType(modelViewMatrix)) == 16);
assert(cgD3D9TypeToSize(cgGetParameterType(someColor)) == 4);
}



// Called to render the scene 渲染场景
void OnRender()
{
// Get the Direct3D resource locations for parameters This can be done earlier and saved 早期获取Direct3D资源参数保存
DWORD modelViewMatrixRegister = cgGetParameterResourceIndex(modelViewMatrix);
DWORD baseTextureUnit = cgGetParameterResourceIndex(baseTexture);
DWORD someColorRegister = cgGetParameterResourceIndex(someColor);

// Set the Direct3D state.设置Direct3D状态
device->SetVertexShaderConstantF(modelViewMatrixRegister, &matrix, 4);
device->SetPixelShaderConstantF(someColorRegister, &constantColor, 1);
device->SetVertexDeclaration(vertexDeclaration);
device->SetTexture(baseTextureUnit, texture);
device->SetVertexShader(vertexShader);
device->SetPixelShader(pixelShader);
// Draw scene.
// ...
}


// Called before the device changes or is destroyed调用在设备改变或者终止之前
void OnDestroyDevice() 
{
	vertexShader->Release();
	pixelShader->Release();
	vertexDeclaration->Release();
}


// Called before application shuts down调用在程序关闭之前
void OnShutdown() 
{
// This frees any core runtime resources. The minimal interface has no dynamic storage to free.释放所有资源,低配接口没用动态资源释放
	cgDestroyContext(context);
}

 

Direct3D Expanded Interface 高配接口

       如果你想使用高配接口,尽量避免那些意外的错误,明确按照高配接口的相关着色器操作来执行,如着色器设定,着色器活化和参数设定包括设置纹理状态。

//设置Direct3D设备
HRESULT cgD3D9SetDevice(IDirect3DDevice9* device);
//获得当前设备关联
IDirect3DDevice9* cgD3D9GetDevice();

//丢失设备时
IDirect3DDevice9* device; // Initialized elsewhere
IDirect3DTexture9* myDefaultPoolTexture;
CGprogram program;
void OneTimeLoadScene()
{
// Load the program with cgD3D9LoadProgram and enable parameter shadowing读取程序和启动映射
/* ... */
cgD3D9LoadProgram(program, TRUE, 0, 0, 0);
/* ... */
// Bind sampler parameter 绑定采样参数
GCparameter parameter;
parameter = cgGetParameterByName(program, "MySampler");
cgD3D9SetTexture(parameter, myDefaultPoolTexture);
}
void OnLostDevice()
{
// First release all necessary resources 第一释放所有所需资源
PrepareForReset();
// Next actually reset the Direct3D device下一步重新设置设备
device->Reset( /* ... */ );
// Finally recreate all those resource最后重建资源
OnReset();
}
void PrepareForReset()
{
/* ... */
// Release expanded interface reference释放高配接口关联
cgD3D9SetTexture(mySampler, 0);
// Release local reference and any other references to the texture释放本地关联和其他任何与纹理有关的关联
myDefaultPoolTexture->Release();
/* ... */
}
void OnReset()
{
// Recreate myDefaultPoolTexture in D3DPOOL_DEFAULT重建纹理池
/* ... */
// Since the texture was just recreated,it must be re-bound to the parameter再现纹理必须重新绑定参数
GCparameter parameter;
parameter = cgGetParameterByName(prog, "MySampler");
cgD3D9SetTexture(mySampler, myDefaultPoolTexture);
/* ... */
}

//提供参数类型
HRESULT cgD3D9SetUniform(CGparameter parameter, const void* value);

D3DXVECTOR3 vectorData(1,2,3);
float matrixData[2][3] = {{1, 2, 3}, {4, 5, 6}};
float arrayData[3][2][2] ={{{1, 2}, {3, 4}},{{5, 6},{7,8}}, {{9, 10}, {11, 12}}};
cgD3D9SetUniform(vectorParam, &vectorData);
cgD3D9SetUniform(matrixParam, matrixData);
cgD3D9SetUniform(arrayParam, arrayData);

HRESULT cgD3D9SetUniformMatrix(CGparameter parameter, const D3DMATRIX* matrix);
D3DXMATRIX matrix(
	1, 1, 1, 0,
	1, 1, 1, 0,
	0, 0, 0, 0,
	0, 0, 0, 0,
);
cgD3D9SetUniformMatrix(matrixParam, &matrix);

//设置标量,向量矩阵参数统一数值
HRESULT cgD3D9SetUniformArray(CGparameter parameter, DWORD startIndex, DWORD 									numberOfElements,const void* array);
HRESULT cgD3D9SetUniformMatrixArray(CGparameter parameter, DWORD startIndex, 								DWORD numberOfElements, const D3DMATRIX* matrices);

//采样参数设置
HRESULT cgD3D9SetTexture(CGparameter parameter, IDirect3DBaseTexture9* 								texture);
HRESULT cgD3D9SetSamplerState(CGparameter parameter, D3DSAMPLERSTATETYPE type, 							DWORD value);

cgD3D9SetSamplerState(parameter, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

//纹理包设置
HRESULT cgD3D9SetTextureWrapMode(CGparameter parameter, DWORD value);
cgD3D9SetTextureWrapMode(parameter, D3DWRAP_U | D3DWRAP_V);

//参数映射
HRESULT cgD3D9EnableParameterShadowing(CGprogram program, CGbool enable);
//是否启用映射
CGbool cgD3D9IsParameterShadowingEnabled(CGprogam program);

//高配接口程序执行
HRESULT cgD3D9LoadProgram(CGprogram program, CG_BOOL parameterShadowingEnabled,
							DWORD assembleFlags);

HRESULT hresult = cgD3D9LoadProgram(vertexProgram, TRUE, D3DXASM_DEBUG);
HRESULT hresult = cgD3D9LoadProgram(fragmentProgram, TRUE, 0);

//释放程序
HRESULT cgD3D9UnloadProgam(CGprogram program);

//绑定程序
HRESULT cgD3D9BindProgram(CGprogram program);

//高配接口配置文件
CGprofile cgD3D9GetLatestVertexProfile();
CGprofile cgD3D9GetLatestPixelProfile();

//返回最佳的编译选项给一个配置文件
char const* cgD3D9GetOptimalOptions(CGprofile profile);

//高配接口程序实例

//VertexProgram.cg
void VertexProgram(
in float4 position : POSITION,
in float4 color : COLOR0,
in float4 texCoord : TEXCOORD0,
out float4 positionO : POSITION,
out float4 colorO : COLOR0,
out float4 texCoordO : TEXCOORD0,
const uniform float4x4 ModelViewMatrix)
{
	positionO = mul(position, ModelViewMatrix);
	colorO = color;
	texCoordO = texCoord; }

//FragmentProgram.cg
void FragmentProgram(
in float4 color : COLOR0,
in float4 texCoord : TEXCOORD0,
out float4 colorO : COLOR0,
const uniform sampler2D BaseTexture,
const uniform float4 SomeColor)
{
	colorO = color * tex2D(BaseTexture, texCoord) + SomeColor;
}

//Direct3D 9 应用程序
#include <cg/cg.h>
#include <cg/cgD3D9.h>
IDirect3DDevice9* device; // Initialized somewhere else 别处初始化
IDirect3DTexture9* texture; // Initialized somewhere else
D3DXCOLOR constantColor; // Initialized somewhere else
CGcontext context;
IDirect3DVertexDeclaration9* vertexDeclaration;
CGprogram vertexProgram, fragmentProgram;
CGparameter baseTexture, someColor, modelViewMatrix;
// Called at application startup 应用打开时调用
void OnStartup()
{
// Create context 创建连接
context = cgCreateContext();
}

// Called whenever the Direct3D device needs to be created设备连接时调用
void OnCreateDevice()
{
// Pass the Direct3D device to the expanded interface.把高配接口传给设备
cgD3D9SetDevice(device);
// Determine the best profiles to use确定最佳配置文件
CGprofile vertexProfile = cgD3D9GetLatestVertexProfile();
CGprofile pixelProfile = cgD3D9GetLatestPixelProfile();

// Grab the optimal options for each profile.获取配置文件的最佳选择
const char* vertexOptions[] = {cgD3D9GetOptimalOptions(vertexProfile), 0 };
const char* pixelOptions[] = { cgD3D9GetOptimalOptions(pixelProfile), 0 };

// Create the vertex shader.创建顶点着色器
vertexProgram = cgCreateProgramFromFile(
context, CG_SOURCE, "VertexProgram.cg",vertexProfile, "VertexProgram", vertexOptions);

// If your program uses explicit binding semantics, you can create a vertex declaration using those semantics.如果你的程序使用明确的约束语义,可以创建一个顶点声明使用这些语义
const D3DVERTEXELEMENT9 declaration[] = {
{ 0, 0 * sizeof(float),
D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
{ 0, 3 * sizeof(float),
D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_COLOR, 0 },
{ 0, 4 * sizeof(float),
D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_TEXCOORD, 0 },
D3DD3CL_END()
};

// Ensure the resulting declaration is compatible with the shader. This is really just a sanity check. 确保结果声明通过着色器完成,已经通过完全检查
assert(cgD3D9ValidateVertexDeclaration(vertexProgram, declaration));
device->CreateVertexDeclaration(declaration, &vertexDeclaration);

// Load the program with the expanded interface. Parameter shadowing is enabled (second parameter = TRUE).从高配接口读取程序,参数映射启用。
cgD3D9LoadProgram(vertexProgram, TRUE, 0);

// Create the pixel shader.创建像素着色器
fragmentProgram = cgCreateProgramFromFile( context, CG_SOURCE, "FragmentProgram.cg", pixelProfile, "FragmentProgram", pixelOptions);

// Load the program with the expanded interface. Parameter shadowing is enabled (second parameter = TRUE). Ignore vertex shader specifc flags, such as declaration usage. .从高配接口读取程序,参数映射启用,忽略顶点着色器特殊标志,就像使用声明。
cgD3D9LoadProgram(fragmentProgram, TRUE, 0);

// Grab some parameters.获取参数
modelViewMatrix = cgGetNamedParameter(vertexProgram, "ModelViewMatrix");
baseTexture = cgGetNamedParameter(fragmentProgram,"BaseTexture");
someColor = cgGetNamedParameter(fragmentProgram, "SomeColor");

// Sanity check that parameters have the expected size明确检查参数的预期大小
assert(cgD3D9TypeToSize(cgGetParameterType(modelViewMatrix)) == 16);
assert(cgD3D9TypeToSize(cgGetParameterType(someColor))== 4);

// Set parameters that don't change. They can be set only once since parameter shadowing is enabled 设置参数不能改变,他们设置只能参数绑定启用时
cgD3D9SetTexture(baseTexture, texture);
cgD3D9SetUniform(someColor, &constantColor);
}

// Called to render the scene渲染场景时调用
void OnRender()
{
// Load model-view matrix.读取可视模型矩阵
D3DXMATRIX modelViewMatrix;
// ...
// Set the parameters that change every frame This must be done before binding the programs 设定每帧参数修改,在绑定程序之前
cgD3D9SetUniformMatrix(modelViewMatrix, &modelViewMatrix);

// Set the vertex declaration设置顶顶声明
device->SetVertexDeclaration(vertexDeclaration);

// Bind the programs. This downloads any parameter values that have been previously set.绑定程序,下载先前设定的参数
cgD3D9BindProgram(vertexProgram);
cgD3D9BindProgram(fragmentProgram);

// Draw scene.绘制场景
// ...
}
// Called before the device changes or is destroyed 设备改变或终止时调用
void OnDestroyDevice()
{
// Calling this function tells the expanded interface to release its internal reference to the Direct3D device and free its Direct3D resources. 释放高配接口的内部关联对Direct3D设备和资源。
	cgD3D9SetDevice(0);
}
// Called before application shuts down 应用关闭时调用
void OnShutdown()
{
// This frees any core runtime resource.释放核心资源
	cgDestroyContext(context);
}

 

Direct3D Debugging Mode 调试模式

         使用Debug DLL:

1.      连接应用程序到cgD3D9d.lib代替cgD3D9.lib。

2.      确定应用能找到cgD3D9d.dll。

3.      打开或者关闭跟踪代码

void cgD3D9EnableDebugTracing(CGbool enable);

         这里有一个例子

cgD3D9EnableDebugTracing(CG_TRUE);
// ...
// Application code that is traced
// ...
cgD3D9EnableDebugTracing(CG_FALSE);

        

         常见错误类型:

         CGerror:

                  cgD3D9Failed

             cgD3D9DebugTrace

          HRESULT:

             CGD3D9ERR_INVALIDPARAM

             CGD3D9ERR_INVALIDPROFILE

             CGD3D9ERR_INVALIDSAMPLERSTATE

             CGD3D9ERR_INVALIDVEREXDECL

             CGD3D9ERR_NODEVICE

             CGD3D9ERR_NOTMATRIX

             CGD3D9ERR_NOTLOADED

             CGD3D9ERR_NOTSAMPLER

             CGD3D9ERR_NOTUNIFORM

             CGD3D9ERR_NULLVALUE

             CGD3D9ERR_OUTOFRANGE

             CGD3D9_INVALID_REG

 

    测试错误

HRESULT cgD3D9GetLastError();
const char* cgD3D9TranslateHRESULT(HRESULT hr);//转换成字符串

   

    错误回调

void MyErrorCallback() {
CGerror error = cgGetError();
if (error == cgD3D9DebugTrace) {
// This is a debug trace output.
// A breakpoint could be set here to step from one
// debug output to the other.
return;
}
char buffer[1024];
if (error == cgD3D9Failed)
sprintf(buffer, "A Direct3D error occurred: %s'\n",
cgD3D9TranslateHRESULT(cgD3D9GetLastError()));
else
sprintf(buffer, "A Cg error occurred: '%s'\n",
cgD3D9TranslateCGerror(error));
OutputDebugString(buffer);
}
cgSetErrorCallback(MyErrorCallback);


下期预告:

         Thinking in Shader(6)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值