doom3渲染器部分1


DOOM3

    map部分讲地图数据,粒子数据,模型等是放到了渲染器。比quake3的渲染器进行了分离了,模型上面与quake3不同的是模型上面的材质图像更多。
 一大半渲染时候要做的事情,在渲染器工作之前,已经使用预渲染来进行对于静态阴影体的生成了,

windows阶段

 根据机器配置opengl,设置渲染的状态(例如渲染3D?2D?),线程等等,

Opengl的这个


配置d3d驱动,对于音频,sound等等这个是用d3d来处理的(我现在都想使用一下d3d了者也)
d3d这个确实是好了


配置opengl驱动的处理了
windows32驱动的配置了,
设置像素的格式,支持opengl。



(2)检查opengl可能出现的错误,设置opengl的状态,诸如缓存溢出未能初始值等等

堆栈溢出等等

得到显示的模式,例如320*240, 1024*768,800*600等等分辨率等等的问题

windows要初始化midi音频,使用glide初始化opengl

模式列表等等截屏的处理,把屏幕上的图像保存为一个jpeg图像

(3)

显示quake3中鼠标的箭头变成一个枪口的样子的函数


得到了默认的状态,例如初始化cullface为裁剪前面

开启多重纹理,清除深度缓存,开启纹理模式

,设置opengl画图为平滑模式

开启顶点数组

禁用混合

开启多边形模式为

开启视口裁剪

禁用gl_face_cull

(4)输出机器上的opengl类型,例如opengl版本为多少,opengl支持的扩展等等

如果驱动支持gamma则输出这个硬件

否则软件支持这个位数的处理

输出纹理模式,开启纹理字符串模式

如果硬件类型为nvidia显卡

如果smpactive这个活跃的话,那么显示出来者也

如果完成了,输出完成呢个了gl的检查

根据1024*768,或者800*600等等模式来配置opengl 了者也



记录,得到了这个机器上的配置,cvar变量,从保存的机器配置上

检查opengl是不是支持多重纹理等等api函数

颜色位数等等

模版位数等等

深度位数

模式、

是否全屏 ,自定义的宽高等等

宽度,高度等等

明亮度,

动态光 ,纹理模式,动态太阳


检查opengl的arb扩展了者也


 
   
渲染部分
渲染初始化
例如这个系统是否支持遮挡查询
openglarb的查询了者也
渲染器的汗多代码其实并不是引擎也能行中用到的,而是工具用到的,
例如magetexture mapname
rendbumps渲染凹凸图像了者也
等等
gui在doom3游戏中经常的有这个,比如触发电梯的,开门的按钮,鼠标点到了那里,就会变成了鼠标的样子了者也
碰撞检测的处理了者也
渲染时候的处理
dxt文件包,乃是指的dxt1,dxt2,3,4,5等等算法的处理
shadow乃是指的这个静态阴影,动态阴影,等等的处理了者也
  • Mute Sound System
  • Run Wipe
    • Capture screen to "_scratch"
    • Display "wipeMaterial" for "com_wipeSeconds" seconds.
扑捉屏幕到这个scratch
显示“wipematrial”
  • Unload Previous Map (Call idGame::MapShutdown)
  • Show the loading gui for the next map (guis/map/____.gui)
  • 加载地图的处理了
  • 显示加载gui
  • 初始化渲染世界
  • 分析地图文件
  • 清除了这个输入缓存的处理
  • Initialize Render World
    • Parse Map File
    • Build lists of portals and models
    • Populate areas with models (but don't load them yet)
  • Clear user input buffers
  • Set user info (idGame::SetUserInfo and idGame::SetPersistentPlayerInfo)
  • Call idGame::InitFromSaveGame or idGame::InitFromNewMap
  • Call idGame::SpawnPlayer
  • 玩家出生
  • 加载所有的声音
  • 加载所有的decls
  • 加载所有的gui数据了者也
  • Load all deferred data
    • Load all models
    • Load all images
    • Load all sounds
    • Load all decls
    • Load all guis
  • 调集了10次,

乃是要加载加载一个关卡里面的模型文件,

md3模型文件了,

lwo文件,doom3中的武器,弹药,实体等等很多都是使用的lightwave文件制造的,

再转化为了这个md5模型文件了者也

ase模型文件等等

  对于模型的数据来进行分析,文件是否有错误,检测等等

(2)还有这个液体模型和粒子模型的处理
maya的这个导入了。
把md3,maya转化为了md5模型

MD5文件格式分为MESH(.md5mesh)和ANIMIATION(.md5anim),分别储存顶点和动画。

MESH部分

首先先看一下文件大概的内容

MD5Version 10commandline "mesh models/monsters/imp/animation/cycles/imp.mb -dest models/md5/monsters/imp/imp.md5mesh -game Doom -prefix IMP1_ -keep Lknee Rknee Lelbow Relbow camera Body -keep Rmissile Lmissile -parent Rmissile Rhand -parent Lmissile Lhand -parent Rwing Chest -parent Lwing Chest -parent Hips Body -parent Waist Body -parent camera Head -prefix IMP2_ -prefix IMP_ -align ALL"numJoints 71numMeshes 1joints {   "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )      //   "Body"   0 ( -0.0000002384 0 56.5783920288 ) ( -0.5 -0.5 -0.5 )      // origin   "Hips"   1 ( 3.3494229317 -0.0225959271 62.0168151855 ) ( -0.5 -0.5 -0.5 )      // Body   ...}mesh {   // meshes: polySurface1   shader "models/monsters/imp/imp"   numverts 891   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2   ...   numtris 1346   tri 0 2 1 0   ...   numweights 1401   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )   ...}

关节(JOINTS):

 "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )

首先是关节的名字,然后是关节的父接点(-1代表没有),接着是关节的位置(X,Y,Z),最后是一个四元数。

当然了四元数不能只有三个元了,但因为是单位四元数,所以我们可以把最后的W计算出来。

计算式:

1.0 = x^2 + y^2 + z^2 + w^2

PS:这里的位置都是绝对位置了,并不是相对于关节的位置。

网格(MESH):

numverts 891   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2

分别对应 顶点序号(U、V坐标) 权值开始序号 权值数

PS:解释下权值数,就是在皮肤骨骼动画中,每个顶点并不是只被一个骨骼所控制,是被许多骨骼所共同控制的,所以要有不用的权值了。这里,顶点的权值是从权值开始序号开始的N个权值。

numtris 1346   tri 0 2 1 0

这个就是三角形索引了,一看就明白,三角形序号和三角形所对应的三个顶点

numweights 1401   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )

这个是权值,依次是:权值序号、关节序号、权值和XYZ位置

对了,还有一点要补充了。顶点的最终位置是这样了

v = w(1).v * w(1).weigth + w(2).v * w(2).weight + ... + w(n).v * w(n).weight

OK,MD5先到一段落,下次再补充动画部分。 

md5模型也可以来进行增加多边形

对于md5模型,doom3中对于ma文件(maya生成的)加载的,

ase文件(3D max产生的),

lwo文件(lightwave)等等文件

转化为md5文件的网格

 据md5Mesh,这是静态的,

 对于静态的物体,就不生成动画数据md5 Anim了.

md3和这个md4文件模型的处理者也
这个md4文件的这个lod处理者也,
还有对于这个多少个骨头的处理者也,对于这个增加了这个surface面的数量

md3和md4文件相乘了以后,然后这个来进行这个来处理者也

来表示这个模型的运动等等者也

模型一类的东西

model monster_boss_cyberdemon
{
    mesh          models/md5/monsters/cyberdemon/cyberdemon.md5mesh
    channel torso ( *Waist )
    channel legs  ( *Hips Body origin ROT -*Waist)

    anim af_pose  models/md5/monsters/cyberdemon/af_pose.md5anim
    anim ik_pose  models/md5/monsters/cyberdemon/ik_pose.md5anim

    anim stand    models/md5/monsters/cyberdemon/idle.md5anim
    anim idle     models/md5/monsters/cyberdemon/idle.md5anim
    anim sight1   models/md5/monsters/cyberdemon/sight.md5anim {
        frame 16.5  sound_voice    snd_sight1
    }
    anim walk     models/md5/monsters/cyberdemon/walk3.md5anim {
        frame 17    sound_body snd_footstep
        frame 17    triggerSmokeParticle cyber_rfoot_dust
        frame 37    sound_body snd_footstep
        frame 37    triggerSmokeParticle cyber_lfoot_dust
    }
    anim pain     models/md5/monsters/cyberdemon/pain_big1.md5anim {
        frame 1    call overrideLegs
        frame 1    sound_voice snd_pain
        frame 16   sound_body  snd_footstep
        frame 49   sound_body  snd_footstep
    }
}
entityDef env_ragdoll_fatty {
  "editor_color"          "1 .5 0"
  "editor_mins"           "-8 -8 -8"
  "editor_maxs"           "8 8 8"
  "editor_usage"          "Ragdoll for monster_zombie_fat\n"
  "spawnclass"            "idAFEntity"
  "bleed"                 "1"
  "sleep"                 "1"
  "skin"                  "skins/models/monsters/fatty.skin"皮肤
  "model"                 "models/md5/monsters/zfat/zfat.md5mesh" 模型的网格
  "anim af_pose"          "models/md5/monsters/zfat/initial.md5anim"
  "articulatedFigure"     "monster_zombie_fat"
}布娃娃系统的处理了者也
 
        
这个ai的这个布娃娃的系统的处理了者也
A body is specified with a structure as follows: 

Deforms

tube
sprite
flare
expand
move
turbulent
参数居然有这么多的东西了啊,这个doom3的参数也太多了吧!
eyeBall
particle
particle2


大致的流程跟这个quake3的类似了
加载所有的这个后置的数据
加载所有的实体
加载所有的这个图像文件
加载所有的这个贴花文件
家在所有的这个gui文件的处理
调集game的幁数,10ms
创建一个静态的光的interactions
运行这个wipe
拉伸屏幕



加载一个关卡里面的模型文件,

md3模型文件了,

lwo文件,doom3中的武器,弹药,实体等等很多都是使用的lightwave文件制造的,

再转化为了这个md5模型文件了者也

ase模型文件等等

(2)还有这个液体模型和粒子模型的处理
maya的这个导入了。

把md3,maya转化为了md5模型

MD5文件格式分为MESH(.md5mesh)和ANIMIATION(.md5anim),分别储存顶点和动画。

MESH部分

首先先看一下文件大概的内容

MD5Version 10
commandline "mesh models/monsters/imp/animation/cycles/imp.mb -dest models/md5/monsters/imp/imp.md5mesh -game Doom -prefix IMP1_ -keep Lknee Rknee Lelbow Relbow camera Body -keep Rmissile Lmissile -parent Rmissile Rhand -parent Lmissile Lhand -parent Rwing Chest -parent Lwing Chest -parent Hips Body -parent Waist Body -parent camera Head -prefix IMP2_ -prefix IMP_ -align ALL"

numJoints 71
numMeshes 1

joints {
   "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )      //
   "Body"   0 ( -0.0000002384 0 56.5783920288 ) ( -0.5 -0.5 -0.5 )      // origin
   "Hips"   1 ( 3.3494229317 -0.0225959271 62.0168151855 ) ( -0.5 -0.5 -0.5 )      // Body
   ...
}

mesh {
   // meshes: polySurface1
   shader "models/monsters/imp/imp"

   numverts 891
   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2
   ...

   numtris 1346
   tri 0 2 1 0
   ...

   numweights 1401
   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )
   ...
}






  • Call idGame::RunFrame 10 times to let things settle
  • Create static light interactions
  • 创建了静态灯的这个interactions
  • Run Wipe
    • Capture screen to "_scratch"
    • Display "wipe2Material" for "com_wipeSeconds" seconds.
  • Un-Mute Sound System
  • 这个doom3的这个来处理的 
  1. Renders all selfShadow objects shadows to the stencil buffer
  2. Renders all noSelfShadow objects with lighting
  3. Renders all noSelfShadow objects shadows to the stencil buffer
  4. Renders all selfShadow objects with lighting
  5. 渲染所有的半影对象对于模板缓存
  6. 渲染所有的半影与这个灯
  7. 渲染所有的不属于半影的对象,相对于模板缓存
  8. 渲染所有的这个半影对象伴随着灯 
  9. doom3居然有这个武器的脚本者也
调集  idGame::SpawnPlayer
玩家出生
Parameters Key

Any number
Any number without a fractional part


Any value enclosed in quotes
An integer number that is an index into an array
An image map, which may include image programs (below)
A vertex / frament program. Written using the GL ARB shader language. These files are stored in the glprogs directory
An expression that is evaluated every frame.


doom3bfg渲染的处理了者也




 

关节(JOINTS):

 "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )

首先是关节的名字,然后是关节的父接点(-1代表没有),接着是关节的位置(X,Y,Z),最后是一个四元数。

当然了四元数不能只有三个元了,但因为是单位四元数,所以我们可以把最后的W计算出来。

计算式:

1.0 = x^2 + y^2 + z^2 + w^2

PS:这里的位置都是绝对位置了,并不是相对于关节的位置。

网格(MESH):

numverts 891
   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2

分别对应 顶点序号(U、V坐标) 权值开始序号 权值数

PS:解释下权值数,就是在皮肤骨骼动画中,每个顶点并不是只被一个骨骼所控制,是被许多骨骼所共同控制的,所以要有不用的权值了。这里,顶点的权值是从权值开始序号开始的N个权值。

numtris 1346
   tri 0 2 1 0

这个就是三角形索引了,一看就明白,三角形序号和三角形所对应的三个顶点

numweights 1401
   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )

这个是权值,依次是:权值序号、关节序号、权值和XYZ位置

对了,还有一点要补充了。顶点的最终位置是这样了

v = w(1).v * w(1).weigth + w(2).v * w(2).weight + ... + w(n).v * w(n).weight

OK,MD5先到一段落,下次再补充动画部分。 

md5模型也可以来进行增加多边形

对于md5模型,doom3中对于ma文件(maya生成的)加载的,

ase文件(3D max产生的),

lwo文件(lightwave)等等文件

转化为md5文件的网格

 据md5Mesh,这是静态的,

 对于静态的物体,就不生成动画数据md5 Anim了.

md3和这个md4文件模型的处理者也
这个md4文件的这个lod处理者也,
还有对于这个多少个骨头的处理者也,对于这个增加了这个surface面的数量

md3和md4文件相乘了以后,然后这个来进行这个来处理者也

来表示这个模型的运动等等者也


模型一类的东西

model monster_boss_cyberdemon
{
    mesh          models/md5/monsters/cyberdemon/cyberdemon.md5mesh
    channel torso ( *Waist )
    channel legs  ( *Hips Body origin ROT -*Waist)

    anim af_pose  models/md5/monsters/cyberdemon/af_pose.md5anim
    anim ik_pose  models/md5/monsters/cyberdemon/ik_pose.md5anim

    anim stand    models/md5/monsters/cyberdemon/idle.md5anim
    anim idle     models/md5/monsters/cyberdemon/idle.md5anim
    anim sight1   models/md5/monsters/cyberdemon/sight.md5anim {
        frame 16.5  sound_voice    snd_sight1
    }
    anim walk     models/md5/monsters/cyberdemon/walk3.md5anim {
        frame 17    sound_body snd_footstep
        frame 17    triggerSmokeParticle cyber_rfoot_dust
        frame 37    sound_body snd_footstep
        frame 37    triggerSmokeParticle cyber_lfoot_dust
    }
    anim pain     models/md5/monsters/cyberdemon/pain_big1.md5anim {
        frame 1    call overrideLegs
        frame 1    sound_voice snd_pain
        frame 16   sound_body  snd_footstep
        frame 49   sound_body  snd_footstep
    }
}
entityDef env_ragdoll_fatty {
  "editor_color"          "1 .5 0"
  "editor_mins"           "-8 -8 -8"
  "editor_maxs"           "8 8 8"
  "editor_usage"          "Ragdoll for monster_zombie_fat\n"
  "spawnclass"            "idAFEntity"
  "bleed"                 "1"
  "sleep"                 "1"
  "skin"                  "skins/models/monsters/fatty.skin"皮肤
  "model"                 "models/md5/monsters/zfat/zfat.md5mesh" 模型的网格
  "anim af_pose"          "models/md5/monsters/zfat/initial.md5anim"
  "articulatedFigure"     "monster_zombie_fat"
}布娃娃系统的处理了者也
 
       
这个ai的这个布娃娃的系统的处理了者也
A body is specified with a structure as follows: 

