遗忘河

一个人的烦恼是因为记性太好.

首页 新随笔 联系 管理
  11 Posts :: 4 Stories :: 13 Comments :: 0 Trackbacks

2008年10月13日 #

  


some gameplay screens.

马桶刷:



被炸弹炸飞:


被狗子咬住:

被拳套冲倒:

弹弓:

烟雾弹:





posted @ 2008-10-13 19:55 大悟终空 阅读(294) | 评论 (0)编辑 收藏

2008年9月11日 #

道具商城:

弹弓




wait room.
posted @ 2008-09-11 20:46 大悟终空 阅读(156) | 评论 (1)编辑 收藏

2007年8月20日 #

当实现分割地形的时候,最好的情况下是能够给每一个分块单独的地表贴图,而不是多个纹理即时混合.事实上,在非编辑状态下,多纹理混合都有性能和硬件支持的问题.比方说某个分区用到了9张纹理,草地,雪地,岩石,泥浆等等. 如果在一个最大支持8纹理的硬件上,要想全部渲染,必须得来2次了, 当然,你可以经验性地控制住每个分区的纹理数目,但是同时也降低了地形的表现能力. 因此,我们往往会将多个纹理混合到一张纹理中,在渲染中只渲染这种混合好的纹理.

目前能找到的关于地形纹理构建的文章都是基于高度来决定最终纹理的数据,但是这种方式有天然的缺陷,对于大多数的地形而言,高度差并不大,还不足够形成令人信服的垂直气候. 而且,对于一条自然道路,更是和地形高度毫无关联了.因此,我们需要一种更灵活的构建方式.

在本人实现中,采取一种通用的Alpha Map 方式.

newColor = oldColor*(1-mask) + srcColor*mask;
逐层地将新的层按照alpha 混合到旧层中. 以下是岩石,草地,沙子按alpha混合的最终效果图:



具体实现见代码:
下载代码和可执行程序

需要注意的是,这种方式涉及到对位图的缩放采样. 在上面的代码实现中,我使用最简单的效果也最差的point 采样方式,这种方式有时也被叫做nearest~~ 也就是说,质量是最差的. 当然,你也可以采取线性,双线,三线,各向异性等方式. google it.

posted @ 2007-08-20 13:50 大悟终空 阅读(273) | 评论 (0)编辑 收藏
































         关于这个根本就不是什么新鲜事情了,但是大多数都是基于几何体的,最后常常导致一个问题:当镜头处于水面的时候,且水下已经用体积雾处理,
这个时候,水面网格常常会表现得着色(雾颜色)不均匀,有难看得锯齿.
       GPG 上有一篇关于程序纹理的文章,也是关于水模拟的. 这里引作参考,实现了一种基于纹理空间的水模拟.
      之所以要基于纹理空间,是因为我还需要在上面加入推进式波浪,参见Crysis GDC 上放出的视频. 目前要实现那样的效果,
我想到的只有在纹理空间比较好解决.
posted @ 2007-08-20 09:40 大悟终空 阅读(436) | 评论 (1)编辑 收藏

2007年8月15日 #

inline bool LMatrix44::GetInverse(LMatrix44& matInvDest) const
{
    
// 事实上,我们绝大多数的逆操作都能成功. 
    
// 注意到我们GetDeterm() 操作中计算了一部分余子式,如果逆操作成功,那么GetDeterm就浪费了.
    
// 因此我们选用一种对以可逆为前提的优化.
    assert(&matInvDest != this);
    
float tmp[12];
    tmp[
0= m33 * m44; tmp[1= m43 * m34; tmp[2= m23 * m44; tmp[3= m24 * m43;
    tmp[
4= m23 * m34; tmp[5= m33 * m24; tmp[6= m13 * m44; tmp[7= m43 * m14;
    tmp[
8= m13 * m34; tmp[9= m33 * m14; tmp[10]= m13 * m24; tmp[11]= m23 * m14;    // # 12*

    
// 计算余子式 (倒置伴随矩阵)
    matInvDest.m11 = m22*(tmp[0- tmp[1]) + m32*(tmp[3- tmp[2]) + m42*(tmp[4- tmp[5]);  // 3* 3- 2+
    matInvDest.m12 = m12*(tmp[1- tmp[0]) + m32*(tmp[6- tmp[7]) + m42*(tmp[9- tmp[8]);
    matInvDest.m13 
= m12*(tmp[2- tmp[3]) + m22*(tmp[7- tmp[6]) + m42*(tmp[10- tmp[11]);
    matInvDest.m14 
= m12*(tmp[5- tmp[4]) + m22*(tmp[8- tmp[9]) + m32*(tmp[11- tmp[10]);
    matInvDest.m21 
= m21*(tmp[1- tmp[0]) + m31*(tmp[2- tmp[3]) + m41*(tmp[5- tmp[4]);
    matInvDest.m22 
= m11*(tmp[0- tmp[1]) + m31*(tmp[7- tmp[6]) + m41*(tmp[8- tmp[9]);
    matInvDest.m23 
= m11*(tmp[3- tmp[2]) + m21*(tmp[6- tmp[7]) + m41*(tmp[11- tmp[10]);
    matInvDest.m24 
= m11*(tmp[4- tmp[5]) + m21*(tmp[9- tmp[8]) + m31*(tmp[10- tmp[11]);
                                                                                        
//36* 24- 16+
    tmp[0= m31 * m42; tmp[1= m41 * m32; tmp[2= m21 * m42; tmp[3= m41 * m22;
    tmp[
4= m21 * m32; tmp[5= m31 * m22; tmp[6= m11 * m42; tmp[7= m41 * m12;
    tmp[
8= m11 * m32; tmp[9= m31 * m12; tmp[10]= m11 * m22; tmp[11]= m21 * m12;
    
    matInvDest.m31 
= m24*(tmp[0- tmp[1]) + m34*(tmp[3- tmp[2]) + m44*(tmp[4- tmp[5]);
    matInvDest.m32 
= m14*(tmp[1- tmp[0]) + m34*(tmp[6- tmp[7]) + m44*(tmp[9- tmp[8]);
    matInvDest.m33 
= m14*(tmp[2- tmp[3]) + m23*(tmp[7- tmp[6]) + m44*(tmp[10- tmp[11]);
    matInvDest.m34 
= m14*(tmp[5- tmp[4]) + m24*(tmp[8- tmp[9]) + m34*(tmp[11- tmp[10]);
    matInvDest.m41 
= m23*(tmp[1- tmp[0]) + m33*(tmp[2- tmp[3]) + m43*(tmp[5- tmp[4]);
    matInvDest.m42 
= m33*(tmp[7- tmp[6]) + m13*(tmp[0- tmp[1]) + m43*(tmp[8- tmp[9]);
    matInvDest.m43 
= m23*(tmp[6- tmp[7]) + m13*(tmp[3- tmp[2]) + m43*(tmp[11- tmp[10]);
    matInvDest.m44 
= m13*(tmp[4- tmp[5]) + m33*(tmp[10- tmp[11]) + m23*(tmp[9- tmp[8]);
                                                                                        
// 72* 48- 32+
    float fDet=(m11*matInvDest.m11 + m21*matInvDest.m12 + m31*matInvDest.m13 + m41*matInvDest.m14);        // 4* 3+
    if (LAbs(fDet) < 0.000001f)
    
{
        matInvDest.SetIdentity();
        
return false;
    }


    fDet 
= 1.0f/fDet;
    matInvDest.m11
*= fDet;matInvDest.m12*= fDet;matInvDest.m13*= fDet;matInvDest.m14*= fDet;
    matInvDest.m21
*= fDet;matInvDest.m22*= fDet;matInvDest.m23*= fDet;matInvDest.m24*= fDet;
    matInvDest.m31
*= fDet;matInvDest.m32*= fDet;matInvDest.m33*= fDet;matInvDest.m34*= fDet;
    matInvDest.m41
*= fDet;matInvDest.m42*= fDet;matInvDest.m43*= fDet;matInvDest.m44*= fDet;//16*
    return true;
}

以上是优化实现,以12个浮点的零时变量消耗,通过计算倒置伴随矩阵,最终获得逆矩阵. 在实现中,以矩阵可逆为前提,避免了大部分的cofactor 计算.
比常规通过求模,然后求逆要少60次乘法.

缺点: 没有形成很好的16字节排列,依旧不便于SSE/SSE2指令优化.
posted @ 2007-08-15 16:20 大悟终空 阅读(779) | 评论 (0)编辑 收藏

2007年7月16日 #

      1. 使用 point_sprit 代替Quad 渲染粒子.
      2.采用一个双向链表组织的缓存管理粒子的生命期.
      3.定义一个点阵算法来提高烟花爆炸行为定义的灵活度. 点阵可以从Photoshop 中导出.
      4.定义一个层次化的结构来组织每个烟花爆破单元.这样可以让一个纯粹的烟花表现变得更加丰富,
         这个思路来源自unreal 3 的粒子系统. 但是这样做,导致编辑变得非常困难,最后只好通过脚本来定义了.
 






posted @ 2007-07-16 16:24 大悟终空 阅读(228) | 评论 (1)编辑 收藏

2007年4月28日 #

         花了近一周的空余时间,对shore rendering 进行了优化. 现在的效果:

  在岸边坡度较高的地方:


修改了寻找海岸边沿的算法. 采取一种类似A* 寻路的递归检测算法. 能够快速勾勒水岸线.
在描边的过程中,需要记录当前点周围6个三角形与水面的相交情况.这个在以后的拉伸过程中会用到.

#2
假定海浪的动能为 W, 那么海浪能上升的高度是一个常数  h = F(W/g ). .
将水岸线沿Y(垂直水面的方向)上升 h 高度.

遍历所有封闭的水岸线.
 遍历每一个水岸线的点.
  计算每个点的拉伸方向. 这里要特别注意的是,如果相邻2个点距离过近,拉伸法线出现相交的几率很大.最后导致海浪起点重叠.会出现
难看的褶皱. 所以,我们需要在计算拉伸法线前,去判断这个情况,然后抛弃出现相交的点.
    
 沿着拉伸法线extrude 出海浪的起点.

#3
 接下来,需要找到海浪的终点,这其实是一步与地形求交的过程, 只是注意下求交的时候只遍历当前点附近的 3*3个点附近的三角形就够了,然后选择一个
交点最近的.作为终点.

对Far Cry , fort 地形 1024*1024 个顶点run-time 构建 shore- strip 的鸟瞰图, 这里镜头拉得有些远, 地形得细节等级都处于最低等级.
posted @ 2007-04-28 11:16 大悟终空 阅读(224) | 评论 (1)编辑 收藏

2007年4月24日 #


void CheckFramebufferStatus()
{
    GLenum status;
    status 
= (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    
switch(status) {
        
case GL_FRAMEBUFFER_COMPLETE_EXT:
            
break;
        
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
            printf(
"Unsupported framebuffer format\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
            printf(
"Framebuffer incomplete, missing attachment\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
            printf(
"Framebuffer incomplete, duplicate attachment\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
            printf(
"Framebuffer incomplete, attached images must have same dimensions\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
            printf(
"Framebuffer incomplete, attached images must have same format\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
            printf(
"Framebuffer incomplete, missing draw buffer\n");
            
break;
        
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
            printf(
"Framebuffer incomplete, missing read buffer\n");
            
break;
        
default:
             printf(
"unknown error !!!!\n");
           
return;
    }

}


void CreateDepthSurface()
{
// 在N卡上,必须创建 color buffer 的镜像.
// 否则,depth buffer 是无效的.
// 如果不想向color buffer 写入数据.
// 可以调用 glDrawBuffer(GL_NONE) glReadBuffer(GL_NONE) 来屏蔽.
// 而在A卡上, 是可以创建独立的 Depth buffer 的..
glGenTextures(1&ctex);
    
   
// glGenRenderbuffersEXT(1, &depth_rb);

   
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);    

    
// init texture
  
//  glBindTexture(texTarget, tex);
  
//  glTexImage2D(texTarget, 0, texInternalFormat, texWidth, texHeight, 0, 
  
//               GL_RGBA, GL_FLOAT, NULL);
    //////////////////////////////////////////////////////////////////////////
    

    glBindTexture(GL_TEXTURE_2D, ctex);
    glTexImage2D(GL_TEXTURE_2D, 
0, GL_RGB8, texWidth, texWidth, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    
    glGenTextures(
1&dtex);
    glBindTexture(GL_TEXTURE_2D, dtex);
    glTexImage2D(GL_TEXTURE_2D, 
0, GL_DEPTH_COMPONENT24, texWidth, texWidth, 0, GL_DEPTH_COMPONENT, GL_INT, NULL);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


 glGenFramebuffersEXT(
1&fb);
     glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);  
     CheckFramebufferStatus();

     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 
         GL_TEXTURE_2D, ctex, 
0);

     CheckFramebufferStatus();
     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
         GL_DEPTH_ATTACHMENT_EXT,
         GL_TEXTURE_2D, dtex, 
0);

   CheckFramebufferStatus();
glDrawBuffer(GL_NONE);
    glReadBuffer(GL_NONE);
 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 
0);

}



我很奇怪为什么SGI , OPENGL.ORG 上的关于fbo扩展的文档都没有说明这一点. 连NV自己的也没有. 或许是那么长的一篇文章,我没有看仔细.
郁闷,,,郁闷,,,,,郁闷.
posted @ 2007-04-24 15:35 大悟终空 阅读(840) | 评论 (0)编辑 收藏

2007年4月21日 #

进行了高斯模糊,并且故意强曝光. 如梦般的感觉.
posted @ 2007-04-21 20:29 大悟终空 阅读(250) | 评论 (0)编辑 收藏

2007年4月4日 #

下午开始接手山海繁体版的工作,一堆的BUG和需求...但愿是个特例,今天在繁体WINXP上忙了一下,感觉整个显示屏像蒙了一层纱布,很影响视觉,字体的轮廓丑陋得让我想起linux. 像山海那样从TureType字体构建位图字体的方式,对我们非常清晰的中文字体也会带来模糊,也怪不得台湾那边的玩家抱怨了.

inline bool GetBit(BYTE* pSrc, int nBit)
{
    return (pSrc[nBit
/8])&(1 <<(7 -(nBit%8)));
}

//=======================================================
if(GetGlyphOutlineW(
                    hFontDC,            
// 设备环境
                    wChar,                
// 要获取轮廓的字符
                    GGO_BITMAP,        
// 要获取的数据类型.GGO_GRAY8_BITMAP
                    
&metrics,                // 字符的信息
                    sizeof(scratchPad),        
// 要返回数据内存的大小
                    scratchPad,                
// 接收返回数据的内存地址
                    
&matrix) != GDI_ERROR)    // 字符渲染时候的变换矩阵
{
                    glyphCount
++;
                    UINT rowStride 
= (metrics.gmBlackBoxX + 3& ~3// DWORD aligned
                    UINT size 
= rowStride * metrics.gmBlackBoxY;
                    rowStride 
= rowStride/8 +((rowStride%8)&&8);
                    rowStride 
= (rowStride+3& ~3;

for(UINT y = 0int(y) < metrics.gmBlackBoxY; y++)
        {
            UINT x;
            
for(x = 0; x < metrics.gmBlackBoxX; x++)
            {
            // 强制去掉字体边缘的阴影.
                c.bitmapData[y 
* c.width + x] = GetBit(src+* stride, x)? 255 : 0;
            }
        }
}
//=============================================================

以上方式的获取就会让轮廓清晰多了.

紧接着来的是关于繁体注音输入法的问题, L D 注音的(我不知道怎么去说繁体注音)的第三个字在IME组字的时候 WPARAM 传来的是 63 ('?') . 百思不得其解.
在WIN32 记事本上却是显示的非常正常.还有"锶"等也是如此...新建一个MFC对话框程序,上面的CEdit控件输入这些字符的时候也是显示的 ? ......
更加迷惑....查遍了论坛,也没有找到解决办法. 正想离开公司的时候突然想到, 记事本用的是RichEdit,而RichEdit 是基于Unicode 字符集的, Edit 则是多字节字符集. 是这个问题麽? 修改工程编译选项,选择字符集为UNICODE.结果,CEdit 果然能正确显示繁体"锶"了,那么接下来的事情就很明了啦.....我又有得忙了.....
回家的路上我正想游到对岸,统一了台湾,统一使用简体中文.
posted @ 2007-04-04 22:13 大悟终空 阅读(187) | 评论 (0)编辑 收藏

仅列出标题  下一页