Unity | Shader基础知识(第十八集:Stencil应用-透视立方盒子)

news2024/9/20 16:32:43

目录

一、前言

二、场景布置

三、 shader部分

1.图片的部分

2.图片部分纯净代码

3.遮罩部分复习

4.深度写入 ZWrite

5.颜色遮罩ColorMask

6.遮罩纯净代码

四、场景中shader使用

五、作者的碎碎念


一、前言

因为这个内容稍微有点多,我尽力讲清楚了,如果不想看长篇大论的,可以直接下载成品。

上一集我们学了一个知识,叫做Stencil,这集我们把这部分知识扩展应用一下,做一个透视立方盒子。旋转到不同的面,展示不同的植物。这个植物可以是模型,也可以是图片。为了方便,我们用图片。(如图1所示)

图1 成品

二、场景布置

这个盒子是由6个quad的片组成的。把显示的面都放在里面,下方的quad加了草地的材质。(如图2所示)

图2 盒子墙

为了让盒子立体效果更好,在周围加了4个柱子,这四个柱子也只是cube拉长了。(如图3所示)

图3 柱子

因为我们展示了4个植物,所以也要放四个植物的图片,放在不同的方向,因为总要展示植物的正面。(如图4所示一个框一个植物)

图4 植物

最后也是最重要的,我们要沿着四周的墙建一圈遮罩(如图5所示),这个遮罩和墙大小一样,但注意墙的可见面是朝里的,但是遮罩的可见面是朝外的。因为你是从外面往里看,然后被遮住。

图5 遮罩

三、 shader部分

我们的shader分成两个,一个是挂在图片上的,一个是挂在遮罩上的。

1.图片的部分

根据之前学过的内容,图片部分就是之前美女图片的代码,链接如下。

Unity | Shader基础知识(第十七集:学习Stencil并做出透视效果)_unity stencil-CSDN博客

在这篇文章中,我们写了一个在遮罩后面才能看见的美女。不想回顾的,我把代码放在下面。

Shader "Custom/013-2"
{
Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent"
        }
        Stencil
		{
			Ref 1
			Comp Equal
			Pass Keep
		}
 
        Cull Off
 
        CGPROGRAM
        #pragma surface surf Lambert alpha:fade
 
        sampler2D _MainTex;
 
        struct Input
        {
            float2 uv_MainTex;
        };
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

在上面的基础上,我们进行更改 。

需要更改的第一个部分,我们之前是在内部去设定测试模版的。(如图6所示)

图6 模版测试

但我们现在有4个树,每一个都在内部去改,我们就需要好多shader了,这样不方便,于是全部放到资源里。

    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        _SComp("Stencil Comp",Float) = 8
        _SOp("Stencil Op",Float) = 2
    }

 然后在后面引用,只需要在原本的参数后面,书写中括号,再书写引用的符号,就可以了。

        Stencil
		{
            Ref[_SRef]
            Comp[_SComp]
            Pass[_SOp]
		}

这样我们就把参数改成外配的了!~


番外备注:

如果上一集你认真测试了,你会发现,总记不得等于到底是哪个,大于到底是哪个,如果有选项就好了,所以,unity为我们内置了选项,enum。