Deforms

tube
sprite
flare
expand
move
turbulent
参数居然有这么多的东西了啊,这个doom3的参数也太多了吧!
eyeBall
particle
particle2


大致的流程跟这个quake3的类似了
加载所有的这个后置的数据
加载所有的实体
加载所有的这个图像文件
加载所有的这个贴花文件
家在所有的这个gui文件的处理
调集game的幁数,10ms
创建一个静态的光的interactions
运行这个wipe
拉伸屏幕




在渲染的时候
在渲染的时候加上了这个prt文件的处理者也
还有md3, ma文件的处理转化为了md5模型
对于这个这个灯还有灯光照到了这个物体上来处理了者也

 跟quake3的前后端相类似

( 前端,主要是判断要渲染的多边形的数目

(1)如果是bsp文件的格式处理的场景,根据pvs计算来

选出玩家所能看见的场景,

场景物体的渲染,先根据bsp树的pvs节点,来判断玩家所在的bsp area场景的数据,

模型的处理


再根据这个玩家的视锥进行裁剪,判断玩家所能看到的场景的多边形数目,再加上

玩家所能看见的物体,及所能看见的场景的多边形加在一起,

就是渲染的多边形总数者也,把它们发送到这个显卡的顶点缓存中去

对于这个内存中的幁缓存和顶点缓存的处理

初始化顶点缓存,然后对于这个缓存数据的处理了者也


将纹理数据最后发送到了这个显卡的幁缓存中去,

使用的opengl扩展来做光照。shader脚本部分的处理

对于NVIDIA的硬件,对于amd的使用amd的硬件扩展,对于其他的硬件,

则使用OpenGL的GL_VERTEX_PROGRAM_ARB扩展,因为这个是OpenGL通用的扩展,通用

这个渲染器根据配置文件的中的显卡的渲染,
arb,arb2,nv,nv2,ati的显卡,来进行这个光照和这个纹理的映射的处理了



deform
这个乃是
还有ovelay的处理


idRenderModel * model = NULL;

if ( ( extension.Icmp( "ase" ) == 0 ) || ( extension.Icmp( "lwo" ) == 0 ) || ( extension.Icmp( "flt" ) == 0 ) || ( extension.Icmp( "ma" ) == 0 ) ) {
model = new (TAG_MODEL) idRenderModelStatic;
} else if ( extension.Icmp( MD5_MESH_EXT ) == 0 ) {
model = new (TAG_MODEL) idRenderModelMD5;
} else if ( extension.Icmp( "md3" ) == 0 ) {
model = new (TAG_MODEL) idRenderModelMD3;
} else if ( extension.Icmp( "prt" ) == 0  ) {
model = new (TAG_MODEL) idRenderModelPrt;
} else if ( extension.Icmp( "liquid" ) == 0  ) {
model = new (TAG_MODEL) idRenderModelLiquid;
模型一共可以分为了五种,
液体,还有这个粒子等等模型的分类的处理了者也

typedef enum {
OP_TYPE_ADD,
OP_TYPE_SUBTRACT,
OP_TYPE_MULTIPLY,
OP_TYPE_DIVIDE,
OP_TYPE_MOD,
OP_TYPE_TABLE,
OP_TYPE_GT,
OP_TYPE_GE,
OP_TYPE_LT,
OP_TYPE_LE,
OP_TYPE_EQ,
OP_TYPE_NE,
OP_TYPE_AND,
OP_TYPE_OR,
OP_TYPE_SOUND
} expOpType_t;
typedef enum {
SS_SUBVIEW = -3, // mirrors, viewscreens, etc
SS_GUI = -2, // guis
SS_BAD = -1,
SS_OPAQUE, // opaque

SS_PORTAL_SKY,

SS_DECAL, // scorch marks, etc.

SS_FAR,
SS_MEDIUM, // normal translucent
SS_CLOSE,

SS_ALMOST_NEAREST, // gun smoke puffs

SS_NEAREST, // screen blood blobs

SS_POST_PROCESS = 100 // after a screen copy to texture
} materialSort_t;

材质的一个排序的处理了者也

typedef enum {
SURFTYPE_NONE, // default type
    SURFTYPE_METAL,
SURFTYPE_STONE,
SURFTYPE_FLESH,
SURFTYPE_WOOD,
SURFTYPE_CARDBOARD,
SURFTYPE_LIQUID,
SURFTYPE_GLASS,
SURFTYPE_PLASTIC,
SURFTYPE_RICOCHET,
SURFTYPE_10,
SURFTYPE_11,
SURFTYPE_12,
SURFTYPE_13,
SURFTYPE_14,
SURFTYPE_15
} surfTypes_t;



1 渲染所有的这个半影的阴影对象
2 渲染所有的这个不在阴影内部的对象
3 渲染所有的模板缓存里的对象物体
4渲染所有的光照的半影物体的出路
材质
textures/alphalabs/a_lfwall21b
{
    qer_editorimage textures/alphalabs/a_lfwall21b
    bumpmap         textures/base_wall/lfwall21_local 凹凸贴图的处理了者也
    diffusemap      textures/alphalabs/a_lfwall21b    漫反射图像的处理
    specularmap     textures/alphalabs/a_lfwall21b_s  反射光的处理了者也
}
第一行是这个材质的图像的名字
第二行是这个凹凸图像的名字
 
         
 
         
对于这个材质的处理,
显示加载上了这个材质,然后再转化为了这个材质的处理了者也

图像编程的这个函数者也

这个使用的五六层材质的图片了者也

heightmap(, )

高度图的参数者也

add(, )

scale(, [,float] [,float] [,float])

invertAlpha()

invertColor()

makeIntensity()

makeAlpha()

makeIntensity()


mefragmentProgram 这个乃是 

gaTexture

这个纹理的这个处理了者也


把图像这个转化为了这个

室外的这个草的问题了者也处理了
者也
对于地形使用这个bsp来处理这个,怎么来处理的呢?
textures/glass/outdoor_glass1
{
    noSelfShadow
    noshadows
    twosided
    translucent
    glass
    forceoverlays
    sort decal

    qer_editorimage textures/glass/glass1
    {
        vertexProgram heatHaze.vfp
        vertexParm  0  0 , 0  // texture scrolling
        vertexParm  1  .5  // magnitude of the distortion

        fragmentProgram heatHaze.vfp
        fragmentMap 0  _currentRender
        fragmentMap 1  textures/sfx/vp1 // the normal map for distortion
    }
    {
        maskcolor                               
        map makealpha(textures/glass/glass1)
    }   
    {
        blend gl_dst_alpha, gl_one
        maskalpha
        cubeMap env/gen2
        red     Parm0
        green   Parm1
        blue    Parm2
        texgen  reflect
    }
    {
        blend filter
        map textures/glass/outdoor_glass1fx
    }
}
这个家伙难道是这个是用的cg的fx文件来进行这个对于材质的处理的?
id使用的自身定义的这个顶点着色器文件等来处理这个
 
          
        
  - idCommon::Frame
   - idSession::UpdateScreen
     - idSession::Draw
       - idGame::Draw
         - idPlayerView::RenderPlayerView
           - idPlayerView::SingleView
             - idRenderWorld::RenderScene
             |  - build params
             |  - ::R_RenderView(params)
             |    {
             |        R_SetViewMatrix
             |        R_SetupViewFrustum
             |        R_SetupProjection      设置投影
             |        static_cast(parms->renderWorld)->FindViewLightsAndEntities();
             |        R_ConstrainViewFrustum    
             |        R_AddLightSurfaces   增加光照的面
             |        R_AddModelSurfaces    增加模型
             |        R_RemoveUnecessaryViewLights
             |        R_SortDrawSurfs                
             |        R_GenerateSubViews
             |        R_AddDrawViewCmd 
             |    }
             |
             - idPlayer::DrawHUD

      FindViewLightsAndEntities:
        PointInArea:  Uses tr.viewDef->initialViewAreaOrigin and search for the area
                      the origin is located in.
                      This is a non-recursive BSP traversal

        


      At the end of the first step, RC_DRAW_VIEW commands are issued. Each command contains a 
      viewDef which contains among other things the list of surfaces to render.           
         
                 
      Note: R_SortDrawSurfs uses libc qsort, C++ sort with template would have been so much faster 
      Note: The end of the process (R_AddDrawViewCmd) adds rendering commands to the command buffer.
            RB_ExecuteBackEndCommands picks up those commands types (RC_DRAW_VIEW)
                
                
        

The naming convention is a bit misleading. Even though there are "Render" and "Draw" everywhere, the CPU is not communicating with the GPU at all. The sole goal of the FrontEnd is to gather informations, pack them in a viewDef and let the backend pick it up.

Doom3 Renderer Backend


 
        
      idRenderSystemLocal::EndFrame
       R_IssueRenderCommands
         RB_ExecuteBackEndCommands
           RB_DrawView
            RB_ShowOverdraw
            RB_STD_DrawView
            {
               RB_BeginDrawingView     // clear the z buffer, set the projection matrix, etc
               RB_DetermineLightScale
               
               
RB_STD_FillDepthBuffer  // fill the depth buffer and clear color buffer to black except on
               
               _DrawInteractions
               {
               5 GPU specific path
                   R10 (GeForce256)
                   R20 (geForce3)
                   R200 (Radeon 8500)
                   ARB
                   ARB2
                }
决定了这个阴影体的这个渲染了者也
                
                // disable stencil shadow test
                qglStencilFunc( GL_ALWAYS, 128, 255 );

                RB_STD_LightScale
                
                RB_STD_DrawShaderPasses   //draw any non-light dependent shading passes
                
                RB_STD_FogAllLights
                
                RB_STD_DrawShaderPasses
                                
                                
        
The Backend starts by rendering all geometry provided by the frontend but only writing to the depth 
Stage Keywords

blend
blend

Blend types:

Type Src Dst
blend gl_src_alpha gl_one_minus_src_alpha
add gl_one gl_one
filter gl_dst_color gl_zero
modulate gl_dst_color gl_zero
none gl_zero gl_one
bumpmap Normal map
diffusemap Diffuse map
specularmap Specular map

Source blend modes:

gl_one Constant 1
gl_zero Constant 0
gl_dst_color The color currently on the screen
gl_one_minus_dst_color One minus the color currently on the screen
gl_src_alpha The alpha channel of the source image
gl_one_minus_src_alpha One minus the alpha channel of the source image
gl_dst_alpha The alpha channel of the screen image
gl_one_minus_dst_alpha One minus the alpha channel of the screen image
gl_src_alpha_saturate Minimum of the source alpha and one minus screen alpha

Destination blend modes:

gl_one Constant 1
gl_zero Constant 0
gl_src_color The color of the source image
gl_one_minus_src_color One minus the color of the source image
gl_src_alpha The alpha channel of the source image
gl_one_minus_src_alpha One minus the alpha channel of the source image
gl_dst_alpha The alpha channel of the screen image
gl_one_minus_dst_alpha One minus the alpha channel of the screen image



map The image program to use for this stage
remoteRenderMap Width and Height of the buffer to render a remote image in to (for cameras). The entity this material is applied to has to support remote render views.
mirrorRenderMap Width and Height of the buffer to render a mirror in to. This of course makes this stage a mirror stage, which is different from using the 'mirror' global keyword because that makes the entire material a mirror, rather than just one stage.
videomap [loop] This stage uses a video stream as an image map
soundmap [waveform] This stage uses a sound meter from the sound system as an image map. Specify 'waveform' to get a scope rather than bars.
cubeMap This stage uses a cube map as the image map. Looks for _px, _py, _pz, _nx, _ny, _nz for the positive x, y, z, and negative x, y, z sides
cameraCubeMap This stage uses a cube map in camera space. Looks for _forward, _back, _left, _right, _up, and _down
ignoreAlphaTest Always use DEPTHFUNC_LEQUAL rather than DEPTHFUNC_EQUAL which is normally used for opaque and alpha tested surfaces
nearest Use nearest texture filtering
linear Use linear texture filtering
clamp Same as the global keywords. Use to override a global clamp for a specific stage.
zeroclamp
alphazeroclamp
noclamp Use to set texture repeat for a stage when global clamp is set

uncompressed
Do not compress this image in medium quality mode



highquality

forceHighQu

ality
Do not compress this image in low quality mode
nopicmip Ignore the image_downSize cvar

vertexColor
Multiply the pixel color by the vertex color

inverseVertexColor
Multiply the pixel color by one minus the vertex color


privatePolygonOffset
Explict larger (or negative) polygon offset for this stage
 
texGen
Type is one of: normal, reflect, skybox, wobbleSky   

scroll ,
Scroll the texture coordinates



translate < exp>,


scale ,
Just scales without a centering
centerScale

,
Subtracts 0.5, then scales, then adds 0.5

shear ,
Subtracts 0.5, then shears, then adds 0.5

rotate
Subtracts 0.5, then rotates, then adds 0.5


maskRed
Don't write to the red channel
maskGreen Don't write to the blue channel
maskBlue Don't write to the green channel
maskAlpha Don't write to the alpha channel
maskColor Shortcut for
maskRed
maskGreen
maskBlue
maskDepth Don't write to the depth buffer
alphaTest Only write if the alpha value is greater than
red Set the red vertex color
green Set the green vertex color
blue Set the blue vertex color
alpha Set the alpha vertex value
rgb Shortcut for
red 
green 
blue 
rgba Shortcut for
red 
green 
blue 
alpha 
color , , , Shortcut for
red exp0
green exp1
blue exp2
alpha exp3
colored Shortcut for
color parm0, parm1, parm2, parm3
if Conditionally disable stages
fragmentProgram Use an ARB fragment program with this stage
vertexProgram Use an ARB vertex program with this stage
program Shortcut for
fragmentProgram 
vertexProgram 
vertexParm
[,exp1] [,exp2] [,exp3]
Values to pass to the vertex program. One expression gets repeated across all 4 values. Two expressions put 0, 1 in z, w. Three expressions put 1 in w.
fragmentMap [options] The image map to use for texture unit
[options] can be cubeMap, cameraCubeMap, nearest, linear, clamp, noclamp, zeroclamp, alphazeroclamp, forceHighQuality, uncompressed, highquality, or nopicmip


megaTexture
This stage uses a mega texture (super secret)
megeTexture这个状态的处理了者也
这个megetexture的处理了者也

加载mgr材质文件

来表示材质属性的文件了

加载这个freetype库文件等等

用来渲染这个字体的处理者也!



Registerskins

其实就是加载这个纹理文件,

jpg,bmp,tga文件调用了这个bmp文件,jpg,tga等等文件加载的图像函数者也


加载地图文件map,proc等等文件者也


InitRenderCommand

初始化这个渲染列表的命令者也!
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
RC_STRETCH_PIC,
RC_DRAW_SURFS,
RC_DRAW_BUFFER,
RC_SWAP_BUFFERS,
RC_SCREENSHOT
} renderCommand_t;
停止渲染列表

线程的状态
{
渲染场景,
设置颜色
DrawBuffer 
Draw2D
Draw3d
}

对于线程的互斥锁,mutex,线程的切换,同步的处理了


线程的状态等等,例如交换缓存,提交数据,一个线程把数据准备好了,另一个进行渲染者也 

不断的运行线程者也,切换线程的状态者也

渲染


渲染buffer
对于子弹的痕迹,还有粒子系统的处理等等

对于beginFrame之前,进行前端的处理
在一幁处理完了后,
每次不断的交换缓存,来进行渲染

RenderFrame,来渲染后置数据了
renderView,视口从配置文件里面得到的这个的
对于配置文件中找到了这个各种功能了

md3模型的顶点数目,这个纹理坐标的处理了





渲染3d
noise噪声的处理

初始化这个命令列表,
各种命令的处理
在这个最后,消除了命令列表了者也


backEndData[tr.smpFrame]->commands.used = 0;

r_firstSceneDrawSurf = 0;

r_numdlights = 0;
r_firstSceneDlight = 0;

r_numentities = 0;
r_firstSceneEntity = 0;

r_numpolys = 0;
r_firstScenePoly = 0;

r_numpolyverts = 0;
}

每一帧,清除了这个一幁之内的多边形数目
和所有的entity的数据了
渲染队列
Brush model和这个md3模型了者也
原来这个quake3这个还有一个关于运行期间的这个glstate设置的结构者也
这个乃是设置这个运行时刻的这个状态的东西者也
data = GLimp_RendererSleep();

if ( !data ) {
return; // all done, renderer is shutting down
}

renderThreadActive = qtrue;
画这个多边形者也!
在渲染时,来交换这个线程的数据者也!
交换这个线程的数据者也
不断的更换这个线程里面的这个数据者也
渲染视图内的多边形
渲染这个


(1)渲染器

(其实这一部分乃是在这个cgame里面定义的者也)

初始化渲染状态,渲染2d,渲染3d,渲染缓存,



关卡截屏,对于每一关生成了截屏的图片了者也

渲染过程中

渲染命令列表

不断的切换渲染线程者也,
例如设置颜色, 

对于渲染器方面,使用控制命令来控制这个渲染状态者也,渲染2d,设置颜色者也
   渲染3d

这几个状态,分别在ui界面时,渲染器切换到2D渲染,

进入游戏后,切换到3D渲染,

 前端,
初始化命令行者也 记录总数者也

如渲染线程的状态分为场景电影,2D,3D,Buffer,画surface,画缓冲区等等

在播放游戏开始的画面视频时,在切换到视频的状态,每个状态对应的执行过程不同,例如3D的渲染3D空间的物体,2D渲染的平面的物体,场景的电影,我们把它剪成一幁一幁地画上去,  

   
交换缓存,来进行渲染者也
画缓存,
画多边形等等的处理者也
后置阶段的所有的多边形者也
线程的处理等等




2d部分的显示者也
渲染2d

字体
渲染2d的处理,,
要渲染了字体和图像了者也
freetype这个opengl的显示纹理乃是使用的这个纹理的2次方了者也,
这个乃是调用的这个把字体保存为了纹理图片,然后来显示纹理的
拉伸纹理,拉伸这个字体的处理等等
载入了这个字体的轮廓,把轮廓保存为了位图,然后来进行处理了者也!
调用显示列表来处理
保存位图,把这个转化为了这个opengl能够使用的这个纹理东西了者也
8位的亮度表示这个alpha?
绑定了字体的纹理
 计算位图中字符图像的宽度
绘制一个正方形,显示字符
然后绑定了这个纹理的宽度和这个长度,来显示的这个字体的处理了者也

// 创建FreeType库
创建一个freetype这个字体的库?
在FreeType库中保存字体信息的类叫做face
在FreeType中使用1/64作为一个像素的高度所以我们需要缩放h来满足这个要求
设置这个face这个的尺寸了者也
然后再来创建了这个显示列表,
释放了这个freetype类,
释放了这个face

最后释放显示列表
最后显示这个字体的处理
字体的使用者也,使用的freetype来绘制

图像
StretchPic();//拉宽页面
显示一幅图像者也
设置颜色
设置2d式的状态等等

在显示这个文字时候,拉宽图像,文字在制定的地方渲染
对于2d的东西,例如生命值,中心的交叉点,还有弹药值等等2d的东西要不断的切换线程的状态,
从而来进行渲染者也



1

加载了dmap文件了者也

dmap文件的格式


列表

Lump Index块索引              Lump Name块名          Description描述

1                             Texture纹理                 表现面的性质,转换为GL纹理

2                             Planes平面地形           map包括了进去

3                             Nodes                          BSP树节点

4                             Leaves                         BSP树叶

5                             Leafface                       face面索引列表,每个Leaf都有


7                             Models模型                 描述了一个场景骨架


10                            Vertex顶点                   不用多说,构造每一个面

11                            Meshvertes                   偏移列表,每个mesh都有


13                            Faces                       也不要多说

14                            Lightmaps光照             打包的光照数据,转换为GL纹理


16                           Visdata                         Cluster-cluster可以看到的一簇一簇数据


每一个部分的结构如下表示的

从网上基于quake3引擎的大致影响之bsp格式直接转过来的者也

typedef struct { 
  int fileofs, filelen; 
  } lump_t;

用来   
  typedef struct { 
  int ident; 
  int version; 
  lump_t lumps[HEADER_LUMPS]; 
  } dheader_t;// 
  typedef struct { 
  char shader[MAX_QPATH]; 

  int surfaceFlags;//绝对经典的东西,还是和q3map一起说比较有趣, 
  int contentFlags;//绝对经典的东西,还是和q3map一起说比较有趣 
  } dshader_t; // lump1 
  // planes x^1 is allways the opposite of plane x 
  typedef struct { 
  float normal[3]; 
  float dist; 
  } dplane_t; // lump2


  typedef struct { 
  int planeNum; 
  int children[2]; // negative numbers are -(leafs+1), not nodes 
  int mins[3]; // for frustom culling 
  int maxs[3]; 
  } dnode_t; // lump3


  typedef struct { 
  int cluster; // -1 = opaque cluster (do I still store these?) 
  int area; 
  int mins[3]; // for frustum culling 
  int maxs[3]; 
  int firstLeafSurface; 
  int numLeafSurfaces; 
  //用于碰撞检测,不用于渲染模块 
  int firstLeafBrush; 
  int numLeafBrushes; 
  } dleaf_t; // lump4


  int leafsurfaces; // lump5 
  int leafbrushes; //lump6 
  

      typedef struct { 
  float mins[3], maxs[3]; 
  int firstSurface, numSurfaces; 
  //下面的变量用于碰撞检测用 
  int firstBrush, numBrushes; 
  } dmodel_t;// lump7


  typedef struct { 
  int firstSide; 
  int numSides; 
  int shaderNum; // the shader that determines the contents flags 
  } dbrush_t;// lump8


  typedef struct { 
  int planeNum; // positive plane side faces out of the leaf 
  int shaderNum; 
  } dbrushside_t;// lump9


  typedef struct { 
  vec3_t xyz; 
  float st[2]; 
  float lightmap[2]; 
  vec3_t normal; 
  byte color[4]; 
  } drawVert_t;// lump10


  int drawIndexes; // lump11


  typedef struct { 
  char shader[MAX_QPATH]; 
  int brushNum; 
  int visibleSide; // the brush side that ray tests need to clip against (-1 == none) 
  } dfog_t;// lump12


  //对表面类型进行总结,具体见下面 
  typedef enum { 
  MST_BAD, 
  MST_PLANAR,//很重要的,说明该表面是一个世界的静态表面,例如墙面,地板等,可以通 
  //过brushside计算出来 
  MST_PATCH,//二次贝塞尔表面,要进行相应三角型化,要求速度的话,可以使用前向差分 
  //算法,二次贝塞尔使用9个控制点插值计算 
  MST_TRIANGLE_SOUP,//用于BMODEL的表面,可以进行三角形扇或带化或顶点索引三角形 
  //如果要了解具体算法,可以参考一些计算几何的算法,如果有足够 
  //深厚的功力,建议参考nvstriper相关代码,还有关于计算几何或 
  //拓拔方面的知识,网络上有一个很好的库ttl,里面有篇实现的论 
  //文,关于gmap概念以及使用半边结构进行各种拓拔查找以及修改, 
  //绝对经典的东西 
  MST_FLARE //实际上就是公告版,因该都会使用吧 
  } mapSurfaceType_t;


  typedef struct { 
  int shaderNum;//索引指向shaderlump 
  int fogNum;//索引指向foglump 
  int surfaceType;// mapSurfaceType_t,具体说明见上 
  int firstVert;//索引指向drawVert_tlump 
  int numVerts; 
  int firstIndex;//索引指向顶点索引lump 
  int numIndexes; 
  

//下面一些变量和静态lightmap相关,事实上现在的图形硬件足够快,静态光照图相关算 
  //法已有没落的趋势,事实上现在比较先进的引擎都是全动态光照,通过BSP进行场景管理 
  //可以非常高效的实现,使渲染效果大幅度提高。这部分是我最感兴趣的部分,以后有机会 
  //可以探讨一下,但是必须要对BSP相关操作有非常的了解才可以深入 

  int lightmapNum; 
  int lightmapX, lightmapY; 
  int lightmapWidth, lightmapHeight; 
  vec3_t lightmapOrigin; 
  vec3_t lightmapVecs[3]; // for patches, [0] and [1] are lodbounds 

  //下面两个变量用于贝塞尔曲面 
 

 int patchWidth; 
  int patchHeight; 
  } dsurface_t;// lump13 
  byte lightBytes; // lump14 
  byte lightgridData;// lump15 
  byte visBytes;// lump16




bsp地图格式的处理了者也

This document describes the Quake 3 BSP file format. This is an unofficial document. Quake 3 is a registered trademark of id Software, which does not sponsor, authorize, or endorse this document.

This document describes the Quake 3 BSP file format as the author understands it. While every effort has been made to ensure that the contents of this document are accurate, the author does not guarantee that any portion of this document is actually correct. In addition, the author cannot be held responsible the consequences of the any use or misuse of the information contained in this document.

Copyright © 2000 Kekoa Proudfoot. All rights reserved.




Description [top]

File structure

Quake 3 BSP files are IBSP files, and therefore have a structure similar to previous BSP files from id Software. Every IBSP file begins with a header, which in turn contains a lump directory. The lump directory describes the layout of the rest of the file, which contains some number of lumps. Each lump stores a particular kind of map data.

Header / Directory
Lump
Lump
Lump
...
The layout of an IBSP file. An IBSP file consists of a header followed by a number of lumps. The header contains a directory which identifies the locations and sizes of the lumps.

Data types

Quake 3 BSP files contains only four basic data types. They are:

Type Description
 
ubyte unsigned byte
int 4-byte integer, little-endian
float 4-byte IEEE float, little-endian
string[n] string of n ASCII bytes, not necessarily null-terminated
 

All data in a BSP file is organized into records composed of these four data types.

Header and Directory

The header record looks like this:

header

string[4] magic Magic number. Always "IBSP".
int version Version number. 0x2e for the BSP files distributed with Quake 3.
direntry[17] direntries Lump directory, seventeen entries.

Each direntry locates a single lump in the BSP file:

direntry

int offset Offset to start of lump, relative to beginning of file.
int length Length of lump. Always a multiple of 4.

Lumps

There are 17 lumps in a Quake 3 BSP file. In the order that they appear in the lump directory, they are:  

Index Lump Name  Description
 
0 Entities Game-related object descriptions.
1 Textures Surface descriptions.
2 Planes Planes used by map geometry.
3 Nodes BSP tree nodes.
4 Leafs BSP tree leaves.
5 Leaffaces Lists of face indices, one list per leaf.
6 Leafbrushes Lists of brush indices, one list per leaf.
7 Models Descriptions of rigid world geometry in map.
8 Brushes Convex polyhedra used to describe solid space.
9 Brushsides Brush surfaces.
10 Vertexes Vertices used to describe faces.
11 Meshverts Lists of offsets, one list per mesh.
12 Effects List of special map effects.
13 Faces Surface geometry.
14 Lightmaps Packed lightmap data.
15 Lightvols Local illumination data.
16 Visdata Cluster-cluster visibility data.

Entities

The entities lump stores game-related map information, including information about the map name, weapons, health, armor, triggers, spawn points, lights, and .md3 models to be placed in the map. The lump contains only one record, a string that describes all of the entities:

entities

string[lengthents Entity descriptions, stored as a string.

The length of the entity string is given by the size of the lump itself, as specified in the lump directory.

The meanings, formats, and parameters of the various entity descriptions are currently outside the scope of this document. For more information about entity descriptions, see the documentation to Q3Radiant, the Quake 3 level editor.

Textures

The textures lump stores information about surfaces and volumes, which are in turn associated with faces, brushes, and brushsides. There are a total of length / sizeof(texture) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

texture

string[64] name Texture name.
int flags Surface flags.
int contents Content flags.

Planes

The planes lump stores a generic set of planes that are in turn referenced by nodes and brushsides. There are a total of length / sizeof(plane) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

plane

float[3] normal Plane normal.
float dist Distance from origin to plane along normal.

Note that planes are paired. The pair of planes with indices i and i ^ 1 are coincident planes with opposing normals.

Nodes

The nodes lump stores all of the nodes in the map's BSP tree. The BSP tree is used primarily as a spatial subdivision scheme, dividing the world into convex regions called leafs. The first node in the lump is the tree's root node. There are a total of length / sizeof(node) records in the lump, wherelength is the size of the lump itself, as specified in the lump directory.

node

int plane Plane index.
int[2] children Children indices. Negative numbers are leaf indices: -(leaf+1).
int[3] mins Integer bounding box min coord.
int[3] maxs Integer bounding box max coord.

Leafs

The leafs lump stores the leaves of the map's BSP tree. Each leaf is a convex region that contains, among other things, a cluster index (for determining the other leafs potentially visible from within the leaf), a list of faces (for rendering), and a list of brushes (for collision detection). There are a total of length / sizeof(leaf) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

leaf

int cluster Visdata cluster index.
int area Areaportal area.
int[3] mins Integer bounding box min coord.
int[3] maxs Integer bounding box max coord.
int leafface First leafface for leaf.
int n_leaffaces Number of leaffaces for leaf.
int leafbrush First leafbrush for leaf.
int n_leafbrushes Number of leafbrushes for leaf.

If cluster is negative, the leaf is outside the map or otherwise invalid.

Leaffaces

The leaffaces lump stores lists of face indices, with one list per leaf. There are a total of length / sizeof(leafface) records in the lump, where length is the size of the lump itself, as specified in the  lump directory.

leafface

int face Face index.

Leafbrushes

The leafbrushes lump stores lists of brush indices, with one list per leaf. There are a total of length / sizeof(leafbrush) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

leafbrush

int brush Brush index.

Models

The models lump describes rigid groups of world geometry. The first model correponds to the base portion of the map while the remaining models correspond to movable portions of the map, such as the map's doors, platforms, and buttons. Each model has a list of faces and list of brushes; these are especially  important for the movable parts of the map, which (unlike the base portion of the map) do not have BSP trees associated with them. There are a total of length / sizeof(models) records in the lump, wherelength is the size of the lump itself, as specified in the lump directory.

model

模型

float[3] mins Bounding box min coord.
float[3] maxs Bounding box max coord.
int face First face for model.
int n_faces Number of faces for model.
int brush First brush for model.
int n_brushes Number of brushes for model.

Brushes

笔刷

The brushes lump stores a set of brushes, which are in turn used for collision detection. Each brush describes a convex volume as defined by its surrounding surfaces. There are a total of length / sizeof(brushes) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

brush

int brushside First brushside for brush.
int n_brushsides Number of brushsides for brush.
int texture Texture index.

Brushsides

笔刷的边

The brushsides lump stores descriptions of brush bounding surfaces. There are a total of length / sizeof(brushsides) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

brushside

int plane Plane index.
int texture Texture index.

Vertexes

The vertexes lump stores lists of vertices used to describe faces. There are a total of length / sizeof(vertex) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

vertex

float[3] position Vertex position.
float[2][2] texcoord Vertex texture coordinates. 0=surface, 1=lightmap.
float[3] normal Vertex normal.
ubyte[4] color Vertex color. RGBA.

Meshverts

The meshverts lump stores lists of vertex offsets, used to describe generalized triangle meshes. There are a total of length / sizeof(meshvert) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

meshvert

int offset Vertex index offset, relative to first vertex of corresponding face.

Effects

The effects lump stores references to volumetric shaders (typically fog) which affect the rendering of a particular group of faces. There are a total of length / sizeof(effect) records in the lump, wherelength is the size of the lump itself, as specified in the lump directory.

effect

string[64] name Effect shader.
int brush Brush that generated this effect.
int unknown Always 5, except in q3dm8, which has one effect with -1.

Faces

The faces lump stores information used to render the surfaces of the map. There are a total of length / sizeof(faces) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

face

int texture Texture index.
int effect Index into lump 12 (Effects), or -1.
int type Face type. 1=polygon, 2=patch, 3=mesh, 4=billboard
int vertex Index of first vertex.
int n_vertexes Number of vertices.
int meshvert Index of first meshvert.
int n_meshverts Number of meshverts.
int lm_index Lightmap index.
int[2] lm_start Corner of this face's lightmap image in lightmap.
int[2] lm_size Size of this face's lightmap image in lightmap.
float[3] lm_origin World space origin of lightmap.
float[2][3] lm_vecs World space lightmap s and t unit vectors.
float[3] normal Surface normal.
int[2] size Patch dimensions.

There are four types of faces: polygons, patches, meshes, and billboards.

Several components have different meanings depending on the face type.

For type 1 faces (polygons), vertex and n_vertexes describe a set of vertices that form a polygon. The set always contains a loop of vertices, and sometimes also includes an additional vertex near the center of the polygon. For these faces, meshvert and n_meshverts describe a valid polygon triangulation. Every three meshverts describe a triangle. Each meshvert is an offset from the first vertex of the face, given by vertex.

For type 2 faces (patches), vertex and n_vertexes describe a 2D rectangular grid of control vertices with dimensions given by size. Within this rectangular grid, regions of 3×3 vertices represent biquadratic Bezier patches. Adjacent patches share a line of three vertices. There are a total of (size[0] - 1) / 2 by (size[1] - 1) / 2 patches. Patches in the grid start at (i, j) given by:

i = 2n, n in [ 0 .. ( size[0] - 1) / 2 ), and
j = 2m, m in [ 0 .. ( size[1] - 1) / 2 ).

For type 3 faces (meshes), meshvert and n_meshverts are used to describe the independent triangles that form the mesh. As with type 1 faces, every three meshverts describe a triangle, and each meshvert is an offset from the first vertex of the face, given by vertex.

For type 4 faces (billboards), vertex describes the single vertex that determines the location of the billboard. Billboards are used for effects such as flares. Exactly how each billboard vertex is to be interpreted has not been investigated.

The lm_ variables are primarily used to deal with lightmap data. A face that has a lightmap has a non-negative lm_index. For such a face, lm_index is the index of the image in the lightmaps lump that contains the lighting data for the face. The data in the lightmap image can be located using the rectangle specified by lm_start and lm_size.

For type 1 faces (polygons) only, lm_origin and lm_vecs can be used to compute the world-space positions corresponding to lightmap samples. These positions can in turn be used to compute dynamic lighting across the face.

None of the lm_ variables are used to compute texture coordinates for indexing into lightmaps. In fact, lightmap coordinates need not be computed. Instead, lightmap coordinates are simply stored with the vertices used to describe each face.


Lightvols

The lightvols lump stores a uniform grid of lighting information used to illuminate non-map objects. There are a total of length / sizeof(lightvol) records in the lump, where length is the size of the lump itself, as specified in the lump directory.

Lightvols make up a 3D grid whose dimensions are:

nx = floor(models[0].maxs[0] / 64) - ceil(models[0].mins[0] / 64) + 1
ny = floor(models[0].maxs[1] / 64) - ceil(models[0].mins[1] / 64) + 1
nz = floor(models[0].maxs[2] / 128) - ceil(models[0].mins[2] / 128) + 1

lightvol

ubyte[3] ambient Ambient color component. RGB.
ubyte[3] directional Directional color component. RGB.
ubyte[2] dir Direction to light. 0=phi, 1=theta.

Visdata

The visdata lump stores bit vectors that provide cluster-to-cluster visibility information. There is exactly one visdata record, with a length equal to that specified in the lump directory.

visdata

int n_vecs Number of vectors.
int sz_vecs Size of each vector, in bytes.
ubyte[n_vecs * sz_vecsvecs Visibility data. One bit per cluster per vector.

Cluster x is visible from cluster y if the (1 << y % 8) bit of vecs[x * sz_vecs + y / 8] is set.

Note that clusters are associated with leaves.

Known Issues and Missing Items [top]

This document is very brief. I have gathered more information, but have not had time to write it up. Occasionally, I add more information to this document.

At some point I put together a page that describes triangle meshes and other q3 leaf elements. I forget the exact reason I created that page, but you might find it interesting.

Feel free to ask for clarification, but please accept my apologies if I can't find the time to answer.





对于bsp文件的这个加载以及处理方案,

对于bsp文件中得到了这个光源,entity来抽取出来进行显示了者也



R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] );
这个说什么都想象不到的者也

// we are about to upload textures
R_SyncRenderThread();

R_LoadShaders( &header->lumps[LUMP_SHADERS] );

R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS] );、
加载光照贴图的处理了者也!

