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

TA学习之路——2.3图形的HLSL常用函数详解

1.基本数学运算

函数作用
max(a,b)返回a,b值中较大的那个
min(a,b)返回a,b值中较小的那个
mul(a,b两变量相乘,常用于矩阵
abs(a)返回a的绝对值
sqrt(x)返回x的平方根
rsqrt(x)返回x的平方根的倒数
degrees(x)将弧度转成角度
radians(x)将角度转成弧度
noise(x)噪声函数

1.1 创建一个测试用例

在这里插入图片描述
第一步,创建一个Quad,并将Scale调到7
第二步,创建一个MathMax材质
第三步,创建一个MathMaxShader
第四步,把材质挂载到Quad上

1.2 MathMaxShader

MathMaxShader代码如下:

Shader "Math/MathMaxShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例_Scale = 1.6;float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = max(1 - x * x,abs(1 - x * x));// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用第62行:

  float Y = max(1 - x * x,abs(1 - x * x));

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

1.3 MathMinShader

MathMinShader代码如下:

Shader "Math/MathMinShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例_Scale = 1.6;float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = min(x, abs(1 - x * x));// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用第62行:

float Y = min(x, abs(1 - x * x));

测试效果展示(测试用例请参考1.1中的介绍)::
在这里插入图片描述

1.4 MathMulShader

mul 函数是 HLSL 中的内置函数,用于执行矩阵乘法或矩阵与向量的乘法。由于 Unity 使用列主序矩阵,矩阵乘法的顺序需要特别注意。

利用mul函数可以让1.3中的图形进行旋转。以下是使用了一个绕y轴旋转的旋转矩阵。

MathMulShader的代码,如下:

Shader "Math/MathMulShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0_Angle ("Angle", Range(-360, 360)) = 0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面//Cull Back // 剔除背面,仅渲染正面Cull Off // 关闭剔除CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;float _Angle;v2f vert (appdata v){v2f o;// 创建绕Y轴旋转矩阵(注意角度转弧度)float angle = radians(_Angle); float4x4 rotMatrix = float4x4(cos(angle), 0, sin(angle), 0,0, 1, 0, 0,-sin(angle), 0, cos(angle), 0,0, 0, 0, 1);// 先旋转模型顶点,再进行MVP变换float4 rotatedVertex = mul(rotMatrix, v.vertex); // 模型空间旋转o.vertex = UnityObjectToClipPos(rotatedVertex); // MVP变换o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = min(x, abs(1 - x * x));// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float4 rotatedVertex = mul(rotMatrix, v.vertex); 

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

绕y轴的旋转矩阵参考

1.5 MathAbsShader

MathAbsShader代码如下:

Shader "Math/MathAbsShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例_Scale = 1.6;float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = abs(x);// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float Y = abs(x);

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

1.6 MathRoundShader

MathRoundShader代码如下:

Shader "Math/MathRoundShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例_Scale = 1.6;float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = round(x * x);// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float Y = round(x * x);

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

1.7 MathSqrtShader

MathSqrtShader代码如下:

Shader "Math/MathSqrtShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{//这里可以注释掉自己调节_Scale = 1.6;// 将UV转换到中心坐标系并调整比例float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = sqrt(x * x);// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float Y = sqrt(x * x);

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

1.8 MathRsqrtShader

MathRsqrtShader代码如下:

Shader "Math/MathRsqrtShader"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面Cull Back // 剔除背面,仅渲染正面//Cull Off // 剔除正面,仅渲染背面CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{//这里可以注释掉自己调节_Scale = 1.6;// 将UV转换到中心坐标系并调整比例float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = rsqrt(x * x);// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float Y = rsqrt(x * x);

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

1.9 MathDegreeAndRadiansShader

MathDegreeAndRadians代码如下:

Shader "Math/MathDegreeAndRadians"
{Properties{_Color ("Color", Color) = (1,1,1,1)_LineWidth ("Line Width", Range(0.001, 0.1)) = 0.01_Scale ("Scale", Float) = 1.0_Radians ("Radians", Range(-10, 10)) = 0}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }LOD 100//Blend SrcAlpha OneMinusSrcAlpha 是 Unity Shader 中用于定义颜色混合模式的命令,//其核心作用是 实现透明效果的标准 Alpha 混合。//具体来说,它会将当前片元(源颜色)的 Alpha 值作为混合因子,//与帧缓冲区中已有颜色(目标颜色)进行加权混合//混合公式为最终颜色最终颜色=(源颜色 * SrcAlpha)+(目标颜色 * (1-SrcAlpha))Blend SrcAlpha OneMinusSrcAlphaPass{//Cull Front // 剔除正面,仅渲染背面//Cull Back // 剔除背面,仅渲染正面Cull Off // 关闭剔除CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _LineWidth;float _Scale;float _Radians;v2f vert (appdata v){v2f o;// 创建绕Y轴旋转矩阵(注意角度转弧度)//弧度转角度float angle = degrees(_Radians);//角度转弧度float rad = radians(angle); //这里为了方便理解degrees和radians,这样写;//也可以不要degrees和radians上面两个,直接把rad换成_Radiansfloat4x4 rotMatrix = float4x4(cos(rad), 0, sin(rad), 0,0, 1, 0, 0,-sin(rad), 0, cos(rad), 0,0, 0, 0, 1);//以下代码与上面三句等同//float4x4 rotMatrix = float4x4(//    cos(_Radians), 0, sin(_Radians), 0,//    0, 1, 0, 0,//    -sin(_Radians), 0, cos(_Radians), 0,//    0, 0, 0, 1//);// 先旋转模型顶点,再进行MVP变换float4 rotatedVertex = mul(rotMatrix, v.vertex); // 模型空间旋转o.vertex = UnityObjectToClipPos(rotatedVertex); // MVP变换o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target{                // 将UV转换到中心坐标系并调整比例float x = (i.uv.x - 0.5) * 2.0 * _Scale;float y = (i.uv.y - 0.5) * 2.0 * _Scale;// 计算函数Y值float Y = abs(x);// 计算垂直距离并应用抗锯齿float diff = abs(y - Y);float line1 = 1.0 - smoothstep(0.0, _LineWidth, diff);// 组合颜色fixed4 col = _Color;col.a *= line1;return col;}ENDCG}}
}

关键函数运用:

float angle = degrees(_Radians);
float rad = radians(angle); 

同样滑动_Radians值可以绕y轴旋转

1.10 自定义的MathNoiseShader

MathNoiseShader代码如下:

Shader "Math/MathNoise" {Properties {_Color ("Color", Color) = (1,1,1,1)_NoiseScale ("Noise Scale", Range(0.1, 50)) = 10.0}SubShader {Tags { "RenderType"="Opaque" }Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata {float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f {float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};float4 _Color;float _NoiseScale;v2f vert (appdata v) {v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}// 随机函数float rand(float2 co) {return frac(sin(dot(co, float2(12.9898, 78.233))) * 43758.5453);}// 噪声函数float noise(float2 uv) {float2 i = floor(uv);float2 f = frac(uv);float a = rand(i);float b = rand(i + float2(1, 0));float c = rand(i + float2(0, 1));float d = rand(i + float2(1, 1));float2 u = f * f * (3.0 - 2.0 * f);return lerp(lerp(a, b, u.x), lerp(c, d, u.x), u.y);}fixed4 frag (v2f i) : SV_Target {float n = noise(i.uv * _NoiseScale);return _Color * n;}ENDCG}}
}

测试效果展示(测试用例请参考1.1中的介绍):
在这里插入图片描述

2.幂指对函数

函数作用
pow(x,y)x的y次幂 x y x^y xy
exp(x)返回以e为底的指数函数 e x e^x ex
exp2(x)返回以2为底的指数函数 2 x 2^x 2x
Idexp(x,exp)返回x与2的exp次方的乘积 x 2 e p x x2^{epx} x2epx
log(x)求以10为底的对数 l n x lnx lnx
log10(x)求以10为底的对数 l o g 10 x log_{10}x log10x
log2(x)求以2为底的对数 l o g 2 x log_2x log2x
frexp(x,out exp)把浮点数x分解成尾数和指数返回值是尾数,exp参数返回的值是指数 x = r e t ∗ 2 e x p x = ret*2^{exp} x=ret2exp

2.1 pow(x,y)

MathPowShader代码如下:

Shader "Math/MathPowShader"
{Properties{_Color ("Line Color", Color) = (1,0,0,1)_LineWidth ("Line Width", Range(0, 0.1)) = 0.05_XMin ("X Min", Float) = -5_XMax ("X Max", Float) = 5_YMin ("Y Min", Float) = 0_YMax ("Y Max", Float) = 32}SubShader{Tags { "RenderType"="Transparent" "Queue"="Transparent" }Blend SrcAlpha OneMinusSrcAlphaPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct 

相关文章:

  • Git常用指令速查
  • Post与Get以及@Requestbody和@Pathvariable标签的应用
  • 使用Docker操作MySQL
  • JavaScript 中的类型转换机制?
  • 高级项目管理
  • iVX 引领软件开发进入 “可视化逻辑时代”
  • 深入学习解读:《数据安全技术 数据分类分级规则》【附全文阅读】
  • 语言特性的发展与应用:从基础到前沿的全面解析
  • [C++]C++20协程的原理
  • Java基础 4.29
  • 【18】爬虫神器 Pyppeteer 的使用
  • Mysql存储引擎、锁机制
  • 【深度学习的灵魂】图片布局生成模型LayoutPrompt(1)
  • 算法题(137):丢手绢
  • (003)Excel 在滚动的时候,保持标题栏可见
  • C# 继承详解
  • MCP Java SDK 介绍与使用指南
  • Lucene中不同搜索类型的使用方法、基本概念、应用场景、差异对比,并通过表格进行总结
  • Linux系统基础:基础指令简介(网络概念部分)
  • 价值投资笔记:企业护城河——虚假陷阱与隐性壁垒的深度解析
  • 铺就长三角南北“交通动脉”,乍嘉苏改高速扩建项目首桩入位
  • 体重管理门诊来了,瘦不下来的我们有救了?|健康有方FM
  • 狄威已任国铁集团副总经理
  • 交行一季度净利253.72亿元增1.54%,不良率微降
  • 被算法重塑的世界,人与技术如何和谐共处
  • 助力企业高质量出海,上海静安发放服务包、服务券