博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于游戏中的材质系统
阅读量:6862 次
发布时间:2019-06-26

本文共 2080 字,大约阅读时间需要 6 分钟。

材质,这个词有各行各业都有自己的解释。

美工把物体贴图和物体颜色,高光等统称为材质。D3D和OPENGL这样的图形接口则把物体表面贴图单独叫做纹理,而把漫反射,高光等叫做材质。

而在游戏引擎或图形引擎中提到的材质,则与此不同。 引擎中提到的材质不仅上面的的内容。 引擎中所谓的材质,是指物体在渲染时一系列的状态控制。 如,ALPHA混合开关以及ALPHA混合因子、纹理过虑方式,纹理通道状态、纹理矩阵、裁剪模式等,在D3D中,就是SetRenderState,SetTextureStageState,SetSamplerStateState等所控制的。在OPENGL中,则大多数由glEnable所控制。

我们所提到的材质系统,则是以此为基础展开的。 上面提到的这些因子,组成了我们的材质。 也是我们在渲染一个物体的时候,提交到设备的状态控制值。 一个物体的一次渲染,我们称作一个PASS。于是我们顺其自然地将这个渲染时的材质控制的最小单位命名为Pass,则:

struct TextureState

{

    void* Texture;

    int ColorOp;

    int ColorAgr1;

    int ColorAgr2;

    int AlphaOp;

    int AlphaAgr1;

    int AlphaAgr2;

.....//更多内容

};

class CPass

{

   CColor mAmbient;

   CColor mDiffuse;

   ....更多内容

    bool mAlphaEnable;

    int mScrBlend;

    int mDstBlend;

    int mCullMode;

   TextureState[4] mTextureStates;

  ...更多内容

};

当我们渲染一个物体的时候,只需要将这个类里面的状态应用到设备,即可完成对物体的绘制。

材质系统的基本内容就是这些,这也是最容易做到的事情。

但是,我们都知道,像D3D或OPENGL这样的图形接口每设置一次GPU状态的时候,都会有一定的开销(通过查看相关文档可以看到某些函数的具体开销值)。而为了保证我们的渲染流畅,我们不得不减少这样的开销。

很自然地,我们会想到,尽量减少切换。而如何减少切换呢。我们可以记录下自己的硬件状态,在设置下一个的时候,先判断当前硬件状态是否相同,如果相同。则不用再设置。 虽然某些图形接口在其层底做了类似的功能。但我们外部判断一下,也未尝不可。从D3D上来讲,外部判断比让其内部判断效率更佳。需要注意的是,由于我们在自己的程序里做了相同判断。因此,当有另一个程序也修改设备状态的时候,就会产生意想不到的效果。所以,我们应该适当的查询一下设备状态,并更新自己的状态记录表。至于这个查询间隔,就要根据自己的实际情况来测试了。

通过记录状态的方法来提升的效率是很不明显的,因此,我们需要对材质进行排序,至于怎么排序,这算法上的问题,在此先不作过多解释。 总之,我们将相似的材质排在一起。由于材质很相似,绘完一个再绘下一个的时候,减少了切换,从而大大提升了效率。

既然已经是涉及到设备了,我们总得考虑一下设备问题。 如果设备不支持我们当前给定的材质状态,怎么办? 返回FALSE不渲染。还是让程序DOWN掉?  对于一些重要的性能,设备不支持让程序DOWN掉是最好的做法,但是,对于像纹理混合通道不足的情况,让其DOWN掉就显得划不来了。毕竟我们设计的游戏程序是想让更多的玩家能玩不是? 这样就会涉及到PASS的拆分问题。

对于PASS的拆分,OGRE已经做得很好了。根据用户的设备性能,如果不满足,就一直拆分,拆到用户满足为止,最后让一个物体渲染多次,来实现多个纹理通道混合的效果。 而多PASS则是在渲染的时候不得不考虑的地方,毕竟有些物殊效果非得用多PASS不可。

对于多PASS的设计,我们可以参考OGRE的材质方法或是D3DX的效果框架。我们把完成一个最终效果的方案称作一个渲染技术 Technique ,一个技术可由多个Pass来完成。

class Technique

{

...更多内容

 vector<CPass*> mPasses;

};

这样就满足了我们的需求。  对于同一种效果,我们可以提供多种Technique供程序选择。 而这个选择的条件则可以是根据硬件性能,或是玩家手动选择的配置来实现。

最后结构如下:

class CMaterial

{

public:

...更多内容

vector<CTechnique*> mRenderTechs

};

乱七八糟地说了一通,希望没晕死人!!!

作者:

出处: 
蛮牛专栏:
简介:09年入行,喜欢游戏和编程,对3D游戏和引擎尤其感兴趣。 
版权声明:本文版权归作者和博客园共有,欢迎转载。转载必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/geniusalex/archive/2010/04/24/1940516.html

你可能感兴趣的文章
springboot 启动的时候报错 Error creating bean with name 'solrClient'
查看>>
【IntelliJ IDEA】在idea上操作 git分支合并【如何将远程swagger分支 合并到 远程 master分支上】【如何切换 本地分支】...
查看>>
SuperMap iObject入门开发系列之三管线系统标注
查看>>
你需要知道的缓存击穿/穿透/雪崩
查看>>
[转]Hyper-V功能大跃进 或引发市场洗牌
查看>>
关于excel导入到封装成工具类jar包和web版门店收银网络无法无法连接上的解决方法...
查看>>
@InitBinder
查看>>
嵌套类可以先在外围类中声明,然后在外围类中定义
查看>>
win7组件服务COM+应用程序编录错误解决办法
查看>>
腾讯微信技术总监周颢:一亿用户增长背后的架构秘密
查看>>
在Solaris系统中,查看tcp/ip配置
查看>>
Android getWindow().setFlags方法
查看>>
POJ 3278 Catch That Cow
查看>>
实用正则手机和邮箱
查看>>
hdu 3046(最小割)
查看>>
c#让程序在WIN7下兼容模式运行
查看>>
[置顶] Codeforces Round #190 (Div. 2)(完全)
查看>>
wikioi 3027 线段覆盖 2
查看>>
Emblog 备忘
查看>>
利用广播实现ip拨号——示例
查看>>