公告

联系我:我的126邮箱: billhsu。 Locations of visitors to this page
<2024年10月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

统计

  • 随笔 - 41
  • 文章 - 0
  • 评论 - 82
  • 引用 - 0

常用链接

留言簿(16)

随笔分类

随笔档案

相册

Game Dev

搜索

  •  

最新评论

阅读排行榜

评论排行榜

基于shader的骨骼蒙皮计算

     摘要: 我的古董显卡很操蛋,好端端的shader,传骨骼矩阵进去,硬是没反应。。
寻寻觅觅,找到了 NVIDIA SDK 的example,终于解决了。
难道我的显卡不支持BLENDINDICES和BLENDWEIGHT?
把BLENDINDICES和BLENDWEIGHT用TEXCOORD[n]表示才正常。。
不说废话,直接上代码。  阅读全文

posted @ 2010-04-01 22:10 Bill Hsu 阅读(1003) | 评论 (0)编辑 收藏
fstream那些事

感觉fstream有些地方设计的不太合理,不知道是bug还是那些牛X们故意这样的。

首先,fstream竟然在中文路径这种东西上不支持,网上也可以看到许多实现方法,但有的方法其实并不是太好。
我觉得这样做最简单:

setlocale(LC_ALL,"");//设置成当前语言环境
ofstream out(filename);//打开文件
setlocale(LC_CTYPE, 0);

还有,fstream的getline也有问题,对于那些\n \r 空行 什么的都没考虑,用起来会出错。
在网上看到一个函数可以完美解决这个问题:
bool readline(ifstream& infile, string& textline)
{

while(getline(infile, textline, '\n'))
{
  
int prev_pos = 0//最开始有效字符位置.
  int post_pos = 0//最后有效字符位置
  
//下面的循环语句能够用textline.find_first_not_of(filter,pos)来处理,出于效率考虑本处使用这样的算法
  while(textline[prev_pos] == ' ' || textline[prev_pos] == '\t' || textline[prev_pos] == '\r')//过滤开始空白
   prev_pos++;
  
if(textline[prev_pos] == '\0')
   
continue;//假如是空白行则再读一行进行处理.
  else
  {
       post_pos
=textline.length()-1;
      
while(textline[post_pos] == ' ' || textline[post_pos] == '\t' || textline[post_pos] == '\r')//过滤最后的空白
             {
                  post_pos
--;
             }
       textline
=textline.substr(prev_pos,post_pos+1-prev_pos);
   
return true;//成功读取一有效行
  }
  
}
return false;//读到文档的末尾
}

我根据上面这个函数 重载了一个char* 版的:

bool readline(ifstream& infile, char* textline)
{
while(infile.getline(textline,32))
{
  
int prev_pos = 0//最开始有效字符位置
  int post_pos = 0//最后有效字符位置.  
  string str=textline;
  
//下面的循环语句能够用textline.find_first_not_of(filter,pos)来处理,出于效率考虑本处使用这样的算法
  while(str[prev_pos] == ' ' || str[prev_pos] == '\t' || str[prev_pos] == '\r')//过滤开始空白
   prev_pos++;
  
if(str[prev_pos] == '\0')
   
continue;//假如是空白行则再读一行进行处理
  else
  {
         post_pos
=str.length()-1;
        
while(str[post_pos] == ' ' || str[post_pos] == '\t' || str[post_pos] == '\r')//过滤最后的空白
         {
               post_pos
--;
         }
        
string str2=str.substr(prev_pos,post_pos+1-prev_pos);
         strcpy(textline,str2.c_str());
        

   return true;//成功读取一有效行
  }
}
return false;//读到文档的末尾
}


posted @ 2010-03-27 18:37 Bill Hsu 阅读(1780) | 评论 (3)编辑 收藏
GPU水面模拟

先上个自己实现的水面模拟图:


效果比较简单,只是模拟了下水面的反射效果。折射与Fresnel系数没有考虑。

水面模拟大致需要分这么几步:
1.剪裁掉水面以下的顶点[gpu里的clipplane要注意转换到Clip Space],
将摄像机放到同原摄像机关于水面对称的位置,比如原来摄像机在(x,y,z),
此时就该把摄像机放在(x,-y,z),up向量也要设置成向下的。
再把场景渲染到Render Target的纹理上(我用的纹理大小是256*256),不知道为什么Render Target的纹理大小不能超过窗口大小,超过的话渲染会出错,知道的大大告诉我一下哈。

于是,就得到了这样一个纹理:


2.将上面得到的纹理与水面的顶点对应.
把Vertex Shader中乘过变换矩阵后的坐标传到Pixel Shader,
在PS中计算

        float2 clipspace = input.Coord.xy / input.Coord.w;
        clipspace.x=((clipspace.x * 0.5f) + 0.5f);
        clipspace.y = ((clipspace.y * -0.5f) + 0.5f);
        clipspace.x=1-clipspace.x;
