Thinking in Shader(6)

开发环境

Window7

CgToolkit

VS2008


        羽化的第二十三篇博客,最近包括CSDN在内很多论坛遭受攻击,大家注意自己的要多注意自己的账户安全- -,话说这一年很快就要过去了,下一篇博客的前言是不是该写点年总结。。。最近工作很忙,羽化在写最终项目代码,目前基本上决定全用C#来写,尽力做到精致完美~ ~ 话说项目一下子来了两个策划,系统在慢慢搭建,虽然羽化不喜欢国内游戏制作的氛围,但这种应该还是可以慢慢改变,这次Cg的学习理论部分差不多结束了,下面都是代码操作,英语水平有限,请大家见谅,只能拿来看看概括,不能当作教程来学习,有兴趣的朋友还是去找找官方资料,详情请见Thinking in Shader(1)。

 

Introductionto CgFX 介绍CgFX

         CgFx是Cg格式的延伸,添加进Cg程序中,CgFX文件也能代表固定管线图形状态和着色器源信息。CgFX API使他可以读取CgFX的特效文件,通过数据设置关联图形状态等等。关键概念包括:Effect、Technique、Pass、State assignment、Annotation、Effect parameter。

Getting Started开始

    考虑下面特效:

//这个特效定义了一个简单参数,type只是为了程序方便调用,初始值是{1,1,1} 有一个限定范围
float3 DiffuseColor<string type = "color";
					float3 minValue = float3(0,0,0);
					float3 maxValue = float3(10,10,10);> = { 1, 1, 1 };

//这个特效还定义了一个方法,其中含有一个简单的渲染通道,这个通道设置适当的OpenGL状态来执行每个顶点光使用固定管线材质模型。注意LightDiffuse可以看出受散色光影响
technique FixedFunctionLighting 
{
	pass 
	{
		LightingEnable = true;
		LightEnable[0] = true;
		LightPosition[0] = float4(-10, 10, 10, 1);
		LightAmbient[0] = float4(.1,.1,.1,.1);
		LightDiffuse[0] = (float4(2*DiffuseColor, 1));
		LightSpecular[0] = float4(1,1,1,1);
		MaterialShininess = 10.f;
		MaterialAmbient = float4(1,1,1,1);
		MaterialDiffuse = float4(.5, .5, .5, 1);
		MaterialSpecular = float4(.5, .5, .5, 1);
	}
}

         下面是创建一个给定特效名字的程序:

CGcontext context = cgCreateContext(); //创建关联
cgGLRegisterStates(context); //创建OpenGL状态管理
CGeffect effect = cgCreateEffectFromFile(context, "simple.cgfx", NULL);
if (!effect) 
{
	fprintf(stderr, "Unable to create effect!\n");
	const char *listing = cgGetLastListing(context);
	if (listing)
	fprintf(stderr, "%s\n", listing);
	exit(1);
}

 

Technique Validation 技术验证

         在使用任何技术在特效上时,都必须先验证下是否可用:

CGtechnique technique = cgGetFirstTechnique(effect);
while (technique)
{
	if (cgValidateTechnique(technique) == CG_FALSE)
	fprintf(stderr, "Technique %s did not validate. Skipping.\n",
			cgGetTechniqueName(technique));
	technique = cgGetNextTechnique(technique);
}

// cgIsTechniqueValidated() 一般用来检查

Passes and Pass State 通道和通道状态

         在CgFX中允许一个通道状态定义在技术中:

CGpass pass = cgGetFirstPass(technique);
while (pass)
{
	cgSetPassState(pass);
	drawGeom();
	cgResetPassState(pass);
	pass = cgGetNextPass(pass);
}

Effect Parameters 特效参数

         参数的句柄可以寻回使用cgGetNamedEffectParameter(),针对这个句柄,可以用cgGetParameterName()得到,值可以设置到程序入口:

CGparameter c = cgGetNamedEffectParameter(effect, "Color");
cgSetParameter3fv(c, Color);
CGparameter mvp = cgGetNamedEffectParameter(effect, "ModelViewProjection");
cgGLSetStateMatrixParameter(mvp, CG_GL_MODELVIEW_PROJECTION_MATRIX,
							CG_GL_MATRIX_IDENTITY);

 

Vertex and Fragment Programs顶点和片段程序

         通过OpenGL状态管理,顶点和片段程序定义分配给了顶点程序和片段程序状态,代表3个不同的类表达式可以分配给另一边:Compilestatements、In‐line assembly、NULL

float4 main(uniform float foo, float4 uv : TEXCOORD0) : COLOR
{
	return (foo > 0) ? uv : 2 * uv;
}

technique SimpleFrag
{
	pass 
	{
		VertexProgram = NULL;
		FragmentProgram = compile arbfp1 main(-2.f);
	}
}
technique AsmFrag 
{
	pass 
	{
		FragmentProgram = asm 
		{
			!!FP1.0
			TEX o[COLR], {0}.x, TEX6, 2D;
			END
		};
	}
}

//另一个例子
float4 main(uniform float foo, float4 uv : TEXCOORD0) : COLOR
{
	return (foo > 0) ? uv : 2 * uv;
}
float bar;
technique NewSimpleFrag
{
	pass 
	{
		VertexProgram = NULL;
		FragmentProgram = compile arbfp1 main(2 * bar);// 2 * bar链接的是main中的参数
	}
}