R_LoadShaders( &header->lumps[LUMP_SHADERS] );

R_LoadLightmaps( &header->lumps[LUMP_LIGHTMAPS] );

R_LoadPlanes (&header->lumps[LUMP_PLANES]);

R_LoadFogs( &header->lumps[LUMP_FOGS], &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES] );

R_LoadSurfaces( &header->lumps[LUMP_SURFACES], &header->lumps[LUMP_DRAWVERTS], &header-
>lumps[LUMP_DRAWINDEXES] );

R_LoadMarksurfaces (&header->lumps[LUMP_LEAFSURFACES]);

R_LoadNodesAndLeafs (&header->lumps[LUMP_NODES], &header->lumps[LUMP_LEAFS]);

R_LoadSubmodels (&header->lumps[LUMP_MODELS]);

R_LoadVisibility( &header->lumps[LUMP_VISIBILITY] );

R_LoadEntities( &header->lumps[LUMP_ENTITIES] );

R_LoadLightGrid( &header->lumps[LUMP_LIGHTGRID] );



加载整个quake3整个的这个流程的处理等等了者也
对于这个分析face,分析光照贴图的分析等等

case MST_PATCH:
ParseMesh ( in, dv, out );
numMeshes++;
break;
case MST_TRIANGLE_SOUP:
ParseTriSurf( in, dv, out, indexes );
numTriSurfs++;
break;
case MST_PLANAR:
ParseFace( in, dv, out, indexes );
numFaces++;
break;
case MST_FLARE:
ParseFlare( in, dv, out, indexes );
numFlares++;
break;

