当前位置: 首页 > news >正文

Unity Shader unity文档学习笔记(十九):粘土效果,任意网格转化成一个球(顶点动画,曲面着色器)

任意网格转换球原理:
由某一点向网格的所有顶点发射一条射线,到圆上,最终就会形成一个圆
在这里插入图片描述
在这里插入图片描述
关键的代码

                float4 worldPos =  mul(unity_ObjectToWorld, v.vertex);// 计算原始顶点到圆心的向量float3 toCenter = worldPos - _WorldSourcePos;float3 dirObj = normalize(toCenter); // 世界空间方向(圆心→顶点的单位向量)// 计算世界空间目标位置(圆周上的点)float3 targetWorldPos = _WorldTargetPos + dirObj * _Radius; // 世界空间目标位置// 将目标位置转换回模型空间(用于顶点混合)float3 targetModelPos = mul(unity_WorldToObject, float4(targetWorldPos, 1)).xyz;float3 baseLocalPos = lerp(v.vertex, targetModelPos, _Transition);o.vertex = UnityObjectToClipPos(baseLocalPos);

整个shader

Shader "Custom/WorldCenterCircleShader"
{Properties{_MainTex("MainTex",2D) ="white"{}_Radius ("目标圆半径", Float) = 1.0       // 最终圆的半径(世界空间)_WorldSourcePos ("原世界坐标", Vector) = (0,0,0) // 原世界坐标_WorldTargetPos ("目标世界坐标", Vector) = (0,0,0) // 目标世界坐标_Color ("基础颜色", Color) = (1,0,0,1)   // 圆的颜色_Transition ("过渡系数", Range(0,1)) = 0 // 0=原模型,1=完整圆(世界空间变形)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;  // 模型空间顶点位置float3 normal : NORMAL;    // 模型空间原始法线float2 uv:TEXCOORD0;//纹理};struct v2f{float4 vertex : SV_POSITION; // 裁剪空间位置float3 worldPos : TEXCOORD0; // 世界空间位置(用于光照)float3 normal : NORMAL;      // 过渡后的法线(模型空间,用于光照)float2 uv:TEXCOORD1; };sampler2D _MainTex;float _Radius;float3 _WorldSourcePos;float3 _WorldTargetPos;fixed4 _Color;float _Transition;float _MinX;float _MaxX;v2f vert (appdata v){v2f o;float4 worldPos =  mul(unity_ObjectToWorld, v.vertex);// 计算原始顶点到圆心的向量float3 toCenter = worldPos - _WorldSourcePos;float3 dirObj = normalize(toCenter); // 世界空间方向(圆心→顶点的单位向量)// 计算世界空间目标位置(圆周上的点)float3 targetWorldPos = _WorldTargetPos + dirObj * _Radius; // 世界空间目标位置// 将目标位置转换回模型空间(用于顶点混合)float3 targetModelPos = mul(unity_WorldToObject, float4(targetWorldPos, 1)).xyz;float3 baseLocalPos = lerp(v.vertex, targetModelPos, _Transition);// 转换为裁剪空间o.vertex = UnityObjectToClipPos(baseLocalPos);float3 originalNormal = normalize(UnityObjectToWorldNormal(v.normal));float3 circleNormal = normalize(toCenter); // 圆周法线(指向外侧)float3 normal = lerp(originalNormal, circleNormal, _Transition); o.normal = mul(normal, (float3x3)unity_WorldToObject);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{//float4 texColor = tex2D(_MainTex, i.uv); //tex2D(smapler, x) 二维纹理查找// 简单漫反射光照(使用过渡后的模型空间法线)float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);// 法线从模型空间转换到世界空间(光照计算需要世界空间法线)float3 normalDir = normalize(i.normal);float diff = saturate(dot(lightDir, normalDir));//fixed4 col = texColor + _Color * (diff * 0.5 + 0.5); // 环境光+漫反射fixed4 col = _Color * diff; // 环境光+漫反射return col;}ENDCG}}FallBack "Diffuse"
}

效果请添加图片描述
但是这种方式对网格顶点是有要求的,如果顶点不够多就会这样
在这里插入图片描述

在这里插入图片描述

这样
在这里插入图片描述
在这里插入图片描述
项目的网格不可能每个顶点都这么多,有没有办法给网格新增一些顶点,当然是有:曲面着色器:
unity的正方体
在这里插入图片描述
参数调到5
在这里插入图片描述
调到10

在这里插入图片描述
转换后:
在这里插入图片描述
曲面细分shader:

Shader "Unlit/TessShader"
{Properties{_TessellationUniform("TessellationUniform",Range(1,64)) = 1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM//定义2个函数 hull domain#pragma hull hullProgram#pragma domain ds#pragma vertex tessvert#pragma fragment frag#include "UnityCG.cginc"//引入曲面细分的头文件#include "Tessellation.cginc" #pragma target 5.0struct VertexInput{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;float4 tangent : TANGENT;};struct VertexOutput{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;};VertexOutput vert (VertexInput v)//这个函数应用在domain函数中,用来空间转换的函数{VertexOutput o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;o.tangent = v.tangent;o.normal = v.normal;return o;}//有些硬件不支持曲面细分着色器,定义了该宏就能够在不支持的硬件上不会变粉,也不会报错#ifdef UNITY_CAN_COMPILE_TESSELLATION//顶点着色器结构的定义struct TessVertex{float4 vertex : INTERNALTESSPOS;float3 normal : NORMAL;float4 tangent : TANGENT;float2 uv : TEXCOORD0;};struct OutputPatchConstant { //不同的图元,该结构会有所不同//该部分用于Hull Shader里面//定义了patch的属性//Tessellation Factor和Inner Tessellation Factorfloat edge[3] : SV_TESSFACTOR;float inside  : SV_INSIDETESSFACTOR;};TessVertex tessvert (VertexInput v){//顶点着色器函数TessVertex o;o.vertex  = v.vertex;o.normal  = v.normal;o.tangent = v.tangent;o.uv      = v.uv;return o;}float _TessellationUniform;OutputPatchConstant hsconst (InputPatch<TessVertex,3> patch){//定义曲面细分的参数OutputPatchConstant o;o.edge[0] = _TessellationUniform;o.edge[1] = _TessellationUniform;o.edge[2] = _TessellationUniform;o.inside  = _TessellationUniform;return o;}[UNITY_domain("tri")]//确定图元,quad,triangle等[UNITY_partitioning("fractional_odd")]//拆分edge的规则,equal_spacing,fractional_odd,fractional_even[UNITY_outputtopology("triangle_cw")][UNITY_patchconstantfunc("hsconst")]//一个patch一共有三个点,但是这三个点都共用这个函数[UNITY_outputcontrolpoints(3)]      //不同的图元会对应不同的控制点TessVertex hullProgram (InputPatch<TessVertex,3> patch,uint id : SV_OutputControlPointID){//定义hullshaderV函数return patch[id];}[UNITY_domain("tri")]//同样需要定义图元VertexOutput ds (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3>patch,float3 bary :SV_DOMAINLOCATION)//bary:重心坐标{VertexInput v;v.vertex = patch[0].vertex*bary.x + patch[1].vertex*bary.y + patch[2].vertex*bary.z;v.tangent = patch[0].tangent*bary.x + patch[1].tangent*bary.y + patch[2].tangent*bary.z;v.normal = patch[0].normal*bary.x + patch[1].normal*bary.y + patch[2].normal*bary.z;v.uv = patch[0].uv*bary.x + patch[1].uv*bary.y + patch[2].uv*bary.z;VertexOutput o = vert (v);return o;}#endiffloat4 frag (VertexOutput i) : SV_Target{return float4(1.0,1.0,1.0,1.0);}ENDCG}}Fallback "Diffuse"
}

加上顶点动画后的shader
主要改动
在这里插入图片描述

Shader "Unlit/TessShader"
{Properties{_TessellationUniform("TessellationUniform",Range(1,64)) = 1_Radius ("目标圆半径", Float) = 1.0       // 最终圆的半径(世界空间)_WorldSourcePos ("原世界坐标", Vector) = (0,0,0) // 原世界坐标_WorldTargetPos ("目标世界坐标", Vector) = (0,0,0) // 目标世界坐标_Transition ("过渡系数", Range(0,1)) = 0 // 0=原模型,1=完整圆(世界空间变形)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM//定义2个函数 hull domain#pragma hull hullProgram#pragma domain ds#pragma vertex tessvert#pragma fragment frag#include "UnityCG.cginc"//引入曲面细分的头文件#include "Tessellation.cginc" #pragma target 5.0float _Radius;float3 _WorldSourcePos;float3 _WorldTargetPos;fixed4 _Color;float _Transition;float _TessellationUniform;struct VertexInput{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;float4 tangent : TANGENT;};struct VertexOutput{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;};VertexOutput vert (VertexInput v)//这个函数应用在domain函数中,用来空间转换的函数{VertexOutput o;float4 worldPos =  mul(unity_ObjectToWorld, v.vertex);// 计算原始顶点到圆心的向量float3 toCenter = worldPos - _WorldSourcePos;float3 dirObj = normalize(toCenter); // 世界空间方向(圆心→顶点的单位向量)// 计算世界空间目标位置(圆周上的点)float3 targetWorldPos = _WorldTargetPos + dirObj * _Radius; // 世界空间目标位置// 将目标位置转换回模型空间(用于顶点混合)float3 targetModelPos = mul(unity_WorldToObject, float4(targetWorldPos, 1)).xyz;float3 baseLocalPos = lerp(v.vertex, targetModelPos, _Transition);o.vertex = UnityObjectToClipPos(baseLocalPos);o.uv = v.uv;o.tangent = v.tangent;float3 originalNormal = normalize(UnityObjectToWorldNormal(v.normal));float3 circleNormal = normalize(toCenter); // 圆周法线(指向外侧)float3 normal = lerp(originalNormal, circleNormal, _Transition); //o.normal = normal;o.normal = mul(normal, (float3x3)unity_WorldToObject);return o;}//有些硬件不支持曲面细分着色器,定义了该宏就能够在不支持的硬件上不会变粉,也不会报错#ifdef UNITY_CAN_COMPILE_TESSELLATION//顶点着色器结构的定义struct TessVertex{float4 vertex : INTERNALTESSPOS;float3 normal : NORMAL;float4 tangent : TANGENT;float2 uv : TEXCOORD0;};struct OutputPatchConstant { //不同的图元,该结构会有所不同//该部分用于Hull Shader里面//定义了patch的属性//Tessellation Factor和Inner Tessellation Factorfloat edge[3] : SV_TESSFACTOR;float inside  : SV_INSIDETESSFACTOR;};TessVertex tessvert (VertexInput v){//顶点着色器函数TessVertex o;o.vertex  = v.vertex;o.normal  = v.normal;o.tangent = v.tangent;o.uv      = v.uv;return o;}OutputPatchConstant hsconst (InputPatch<TessVertex,3> patch){//定义曲面细分的参数OutputPatchConstant o;o.edge[0] = _TessellationUniform;o.edge[1] = _TessellationUniform;o.edge[2] = _TessellationUniform;o.inside  = _TessellationUniform;return o;}[UNITY_domain("tri")]//确定图元,quad,triangle等[UNITY_partitioning("fractional_odd")]//拆分edge的规则,equal_spacing,fractional_odd,fractional_even[UNITY_outputtopology("triangle_cw")][UNITY_patchconstantfunc("hsconst")]//一个patch一共有三个点,但是这三个点都共用这个函数[UNITY_outputcontrolpoints(3)]      //不同的图元会对应不同的控制点TessVertex hullProgram (InputPatch<TessVertex,3> patch,uint id : SV_OutputControlPointID){//定义hullshaderV函数return patch[id];}[UNITY_domain("tri")]//同样需要定义图元VertexOutput ds (OutputPatchConstant tessFactors, const OutputPatch<TessVertex,3>patch,float3 bary :SV_DOMAINLOCATION)//bary:重心坐标{VertexInput v;v.vertex = patch[0].vertex*bary.x + patch[1].vertex*bary.y + patch[2].vertex*bary.z;v.tangent = patch[0].tangent*bary.x + patch[1].tangent*bary.y + patch[2].tangent*bary.z;v.normal = patch[0].normal*bary.x + patch[1].normal*bary.y + patch[2].normal*bary.z;v.uv = patch[0].uv*bary.x + patch[1].uv*bary.y + patch[2].uv*bary.z;VertexOutput o = vert (v);return o;}#endiffloat4 frag (VertexOutput i) : SV_Target{return float4(1.0,1.0,1.0,1.0);}ENDCG}}Fallback "Diffuse"
}
http://www.dtcms.com/a/330683.html

相关文章:

  • 算法提升之树上问题-(LCA)
  • vue3使用leaflet地图
  • **超融合架构中的发散创新:探索现代编程语言的挑战与机遇**一、引言随着数字化时代的快速发展,超融合架构已成为IT领域的一种重要趋势
  • 【入门级-算法-2、入门算法:枚举法】
  • 代码随想录Day50:图论(图论理论、深度搜索理论、所有可达路径、广度搜索理论)
  • 表单输入绑定详解
  • 给电脑升级内存,自检太慢,以为出错
  • FPS游戏时,你的电脑都在干什么(CS2)
  • langchain入门笔记03:使用fastapi部署本地大模型后端接口,优化局域网内的问答响应速度
  • 网页加载缓慢系统排查与优化指南
  • 消费级显卡分布式智能体协同:构建高性价比医疗AI互动智能体的理论与实践路径
  • npm介绍,指令合集,换源指令
  • 【大文件上传】分片上传+断点续传+Worker线程计算Hash
  • Bean的生命周期
  • (2-10-1)MyBatis的基础与基本使用
  • 【word】一次选中全部表格,宏方法
  • [工具]vscode 使用AI 优化代码
  • week1-[分支结构]中位数
  • AI技术产品化:核心认知与实战指南
  • 【深度学习计算性能】04:硬件
  • 集成电路学习:什么是Machine Learning机器学习
  • 云原生存储架构设计与性能优化
  • 自动驾驶轨迹规划算法——Apollo OpenSpace Planner
  • 利用GISBox完成超图S3M与OSGB三维模型格式的转换
  • Elasticsearch 中如何配置 RBAC 权限-实现安全的访问控制
  • 现在都是APP,小程序抢购,支持浏览器不支持 SSE
  • GPT-5 提示词优化全攻略:用 Prompt Optimizer 快速迁移与提升,打造更稳更快的智能应用
  • LeetCode——Hot 100【合并区间 最大子数组和】
  • 算法148. 排序链表
  • 希尔排序专栏