在上一个样例中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上。

这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁、后面剪裁(front face culling and back face culling)来达到透明效果。

当一个mesh组件的信息被传递后,我们能够通过代码决定哪些部分渲染(render)出来。而哪些部分不要。这个过程就像把那些不要的部分剔除了,我们看不到他。尽管他的mesh信息还在。可是我们的GPU不会去处理它。肯定比剔除前GPU的性能消耗要低。

这个过程就好比我们的mesh组件是一个透明的膜,我们如果这个胶纸我们根本看不到,而片段着色器在着色的时候像毛笔选择性地上色。最后的效果是我们可能看到膜的一部分是可见的,可是不见的地方,膜还是存在的,仅仅是我们没有给他上色。我们既看不看他们,也不须要再他们上面画宝贵的墨水(GPU并行处理能力)

所以我们能够来改造一下上一个样例中的经度绿色假彩色球体,将其经度>0.5的部分擦掉,那么代码应该对应改动为:

Pass{
Cull Off // 关掉裁剪模式,作用后面再说
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct vertexOutput {
float4 pos : SV_POSITION;
//由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的
float4 posInObjectCoords : TEXCOORD0;
};
vertexOutput vert(appdata_full input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
//直接把texcoord传递给片段着色器
output.posInObjectCoords = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
//当坐标的y值大于0.5的时候擦除片段
if (input.posInObjectCoords.y > 0.5)
{
discard;
} //其余部分仍然按y值大小生成经度绿色球
return float4(0.0, input.posInObjectCoords.y , 0.0, 1.0);
}
ENDCG
}

那么把这个shader给material,然后给一个球体能够看到我们上次见到的绿色假彩色球仅仅剩下南半球了:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbW9iYW5jaGVuZ3NodWFuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

从正面看起来像是实心的

略微倾斜一下从上面看过去能够看到球体内部是空心的,所以我用膜和毛笔来比喻这个render过程。

我们来把球体换成立方体,看看是什么样子:

能够发现这是一个诡异的立方体,立方体的六个面分别仅仅绘制了一半,且都是以下的一半。

为啥立方体和球体上的效果区别这么大呢?

由于立方体是直角坐标系,球体是极坐标系啊…………扇耳光~~~还给老师了吗 吗吗吗吗吗

同理我们将>0.5改为<0.5,就能够得到球体的北半球。

这是最简单的表面剔除(cuteaway)

更好一点的表面剔除是将片段的位置从对象坐标系转换到世界坐标系,然后依据基础矩阵进行变换能够计算出哪些片段位于其它球体的内部(原始半径是0.5),然后再将位于其它球体内部的表面剔除,这种话假如两个球互相重叠一部分,那么即使两个球互相绕着自己的球心怎么旋转。没有重叠的部分都会被绘制,而重叠的部分不会被绘制,反正我们看不到,这样省性能。

由于即使球体旋转。物体的坐标经过unity的内建矩阵变换为世界坐标后,重叠部分的世界坐标是固定的。所以不会出现两个球体重叠部分表面被裁剪后,旋转一个球之后慢慢看到被裁剪的那个洞了。

(由于前面的方法是按对象坐标系裁剪的)

前面与后面剪裁

刚刚的代码中我们看到了Cull Off。这行代码位于CGPROGRAM标记之前,所以他不属于CG的范畴。它是我们Unity中的ShaderLab的指令。所以他不须要分号来结尾。

Cull Off 即为关掉三角形剪裁(为何突然冒出来了三角形,脑补一下,我们的立体图像在计算机中是以三角形拼凑的,正由于如此我们的三维图形才会产生锯齿,那都是三角形的功劳啊)

Cull Front 为前面(外部)剪裁

Cull Back 为后面(内部)剪裁,而这是我们全部Shader的默认模式,也就是说假设Shader不是你自己写的。非常可能转动我们的半球的时候,你仅仅看的到前方的曲面而不是半球曲面,不信你能够拖个模型看看

至于为何默认是后面剪裁呢。由于大部分情况下我们的渲染都是对整个三维体的表面进行的。那么既然表面所有被渲染,你就看不到正背对着你的部分。所以默认后面剪裁会节省非常多物理性能啊!

只是既然我们将表面进行了擦除。那么我们能够透过被擦除的部分看到背面的内表面,那么我们应该改动这个剪裁模式了,就像一个房子有房顶。我们从正上方看不到房子里面的地板,所以地板应该属于剪裁的范畴。可是假设我们把房顶擦除了(推开房顶),还看不到地板那就有点恐怖了,这样的事情就要切换剪裁模式

为了更直观的明确这两种模式。我们改动上面的代码为内部/外部剪裁的双通道(Pass)。而且每一个Pass中的最后着色不同(红和绿)

要明确一点,Unity中的Shader仅仅会运行一个SubShader,可是会运行全部的Pass

改动后的代码:

Pass{
Cull front // 外部剪裁,那么这个通道能够理解为是给篮球的内表面上色
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct vertexOutput {
float4 pos : SV_POSITION;
//由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的
float4 posInObjectCoords : TEXCOORD0;
};
vertexOutput vert(appdata_full input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
//直接把texcoord传递给片段着色器
output.posInObjectCoords = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
//当坐标的y值大于0.5的时候擦除片段
if (input.posInObjectCoords.y > 0.5)
{
discard;
} //其余部分仍然按y值大小生成经度绿色球
return float4(0.0, input.posInObjectCoords.y , 0.0, 1.0);
}
ENDCG
} Pass{
Cull back //内部剪裁。那么这个通道能够理解为是给篮球的外表面上色
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct vertexOutput {
float4 pos : SV_POSITION;
//由顶点着色器输出mesh信息中的纹理坐标,这个坐标是以对象为坐标系的
float4 posInObjectCoords : TEXCOORD0;
};
vertexOutput vert(appdata_full input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
//直接把texcoord传递给片段着色器
output.posInObjectCoords = input.texcoord;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
//当坐标的y值大于0.5的时候擦除片段
if (input.posInObjectCoords.y > 0.5)
{
discard;
} //其余部分仍然按y值大小生成经度红色球
return float4(input.posInObjectCoords.y, 0.0 , 0.0, 1.0);
}
ENDCG
}