out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight, 
                          shader->fogParms.color[1] * tr.identityLight, 
                          shader->fogParms.color[2] * tr.identityLight, 1.0 );
R_ColorShiftLightingBytes( &w->lightGridData[i*8], &w->lightGridData[i*8] );
R_ColorShiftLightingBytes( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] );

对于光照这个偏移了

根据视口的高度,宽度等等来生成



2根据bsp文件中存储的玩家的位置,

来决定玩家的照相机的位置,根据配置文件的存储的这个view视口的

长,宽,远,近平面来生成这个平截头体,来判断这个与

bsp树中的这个
视锥体的六个平面与这个照相机的处理了这个,然后这个六个平面和这个pvs的处理者也

照相机的,这个六个视锥平面,来判断这个与bsp文件的相交处理,

然后相交来进行判断,

来裁剪了这个叶子节点,看不见的model了者也

对于照相机与平面的判定,如果在平面之前,那么渲染前面平面,
在渲染当前的平面
在渲染后面的平面
如果照相机在平面的后面,那么闲渲染这个后面的节点,在渲染中间的节点了,
再渲染前面的节点了,




5、  按从后到前的顺序渲染透明的面列表

点于这个六个平面的相交来进行判断




渲染器前端

R_LoadEntities
加载了这个entity物体了者也


quake3的bsp这个文件里面里面的这个解析出来了这个灯光的处理,灯光的类型,是不是进行这个
然后对于这个灯在渲染时,来进行这个光照


其他的静态的模型乃是使用这个bsp文件里面存储的这个model者也!
对于静态模型的这个处理怎么回事者也!
对于这个模型等等的这个处理怎么来处理的呢?



对于更新的这个entity,游戏逻辑部分发过来的这个粒子系统这个的更新的处理等等
然后bsp file->winding
model->mesh
flare->addflare者也
然后历经这个view的各项裁剪,例如box裁剪,sphere裁剪,等等各项裁剪者也

 render->根据配置文件的来配置opengl->设置视口大小->加载bsp文件

->根据 玩家位置,计算pvs潜在可视集->来找到这个brush的处理等等

+md3 model所有的这个多边形者也!


这里还可以加上了这个玩家武器发出的这个粒子系统者也!

找到玩家所在的房间及邻居房间+敌人模型或表示物体的模型->

  (1)表示房间多边形 数目(2)表示物体的多  边 形,(3)光源数目等等->

(1)将表示房间的多边形与表示物体或人物模型的多边形组合到一起

(2)在确定完玩家潜在能看到的多边形后->

 对于玩家生成平截头体,根据平截头体,再进一步裁剪pvs中看不见的多边形,

  剩下的多边形其实就是一幁所要处理的东西了->

     将多边形进行排序,对不透明的多边形从前往后渲染,从后往前对透明的多边形先渲染->

   当对于多边形阶段完了后,对多边形进行细分->

然后对于这一部分的顶点,进行细分者也
winding细分,mesh细分,网格的细分者也





后端阶段
这个裁剪的处理了,对于在平面的处理

裁剪的curve的处理,对于brush的处理了


R_AddMarkFragments

把这些子弹的痕迹做成了这个段的处理了
 R_BoxSurfaces_r


R_ColorShiftLightingBytes
这个颜色挪移的位了者也



渲染器后端
// all of the information needed by the back end must be
// contained in a backEndData_t.  This entire structure is
// duplicated so the front and back end can run in parallel
// on an SMP machine
typedef struct {
drawSurf_t drawSurfs[MAX_DRAWSURFS];
dlight_t dlights[MAX_DLIGHTS];
trRefEntity_t entities[MAX_ENTITIES];
srfPoly_t *polys;//[MAX_POLYS];
polyVert_t *polyVerts;//[MAX_POLYVERTS];
renderCommandList_t commands;
} backEndData_t;
后置处理的这个多边形数量,
还有这个动态灯的数量
还有这个实体的数量等等
这个渲染命令列表者也

RE_AddDynamicLightToScene
增加动态灯光给场景中
RE_AddLightToScene
RE_AddAdditiveLightToScene
渲染场景的处理了

RE_RenderScene
然后渲染了场景

主要是更新的这个brush model

还有这个md3 model模型

还有光源部分的更新处理等等


我明白了这个后置阶段以后,把模型还有场景的信息全部加载进来之后
然后再进行这个细分的处理,细分到了一定的程度

最后到达这个后端阶段者也
多边形数目
光源数目
实体数目、多边形顶点数目
这就是每一幁所能看见的数目者也
每一次都要更新这个三者,最后消除时,直接把构成这个三个数量清0即可者也

在更新的过程中,

对于动态的灯光的更新和对于运动物体的更新等等的处理

MD3

md3文件的处理
/*
========================================================================

.MD3 triangle model file format

========================================================================
*/

#define MD3_IDENT (('3'<<24)+('P'<<16)+('D'<<8)+'I')
#define MD3_VERSION 15

// limits
#define MD3_MAX_LODS 4
#define MD3_MAX_TRIANGLES 8192 // per surface
#define MD3_MAX_VERTS 4096 // per surface
#define MD3_MAX_SHADERS 256 // per surface
#define MD3_MAX_FRAMES 1024 // per model
#define MD3_MAX_SURFACES 32 // per model
#define MD3_MAX_TAGS 16 // per frame

// vertex scales
#define MD3_XYZ_SCALE (1.0/64)

typedef struct md3Frame_s {
vec3_t bounds[2];
vec3_t localOrigin;
float radius;
char name[16];
} md3Frame_t;

typedef struct md3Tag_s {
char name[MAX_QPATH]; // tag name
vec3_t origin;
vec3_t axis[3];
} md3Tag_t;

/*
** md3Surface_t
**
** CHUNK SIZE
** header sizeof( md3Surface_t )
** shaders sizeof( md3Shader_t ) * numShaders
** triangles[0] sizeof( md3Triangle_t ) * numTriangles
** st sizeof( md3St_t ) * numVerts
** XyzNormals sizeof( md3XyzNormal_t ) * numVerts * numFrames
*/
typedef struct {
int ident; // 

char name[MAX_QPATH]; // polyset name

int flags;
int numFrames; // all surfaces in a model should have the same

int numShaders; // all surfaces in a model should have the same
int numVerts;

int numTriangles;
int ofsTriangles;

int ofsShaders; // offset from start of md3Surface_t
int ofsSt; // texture coords are common for all frames
int ofsXyzNormals; // numVerts * numFrames

int ofsEnd; // next surface follows
} md3Surface_t;

typedef struct {
char name[MAX_QPATH];
int shaderIndex; // for in-game use
} md3Shader_t;

typedef struct {
int indexes[3];
} md3Triangle_t;

typedef struct {
float st[2];
} md3St_t;

typedef struct {
short xyz[3];
short normal;
} md3XyzNormal_t;

typedef struct {
int ident;
int version;

char name[MAX_QPATH]; // model name

int flags;

int numFrames;
int numTags;
int numSurfaces;

int numSkins;

int ofsFrames; // offset for first frame
int ofsTags; // numFrames * numTags
int ofsSurfaces; // first surface, others follow

int ofsEnd; // end of file
} md3Header_t;





我怀疑这个乃是使用的这个添加的lod的多边形的处理了者也

MD3模型的格式、导入与骨骼概念动画

 MD3模型就是MD2模型的升级版,是ID公司的游戏引擎Quake3中使用的主模型格式。它的特点主要集中在骨骼概念的引入吧。相关的模型载入类文章:

言归正传吧。其实我觉得MD3模型是一种颇麻烦的模型格式。也许当时骨骼动画还没有大行其道吧,制定模型格式的时候对骨骼概念有了借鉴,但是也只是仅仅限于比较表层的概念:譬如说上层骨骼的运动会影响其下层的骨骼的运动,这种父子关系应该说是骨骼动画中比较核心的东西。MD3实现了这层概念,但是表现出来的却是颇粗糙的:一个怪物模型(MD系列模型主要就是一些人体和怪物)被分成三部分:头部模型、上身模型、下身模型(当然可以说还有一些武器模型)。这三个模型是分别独立的,分别对应一个.md3后缀二进制模型文件和一个.skin后缀文本的材质文件(这些文件名包含head、upper、lower来作区分,显得随意性很大)。

三个模型之间用tag来标记连接点,下身模型(lower)作为基本的父模型,上身模型(upper)则是它的子模型,下身的运动会相应地传递到上身,同样头部模型(head)是上身模型的子模型。怎么样,很简朴的骨骼吧。我们其实很难说MD3它不是骨骼模型,但是说它是又好像觉得太勉强了点——嘛,就是这种状态。动画信息存储在一个以.animation后缀名的文本文件中:

 
  1. sex f
  2. // first frame, num frames, looping frames, frames per second
  3. headoffset -15 0 0
  4. 0   30  0   20      // BOTH_DEATH1
  5. 29  1   0   20      // BOTH_DEAD1
  6. .....
  7. 90  40  0   20      // TORSO_GESTURE
  8. ...
  9. 153 8   8   20      // LEGS_WALKCR
  10. ....

动画只有下身和上身具备,头部和武器等都是连接到上身模型上,跟着它运动的而已。每个数字的意义在开头的注释行说得很清楚了。而其每一行所代表的动画则用后注释的方式标明——是的,即使不标也没关系,不过是隐藏了动画的信息难为使用者而已。(本ZWModelMD3类是根据这些字眼来判断动画归属上半身还是下半身模型的,所以不标则很麻烦。)还好MD系列模型所属的ID公司不是那么小家子的,毕竟连模型格式都那么公开了。MD3模型,即使那么不方便,也算是标记了一个小时代了吧。

MD3模型的格式、导入与骨骼概念动画—OpenGL技术-ZwqXin.mht

说它不方便,首先当然是一个模型就包含那么多个文件:最基本的3个.md3和3个.skin、1个.animation还有纹理(与MD2不同,不再是一个模型一个纹理那样简洁的了),有时候还附加一个或2个.md3的武器模型和对应的材质文件(用.shader文件)。所以标准的做法是把它们集合到一个以模型名字为名字的文件夹中。这里给我的模型管理类引入了路径问题,已经勉强解决了我就不在此提了。

理应MD3的载入类ZWModelMD3与ZModelMD2很相似,但是事实完全8是这样的。我还是得几乎重新写载入部分的代码。其中一个理由很容易理解,存储格式变化颇大(后面慢慢道来);还有一个理由则是现在一个模型要包含三个子部分模型和一个武器模型的集合(可以为0),也就是很多东西都要至少三份了。当然导入上就只是加个循环的简单问题,但是识别文件和连接模型也得花点心思了。

 
  1. //寻找该文件上层文件夹下的md3后缀文件
  2.    int nPartType = 0;
  3. WIN32_FIND_DATA FindData;
  4. memset(szPathFileName, 0, sizeof(szPathFileName));
  5. wcscat_s(szPathFileName, sizeof(szPathFileName) / sizeof(wchar_t), szResDirectory);
  6. wcscat_s(szPathFileName, sizeof(szPathFileName) / sizeof(wchar_t), L"*.md3");
  7. HANDLE hFindHandle = ::FindFirstFile(szPathFileName, &FindData);
  8. if(INVALID_HANDLE_VALUE != hFindHandle)
  9. {
  10.     do 
  11.     {
  12.         nPartType = -1;
  13.         _wcslwr_s(FindData.cFileName, sizeof(FindData.cFileName) / sizeof(wchar_t));
  14.         if(wcsstr(FindData.cFileName, L"head"))
  15.         {
  16.             nPartType = MD3_MAINPART_HEAD;
  17.         }
  18.         else if(wcsstr(FindData.cFileName, L"upper"))
  19.         {
  20.             nPartType = MD3_MAINPART_UPPER;
  21.         }
  22.         else if(wcsstr(FindData.cFileName, L"lower"))
  23.         {
  24.             nPartType = MD3_MAINPART_LOWER;
  25.         }
  26.         if(nPartType >= 0 && nPartType < MD3_MAINPART_COUNT)
  27.         {
  28.             memset(szPathFileName, 0, sizeof(szPathFileName));
  29.             wcscat_s(szPathFileName, sizeof(szPathFileName) / sizeof(wchar_t), szResDirectory);
  30.             wcscat_s(szPathFileName, sizeof(szPathFileName) / sizeof(wchar_t), FindData.cFileName);
  31.             if(0 == _wfopen_s(&m_FilePointer, szPathFileName, L"rb"))
  32.             {
  33.                 if(!ImportSubModel(&m_ModelMainMD3[nPartType], szPathFileName, 
  34.                     (MD3_MAINPART_UPPER == nPartType || MD3_MAINPART_LOWER == nPartType), usage))
  35.                 {
  36.                     return false;
  37.                 }
  38.                 fclose(m_FilePointer);
  39.                 m_FilePointer = NULL;
  40.             }
  41.         }
  42.     } while (::FindNextFile(hFindHandle, &FindData));
  43. }

可以的话我都不想这样做,加了这么多平台相关的代码不说,实在很麻烦(skin文件也是类似的):轮询文件夹下的文件(m_ModelMainMD3[MD3_MAINPART_COUNT]是那三个SubModel),找文件名的关键字(是的,如果你的头部模型文件里没有head这四个字符或者文件夹里有两个以上包含head字符的.md3文件,会把问题弄得很复杂)。ImportSubModel函数与以往一样,导入文件后初始化帧信息和生成VBO。还是从MD3模型格式开始吧:

 
  1. typedef struct tagMd3Header
  2. {
  3.     char  szMagic[4];        // The magic string used to identify the file.
  4.     int32 nVersion;          // The file version number (must be 15).
  5.     char  szFileName[MNAME]; // The file name.
  6.     int32 nFlag;             // The retained flag.
  7.     int32 nNumFrames;        // The number of animated bones' frames.
  8.     int32 nNumTags;          // The number of tags.
  9.     int32 nNumMeshes;        // The number of meshes associated with the model.
  10.     int32 nNumMaxSkin;       // The max number of skins.
  11.     int32 nOffsetFrames;     // The offset in the file for the frames data.
  12.     int32 nOffsetTags;       // The offset in the file for the tags data.
  13.     int32 nOffsetMeshes;     // The offset in the file for the meshes data.
  14.     int32 nFileSize;         // The size of the whole file.
  15. }Md3Header;
  16. //导入结构定义
  17. typedef struct tagBoneFrameInfo
  18. {
  19.     float32 fMinPos[3];
  20.     float32 fMaxPos[3];
  21.     float32 fPos[3];
  22.     float32 fScale;
  23.     char    szCreator[16];
  24. }BoneFrameInfo;
  25. typedef struct tagTagInfo
  26. {
  27.     char  szName[MNAME];
  28.     float32 fTranslation[3];
  29.     float32 fRotation[3][3];
  30. }TagInfo;
  31. typedef struct tagMeshHeaderInfo
  32. {
  33.     char  szMeshID[4];       // The mesh ID.
  34.     char  szMeshName[MNAME]; // The mesh name.
  35.     int32 nFlag;             // The retained flag.
  36.     int32 nNumMeshFrames;    // The number of frames of every mesh(should equal to header's nNumFrames).
  37.     int32 nNumSkins;         // The number of mesh skins.(should equal to 1 ?)
  38.     int32 nNumVertices;      // The number of mesh vertices.
  39.     int32 nNumFaces;         // The number of mesh faces.
  40.     int32 nOffsetFaces;      // The offset from the nOffsetMeshes defined by header, for the faces data.
  41.     int32 nOffsetSkins;      // The offset from the nOffsetMeshes defined by header, for the skins data.
  42.     int32 nOffsetTexcoord;   // The offset from the nOffsetMeshes defined by header, for the texcoords data.
  43.     int32 nOffsetVertices;   // The offset from the nOffsetMeshes defined by header, for the vertices data.
  44.     int32 nMeshInfoSize;     // The size of the whole mesh info data.
  45. }MeshHeaderInfo;
  46. typedef struct tagFaceInfo
  47. {
  48.     int32 nVertIndex[3];
  49. }FaceInfo;
  50. typedef struct tagSkinInfo
  51. {
  52.     char  szName[MNAME];
  53.     int32 nIndex;
  54. }SkinInfo;
  55. typedef struct tagTexcoordInfo
  56. {
  57.     float32 u;
  58.     float32 v;
  59. }TexcoordInfo;
  60. typedef struct tagFrameVertInfo
  61. {
  62.     int16         vertSrc[3];
  63.     unsigned char normalInfo[2]; 
  64. }FrameVertInfo;
  65. //导入结构定义结束

与MD2格式模型一样,一切从文件头Md3Header开始,每个MD3文件开头的sizeof(Md3Header)大小的都是一个这样的文件头,注释部分我参考了网上注解,应该没错吧(如果有错请指出)。与MD2的不同貌似信息少了不少——别担心,后面还有个MeshHeaderInfo呢。Md3Header除了用于标识的MagicWord(IDP3),version(15),没啥用的maxSkin外,最主要的就是三个东西:boneFrame、tag、mesh。在“导入结构定义”部分的头三个,就是这部分信息的数据结构,BoneFrameInfo基本可以不理会,除非你想把骨骼控制点(建模软件里弄骨骼的那些)也渲染出来。TagInfo就是骨骼信息的核心了,每个tag作为一个连接标记,决定了所连接的子模型的位置和运动形式——一个变换矩阵。而MeshHeaderInfo就是我们模型的Base数据了,一个模型由一个或多个网格对象(Mesh)组成,每个网格对象对应单一纹理和VBO信息组,这个与3DS、OBJ类似(参见[用Indexed-VBO渲染3DS模型] [OBJ模型文件的结构、导入与渲染Ⅱ])。每个Mesh段也是开头一个信息头,指涉其所在区域内数据的组织:顶点位置、顶点法线、顶点纹理坐标、顶点索引(Skin信息不用理会,我们使用的是用mesh的名字标识去检索.skin文件内容)。顶点信息(FrameVertInfo)有点怪异,接下来会说说。如果你这时惊讶于为什么还是每帧都一堆顶点属性(这不还是逐帧动画么),你还没弄清楚“骨骼概念”动画与真正的骨骼动画的差距。

再来看看我自定义的保存模型信息的数据结构(再提醒一次,如果你只打算用传统的glVertex打点来绘制而不用VBO,你大可不必这么麻烦地转换,从上述读入的文件"raw信息"已经基本足够提供个给你绘制了,网上也有很多这样的例子吧):

 
  1. // Tag信息
  2. typedef struct tag3DTagFrameInfo
  3. {
  4.     Vector3 fTranslation;
  5.     float   fRotation[3][3];
  6. }t3DTagFrameInfo;
  7. // TagLink挂接模型信息
  8. typedef struct tag3DTagLink
  9. {
  10.     char                  szTagName[MNAME]; // Tag名称
  11.     t3DTagFrameInfo      *pTagFrameInfos;   // 该Tag下各帧的矩阵信息
  12.     std::vector<void *>   LinkingModels;    // 挂接模型
  13. }t3DTagLink;
  14. // 动画信息
  15. typedef struct tag3DAnimation 
  16. {
  17.     unsigned int nStartFrame;
  18.     unsigned int nEndFrame;
  19.     unsigned int nFramesPerSec;
  20. }t3DAnim;
  21. // 模型的帧动画信息
  22. typedef struct tag3DFrameInfo
  23. {
  24.     unsigned int            nCurFrame;  // 当前帧
  25.     unsigned int            nNextFrame; // 下一帧
  26.     unsigned int            nStartFrame;// 开始帧
  27.     unsigned int            nEndFrame;  // 结束帧
  28.     float                   fSecPerKeyFrame;  // 关健帧间隔
  29.     float                   fCurBlendValue;   // 当前融合变量
  30.     DWORD                   DStartPlot;       // 开始时点
  31. }t3DFrameInfo;
  32. // 网格对象信息
  33. typedef struct tag3DObject
  34. {
  35.     char            szName[MNAME];
  36.     GLuint          nDiffuseMap;
  37.     Vector3        *pPosVerts;
  38.     Vector3        *pNormals;
  39.     TexCoord       *pTexcoords;
  40.     unsigned short *pIndexes;
  41.     unsigned int    nNumIndexes;
  42.     unsigned int    nNumVerts;
  43.     unsigned int    nNumPosVBOs;
  44.     GLuint         *pPosVBO;
  45.     GLuint         *pNormVBO;
  46.     GLuint          nTexcoordVBO;
  47.     GLuint          nIndexVBO;
  48. }t3DObject;
  49. // 模型信息结构体
  50. typedef struct tag3DModel 
  51. {
  52.     bool                    bVisable;   // 是否渲染
  53.     bool                    bIsTextured;// 是否使用纹理
  54.     Md3Header               MD3Header;  // MD3头文件
  55.     t3DObject              *pObjects;   // 网格对象
  56.     t3DTagLink             *pLinkModels;// Tag连接的模型
  57.     std::vector    Animations; // 动画列表
  58.     t3DFrameInfo           *pFrameInfo; // 帧信息(只对Upper和Loewer)
  59.     GLuint                  TexObjDiffuseMap; // 纹理所在的纹理对象
  60. }t3DModel;

网格对象t3DObject这个我就不多解释了,结合[OBJ模型文件的结构、导入与渲染Ⅰ]中类似的数据定义,或者看名字都知道了。t3DModel这里除了保存一堆网格对象外,还有一个帧信息t3DFrameInfo,只有上身模型和下身模型才有必要new一个出来:因为它就是用于动画的信息啊(结合一个模型所具有的动画t3DAnim列表[由.animation文件导入])。然后比较新颖的就是这个t3DTagLink结构了吧,它就是保存上述的tag信息了,它保存了tag名字、这个tag在每一动画帧下的用于子模型的变换矩阵信息(位置和旋转),还保存着连接到这个tag的子模型列表(LinkingModels)。

数据的转换应该来说关键只是这些数据结构的定义,实际的转换代码也就那么些赋值转换之类了。这里特别注意的是FrameVertInfo(上面提及过),3个short和2个字节可以表示一个顶点位置和一个法线?ID公司的人就是那么有点犀利——把short除以64来得到位置信息,把两个BYTE归一成(0,1)再乘以360度的弧度来标识球体的经度维度——原点指向该经纬位置的向量,就是我们需要的法线啦!绝!这个我是从GPU GEMS1某个例子里导入MD3模型的代码中发现奇怪的,网上查到解析信息才知道的,不然我可能就忽略它自己去计算粗糙的法线了(毕竟MD2就只能这样)。以下清单的解压缩部分是重点哈~~

 
  1.     typedef struct tagFrameVertInfo
  2.     {
  3.         int16         vertSrc[3];
  4.         unsigned char normalInfo[2]; 
  5.     }FrameVertInfo;
  6. //  读入文件中的对象到模型中
  7. void ZWModelMD3::ProcessFileInfo(t3DModel *pModel)
  8. {
  9.     //Load Tags Data
  10.        .....
  11.     //Load Meshes Data
  12.     pModel->pObjects = new t3DObject[pModel->MD3Header.nNumMeshes];
  13.     MeshHeaderInfo meshHeaderInfo = {0};
  14.     float dLongtitude = 0, dLattitude = 0;
  15.     int32 nCurMeshOffset = pModel->MD3Header.nOffsetMeshes;
  16.     for(int i = 0; i < pModel->MD3Header.nNumMeshes; ++i)
  17.     {
  18.         fseek(m_FilePointer, nCurMeshOffset, SEEK_SET);
  19.         fread_s(&meshHeaderInfo, sizeof(MeshHeaderInfo), sizeof(unsigned char), 
  20.             sizeof(MeshHeaderInfo) / sizeof(unsigned char), m_FilePointer);
  21.         int nTotalVerts = meshHeaderInfo.nNumVertices * pModel->MD3Header.nNumFrames
  22.         FrameVertInfo  *pFrameVertInfo = new FrameVertInfo[nTotalVerts];
  23.   
  24.         pModel->pObjects[i].pPosVerts = new Vector3[nTotalVerts];
  25.         pModel->pObjects[i].pNormals  = new Vector3[nTotalVerts];
  26.         for(int j = 0; j < nTotalVerts; ++j)
  27.         {
  28.             pModel->pObjects[i].pPosVerts[j].set(pFrameVertInfo[j].vertSrc[0] / 64.0f,
  29.                                                  pFrameVertInfo[j].vertSrc[1] / 64.0f,
  30.                                                  pFrameVertInfo[j].vertSrc[2] / 64.0f);
  31.             dLongtitude = pFrameVertInfo[j].normalInfo[0] * 2.0f * MD3_PI / 255;
  32.             dLattitude  = pFrameVertInfo[j].normalInfo[1] * 2.0f * MD3_PI / 255;
  33.             pModel->pObjects[i].pNormals[j].set(cosf(dLattitude) * sinf(dLongtitude), 
  34.                                                 cosf(dLongtitude),
  35.                                                 -sinf(dLattitude) * sinf(dLongtitude));
  36.         }
  37.         delete []pFrameVertInfo;
  38.               //...............
  39.         }
  40. };

现在再来看看怎么连接模型吧(MD3的骨骼概念核心):

 
  1. void ZWModelMD3::LinkModels(t3DModel *pParentModel, t3DModel *pChildModel, char *szTagName)
  2. {
  3.     for(int i = 0; i < pParentModel->MD3Header.nNumTags; ++i)
  4.     {
  5.         if(0 == strcmp(pParentModel->pLinkModels[i].szTagName, szTagName))
  6.         {
  7.             pParentModel->pLinkModels[i].LinkingModels.push_back(pChildModel);
  8.         }
  9.     }
  10. }
  11.     LinkModels(&m_ModelMainMD3[MD3_MAINPART_LOWER], &m_ModelMainMD3[MD3_MAINPART_UPPER], "tag_torso");
  12.     LinkModels(&m_ModelMainMD3[MD3_MAINPART_UPPER], &m_ModelMainMD3[MD3_MAINPART_HEAD],  "tag_head");

