翻译 Cg Program in Unity - 2.4 Silhouetten Enhancement

来源:互联网 发布:linux 自启动文件 编辑:程序博客网 时间:2024/05/29 07:46

 本章内容将讲解表面法向量变换(Transformation of surface normal vector)。在学习这章之前,你需要先确保理解了前面章节的内容。


我们想做出的就是右边这张图所展现的效果:一个半透明物体的边缘比其余部分的透明度更低。这样可以增加三维感,即使在没有灯光的情况。这里的法线变化对于获得这种效果是非常重要的。










 Silhouetees of Smooth Surface(光滑轮廓表面)


在表面是光滑的情况时,轮廓表面的法向量平行于视平面也垂直于观测者方向。在左图中,位于左图最上部分的蓝色法线平行于视平面,其他的法向量点则对观测者(相机)有个多的方向。通过计算观察者方向和法向量,我们可以得到它们是否(几乎)垂直于彼此,由此可以得到这个点是否是轮廓上的点。

更具体的说,如果V是一个观测者方向上的单位向量(长度是1),而N是一个单位化的表面的法向量,如果这两者相互垂直,那么他们的点积(dot)的结果就是0:V * N = 0。但是,这种直接得到0的情况是非常少见的,通常只要值接近了0,我们都认为这个点属于轮廓上的点。


Increasing the Opacity at Silhouette (增加轮廓上的不透明度)


对于我们想要的效果,我们需要在V*N的结果接近0的点上增加不透明度α。视方向和法向量点积接近于0的点,我们有许多办法去增加不透明度。这里讲其中一个方法(实际上这背后有一个实际的物理模型,我们将在5.1章讲它。),从一个常规的不透明度α增加不透明度到α‘的公式:




像这样的方程去检测极端情况总是有意义的(?)。考虑一个点接近于轮廓的情况: V*N≈0。在这种情况下,正常的α会去除以一个很小的正数值(注意GPU通常都能很优雅的去处理除以0的情况;因此,我们不用担心这个问题)。因此,不管α的值是什么,α和一个很小数的比例都会很大。而Min这个函数的作用就是保证得到的结果不永远不会超过1。

另一方面,如果一个点原理轮廓,我们的V*N≈1.这样,α’≈min(1,α);也就是说它的透明度不会变化多少。这也就是我们想要的效果。所以我们这里这样做是很有道理的。

Implementing an Equation in a Shader

