Unity 用C#变更Material中的Emission的Texture

本文介绍如何在Unity中使用脚本动态切换材质的Emission属性,通过示例代码展示如何在鼠标进入和离开时更换不同的纹理,实现材质发光效果的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用Unity的時候會希望可以變更一些比較不常用的材質屬性,這次講一下Emission這個屬性。

需要注意的是_EmissionMap這是指直接使用Shader的屬性名稱。


範例

public class EmissionColor : MonoBehaviour {


    public Texture MyTexture_A;
    public Texture MyTexture_B;
    private Renderer rend;


    private void OnMouseEnter()
    {

        rend = GetComponent<Renderer>();
        rend.material.SetTexture("_EmissionMap", MyTexture_A);
    }

    private void OnMouseExit()
    {
        rend = GetComponent<Renderer>();
        rend.material.SetTexture("_EmissionMap",MyTexture_B);
    }
}

 

<think>根据用户的问题,用户希望了解在Unity Shader中如何实现图像去色(灰度处理)。去色效果通常是将彩色图像转换为灰度图像,即只保留亮度信息,去除颜色信息。 在Unity中实现去色效果有多种方法,常见的有: 1. 平均值法:将RGB三个分量的平均值作为灰度值。 2. 加权平均值法:根据人眼对不同颜色的敏感度,使用不同的权重计算灰度值。通常使用公式:Gray = 0.299*R + 0.587*G + 0.114*B。 此外,还可以通过后处理方式实现全屏去色效果,或者对单个物体进行去色。 下面我将提供一个基于后处理的去色Shader示例,以及一个对单个物体进行去色的Shader示例。 ### 后处理去色Shader(全屏去色) 后处理去色可以通过创建一个渲染到屏幕的后处理效果来实现。以下是使用加权平均值法的后处理Shader: ```hlsl Shader "Hidden/GrayscaleEffect" { Properties { _MainTex ("Texture", 2D) = "white" {} _Intensity ("Intensity", Range(0, 1)) = 1.0 } SubShader { Cull Off ZWrite Off ZTest Always 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; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; float _Intensity; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); // 计算灰度值(加权平均) float gray = dot(col.rgb, float3(0.299, 0.587, 0.114)); // 混合原色和灰度 fixed4 finalColor = lerp(col, fixed4(gray, gray, gray, col.a), _Intensity); return finalColor; } ENDCG } } } ``` 然后,创建一个C#脚本用于应用后处理: ```csharp using UnityEngine; [ExecuteInEditMode] public class GrayscaleEffect : MonoBehaviour { [Range(0, 1)] public float intensity = 1.0f; private Material material; void OnRenderImage(RenderTexture source, RenderTexture destination) { if (material == null) { Shader shader = Shader.Find("Hidden/GrayscaleEffect"); if (shader == null) { Debug.LogError("Shader not found!"); Graphics.Blit(source, destination); return; } material = new Material(shader); } material.SetFloat("_Intensity", intensity); Graphics.Blit(source, destination, material); } } ``` ### 单个物体的去色Shader 如果只想对单个物体进行去色,可以使用以下Shader: ```hlsl Shader "Custom/Grayscale" { Properties { _MainTex ("Texture", 2D) = "white" {} _Intensity ("Intensity", Range(0, 1)) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 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; }; sampler2D _MainTex; float4 _MainTex_ST; float _Intensity; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); float gray = dot(col.rgb, float3(0.299, 0.587, 0.114)); fixed4 grayscale = fixed4(gray, gray, gray, col.a); return lerp(col, grayscale, _Intensity); } ENDCG } } } ``` 将这个Shader应用到材质上,然后赋予需要去色的物体。通过调整`_Intensity`属性,可以控制去色的程度。 ### 说明 - 加权平均公式:`float gray = dot(col.rgb, float3(0.299, 0.587, 0.114));` 是常用的灰度转换公式,因为它更符合人眼对颜色的感知。 - 如果希望完全去色,可以将`_Intensity`设置为1;如果希望部分去色,可以设置为0到1之间的值。 - 后处理方式会影响整个屏幕,而单个物体的Shader只影响应用了该Shader的物体。 以上方法都可以实现去色效果,具体使用哪种取决于需求。 §§相关问题§§ 1. 如何在Unity中实现部分去色效果(例如只对特定区域去色)? 2. 去色效果在游戏开发中有哪些应用场景? 3. 除了加权平均法,还有哪些图像灰度化算法?</think>### Unity Shader实现图像去色(灰度处理) 在Unity中实现图像去色(灰度处理)的核心是通过Shader对RGB颜色进行转换,保留亮度信息而丢弃色相信息。以下是两种常用实现方法: #### 方法1:后处理全屏去色(推荐) ```hlsl Shader "Hidden/GrayscalePostEffect" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Cull Off ZWrite Off ZTest Always 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; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); // 人眼感知的灰度转换公式 float gray = dot(col.rgb, float3(0.299, 0.587, 0.114)); return fixed4(gray, gray, gray, col.a); } ENDCG } } } ``` **实现步骤:** 1. 创建后处理脚本: ```csharp using UnityEngine; [ExecuteInEditMode] public class GrayscaleEffect : MonoBehaviour { [Range(0, 1)] public float intensity = 1.0f; private Material material; void OnRenderImage(RenderTexture src, RenderTexture dest) { if (material == null) { material = new Material(Shader.Find("Hidden/GrayscalePostEffect")); } material.SetFloat("_Intensity", intensity); Graphics.Blit(src, dest, material); } } ``` 2. 将脚本挂载到相机对象上 3. 通过`intensity`参数控制灰度强度(0=原色,1=完全灰度) #### 方法2:物体材质去色 ```hlsl Shader "Custom/ObjectGrayscale" { Properties { _MainTex ("Albedo (RGB)", 2D) = "white" {} _GrayscaleAmount ("Grayscale Amount", Range(0,1)) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma surface surf Standard struct Input { float2 uv_MainTex; }; sampler2D _MainTex; float _GrayscaleAmount; void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex); float gray = dot(c.rgb, float3(0.299, 0.587, 0.114)); o.Albedo = lerp(c.rgb, gray.xxx, _GrayscaleAmount); o.Alpha = c.a; } ENDCG } FallBack "Diffuse" } ``` **使用方法:** 1. 创建材质并指定此Shader 2. 调整`_GrayscaleAmount`参数控制灰度程度 3. 将材质赋予需要去色的物体 ### 技术要点说明 1. **灰度转换公式**: - 标准公式:$Gray = 0.299R + 0.587G + 0.114B$ - 该系数基于人眼对颜色的敏感度[^3] - 简单平均法:$Gray = (R + G + B)/3$(效果较差) 2. **性能优化**: - 使用`dot`函数进行向量点积计算,效率高于分量单独计算 - 后处理版本使用`ZTest Always`避免深度测试开销 3. **扩展应用**: - 结合[抖动处理(Dithering)](^2)可增强灰度层次感 - 配合[透明度测试(Opacity Mask)](^4)实现局部去色效果 - 在[自发光通道(Emission)](^4)应用灰度图可创建特殊发光效果 ### 效果对比 | 处理方式 | 优点 | 缺点 | |---------|------|------| | **后处理全屏去色** | 覆盖整个画面,无需修改材质 | 影响UI等不需要去色的元素 | | **物体材质去色** | 可精确控制特定物体 | 需为每个物体单独设置材质 | > 注:实际应用中,可通过遮罩纹理实现局部去色效果,例如使用第二张UV通道控制不同区域的灰度强度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值