后面是ImportModel里的执行代码。其实我们只是在t3DTagLink里保存了子模型的指针而已。下身模型的一个叫“tag_torso”的Tag连接上身模型,上身模型的一个叫“tag_head”的Tag连接头部模型。(顺带一提,上身模型的一个叫“tag_weapon”的Tag一般是用来连接武器模型的[如果有的话]。)我们渲染的时候,其实就是先渲染父模型,再渲染子模型,再渲染子模型的子模型这样下去(每个子模型渲染前都乘以对应连接tag的变换矩阵)……因为是一种树型的调用模式,所以递归出场了(实在兴奋不起来):

 
  1. void ZWModelMD3::DrawModelWithSubModel(t3DModel *pModel, bool bShaderMode)
  2. {
  3.     DrawSubModel(pModel, bShaderMode);
  4.     ZWQuaternion qQuat, qNextQuat, qInterpolatedQuat;
  5.     Vector3 iterpPos;
  6.     ZWMatrix16 mtFin;
  7.     for(int i = 0; i < pModel->MD3Header.nNumTags; ++i)
  8.     {
  9.         if(pModel->pLinkModels[i].LinkingModels.size() > 0 && pModel->pFrameInfo)
  10.         {
  11.             iterpPos = pModel->pLinkModels[i].pTagFrameInfos[pModel->pFrameInfo->nCurFrame].fTranslation;
  12.             iterpPos = iterpPos + (pModel->pLinkModels[i].pTagFrameInfos[pModel->pFrameInfo->nNextFrame].fTranslation
  13.                      - iterpPos) * pModel->pFrameInfo->fCurBlendValue;
  14.             
  15.             qQuat.SetFromMatrixRotationElements(&pModel->pLinkModels[i].pTagFrameInfos[pModel->pFrameInfo->nCurFrame].fRotation[0][0]);
  16.             qNextQuat.SetFromMatrixRotationElements(&pModel->pLinkModels[i].pTagFrameInfos[pModel->pFrameInfo->nNextFrame].fRotation[0][0]);
  17.             qInterpolatedQuat.SlerpFrom(qQuat, qNextQuat, pModel->pFrameInfo->fCurBlendValue);
  18.             qInterpolatedQuat.GenerateMatrix3X3(&mtFin);
  19.             mtFin.SetTranslationPart(ZWVector4D(iterpPos.x, iterpPos.y, iterpPos.z, 1.0f));
  20.             glPushMatrix();
  21.             glMultMatrixf(mtFin.mt);
  22.             for(unsigned int j = 0; j < pModel->pLinkModels[i].LinkingModels.size(); ++j)
  23.             {
  24.                 DrawModelWithSubModel((t3DModel*)pModel->pLinkModels[i].LinkingModels[j], bShaderMode);
  25.             }
  26.             glPopMatrix();
  27.         }
  28.     }
  29. }
  30. //渲染时调用
  31. DrawModelWithSubModel(&m_ModelMainMD3[MD3_MAINPART_LOWER], true);

这部分参考的是GameTutorials, LLC的一个MD3导入教程(因为比较久远,那时候VBO还没出生)。这个教程更重要的是一些tips,譬如导入.animation文件时lower的索引要减去upper索引的首值。还有就是我们插值的方式,我们要进行动画帧间的插值,线性插值的前后应该是对应乘了变换矩阵的点坐标——这样麻烦了点,效果也不好。考虑到我们实际插值的是一个点坐标向量的旋转,所以真●主角出场了——

Quaternion四元数([GimbalLock万向节锁与四元数旋转])!!

这下倒有点兴奋了。我们在上面把Tag信息里相邻两帧的3X3roatation传给ZWQuaternion类生成两个四元数,再利用SLERP四元数球插值(网上参考很多)来弄出中间的代表旋转的四元数——变换回矩阵,加上translation部分,这样就把子模型的位置点坐标转到正确漂亮的位置了!

那你说最底的父模型——下身模型怎么办,没有其他外部的tag信息提供变换矩阵参数给它啊——是的,它的话,唯有线性插值了TAT(建议用shader Mode)。

渲染部分整个代码就跟其他格式模型差不多了,动画部分也可以根据MD2的那套延伸出[MD2格式模型的格式、导入与帧动画](毕竟本质上还是帧动画,只不过渲染上加了个骨骼的概念而已嘛)。导入skin文件其实就是查询匹配模型的网格对象的名字,然后把路径最后的文件名指涉的纹理文件导入为纹理而已;最后给出的是我的.animation文件的导入函数,其实就是上面提及的那个BUG不BUG的东西要注意点。注意,上下身的动画帧总数很多时候是8一样的,连续动画最后模型姿态会变囧的。(其实MD3模型就是上下身各指定一个动画吧,不过除了BOTH的动画外,其他的组合实在很容易让人,擦。)

 
  1. void ZWModelMD3::LoadAnimationInfo()
  2. {
  3.     char strBuff[MAX_LINE]  = {0};
  4.     t3DAnim animation = {0};
  5.     unsigned int numfr = 0, loopfr = 0;
  6.     int nLegFrameFix = -1;
  7.     while (fgets(strBuff, MAX_LINE, m_FilePointer))
  8.     {
  9.         if(!isdigit(strBuff[0]))
  10.         {
  11.             continue;
  12.         }
  13.         if(4 == sscanf_s(strBuff, "%d %d %d %d", &animation.nStartFrame, &numfr, &loopfr, 
  14.             &animation.nFramesPerSec))
  15.         {
  16.             animation.nEndFrame = animation.nStartFrame + numfr;
  17.             if(strstr(strBuff, "BOTH"))
  18.             {
  19.                 m_ModelMainMD3[MD3_MAINPART_UPPER].Animations.push_back(animation);
  20.                 m_ModelMainMD3[MD3_MAINPART_LOWER].Animations.push_back(animation);
  21.             }
  22.             else if(strstr(strBuff, "TORSO"))
  23.             {
  24.                 m_ModelMainMD3[MD3_MAINPART_UPPER].Animations.push_back(animation);
  25.             }
  26.             else if(strstr(strBuff, "LEG"))
  27.             {
  28.                 if(-1 == nLegFrameFix)
  29.                 {
  30.                     nLegFrameFix = animation.nStartFrame - 
  31.                         m_ModelMainMD3[MD3_MAINPART_UPPER].Animations[0].nStartFrame;
  32.                 }
  33.                 animation.nStartFrame -= nLegFrameFix;
  34.                 animation.nEndFrame   -= nLegFrameFix;
  35.                 m_ModelMainMD3[MD3_MAINPART_LOWER].Animations.push_back(animation);
  36.             }
  37.         }
  38.     }
  39. }

就这样结束吧。老实说,MD3这么麻烦,要不是为了学习性连贯点,我就该直奔MD5去了。



model模型动画的处理



从bsp文件中的静态的md3 mesh模型,和这个游戏过程中加载的这个敌人的md3模型的处理等等

lod = (md4LOD_t *)( (byte *)header + header->ofsLODs );
这个家伙这个lod的这个处理,原来这个md4文件这个东西乃是骨骼的处理了
还有这个md3文件乃是这个网格的处理了

增加了这个动画的曲面surface
/ lerp all the needed bones

插值这个
header = (md4Header_t *)((byte *)surface + surface->ofsHeader);

frameSize = (int)( &((md4Frame_t *)0)->bones[ header->numBones ] );

frame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
backEnd.currentEntity->e.frame * frameSize );
oldFrame = (md4Frame_t *)((byte *)header + header->ofsFrames + 
backEnd.currentEntity->e.oldframe * frameSize );

RB_CheckOverflow( surface->numVerts, surface->numTriangles * 3 );

triangles = (int *) ((byte *)surface + surface->ofsTriangles);
indexes = surface->numTriangles * 3;
baseIndex = tess.numIndexes;
baseVertex = tess.numVertexes;
for (j = 0 ; j < indexes ; j++) {
tess.indexes[baseIndex + j] = baseIndex + triangles[j];
}
tess.numIndexes += indexes;

//
// lerp all the needed bones
//
if ( !backlerp ) {
// no lerping needed
bonePtr = frame->bones;
} else {
bonePtr = bones;
for ( i = 0 ; i < header->numBones*12 ; i++ ) {
((float *)bonePtr)[i] = frontlerp * ((float *)frame->bones)[i]
+ backlerp * ((float *)oldFrame->bones)[i];
}
}


模型如果是水的波浪的话

对于水波浪的移动,根据法线来计算水波的颜色,从而来显示这个水面的颜色者也

波浪阶段wave的形式有几种

sin,三角形,四边形,还有其他的形,来处理者也,

根据shader文件中记录的这个wave的类型,来进行这个相应的水波的选择,来绘制

水波的移动,根据这个法线来计算水面的颜色

这个乃是使用的这个shader文件里面的东西者也


渲染器后端的处理

决定下了这个视口内部要渲染的多边形数目以后


光照的处理

渲染时,光源只有平移,缩放,旋转等状态,

从bsp这个地图的文件中找到了这个light,提取了出来了者也,
然后对于这个light的处理了这样

灯的闪烁,




环境光照
doom3源码中使用的这个环境贴图来进行环境光的处理


游戏中的光照

基本几何体的光照,
更新动态的光源,静态的光源不必要进行更新的处理了者也
主要是brush上面的光照