为了在着色器的中实现一个α方程,第一个问题是:我们也该在顶点着色器中还是片段着色器中 ?在一些情况下,回答是很清楚的,因为执行过程中我们需要用到纹理映射(texture mapping),而它通常在片段着色器中获得。在许多情况下,不管怎么样,并没有一个完全的答案。在顶点着色器中可以获得更快的速度(因为在这里需要处理的量比片段着色器里面少),但是得到的图像质量也更低(在不同顶点之间法向量和顶点的其他属性会突兀地变化)。因此,如果你更关心性能,在顶点着色器中执行是一个更好的选择。另外一方面,如果你更关系图像质量,在片段中执行更好。这个问题在逐片段光源(也就高洛德着色(Gouraud shading)和逐顶点光源(补色着色)上也有相同的问题。

下个问题是:我们执行的时候应该使用哪个坐标系?同样的,这也没有统一答案。不管怎样,在Unity中使用世界坐标通常是一个不错的选择,因为许多的uniform变量是使用的世界坐标系的。(在其他环境中很多使用视口坐标。)

最后一个问题:我们从哪儿获得上面等式中的参数?通常α这个值是Unity着色器中的一个属性(一个RGBA颜色)。而法向量gl_Normal是一个标准的顶点输入参数。 而视方向可以通过从世界坐标系中的顶点的坐标到相机位置(_WorldSpaceCameraPos)的向量获得,他们都由Unity提供。

因此,我们仅仅在执行之前需要去变换顶点和法向量到世界坐标系。转换矩阵_Object2World是从对象坐标空间到世界坐标的转换,而它的逆矩阵_World2Objec,他们t由Unity提供,之前我们讨论过。对点和向量使用矩阵我们在专门的章节“Applying Matrix Transformation"讲解。通常情况,点和向量的转换时我们使用点或者向量乘模型矩阵来做计算:



另外方面,法向量转换时要乘以逆转置转换矩阵。因为提供给我们使用逆转换矩阵(它除去右下角的_World2Object * unity_scale.w) ,所以另外一个更好的选择是法向量左乘逆矩阵,这种方法等同于右乘逆转转置矩阵。






注意,如果矩阵的右下角不正确也没关系,因为它会去乘以0。还要提一个问题,去乘以unity_Scale.w不是必须的,因为缩放不会影响单位法向量。

现在我们已经知道着色器所有的 部分,我们可以写出以下着色器程序:
Shader "Cg silhouette enhancement" {Properties {_Color ("Color", Color) = (1, 1, 1, 0.5)// user-specified RGBA color including opacity}SubShader {Tags { "Queue" = "Transparent" }// draw after all opaque geometry has been drawnPass {ZWrite Off // don't occlude other objectsBlend SrcAlpha OneMinusSrcAlpha // standard alpha blendingCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"uniform float4 _Color; // define shader property for shadersstruct vertexInput {float4 vertex : POSITION;float3 normal : NORMAL;};struct vertexOutput {float4 pos : SV_POSITION;float3 normal : TEXCOORD;float3 viewDir : TEXCOORD1;};vertexOutput vert(vertexInput input){vertexOutput output;float4x4 modelMatrix = _Object2World;float4x4 modelMatrixInverse = _World2Object;// multiplication with unity_Scale.w is unnecessary// because we normalize transformed vectorsoutput.normal = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse)));output.viewDir = normalize(_WorldSpaceCameraPos- float3(mul(modelMatrix, input.vertex)));output.pos = mul(UNITY_MATRIX_MVP, input.vertex);return output;}float4 frag(vertexOutput input) : COLOR{float3 normalDirection = normalize(input.normal);float3 viewDirection = normalize(input.viewDir);float newOpacity = min(1.0, _Color.a/ abs(dot(viewDirection, normalDirection)));return float4(float3(_Color), newOpacity);}ENDCG}}}

注意,在片段着色器的一开始我们将output.normal和output.viewDir都做了单位化处理(因为我们希望在方向间插入的时候不会多了和少了他们的权重????)。无论如何,在许多情况下顶点着色器程序中并不需要单位化的outpout.normal。相同的,片段着色器中也基本不需要去单位化output.viewDir。

More Artistic Control(更多艺术的控制)


当我们用一个物理模型去描述轮廓增加的时候,我们实际缺少了艺术的控制;例如,一个CG艺术家不能轻易地通过物理模型那样地淡化或强化一个轮廓。为了允许更多的艺术性的控制,你可以引进一个(正)浮点数属性,然后取|V*N|和那个数字的指数幂的点积。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为mate10耳机声音小怎么办 200打一年到期了怎么办 手机欠费变成2g怎么办 手机4g网用不了怎么办 手机玩王者荣耀卡怎么办 华为隐私空间密码忘记了怎么办 华为手机王者太卡怎么办 华为手机太卡怎么办呢 华为手机5x太卡!怎么办 华为手机玩游戏时太卡了怎么办? 买到华为翻新机怎么办 华为畅享8声音小怎么办 华为5a安全模式怎么办 手机跳屏怎么办金立 苹果手机触控不灵敏怎么办 华为mate8手机声音小怎么办 华为mate9相机无法对焦怎么办 新疆外地电信卡信号差怎么办 华为手机搜索不到wifi怎么办 华为浏览器恢复只有一个页面怎么办 华为手机触摸屏没反应怎么办 快递不给送上楼怎么办 华为荣耀手机声音小怎么办 华为手机来电铃声小怎么办 s弯出来时老压线怎么办 苹果7p手机弯了怎么办 小米手机摔弯了怎么办 华为畅享5没声音怎么办 掌阅语音闪退怎么办 华为mate开屏成排线怎么办 华为mate8电池坏了怎么办 8plus拍照不清晰怎么办 荣耀手环3丢了怎么办 华为mate9手机声音小怎么办 华为麦芒6丢了怎么办 华为麦芒4无法访问移动网络怎么办 自拍时屏幕是白的怎么办 华为麦芒5手机音量小怎么办 小米5x玩王者卡怎么办 小米5x打王者卡怎么办 华为荣耀10卡顿怎么办