周笔记(3/52) - DX11 - Lighting/Texturing/Blending/Stenciling

2017/1/14~2017/1/21 总2017年第3周

Chapter 7 Lighting

  1. 对顶点的normal进行变换时,使用变换矩阵的逆矩阵即可。(如果是正交矩阵的话使用转置矩阵)
  2. 总光照颜色=Ambient+Diffuse+Specular
    • Ambient = light_a * material_a
    • Diffuse = light_d * material_d * K_d
      • K_d = max( light_dir dot normal_dir, 0)
    • Specular = light_s * specular_s * K_s
      • K_s = pow(reflect_light_dir dot view_dir, material_d.w)
      • reflect_light_dir = light - 2 * (light dot normal) * normal
      • (来自wiki等的第二种方案)K_s = pow((reflect_light_dir+view_dir).normal_dir, material_d.w)
  3. 光源类型
    • 平行光(Directional)
      • 光照结果 = Ambient + Diffuse
    • 点光源(Point)
      • 光照结果 = Ambient + (Diffuse * Specular) * I_d
      • I_d = I_d0 / (a0 + a1 * d + a2 * d * d)
    • 聚光灯(Spot)
      • 光照结果 = ( Ambient + (Diffuse * Specular) * I_d ) * K_spot
      • K_spot = pow(max(cosθ,0), s)
        (θ和s均为聚光灯的参数)
      • (来自wiki等的其他方案)例如内外环插值、含指数的插值等。
    • 注意:GPU将对变量的每一个分量进行4个float(32个字节)的对齐,因此在传入灯光等数据的时候,需要先将其对齐。可以增加占位来对齐。
  4. 对于使用曲面函数来制作的网格,可以使用梯度作为其法线

Chapter 8 Texturing

  1. 贴图的坐标是左上角为原点
  2. 使用ID3D11Texture2D / ID3D11CreateTextureFromFile 来存储和读取贴图,但它并不绑定到pipeline中,而是使用ShaderResourceView来绑定
    • ID3D11ShaderResourceView* mDiffuseMapSRV;
    • HR(D3DX11CreateShaderResourceViewFromFile(md3dDevice,
      L”WoodCrate01.dds”, 0, 0, &mDiffuseMapSRV, 0 ));
    • ID3DX11EffectShaderResourceVariable* DiffuseMap;
    • fxDiffuseMap = mFX->GetVariableByName(“gDiffuseMap”)->AsShaderResource();
    • fxDiffuseMap->SetResource(mDiffuseMapSRV);
    • 如果在drawcall之间改变贴图的话,需要调用Apply:pass->Apply(0, md3dImmediateContext);
  3. 滤波

    • 放大
      • 最邻近点采样(Nearest Neighbour Point Sampling)
      • 单/双线性插值(Linear/BiLinear interpolating)
    • 缩小

      • 三线性滤波(trilinear interpolating)
        三线性滤波的贴图
        (图片来自wiki)
      • .DDS文件可以存储mipmap链。不过即使没有,DX也会在创建贴图时创建一个。
      • 各向异性滤波(Anisotropic Filtering):当要贴图的表面和视线接近垂直时也能获得较好的结果
        各向异性滤波的贴图
        (图片来自wiki)

        With RIP map anisotropic filtering, in addition to downsampling to 128 × 128, images are also sampled to 256 × 128 and 32 × 128 etc. These anisotropically downsampled images can be probed when the texture-mapped image frequency is different for each texture axis. Therefore, one axis need not blur due to the screen frequency of another axis, and aliasing is still avoided. Unlike more general anisotropic filtering, the RIP mapping described for illustration is limited by only supporting anisotropic probes that are axis-aligned in texture space, so diagonal anisotropy still presents a problem, even though real-use cases of anisotropic texture commonly have such screenspace mappings.
        (翻译)使用 RIP 映射各向异性滤波,除了向下采样到128x128之外,也向下采样到256x128,32x128,等等。这些各向异性的向下采样图像,可以在当贴图映射图像频率在各个方向不同时使用。所以,某个轴向不需要因另一个轴的屏幕频率而模糊,而且走样依然被避免了。不像那些普通的各向异性滤波,渲染中的RIP映射仅限于支持轴对齐方向的走样。所以对角线方向的各向异性依然是个问题。虽然在实际应用中,各向异性贴图通常都有这种屏幕空间映射。(原文来自wiki)

      • 后期添加调制(modulate with late add):把ambient和diffuse添加到纹理颜色上。可以用线性映射代替pixel shader中的逐像素计算。

      • 可在贴图级再增加一个纹理映射,方便进行纹理上的变换。例如砖墙的变换贴图映射的缩放、下落的瀑布、随时间变化的粒子特效
      • 图像压缩
        • 可以使用dx texture tool、NVIDIA texture tool 制作压缩后的贴图(DDS格式)
        • 贴图在GPU中以压缩后的形式储存,在读取的时候依然能快速的得到解压后的结果
        • D3DX11_IMAGE_LOAD_INFO.D3D11_TEXTURE2D_DESC.Format中存储压缩格式

