zoukankan      html  css  js  c++  java
  • 转刚研究3D基本概念容易搞混的几个问题

    1.Viewport和Frustum有什么区别?
    2.Viewport和Frustum的NearClipPl?ane有什么区别?
    3.Vertex,Point,Vector有什么含义上的区别? Plane,Face和Mesh呢?
    4.为什么顶点会有W分量,它怎么算出来的?干什么用的?
    5.在一次完整的顶点渲染管线中,最多会出现多少种坐标系?(例如世界坐标系)
    6.上面的每个坐标系的实际意义是什么?互相之间怎么转换?转换矩阵怎么写,意义又是什么?
    7.光照是怎么计算的?光源可以设置Ambient,Diffuse...为什么Material也可以设置Ambient,Diffuse...?为什么顶点数据中还可以再指定Diffuse,Specular?
    8.在每帧的颜色混合过程中,我们可以在SetTexture?StageState?中指定AlphaOp,ColorOp,在SetRenderS?tate中指定SrcBlend和DestBlend,它们互相是什么关系?
    9.几种AlphaBlend?方式对应的实际含义是什么?
    10.AlphaTest和AlphaBlend?有什么区别? AlphaBlend?可以完全取代AlphaTest吗?
    11.TextureSam?plerMode中,可以分别对MIN,MAG,MIP指定Point和Linear,它们可以有哪些组合?各代表什么意义?
    12.全屏抗锯齿和TextureSam?plerMode有关系吗? 和MontionBlu?r有关系吗?
    13.Cull_CW,Cull_CCW是干什么用的? 不做Cull行吗? Cull和Clip有区别吗?
    14.ShadingMod?e可以指定FLAT,GOURAUD,PHONG,这发生在渲染过程中的哪一步? 和FillMode有什么关系?
    15.UV有什么用?UV和ST有什么区别?UV在光栅化时需要被插值吗?插值完了再做什么?
    16.VertexShad?er和PixelShade?r分别对应于FixedPipel?ine的哪些步骤? 先搞清楚FixedPipel?ine对进一步研究Programmab?lePipeline?很有好处,你同意吗?为什么?
    17.如果上面的问题你都搞清楚了, 你能在心中清晰地描述出每一个三角形, 是如何从刚开始的模型数据, 成为屏幕上的象素点?
    18.BSP,OSP,Voxel...它们处于RenderPipe?line的什么地位上?
    19.现在,请用Vertex和PixelShade?r,实现出和DX9的FixedPipel?ine一样的功能.
    20.思考第19个问题,然后说说看,这其中可以玩哪些花招?(Shader是用来玩的...)

    1.2.
    Viewport是定义在"屏幕坐标系"下的,它是渲染目标表面的一个区域.渲染到这个区域以外的图形将被Clip掉.
    ViewFrustu?m 是定义在"世界坐标系"下的,它是一个四楞台.顶面就叫做NearClipPl?ane,底面就叫做FarClipPla?ne.落在 ViewFrustu?m之外的物体,默认情况下会被Clip.ViewFrustu?m的顶点就是Camera也就是眼睛所在的位置,顶角的一半成为 FOV(视域,即视野范围)
    那么,ViewFrustu?m实际上就是从"世界坐标系"下的眼睛位置去观察Viewport...
    3.
    Point,Vector(向量)是数学名词,当我们提到它们,往往是在做一些物理和几何运算,比如碰撞检测.而Vertex则是具有图形意义的顶点,往往带有除了空间位置以外的其他信息,例如Normal,Diffuse...
    类似的Plane也属于数学概念,我们常常在BSP树的切分面时提到它.Face是带有一组顶点和边信息的面,是进行Shading的基本单位.Mesh是一组面,又叫网格,含有更多的图形信息,比如Texture...
    4.
    当我们使用标准4x4的Matrix(特别是Projection?Matrix,它必须是齐次的,它的3行4列元素必须=1.0f)进行坐标变换,而为每个初始顶点额外指定一个W=1.0f时,那么在变换到齐次坐标系下时,W分量可以用来进行Clip:
    -W < X <= W,  -W < Y <= W,  0 < Z <= W
    凡是不满足上式的点将被Clip.(注意Clip不简单等于不画)
    此外W还被用于Fog和DepthBuffe?r.
    最后就是不要把XYZW和四元数搞混了,后者是为了解决GimbalLock?和平滑的旋转插值等问题引入的数学方式.
    5.6.
    会顺次出现"ModelSpace?"(LocalSpace?)->"WorldSpace?"->"ViewSpace"(CameraSpac?e)->"Projection?Space"->"ScreenSpac?e"
    在 ModelSpace?下,各个Object之间没有相互关系,也不知道Camera和Frustum的存在.为了把孤立的Object全部放在 WorldSpace?下,通常会乘以一些最初的变换矩阵.另外,ModelSpace?并不是一个必须的概念,OpenGL就没有 ModelSpace?.
    在WorldSpace?下,所有Object都有了统一的坐标定义.所以在这里开始可以做很多工作.比如场景数据结构 的遍历,碰撞检测等等,光源也在这里被初始化.在这里乘以ViewMatrix?就可以变换到ViewSpace.通常用eye,look,up来定义一 个ViewMatrix?.
    在ViewSpace下,坐标原点位于Camera的点也就是ViewFrustu?m的顶点,而方向对齐Camera的方向.这里进行Back-face Culling:
    Visibility? = planeNorma?l.dotProduct?(ViewVector?) > 0
    此时乘以Projection?Matrix变换到Projection?Space.
    在Projection?Space下,坐标系变成方形.这里进行Frustum Culling(使用W),和利用DepthBuffe?r来隐面消除.
    在做完ViewportSc?ale之后,就到了ScreenSpac?e.此时实际上3D的顶点已经成为2D的顶点.接下来就可以进行光照计算,光栅化,Alpha混合和贴图了.
    变换矩阵:
    平移:             缩放:             旋转(以X为例):     投影:
    | 1  0  0  0 |    | Sx 0  0  0 |    | 1  0   0   0 |   | w 0  0   0 |
    | 0  1  0  0 |    | 0  Sy 0  0 |    | 0  cos sin 0 |   | 0 h  0   0 |
    | 0  0  1  0 |    | 0  0  Sz 0 |    | 0 -sin cos 0 |   | 0 0  Q   1 |
    | Tx Ty Tz 1 |    | 0  0  0  1 |    | 0  0   0   1 |   | 0 0 -QZn 0 |
    其中:w=cot(FOVh/2). h=cot(FOVv/2). Q=Zf/(Zf-Zn)
    如果使用DX或者GL的话,往往有非常方便的接口可以调用,不需要牢记这些数学公式.
    7.
    光分为全局环境光,平光,点光,聚光.
    光照计算公式比较复杂,总的来说就是
    Lighting = Ambient + Diffuse + Specular + Emissive
    也就是四个分量.而其中的每个分量,简单来说就是光源和Materail以某种方式相乘累加的结果.
    Ambient Lighting = Ca*[Ga + sum(La*Atten*Spot)]
    Diffuse Lighting = sum[Cd*Ld*(N.Ldir)*Atten*Spot]
    Specular Lighting = Cs*sum[Ls*(N.H)P*Atten*Spot]
    Emissive Lighting = Ce
    上面Ca代表Material的属性, La代表Light的属性, 从上面式子我们可以看得出光照计算的大概过程.
    一些细节:
    Ga:全局环境光,我们在RenderStat?e里可以设置.
    Atten:光的衰减因子,可以分为常数,线性,和平方衰减.
    Atten = 1/( att0i + att1i * d + att2i * d2)  d表示Vertex到光源的距离.
    对于平行光,Atten=1; 如果光源超出范围,Atten=0
    Spot:光的聚光因子.这个计算比较复杂,对于非聚光灯,Spot=1.
    N:Vertex Normal.
    Ldir:从顶点到光源的向量.
    H:被称为Half way vector(中间向量)
    H = norm(norm(Cp - Vp) + Ldir)  Cp:Camera位置 Vp:顶点位置. norm表示单位化.
    P:Specular的反射强度.也称为Shiness.在指定Material的Specular时通常会一起指定.
    总结一下:
    对于Ambient和Emissive的计算,是不用考虑Normal和光的方向的.尤其是Emissive(自发光)只和Material有关,光源没有这个属性.
    注意所有光源都可以有Amient分量,它和全局环境光不是一个概念.
    最重要的是:
    光照计算的结果,是由Light和Material共同决定的.Light的Ambient,Diffuse...指定了光源本身的属性.而Material的Ambient,Diffuse...指定了被照亮的物体以何种程度受到光的影响.
    一定还有一个疑问:
    为什么顶点的数据中还可以指定Diffuse和Specular呢?这其实是逐顶点指定了Material.你可以通过RenderStat?e的设置,而决定Material的来源:从顶点数据得到,或者从全局设置的Material得到.
    默认情况下Ambient和Emissive从Material得到,Diffuse和Specular从Vertex得到.这时你设置Material的Diffuse和Specular是没用的.
    8.
    Alpha和Color信息从哪里来? 可以来自于Vertex,Material,Texture.
    Alpha和Color信息到哪里去? 我们最终的视觉效果,也就是FrameBuffe?r中的像素点.
    在FrameBuffe?r的Alpha混合的过程中,我们可以指定各种各样的混合公式,这通过指定SrcBlend和DestBlend实现.
    例如DX默认的混合公式:
    Final Color = SrcColor * SrcAlpha + DestColor * (1-SrcAlpha)
    这实际上是指定 SrcBlend = D3DBLEND_S?RCALPHA; DestBlend = D3DBLEND_I?NVSRCALPHA?.
    而SrcBlend和DestBlend这两个因数,无非来自于以下四个可能的来源.
    SrcColor,SrcAlpha,DestColor,DestAlpha.
    这四个因素本身可以取反,如InvSrcAlph?a.再加上Zero和One,就形成了各种各样的混合方式.
    DestColor,DestAlpha的来源显然是FrameBuffe?r目前的Pixel数据,那么SrcColor,SrcAlpha呢?它们来源于纹理混合的AlphaOp,ColorOp.
    以Alpha为例,假设指定AlphaArg1=Texture,AlphaArg2=Diffuse,AlphaOp=Modulate,那么该点的Alpha值实际上是由贴图的Alpha通道的Alpha值,与Diffuse色的Alpha值相乘得到.
    而Diffuse的来源又可以是Vertex或者Material.(参看光照计算)
    Color的情况一样,只不过来源为贴图的颜色通道,和Diffuse的Color值.
    总结一下:
    对于Alpha或者Color:
    Vertex/Material ---| blend
                       |-------| blend
    Texture -----------|       |-------FinalPixel?
    FrameBuffe?r----------------|
    注意:
    Texture的Blend公式,只对当前描画的Primitive有效,而FrameBlend?公式,则对所有Primitive都有作用.
    为了进行AlphaBlend?,当然要先把EnableAlph?aBlending打开,否则...
    9.
    通过AlphaBlend?可以实现非常多的常见特效,比如火,烟,云雾,爆炸等等.与粒子系统也有着非常密切的关系.而一切特效,无非都是通过指定不同的Alpha混合方式实现的.
    打个比方,如果要实现火的效果,首先Texture上应该有Alpha通道,然后把Diffuse的Alpha和Color都指定为255.
    此时
    AlphaArg1=Texture,AlphaArg2=Diffuse,AlphaOp=Modulate
    ColorArg1=Texture,ColorArg2=Diffuse,ColorOp=Modulate
    SrcBlend = SrcAlpha, DestBlend = One
    就可以了.结合粒子系统,你会看到耀眼的火光把屏幕照亮.
    而且这种FrameBlend?方式还有一个优点:因为DestBlend=One,所以混合顺序不影响描画结果.对于带Alpha粒子Z排序通常是比较麻烦的,利用这个公式可以避免这一点.
    又比如:
    SrcBlend = SrcAlpha, DestBlend = InvSrcAlph?a对应单色滤镜.
    SrcBlend = SrcColor, DestBlend = InvSrcColo?r对应彩色滤镜.
    总之可能实现的效果非常多,各位不妨试试看各种有趣的组合,这里就不多说了.
    10.
    AlphaTest指的是,对于SrcAlpha值(参看上面AlphaBlend?的介绍),与某个参考值进行比较,如果不满足某种条件,那么该点就不会被描画.
    虽然AlphaTest也利用到了SrcAlpha,但是却不是用来混合.
    AlphaTest可以实现镂空(比如2D中经典的透明色问题),消除Texture拉伸引起的黑边等效果,它和AlphaBlend?不是等价的,AlphaBlend?也不能完全代替AlphaTest.
    举一个两者可以互相等价的例子:
    假如有一个BillBoard显示的树.它的Texture具有Alpha通道,而且透明部分的Alpha=0,其余部分=255.
    那么设定AlphaTest参考值为0,比较公式为NotEqual,就可以实现透明色.
    有趣的是,这个结果和采用AlphaBlend?得到的结果相同.
    可是,如果Texture的Alpha通道有Alpha渐变,那么AlphaTest就显得力不从心了...
    理解了AlphaTest的基本思想,就可以很容易理解DepthTest和StencilTes?t.



    11.
    在纹理映射的过程中,插值得到的Texel的地址一般都不是一个整数,而是个小数.也就是没有一个Texel能够和这个地址精确对应.
    怎么办?默认的方式是采用Nearest-Point-Sample,在这种方式下,会找到最近的Texel,直接作为最终结果.
    下边举个例子,在此之前,顺便提下TextureAdd?ressMode.分为3种:Wrap,Clamp,Mirror,Border
    不太严谨地表示下:
    Wrap: EEEEEE  (顺延下去)
    Clamp: E===== (拉伸出去)
    Mirror: E3E3E3 (顺延且不断取反)
    Border: E????? (你想填啥色就填啥色)
    还有,U的范围[0.0, 1.0],对应到水平具有N个Texel的贴图,范围就是[-0.5, N-0.5].
    假 设现在取Wrap方式,那么对于一个U值0.999,按照Nearest-Point-Sample,取到的Texel就是贴图的最右边的那一点,而永远 不会是贴图最左边的那个点.这时如果下一个插出的U值对应到贴图最左边的第二个点.那么就产生了跳跃,贴图效果就会有断裂感.
    当贴图比被贴图的表面大(Texel采样不足),或者小很多时(Texel过度采样),类似结果尤其明显.
    现在Linear-Sample就很容易解释:对于一个不能精确对应的Texel地址,我们取以下四个Texel:
    Nearest-Point上,下,左,右.
    并计算Weight(权值):
    W1 = (1 - Ufrac) * (1 - Vfrac)
    W2 = Ufrac * (1 - Vfrac)
    W3 = (1 - Ufrac) * Vfrac
    W4 = Ufrac * Vfrac
    而混合出最终的结果.
    这就是Linear-Sample.
    Nearest-Point-Sample和Linear-Sample都分别可以应用于MIN(贴图比被贴图的表面大),MAG(贴图比被贴图的表面小)方式上,产生想要的结果.
    MIP的情况有所不同.
    首先MIP是指MipMap.什么是MipMap呢?
    假设你看着CS的一面墙,墙上有花纹.
    现在你向这面墙走近,是不是觉得本来细致的花纹变成了大的色斑?
    现在你离开这面墙走远,是不是觉得花纹好像揉皱了看不清楚?
    其实这个道理还是Texel采样不足和Texel过度采样.同一个表面,在不同的距离观察,应该采用不同分辨率和精度级别的贴图.
    于是我们从具有最大精度的贴图开始,逐步降低分辨率(通常是长宽除2),直到到达最低分辨率(通常是8级),这样产生的一组贴图,就称为MipMap.
    注意MipMap会同时提高渲染效率和渲染效果,而付出在于Memory.
    对于MIP指定Nearest-Point-Sample,意味着你将直接选择一个最接近的精度级别的MipMap作为贴图,然后再应用上面提过的方式进行映射.
    对于MIP指定Linear-Sample,意味着你将选择两个最接近的精度级别的MipMap作为贴图,然后再应用上面提过的方式进行映射,然后结果再根据权值再混合.
    这是最高质量的纹理映射方式,有时被戏称为"三线滤波".(MIN:LINEAR, MAG:LINEAR, MIP:LINEAR)

  • 相关阅读:
    如何从svn上down项目
    查看当前项目的svn地址
    项目启动失败
    新增sql后面可以跟where条件(多表关联新增数据和复制数据)
    递归思想之---斐波拉契数列
    递归思想之---阶乘算法
    java递归思想之---汉诺塔
    将 Docker 镜像体积减小 转载:https://mp.weixin.qq.com/s/kyK6652kchtudZHhSsYx_Q
    工具 转载 https://mp.weixin.qq.com/s/Y1RHEDu0vuH4qm9QtMISFg
    Kubernetes 学习笔记 权威指南第五&六章
  • 原文地址:https://www.cnblogs.com/kex1n/p/2375101.html
Copyright © 2011-2022 走看看