Unity URP 如何写基础的曲面细分着色器
左边是默认Cube在网格模式下经过曲面细分的结果,右边是原状态。
曲面细分着色器在顶点着色器、几何着色器之后,像素着色器之前。
它的作用时根据配置信息生成额外的顶点以切割原本的面片。
关于这部分有一个详细的英文教程,感兴趣可以看一下。
https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/
以下是完整代码
Shader "Kerzh/KerzhCgShaderTemplate"
{Properties{_Color("Color", Color) = (1,1,1,1)_TessellationUniform ("Tessellation Uniform", Vector) = (1,1,1,1)}SubShader{Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline" }Pass{CGPROGRAM#pragma vertex vert#pragma hull hull#pragma domain domain#pragma geometry geom#pragma fragment frag#pragma target 4.6#include "UnityCG.cginc"#include "Assets/TA/ShaderLib/CgincInclude//CommonCgInc.cginc"#include "Assets/TA/ShaderLib/CgincInclude//CustomTessellation.cginc"MeshData vert (MeshData input){return input;}//如果不正确配置会报错[UNITY_domain("tri")] // 正在处理三角形 "tri", "quad", or "isoline"[UNITY_outputcontrolpoints(3)] // 每个面片输出的顶点为3个[UNITY_outputtopology("triangle_cw")] // 当创建三角形时应是顺时针还是逆时针,这里应是顺时针 "point", "line", "triangle_cw", or "triangle_ccw"[UNITY_partitioning("integer")] // 如何细分切割面片 "integer", "pow2", "fractional_even", or "fractional_odd"[UNITY_patchconstantfunc("patchConstantFunction")] // 细分切割部分还必须提供函数处理,每个面片调用一次MeshData hull (InputPatch<MeshData, 3> patch, uint id : SV_OutputControlPointID) // 每个顶点调用一次,如果是处理三角形就是调用三次{// 如果_TessellationUniform输入值为1,不产生任何变化,但当输入值为2时,具体发生了什么// 对于一个三角形(因为我们配置的是处理三角形),根据三条边的二等分位置添加额外的一个顶点,如果是3就是三等分位置添加两个顶点// 对于一个三角形(因为我们配置的是处理三角形),根据三条个顶点添加一个中心顶点// 根据patchConstantFunction赋值分配生成顶点的插值权重return patch[id];}// barycentricCoordinates分别代表各个点的插值权重,每个面片调用一次,对细分后的三角顶点形进行处理(也就是说原顶点不经过此处理?)[UNITY_domain("tri")] // 正在处理三角形MeshData domain(TessellationFactors factors, OutputPatch<MeshData, 3> patch, float3 barycentricCoordinates : SV_DomainLocation) {MeshData data; // 新的插值权重顶点#define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) data.fieldName = \patch[0].fieldName * barycentricCoordinates.x + \patch[1].fieldName * barycentricCoordinates.y + \patch[2].fieldName * barycentricCoordinates.z;//对所有信息利用插值权重进行插值计算MY_DOMAIN_PROGRAM_INTERPOLATE(vertex)MY_DOMAIN_PROGRAM_INTERPOLATE(normalOS)MY_DOMAIN_PROGRAM_INTERPOLATE(tangentOS)MY_DOMAIN_PROGRAM_INTERPOLATE(uv1)MY_DOMAIN_PROGRAM_INTERPOLATE(uv2)MY_DOMAIN_PROGRAM_INTERPOLATE(vertexColor)return data;}//最大的顶点数,这里比如你要生成三个三角形面片,那么一个面片需要三个顶点,就是9个顶点,一般来讲这里直接填多一点即可,不过可能填太多了会导致内存占用?[maxvertexcount(9)]void geom (triangle MeshData input[3],inout TriangleStream<VOutData> triStream){//原样转换过去VOutData output[3];for(int i=0;i<3;i++){VOutData p0;p0 = FillBaseV2FData(input[i]);output[i] = p0;}triStream.RestartStrip(); // 重新开始一个新的三角形triStream.Append(output[0]);triStream.Append(output[1]);triStream.Append(output[2]);return;//验证准确性用 勿删MeshData centerMeshData;centerMeshData.vertex = (input[0].vertex + input[1].vertex + input[2].vertex)/3.0;centerMeshData.uv1 = (input[0].uv1 + input[1].uv1 + input[2].uv1)/3.0;centerMeshData.uv2 = (input[0].uv2 + input[1].uv2 + input[2].uv2)/3.0;centerMeshData.tangentOS = (input[0].tangentOS + input[1].tangentOS + input[2].tangentOS)/3.0;centerMeshData.normalOS = (input[0].normalOS + input[1].normalOS + input[2].normalOS)/3.0;centerMeshData.vertexColor = (input[0].vertexColor + input[1].vertexColor + input[2].vertexColor)/3.0;centerMeshData.vertex += float4((centerMeshData.normalOS * 0.35), 0);VOutData center = FillBaseV2FData(centerMeshData);// 根据这三个点分别和中心点制造三角形输出triStream.RestartStrip(); // 重新开始一个新的三角形triStream.Append(output[1]);triStream.Append(center);triStream.Append(output[0]);triStream.RestartStrip(); // 重新开始一个新的三角形triStream.Append(output[2]);triStream.Append(center);triStream.Append(output[1]);triStream.RestartStrip(); // 重新开始一个新的三角形triStream.Append(output[0]);triStream.Append(center);triStream.Append(output[2]);}float4 _Color;float4 frag (VOutData i) : SV_Target{return _Color;}ENDCG}}
}
依赖文件CommonCgInc.cginc:
#ifndef CommonCgInc
#define CommonCgIncfloat3 FromScript_LocalPositionWS;
float3 FromScript_LocalRotationWS;
float3 FromScript_LocalScaleWS;//输入结构
struct MeshData
{float4 vertex : POSITION;float2 uv1 : TEXCOORD0;float2 uv2 : TEXCOORD1;float4 tangentOS :TANGENT;float3 normalOS : NORMAL;float4 vertexColor : COLOR;
};//传递结构
struct VOutData
{float4 pos : SV_POSITION; // 必须命名为pos ,因为 TRANSFER_VERTEX_TO_FRAGMENT 是这么命名的,为了正确地获取到Shadowfloat2 uv1 : TEXCOORD0;float3 tangentWS : TEXCOORD1;float3 bitangentWS : TEXCOORD2;float3 normalWS : TEXCOORD3;float3 posWS : TEXCOORD4;float3 posOS : TEXCOORD5;float3 normalOS : TEXCOORD6;float4 vertexColor : TEXCOORD7;float2 uv2 : TEXCOORD8;
};//传递结构赋值
VOutData FillBaseV2FData(MeshData input)
{VOutData output;output.pos = UnityObjectToClipPos(input.vertex);output.uv1 = input.uv1;output.uv2 = input.uv2;output.normalWS = normalize(UnityObjectToWorldNormal(input.normalOS));output.posWS = mul(unity_ObjectToWorld, input.vertex);output.posOS = input.vertex.xyz;output.tangentWS = normalize(UnityObjectToWorldDir(input.tangentOS));output.bitangentWS = cross(output.normalWS, output.tangentWS) * input.tangentOS.w; //乘上input.tangentOS.w 是unity引擎的bug,有的模型是 1 有的模型是 -1,必须这么写output.normalOS = input.normalOS;output.vertexColor = input.vertexColor;return output;
}// Hue, Saturation, Value
// Ranges:
// Hue [0.0, 1.0]
// Sat [0.0, 1.0]
// Lum [0.0, HALF_MAX]
// //HSV色彩模型转为RGB色彩模型 FROM::color.hlsl
float3 HSV2RGB( float3 hsv ){const float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);float3 p = abs(frac(hsv.xxx + K.xyz) * 6.0 - K.www);return hsv.z * lerp(K.xxx, saturate(p - K.xxx), hsv.y);
}
//RGB色彩模型转为HSV色彩模型 FROM::color.hlsl
float3 RGB2HSV(float3 rgb)
{float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);float4 p = lerp(float4(rgb.bg, K.wz), float4(rgb.gb, K.xy), step(rgb.b, rgb.g));float4 q = lerp(float4(p.xyw, rgb.r), float4(rgb.r, p.yzx), step(p.x, rgb.r));float d = q.x - min(q.w, q.y);float e = 1.0e-10;return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}//Gooch光照模型 ⻛格化的着⾊模型 强调冷暖色调 FROM::render4th P146
float3 GoochModel(float3 baseColor, float3 highLightColor, float3 normalWs, float3 lightDirWs, float3 viewDirWs){normalWs = normalize(normalWs);lightDirWs = normalize(lightDirWs);float3 coolColor = float3(0,0,0.55) + 0.25*baseColor;float3 warmColor = float3(0.3,0.3,0) + 0.25*baseColor;float size = clamp(100*(dot(reflect(lightDirWs, normalWs), viewDirWs) - 97), 0, 1);float4 halfLambert = dot(normalWs, lightDirWs) * 0.5 + 0.5;return size*highLightColor + (1-size)*(halfLambert*warmColor + (1 - halfLambert)* coolColor);
}//添加虚拟点光源 _VirtualLightFade越大,衰减越快
float3 CalculatePointVirtualLight(float3 _VirtualLightPos, float3 positionOS, float _VirtualLightFade, float3 _VirtualLightColor)
{float virtualLightDis = distance(_VirtualLightPos,positionOS);float3 virtualLight = exp(-_VirtualLightFade*virtualLightDis)*_VirtualLightColor;//TODO:也许补充方向衰减return virtualLight;
}//切线空间计算视差uv 根据视角方向以深度反追命中点uv
float2 CalculateRealUVAfterDepth(float2 originUV, float3 viewDirTS, float depth)
{//计算视角方向和深度方向的cos值float cosTheta = dot(normalize(viewDirTS), float3(0,0,-1)); // 一般来讲unity是左手坐标系,但在切线和观察空间较为特殊是右手坐标系,不过这并不影响z轴方向的判断//根据深度差算出两点间距离float dis = depth / cosTheta;//算出应用深度差后对应点位float3 originUVPoint = float3(originUV, 0);float3 afrerDepthUVPoint = originUVPoint + normalize(viewDirTS) * dis;//返回应用深度差后对应UVreturn afrerDepthUVPoint.xy;
}
#endif
依赖文件CustomTessellation.cginc:
// Tessellation programs based on this article by Catlike Coding:
// https://catlikecoding.com/unity/tutorials/advanced-rendering/tessellation/
// 关于参数的详细说明
// https://zhuanlan.zhihu.com/p/479792793#include "Assets/TA/ShaderLib/CgincInclude//CommonCgInc.cginc"//细分切割函数对于每个面片调用一次,对于每一个面片,比如三角形:每条边需要一个切割因子,内部需要一个切割因子
struct TessellationFactors {float edge[3] : SV_TessFactor; // 对应三条边的切割因子float inside : SV_InsideTessFactor; // 对应内部的切割因子
};float4 _TessellationUniform; // 细分因子,当值为1时不发生细分切割。因子可以分别设置,比如边因子是1内部因子是5,那就不会在边上生成顶点,会在中心生成五个顶点
//自定义的细分切割方法,每个面片调用一次
TessellationFactors patchConstantFunction (InputPatch<MeshData, 3> patch)
{TessellationFactors f;f.edge[0] = _TessellationUniform.x;f.edge[1] = _TessellationUniform.y;f.edge[2] = _TessellationUniform.z;f.inside = _TessellationUniform.w;return f;
}
其中,通过
#pragma hull hull #pragma domain domain
定义hull和domain着色器,其中hull负责切割,domain用于根据权重处理细分后的顶点数据。
hull部分:
//细分切割函数对于每个面片调用一次,对于每一个面片,比如三角形:每条边需要一个切割因子,内部需要一个切割因子
struct TessellationFactors {float edge[3] : SV_TessFactor; // 对应三条边的切割因子float inside : SV_InsideTessFactor; // 对应内部的切割因子
};float4 _TessellationUniform; // 细分因子,当值为1时不发生细分切割。因子可以分别设置,比如边因子是1内部因子是5,那就不会在边上生成顶点,会在中心生成五个顶点
//自定义的细分切割方法,每个面片调用一次
TessellationFactors patchConstantFunction (InputPatch<MeshData, 3> patch)
{TessellationFactors f;f.edge[0] = _TessellationUniform.x;f.edge[1] = _TessellationUniform.y;f.edge[2] = _TessellationUniform.z;f.inside = _TessellationUniform.w;return f;
}//如果不正确配置会报错[UNITY_domain("tri")] // 正在处理三角形 "tri", "quad", or "isoline"[UNITY_outputcontrolpoints(3)] // 每个面片输出的顶点为3个[UNITY_outputtopology("triangle_cw")] // 当创建三角形时应是顺时针还是逆时针,这里应是顺时针 "point", "line", "triangle_cw", or "triangle_ccw"[UNITY_partitioning("integer")] // 如何细分切割面片 "integer", "pow2", "fractional_even", or "fractional_odd"[UNITY_patchconstantfunc("patchConstantFunction")] // 细分切割部分还必须提供函数处理,每个面片调用一次MeshData hull (InputPatch<MeshData, 3> patch, uint id : SV_OutputControlPointID) // 每个顶点调用一次,如果是处理三角形就是调用三次{// 如果_TessellationUniform输入值为1,不产生任何变化,但当输入值为2时,具体发生了什么// 对于一个三角形(因为我们配置的是处理三角形),根据三条边的二等分位置添加额外的一个顶点,如果是3就是三等分位置添加两个顶点// 对于一个三角形(因为我们配置的是处理三角形),根据三条个顶点添加一个中心顶点// 根据patchConstantFunction赋值分配生成顶点的插值权重return patch[id];}
这里做的操作比较少,只是传入每个面片的切割因子,一个面片(三角形)的每条边需要一个切割因子,内部需要一个切割因子,一共四个切割因子。
domain部分:
// barycentricCoordinates分别代表各个点的插值权重,每个面片调用一次,对细分后的三角顶点形进行处理(也就是说原顶点不经过此处理?)[UNITY_domain("tri")] // 正在处理三角形MeshData domain(TessellationFactors factors, OutputPatch<MeshData, 3> patch, float3 barycentricCoordinates : SV_DomainLocation) {MeshData data; // 新的插值权重顶点#define MY_DOMAIN_PROGRAM_INTERPOLATE(fieldName) data.fieldName = \patch[0].fieldName * barycentricCoordinates.x + \patch[1].fieldName * barycentricCoordinates.y + \patch[2].fieldName * barycentricCoordinates.z;//对所有信息利用插值权重进行插值计算MY_DOMAIN_PROGRAM_INTERPOLATE(vertex)MY_DOMAIN_PROGRAM_INTERPOLATE(normalOS)MY_DOMAIN_PROGRAM_INTERPOLATE(tangentOS)MY_DOMAIN_PROGRAM_INTERPOLATE(uv1)MY_DOMAIN_PROGRAM_INTERPOLATE(uv2)MY_DOMAIN_PROGRAM_INTERPOLATE(vertexColor)return data;}
这里则是根据传入的边和内部的切割因子的权重,对于新增加的顶点,使用这个方法中的规则填充顶点的对应信息,以完成切割。
MY_DOMAIN_PROGRAM_INTERPOLATE
是定义了一个宏用于重复处理所有的属性,还是要根据实际情况对应处理方法。
相关文章:

