顶点程序经典案例——树木生长
树木生长Shader
一、介绍
大家好,我是阿赵。这次来做一个树木生长的Shader。
顶点程序作为整个渲染管线里面和片段程序并列的两大可控过程之一,一直存在感都比较低。我们平时制作的效果,很多都是在片段程序里面实现的计算,顶点程序一般只是用来计算一下坐标系转换。
这次介绍的树木生长shader,我个人感觉是顶点程序的一个比较经典的应用,通过控制模型的顶点,做出一棵树的生长动画,还是比较有意思的。
另外一个知识点,就是黑白遮罩的运用。在深入学习各种效果的Shader编写之后,会发现很多效果的计算基础,都是模型不同部位的黑白颜色分布的计算。比如说透明度的计算,黑透白不透,比如边缘光的计算,边缘计算出白色,内部计算出黑色,等。
这个例子里面,黑白色控制了顶点是否显示,控制了树木生长的边缘,控制了刚长出来的部分的颜色,诸如此类。如果明白了黑白关系,在编写Shader的道路上,可以说是跨进了一大步。
其实我知道我在一开始写这么多废话,一般也不会有人看的。所以还是快点说制作过程吧。完整Shader在最后面。
二、制作过程说明
1、准备工作:
看到上面的视频,可能有些朋友会说,是不是直接在3DsMax里面做一段动画,然后直接在Unity里面播放呢?
其实不是的。我这里只在3DsMax里面准备了一棵树的模型,它包括了树干和树叶2个部分。

把模型导出fbx然后导入Unity后,把贴图附上,会看到这个模型的效果如下,并没有任何的动画。

地面是为了好看我随便找了一张贴图赋予了一个地面,这个不重要,我们只要关系树干和树叶就行了。
2、展UV
先说一下,为什么树木能实现生长的效果。
为了让树木能从根部到顶部,再到树叶逐渐的出现,我必须找到一个信息,是从树木根部一直到叶子渐变的。为了看得比较清晰,我先把叶子隐藏了,单纯用树干来做说明。

这种信息可以有很多,举个例子:
1.顶点颜色
2.UV坐标
3.贴图颜色
4.顶点坐标
等
通过这些手段,理论上都能实现到这种渐变的效果。但顶点坐标只能是从上到下,或者从左到右之类线性的控制,这里的树枝有可能是横向纵向甚至是拐弯的,所以并不适合用顶点坐标来做。所以我们可以在顶点颜色、UV坐标、贴图颜色这些数据里面选择一种比较容易实现的来做,都无所谓。
我这里选择的是UV坐标。
由于模型已经有了UV1信息用于漫反射贴图的UV坐标计算了。所以我要展一个UV2。

展完之后的UV2大概是这个样子的,我使用了uv的u坐标,从左往右在0-1的区间渐变。
把展好UV后的模型导入到Unity,然后单独显示一下我们需要的坐标看看。
3、检查UV信息显示
这里插一个知识点,介绍一下怎么单独去看模型的某个数据。
比如我现在要看UV2的信息,我可以在顶点程序里面先读取了uv2信息传入到片段程序,然后在最后的输出时
return half4(i.uv2.xxx,1);
这样,就可以单独把我们需要的信息当做颜色显示出来。
我这里的UV2的u坐标信息,显示完是这样的:

可以看到,现在树干从根部到树枝,是有一个由黑到白的渐变。
如果我想把颜色反过来,根部是白色,树枝是黑色,可以这样:
float val = 1- i.uv2.x
return half4(val.xxx,1);
这样,就能得到了之前显示的那个渐变效果了:

4、控制黑白渐变的过程
上面的黑白渐变图,发现有一个问题,就是黑白渐变的区域太大了,我们想做树木生长,一般是需要有一个比较明显的黑白分割线过渡的。
为了实现过渡范围的控制,可以使用smoothstep方法来控制:
float v2Val = 1 - v.uv2.x;
float heightVal = saturate(v2Val + _height);
float growVal = smoothstep(_min, _max, heightVal);
还是那个规则,黑的地方不显示,白的地方显示,所以就可以得到下面这个效果,可以看看黑白范围和最后显示效果的对比:




5、根据法线方向做树枝大小缩放
树木的生长并不是圆柱形生长出来,而是生长出来的地方是尖的,长出一段距离之后才慢慢变粗。
这个效果实现起来不难,还是刚才的黑白图过渡部分,我们可以使用黑白关系,然后加上模型顶点法线的方向,来做一个顶点沿着法线方向的缩放。
由于模型显示的过渡范围和变尖的过渡范围可能不一致,所以虽然都是用smoothstep来控制范围,但min和max的值可以不一样。
float v2Val = 1 - v.uv2.x;
float heightVal = saturate(v2Val + _height);
float growVal = smoothstep(_min, _max, heightVal);
heightVal = smoothstep(_endMin, _endMax, heightVal);