Chapter 9 Blending

  1. 使用如下公式模板进行计算:这里写图片描述
    • 在“田”处放入运算符,Fsrc和Fdst为参数
    • 运算符可选:加,减,反向减,min,max
    • F可选src或dst的颜色、反向颜色、alpha值、0或1、自己指定
    • alpha通道和RGB通道可以使用不同的公式
  2. D3D11支持同时渲染8个物体,因此D3D11_BLEND_DESC中,也有一个长度为8的D3D11_RENDER_TARGET_BLEND_DESC来描述它。但是IndependentBlendEnable是false的话,所有的都会使用列表的idx=0者。
  3. 深度测试的问题
    • 一般需要先渲染不透明物体再渲染透明物体,过具有交换律的blend操作符不受此限制
    • 在渲染不透明物体时,需要disable深度缓存的写入。但是依然需要被深度测试。
  4. 可以在DX texture tool中载入alpha通道的贴图来创建具有alpha通道的贴图
  5. Clipping Pixels:在ps中使用clip()可以立即放弃渲染该像素(跳过后续的代码)
  6. 制作雾效(Fog):
    • 可以掩饰(因远平面的关系)物体忽然出现到视角中
    • foggedColor = (1-s) * lightColor + s * fogColor
    • s = saturate( (dist(camera, element) - fogStart) / fogRange )

Chapter 10 Stenciling

  1. 判断函数:(StencilRef & StencilReadMask ⊴ Value & StencilReadMask)
    • StencilRef 为RenderState中传入
    • “⊴”符号可以被替换为 never、less、greater、equal、not equal、always 等
  2. D3D11中对应的状态:ID3D11DepthStencilState
  3. 使用Stencil Buffer的设置流程:
    • 清除模板缓存:ID3D11DeviceContext::ClearDepthStencilView
    • 创建深度模板缓存描述:D3D11_DEPTH_STENCIL_DESC
      • 深度测试、模板测试 的 Mask、操作符、成功失败后的操作、是否开启,均在此处定义
      • 深度测试的成功失败后的操作:只有不写入和写入两种;
      • 模板测试的成功失败后的操作:有keep/zero/replace/
      • 注意上述操作只对深度模板缓存本身的值生效。例如在渲染镜面反射物体时,不应该指定模板为replace。
    • 使用描述创建深度模板缓存状态:ID3D11Device::CreateDepthStencilState
    • 设置深度模板缓存状态:ID3D11DeviceContext::OMSetDepthStencilState
  4. 镜面效果步骤:
    • 渲染所有物体(包括即将被反射的物体)
    • 设置模板测试总是成功(always)、成功后写入(replace);设置深度缓存为不写入(zero)
    • 渲染镜面
    • 设置模板测试为相等(equal)、成功后保持(keep)
    • 计算并设置反射后的光线角度、物体的局部坐标、反转顶点绕序
    • 渲染将要被反射的物体
  5. 物体阴影效果步骤:
    • 数学部分:
      • 设平面为: n dot x + d = 0,要投影的点为 p,那么容易得到投影后的点为:
      • 平行光:(L为光线方向的逆向)
        这里写图片描述
        矩阵形式为:
        这里写图片描述
      • 点光源:(L为光源位置)
        这里写图片描述
        矩阵形式为:
        这里写图片描述
      • 虽然L在点光源和平行光中分别代表位置和方向,但是其实可以把平行光中的L看作是无限远处的光源位置
      • 使用Lw = 0或1,可以将上述两个矩阵统一起来:
        这里写图片描述
    • 使用Stencil Buffer来防止双重融合:
      • 打开stencil,设置对比符为equal,成功后的操作为D3D11_STENCIL_OP_INCR(加1)
      • 渲染阴影们
    • 可以使用“加1”操作来统计“深度复杂度(depth complexity”,以此查看渲染时的深度复杂度:
      • 使用对比符Always,成功后 INCR
      • 渲染所有物体
      • 设置StencilRef为每一个深度值,对比符为Equal
      • 渲染某个颜色
      • (另一种方法是使用一个固定颜色的PS,以及不测试深度值的叠加的低alpha的全体blend到一块)
    • 深度测试实际上发生在Merge阶段,在Pixel Shader之后,亦即可能发生计算完昂贵的Pixel Shader之后才发现需要抛弃该像素。然而,现代的图形卡支持early z-test,不过,是否生效要由Pixel Shader中是否修改了深度值来决定。不论如何,尽量按照从近至远的顺序来渲染吧!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值