Thinking in Shader(6)

Thinking in Shader(6)

分类: Cg 图形学 408人阅读 评论(0) 收藏 举报

开发环境

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开始

    考虑下面特效:

  1. //这个特效定义了一个简单参数,type只是为了程序方便调用,初始值是{1,1,1} 有一个限定范围   
  2. float3 DiffuseColor<string type = "color";  
  3.                     float3 minValue = float3(0,0,0);  
  4.                     float3 maxValue = float3(10,10,10);> = { 1, 1, 1 };  
  5.   
  6. //这个特效还定义了一个方法,其中含有一个简单的渲染通道,这个通道设置适当的OpenGL状态来执行每个顶点光使用固定管线材质模型。注意LightDiffuse可以看出受散色光影响   
  7. technique FixedFunctionLighting   
  8. {  
  9.     pass   
  10.     {  
  11.         LightingEnable = true;  
  12.         LightEnable[0] = true;  
  13.         LightPosition[0] = float4(-10, 10, 10, 1);  
  14.         LightAmbient[0] = float4(.1,.1,.1,.1);  
  15.         LightDiffuse[0] = (float4(2*DiffuseColor, 1));  
  16.         LightSpecular[0] = float4(1,1,1,1);  
  17.         MaterialShininess = 10.f;  
  18.         MaterialAmbient = float4(1,1,1,1);  
  19.         MaterialDiffuse = float4(.5, .5, .5, 1);  
  20.         MaterialSpecular = float4(.5, .5, .5, 1);  
  21.     }  
  22. }  
//这个特效定义了一个简单参数,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);
	}
}

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

  1. CGcontext context = cgCreateContext(); //创建关联   
  2. cgGLRegisterStates(context); //创建OpenGL状态管理   
  3. CGeffect effect = cgCreateEffectFromFile(context, "simple.cgfx", NULL);  
  4. if (!effect)   
  5. {  
  6.     fprintf(stderr, "Unable to create effect!\n");  
  7.     const char *listing = cgGetLastListing(context);  
  8.     if (listing)  
  9.     fprintf(stderr, "%s\n", listing);  
  10.     exit(1);  
  11. }  
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 技术验证

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

 

  1. CGtechnique technique = cgGetFirstTechnique(effect);  
  2. while (technique)  
  3. {  
  4.     if (cgValidateTechnique(technique) == CG_FALSE)  
  5.     fprintf(stderr, "Technique %s did not validate. Skipping.\n",  
  6.             cgGetTechniqueName(technique));  
  7.     technique = cgGetNextTechnique(technique);  
  8. }  
  9.   
  10. // cgIsTechniqueValidated() 一般用来检查  
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中允许一个通道状态定义在技术中:

 

  1. CGpass pass = cgGetFirstPass(technique);  
  2. while (pass)  
  3. {  
  4.     cgSetPassState(pass);  
  5.     drawGeom();  
  6.     cgResetPassState(pass);  
  7.     pass = cgGetNextPass(pass);  
  8. }  
CGpass pass = cgGetFirstPass(technique);
while (pass)
{
	cgSetPassState(pass);
	drawGeom();
	cgResetPassState(pass);
	pass = cgGetNextPass(pass);
}

 

