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

Unity3D 中纯 Shader 的双色纹理的平铺计算与实现

Unity3D 中纯 Shader 的双色纹理的平铺计算与实现

  • 1 创建自定义Shader
  • 2 创建材质
  • 3 创建控制脚本
  • 4 将材质和脚本应用到物体
  • 5 可视化配置

我们不使用纹理贴图,通过Shader程序化生成条纹来实现黑黄双色纹理的平铺,目的是确保在任何尺寸下都不会变形。

1 创建自定义Shader

在Unity编辑器的Project窗口中:

  • 在【Assets】下创建【Shader】目录
  • 右键点击【Shader】目录,选择 【Create > Shader > Standard Surface Shader】
    在这里插入图片描述
  • 命名为 “TwoColorStripes.shader”

打开新创建的Shader文件,替换为以下代码:

Shader "Custom/TwoColorStripes"
{Properties{_ColorA ("Color A", Color) = (0,0,0,1)    // 黑色_ColorB ("Color B", Color) = (1,0.92,0.016,1) // 黄色(RGB:255,235,4)_StripeWidth ("Stripe Width", Float) = 0.5   // 每条条纹的宽度(单位:米)_Direction ("Direction", Vector) = (1,0,0,0) // 默认沿X轴方向[Toggle] _WorldSpace ("World Space", Float) = 0 // 是否使用世界坐标}SubShader{Tags { "RenderType"="Opaque" }CGPROGRAM#pragma surface surf Standard fullforwardshadows#pragma target 3.0struct Input{float3 worldPos; // 世界坐标};fixed4 _ColorA;fixed4 _ColorB;float _StripeWidth;float4 _Direction;float _WorldSpace;void surf (Input IN, inout SurfaceOutputStandard o){// 计算条纹位置float position;if (_WorldSpace > 0.5){// 使用世界坐标position = dot(IN.worldPos, _Direction.xyz);}else{// 使用物体本地坐标position = dot(IN.worldPos - unity_ObjectToWorld._m03_m13_m23, _Direction.xyz);}// 计算条纹模式float stripe = frac(position / _StripeWidth);// 选择颜色o.Albedo = (stripe < 0.5) ? _ColorA.rgb : _ColorB.rgb;o.Metallic = 0;o.Smoothness = 0;o.Alpha = 1;}ENDCG}FallBack "Diffuse"
}

如果使用了 Universal Render Pipeline (URP) ,我们需要创建URP兼容的Shader:

Shader "Custom/URP_TwoColorStripes"
{Properties{_ColorA ("Color A", Color) = (0,0,0,1)_ColorB ("Color B", Color) = (1,0.92,0.016,1)_StripeWidth ("Stripe Width", Float) = 0.5_Direction ("Direction", Vector) = (1,0,0,0)[Toggle] _WorldSpace ("World Space", Float) = 0}SubShader{Tags { "RenderType" = "Opaque""RenderPipeline" = "UniversalPipeline""Queue" = "Geometry"}Pass{Name "ForwardLit"Tags { "LightMode" = "UniversalForward" }HLSLPROGRAM#pragma vertex vert#pragma fragment frag#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"struct Attributes{float4 positionOS   : POSITION;float3 normalOS     : NORMAL;};struct Varyings{float4 positionHCS  : SV_POSITION;float3 positionWS   : TEXCOORD0;float3 normalWS     : TEXCOORD1;};CBUFFER_START(UnityPerMaterial)half4 _ColorA;half4 _ColorB;float _StripeWidth;float4 _Direction;float _WorldSpace;CBUFFER_ENDVaryings vert(Attributes IN){Varyings OUT;// 顶点位置变换VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.positionOS.xyz);OUT.positionHCS = vertexInput.positionCS;OUT.positionWS = vertexInput.positionWS;// 法线变换VertexNormalInputs normalInput = GetVertexNormalInputs(IN.normalOS);OUT.normalWS = normalInput.normalWS;return OUT;}half4 frag(Varyings IN) : SV_Target{// 计算条纹位置float position;if (_WorldSpace > 0.5){// 使用世界坐标position = dot(IN.positionWS, _Direction.xyz);}else{// 使用物体本地坐标float3 objectPos = mul(unity_WorldToObject, float4(IN.positionWS, 1.0)).xyz;position = dot(objectPos, _Direction.xyz);}// 计算条纹模式float stripe = frac(position / _StripeWidth);// 选择颜色half4 baseColor = (stripe < 0.5) ? _ColorA : _ColorB;// 基本光照计算Light mainLight = GetMainLight();float3 normal = normalize(IN.normalWS);float NdotL = saturate(dot(normal, mainLight.direction));half3 diffuse = mainLight.color * NdotL;// 组合最终颜色half3 color = baseColor.rgb * (diffuse + SampleSH(normal));return half4(color, baseColor.a);}ENDHLSL}}FallBack "Universal Render Pipeline/Simple Lit"
}

2 创建材质

在Project窗口中:

  • 右键点击【Create > Material】
  • 命名为 “Mat_BlackYellowStripes”
  • 在 Material 的 Inspector,将Shader设置为 “Custom/TwoColorStripes”
    在这里插入图片描述
  • 按需调整材质属性:Color A为黑色 (0,0,0),Color B为黄色 (RGB: 255/255, 235/255, 4/255),Stripe Width为0.54
    在这里插入图片描述

3 创建控制脚本

  • 创建新的C#脚本 “StripeController.cs”:
    在这里插入图片描述
using UnityEngine;[RequireComponent(typeof(Renderer))]
public class StripeController : MonoBehaviour
{[Header("条纹设置")]public int stripeCount = 8; // 条纹总数(偶数)public Vector3 direction = Vector3.right; // 条纹方向[Header("调试选项")]public bool updateInRuntime = true;private Material stripeMaterial;private Vector3 lastScale;void Start(){InitializeMaterial();UpdateStripeProperties();}void Update(){if (updateInRuntime && transform.hasChanged){UpdateStripeProperties();transform.hasChanged = false;}}private void InitializeMaterial(){Renderer renderer = GetComponent<Renderer>();// 创建材质实例(确保每个物体独立)stripeMaterial = new Material(renderer.sharedMaterial);renderer.material = stripeMaterial;}public void UpdateStripeProperties(){if (stripeMaterial == null) return;// 获取物体边界尺寸Bounds bounds = GetComponent<Renderer>().bounds;Vector3 size = bounds.size;// 计算实际长度(沿条纹方向)float length = Vector3.Dot(size, direction);// 计算条纹宽度float stripeWidth = length / stripeCount;// 更新材质属性stripeMaterial.SetFloat("_StripeWidth", stripeWidth);stripeMaterial.SetVector("_Direction", direction);// 可选:自动确定使用世界坐标还是本地坐标bool useWorldSpace = (transform.parent != null);stripeMaterial.SetFloat("_WorldSpace", useWorldSpace ? 1 : 0);Debug.Log($"更新条纹: 长度={length:F2}m, 条纹数={stripeCount}, 宽度={stripeWidth:F2}m");}// 针对特定尺寸的快捷设置public void Apply432Setup(){// 设置条纹数量为8(4黑+4黄)stripeCount = 8;// 默认沿X轴(物体长度方向)direction = Vector3.right;UpdateStripeProperties();}[ContextMenu("手动更新条纹设置")]public void ManualUpdate(){UpdateStripeProperties();}
}

4 将材质和脚本应用到物体

  • 在Hierarchy中创建一个选择您的踢脚线物体
    在这里插入图片描述

  • 给物添加组件:
    将 “Mat_BlackYellowStripes” 材质拖到Renderer组件的Material槽
    在这里插入图片描述

  • 添加 “StripeController” 脚本组件
    在这里插入图片描述

  • 配置脚本参数:
    设置Stripe Count为8(4条黑+4条黄)
    设置Direction为物体长度方向(通常是X轴:1,0,0)

  • 点击运行测试:
    物体应显示等宽的黑黄交替条纹
    修改物体缩放时,条纹会自动调整
    在这里插入图片描述

5 可视化配置

  • 在Project中的【Assets】目录下创建【Editor】目录
  • 创建编辑器扩展脚本 “StripeControllerEditor.cs”:
    在这里插入图片描述
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;[CustomEditor(typeof(StripeController))]
public class StripeControllerEditor : Editor
{public override void OnInspectorGUI(){base.OnInspectorGUI();StripeController controller = (StripeController)target;GUILayout.Space(10);// 预览颜色EditorGUILayout.LabelField("颜色预览", EditorStyles.boldLabel);Material mat = controller.GetComponent<Renderer>().sharedMaterial;if (mat != null){Color colorA = mat.GetColor("_ColorA");Color colorB = mat.GetColor("_ColorB");EditorGUILayout.BeginHorizontal();EditorGUILayout.ColorField(colorA);EditorGUILayout.ColorField(colorB);EditorGUILayout.EndHorizontal();}// 操作按钮GUILayout.Space(10);if (GUILayout.Button("应用设置", GUILayout.Height(30))){controller.ManualUpdate();}// 针对4.32m物体的快捷按钮GUILayout.Space(5);if (GUILayout.Button("应用4.32m预设")){controller.Apply432Setup();}// 显示当前条纹信息GUILayout.Space(10);EditorGUILayout.LabelField("当前条纹设置", EditorStyles.boldLabel);if (mat != null){float stripeWidth = mat.GetFloat("_StripeWidth");Vector3 direction = mat.GetVector("_Direction");EditorGUILayout.LabelField($"条纹宽度: {stripeWidth:F2}m");EditorGUILayout.LabelField($"方向: ({direction.x:F1}, {direction.y:F1}, {direction.z:F1})");}}
}
#endif

在这里插入图片描述

http://www.dtcms.com/a/330116.html

相关文章:

  • 二次筛法Quadratic Sieve因子分解法----C语言实现
  • [git diff] 对比检查变更 | 提交前复审 | 版本回退
  • SQL 核心操作全解析:从基础查询到关联关系实战
  • Spring Boot项目通过Feign调用三方接口的详细教程
  • 在es中安装kibana
  • 雨量系列篇一:翻斗雨量传感器与压电雨量传感器的区别是什么
  • java法定退休年龄计算器
  • Thinkphp(GUI)漏洞利用工具,支持各版本TP漏洞检测,命令执行,Getshell
  • reactive和ref使用方法及场景
  • GitHub 热榜项目 - 日榜(2025-08-13)
  • 光伏电站运维巡检指南
  • 02 流程流转
  • H616基于官方外设开发----1
  • 每日五个pyecharts可视化图表-line:从入门到精通 (5)
  • C++ 四种类型转换
  • el-table合并相同名称的列
  • 朝花夕拾(三)---------中文分词利器jieba库的详解与实战应用(python)
  • 洛谷 小 Y 拼木棒 贪心
  • 函数对象(仿函数)适配器
  • 《量子雷达》第2章 从量子信息到量子雷达 预习2025.8.13
  • 工业视觉检测中的常见的四种打光方式
  • Java 导出word 实现表格内插入图表(柱状图、折线图、饼状图)--可编辑数据
  • java反射与泛型的简单知识和应用
  • 【KO】Android 网络相关面试题
  • 326. 3 的幂
  • 不用费心备份操作的实验记录本
  • VUE基础笔记
  • 【AI学习100天】Day07 加入AI社区,通往AGI之路
  • C# 反射和特性(获取Type对象)
  • 【C#】利用数组实现大数数据结构