分为两种情况,
doom3中已经变成了这个逐像素的光照了
 
         
灯光
有两种类型的灯,在doom3关卡的编辑器按这个j来处理这个
这个点光源
Projected lights投影的灯
和   
点光源
原来这个doom3这么多的东西啊
这个vfg格式是什么呢??
这个乃是什么的呢?
// uplight the entire screen to crutch up not having better blending range
RB_STD_LightScale();
// now draw any non-light dependent shading passes
int processed = RB_STD_DrawShaderPasses( drawSurfs, numDrawSurfs );
// fob and blend lights
RB_STD_FogAllLights();
// now draw any post-processing effects using _currentRender
if ( processed < numDrawSurfs ) {
RB_STD_DrawShaderPasses( drawSurfs+processed, numDrawSurfs-processed );
}
RB_RenderDebugTools( drawSurfs, numDrawSurfs 
对于这个雾的处理和这个混合光的处理了等等

光源上使用一个包围体进行对光源的距离进行遮挡,

阴影,的处理,阴影

光照,

光照的处理了

 根据灯到这个entity的这个网格的距离,来计算这个normal的处理,是否大于小于0,怎么来处理

静态的灯光,和这个静态的网格

动态的灯光

(后端:主要是这个是渲染了)

3 对于光源渲染,预渲染的与实时渲染的相结合。给光源也生成一个平截头体,

给实体也生成一个平截头体,用来判断光源能照到那些实体entity,预渲染与实时渲染都是这么办的。

能照到的物体,使用这个光照方程进行光照的,前向光照的。

把光源照射到物体的反射光,镜面光的值传入到纹理,从entity的高度图里抽取出法线来,进行渲染的,

对于场景的这个每个face面,判断这个与法线的这个叉积的结果是不是0,从而来判断这个结果,
是不是向上,来判断这个face的面的方向的处理
然后对着进行这个光线与之的判断,
最后,五层贴图的处理,
漫反射,镜面反射,法线等等的一个处理了者也
各种纹理贴图的一个处理了者也
互相组合的一个过程了者也

const float n = dotDir0Dir2 * dotDir1Dir2 - dotDir0Dir1 * dotDir2Dir2;

const float t1 = n / d;

const float t1c = idMath::ClampFloat( 0.0f, 1.0f, t1 );

const float t2 = ( dotDir0Dir2 + dotDir1Dir2 * t1 ) / dotDir2Dir2;

const float t2c = idMath::ClampFloat( 0.0f, 1.0f, t2 );

const idVec3 closest1 = start1 + ( dir1 * t1c );

const idVec3 closest2 = start2 + ( dir2 * t2c );

const float distSqr = ( closest2 - closest1 ).LengthSqr();

return distSqr;

// test if the line passes through the triangle

这家伙要测试光线能否穿过三角形,怎么做到的呢?

// if determinant is near zero then the ray lies in the triangle plane

决定这个光线是不是在这个三角形平面的上下?

#define TEMP_ROUND4( x ) ( ( x + 3 ) & ~3 ) // round up to a multiple of 4 for SIMD

光线追踪的处理
// create two planes orthogonal to each other that intersect along the trace
startDir = end - start;
startDir.Normalize();
startDir.NormalVectors( planes[0].Normal(), planes[1].Normal() );
planes[0][3] = - start * planes[0].Normal();
planes[1][3] = - start * planes[1].Normal();
创建两个平面正视投影,来对于各自插入了光追了者也
开始平面
// create front and end planes so the trace is on the positive sides of both
planes[2] = startDir;
planes[2][3] = - start * planes[2].Normal();
planes[3] = -startDir;
planes[3][3] = - end * planes[3].Normal();

lobal Keywords for light materials

全局的这个键值对于灯光的材质的处理等等

noShadows这个上面没有阴影的有没有

forceShadows

fog, blend, and ambient lights don't cast shadows by default. This forces them to cast shadows

noPortalFog

fogLight雾里面有没有灯光了

blendLight混合的灯光了者也

ambientLight

lightFalloffImage

对于这个图像的升采样和这个降采样的处理
dxt压缩的一个处理
遮挡查询的处理了
对于这个opengl的这个错误的各种的信息的输出等等
dds图像的处理了者也
dxt1,dxt5的处理

// If the line from localLight to localView intersects the geometry

// bounding box then the view is inside the infinite shadow projection.

局部的光照了啊?
难道还有这个全局的光照了?

在局部坐标系,和这个全局的坐标系

 

阴影部分

对于纹理,阴影,混合等等全部的使用了阴影来进行这个的处理了者也

对于阴影椎算法,有两种算法的,z-pass,z-fail算法的,z-fail算法适用于各种情况,而z-fail算法则在某些情况下不通用了者也
在照相机位于这个阴影体外面的时候,这个算法将会产生了这个错误的结果了者也,
我们如果将这个如果深度测试失败的话,则将其写入了模板缓存,同时将这个计数的增加和减少相互替换的话,
那么这种方法就叫做这个z-fail(或者是camack倒置法),这个方法在任何情况下通同的,
但是,z-fail方法必须处理这个在阴影体的前端和这个后端进行闭合,而且对于粒子,公告板等等东西都不顶用的,必须填充这个阴影体的处理了者也
对于所有的物体无限远处,把物体
生成阴影体,
渲染前端面
渲染后端面
渲染对象的轮廓了者也

对于静态的物体,预先计算阴影,动态的生成一个阴影体来生成阴影。

对于动态的阴影

Doom3 阴影部分使用idBound这个包围体对物体,模型进行一次包围,

使得进入到模版缓冲区的数据减少,然后再进行模板测试,

对于物体来说,所有能照着物体的光源逐个的进行阴影处理

对于阴影面的轮廓的绘制的处理了

 

阴影处理

分为三种阴影,预处理阴影,静态阴影,动态阴影三种情况的处理了

对于area的这个bsp树的这个 node节点的这个包围盒的处理

我怀疑这个来判断

 时刻要判断玩家位置和构成这个物体的包围盒的比较了者也

先生成了这个阴影体的最大值和这个最小值,如果与照相机的位置来进行比较

,判断是不是需要使用这个z-fail方法来渲染,照相机位置在包围盒外部的话,那么使用的z-pass来进行绘制

如果在包围盒内部的话,使用z-fail来进行绘制

如果

// The shadow volume may be depth culled if either the shadow volume was culled to the view frustum or if the

// depth range of the visible part of the shadow volume is outside the depth range of the light volume.

然后写入了这个阴影的索引值了者也

如果阴影体需要z-fail的话,那么写入了这个阴影索引

// write out the shadow volume state

预处理阴影
预处理阴影
给物体预先生成生成了阴影体
一个预处理的阴影乃是一个静态的光源,照射一个静态的环境的时候形成的阴影体的处理

Pre-Light Shadow Volume Setup

A pre-light shadow is cast from static world geometry touching a static light.

A pre-light shadow volume does not extend to infinity but is capped at the light

boundaries which means the end caps always need to be rendered.

A pre-light shadow volume is created at map compile time and this job determines whether or

not the shadow volume needs to be rendered with Z-Fail.

一个预处理的阴影体应该是在地图编译时候,来进行阴影的处理的,

并且job来决定这个那部分需要这个是用z-fail来进行渲染的处理的

静态生成了阴影体

对于游戏中的这个静态的灯 生成了阴影

,也是用这个方法来判断是不是要生成了这个阴影了者也

Static Shadow Volume Setup

A static shadow is cast from a static model touching a static light.

A static shadow volume extends to infinity which allows the end caps to be omitted

when the view is outside and far enough away from the shadow volume.

A static shadow volume is created at map load time and this job determines whether or

not the end caps need to be rendered, whether or not the shadow volume needs to be

rendered with Z-Fail, and optionally calculates the shadow volume depth bounds.

动态生成了阴影体的处理

先生成了这个阴影体的最大值和这个最小值,如果与照相机的位置来进行比较

,判断是不是需要使用这个z-fail方法来渲染,照相机位置在包围盒外部的话,那么使用的z-pass来进行绘制

如果在包围盒内部的话,使用z-fail来进行绘制

动态的这个阴影体的生成部分
由于这个阴影体的这个机器消耗了cpu的处理了,所有必须进行这个优化的
是用sse simd指令集来计算这个三角形是不是朝向了光源
CalculateTriangleFacingCulledStatic
计算灯光的起点,终点,来生成了一条光线
来计算有多少个三角形在灯光的前面,
有多少个三角形在这个灯光的后面了者也
计算三角形是不是是被裁剪了者也
/*
=====================
DynamicShadowVolumeJob
Creates shadow volume indices for a surface that intersects a light.
Optionally also creates new surface indices with just the triangles
inside the light volume. These indices will be unique for a given
light / surface combination.
创建一个阴影体索引,从一个surface灯光,优化,创建
The shadow volume indices are created using the original surface vertices.
However, the indices are setup to be used with a shadow volume vertex buffer
with all vertices duplicated where the even vertices have the same positions
as the surface vertices (at the near cap) and each odd vertex has the
same position as the previous even vertex but is projected to infinity
(the far cap) in the vertex program.
// Calculate the shadow depth bounds.
计算这个阴影的深度盒子
int numLightIndices = 0;
R_ViewPotentiallyInsideInfiniteShadowVolume
If we know that we are "off to the side" of an infinite shadow volume,
we can draw it without caps in Z-pass mode.
判断这个在阴影体的内部还是外部
如果在这个阴影体的外部,我们使用这个z-pass模式来进行这个阴影体的渲染了者也

使用多重jetter来使得阴影模糊

(这个代码的分析包括了这个doom3和doom3bfg的代码分析了者也)

加入了 bloom,抖动等等技术,对于图像的模糊者也

 

5 对于屏幕的2D部分,也就是屏幕下方的生命值,弹药数目。

武器值等进行渲染。

切换渲染命令为渲染2D。

转换投影方式为正投影,来渲染文字,图片等信息

doom3bfg的这个是用的这个glsl这个,来进行编程,写的这个shader语句来进行的者也
将cg转化了glsl语句了者也
将所有的这个参数,矩阵等等的准备工作了者也
加载所有的这个shader文件,然后在进行这个关于shader文件的编译了者也
对于render log文件的处理了者也
doom3源码的一些东西随笔
这个turque这个对于粉刷道路,种植树木等等这个太好了者也

 doom3中的这个guimodel的处理了

对于图像的处理了,
加上了这个直方图,还有这个
Interaction between static entityDef surfaces and a static lightDef.
Interactions with no lightTris and no shadowTris are still
valid, because they show that a given entityDef / lightDef
do not interact, even though they share one or more areas.
这个裁剪位的处理了
// For each vertex a byte with the bits [0-5] set if the
// vertex is at the back side of the corresponding clip plane.
// If the 'cullBits' pointer equals LIGHT_CULL_ALL_FRONT all
// vertices are at the front of all the clip planes.
// Clip planes in surface space used to calculate the cull bits.
idPlane localClipPlanes[6];
裁剪平面来计算这个裁剪位的处理了
// Pre-generated shadow volumes from dmap are not present in surfaceInteraction_t,
// they are added separately.
// shadow volume triangle surface
如果已经有了阴影的话
如果做空的处理
静态的这个Interaction
// get space from here, if NULL, it is a pre-generated shadow volume from dmap
Determines which triangles of the surface are facing towards the light origin.
The facing array should be allocated with one extra index than
the number of surface triangles, which will be used to handle dangling
edge silhouettes.
决定这个三角形的面是不是朝向了这个灯的起点了,朝向,如果不朝向光照,那么无需计算这个的光照了者也
如果朝向,那么需要计算这个网格点的光照了者也
全局阴影,局部的阴影的处理了
R_GlobalPointToLocal
const float d = plane.Distance( localLightOrigin );
cullInfo.facing[face] = ( d >= 0.0f );
R_CalcInteractionCullBits
We want to cull a little on the sloppy side, because the pre-clipping
of geometry to the lights in dmap will give many cases that are right
at the border. We throw things out on the border, because if any one
vertex is clearly inside, the entire triangle will be accepted.
=====================
裁剪这个三角形曲面的包围盒
// cull the triangle surface bounding box
R_CreateInteractionLightTris
This is only used for the static interaction case, dynamic interactions
just draw everything and let the GPU deal with it.
The resulting surface will be a subset of the original triangles,
it will never clip triangles, but it may cull on a per-triangle basis.
// if any surface is a shadow-casting perforated or translucent surface, or the
// base surface is suppressed in the view (world weapon shadows) we can't use
// the external shadow optimizations because we can see through 
=====================
R_CreateInteractionShadowVolume
Note that dangling edges outside the light frustum don't make silhouette planes because
a triangle outside the light frustum is considered facing and the "fake triangle" on
the outside of the dangling edge is also set to facing: cullInfo.facing[numFaces] = 1;
预处理
增加阴影
这家伙对于entity来进行排序,判断是不是这个entity,还是这个area,还是这个动态的东西了者也

// Move the draw surfs to the view.

// Kick off jobs to setup static and dynamic shadow volumes.
让这个job来决定这个是不是静态的阴影或者是动态的阴影椎了
// surface light interactions
// check for a static interaction
检查一个静态的
原来光照这个也是分为静态,动态,还有预处理的啊
// try to do a more precise cull of this model surface to the light
if ( R_CullModelBoundsToLight( lightDef, tri->bounds, entityDef->modelRenderMatrix ) ) {
continue;
}
// Find which of the visible lights contact this entity
//
// If the entity doesn't accept light or cast shadows from any surface,
// this can be skipped.
//
// OPTIMIZE: world areas can assume all referenced lights are used
R_AddSingleModel
May be run in parallel.
Here is where dynamic models actually get instantiated, and necessary
interaction surfaces get created. This is all done on a sort-by-model
basis to keep source data in cache (most likely L2) as any interactions
and shadows are generated, since dynamic models will typically be lit by
two or more lights.
// process the shader expressions for conditionals / color / texcoords
RB_DrawBounds
现在想一想,我何尝不是给人误导了,盲目的去学习什么高新技术,实际上,错误的,真正的开发中那里又那么多的高新技术?
真是搞笑
RB_SimpleSurfaceSetup
// light interaction overdraw
Debugging tool to see how much dynamic range a scene is using.
The greatest of the rgb values at each pixel will be used, with
the resulting color shading from red at 0 to green at 128 to blue at 255
RB_ShowLightCount
This is a debugging tool that will draw each surface with a color
based on how many lights are effecting it
===============
RB_EnterWeaponDepthHack
RB_TestImage();
RB_ShowPortals();
RB_ShowSilhouette();
RB_ShowDepthBuffer();
RB_ShowIntensity();
RB_ShowCenterOfProjection();
RB_ShowLines();
RB_ShowDebugLines();
RB_ShowDebugText();
RB_ShowDebugPolygons();
RB_ShowTrace( drawSurfs, numDrawSurfs );
RB_ShowLightCount();
RB_ShowTexturePolarity( drawSurfs, numDrawSurfs );
RB_ShowTangentSpace( drawSurfs, numDrawSurfs );
RB_ShowVertexColor( drawSurfs, numDrawSurfs );
RB_ShowTris( drawSurfs, numDrawSurfs );
RB_ShowUnsmoothedTangents( drawSurfs, numDrawSurfs );
RB_ShowSurfaceInfo( drawSurfs, numDrawSurfs );
RB_ShowEdges( drawSurfs, numDrawSurfs );
RB_ShowNormals( drawSurfs, numDrawSurfs );
RB_ShowViewEntitys( backEnd.viewDef->viewEntitys );
RB_ShowLights();
RB_ShowTextureVectors( drawSurfs, numDrawSurfs );
RB_ShowDominantTris( drawSurfs, numDrawSurfs );
TRIANGLE MESH PROCESSING
The functions in this file have no vertex / index count limits.
Truly identical vertexes that match in position, normal, and texcoord can
be merged away.
Vertexes that match in position and texcoord, but have distinct normals will
remain distinct for all purposes.  This is usually a poor choice for models,
as adding a bevel face will not add any more vertexes, and will tend to
look better.
Match in position and normal, but differ in texcoords are referenced together
for calculating tangent vectors for bump mapping.
Artists should take care to have identical texels in all maps (bump/diffuse/specular)
in this case
Vertexes that only match in position are merged for shadow edge finding.
Degenerate triangles.
Overlapped triangles, even if normals or texcoords differ, must be removed.
for the silhoette based stencil shadow algorithm to function properly.
Is this true???
Is the overlapped triangle problem just an example of the trippled edge problem?
Interpenetrating triangles are not currently clipped to surfaces.
Do they effect the shadows?
if vertexes are intended to deform apart, make sure that no vertexes
are on top of each other in the base frame, or the sil edges may be
calculated incorrectly.
We might be able to identify this from topology.
Dangling edges are acceptable, but three way edges are not.
Are any combinations of two way edges unacceptable, like one facing
the backside of the other?
Topology is determined by a collection of triangle indexes.
The edge list can be built up from this, and stays valid even under
deformations.
Somewhat non-intuitively, concave edges cannot be optimized away, or the
stencil shadow algorithm miscounts.
Face normals are needed for generating shadow volumes and for calculating
the silhouette, but they will change with any deformation.
Vertex normals and vertex tangents will change with each deformation,
but they may be able to be transformed instead of recalculated.
bounding volume, both box and sphere will change with deformation.
silhouette indexes
shade indexes
texture indexes
  shade indexes will only be > silhouette indexes if there is facet shading present
lookups from texture to sil and texture to shade?
The normal and tangent vector smoothing is simple averaging, no attempt is
made to better handle the cases where the distribution around the shared vertex
is highly uneven.
  we may get degenerate triangles even with the uniquing and removal
  if the vertexes have different texcoords.
/*
=================
R_ReverseTriangles
Lit two sided surfaces need to have the triangles actually duplicated,
they can't just turn on two sided lighting, because the normal and tangents
are wrong on the other sides.
This should be called before R_CleanupTriangles
=================
反转多边形的处理,
my god!doom3源代码真的是非常的复杂的啊
===================
R_InitDrawSurfFromTri
DEFORMED SURFACES
R_CreateVertexNormals
void R_DeriveUnsmoothedNormalsAndTangents( srfTriangles_t * tri )
R_DeriveNormalsAndTangents
Derives the normal and orthogonal tangent vectors for the triangle vertices.
For each vertex the normal and tangent vectors are derived from all triangles
using the vertex which results in smooth tangents across the mesh.
============
这家伙对于切线来进行处理的啊
// polygonOffset
// {
// map invertColor( textures/splat )
// blend GL_ZERO GL_ONE_MINUS_SRC
// vertexColor
// clamp
// }
Overlays are used for adding decals on top of dynamic models.
Projects an overlay onto deformable geometry and can be added to
a render entity to allow decals on top of dynamic models.
This does not generate tangent vectors, so it can't be used with
light interaction shaders. Materials for overlays should always
be clamped, because the projected texcoords can run well off the
texture since no new clip vertexes are generated.
Overlays with common materials will be merged together, but additional
overlays will be allocated as needed. The material should not be
one that receives lighting, because no interactions are generated
for these lightweight surfaces.
overlays的这个处理方法了者也

全局坐标系和这个本地的坐标系的处理了者也

阴影椎的裁剪位

R_SegmentToSegmentDistanceSquare

段距离的平方的处理

This deals with column-major (OpenGL style) matrices where transforms are

applied with right-multiplication.

This is the old DOOM3 matrix code that should really to be replaced with idRenderMatrix.

==========================================================================================

*/

矩阵的处理了者也

全局矩阵转化了这个局部矩阵的处理

多重矩阵的处理了者也

void R_AxisToModelMatrix( const idMat3 &axis, const idVec3 &origin, float modelMatrix[16] );

void R_MatrixTranspose( const float in[16], float out[16] );

void R_MatrixMultiply( const float *a, const float *b, float *out );

void R_TransformModelToClip( const idVec3 &src, const float *modelMatrix, const float *projectionMatrix, idPlane &eye, idPlane &dst );

void R_TransformClipToDevice( const idPlane &clip, idVec3 &ndc );

void R_GlobalToNormalizedDeviceCoordinates( const idVec3 &global, idVec3 &ndc );

// note that these assume a normalized matrix, and will not work with scaled axis

void R_GlobalPointToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out );

void R_LocalPointToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out );

void R_GlobalVectorToLocal( const float modelMatrix[16], const idVec3 &in, idVec3 &out );

void R_LocalVectorToGlobal( const float modelMatrix[16], const idVec3 &in, idVec3 &out );

void R_GlobalPlaneToLocal( const float modelMatrix[16], const idPlane &in, idPlane &out );

void R_LocalPlaneToGlobal( const float modelMatrix[16], const idPlane &in, idPlane &out );

void R_SetupViewMatrix( viewDef_t *viewDef );

void R_SetupProjectionMatrix( viewDef_t *viewDef );

对于的cg的加载的处理

shader文件部分的处理了

顶点矩阵,参数的处理了者也

图像的program的处理,例如旋转图像,mipmaps等等的处理了

R_InitFrameData

对于这个幁缓存的处理了者也

// sort the draw surfs based on:

// 1. sort value (largest first)

// 2. depth (smallest first)

// 3. index (largest first)

对于所有的surface来进行排序
深度
索引的处理
渲染视图了者也
R_RenderView
A view may be either the actual camera view,
a mirror / remote location, or a 3D view on a gui surface.
Parms will typically be allocated with R_FrameAlloc
// make sure that interactions exist for all light / entity combinations that are visible
// add any pre-generated light shadows, and calculate the light shader values
R_AddLights();
// adds ambient surfaces and create any necessary interaction surfaces to add to the light lists
R_AddModels();
// build up the GUIs on world surfaces
R_AddInGameGuis( tr.viewDef->drawSurfs, tr.viewDef->numDrawSurfs );
// any viewLight that didn't have visible surfaces can have it's shadows removed
R_OptimizeViewLightsList();
// sort all the ambient surfaces for translucency ordering
R_SortDrawSurfs( tr.viewDef->drawSurfs, tr.viewDef->numDrawSurfs );
增加了模型,增加灯,增加了这个gui,增加了
排序的处理了
// add the rendering commands for this viewDef
R_AddDrawViewCmd( parms, false );
R_AddDrawPostProcess( parms );
enum cacheType_t {
CACHE_VERTEX,
CACHE_INDEX,
CACHE_JOINT
};
对于幁数据的处理
idFrameData smpFrameData[NUM_FRAME_DATA];
case DI_REMOTE_RENDER:
 R_RemoteRender( drawSurf, const_cast(&stage->texture) );
break;
case DI_MIRROR_RENDER:
 R_MirrorRender( drawSurf, const_cast(&stage->texture), scissor );
break;
case DI_XRAY_RENDER:
  R_XrayRender( drawSurf, const_cast(&stage->texture), scissor );
