首页 > 其他分享 >【Unity3D】调整屏幕亮度、饱和度、对比度

【Unity3D】调整屏幕亮度、饱和度、对比度

时间:2023-08-09 21:22:25浏览次数:41  
标签:Unity3D RenderTexture 亮度 后处理 饱和度 对比度 屏幕

1 屏幕后处理流程

​ 调整屏幕亮度、饱和度、对比度,需要使用到屏幕后处理技术。因此,本文将先介绍屏幕后处理流程,再介绍调整屏幕亮度、饱和度、对比度的实现。

​ 本文完整资源见→Unity3D调整屏幕亮度、饱和度、对比度

​ 屏幕后处理即:渲染完所有对象后,得到一张屏幕图像,对该屏幕图像进一步处理的过程称为屏幕后处理。屏幕后处理一般在 MonoBehaviour 生命周期 的 OnRenderImage 方法中进行,如下,src 是渲染完所有对象后的屏幕图像,dest 是经屏幕后处理得到的目标图像。如果用户想在不透明的 Pass 执行完毕后立即调用 OnRenderImage 方法,可以在 OnRenderImage 方法前面加上 [ImageEffectOpaque] 标签。

// [ImageEffectOpaque] // 在不透明的Pass执行完毕后立即调用OnRenderImage方法
void OnRenderImage(RenderTexture src, RenderTexture dest)

​ 在 OnRenderImage 方法里,通常使用 Graphics.Blit 方法完成对纹理的处理,如下是常用的 Bilt 方法,source 是源纹理,dest 是目标纹理,mat 是进行屏幕后处理的材质,用户可以在该材质绑定的 Shader 中实现屏幕后处理特效。注意,屏幕后处理的 Shader 中必须包含名为 "_MainTex" 的纹理属性,用户在调用 Graphics.Blit 方法时会自动将 source 赋值给 Shader 中的 _MainTex 属性。

public static void Blit(Texture source, RenderTexture dest)
public static void Blit(Texture source, RenderTexture dest, Material mat, [Internal.DefaultValue("-1")] int pass)
public static void Blit(Texture source, Material mat, [Internal.DefaultValue("-1")] int pass)

​ 另外,用户通过 CommandBuffer.DrawRenderer 和 Graphics.ExecuteCommandBuffer 也可以实现 Graphics.Blit 效果,详见案例:选中物体描边特效,主要流程如下:

CommandBuffer commandBuffer = new CommandBuffer();
RenderTexture tempTex = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);
commandBuffer.SetRenderTarget(tempTex);
commandBuffer.ClearRenderTarget(true, true, Color.clear); // 设置模板清屏颜色为(0,0,0,0)
commandBuffer.DrawRenderer(renderer, effectMaterial); // renderer是物体的Render组件, effectMaterial是特效材质
Graphics.ExecuteCommandBuffer(commandBuffer);
// use tempTex
RenderTexture.ReleaseTemporary(tempTex); // 使用完tempTex后, 需要释放掉

​ 在 Shader 中,用户也可以通过 GrabPass 抓取屏幕图像,详见案例:反射和折射

2 亮度、饱和度、对比度

1)亮度

​ 亮度表示颜色的明暗程度,亮度越高,颜色越亮,灰度值也越高。

2)饱和度

​ 饱和度指色彩的鲜艳程度,也称色彩的纯度。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。纯的颜色都是高度饱和的,如鲜红,鲜绿。混杂上白色,灰色或其他色调的颜色,是不饱和的颜色,如绛紫,粉红,黄褐等。完全不饱和的颜色根本没有色调,如黑白之间的各种灰色。

3)对比度

​ 对比度指一幅图像灰度反差的大小,即最大亮度与最小亮度之比。对比度越大,不同颜色之间的反差越大,黑白分明,对比度过大,图像会显得刺眼;对比度越小,不同颜色之间的反差越小,对比度过小,画面会显得灰蒙蒙。

3 代码实现

​ BrigSatuCont.cs

using UnityEngine;

[ExecuteInEditMode] // 编辑态可以查看脚本运行效果
[RequireComponent(typeof(Camera))] // 需要相机组件
public class BrigSatuCont : MonoBehaviour {
    [Range(0.1f, 3.0f)]
    public float brightness = 1.0f; // 亮度
    [Range(0.1f, 3.0f)]
    public float saturation = 1.0f; // 饱和度
    [Range(0.1f, 3.0f)]
    public float contrast = 1.0f; // 对比度
    private Material material; // 材质

    private void Start() {
        material = new Material(Shader.Find("MyShader/BrightnessSaturationContrast"));
        material.hideFlags = HideFlags.DontSave;
    }

    //[ImageEffectOpaque] // 在不透明的Pass执行完毕后立即调用OnRenderImage方法
    void OnRenderImage(RenderTexture src, RenderTexture dest) {
        if (material != null) {
            material.SetFloat("_Brightness", brightness); // 设置亮度
            material.SetFloat("_Saturation", saturation); // 设置饱和度
            material.SetFloat("_Contrast", contrast); // 设置对比度
            Graphics.Blit(src, dest, material);
        } else {
            Graphics.Blit(src, dest);
        }
    }
}

​ BrigSatuCont.Shader

