9.1 THE BLENDING EQUATION
Csrc是这帧PS计算结果输出,Cdest是当前back buffer计算结果(比如已经计算好的透明体背后的solid的color),Fsrc (source blend factor) and Fdst (destination blend factor)
⊗表示componentwise multiplation ,⊞ 表示binary operation,这两个下面两节会说。
alpha和rgb 类似,之所以分开,是为了要分开控制。而且alpha的blend的需求频率比rgb要小很多,因为一般用不到back buffer的alpha。
9.2 BLEND OPERATIONS
解释⊞,binary operation
alpha类似
9.3 BLEND FACTORS
解释⊗,factor
具体在D3D11_BLEND 的enum type里
9.4 BLEND STATE
在DX中,以上信息由ID3D11BlendState 控制,创建它,通过ID3D11Device::CreateBlendState方法 传入D3D11_BLEND_DESC 结构体。
HRESULT ID3D11Device::CreateBlendState( const D3D11_BLEND_DESC *pBlendStateDesc, ID3D11BlendState **ppBlendState);
注意其中的一些参数
AlphaToCoverageEnable 用于MSAA 计算覆盖率时使用,第11章时用到
RenderTarget 8个D3D11_RENDER_TARGET_BLEND_DESC 大小的数组,表示8个rendr target 依次怎么blend,默认用第一个的
RenderTargetWriteMask:用于控制是否允许写入哪些通道
bind STATE 到pipeline 调用
void ID3D11DeviceContext::OMSetBlendState( ID3D11BlendState *pBlendState, const FLOAT BlendFactor, UINT SampleMask);
9.5 EXAMPLES (书中有很多效果对比图)
9.5.1 No Color Write
方法1 Fsrc=(0,0,0),Fdest=(1,1,1) C=Csrc*(0,0,0)+Cdest*(1,1,1)
方法2 D3D11_RENDER_TARGET_BLEND_DESC::RenderTargetWriteMask =0
9.5.2 Adding/Subtracting
Add会让画面变亮,因为更多的像素值变大了。Subtract会让画面变暗,因为像素值变小了。
C=Csrc*(1,1,1)+/- Cdest*(1,1,1)
9.5.3 Multiplying
Fsrc=(0,0,0),Fdest=D3D11_BLEND_SRC_COLOR
C=Csrc*(0,0,0)+Cdest*Csrc
正片叠底,通常执行正片叠底模式后的颜色比原来两种颜色都深。任何颜色和黑色正片叠底得到的仍然是黑色,任何颜色和白色执行正片叠底则保持原来的颜色不变,而与其他颜色执行此模式会产生暗室中以此种颜色照明的效果。
9.5.4 Transparency
Fsrc=D3D11_BLEND_SRC_ALPHA,Fdest=D3D11_BLEND_INV_SRC_ALPHA
C=Csrc*As+Cdest*(1-As)
使用这种方法,就要注意object的绘制顺序
基本原则是Draw objects that do not use blending first. Next, sort the objects that use blending by their distance from the camera. Finally, draw the objects that use blending in a back-to-front order. 先绘制不用blend的object,然后对需要blend的object根据和camera的距离做排序,然后根据排序从后往前绘制。
如果有半透明的才需要排序,否则如果只是 add subtract multiple,虽然还是先渲染不需要blend的,再渲染blend的objects,但这些objects就不需要排序了,因为这三种操作是可交换的,先后顺序不影响。?
9.5.5 Blending and the Depth Buffer
当渲染一系列blend的object,这一系列是不互相阻挡的,因此不希望他们覆写掉depth value,如果这样,后面blend的同系列的就可能无法通过深度测试,从而无法blend,所以这种时候会关闭这些像素的深度写入,只写入rgb值。
比如一堆粒子,互相之间是addtive的,一个像素上 addtive到的例子越多,这个地方就越亮,反之越暗,这个也和实际情况相符。
9.6 ALPHA CHANNELS
一般比如上一章节 最终ps 传出 diffuse texture 的alpha,作为 src的alpha值。
介绍DXTex 工具可以在把一张只有rgb的和一张作为alpha的灰度图合并,把灰度图作为alpha channel插入进去。这种photoshop啥的都可以。
9.7 CLIPPING PIXELS
调用clip(x) 方法可以裁剪掉 传入x<0 的像素,一般传入alpha,如果alpha小于0,表示不可见,直接丢弃
因此ps中加入参数gAlphaClip, 如果为true,会执行裁剪。
虽然用blend也可以做到,但这个更高效,不用执行blend,之后的ps代码也可以不用执行。
这里的例子中注意丢弃像素之后,object的背面可能也需要画出来,因此需要关闭背面剔除。
9.8 FOG
模拟天气雾效有以下好处
1.遮挡远程物件,减少绘制
2.阻止poping现象发生,这是说远处一个物体本来在视锥体之外,由于相机移动到了视锥体之内,它会突然出现,非常突兀。
3.另外即使是晴天,也会需要在远距离又一些雾效,比如远处的山也需要给予深度的朦胧效果,模拟大气散射效果。
计算方式:
首先 foggedcolor用 系数s 混合 litcolor和 fogcolor
s的计算是基于 定义 fogStart和fogRange,雾的起始距离和范围。
saturate 方法会clamp 传入的值到0~1.
所以可以看到 fog 完全不影响 fogstart之前的object的颜色,而fogend=fogstart+fogrange之后的object会完全隐藏掉。
例子中fog计算会在ps的最后,再计算了litColor之后再最终混合雾效。
例子中一个是distToEye 和toEye 计算了两次可以优化一下。一个是 添加了wireframe,lighting,fog三种模式,可以对比查看。