既可以让水面顶点与纹理对应,然后再想办法把纹理坐标扰乱来模拟水面波动。

3.再渲染一次场景就可以了。

大家也可以参考下Azure的水面渲染源代码:
http://www.azure.com.cn/article.asp?id=186

posted @ 2010-03-23 20:59 Bill Hsu 阅读(1961) | 评论 (0)编辑 收藏
可编程管道下的剪裁平面

剪裁平面 (Clip Plane) 在图形学领域有着重要的作用,比如水面模拟中,渲染折射纹理时,我们就必须将水面以上的顶点通过剪裁平面剪裁掉。

在过去的固定渲染管道时代,剪裁平面的实现较为简单,比如在 DirectX 9 中,可以先设定剪裁平面在世界坐标系下的方程 (ax+by+cz+d=0) ,再调用 SetClipPlane(DWORD Index,CONST float * pPlane) 这个 API 函数就可以了。

 

附上例子程序:

vPosition=D3DXVECTOR3(0,0,0); // 平面上一个点
vNormal=D3DXVECTOR3(0,1,0); // 法向量
D3DXPlaneFromPointNormal( &clipplane, &vPosition, &vNormal ); // 生成剪裁平面

m_pDevice()->SetClipPlane( 0, (
float *)clipplane); 

 

然而,在现在的可编程管道 (programmable pipeline) 下,设置的剪裁平面会被在剪裁坐标系下处理,而不是在世界坐标系下。

解决这个问题的方法有:

1)  给要剪裁的顶点做标记,在Pixel Shader中把它剪裁掉。

2)  使用近斜平面裁剪(Oblique Near-Plane Clipping),即修改投影矩阵,将要剪裁的顶点放在视截体之外,从而避免了该顶点的绘制。

3)  修改平面方程,使之从世界坐标系转换到剪裁坐标系。


上述方法中,第一种和第二种效率并不高:在
Pixel Shader中剪裁没有减少任何不必要的顶点处理,而计算近斜平面裁剪矩阵较为繁琐。所以,方法三是最佳选择。

 要将一个平面从世界坐标系转换到剪裁坐标系,必须求出这个变换矩阵。

设平面方程ax+by+cz+d=0,用一个4维向量来n表示(a,b,c,d),设平面上有个点p:(x,y,z,1)。根据平面方程的定义,有:


nTp = ax + by + cz + d = 0

设矩阵R可以让点P从世界坐标系转换到剪裁坐标系,矩阵Q可以让平面n实现同样的变换。那么,有:

p'= Rp
n'= Qn

其中p'n'分别是转换后的点与平面。


n'Tp'= 0
(Qn)T (Rp) = 0
nTQTRp = 0


如果:QTR = I

那么:

nTQTRp = nTIp = nTp = 0

于是:

QT = R-1
Q
= (R-1)T

DirectX 3D中,将一个点从世界坐标系转换到剪裁坐标系,所用的矩阵为观察矩阵与投影矩阵的乘积,即:

D3DXMATRIX  TranMatrix = matView*matProj;

(TranMatrix为所求的变换矩阵,matViewmatProj分别为观察矩阵与投影矩阵)

 

附上在D3D中变换的完整代码:

D3DXPLANE tempPlane = clipplane;
D3DXPlaneNormalize(&tempPlane, &tempPlane);

D3DXMATRIX  TranMatrix = matView*matProj;
D3DXMatrixInverse(&TranMatrix, NULL, &TranMatrix);
D3DXMatrixTranspose(&TranMatrix, &TranMatrix);
D3DXPlaneTransform(&tempPlane, &tempPlane, &TranMatrix);

参考资料:

1.Back Face Culling Notes ,Jordan Smith (University of California, Berkeley)

http://www.cs.berkeley.edu/~ug/slide/pipeline/assignments/backfacecull.shtml 

2.GameDev Forum

http://www.gamedev.net/community/forums/topic.asp?topic_id=402381

3.Oblique Near-Plane Clipping with Orthographic Camera ,Aras

http://aras-p.info/texts/obliqueortho.html

posted @ 2010-01-20 22:00 Bill Hsu 阅读(1986) | 评论 (2)编辑 收藏
矩阵求逆代码

     摘要: 感觉线性代数作业里一直少不了矩阵求逆,

写个带输出算逆矩阵的步骤的矩阵求逆程序,希望给即将或正在学线代的同学一点方便。  阅读全文

posted @ 2009-12-11 22:23 Bill Hsu 阅读(6725) | 评论 (8)编辑 收藏
仅列出标题
共9页: 1 2 3 4 5 6 7 8 9