【翻译】第六章节:透明度(关于混合)


转载地址:http://www.omuying.com/article/94.aspx

原文链接:http://en.wikibooks.org/wiki/Cg_Programming/Unity/Transparency

具体的说,本篇文章关于渲染透明对象,例如:透明的玻璃、塑料、织物等等(实际上是半透明的对象,他们不一定完全透明)。透过(半)透明的对象我们可以看到他们身后的颜色,其时是它们的颜色与它们身后的颜色进行了混合。

混合

在《Programmable Graphics Pipeline》章节中提到,片段着色器为每个片段(除非片段被擦除)计算 RGB 颜色值(在片段输出参数使用语义词 COLOR,包括红、绿、蓝、透明分量),片段的处理细节可以查看《Per-Fragment Operations》章节,其中一个操作是混合阶段,主要用来合并片段的颜色(由片段输出参数指定),这被称为“source color”,与之相应的是已存在帧缓冲区的像素颜色,这被成为“destination color”(因为帧缓冲区的颜色是混合结果)。

混合是一个固定阶段,你可以通过混合公式对它进行配置但你无法对它编程,你可以通过公式像下面那样来混合 RGBA 颜色值:

1 float4 result = SrcFactor * fragment_output + DstFactor * pixel_color;

其中 fragment_output 是通过片段着色器计算的 RGBA 颜色,pixel_color 是当前帧缓冲区的颜色,result 是混合结果(混合输出阶段),SrcFactor 和 DstFactor 是可配置的 RGBA 颜色(类型是 float4),并且片段颜色和帧颜色的各个分量分别相乘,SrcFactor 和 DstFactor 的值在 Unity ShaderLab 中可以用下面语法指定 :

1 Blend {code for SrcFactor} {code for DstFactor}

比较常用的混合因子(factor)可以查看下表,更详细的混合因子(factor)可以查看《Unity's ShaderLab reference about blending》:

Code
Resulting Factor (SrcFactor or DstFactor)
One
float4(1.0, 1.0, 1.0, 1.0)
Zero
float4(0.0, 0.0, 0.0, 0.0)
SrcColor
fragment_output
SrcAlpha
fragment_output.aaaa
DstColor
pixel_color
DstAlpha
pixel_color.aaaa
OneMinusSrcColor
float4(1.0, 1.0, 1.0, 1.0) - fragment_output
OneMinusSrcAlpha
float4(1.0, 1.0, 1.0, 1.0) - fragment_output.aaaa
OneMinusDstColor
float4(1.0, 1.0, 1.0, 1.0) - pixel_color
OneMinusDstAlpha
float4(1.0, 1.0, 1.0, 1.0) - pixel_color.aaaa

由于 alpha 混合的流行,即使没有采用 alpha 混合,颜色的 alpha 分量也通常被称为不透明。此外,请注意计算机图形学中透明度的常见计算公式为 1 - 不透明度。

预乘 alpha 混合

alpha 混合还有一个非常重要的公式,有时候片段输出颜色已经预乘过颜色分量的 alpha 分量,在这种情况下,alpha 不应该被再次相乘,正确的混合是:

Blend One OneMinusSrcAlpha

这对应于:

1 float4 result = float4(1.0, 1.0, 1.0, 1.0) * fragment_output + (float4(1.0, 1.0, 1.0, 1.0) - fragment_output.aaaa) * pixel_color;

附加(Additive)混合

下面是另一种混合方式:

Blend One One

这对应于:

1 float4 result = float4(1.0, 1.0, 1.0, 1.0) * fragment_output + float4(1.0, 1.0, 1.0, 1.0) * pixel_color;

这只是给帧缓冲区的颜色添加片段输出颜色,注意这儿 alpha 并没有被使用,尽管如此,这个混合方式在处理一些透明效果时非常有用,比如,它经常被用在粒子系统中处理火或者透明物体发出的光。

Shader "Custom/Blending"
{
Properties
{
_Opacity("alpha opacity", Range(0.0,1.0)) = 0.3
}


SubShader //第一个 pass 使用前脸剔除来渲染背面(内部),第二个 pass 使用后脸剔除来渲染前面(外部)。
{ //这个着色器适合凸起的网格(封闭网无凹痕,例如球体或者立方体)或者近似的网格。
Tags { "Queue" = "Transparent" }//在不透明物体已绘制之后绘制
Pass
{
Cull Front //第一个渲染通道仅背面
Zwrite off //不写入深度缓冲区
Blend Zero SrcAlpha//乘法的混合,用于减少alpha值


CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float _Opacity;




struct vertexOutput
{
float4 pos : SV_POSITION;
float4 posInObjectCoords : TEXCOORD0;//测试使用,可以删除
};

vertexOutput vert (float4 vertexPos:POSITION) 
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, vertexPos);
output.posInObjectCoords = vertexPos;
return output;
}

fixed4 frag (vertexOutput input) : COLOR
{
if (input.posInObjectCoords.y > 0.0)
{
discard;
}
return float4(1.0, 0.0, 0.0, _Opacity);
}
ENDCG
}


Pass
{
Cull Back //第一个渲染通道仅背面
Zwrite off
Blend Zero SrcAlpha 


CGPROGRAM
#pragma vertex vert
#pragma fragment frag


float _Opacity;


struct vertexOutput
{
float4 pos : SV_POSITION;
float4 posInObjectCoords : TEXCOORD0;
};




vertexOutput vert(float4 vertexPos:POSITION) 
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, vertexPos);
output.posInObjectCoords = vertexPos;
return output;
}


fixed4 frag(vertexOutput input) : COLOR
{
if (input.posInObjectCoords.y >0.0)
{
discard;
}
return float4(0.0, 1.0, 0.0, _Opacity);
}
ENDCG
}
}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值