Shader "MyShader/BrightnessSaturationContrast" { // 调整亮度、饱和度、对比度
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {} // 主纹理
        _Brightness ("Brightness", Float) = 1 // 亮度
        _Saturation("Saturation", Float) = 1 // 饱和度
        _Contrast("Contrast", Float) = 1 // 对比度
    }

    SubShader {
        Pass {
            // 深度测试始终通过, 关闭深度写入
            ZTest Always ZWrite Off
            
            CGPROGRAM 
            #pragma vertex vert_img // 使用内置的vert_img顶点着色器
            #pragma fragment frag 
            #include "UnityCG.cginc"

            sampler2D _MainTex; // 主纹理
            half _Brightness; // 亮度
            half _Saturation; // 饱和度
            half _Contrast; // 对比度
        
            fixed4 frag(v2f_img i) : SV_Target { // v2f_img为内置结构体, 里面只包含pos和uv
                fixed4 tex = tex2D(_MainTex, i.uv); // 纹理采样
                fixed3 finalColor = tex.rgb * _Brightness; // 应用亮度_Brightness
                fixed luminance = 0.2125 * tex.r + 0.7154 * tex.g + 0.0721 * tex.b; // 计算亮度
                fixed3 luminanceColor = fixed3(luminance, luminance, luminance); // 饱和度为0、亮度为luminance的颜色
                finalColor = lerp(luminanceColor, finalColor, _Saturation); // 应用饱和度_Saturation
                fixed3 avgColor = fixed3(0.5, 0.5, 0.5); // 饱和度为0、亮度为0.5的颜色
                finalColor = lerp(avgColor, finalColor, _Contrast); // 应用对比度_Contrast
                return fixed4(finalColor, tex.a);  
            }  

            ENDCG
        }
    }

    Fallback Off
}

​ 说明: vert_img 是 Unity 内置的顶点着色器,v2f_img 是 Unity 内置的结构体变量,vert_img 和 v2f_img 的实现见→Shader常量、变量、结构体、函数

运行效果:

​ 1)调整亮度

img

​ 2)调整饱和度

img

​ 3)调整对比度

img

​ 声明:本文转自【Unity3D】调整屏幕亮度、饱和度、对比度

标签:Unity3D,RenderTexture,亮度,后处理,饱和度,对比度,屏幕
From: https://www.cnblogs.com/zhyan8/p/17615595.html

相关文章

  • Unity3D___微信小游戏常用API总结
    获取用户信息游戏初始化WX.InitSDK((code)=>{//打印屏幕信息varsystemInfo=WX.GetSystemInfoSync();Debug.Log($"{systemInfo.screenWidth}:{systemInfo.screenHeight},{systemInfo.windowWidth}:{systemInfo.windowHeight},......
  • Unity3D_拯救死循环
    当我们无意间写了死循环,此时只能调出任务管理器重新打开Unity工程一个偶然的机会我得知了一个不用结束任务,就可以挽救死循环的方法,整理如下总体思路:首先,创建一个Cube,让它沿Y轴旋转,通过它是否旋转来判断程序是否进入了死循环;其次,创建一个bool类型的变量,默认值为false,通过按......
  • Unity3D 使用带刚体组件的预制体配合脚本自动生成一面墙时上层墙体被弹飞
    异常效果如下图所示:预制体是一个正方体(Cube),其参数设置如下图所示:控制墙面生成的C#脚本如下所示:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;publicclassWall:MonoBehaviour{publicTransformbrick;//Usethisf......
  • Unity3D 自定义类的数组初始化
    实现功能:1.自定义类,用于保存数据等2.初始化数组代码:publicclasstree_elem{//位置publicintx,y;//大小【相对于原始大小的比例】最后随机分配publicfloatsize;//树的类型,最后随机分配publictree_kindkind;publictree_ele......
  • Unity3D 播放运行时游戏对象往上飞了
    我的原因是不小心给主摄像机(MainCamera)添加了刚体(Rigidbody)组件,导致播放运行时摄像机受重力作用往下掉,造成游戏(Game)视图窗口内看见的游戏对象往上飞了!如下图所示: 把挂在摄像机的上刚体(Rigidbody)组件移除即可!~......
  • unity3d unitywebrequest
    Unity3D中的UnityWebRequest是用于发送HTTP请求和处理HTTP响应的类。它提供了一种方便的方式来从服务器获取数据,例如从Web服务器的数据库中检索数据,并通过HTTP请求将数据发送回Unity3D应用程序。使用UnityWebRequest类,您可以执行以下操作:创建请求:您可以使用UnityWebRequest类......
  • 在Unity3D中使用ScriptableObject进行序列化
    ScriptableObject类型经常用于存储一些unity3d本身不可以打包的一些object,比如字符串,一些类对象等。用这个类型的子类型,则可以用BuildPipeline打包成assetbundle包供后续使用,非常方便。这样除了playerpref和c#文件读取外,另外的一种存取一些数据对象的方法1.usingUnityEngine;......
  • unity3D制作并使用Assetbundles方法
    在网页中为了控制.unity文件的大小,加速载入速度,可以把系统用到的资源制作成Assestbundles,根据需要进行动态的加载和卸载。具体作法:1、使用脚本重新定义系统菜单,添加一个制作Assetbunles的菜单命令://C#Example//Buildsanassetbundlefromtheselected......
  • Unity3D_根据不同的屏幕缩放UI(在横屏上运行竖屏软件)
    一、首先我们创建一个1080*1920分辨率的场景 效果如下二、随便添加一张UI图片三、打包出来看效果(我们发现UI显示不全,这是因为UI的尺寸任然是1080*1920,而我们的电脑是1920*1080) 四、我们在Unity中做以下设置1.选中游戏物体Canvas2.点击组件CanvasScaler上的UISc......
  • Unity3D 游戏实战开发之英雄联盟
    本次游戏项目为类dota游戏中的经典之作《英雄联盟》,向经典致敬。通过本次课程,你会学到网游开发模式、C#服务器开发、协议定制、Unity5.0新特性开发、UGUI应用、同步方案、解决问题思路、各种扩展工具的开发………! 演示地址:www.runruncode.com/video-game/19444.html ......