Effect Parameters 特效参数

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

  1. CGparameter c = cgGetNamedEffectParameter(effect, "Color");  
  2. cgSetParameter3fv(c, Color);  
  3. CGparameter mvp = cgGetNamedEffectParameter(effect, "ModelViewProjection");  
  4. cgGLSetStateMatrixParameter(mvp, CG_GL_MODELVIEW_PROJECTION_MATRIX,  
  5.                             CG_GL_MATRIX_IDENTITY);  
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

  1. float4 main(uniform float foo, float4 uv : TEXCOORD0) : COLOR  
  2. {  
  3.     return (foo > 0) ? uv : 2 * uv;  
  4. }  
  5.   
  6. technique SimpleFrag  
  7. {  
  8.     pass   
  9.     {  
  10.         VertexProgram = NULL;  
  11.         FragmentProgram = compile arbfp1 main(-2.f);  
  12.     }  
  13. }  
  14. technique AsmFrag   
  15. {  
  16.     pass   
  17.     {  
  18.         FragmentProgram = asm   
  19.         {  
  20.             !!FP1.0  
  21.             TEX o[COLR], {0}.x, TEX6, 2D;  
  22.             END  
  23.         };  
  24.     }  
  25. }  
  26.   
  27. //另一个例子   
  28. float4 main(uniform float foo, float4 uv : TEXCOORD0) : COLOR  
  29. {  
  30.     return (foo > 0) ? uv : 2 * uv;  
  31. }  
  32. float bar;  
  33. technique NewSimpleFrag  
  34. {  
  35.     pass   
  36.     {  
  37.         VertexProgram = NULL;  
  38.         FragmentProgram = compile arbfp1 main(2 * bar);// 2 * bar链接的是main中的参数   
  39.     }  
  40. }  
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使定义状态关联到贴图在特效文件中成为可能,例如:

  1. sampler2D samp = sampler_state {  
  2.                 generateMipMap = true;  
  3.                 minFilter = LinearMipMapLinear;  
  4.                 magFilter = Linear;};  
  5.   
  6. float4 texsimple(uniform sampler2D sampler,  
  7.             float2 uv : TEXCOORD0) : COLOR {  
  8. return tex2D(sampler, uv);  
  9. }  
  10. technique TextureSimple {  
  11.     pass  
  12.     {  
  13.         FragmentProgram = compile arbfp1 texsimple(samp);  
  14.     }  
  15. }  
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()例如:

  1. CGparameter p = cgGetNamedEffectParameter(effect, "samp");  
  2. GLuint handle;  
  3. glGenTextures(1, &handle);  
  4. glBindTexture(GL_TEXTURE_2D, handle);  
  5. cgGLSetTextureParameter(p, handle);  
  6. cgSetSamplerState(p);  
  7. ...  
  8. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, RES, RES, 0, GL_RGBA,  
  9.             GL_FLOAT, data);  
  10.   
  11. //目前来看 最简单的设置管理贴图关联指令   
  12. cgGLSetManageTextureParameters(context, CG_TRUE);  
  13.   
  14. CGparameter progParam = cgGetNamedParameter(prog, "sampler");  
  15. cgGLEnableTextureParameter(progParam);  
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接口和未知数组

  1. //实例   
  2. interface Light  
  3. {  
  4.     float4 value();  
  5. };  
  6. struct SpotLight : Light  
  7. {  
  8.     float4 value() { return float4(1,2,3,4); }  
  9. };  
  10. float4 main(uniform Light l[]) : COLOR   
  11. {  
  12.     float4 v = float4(0,0,0,0);  
  13.     for (int i = 0; i < l.length; ++l)  
  14.         v += l[i].value();  
  15.     return v;  
  16. }  
  17.   
  18. //解决光照使用Cg   
  19. SpotLight spots[4];  
  20. technique  
  21. {  
  22.     pass   
  23.     {  
  24.         FragmentProgram = compile arbfp1 main(spots);  
  25.     }  
  26. }  
  27.   
  28. //解决光照使用Cg runtime   
  29. Light lights[];  
  30. technique   
  31. {  
  32.     pass   
  33.     {  
  34.         FragmentProgram = compile arbfp1 main(lights);  
  35.     }  
  36. }  
  37.   
  38. //传递参数   
  39. CGtype spotType = cgGetNamedUserType(effect, "SpotLight");  
  40. CGparameter spots = cgCreateParameterArray(context, spotType, 4);  
  41. CGparameter lights = cgGetNamedEffectParameter(effect, "lights");  
  42. cgConnectParameter(spots, lights);  
//实例
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的功能,但有时很有用,在贴图索引中。

  1. //在虚拟机中声明   
  2. float foo = 4.f;  
  3. float4 func(float2 p : POSITION, float2 delta : PSIZE) : COLOR  
  4. {  
  5.     return foo * p.xyxy;  
  6. }  
  7.   
  8. //使用CG_PROFILE_GENERIC配置文件   
  9. CGprogram tp = cgCreateProgramFromEffect(effect, CG_PROFILE_GENERIC, "func", NULL);  
  10.   
  11. //cgEvaluateProgram评估程序   
  12. cgEvaluateProgram(Cgprogram prog, float *obuf, int ncomp,  
  13.                     int nx, int ny, int nz);  
  14.   
  15. //设置缓冲   
  16. #define RES 256   
  17. #define NCOMPS 4   
  18. float *buf = new float[NCOMPS*RES*RES];  
  19. cgEvaluateProgram(tp, buf, NCOMPS, RES, RES, 1);  
  20. // do something with buf   
  21. delete[] buf;  
//在虚拟机中声明
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 注释

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

  1. float3 LightDir < string UItype = "direction"; >;  
  2. technique fancyHalo <bool optional = true;> {  
  3. pass < string geometry = "character"; string destination = "texture"; > {  
  4. ...  
  5. }  
  6. }  
  7.   
  8. //给一个句柄,这样通过API可以拿到   
  9. CGannotation cgGetFirstTechniqueAnnotation(CGtechnique);  
  10. CGannotation cgGetFirstPassAnnotation(CGpass);  
  11. CGannotation cgGetFirstParameterAnnotation(CGparameter);  
  12. CGannotation cgGetFirstProgramAnnotation(CGprogram);  
  13. CGannotation cgGetNextAnnotation(CGannotation);  
  14.   
  15. Gannotation cgGetNamedTechniqueAnnotation(CGtechnique, const char *);  
  16. CGannotation cgGetNamedPassAnnotation(CGpass, const char *);  
  17. CGannotation cgGetNamedParameterAnnotation(CGparameter, const char *);  
  18. CGannotation cgGetNamedProgramAnnotation(CGprogram, const char *);  
  19.   
  20. const float *cgGetFloatAnnotationValues(CGannotation, int *nvalues);  
  21. const int *cgGetIntAnnotationValues(CGannotation, int *nvalues);  
  22. const char *cgGetStringAnnotationValue(CGannotation);  
  23. const int *cgGetBooleanAnnotationValues(CGannotation, int *nvalues);  
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骨骼动力学应用

posted @ 2013-03-23 18:28  小薇林  阅读(285)  评论(0编辑  收藏  举报