Textures and Samplers 贴图和采样器

         CgFX使定义状态关联到贴图在特效文件中成为可能,例如:

sampler2D samp = sampler_state {
				generateMipMap = true;
				minFilter = LinearMipMapLinear;
				magFilter = Linear;};

float4 texsimple(uniform sampler2D sampler,
			float2 uv : TEXCOORD0) : COLOR {
return tex2D(sampler, uv);
}
technique TextureSimple {
	pass
	{
		FragmentProgram = compile arbfp1 texsimple(samp);
	}
}

         得到这个特效文件,应用程序需要另外两步:1.应用必须表明哪张贴图处理需要sampler2D在特效文件中,2.应用程序必须使用Cg runtime设置贴图状态在适当的时间中给出到sampler_state 块中。最简单的方法是用cgGLSetupSampler(param, textureID)和初始化状态cgSetSamplerState()例如:

CGparameter p = cgGetNamedEffectParameter(effect, "samp");
GLuint handle;
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
cgGLSetTextureParameter(p, handle);
cgSetSamplerState(p);
...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RES, RES, 0, GL_RGBA,
			GL_FLOAT, data);

//目前来看 最简单的设置管理贴图关联指令
cgGLSetManageTextureParameters(context, CG_TRUE);

CGparameter progParam = cgGetNamedParameter(prog, "sampler");
cgGLEnableTextureParameter(progParam);

 

Interfaces and Unsized Arrays接口和未知数组

//实例
interface Light
{
	float4 value();
};
struct SpotLight : Light
{
	float4 value() { return float4(1,2,3,4); }
};
float4 main(uniform Light l[]) : COLOR 
{
	float4 v = float4(0,0,0,0);
	for (int i = 0; i < l.length; ++l)
		v += l[i].value();
	return v;
}

//解决光照使用Cg
SpotLight spots[4];
technique
{
	pass 
	{
		FragmentProgram = compile arbfp1 main(spots);
	}
}

//解决光照使用Cg runtime
Light lights[];
technique 
{
	pass 
	{
		FragmentProgram = compile arbfp1 main(lights);
	}
}

//传递参数
CGtype spotType = cgGetNamedUserType(effect, "SpotLight");
CGparameter spots = cgCreateParameterArray(context, spotType, 4);
CGparameter lights = cgGetNamedEffectParameter(effect, "lights");
cgConnectParameter(spots, lights);

Evaluating Cg Programs using the Virtual Machine 用虚拟机评估Cg程序

         很多情况下使用CPU来运行Cg程序在Cg runtime虚拟机上,CPU不提供一些GPU的功能,但有时很有用,在贴图索引中。

//在虚拟机中声明
float foo = 4.f;
float4 func(float2 p : POSITION, float2 delta : PSIZE) : COLOR
{
	return foo * p.xyxy;
}

//使用CG_PROFILE_GENERIC配置文件
CGprogram tp = cgCreateProgramFromEffect(effect, CG_PROFILE_GENERIC, "func", NULL);

//cgEvaluateProgram评估程序
cgEvaluateProgram(Cgprogram prog, float *obuf, int ncomp,
					int nx, int ny, int nz);

//设置缓冲
#define RES 256
#define NCOMPS 4
float *buf = new float[NCOMPS*RES*RES];
cgEvaluateProgram(tp, buf, NCOMPS, RES, RES, 1);
// do something with buf
delete[] buf;

Annotations 注释

         使用注释能使参数信息更加明确,一个注释是一个可用数值列表,表示为<>尖括号

float3 LightDir < string UItype = "direction"; >;
technique fancyHalo <bool optional = true;> {
pass < string geometry = "character"; string destination = "texture"; > {
...
}
}

//给一个句柄,这样通过API可以拿到
CGannotation cgGetFirstTechniqueAnnotation(CGtechnique);
CGannotation cgGetFirstPassAnnotation(CGpass);
CGannotation cgGetFirstParameterAnnotation(CGparameter);
CGannotation cgGetFirstProgramAnnotation(CGprogram);
CGannotation cgGetNextAnnotation(CGannotation);

Gannotation cgGetNamedTechniqueAnnotation(CGtechnique, const char *);
CGannotation cgGetNamedPassAnnotation(CGpass, const char *);
CGannotation cgGetNamedParameterAnnotation(CGparameter, const char *);
CGannotation cgGetNamedProgramAnnotation(CGprogram, const char *);

const float *cgGetFloatAnnotationValues(CGannotation, int *nvalues);
const int *cgGetIntAnnotationValues(CGannotation, int *nvalues);
const char *cgGetStringAnnotationValue(CGannotation);
const int *cgGetBooleanAnnotationValues(CGannotation, int *nvalues);

OpenGL State 和 OpenGL SamplerState

         主要左右还是调试上,对应几张很长很长的表,具体可以详见CgUsersManual文档。。。

 

 

差不多这里把OpenGL和Direct3D的基本调用说了下,下次应该送上在公司没事做的一个骨骼动力学,比较简陋,大家将就看吧- -

 

下期预告:

         Unity骨骼动力学应用


评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页