Unity URP 如何写基础的曲面细分着色器
左边是默认Cube在网格模式下经过曲面细分的结果,右边是原状态。 曲面细分着色器在顶点着色器、几何着色器之后,像素着色器之前。 它的作用时根据配置信息生成额外的顶点以切割原本的面片。 关于这部分有一个详细的英文教程,感兴趣可以看一…...
android pdf框架-8,图片缓存
解码会产生很多图片,滑过后不要显示,如果直接回收,会浪费不少资源. 在没有缓存的情况下,会看到gc还是比较频繁的. 有了缓存后,明显gc少了. 目录 常用的缓存 自定义缓存 显示相关的内存缓存 解码缓存池 内存缓存实现: 解码缓存池实现: 常用的缓存 lrucache,这是最常用…...

UE5.2 SmartObject使用实践
SmartObject是UE5新出的一项针对AI的功能,可为开发者提供如公园长椅、货摊等交互对象的统一外观封装,如UE的CitySample(黑客帝国Demo)中就运用到了SmartObject。 但SmartObject实践起来较为繁琐,主要依赖于AI及行为树…...

奇舞周刊第521期:实现vue3响应式系统核心-MVP 模型
奇舞推荐 ■ ■ ■ 实现vue3响应式系统核心-MVP 模型 手把手带你实现一个 vue3 响应式系统,代码并没有按照源码的方式去进行组织,目的是学习、实现 vue3 响应式系统的核心,用最少的代码去实现最核心的能力,减少我们的学习负担&…...
Mybatis-plus手写SQL如何使用条件构造器和分页
Mybatis-plus手写SQL如何使用条件构造器和分页插件 前言:在使用mybatis-plus过程中,使用条件构造器和分页插件非常效率的提升开发速度,但有些业务需要使用连表查询,此时还想使用条件构造器和使用分页时应该如何操作呢?…...
Vue的table组件合并行方法
/*** param {Array} data - 原始数据集合* param {string} addParamer - 这个是自定义的参数,向每个对象中添加一个参数 按照这个参数的个数进行合并* param {} args - 剩余参数 这个是合并规则 ,比如按照时间合并 那就传入对象中的时间参数date…...
5. C语言字符串处理常用方法
在 C 语言中,字符串是以字符数组的形式表示的,以空字符 \0 结尾。C 语言提供了一系列的字符串处理函数,可以用于字符串的操作、查找、比较等。以下是一些常用的 C 语言字符串处理函数: 1. 字符串定义与初始化 #include <stdio.h> #include <string.h>int mai…...

ts--(入门到离职系列)
TS 与 JS 的区别 TypeScript[4] 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。-- 官方文档 说人话就是 TS 拓展了 JS 的一些功能,解决了 JS 的一些缺点&#…...
java后端常见问题
java面向对象的特征,如何应用 面向对象编程是利用类和对象的编程思想万物皆成类,对象是类的具体体现,面向对象的三大基础特性,继承封装多态。、封装:封装隐藏了类的具体内部实现机制,可以在不影响使用的情…...

windows系统玩游戏找不到d3dx9_43.dll缺失,无法启动此程序的解决方法
今日,我们要深入讨论d3dx9_43.dll文件的重要性及其缺失问题。最近,我也遇到了这个文件丢失的困扰,因此想借此机会与大家分享如何解决d3dx9_43.dll缺失的问题。 一.电脑d3dx9_43.dll丢失会提示什么? 关于电脑提示d3dx9_43.dll丢失…...
MATLAB中mapminmax函数用法
目录 语法 说明 示例 使用 mapminmax 函数格式化矩阵 mapminmax函数的功能是通过将行最小值和最大值映射到 [-1 1] 来处理矩阵。 语法 [Y,PS] mapminmax(X,YMIN,YMAX) [Y,PS] mapminmax(X,FP) Y mapminmax(apply,X,PS) X mapminmax(reverse,Y,PS) dx_dy mapminmax(d…...
数据结构导航 -- 38篇
数据结构实现代码 线性表 顺序表代码-C-CSDN博客 单链表代码-C-CSDN博客 双链表代码-C-CSDN博客 有序表概述-CSDN博客 栈 栈代码数组实现-C-CSDN博客 栈代码链表实现(链栈)-C-CSDN博客 队列 队列与环形队列顺序存储代码数组实现-C-CSDN博客 队…...

前端性能优化 | CDN缓存
前言 CDN(Content Delivery Network)是一种分布式的网络架构,通过在全球各地部署节点服务器来快速传输和分发网络内容。CDN的主要目标是提供快速、可靠的内容传输,以提升用户体验。 本文主要从以下方面讲解CDN 什么是CDNCDN的作…...

【C#语言入门】17. 事件详解(上)
【C#语言入门】17. 事件详解(上) 一、初步了解事件 定义:单词Event,译为“事件” 通顺的解释就是**“能够发生的什么事情”**,例如,“苹果”不能发生,但是“公司上市”这件事能发生。在C#中事…...
Charles无法打开导出的har文件解决方法
打开出错:MalformedJson: Use JsonReader.setLenient(true) to accept malformed JSON at line1 column 1368184 path $.log.entries[41].request.postData.text 一、解决办法 用json.dumps格式化一下里面内容,保存为新文件再打开 import jsondef modify…...
FFmpeg--FlvPaser源码:解析.flv输出.h264
文章目录 程序功能:函数调用流程:部分FlvParse.h部分FlvParse.cpp 程序功能: 解析flv文件,重写一个h264文件,如输入movie.flv , 输出movie.h264 (只有视频,没有声音) 函数调用流程: 1 Proce…...

【项目笔记】java微服务:黑马头条(day02)
文章目录 app端文章查看,静态化freemarker,分布式文件系统minIO1)文章列表加载1.1)需求分析1.2)表结构分析1.3)导入文章数据库1.3.1)导入数据库1.3.2)导入对应的实体类 1.4)实现思路1.5)接口定义1.6)功能实现1.6.1):导入heima-leadnews-article微服务&am…...

每天五分钟计算机视觉:图像数据不足带来的问题和解决办法
本文重点 在当今的数字时代,图像数据的应用已经渗透到各个领域,包括但不限于计算机视觉、机器学习、自动驾驶、医疗诊断等。然而,当图像数据不足时,会引发一系列问题,对相关应用产生负面影响。 尤其是计算机视觉领域,图像数据尤为珍贵和稀缺,如果计算机视觉的任务中,如…...
手机App防沉迷系统C卷(JavaPythonC++Node.jsC语言)
智能手机方便了我们生活的同时,也侵占了我们不少的时间。"手机App防沉迷系统"能够让我们每天合理的规划手机App使用时间,在正确的时间做正确的事。 它的大概原理是这样的: 1、在一天24小时内,可注册每个App的允许使用时段; 2、一个时段只能使用一个App,举例说明…...
【WEEK2】学习目标及总结【SpringMVC】【中文版】
学习目标: 三周完成SpringMVC入门——第二周 学习内容: 参考视频教程【狂神说Java】SpringMVC最新教程IDEA版通俗易懂使用注释完成MVC程序Controller控制器RestFul风格结果跳转方式数据处理 学习时间及产出: 第二周 MON~FRI 2024.3.4 【W…...
Matlab | matlab中的图像处理详解
MATLAB 图像处理详解 这里写目录标题图像处理 MATLAB 图像处理详解一、图像基础操作1. 图像读写与显示2. 图像信息获取3. 图像类型转换二、图像增强技术1. 对比度调整2. 去噪处理3. 锐化处理三、图像变换1. 几何变换2. 频域变换四、图像分割1. 阈值分割2. 边缘检测3. 区域分割五…...

drawio 开源免费的流程图绘制
开源地址 docker-compose 一键启动 #This compose file adds draw.io to your stack version: 3.5 services:drawio:image: jgraph/drawiocontainer_name: drawiorestart: unless-stoppedports:- 8081:8080- 8443:8443environment:PUBLIC_DNS: domainORGANISATION_UNIT: unitOR…...

视觉SLAM基础补盲
3D Gaussian Splatting for Real-Time Radiance Field Rendering SOTA方法3DGS contribution传统重建基于点的渲染NeRF 基础知识补盲光栅化SFM三角化极线几何标准的双目立体视觉立体匹配理论与方法立体匹配的基本流程李群和李代数 李群和李代数的映射李代数的求导李代数解决求导…...

爆炸仿真的学习日志
今天学习了一下【Workbench LS-DYNA中炸药在空气中爆炸的案例-哔哩哔哩】 https://b23.tv/kmXlN29 一开始 如果你的 ANSYS Workbench 工具箱(Toolbox)里 只有 SPEOS,即使尝试了 右键刷新、重置视图、显示全部 等方法仍然没有其他分析系统&a…...

怎么让大语言模型(LLMs)自动生成和优化提示词:APE
怎么让大语言模型(LLMs)自动生成和优化提示词:APE https://arxiv.org/pdf/2211.01910 1. 研究目标:让机器自己学会设计提示词 问题:大语言模型(如GPT-3)很强大,但需要精心设计的“提示词”才能发挥最佳效果。过去靠人工设计提示词,费时费力,还可能因表述差异导致模…...
网关路由配置(Gateway Filters)
- id: system-admin-api # 路由的编号uri: grayLb://system-serverpredicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组- Path/admin-api/system/**filters:- RewritePath/admin-api/system/v3/api-docs, /v3/api-docs # 配置,…...
ES6——对象扩展之Set对象
在ES6(ECMAScript 2015)中,Set 对象允许存储任何类型的唯一值,无论是原始值还是对象引用。Set 对象有一些有用的方法,可以操作集合中的数据。以下是一些常用的 Set 对象方法: 方法描述 add 向 Set 对象添加…...

智能制造数字孪生全要素交付一张网:智造中枢,孪生领航,共建智造生态共同体
在制造业转型升级的浪潮中,数字孪生技术正成为推动行业变革的核心引擎。从特斯拉通过数字孪生体实现车辆全生命周期优化,到海尔卡奥斯工业互联网平台赋能千行百业,数字孪生技术已从概念验证走向规模化落地。通过构建覆盖全国的交付网络&#…...
使用 Ansible 在 Windows 服务器上安装 SSL 证书
在本教程中,我将向您展示如何使用 Ansible 在 Windows 服务器上安装 SSL 证书。使用 Ansible 自动化 SSL 证书安装过程可以提高 IT 运营的效率、一致性和协作性。我将介绍以下步骤: 将 SSL 证书文件复制到服务器将 PFX 证书导入指定的存储区获取导入的证…...

Qt(part1)Qpushbutton,信号与槽,对象树,自定义信号与槽,lamda表达式。
1、创建Qt程序 2、命名规范及快捷键 3、Qpushbutton按钮创建 4、对象树概念 5、信号与槽 6、自定义信号与槽 7、当自定义信号和槽发生重载时 8、信号可以连接信号,信号也可以断开。 9、lamda表达式...