您的位置:首页 > 运维架构

Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.

2013-12-16 02:53 441 查看
  这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用.

  在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blinn-phong光照模型,平常我们说语言只是手段,关键是怎么运用,这个用在如一些高级编程语言上,我们或多或少有不同想法,但是在着色语言上,我认为太对了.因语法都是基于C,C++来的,并且去除很多高级特性,可以说语法都是简单到了差不多了,关键在于他内置的一些传递参数的区别上,下来让我们用Cg着色器语言来完善Obj模型里的基本功能.

  我们想在.Net环境中使用Cg着色器语言,首先我们需要安装Cg Toolkit,然后使用封装了Cg Toolkit的cgnet,上面还有Cgnet.OpenTK,针对的是Cgnet在OpenTK环境里的简单封装.然后我们在.net环境引用相关DLL,就可以引用到Cg着色器语言了.主要用法和Cg中差不多,在这先说最简单的顶点差色器与片断着色器,首先是生成一个Cg着色器语言环境,然后在这环境里就可以获取最新可用的着色器配置,然后和执行代码生成对应的着色器语言执行对象,在Cg Toolkit安装中,可以看到里有很多的学习例子,上述过程每个例子基本都存在这过程,虽然是用C++写的,看几次就有印象了,额外说一句,本来我看那些例子还分DXD9,DXD10等,OpenGL就一个,还在想,这是不是太偏向DX了,那想打开一看,Opengl里的初级,高级例子比DXD9,DXD10加起来都多,不知是DX本身自带还是昨的,反正用OpenGL的足够学习如何使用Cg语法了.下面针对Cg里做一个简单的封装.

float3 expand(float3 v)
{
return (v-0.5) * 2.0;
}
void f_main(float3 position  : TEXCOORD0,
float3 normal    : TEXCOORD1,
float2 texCoord  : TEXCOORD2,
float3x3 tnb : TEXCOORD3,
//float3 lightPosition : TEXCOORD3,
//float3 eyePosition: TEXCOORD4,
out float4 color     : COLOR,
uniform float3 globalAmbient,
uniform float3 lightColor,
uniform float3 Ke,
uniform float3 Ka,
uniform float3 Kd,
uniform float3 Ks,
uniform float3 lightPosition,
uniform float3 eyePosition,
uniform sampler2D dtext,
uniform sampler2D maptext,
uniform float  shininess
)
{
float3 P = position;
//   float3 normalTex = tex2D(maptext, texCoord).xyz;
//   float3 N = expand(normalTex);//normalize(normal); //
//float3 E = mul(tnb,eyePosition);
//float3 Light = mul(tnb,lightPosition);
float3 normalTex = tex2D(maptext, texCoord).xyz;
float3 N =normalize(mul(inverse(tnb),expand(normalTex)));  //normalize(normal);
float3 E = eyePosition;
float3 Light = lightPosition;
// Compute emissive term
float3 emissive = Ke;
// Compute ambient term
float3 ambient = Ka * globalAmbient;
// Compute the diffuse term
float3 L = normalize(Light - P);
float diffuseLight = max(dot(L, N), 0);
float3 diffuse = Kd * lightColor * diffuseLight;
// Compute the specular term
float3 V = normalize(E - P);
float3 H = normalize(L + V);
float specularLight = pow(max(dot(H, N), 0), shininess);
if (diffuseLight <= 0) specularLight = 0;
float3 specular = Ks * lightColor * specularLight;
//float3 tex =lerp(tex2D(maptext, texCoord).xyz,tex2D(dtext, texCoord).xyz,1.0);
float3 tex =tex2D(dtext, texCoord).xyz;//,1.0);
float3 light = emissive + ambient + diffuse + specular;
color.xyz = light * tex;
color.w = 1;
}


片断着色器 切线空间
  上面着色器中,分别有一些注释的代码,没注释的是在模型空间运算,注释的是在切线空间运算,效果是一样的。

  其实还有第三种方法,不需要在CPU里计算切线,可以启用几何着色器,几何着色器位与顶点着色器与片断着色器之间,在这中间,可以根据顶点着色器中各变量,计算相应结果,如切线,然后传入片断着色器,因我的机器太旧,启用不起来,以后有机会再试。

  下面放出对比效果图:  



  第一张加上法线贴图,第二张没有,这二张是同一个模型,同样的精度,可以看到法线贴图的模型看起来细节要比没有的高不少。

  下面放出源代码(记的安装Cg Toolkit):引用DLL 代码 模型文件部分1 模型文件部分2 模型文件部分3 和前面一样,其中EDSF前后左右移动,鼠标右键加移动鼠标控制方向,空格上升,空格在SHIFT下降。

  因为模型文件有些大,故分开上传,大家组织好对应目录应该就可以编译过了。

  其中大家可以试试求法线或求切线,不按照求平均值的方式,而是在设置面时,对面的每个顶点分别设置时,看看效果,相关部分都有注释。对这部分有兴趣的同学不妨改改相关代码。加了法线贴图后,有时会发现在某些角度看有黑点,现在不知是代码里,相关光照与顶点的计算不在一起的原因还是别的原因,各位如果遇到过这个问题,谢谢指点。

  

  

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: