炼数成金 门户 CUDA 查看内容

在游戏设计中充分利用可编程的GPU

2015-9-9 14:23| 发布者: 炼数成金_小数| 查看: 987| 评论: 0|原作者: effulgent|来自: it168

摘要: 充分意识到GPU海量的吞吐和强悍的浮点计算能力,将极高提高程序性能,也能让充分发挥显卡的价值,GPU作为电脑上2个可编程的高性能芯片之一,长期以来都没得到普通程序员应有的重视,主要因为其编程麻烦,资料工具欠 ...

工具 计算机 编程 GPU 芯片

充分意识到GPU海量的吞吐和强悍的浮点计算能力,将极高提高程序性能,也能让充分发挥显卡的价值,GPU作为电脑上2个可编程的高性能芯片之一,长期以来都没得到普通程序员应有的重视,主要因为其编程麻烦,资料工具欠缺。这里我将叙述我的游戏编程中尽可能多的使用GPU做事的一些经验,主要是想表达一种合理使用计算机资源的一种思想吧。

我对DX10和SM3.0都不熟悉,所以更有用的GS数据输出,甚至于更强大的CUDA都不在本文叙述范围之内,这里更多讨论SM2.0和DX9,相信大部分朋友都应该具备实践的条件。专业的GPGPU都利用科学计算作为实例,我觉得不妥,还是简单点好,在这里我说说如何将公告板的所有几何计算都放到GPU里去。

公告板对于图形程序员都再熟悉不过,就是让几何体(通常是四边形)总是面对相机,其实就是一个旋转过程,最简单的就是雪花,草丛等等,在这里我要讲一个稍微复杂点的例子,比如魔兽中的锁链魔法,或者天空中的分形闪电,其实这些都是链接在2个点之间的一条或多条几何体面片,一段可能是一个四边形,也可能是多个四边形,如下图:
在游戏设计中充分利用可编程的GPU
如果一段不是一个面片就用不着旋转了,所以我们主要说上面那种情况。法师对一个或多个目标发送带链接的魔法,其实就是在目标之间生成链接的面片,并且面片上进行相关的纹理动画,当目标之间方位不断改变时还要进行几何变换等操作。原理很简单,就是让所有面片都能面对观众,这样在特定方向观看时才不会有严重失真的表现,我们主要看如何把所有计算都塞到GPU中去。
在游戏设计中充分利用可编程的GPU

首先我们必须在CPU中生成所有需要的顶点,因为没有GS的GPU不能生成顶点。比如我们要从A点生成一条几何条带到B点,我们生成8个中间点,共10个点。通过相邻的2个点,我们可以求出2个点的中间点,Pmid= (Pi + Pi+1) / 2,我们为第一个段生成4个顶点,后续的段因为共用前一个段的后2个顶点,所以后面的每段只需要2个顶点,每个顶点的几何坐标设置为本段的中间点坐标Pmid,这样每个段的顶点都是窝在一起的,我们需要在VS里将其扩展成四边形,但我们需要信息,当前顶点该如何扩展,如下图:
在游戏设计中充分利用可编程的GPU

我们可以用UV坐标做标识,UV坐标y分量为0的都向后扩展,y分量!=0的都向前扩展,而x==0的向左,x==1的向右。因为一般的锁链上的纹理都是U向CLAMP,V向WRAP的,所以UV正好给我们提供了如何扩展几何体的信息,但扩展多少呢?我们需要再利用一个数据流送入信息,我们就利用TEXCOORD1吧,X方向和Y方向扩展数量正好用2个FLOAT送入。之后是旋转,其实就是扩展,我们需要2个轴,一个是X方向的,一个是Y方向的,Y方向的其实就是LeashY = Pi+1 - Pi,至于原理就是公告板旋转,只是约束轴不同,而X方向LeashX = Cross( LeashY, (CameraPos - VertexPos) ),所以我们还需要一个流送入LeashY,而LeashX可以通过顶点原始坐标和LeashY在VS中计算出来,不用在CPU里做。所以要在CPU里做的就是生成顶点和UV,而这2个计算量非常小,顶点真实坐标的计算,公告板的旋转等都放到VS里来了。现在我们看看VS大概是什么样子。
  float3 g_CameraPos;

  float4x4 g_WorldMatrix;

  float4x4 g_ViewProjMatrix;

  struct VS_INPUT

  {

  float3 VertexPos : POSITION0;

  float2 UV0    : TEXCOORD0;

  float3 LeashY  : TEXCOORD1;

  float2 Size    : TEXCOORD2;

  };

  struct VS_OUTPUT

  {

  float3 ProjPos : POSITION0;

  float2 UV0  : TEXCOORD0;

  };

  VS_OUTPUT VS_Main( VS_INPUT In )

  {

  VS_OUTPUT Out;

  float4 VertexWorldPos = mul(float4(In.VertexPos, 1.f), g_WorldMatrix);

  float3x3 WorldRotateMatrix;

  WorldRotateMatrix[0] = float3(g_WorldMatrix[0][0], g_WorldMatrix[0][1], g_WorldMatrix[0][2]);

  WorldRotateMatrix[1] = float3(g_WorldMatrix[1][0], g_WorldMatrix[1][1], g_WorldMatrix[1][2]);

  WorldRotateMatrix[2] = float3(g_WorldMatrix[2][0], g_WorldMatrix[2][1], g_WorldMatrix[2][2]);

  //注意旋转轴需要被旋转否则不对

  float3 RotatedLeashY = normalize(mul(In.LeashY, WorldRotateMatrix ));

  float3 LeashX = normalize(cross(g_CameraPos-VertexWorldPos, RotatedLeashY));

  //开始旋转了

  float3 DealedPos = float3(0,0,0);

  float3 ExtendY = In.Size.y*RotatedLeashY;

  float3 ExtendX = In.Size.x*LeashX;

  if(In.UV0.y == 0 )

  {

  if(In.UV0.x == 0 )

  {

  DealedPos = -ExtendY-ExtendX;

  } else {

  DealedPos = -ExtendY+ExtendX;

  }

  } else {

  if(In.UV0.x == 0 )

  {

  DealedPos = ExtendY-ExtendX;

  } else {

  DealedPos = ExtendY+ExtendX;

  }

  }

  Out.ProjPos = mul(float4(VertexWorldPos.xyz+DealedPos, 1.0f), g_ViewProjMatrix);

  Out.UV0 = In.UV0;

  }
怎么样?CPU既不用计算顶点坐标,又不用旋转公告板,做一些改进后,甚至可以完成锁链的拉伸变形,完全不用CPU管。在可编程的GPU出现以前,很多计算工作是在CPU中完成,现在有了SM2.0和SM3.0都可以移植到GPU中来,大家多多发现吧。

鲜花

握手

雷人

路过

鸡蛋

最新评论

热门频道

  • 大数据
  • 商业智能
  • 量化投资
  • 科学探索
  • 创业

即将开课

热门文章

     

    GMT+8, 2020-1-25 00:46 , Processed in 0.136316 second(s), 23 queries .