6、生长颜色的变化
最后,我还想实现一种效果,在树木刚长出来的时候,颜色是比较浅的,然后到了生长完成的时候,颜色会变深:


为了实现这种效果,我继续利用了刚才的黑白渐变过渡的信息,给他叠加一个颜色:
half3 diffuseCol = (1 - i.growVal)*_growCol + col.rgb;
这样在过渡的部分,就会乘以一个growCol,在生长完成之后,就纯是漫反射贴图的颜色。
7、树叶部分
其实刚才我们已经把整个shader做完了。树叶的部分,实际上不需要额外写shader去实现,因为展UV的时候,树叶也是根据出现的先后顺序,展UV在树枝的后面的。

这里我比较的偷懒,把相同形状的树叶的UV展在了一起了,所以实际出现的效果,就是同样形状的树叶会一起长出来。如果想效果更真实有点,可以根据整棵树的树枝生长先后顺序,来排列这些树叶的UV2.


三、完整shader
Shader "azhao/TreeGrow"
{Properties{_MainTex("Texture", 2D) = "white" {}_AlphaMap("AlphaMap", 2D) = "white" {}_height("height", Range(-1 , 1)) = 0_min("min", Range(0 , 1)) = 0_max("max", Range(0 , 1)) = 1_endMin("endMin", Range(0 , 1)) = 0_endMax("endMax", Range(0 , 1)) = 1_growCol("growCol", Color) = (0,1,0,0) }SubShader{cull offTags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float2 uv2 : TEXCOORD1;float3 normal:NORMAL;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float2 uv2 : TEXCOORD1;float growVal : TEXCOORD2;};uniform float _min;uniform float _max;uniform float _height;uniform float _endMin;uniform float _endMax;uniform sampler2D _MainTex;uniform float4 _MainTex_ST;uniform float4 _growCol;uniform sampler2D _AlphaMap;v2f vert (appdata v){v2f o; o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.uv2 = v.uv2;float v2Val = 1 - v.uv2.x;float heightVal = saturate(v2Val + _height);float growVal = smoothstep(_min, _max, heightVal);heightVal = smoothstep(_endMin, _endMax, heightVal);heightVal = max(heightVal, growVal);float3 offsetVal = v.normal*heightVal - v.normal;o.vertex = UnityObjectToClipPos(v.vertex+ float4(offsetVal,1));o.growVal = growVal;return o;}half4 frag (v2f i) : SV_Target{half4 col = tex2D(_MainTex, i.uv);half3 diffuseCol = (1 - i.growVal)*_growCol + col.rgb;half4 alphaCol = tex2D(_AlphaMap, i.uv);float alpha = alphaCol.r*i.growVal;clip(alpha - 0.5);return half4(diffuseCol,alpha);}ENDCG}}
}
相关文章:
顶点程序经典案例——树木生长
树木生长Shader一、介绍 大家好,我是阿赵。这次来做一个树木生长的Shader。 顶点程序作为整个渲染管线里面和片段程序并列的两大可控过程之一,一直存在感都比较低。我们平时制作的效果,很多都是在片段程序里面实现的计算,顶点程序…...
在云计算环境下保护Java应用程序的有效措施
云计算(Cloud)技术是近年来计算机科学的一个重要突破。大多数组织已经通过将自己的应用程序移入云平台而获益。不过,如何保证应用程序在第三方服务器上的安全性,是一项艰巨的挑战。 在本文中,我们将重点讨论Java&…...
vscode-markdown-代码片段及快捷键设置
代码片段及快捷键设置 主要为了插入表格和图片标签节约一点输入时间 代码片段设置 ctrlshiftp 打开面板输入 configure user snippets选择markdowncopy如下设置放入{}中 "tb4*4": {"prefix": "tb4*4","body": ["| $1 | $2 | $…...
ModelNet40数据集
跑PointNet,modelnet40数据集时; 有些人直接用.off文件;——【CAD模型】普林斯顿形状Banchmark中的.off文件遵循以下标准: OFF文件全是以OFF关键字开始的ASCII文件。下一行说明顶点的数量、面片的数量、边的数量。 边的数量可以安全地省略。对模型不会有影响(可以为…...
【都2023年了,还在问网络安全怎么入门】
前言 【都2023年了,还在问网络安全怎么入门】所以这一期就出一一个怎么学习网络安全的学习路线和方法,觉得有用的话点赞收藏下 首先咱们聊聊,学习网络安全方向通常会有哪些问题 1、打基础时间太长 学基础花费很长时间,光语言都有…...
Apple Xcode 14.3 (14E222b) 正式版发布下载
Command Line Tools for Xcode 14, tvOS 16 & watchOS 9 Simulator Runtime 请访问原文链接:https://sysin.org/blog/apple-xcode-14/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org Xcode 14 包含了在所有 Ap…...
【Linux】sar常用选项介绍
sar 使用 安装sysstat apt-get install sysstat -y #或 yum install sysstat -y选项 用法: sar [ 选项 ] [ <时间间隔> [ <次数> ] ] 选项: [ -A ] [ -B ] [ -b ] [ -C ] [ -D ] [ -d ] [ -F [ MOUNT ] ] [ -H ] [ -h ] [ -p ] [ -q ] [ -r [ ALL ] ]…...
PHP 单笔转账到支付宝账户,支付宝公钥证书实现版本
支付宝某些业务只能使用公钥证书方式来验签 如:即使转账 红包等 笔者就要实现这样一个功能,【单笔转账到支付宝账户】,采用支付宝公钥证书签名来实现。 话不多说,流程先走起 第一步:下载支付宝秘钥生成器 由于我们使…...
第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组 E 题
颜色平衡树问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序问题描述 格式输入 输入的第一行包含一个整数 n ,表示树的结点数。 接下来 n 行,每行包含两个整数 Ci , Fi,用一个空格分隔,表示第 i 个结点 …...
Python 小型项目大全 21~25
二十一、DNA 可视化 原文:http://inventwithpython.com/bigbookpython/project21.html 脱氧核糖核酸是一种微小的分子,存在于我们身体的每个细胞中,包含着我们身体如何生长的蓝图。它看起来像一对核苷酸分子的双螺旋结构:鸟嘌呤、…...
MinIO从信息泄漏到RCE
文章目录信息泄露漏洞利用漏洞分析漏洞修复RCE漏洞分析参考文章信息泄露 漏洞利用 如果MinIO以集群方式部署,存在信息泄露漏洞,攻击者可以通过HTTP请求获取目标进程的所有环境变量,包括MINIO_SECRET_KEY和MINIO_ROOT_PASSWORD. vulhub有环…...
202.Spark(九):SparkStreaming案例实操
目录 一、启动zookeeper,kafka基础环境 二、项目导好jar包,并且创建源数据,并在kafka中测试能否消费到数据...
GlusterFS(GFS)分布式文件系统
目录 一.文件系统简介 1.文件系统的组成 2.文件系统的作用 3.文件系统的挂载使用 二.GlusterFS概述 1.GlusterFS是什么? 2.GlusterFS的特点 3.GlusterFS术语介绍 3.1 Brick(存储块) 3.2 Volume(逻辑卷) 3.3…...
ChatGPT文本框再次升级,打造出新型操作系统
在ChatGPT到来之前,没有谁能够预见。但是,它最终还是来了,并引起了不小的轰动,甚至有可能颠覆整个行业。 从某种程度上说,ChatGPT可能是历史上增长最快的应用程序,仅在两个多月就拥有了1亿多活跃用户&…...
DPU02国产USB转UART控制芯片替代CP2102
目录DPU02简介DPU02芯片特性应用DPU02简介 DPU02是高度集成的USB转UART的桥接控制芯片,该芯片为RS-232设计更新为USB设计,并简化PCB组件空间提供了一个简单的解决方案。 DPU02包括了一个USB 2.0全速功能控制器、USB收发器、振荡器、EEPROM和带…...
Softing新版HART多路复用器软件支持西门子控制器
用于访问配置和诊断数据的HART多路复用器软件——Softing smartLink SW-HT,现在支持西门子的ET200远程IO和FDT/DTM接口。 smartLink SW-HT是一个基于Docker容器的软件应用。通过该软件,用户可以快速地访问以太网远程IO的HART设备,并且无需额外…...
〖Python网络爬虫实战⑫〗- XPATH语法介绍
订阅:新手可以订阅我的其他专栏。免费阶段订阅量1000python项目实战 Python编程基础教程系列(零基础小白搬砖逆袭) 说明:本专栏持续更新中,目前专栏免费订阅,在转为付费专栏前订阅本专栏的,可以免费订阅付费…...
实例方法、类方法、静态方法、实例属性、类属性
背景:今天在复习类相关知识的时候,突然想到这几种类型的方法的区别和用法,感觉有点模棱两可,于是总结一下,加深记忆。 定义:想要区别和理解几种方法,首先要定义一个类,要在类中加深…...
数据结构---二叉树
专栏:数据结构 个人主页:HaiFan. 专栏简介:这里是HaiFan.的数据结构专栏,今天的内容是二叉树。 二叉树树的概念及结构二叉树概念及结构二叉树的概念二叉树的存储结构二叉树的顺序结构及实现大根堆和小根堆堆的实现及其各个接口堆的…...
CMake——从入门到百公里加速6.7s
目录 一、前言 二、HelloWorld 三、CMAKE 界面 3.1 gui正则表达式 3.2 GUI构建 四 关键字 4.1 add_library 4.2 add_subdirectory 4.3 add_executable 4.4 aux_source_directory 4.5 SET设置变量 4.6 INSTALL安装 4.7 ADD_LIBRARY 4.8 SET_TARGET_PROPERTIES 4.9…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
