Unity可视化Shader工具ASE介绍——10、ASE实现曲面细分

2024-03-15 00:50

本文主要是介绍Unity可视化Shader工具ASE介绍——10、ASE实现曲面细分,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阿赵的Unity可视化Shader工具ASE介绍目录
  大家好,我是阿赵。
  之前介绍地面交互的时候,介绍了曲面细分着色器的使用。这个过程,在ASE里面也是可以实现的。关于曲面细分的具体作用,这里就不再重复,如果有兴趣了解可以看看我的地面交互系列的博文。

一、通过选项开启曲面细分

  在ASE里面,只有Surface类型的模板支持曲面细分,所以先建一个Surface模板的Shader
在这里插入图片描述

  先来看这个地方,在OutputNode里面,有一个Tessellation的选项,把它勾选上,然后用这个shader创建一个材质球,赋给地面,就会看到地面已经出现了细分了。
在这里插入图片描述

  之前介绍曲面细分的Surface类型着色器写法的时候,介绍过,Surface类型里面内置了3种方式的曲面细分实现方法,分布是Fixed、DistanceBased和EdgeLength。在ASE里面,也可以选择这些类型来实现:
在这里插入图片描述

  在勾选了之后,默认选择的是EdgeLength方式,也就是以边的长度来细分。可以手段选择其他的类型。

1、Fixed方式细分

在这里插入图片描述

  如果改成Fixed,下面的参数会变成Tess,实际上就是细分的固定数值了。
  然后上面有一个Phong的选项,Phone细分是一种会沿着法线方向做细分的方式,如果开启了之后,模型会圆滑,如果不开启,则是在原有的三角面的基础上做细分,不会改变基础形状,会比较有棱有角。
在这里插入图片描述

2、DistanceBased方式细分

在这里插入图片描述

  如果选择了DistanceBased细分方式,除了Tess参数以外,还会多了Min和Max两个数值,用于控制距离范围。

在这里插入图片描述

3、EdgeLength方式细分

在这里插入图片描述

  选择这种方式之后,参数会变成EdgeLength

在这里插入图片描述

  如果选择EdgeLengthCull,那么还会有一个MaxDisp参数,代表的是Max DisplaceMent

二、通过节点连线实现曲面细分

  用上面的方式实现曲面细分,会有一个问题,由于参数都是固定输入了,不能很灵活的去修改。
  所以ASE也可以通过节点来指定曲面细分的参数的。
在这里插入图片描述

  在输出模块的节点上面,可以看到Tessellation的输入接口。
在这里插入图片描述

  搜索一下节点,可以看到,刚才介绍的几种方式基本都有对应的节点。

1、Fixed方式:

  Fixed方式不需要节点,直接输入数值就行了。
在这里插入图片描述

  注意看,如果我们连了节点到Tessellation上面,之前在输出节点属性里面的Tessellation选项就会变成灰色,不可以再编辑参数了,但Phong选项还在。
在这里插入图片描述

2、DistanceBased方式

  如果通过距离控制:
在这里插入图片描述
在这里插入图片描述

  这样就可以在材质球上面控制这些参数了。

3、EdgeLength方式

  根据边长
在这里插入图片描述

4、EdgeLengthCull方式

在这里插入图片描述

三、动态计算曲面细分范围

  上面用节点的方式可以解决固定参数的问题,可以在材质球上面修改参数。但其实也不太灵活,只是能改参数,实现不了很多效果。
  这里来讲一下怎样实现更复杂的效果,比如我连了这么一个线:
在这里插入图片描述

  现在的效果是:
在这里插入图片描述

  这个计算结果得到的是,指定一个中心点和半径,然后在范围内做曲面细分。那么剩下的问题就比较简单了,用这个计算出来的值,连线给Tessellation就行。
在这里插入图片描述

  但保存之后,并没有出现我们想要的结果,发现Shader报错了
在这里插入图片描述

  打开生成的Shader看看,可以发现问题:
在这里插入图片描述

  在细分的函数里面,传入了v0、v1、v2三个点,但下面却是使用了v.vertex,这里v并没有定义。
  既然这样,可以分开三个点分别计算距离,或者三个点求平均值再计算距离。我这里就简单的使用平均值:
在这里插入图片描述

  修改完之后,效果就出来了。
在这里插入图片描述

四、源码

  也不算什么源码,给一下最后ASE生成的Shader源码,有兴趣的朋友可以通过ASE编辑器打开看看节点的连接方式:

