在上一个例子中,我们得到了由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,然后给一个球体可以看到我们上次见到的绿色假彩色球只剩下南半球了:

从正面看起来像是实心的

稍微倾斜一下从上面看过去可以看到球体内部是空心的,所以我用膜和毛笔来比喻这个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还有更神奇的地方等待我们去发现~

转载于:https://www.cnblogs.com/decode1234/p/6930530.html

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

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

    http://blog.csdn.net/mobanchengshuang/article/details/38731035 上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单 ...

  2. rgb立方体用html语言,解读Unity中的CG编写Shader系列一

    CG=C for Graphics  用于计算机图形编程的C语言超集 前提知识点: 1.CG代码必须用 CGPROGRAM ... ENDCG括起来 2.顶点着色器与片段着色器的主函数名称可随意,但需 ...

  3. 解读Unity中的CG编写Shader系列二

    转自 http://www.itnose.net/detail/6095974.html 上一篇文章的例子中我们可以看到顶点着色器的输出参数可以说是直接作为了片段着色器的形参传递过来,那么不由得一个问 ...

  4. unity 2020 怎么写shader使其接受光照?_如何在Unity中造一个PBR Shader轮子

    之前有业界大佬建议我去了解下Unity的PBR.说来惭愧,我查找了下资料才发现自己在这方面的知识居然是一片空白.经过几周的学习与尝试我对这一块算是有了初步的了解,于是写了这篇文章,一方面对自己学到的东 ...

  5. 关于Unity中Shader的内置值

    Unity provides a handful of builtin values for your shaders: things like current object's transforma ...

  6. unity build-in管线中的PBR材质Shader分析研究

    PBR分析 前言 我理解的PBR PBR组成部分 直接光漫反射 直接光镜面反射(高光) 间接光漫反射 间接光镜面反射 最终加和 结果 前言 近来,用到了几次Surface Shader,对于其封装好的 ...

  7. Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

    转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交 ...

  8. 【Unity3D Shader编程】之五 圣诞夜篇 Unity中Shader的三种形态对比 混合操作合辑

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  9. Unity Shader:雾的数学运算以及在Unity中使用Fog

    文章目录 1,Unity Fog效果图 2,uniform fog均匀雾的数学公式推导 3,Fog在Unity中的应用 4,Unity Fog的源码分析 5,Unity exp fog VS unif ...

最新文章

  1. java 工厂的变形模拟的各种应用
  2. 2.1 数个常用的网络命令
  3. Lync在Internet上无法登录问题之一
  4. 数字图像处理—亮度变换与空间滤波—亮度变换函数
  5. floatmap 二维数组_用J中的多维数组进行Arrays.fill
  6. 秦九韶算法matlab程序,数值分析matlab程序实例.doc
  7. linux vi如何输入井号,为什么我可以使用井号(#)来破坏vim用户功能命名规则
  8. php 双向队列,PHP实现一个双向队列
  9. 沟通技巧系列 - 积极和移情倾听
  10. 让UpdatePanel支持上传文件:解决当页面显式设置document.domain时提示的500错误
  11. java c3p0 存储过程_JAVA Spring 连接池 调用 Oracle 存储过程的问题?
  12. 佛山高新区构建大数据产业新生态
  13. notepad++行首行尾添加字符
  14. python 类 super_python的类的super()
  15. 光立方体c语言程序,444光立方程序C语言源代码 - 444光立方程序怎么写 光立方原理图、源代码及制作教程...
  16. 编译原理 --- 递归下降分析器
  17. 九、CompletableFuture异步编排
  18. Vue简单快速上手 idea版
  19. 【机器学习】P18 反向传播(导数、微积分、链式法则、前向传播、后向传播流程、神经网络)
  20. Xilinx ISE_14.7安装包下载

热门文章

  1. c语言sum出错,ACM:Sum Problem 求和问题C语言源码
  2. 一台古老电脑之维修记
  3. API网关-apisix源码剖析,初始化依赖
  4. 【忘川风华录】交互负责人:在奇幻和萌趣中探索国风的立体体验
  5. LUT Utility for FCPX(Luts调色文件加载工具)支持M1
  6. 题目:JavaWeb乐购资源管理系统(附源码链接免费下载)
  7. 优化mysql slave的同步速度
  8. acos1.2的下载及CentOS7下安装nacos1.2
  9. Guava Cache用法介绍
  10. Python笔记——Django路由系统