break;
这个东西真的是不好搞了者也,太难了者也
idCVar r_drawEyeColor( "r_drawEyeColor", "0", CVAR_RENDERER | CVAR_BOOL, "Draw a colored box, red = left eye, blue = right eye, grey = non-stereo" );
idCVar r_motionBlur( "r_motionBlur", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 - 5, log2 of the number of motion blur samples" );
idCVar r_forceZPassStencilShadows( "r_forceZPassStencilShadows", "0", CVAR_RENDERER | CVAR_BOOL, "force Z-pass rendering for performance testing" );
idCVar r_useStencilShadowPreload( "r_useStencilShadowPreload", "1", CVAR_RENDERER | CVAR_BOOL, "use stencil shadow preload algorithm instead of Z-fail" );
idCVar r_skipShaderPasses( "r_skipShaderPasses", "0", CVAR_RENDERER | CVAR_BOOL, "" );
idCVar r_skipInteractionFastPath( "r_skipInteractionFastPath", "1", CVAR_RENDERER | CVAR_BOOL, "" );
idCVar r_useLightStencilSelect( "r_useLightStencilSelect", "0", CVAR_RENDERER | CVAR_BOOL, "use stencil select pass" );
这个太复杂了真的是,
idCVar r_drawEyeColor( "r_drawEyeColor", "0", CVAR_RENDERER | CVAR_BOOL, "Draw a colored box, red = left eye, blue = right eye, grey = non-stereo" );
idCVar r_motionBlur( "r_motionBlur", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 - 5, log2 of the number of motion blur samples" );
idCVar r_forceZPassStencilShadows( "r_forceZPassStencilShadows", "0", CVAR_RENDERER | CVAR_BOOL, "force Z-pass rendering for performance testing" );
idCVar r_useStencilShadowPreload( "r_useStencilShadowPreload", "1", CVAR_RENDERER | CVAR_BOOL, "use stencil shadow preload algorithm instead of Z-fail" );
idCVar r_skipShaderPasses( "r_skipShaderPasses", "0", CVAR_RENDERER | CVAR_BOOL, "" );
idCVar r_skipInteractionFastPath( "r_skipInteractionFastPath", "1", CVAR_RENDERER | CVAR_BOOL, "" );
idCVar r_useLightStencilSelect( "r_useLightStencilSelect", "0", CVAR_RENDERER | CVAR_BOOL, "use stencil select pass" );
这个怎么来处理了者也,怎么来处理了者也
到我现在看来,
这个真的是必须内功深厚,理解不好处理的者也
必须内功相当的深厚了者也
生成了材质material的这个处理
typedef enum {
TF_LINEAR,
TF_NEAREST,
TF_DEFAULT // use the user-specified r_textureFilter
} textureFilter_t;
typedef enum {
TR_REPEAT,
TR_CLAMP,
TR_CLAMP_TO_ZERO, // guarantee 0,0,0,255 edge for projected textures
TR_CLAMP_TO_ZERO_ALPHA // guarantee 0 alpha edge for projected textures
} textureRepeat_t;
typedef struct {
int stayTime; // msec for no change
int fadeTime; // msec to fade vertex colors over
float start[4]; // vertex color at spawn (possibly out of 0.0 - 1.0 range, will clamp after calc)
float end[4]; // vertex color at fade-out (possibly out of 0.0 - 1.0 range, will clamp after calc)
} decalInfo_t;
对于先是图像,然后再做成了这个material的这个材质的处理了啊
通过过滤,裁剪,替换等等方式来做成了这个方式的处理了啊
enum hdmi3DState_t {
HDMI3D_NOT_SUPPORTED, // The TV doesn't support it
HDMI3D_NOT_ENABLED, // The TV supports it, but the user disabled it
HDMI3D_NOT_ACTIVE, // The TV supports it, and the user enabled it, but it's not active
HDMI3D_ACTIVE
};
enum textureType_t {
TT_DISABLED,
TT_2D,
TT_CUBIC
};
纹理的处理了者也
enum textureFormat_t {
FMT_NONE,
//------------------------
// Standard color image formats
//------------------------
FMT_RGBA8, // 32 bpp
FMT_XRGB8, // 32 bpp
//------------------------
// Alpha channel only
//------------------------
// Alpha ends up being the same as L8A8 in our current implementation, because straight 
// alpha gives 0 for color, but we want 1.
FMT_ALPHA,
//------------------------
// Luminance replicates the value across RGB with a constant A of 255
// Intensity replicates the value across RGBA
//------------------------
FMT_L8A8, // 16 bpp
FMT_LUM8, //  8 bpp
FMT_INT8, //  8 bpp
//------------------------
// Compressed texture formats
//------------------------
FMT_DXT1, // 4 bpp
FMT_DXT5, // 8 bpp
//------------------------
// Depth buffer formats
//------------------------
FMT_DEPTH, // 24 bpp
//------------------------
//
//------------------------
FMT_X16, // 16 bpp
FMT_Y16_X16, // 32 bpp
FMT_RGB565, // 16 bpp
};
int BitsForFormat( textureFormat_t format );
纹理居然有这么多的处理了啊
真的没有想的到的啊!
enum textureColor_t {
CFM_DEFAULT, // RGBA
CFM_NORMAL_DXT5, // XY format and use the fast DXT5 compressor
CFM_YCOCG_DXT5, // convert RGBA to CoCg_Y format
CFM_GREEN_ALPHA // Copy the alpha channel to green
};
typedef struct {
idImage *image;
int size;
int index;
} sortedImage_t;
这个对于材质来进行这个的排序处理了者也
尺寸的处理,
R_ListImages_f
uncompressed
对于这个图像的处理了者也

对于纹理部分

renderStream的处理

无论动静,对于纹理部分,doom3最多包含有有五层纹理,specular,bump,falloff,Diffuse

等等五层的纹理,进入五个顶点编程渲染的状态 GL_VERTEX_PROGRAM_ARB ,

对于NVIDIA的硬件,对于amd的使用amd的硬件扩展,对于其他的硬件,

则使用OpenGL的GL_VERTEX_PROGRAM_ARB扩展,因为这个是OpenGL通用的扩展,通用的

ARB (minimum extensions, no specular highlights, no vertex programs), 
R200 (full featured, almost always single pass interaction rendering), 
ARB2 (floating point fragment shaders, minor quality improvements, always single pass).

对于纹理的状态,具有两层,三层,五层等等纹理状态,

来分别来进行渲染的处理了者也

这个材质图片的处理,

材质居然有如此多的东西啊
加载的mgr材质的文件
将quake3的shader文件转化为了这个材质文件的mgr文件了者也
材质的属性的处理
 
             

Image Program Functions

图像的编程函数

These can be used anywhere that accepts and can be nested

heightmap(, ) Turns a grayscale height map into a normal map. varies the bumpiness
addnormals(, ) Adds two normal maps together. Result is normalized.
smoothnormals() Does a box filter on the normal map, and normalizes the result.
add(, ) Adds two images without normalizing the result
scale(, [,float] [,float] [,float]) Scales the RGBA by the specified factors. Defaults to 0.
invertAlpha() Inverts the alpha channel (0 becomes 1, 1 becomes 0)
invertColor() Inverts the R, G, and B channels
makeIntensity() Copies the red channel to the G, B, and A channels
makeAlpha() Sets the alpha channel to an average of the RGB channels. Sets the RGB channels to white.

图像的各项的一个参数了
对于材质的属性的解析

对于图像方程系数的解析,根据这个来对于图像来进行这个反转,旋转,mipmap的处理
缩放等等的处理




半透明的阴影的处理
noFog
mirror
guisurf 

这个材质居然有镜面和阴影的处理怎么来处理呢?
sort
对于材质的这个排序的处理, 
subview, opaque, decal, far, medium, close, almostNearest, nearest, postProcess、
对于这个贴花,透明的处理,中等,远处,关闭
最近的

例如透明的处理
材质居然要进行这个的处理了者也
材质的shader文件有这么多的东西了者也
diffusemap
specularmap
deform
bumpmap
DECAL_MACRO

doom3的 这个太强大了者也!
对于这个doom3的这个阴影的处理,怎么处理的呢?

对于纹理图像的操作方面,卡马克同志直接对图像的值进行了插值,使用镜面光方程,

使得 亮度越高,则表示为一个镜面 ,而不再是使用了光照贴图来表示光照了。

对于图像的处理,doom3中写了直方图处理,伽马等。 


原来doom3对bmp,pcx等图形文件都是直接从调色板中直接寻找到对应的像素,

存放到pic指针指向的内存中去。

加载了bmp,dds,jpg,tga等等文件等,做成了纹理的处理

将图像的数据发送到了幁缓存区,


从而做成纹理缓存者也

,对于游戏中的所有图像,进行图像的检查过滤,对于纹理图像文件,判断是

什么格式例如bmp,jpg,tga,dds,来调用相对应的加载函数。

binaryImage的这个图像的处理了者也
遮挡查询的处理
如果纹理时2d的纹理,那么绑定2d的纹理
如果是3d的纹理,那么绑定3d的纹理
如果是cube纹理,那么绑定cube的纹理

如果纹理经过压缩,那么解压缩这个纹理的处理

然后把这个纹理变成像素格式来存储了
设置纹理的参数的处理了
对于纹理的这个设置的处理了
根据这个纹理的压缩格式来做这个的处理了者也
最后把这个纹理发送到了这个缓存中去,
渲染凹凸映射,宽度,高度,尺寸
映射值在0.01到1.0之间
法线贴图的处理图像和
高度的多边形模型的处理等等
doom3的命令居然有这么多的东西了啊?真的没有想的到了者也
这个doom3的命令居然有了这么多的东西了者也

G


bump映射,凹凸映射
这个乃是高度图的凹凸映射,和法线映射

Two types of images can be used for bump mapping:

 height maps and normal maps. 


这个doom3中的这个全局光照和局部光照的处理等等
( ( R-128 ) / 128, ( G-128 ) / 128, ( B-128 ) / 128 )
textures/doom/techpanel
{
    qer_editorimage ase/techpanel.tga
    diffusemap      ase/techpanel_diffuse.tga
    specularmap     ase/techpanel_specular.tga
    bumpmap         ase/techpanel_local.tga
}
renderBump [-size  ] [-aa <0/1/2>]
      [-trace <0.01 - 1.0>]  
Size defaults to 256 by 256 if not specified. 

AA defaults to 1 if not specified. 

Trace defaults to 0.05 if not specified
尺寸应该是在了256之间

对于最后的结果gammma修正,和gui 2d屏幕上玩家的武器数据,以及对于玩家的生命值等等的输出到了屏幕之中了

  

渲染器

初始化阶段
主要配置opengl驱动等等者也

初始化时候要加载整个关卡里面所有的图像文件,


加载一个关卡里面的模型文件,

md3模型文件了,

lwo文件,doom3中的武器,弹药,实体等等很多都是使用的lightwave文件制造的,

再转化为了这个md5模型文件了者也

ase模型文件等等

(2)还有这个液体模型和粒子模型的处理
maya的这个导入了。

把md3,maya转化为了md5模型

MD5文件格式分为MESH(.md5mesh)和ANIMIATION(.md5anim),分别储存顶点和动画。

MESH部分

首先先看一下文件大概的内容

MD5Version 10
commandline "mesh models/monsters/imp/animation/cycles/imp.mb -dest models/md5/monsters/imp/imp.md5mesh -game Doom -prefix IMP1_ -keep Lknee Rknee Lelbow Relbow camera Body -keep Rmissile Lmissile -parent Rmissile Rhand -parent Lmissile Lhand -parent Rwing Chest -parent Lwing Chest -parent Hips Body -parent Waist Body -parent camera Head -prefix IMP2_ -prefix IMP_ -align ALL"

numJoints 71
numMeshes 1

joints {
   "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )      //
   "Body"   0 ( -0.0000002384 0 56.5783920288 ) ( -0.5 -0.5 -0.5 )      // origin
   "Hips"   1 ( 3.3494229317 -0.0225959271 62.0168151855 ) ( -0.5 -0.5 -0.5 )      // Body
   ...
}

mesh {
   // meshes: polySurface1
   shader "models/monsters/imp/imp"

   numverts 891
   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2
   ...

   numtris 1346
   tri 0 2 1 0
   ...

   numweights 1401
   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )
   ...
}

关节(JOINTS):

 "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )

首先是关节的名字,然后是关节的父接点(-1代表没有),接着是关节的位置(X,Y,Z),最后是一个四元数。

当然了四元数不能只有三个元了,但因为是单位四元数,所以我们可以把最后的W计算出来。

计算式:

1.0 = x^2 + y^2 + z^2 + w^2

PS:这里的位置都是绝对位置了,并不是相对于关节的位置。

网格(MESH):

numverts 891
   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2

分别对应 顶点序号(U、V坐标) 权值开始序号 权值数

PS:解释下权值数,就是在皮肤骨骼动画中,每个顶点并不是只被一个骨骼所控制,是被许多骨骼所共同控制的,所以要有不用的权值了。这里,顶点的权值是从权值开始序号开始的N个权值。

numtris 1346
   tri 0 2 1 0

这个就是三角形索引了,一看就明白,三角形序号和三角形所对应的三个顶点

numweights 1401
   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )

这个是权值,依次是:权值序号、关节序号、权值和XYZ位置

对了,还有一点要补充了。顶点的最终位置是这样了

v = w(1).v * w(1).weigth + w(2).v * w(2).weight + ... + w(n).v * w(n).weight

OK,MD5先到一段落,下次再补充动画部分。 

md5模型也可以来进行增加多边形

对于md5模型,doom3中对于ma文件(maya生成的)加载的,

ase文件(3D max产生的),

lwo文件(lightwave)等等文件

转化为md5文件的网格

 据md5Mesh,这是静态的,

 对于静态的物体,就不生成动画数据md5 Anim了.

md3和这个md4文件模型的处理者也
这个md4文件的这个lod处理者也,
还有对于这个多少个骨头的处理者也,对于这个增加了这个surface面的数量

md3和md4文件相乘了以后,然后这个来进行这个来处理者也

来表示这个模型的运动等等者也


模型一类的东西

model monster_boss_cyberdemon
{
    mesh          models/md5/monsters/cyberdemon/cyberdemon.md5mesh
    channel torso ( *Waist )
    channel legs  ( *Hips Body origin ROT -*Waist)

    anim af_pose  models/md5/monsters/cyberdemon/af_pose.md5anim
    anim ik_pose  models/md5/monsters/cyberdemon/ik_pose.md5anim

    anim stand    models/md5/monsters/cyberdemon/idle.md5anim
    anim idle     models/md5/monsters/cyberdemon/idle.md5anim
    anim sight1   models/md5/monsters/cyberdemon/sight.md5anim {
        frame 16.5  sound_voice    snd_sight1
    }
    anim walk     models/md5/monsters/cyberdemon/walk3.md5anim {
        frame 17    sound_body snd_footstep
        frame 17    triggerSmokeParticle cyber_rfoot_dust
        frame 37    sound_body snd_footstep
        frame 37    triggerSmokeParticle cyber_lfoot_dust
    }
    anim pain     models/md5/monsters/cyberdemon/pain_big1.md5anim {
        frame 1    call overrideLegs
        frame 1    sound_voice snd_pain
        frame 16   sound_body  snd_footstep
        frame 49   sound_body  snd_footstep
    }
}
entityDef env_ragdoll_fatty {
  "editor_color"          "1 .5 0"
  "editor_mins"           "-8 -8 -8"
  "editor_maxs"           "8 8 8"
  "editor_usage"          "Ragdoll for monster_zombie_fat\n"
  "spawnclass"            "idAFEntity"
  "bleed"                 "1"
  "sleep"                 "1"
  "skin"                  "skins/models/monsters/fatty.skin"皮肤
  "model"                 "models/md5/monsters/zfat/zfat.md5mesh" 模型的网格
  "anim af_pose"          "models/md5/monsters/zfat/initial.md5anim"
  "articulatedFigure"     "monster_zombie_fat"
}布娃娃系统的处理了者也
 
     
这个ai的这个布娃娃的系统的处理了者也
A body is specified with a structure as follows: 

Deforms

tube
sprite
flare
expand
move
turbulent
参数居然有这么多的东西了啊,这个doom3的参数也太多了吧!
eyeBall
particle
particle2


大致的流程跟这个quake3的类似了
加载所有的这个后置的数据
加载所有的实体
加载所有的这个图像文件
加载所有的这个贴花文件
家在所有的这个gui文件的处理
调集game的幁数,10ms
创建一个静态的光的interactions
运行这个wipe
拉伸屏幕

加载一个关卡里面的模型文件,

md3模型文件了,

lwo文件,doom3中的武器,弹药,实体等等很多都是使用的lightwave文件制造的,

再转化为了这个md5模型文件了者也

ase模型文件等等

(2)还有这个液体模型和粒子模型的处理
maya的这个导入了。

把md3,maya转化为了md5模型

MD5文件格式分为MESH(.md5mesh)和ANIMIATION(.md5anim),分别储存顶点和动画。

MESH部分

首先先看一下文件大概的内容

MD5Version 10
commandline "mesh models/monsters/imp/animation/cycles/imp.mb -dest models/md5/monsters/imp/imp.md5mesh -game Doom -prefix IMP1_ -keep Lknee Rknee Lelbow Relbow camera Body -keep Rmissile Lmissile -parent Rmissile Rhand -parent Lmissile Lhand -parent Rwing Chest -parent Lwing Chest -parent Hips Body -parent Waist Body -parent camera Head -prefix IMP2_ -prefix IMP_ -align ALL"

numJoints 71
numMeshes 1

joints {
   "origin"   -1 ( 0 0 0 ) ( -0.5 -0.5 -0.5 )      //
   "Body"   0 ( -0.0000002384 0 56.5783920288 ) ( -0.5 -0.5 -0.5 )      // origin
   "Hips"   1 ( 3.3494229317 -0.0225959271 62.0168151855 ) ( -0.5 -0.5 -0.5 )      // Body
   ...
}

mesh {
   // meshes: polySurface1
   shader "models/monsters/imp/imp"

   numverts 891
   vert 0 ( 0.8658549786 0.3910109997 ) 1377 2
   ...

   numtris 1346
   tri 0 2 1 0
   ...

   numweights 1401
   weight 0 47 1 ( 1.5918749571 -0.9465401769 4.3310847282 )
   ...
}

你可能感兴趣的:(doom3)