// Made with Amplify Shader Editor
// Available at the Unity Asset Store - http://u3d.as/y3X 
Shader "ASETessellation"
{Properties{_max("max", Float) = 1_min("min", Float) = 0_tessVal("tessVal", Float) = 1_range("range", Float) = 1_centerPos("centerPos", Vector) = (0,0,0,0)[HideInInspector] __dirty( "", Int ) = 1}SubShader{Tags{ "RenderType" = "Opaque"  "Queue" = "Geometry+0" }Cull BackCGPROGRAM#include "Tessellation.cginc"#pragma target 4.6#pragma surface surf Standard keepalpha addshadow fullforwardshadows vertex:vertexDataFunc tessellate:tessFunction struct Input{float3 worldPos;};uniform float _min;uniform float _max;uniform float3 _centerPos;uniform float _range;uniform float _tessVal;float4 tessFunction( appdata_full v0, appdata_full v1, appdata_full v2 ){float3 vert = (v0.vertex + v1.vertex + v2.vertex) / 3;float3 ase_worldPos = mul( unity_ObjectToWorld, vert );float4 appendResult14 = (float4(ase_worldPos , 0.0));float smoothstepResult22 = smoothstep( _min , _max , ( 1.0 - ( distance( float4( _centerPos , 0.0 ) , appendResult14 ) / _range ) ));float4 temp_cast_1 = (( max( saturate( smoothstepResult22 ) , 0.01 ) * _tessVal )).xxxx;return temp_cast_1;}void vertexDataFunc( inout appdata_full v ){}void surf( Input i , inout SurfaceOutputStandard o ){o.Alpha = 1;}ENDCG}Fallback "Diffuse"CustomEditor "ASEMaterialInspector"
}
/*ASEBEGIN
Version=18500
0;0;1920;1019;1799.171;493.4954;1.3;True;True
Node;AmplifyShaderEditor.WorldPosInputsNode;12;-1200.876,90.80692;Inherit;False;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3
Node;AmplifyShaderEditor.Vector3Node;11;-1175.583,-133.3799;Inherit;False;Property;_centerPos;centerPos;4;0;Create;True;0;0;False;0;False;0,0,0;0,0,0;0;4;FLOAT3;0;FLOAT;1;FLOAT;2;FLOAT;3
Node;AmplifyShaderEditor.DynamicAppendNode;14;-986.2843,80.69485;Inherit;False;FLOAT4;4;0;FLOAT3;0,0,0;False;1;FLOAT;0;False;2;FLOAT;0;False;3;FLOAT;0;False;1;FLOAT4;0
Node;AmplifyShaderEditor.DistanceOpNode;13;-796.7131,9.478409;Inherit;False;2;0;FLOAT3;0,0,0;False;1;FLOAT4;0,0,0,0;False;1;FLOAT;0
Node;AmplifyShaderEditor.RangedFloatNode;16;-818.4869,167.191;Inherit;False;Property;_range;range;3;0;Create;True;0;0;False;0;False;1;10;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.SimpleDivideOpNode;21;-658.8125,78.10852;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.RangedFloatNode;23;-620.457,190.956;Inherit;False;Property;_min;min;1;0;Create;True;0;0;False;0;False;0;0;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.RangedFloatNode;24;-628.964,288.5267;Inherit;False;Property;_max;max;0;0;Create;True;0;0;False;0;False;1;2.51;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.OneMinusNode;17;-575.0996,-24.93669;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.SmoothstepOpNode;22;-467.9477,49.72478;Inherit;False;3;0;FLOAT;0;False;1;FLOAT;0;False;2;FLOAT;1;False;1;FLOAT;0
Node;AmplifyShaderEditor.SaturateNode;18;-280.739,67.37544;Inherit;False;1;0;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.RangedFloatNode;26;-290.9912,142.4471;Inherit;False;Constant;_Float0;Float 0;6;0;Create;True;0;0;False;0;False;0.01;0;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.SimpleMaxOpNode;25;-147.9912,87.44708;Inherit;False;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.RangedFloatNode;19;-329.5429,269.0027;Inherit;False;Property;_tessVal;tessVal;2;0;Create;True;0;0;False;0;False;1;15;0;0;0;1;FLOAT;0
Node;AmplifyShaderEditor.SimpleMultiplyOpNode;20;-154.6485,251.0924;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0
Node;AmplifyShaderEditor.StandardSurfaceOutputNode;0;0,0;Float;False;True;-1;6;ASEMaterialInspector;0;0;Standard;ASETessellation;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;False;Back;0;False;-1;0;False;-1;False;0;False;-1;0;False;-1;False;0;Opaque;0.5;True;True;0;False;Opaque;;Geometry;All;14;all;True;True;True;True;0;False;-1;False;0;False;-1;255;False;-1;255;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;-1;True;3;15;10;25;False;0.5;True;0;0;False;-1;0;False;-1;0;0;False;-1;0;False;-1;0;False;-1;0;False;-1;0;False;0;0,0,0,0;VertexOffset;True;False;Cylindrical;False;Relative;0;;-1;-1;-1;2;0;False;0;0;False;-1;-1;0;False;-1;0;0;0;False;0.1;False;-1;0;False;-1;False;16;0;FLOAT3;0,0,0;False;1;FLOAT3;0,0,0;False;2;FLOAT3;0,0,0;False;3;FLOAT;0;False;4;FLOAT;0;False;5;FLOAT;0;False;6;FLOAT3;0,0,0;False;7;FLOAT3;0,0,0;False;8;FLOAT;0;False;9;FLOAT;0;False;10;FLOAT;0;False;13;FLOAT3;0,0,0;False;11;FLOAT3;0,0,0;False;12;FLOAT3;0,0,0;False;14;FLOAT4;0,0,0,0;False;15;FLOAT3;0,0,0;False;0
WireConnection;14;0;12;0
WireConnection;13;0;11;0
WireConnection;13;1;14;0
WireConnection;21;0;13;0
WireConnection;21;1;16;0
WireConnection;17;0;21;0
WireConnection;22;0;17;0
WireConnection;22;1;23;0
WireConnection;22;2;24;0
WireConnection;18;0;22;0
WireConnection;25;0;18;0
WireConnection;25;1;26;0
WireConnection;20;0;25;0
WireConnection;20;1;19;0
WireConnection;0;14;20;0
ASEEND*/
//CHKSM=CB82F0A63384ACEE4428BD338EEB87DE1C372740

这篇关于Unity可视化Shader工具ASE介绍——10、ASE实现曲面细分的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/810292

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter