Unity Shader编程】之基础纹理

一,单张纹理

好的,用户想学习Unity Shader中的单张纹理章节。我需要根据提供的搜索结果来整理相关内容。首先,查看搜索结果中的相关部分,特别是‌、‌、‌、‌、‌这几条,因为它们提到了基础纹理、单张纹理的实现方法和相关属性设置。

用户问题中的“单张纹理章节”可能涉及纹理映射的基本概念、UV坐标、纹理属性设置以及在Shader中的具体应用。需要分步骤讲解如何实现单张纹理的渲染,包括Properties块的定义、顶点着色器和片元着色器的处理,以及纹理采样和光照计算。

要注意引用来源的标注,每个要点后面要加上对应的角标,比如‌提到纹理类型和UV坐标,‌和‌讨论了纹理属性和Wrap Mode,‌中的代码示例展示了如何声明变量和使用TRANSFORM_TEX。需要确保每个步骤都有对应的引用,并且结合多个来源的信息,避免重复引用同一个网页。

同时,用户之前的问题涉及法线贴图,但现在转向单张纹理,可能希望了解基础部分,所以需要从最基础的纹理映射开始,逐步展开。结构上可以分为基本概念、实现步骤、关键代码示例、属性设置和常见问题,每个部分引用相关搜索结果。确保回答清晰、结构化,并且每个点都有对应的来源支持。

单张纹理章节核心知识点总结‌

  1. 纹理映射基础‌
    定义‌:通过纹理映射(Texture Mapping)将2D图片逐纹素(Texel)映射到模型表面,控制模型颜色和细节‌。
    UV坐标‌:顶点存储的纹理映射坐标(二维变量 (u,v)),通常归一化到 [0,1] 范围,用于采样纹理‌。
    坐标系差异‌:
    OpenGL纹理空间原点在左下角,DirectX在左上角,Unity默认采用OpenGL风格‌。
  2. 单张纹理实现步骤‌
    2.1 声明纹理属性‌

在Shader的 Properties 块中定义纹理贴图及参数:

Properties {
_MainTex (“基础贴图”, 2D) = “white” {} // white 表示默认纯白色纹理‌:ml-citation{ref=“1,8” data=“citationList”}
_Color (“颜色调节”, Color) = (1,1,1,1) // 可选颜色混合参数‌:ml-citation{ref=“8” data=“citationList”}
}

需在CG代码中声明变量:

sampler2D _MainTex;
float4 _MainTex_ST; // 存储Tiling和Offset参数(xy为缩放,zw为偏移)‌:ml-citation{ref=“4,8” data=“citationList”}

2.2 顶点着色器处理UV‌

通过 TRANSFORM_TEX 宏应用Tiling/Offset:

struct v2f {
float2 uv : TEXCOORD0;
// 其他数据(如顶点位置、法线等)
};

v2f vert(appdata_base v) {
v2f o;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); // 应用缩放和偏移‌:ml-citation{ref=“1,8” data=“citationList”}
return o;
}

2.3 片元着色器采样与混合‌

采样纹理并与颜色参数混合,计算最终颜色:

fixed4 frag(v2f i) : SV_Target {
fixed4 texColor = tex2D(_MainTex, i.uv); // 采样纹理‌:ml-citation{ref=“1,6” data=“citationList”}
fixed3 albedo = texColor.rgb * _Color.rgb; // 混合颜色参数‌:ml-citation{ref=“8” data=“citationList”}
// 应用光照计算(如Lambert漫反射)
return fixed4(albedo, texColor.a);
}

  1. 纹理属性设置关键点‌
    Texture Type‌:
    单张纹理通常设为 Default,法线贴图需设为 Normal Map‌。
    Wrap Mode‌:
    Repeat:平铺纹理,适合无缝贴图‌;
    Clamp:边缘拉伸,避免接缝处采样异常‌。
    Filter Mode‌:
    Point:像素风格,性能最优‌;
    Bilinear/Trilinear:平滑过渡,质量更高但消耗更大‌。
  2. 常见问题与调试‌
    UV坐标异常‌:检查模型是否导出正确UV,或调整 _MainTex_ST 参数‌。
    颜色偏差‌:确保纹理导入设置中 sRGB 选项正确(颜色贴图启用,法线贴图禁用)‌。
    性能优化‌:
    移动端优先使用低分辨率纹理和 Bilinear 滤波‌;
    复杂场景启用Mipmap减少远处纹理锯齿‌。
  3. 完整代码示例(Surface Shader)‌
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "Custom/SingleTextureExample" {  Properties {  _MainTex ("Base Texture", 2D) = "white" {}  _Color ("Color Tint", Color) = (1,1,1,1)  }  SubShader {  Pass {  Tags { "LightMode" = "ForwardBase" }  CGPROGRAM  #pragma vertex vert  #pragma fragment frag  #include "UnityCG.cginc"  struct appdata {  float4 vertex : POSITION;  float3 normal : NORMAL;  float2 uv : TEXCOORD0;  };  struct v2f {  float4 pos : SV_POSITION;  float2 uv : TEXCOORD0;  float3 worldNormal : TEXCOORD1;  };  sampler2D _MainTex;  float4 _MainTex_ST;  fixed4 _Color;  fixed4 _LightColor0;  v2f vert (appdata v) {  v2f o;  // --- 方法1:Unity内置函数(注释掉以禁用)---  // o.pos = UnityObjectToClipPos(v.vertex);  // o.uv = TRANSFORM_TEX(v.uv, _MainTex);  // o.worldNormal = UnityObjectToWorldNormal(v.normal);  // --- 方法2:手动计算(默认启用)---  o.pos = UnityObjectToClipPos(v.vertex);          // 手动MVP转换‌:ml-citation{ref="3,4" data="citationList"}  o.uv = v.uv * _MainTex_ST.xy + _MainTex_ST.zw;    // 手动计算Tiling/Offset‌:ml-citation{ref="2,6" data="citationList"}  o.worldNormal = mul((float3x3)unity_ObjectToWorld, v.normal);  // 手动法线转换‌:ml-citation{ref="4,5" data="citationList"}  return o;  }  fixed4 frag (v2f i) : SV_Target {  // 纹理采样与颜色混合  fixed4 texColor = tex2D(_MainTex, i.uv);          // 采样主纹理‌:ml-citation{ref="1,2" data="citationList"}  fixed3 albedo = texColor.rgb * _Color.rgb;  // 光照计算(漫反射)  float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  float3 normal = normalize(i.worldNormal);  float diff = saturate(dot(normal, lightDir)*0.5+0.5);     // 漫反射强度‌:ml-citation{ref="4,5" data="citationList"}  fixed3 finalColor = albedo * _LightColor0.rgb * diff;  return fixed4(finalColor, texColor.a);  }  ENDCG  }  }  FallBack "Diffuse"  
}  

二,法线纹理

‌Unity 法线贴图设置与工作原理

‌法线贴图对顶点的影响机制‌
法线贴图‌不会直接修改顶点坐标‌,而是通过‌扰动表面法线方向‌改变光照计算结果,从而在视觉上模拟凹凸效果。以下是具体实现原理与步骤:
‌一、顶点与法线的关系‌
‌顶点数据基础‌:
顶点包含‌位置(Position)‌、‌法线(Normal)‌和‌切线(Tangent)‌等属性,定义了模型的几何形状与表面朝向‌。
顶点着色器中,通过模型变换矩阵(如 UNITY_MATRIX_MVP)将顶点从模型空间变换到裁剪空间‌。
‌法线贴图的作用‌:
法线贴图存储的是‌切线空间下的法线偏移‌(RGB 通道映射到 [-1,1] 范围),而非顶点位置信息‌。
通过修改法线方向,改变‌光线反射方向‌,在固定顶点位置下模拟表面凹凸感‌。

将贴图设为 ‌Normal Map‌ 类型后,Unity 通过以下流程将其识别为物体法线方向,并参与光照计算:

‌**1. ‌贴图类型标记的作用
数据格式处理‌:标记为 Normal Map 后,Unity 会针对不同平台(如 PC、移动端)自动采用合适的压缩格式(如 DXT5nm)‌。
法线解压优化‌:通过 UnpackNormal 函数将法线贴图的颜色值(01)映射回三维法线向量(-11),例如:
glsl
Copy Code
float3 normalTangent = UnpackNormal(tex2D(_NormalMap, uv)); // 解压法线‌:ml-citation{ref=“1,3” data=“citationList”}

此步骤确保法线方向的正确性‌。
‌**2. ‌法线贴图的转换流程
切线空间→世界空间‌:
顶点着色器‌传递模型的‌切线‌(Tangent)、‌副切线‌(Binormal)和‌原始法线‌(Normal),构建 ‌TBN 矩阵‌(Tangent-Binormal-Normal Matrix)‌。

float3x3 TBN = float3x3(  normalize(worldTangent),  normalize(worldBinormal),  normalize(worldNormal)  
); // TBN矩阵构建‌:ml-citation{ref="4,5" data="citationList"}  

片元着色器‌通过 TBN 矩阵将切线空间法线转换到世界空间:

float3 worldNormal = mul(normalTangent, TBN); // 切线→世界空间转换‌:ml-citation{ref="4,5" data="citationList"}  

‌**3. ‌法线方向的应用
光照计算‌:转换后的世界空间法线参与光照模型(如 Blinn-Phong 或 PBR),直接影响漫反射和高光效果。例如:

float diff = saturate(dot(worldNormal, lightDir)); // 漫反射计算‌:ml-citation{ref="4,6" data="citationList"}  
float3 halfDir = normalize(lightDir + viewDir);  
float spec = pow(saturate(dot(worldNormal, halfDir)), _Gloss * 128); // 高光计算‌:ml-citation{ref="4,6" data="citationList"}  

关键注意事项‌

*贴图导入设置‌: 必须将法线贴图类型设为 Normal Map,否则 UnpackNormal 无法正确解压数据‌。 Unity 默认法线贴图的 ‌z 分量为正‌,仅存储 x、y 分量(z 通过计算得出)‌。

Shader 属性命名‌: 法线贴图变量需命名为 _BumpMap 或 _NormalMap,否则 Unity 内置管线可能无法识别‌。 非均匀缩放修正‌: 若模型存在缩放,需通过‌逆转置矩阵‌修正法线方向:*

**float3 worldNormal = mul(transpose(inverse((float3x3)unity_ObjectToWorld)), normal);  

避免因缩放导致法线方向错误‌。
效果对比‌
未用法线贴图‌ ‌使用法线贴图‌
表面平滑无细节 凹凸细节清晰,光影动态变化
依赖模型顶点法线 低模即可实现高精度效果**

通过上述流程,Unity Shader 能够将法线贴图的颜色数据解析为法线向量,并动态影响光照计算,最终实现高细节的表面效果‌。

法线纹理的两种计算方式对比‌

  1. 切线空间计算(Tangent Space)‌

核心逻辑‌:在切线空间下直接处理光照方向、视角方向,将光照方向转换到切线空间进行计算‌。
优势‌:

效率高‌:矩阵变换(如光照方向转换)可在顶点着色器完成,减少片元着色器计算量‌。
灵活性高‌:
支持 ‌UV 动画‌(如水流、熔岩动态效果)‌;
法线贴图可跨模型复用(记录相对法线信息,不受模型变形影响)‌。
可压缩‌:仅需存储法线贴图的 XY 分量(Z 方向由归一化推导得出)‌。

劣势‌:

全局效果精度低‌:
处理镜面反射、环境映射等全局效果时可能不够准确‌;
切线空间法线需逐顶点构造 TBN 矩阵,模型变形(如骨骼动画)可能导致误差‌。
2. 世界空间计算(World Space)‌

核心逻辑‌:将法线贴图从切线空间转换到世界空间,直接在世界坐标系下进行光照计算‌。
优势‌:

全局效果精准‌:
光照、反射等计算基于统一的世界坐标系,精度更高‌;
适用于复杂光照场景(如动态阴影、全局光照)‌。
实现直观‌:无需处理切线空间与模型空间的关系,逻辑更清晰‌。

劣势‌:

性能开销大‌:
TBN 矩阵构造和法线空间转换需在片元着色器执行,计算密集‌;
对低端设备不友好(如移动端)‌。
兼容性差‌:
法线贴图无法跨模型复用(存储绝对法线方向)‌;
模型变形时需重新计算 TBN 矩阵‌。
适用场景总结‌
计算方式‌ ‌推荐场景‌ ‌不适用场景‌
切线空间计算‌ 移动端/性能敏感场景、UV 动画、模型复用需求‌ 高精度全局光照、动态模型变形‌
世界空间计算‌ PC/主机端、复杂光照场景(如镜面反射、环境映射)‌ 低性能设备、需 UV 动画的场景‌

关键结论‌

效率优先选切线空间‌:适合性能敏感场景及动态效果需求‌;
效果优先选世界空间‌:需高精度全局光照时不可替代‌。

1,‌切线空间法线贴图实现原理与步骤

基本思路:再片元着色器中通过纹理采样得到切线空间下的法线,然后再与切线空间下的视角方向,光照方向等进行计算。为此,我们需要再顶点着色器中把视角方向和光照方向从模型空间变到切线空间中
切线空间法线贴图通过‌顶点切线坐标系‌存储法线偏移,在 Shader 中通过 ‌TBN 矩阵‌将法线转换到世界空间参与光照计算。以下是完整实现流程:
‌一、原理概述‌
‌切线空间特性‌:
切线空间由顶点‌切线(T)‌、‌副切线(B)‌、‌法线(N)‌构成,法线贴图存储的是该空间下的法线偏移‌。
在此空间下,法线方向‌无需依赖模型姿态‌,仅需将光照方向、视角方向等外部向量转换到切线空间,即可直接参与计算‌13。
‌核心步骤‌:
‌顶点着色器‌:将模型空间的光照方向、视角方向转换到切线空间。
‌片元着色器‌:采样法线贴图,与切线空间的光照方向、视角方向计算光照‌。

Shader "Custom/TangentSpaceNormal" {Properties {_MainTex ("Albedo", 2D) = "white" {}_BumpMap ("Normal Map", 2D) = "bump" {}}SubShader {Tags { "RenderType"="Opaque" }Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT; // tangent.w用于副切线方向修正float2 uv : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float2 uv : TEXCOORD0;// 切线空间下的光照方向与视角方向float3 lightDirTS : TEXCOORD1; // Tangent Space Light Directionfloat3 viewDirTS : TEXCOORD2;  // Tangent Space View Direction};sampler2D _MainTex, _BumpMap;v2f vert(appdata v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.uv;// 计算TBN矩阵float3 worldNormal = UnityObjectToWorldNormal(v.normal);float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);float3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;float3x3 TBN_World = float3x3(worldTangent, worldBinormal, worldNormal);// 模型空间→切线空间转换矩阵float3x3 TBN_Object = mul(TBN_World, (float3x3)unity_WorldToObject);// 将光照方向、视角方向转换到切线空间float3 lightDirObj = normalize(ObjSpaceLightDir(v.vertex)); // 模型空间光照方向float3 viewDirObj = normalize(ObjSpaceViewDir(v.vertex));    // 模型空间视角方向o.lightDirTS = mul(TBN_Object, lightDirObj);                 // 模型→切线空间o.viewDirTS = mul(TBN_Object, viewDirObj);return o;}fixed4 frag(v2f i) : SV_Target {// 采样法线贴图(切线空间)fixed3 normalTS = UnpackNormal(tex2D(_BumpMap, i.uv));// 切线空间下的光照计算(以Blinn-Phong为例)float3 lightDirTS = normalize(i.lightDirTS);float3 viewDirTS = normalize(i.viewDirTS);float3 halfDirTS = normalize(lightDirTS + viewDirTS);// 漫反射float diff = saturate(dot(normalTS, lightDirTS));// 高光float spec = pow(saturate(dot(normalTS, halfDirTS)), 32);fixed4 albedo = tex2D(_MainTex, i.uv);return albedo * _LightColor0 * (diff + spec);}ENDCG}}
}

在这里插入图片描述

2,‌世界空间法线贴图实现原理与步骤

‌顶点着色器阶段‌:

构建‌TBN矩阵的逆矩阵‌(Model→Tangent空间)‌。
将模型空间的法线、切线、副切线转换到‌世界空间‌,构建‌World→Tangent矩阵‌‌45。
‌片元着色器阶段‌:

采样法线贴图后,需通过矩阵将法线从‌切线空间‌变换到‌世界空间‌,再与光照方向计算‌。

Shader “Custom/WorldSpaceNormalMap” {
Properties {
_MainTex (“Albedo”, 2D) = “white” {}
_NormalMap (“Normal Map”, 2D) = “bump” {}
_NormalScale (“Normal Scale”, Range(0,2)) = 1.0
}
SubShader {
Tags { “RenderType”=“Opaque” }

    Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata {float4 vertex : POSITION;float3 normal : NORMAL;float4 tangent : TANGENT;float2 uv : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float3 worldPos : TEXCOORD1;// TBN矩阵相关向量float3 worldNormal : TEXCOORD2;float3 worldTangent : TEXCOORD3;float3 worldBitangent : TEXCOORD4;};sampler2D _MainTex, _NormalMap;float _NormalScale;v2f vert (appdata v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = v.uv;o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;// --- 使用Unity内置函数计算 ---// o.worldNormal = UnityObjectToWorldNormal(v.normal);// o.worldTangent = UnityObjectToWorldDir(v.tangent.xyz);// --- 手动计算TBN矩阵 ---o.worldNormal = mul((float3x3)unity_ObjectToWorld, v.normal);o.worldTangent = mul((float3x3)unity_ObjectToWorld, v.tangent.xyz);// 副切线计算(考虑手性与非均匀缩放)float3 worldBitangent = cross(o.worldNormal, o.worldTangent) * v.tangent.w * unity_WorldTransformParams.w;o.worldBitangent = worldBitangent;return o;}float4 frag (v2f i) : SV_Target {// 采样法线贴图并解包(切线空间→世界空间)float3 tangentNormal = UnpackNormal(tex2D(_NormalMap, i.uv));tangentNormal.xy *= _NormalScale;tangentNormal.z = sqrt(1 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));// 构建TBN矩阵float3x3 tbn = float3x3(normalize(i.worldTangent),normalize(i.worldBitangent),normalize(i.worldNormal));// 将法线从切线空间转换到世界空间float3 worldNormal = mul(tbn, tangentNormal);// 光照计算(世界空间)float3 lightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos);float diffuse = max(0, dot(worldNormal, lightDir));// 采样漫反射贴图float4 albedo = tex2D(_MainTex, i.uv);return albedo * diffuse;}ENDCG}
}

}

‌关键逻辑解析‌
‌顶点着色器阶段‌

‌TBN矩阵构建‌:
使用内置函数时,直接调用 UnityObjectToWorldNormal 和 UnityObjectToWorldDir 转换法线、切线到世界空间‌。
手动计算时,通过 mul 与 unity_ObjectToWorld 矩阵完成变换,并计算副切线(需处理非均匀缩放与手性)‌。
‌片元着色器阶段‌

‌法线解包‌:UnpackNormal 用于解码法线贴图(支持压缩格式)‌。
‌TBN矩阵应用‌:通过矩阵乘法将切线空间法线转换到世界空间‌。
‌光照计算‌:所有方向向量统一在世界空间下计算漫反射‌。
‌渐变纹理(Ramp Texture)的核心概念与实现‌
渐变纹理是一种通过‌预定义颜色过渡规则‌控制表面光照效果的纹理技术,主要用于实现‌非真实感渲染‌(如卡通风格、插画风格)‌13。其核心原理与关键应用如下:

三,渐变纹理

‌一、基本原理‌

‌替代传统漫反射计算‌

传统Lambert模型通过法线与光源方向点积计算明暗,而渐变纹理将计算结果映射到‌0~1区间‌,作为UV坐标采样渐变纹理颜色‌13。
公式:
glsl
Copy Code
float halfLambert = dot(normal, lightDir) * 0.5 + 0.5; // 映射到[0,1]
float3 rampColor = tex2D(_RampTex, float2(halfLambert, 0.5));
‌颜色可控性‌

设计师可通过调整渐变纹理的‌颜色过渡曲线‌,精确控制物体表面的明暗层次与色调变化,例如实现硬边阴影或冷暖色调过渡‌。
‌二、核心优势‌
‌风格化渲染支持‌
渐变纹理通过离散的颜色分界强化轮廓线,使模型呈现‌卡通插画风格‌(见图1)‌。
‌性能高效‌
仅需一次纹理采样即可替代复杂的光照计算,适用于移动端或低性能设备‌。

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "Unity Shaders Book/Chapter 7/Ramp Texture" {Properties {_Color ("Color Tint", Color) = (1, 1, 1, 1)_RampTex ("Ramp Tex", 2D) = "white" {}_Specular ("Specular", Color) = (1, 1, 1, 1)_Gloss ("Gloss", Range(8.0, 256)) = 20}SubShader {Pass { Tags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag#include "Lighting.cginc"fixed4 _Color;sampler2D _RampTex;float4 _RampTex_ST;fixed4 _Specular;float _Gloss;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;};struct v2f {float4 pos : SV_POSITION;float3 worldNormal : TEXCOORD0;float3 worldPos : TEXCOORD1;float2 uv : TEXCOORD2;};v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.uv = TRANSFORM_TEX(v.texcoord, _RampTex);return o;}fixed4 frag(v2f i) : SV_Target {fixed3 worldNormal = normalize(i.worldNormal);fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;// Use the texture to sample the diffuse colorfixed halfLambert  = 0.5 * dot(worldNormal, worldLightDir) + 0.5;fixed3 diffuseColor = tex2D(_RampTex, fixed2(halfLambert, halfLambert)).rgb * _Color.rgb;fixed3 diffuse = _LightColor0.rgb * diffuseColor;fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));fixed3 halfDir = normalize(worldLightDir + viewDir);fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);return fixed4(ambient + diffuse + specular, 1.0);}ENDCG}} FallBack "Specular"
}

4,遮罩纹理

‌一、技术原理‌
‌遮罩作用机制‌

遮罩纹理存储灰度值(单通道)或RGBA多通道数据,在渲染过程中通过‌纹理采样‌获取特定位置的遮罩值(如 r 通道),并与表面属性(如高光强度、漫反射系数)进行‌乘法运算‌,实现区域化控制‌。
公式示例(控制高光强度):
glsl
Copy Code
float mask = tex2D(_MaskTex, uv).r;
float3 specular = _LightColor0.rgb * pow(max(0, dot(N, H)), _Gloss) * mask;
(mask 为遮罩值,0表示完全屏蔽高光,1表示完全保留)‌。
‌数据映射规则‌

灰度值范围(0~1)对应属性影响的衰减程度,例如:
‌0(黑色)‌:完全屏蔽效果(如无高光)
‌0.5(灰色)‌:中等强度
‌1(白色)‌:完全生效‌。

fixed4 frag(v2f i) : SV_Target {  // 采样基础颜色  fixed4 albedo = tex2D(_MainTex, i.uv);  // 计算光照方向与视角方向  float3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));  float3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));  float3 halfDir = normalize(lightDir + viewDir);  // 采样遮罩纹理(R通道控制高光强度)  float mask = tex2D(_MaskTex, i.uv).r;  // 计算高光反射  float spec = pow(max(0, dot(i.worldNormal, halfDir)), _Gloss);  float3 specular = _LightColor0.rgb * _Specular.rgb * spec * mask;  // 遮罩值mask控制高光区域‌:ml-citation{ref="1,2" data="citationList"}  // 最终颜色混合  return fixed4(albedo.rgb + specular, 1.0);  
}  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/32038.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT系列教程(18) MVC结构之QItemSelectionModel模型介绍

视频教程 https://www.bilibili.com/video/BV1FP4y1z75U/?vd_source8be9e83424c2ed2c9b2a3ed1d01385e9 QItemSelectionModel Qt的MVC结构支持多个View共享同一个model,包括该model的选中状态等。我们可以通过设置QItemSelectionModel,来更改View的选…

全网最详解答OSPF基础

目录 此图片为思科的(有些地方不对) 总结状态机: OSPF的工作过程: 结构突变 1 突然新增一个网段--触发更新 2 突然断开一个网段--触发更新 3 无法通信---dead time OSPF的配置 ​编辑条件匹配: ​编辑1&…

Flink深入浅出之05:CEP复杂事件

深入浅出Flink-第五天 1️⃣深入理解Flink的CEP的机制和使用,Flink实时处理应用案例。 4️⃣ 要点 📖 1. Flink的复杂事件处理机制CEP 1.1 CEP概念 CEP是Complex Event Processing三个单词的缩写,表示复杂事件处理,是一种基于…

AI编程: 一个案例对比CPU和GPU在深度学习方面的性能差异

背景 字节跳动正式发布中国首个AI原生集成开发环境工具(AI IDE)——AI编程工具Trae国内版。 该工具模型搭载doubao-1.5-pro,支持切换满血版DeepSeek R1&V3, 可以帮助各阶段开发者与AI流畅协作,更快、更高质量地完…

基于腾讯云高性能HAI-CPU的跨境电商客服助手全链路解析

跨境电商的背景以及痛点 根据Statista数据,2025年全球跨境电商市场规模预计达6.57万亿美元,年增长率保持在12.5% 。随着平台规则趋严(如亚马逊封店潮),更多卖家选择自建独立站,2024年独立站占比已达35%。A…

神经网络探秘:原理、架构与实战案例

神经网络探秘:原理、架构与实战案例 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。https://www.captainbed.cn/ccc 在人工智能的浪潮中,神经网络作为核心驱动力之一…

Web网页制作(静态网页):千年之恋

一、是用的PyCharm来写的代码 二、代码中所用到的知识点(无 js) 这段HTML代码展示了一个简单的注册页面,包含了多个HTML元素和CSS样式的应用。 这段HTML代码展示了一个典型的注册页面,包含了常见的HTML元素和表单控件。通过CSS样…

win32汇编环境,对话框中使用树形视图示例四

;运行效果,当点击张辽时,展示张辽的图像 ;当点击曹仁时,展示曹仁的图像 ;win32汇编环境,对话框中使用树形视图示例四 ;当点击树形视图treeview控件中的某项时,展示某些功能。这里展示的是当点到某个将领时,显示某个将领的图像 ;直接抄进RadAsm可编译运行。重要部分加备注。…

基于SpringBoot的“体育购物商城”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“体育购物商城”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体模块设计 前台用户登录界面 系统首页界面…

c#面试题整理9

1.遍历xml文档 2.解释一下这段 String s new String("xyz"); 这段在C#平台中,编译失败 3.说明一下抽象类 抽象类可以有构造函数 抽象类不能是静态和密封的类,密封的类表示无法继承,抽象类本身就不可实例化,加不好…

第85期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区,集成了生成预训练Transformer(GPT)、人工智能生成内容(AIGC)以及大语言模型(LLM)等安全领域应用的知识。在这里,您可以找…

如何安全处置旧设备?

每年,数百万台旧设备因老化、故障或被新产品取代而被丢弃,这些设备上存储的数据可能带来安全风险。 如果设备没有被正确删除数据,这些数据往往仍可被恢复。因此,安全处置旧设备至关重要。 旧设备可能包含的敏感数据 旧设备中可能…

【物联网-WIFI】

物联网-WIFI ■ ESP32-C3-模块简介■ ESP32-C3-■ ESP32-C3-■ WIFI-模组■ WIFI-■ WIFI- ■ ESP32-C3-模块简介 ■ ESP32-C3- ■ ESP32-C3- ■ WIFI-模组 ■ WIFI- ■ WIFI-

Linux——system V共享内存

共享内存区是最快的IPC(进程内通信)形式,不再通过执行进入内核的系统调用来传递彼此的数据 1.共享内存的原理 IPC通信的本质是让不同的进程先看到同一份资源,然后再进行通信,所以想要通过共享内存进行通信,那么第一步一定是让两个…

爱普生可编程晶振SG-8200CJ特性与应用

在高速发展的电子技术领域,时钟源作为电子系统的“心脏”,其性能直接影响设备的稳定性与可靠性。爱普生SG-8200CJ可编程晶振凭借其优秀的频率精度、低抖动性能及广泛的环境适应性,正成为众多领域的得力之选,为各类设备的高效运行与…

基于YOLO11深度学习的运动品牌LOGO检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

小程序 wxml 语法 —— 36 wxml 语法 - setData() 修改数据

在小程序中修改数据不推荐通过赋值的方式进行修改,通过赋值的方式修改数据无法改变页面的数据; 在微信小程序中,推荐调用 setData() 方式进行修改,setData() 方法接收对象作为参数,key 是需要修改的数据,v…

Linux 生成静态库

文章目录 前提小知识生成和使用.a库操作步骤 在应用程序中,有一些公共的代码需要反复使用的,可以把这些代码制作成“库文件”;在链接的步骤中,可以让链接器在“库文件”提取到我们需要使用到的代码,复制到生成的可执行…

校验pytorch是否支持显卡GPU 不支持卸载并安装支持版本

1.输入如下命令 pythonimport torchtorch.__version__torch.cuda.is_available() // 输出False 就是不支持如下图 2.可以看到我电脑目前是不支持的 我们现在开始卸载 exit() //先退出pip uninstall torch //开始卸载这就卸载完成了 3.我们开始安装 nvidia-smi.exe //运行…

日常debug——苍穹外卖套餐修改时不回显数据

发现问题 今天在改套餐相关接口时,出现了一些问题。根据之前写的菜品和口味两个表的增删改查操作的时候,修改菜品数据时,前端页面会向后端发送请求,将菜品信息回显,口味数据也会出现。但是在写套餐相关的接口时&#…