//选项    引用UnityEngine.Rendering.CompareFunction作为enum
[Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
//选项    引用UnityEngine.Rendering.StencilOp作为enum
[Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2

这时候,你外面的材质球,对应的地方就会变成下拉选项。(如图7所示)

图7 下拉框

这样就方便多了!


因为我们的植物图片并不是一直显示,而是看见遮罩那一面的时候才显示,所以我们必须在遮罩后面渲染,因为遮罩打算放在Transparent层级,所以我们植物就比它晚一个点就行。

Tags
{
"Queue" = "Transparent+1"
}

到此为止,我们图片的所有更改都结束了。

2.图片部分纯净代码
Shader "Custom/014plant"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        [Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
        [Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent+1"
        }
        Stencil
		{
            Ref[_SRef]
            Comp[_SComp]
            Pass[_SOp]
		}

        Cull Off

        CGPROGRAM
        #pragma surface surf Lambert alpha:fade

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
3.遮罩部分复习

也是之前学过的内容,遮罩部分也就是之前的遮罩代码,链接如下。

Unity | Shader基础知识(第十七集:学习Stencil并做出透视效果)_unity stencil-CSDN博客

不想回顾的,我把代码放在下面。

Shader "Custom/013-1"
{
Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
    }
    SubShader
    {
        Tags
        {
        "Queue" = "Transparent-1"
        }
        Stencil
		{
			Ref 1
			Comp Always
			Pass replace
		}
 
        Cull Off
 
        CGPROGRAM
        #pragma surface surf Lambert alpha:fade
 
        sampler2D _MainTex;
 
        struct Input
        {
            float2 uv_MainTex;
        };
 
        void surf (Input IN, inout SurfaceOutput o)
        {
            fixed4 c =tex2D (_MainTex, IN.uv_MainTex);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

首先,我们依然把内置的模版测试改成外部可更改的,这部分略。之后我们需要学两个重要的知识点:深度写入和颜色遮罩。

4.深度写入 ZWrite

这个功能默认是开启的,也是一个非常好用的功能。

如果物体a被物体b挡住了,在大部分时候,我们是不需要去看物体a的,因为被挡住了,所以就看不见了。(如图8所示),方块的一部分,被平面挡住了。

图8 平面挡住方块

但是,你怎么知道方块在后面的?因为计算机检测了深度。如果此时把深度检测关了。计算机就觉得,大家都在第一面上,所以都显示。(如图9所示)

图9 关闭深度检测

 


我们进一步了解一下这个功能,在打开ZWrite时,如果它检测到物体是在前面的,并且,不是透明的(我设置不是透明,如图10所示)。计算机就会考虑,被一个不是透明的物体挡住了,那就不渲染了。所以这里不仅仅是看不见,而是它压根就不画了。

图10 

这里我们设置为普通物体(如图10所示),再打开深度写入,同时我们让前面的固体显示是透明的。就会出现(如图11所示)。后面的物体会以为自己挡住了,所以不画了,就会出现这个景象。

图11 以为自己被挡住

总结:

a.打开深度写入 ZWrite On

这时候,计算机会测试一下, 发现有谁是躲在后面的吗?干脆就不画这部分了

b.关闭了深度写入ZWrite Off

这时候,计算机不管你是否在后面,都会渲染。


5.颜色遮罩ColorMask

我们在unity里每次看图片,都有一个颜色通道功能。(如图12所示)

图12 颜色通道

在shader中,我们也自带了这个功能,我们可以选择只显示一个通道的内容。也可以选择都不显示。(就是前面我们深度写入中,虽然是物体,但做成了不显示的样子) 

标注了颜色遮罩,我们就可以选择只显示某一种或者某几种,或者不显示。

ColorMask RGBA        全部显示

ColorMask 0                全部关闭

ColorMask R                显示红色通道

ColorMask G                显示绿色通道 

ColorMask B                显示蓝色通道 

ColorMask A                显示透明通道 

ColorMask RG             显示红色和绿色通道

ColorMask RB             显示红色和蓝色通道

ColorMask RA             显示红色和透明通道

ColorMask GB             显示绿色和蓝色通道

ColorMask GA             显示绿色和透明通道

ColorMask BA             显示蓝色和透明通道

6.遮罩纯净代码

所以,我们的遮罩应该就是一个不显示的物体,要把颜色遮罩设置为0,但同时它不能挡住后面的花花草草,所以要把深度检测关了。

Shader "Custom/014"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _SRef("Stencil Ref",Float) = 1
        [Enum(UnityEngine.Rendering.CompareFunction)] _SComp("Stencil Comp",Float) = 8
        [Enum(UnityEngine.Rendering.StencilOp)] _SOp("Stencil Op",Float) = 2
    }

    SubShader
    {
        Tags { "Queue" = "Geometry" }

        ZWrite off
        ColorMask 0
       
       Stencil
       {
        Ref[_SRef]
        Comp[_SComp]
        Pass[_SOp]
       }

        CGPROGRAM
       #pragma surface surf Lambert
       sampler2D _MainTex;

       struct Input
       {
       float2 uv_MainTex;
       };

       void surf(Input IN,inout SurfaceOutput o)
       {
       o.Albedo = tex2D (_MainTex, IN.uv_MainTex);
       
       }
        ENDCG
    }
    FallBack "Diffuse"
}

四、场景中shader使用

遮罩和图片的shader需要各自的材质并创建,这里我就略过了,直接进入参数配置。

我们的遮罩和植物图片应该是一一对应的。

对应植物1的遮罩:

植物1:

其他部分不变,其他植物使用不同的数就行,如3,4,5

这样就完成了所有的设置了。

五、作者的碎碎念

这集设置场景的部分比较多,但shader代码和之前差距不大哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1933541.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VAE论文阅读

在网上看到的VAE解释,发现有两种版本: 按照原来论文中的公式纯数学推导,一般都是了解生成问题的人写的,对小白很不友好。按照实操版本的,非常简单易懂,比如苏神的。但是却忽略了论文中的公式推导&#xff…

jquery中pdf在页面的显示和导出

jquery中pdf在页面的显示和导出 01 显示pdf01 .pdf结尾在线接口显示到页面 (pdf.js库怎么安装及使用):只显示一页02 如何用PDF.JS显示整个PDF (而不仅仅是一页)?03 jQuery实现在线预览PDF文件(通过a标签链接跳转): 02 …

【网络安全】PostMessage:分析JS实现XSS

未经许可,不得转载。 文章目录 前言示例正文 前言 PostMessage是一个用于在网页间安全地发送消息的浏览器 API。它允许不同的窗口(例如,来自同一域名下的不同页面或者不同域名下的跨域页面)进行通信,而无需通过服务器…

【STM32 HAL库】全双工DMA双buffer的I2S使用

1、配置I2S 我们的有效数据是32位的,使用飞利浦格式。 2、配置DMA **这里需要注意:**i2s的DR寄存器是16位的,如果需要发送32位的数据,是需要写两次DR寄存器的,所以DMA的外设数据宽度设置16位,而不是32位。…

ArrayLis练习

代码呈现 import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {//创建集合ArrayList<String> list new ArrayList();//添加元素list.add("A");list.add("B");list.add("C");list.add(&quo…

222.买卖股票的最佳时机(力扣)

代码解决 class Solution { public:int maxProfit(vector<int>& prices) {// 初始化最小买入价为第一个价格int min1 prices[0];// 初始化最大利润为0int max1 0;// 从第二天开始遍历价格数组for (int i 1; i < prices.size(); i) {// 计算当前价卖出的利润&a…

C++:智能指针shared_ptr、unique_ptr、weak_ptr的概念、用法即它们之间的关系

智能指针 (1)概述 A.Why&#xff08;C为什么引入智能指针&#xff09; C引入智能指针的根本原因就是解决手动管理动态内存所带来的问题&#xff0c;手动管理动态内存常见的问题如下&#xff1a;内存泄漏、悬挂指针、释放操作未定义等 内存泄漏问题&#xff1a; 当程序用光了它…

React的usestate设置了值后马上打印获取不到最新值

我们在使用usestate有时候设置了值后&#xff0c;我们想要更新一些值&#xff0c;这时候&#xff0c;我们要想要马上获取这个值去做一些处理&#xff0c;发现获取不到&#xff0c;这是为什么呢&#xff1f; 效果如下&#xff1a; 1、原因如下 在React中,当你使用useState钩子…

线程安全(七)ReentrantLock 简介、Condition 条件变量、锁的工作原理、synchronized 与 Lock 的区别

目录 一、ReentrantLock 简介1.1 Reentrant 的特性:1.2 基本语法1.3 ReentrantLock 的主要方法:1.4 lock()、tryLock()、lockInterruptibly() 的区别:二、Condition 条件变量2.1 什么是 Condition 条件变量?2.2 Condition 的核心方法:2.3 Condition 使用示例1:等待与唤醒…

PJA1介导的焦亡抑制是鼻咽癌产生耐药性的驱动因素

引用信息 文 章&#xff1a;PJA1-mediated suppression of pyroptosis as a driver of docetaxel resistance in nasopharyngeal carcinoma. 期 刊&#xff1a;Nature Communications&#xff08;影响因子&#xff1a;14.7&#xff09; 发表时间&#xff1a;2024年6月2…

LLaMA-Factory

文章目录 一、关于 LLaMA-Factory项目特色性能指标 二、如何使用1、安装 LLaMA Factory2、数据准备3、快速开始4、LLaMA Board 可视化微调5、构建 DockerCUDA 用户&#xff1a;昇腾 NPU 用户&#xff1a;不使用 Docker Compose 构建CUDA 用户&#xff1a;昇腾 NPU 用户&#xf…

变阻器与电位器有什么区别?

变阻器和电位器都是可以改变电阻值的电子元件&#xff0c;它们在电路中的作用和调节方式有一定的相似性&#xff0c;但它们之间还是存在一些区别的。 1. 结构上的区别&#xff1a;变阻器主要由固定电阻体和可动滑片组成&#xff0c;通过滑动滑片来改变电阻体的电阻值。而电位器…

数据库(创建数据库和表)

目录 一&#xff1a;创建数据库 二&#xff1a;创建表 2.1&#xff1a;创建employees表 2.2&#xff1a;创建orders表 2.3&#xff1a;创建invoices表 一&#xff1a;创建数据库 mysql> create database mydb6_product; Query OK, 1 row affected (0.01 sec) mysql&g…

linux centos limits.conf 修改错误,无法登陆问题修复 centos7.9

一、问题描述 由于修改/etc/security/limits.conf这个文件中的值不当&#xff0c;重启后会导致其账户无法远程登录&#xff0c;本机登录。 如改成这样《错误示范》&#xff1a; 会出现&#xff1a; 二、解决 现在知道是由于修改limits.conf文件不当造成的&#xff0c;那么就…

智慧农业新纪元:解锁新质生产力,加速产业数字化转型

粮食安全乃国家之根本&#xff0c;“浙江作为农业强省、粮食生产重要省份&#xff0c;在维护国家粮食安全大局中肩负着重大使命。浙江粮食产业经济年总产值已突破4800亿元&#xff0c;稳居全国前列&#xff0c;然而&#xff0c;同样面临着规模大而不强、质量效益有待提升、数字…

JVM高频面试点

文章目录 JVM内存模型程序计数器Java虚拟机栈本地方法栈Java堆方法区运行时常量池 Java对象对象的创建如何为对象分配内存 对象的内存布局对象头实例数据对齐填充 对象的访问定位 垃圾收集器找到垃圾引用计数法可达性分析&#xff08;根搜索法&#xff09; 引用概念的扩充回收方…

字符数组的魅力:C语言字符数组与字符串编程实践

1.概念 字符数组&#xff0c;数组元素是char(字符型)的数组&#xff0c;它可以是一维数组&#xff0c;也可以是二维数组。 2.定义的时候赋值 char ch1[]{c,h,i,n,a}; char ch2[]{"china"}; //相当于 char ch2[] "china"; 元素个数为6&#xff0c;默认会…

探索Linux世界 —— shell与权限的相关知识

一、shell以及其运行原理 1、什么是shell Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#x…

6个高效再利用的UI作品集设计模板

UI 作品集是指用户界面设计师的个人作品集。它展示了设计师的设计能力、技巧和风格&#xff0c;也是充分展示他们设计能力的证明。优秀的UI 作品集应具有简洁明了、美观大方、良好的互动体验和明确的目标。本文将从两个方面的介绍 Ui 作品集模板的全部内容&#xff1a;UI 作品集…

Linux - 基础开发工具(yum、vim、gcc、g++、make/Makefile、git、gdb)

目录 Linux软件包管理器 - yum Linux下安装软件的方式 认识yum 查找软件包 安装软件 如何实现本地机器和云服务器之间的文件互传 卸载软件 Linux编辑器 - vim vim的基本概念 vim下各模式的切换 vim命令模式各命令汇总 vim底行模式各命令汇总 vim的简单配置 Linux编译器 - gc…