我们完毕了一个拥有两个Pass的Shader,如今看看球体是什么样子:

从顶部往下看。因为全然垂直看下去我们不知道这个球体的凹进去的还是凸出来的。仿佛还是我们上个样例中的绿色经度球,

我们再从底部网上看:

我们还是不知道这个红黑部分是凹的还是凸的,毕竟这是个半球,垂直半球去看没啥发现

我们再从正面偏上看过去:

可见绿黑部分是凹进去的内表面,红黑部分是凸起的外表面~

至此,我们已经能够随心所欲地控制我们的表面哪些地方可见或者不可见啦。

接下来CG还有更奇妙的地方等待我们去发现~

假设我的博客对您有帮助或者您有不论什么疑问,欢迎增加重庆u3d交流QQ群我会给您解答:68994667,也能够加群与我们一同交流技术

解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式的更多相关文章

  1. [转]解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式

    在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁.后面 ...

  2. 解读Unity中的CG编写Shader系列四(unity中的圆角矩形shader)

    转自 http://www.itnose.net/detail/6097625.html 上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做 ...

  3. 解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader

    上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,可是又非经常常使用的样例:把一张图片做成圆角矩形 例3:圆角矩形Shader 好吧我承认在做这个样例的时候走了不少弯路,因 ...

  4. [转]解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader

    上篇文章中我们掌握了表面剔除和剪裁模式这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做成圆角矩形 例3:圆角矩形Shader好吧我承认在做这个例子的时候走了不少弯路,由于本人对矩 ...

  5. 解读Unity中的CG编写Shader系列八(镜面反射)

    转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...

  6. [转]解读Unity中的CG编写Shader系列9——镜面反射

    讨论完漫反射之后,接下来肯定就是镜面反射了在开始镜面反射shader的coding之前,要扩充一下前面提到的知识,加深理解镜面反射与漫反射的区别.注:这篇文章实现的镜面反射是逐顶点着色(per-ver ...

  7. [转]解读Unity中的CG编写Shader系列7——漫反射

    如果前面几个系列文章的内容过于冗长缺乏趣味着实见谅,由于时间原因前面的混合部分还没有写完,等以后再补充,现在开始关于反射的内容了.折射与反射在物理世界中,光的反射与折射往往是同时存在的,光源由真空或者 ...

  8. 解读Unity中的CG编写Shader系列七(不透明度与混合)

    转自http://www.itnose.net/detail/6098539.html 1.不透明度 当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段 ...

  9. 解读Unity中的CG编写Shader系列三

    转自http://www.itnose.net/detail/6096068.html 在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章 ...

随机推荐

  1. HDU 1426 Sudoku Killer(搜索)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1426 题意很明确,让你解一个9*9的数独. DFS即可. #include <cstdio> ...

  2. 分析dump

    一.使用jmap工具生成dump文件 二.MAT工具的下载和安装 三.使用MAT工具进行内存泄露分析  -- Step 1 :  ps –ef | grep <process> (whic ...

  3. NOIP 2017 赛后反思 [补档]

    首先写一下比赛的情况: D1: T1: 之前做过类似的题目, 因而知道大致的结论, 迅速完成. T2: 貌似直接模拟就可以了, 涉及到字符串信息提取, 比较麻烦, 因而想放到最后做. T3: 非常简洁 ...

  4. sql server 高可用故障转移(1)

    原文:sql server 高可用故障转移(1) 群集准备工作 个人电脑 内存12G,处理器 AMD A6-3650CPU主频2.6GHz 虚拟机 VMware Workstation 12 数据库  ...

  5. WCF 与其它技术的比较

    以下特性WCF都支持 特性 Web Service .Net Remoting Enterprise Services WSE(WS Enhancements) MSMQ 具有互操作性的Web服务 支 ...

  6. Web性能压力测试工具之WebBench详解

    PS:在运维工作中,压力测试是一项很重要的工作.比如在一个网站上线之前,能承受多大访问量.在大访问量情况下性能怎样,这些数据指标好坏将会直接影响用户体验.但是,在压力测试中存在一个共性,那就是压力测试 ...

  7. [置顶] kubernetes资源类型--Volume

    在Docker的设计实现中,容器中的数据是临时的,即当容器被销毁时,其中的数据将会丢失.如果需要持久化数据,需要使用Docker数据卷挂载宿主机上的文件或者目录到容器中.在K8S中,当Pod重建的时候 ...

  8. npm中package-lock.json的作用:npm install安装时使用

    简单理解: XYZ 的格式 对应为: 主版本号.次版本号.修订号,版本号递增规则如下: 主版本号:当你做了不兼容的 API 修改, 次版本号:当你做了向下兼容的功能性新增, 修订号:当你做了向下兼容的 ...

  9. samba 服务实现在windows共享文件

    1. 什么是samba Samba服务类似于windows上的共享功能,可以实现在Linux上共享文件,windows上访问,当然在Linux上也可以访问到. 是一种在局域网上共享文件和打印机的一种通 ...

  10. SparkMLlib分类算法之逻辑回归算法

    SparkMLlib分类算法之逻辑回归算法 (一),逻辑回归算法的概念(参考网址:http://blog.csdn.net/sinat_33761963/article/details/5169383 ...