[游戏开发]Unity颜色矫正无障碍方案

news/2024/12/13 4:51:43/

[目录]

  • 0. 前言
  • 1. 颜色矫正
  • 2. 线性变换Shader
  • 2. 颜色纠正参数
  • 3. 摄像机后处理
  • 4. 效果
  • 5. 结束咯

0. 前言

之前有在关注色盲视觉纠正问题,最近在调整游戏的时候就打算把这个用上。

色弱色盲,这其实算是一种误称吧,只是人类中的少数派,只不过看到的颜色和大部分人不一样。下文用,视觉少数者,来称呼吧。

本质上是因为感知颜色的细胞发生突变,感知与大部分人有差异。之前就一直在想能不能有一些方法对颜色做一些调整作为纠正。比如说红色感知弱,显示的时候把红强度提高作为弥补。但目前来说好像还没有确切的方案来执行,甚至色盲色弱的标准以及测试都不清楚,何谈纠正呢。

主要是色觉其实是比较复杂的,人有3种感光细胞用于感知光线,然后感知之后再由大脑脑补一下出画面。这其中的过程并不能够简单映射得出结果,比如同种颜色在不通颜色的比较下会感知不同。而且三种感光细胞还有一定的感光范围,和RBG这种常用的颜色空间基准还有偏差。所以这部分是比较难处理的。另外如果从小看到的火就是蓝色的,那后面蓝色这个颜色的意义也会发生改变,这个也难以统一。

1. 颜色矫正

颜色矫正是为了让颜色更好区分,并不是开了之后就会让视觉少数者感知到其他人一样的颜色。处理还是有挺多种方法的。

  • 颜色映射,红色映射为某一种颜色,紫色映射为另一种等等,这种方法主要是映射空间难以确定,而且运行比较复杂,一般只有对图片做处理才会有这种方式。
  • 旋转H分量,在HSV空间缩放旋转H分量的方式,这样在色环上做的处理就可以让颜色均匀,只不过旋转角度难以确定、前后颜色差异比较大。
  • 线性变换,RGB颜色做一个线性变换,这样颜色可以做到均匀计算量也比较小。至于能否在线性空间内找到合适的方法,或者因人而异的指定参数这个还是比较难确定。

基本上目前软件上,基本都是用第三种做的矫正处理,目前window中就是用的这个,所以后续讲的也是如此,参数也是用window开纠正后的颜色,反向求解出来的,效果应该还可以。对于应用到游戏中、UnIty中,目前考虑的方法就是用写一个 颜色线性变换Shader,确定好不同的颜色纠正参数,然后在摄像机后处理的时候做统一的纠正处理。

2. 线性变换Shader

这里就简单的写一个RGB线性变换的shder,主要目的是让颜色与给定的矩阵做叉乘,如下。

Shader "MyShader/ColorTr" {Properties {[PerRendererData] _MainTex ("Texture", 2D) = "white" {}_UtR ("UtR",Vector)=(0.14,0.86,0,0)_UtG ("UtG",Vector)=(0.14,0.86,0,0)_UtB ("UtB",Vector)=(0,0,1,0)}SubShader {Pass {CGPROGRAM#include "UnityCG.cginc"#pragma vertex vert#pragma fragment fragsampler2D _MainTex;float4 _UtR;float4 _UtG;float4 _UtB;struct a2v {float4 vertex : POSITION;float3 normal : NORMAL;float4 texcoord : TEXCOORD0;//float3 color : COLOR0;};struct v2f {float4 pos : SV_POSITION;float3 texcoord : COLOR0;};v2f vert(a2v v) {v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.texcoord = v.texcoord;return o;}fixed4 frag(v2f i) : SV_Target {float4 color = tex2D(_MainTex, i.texcoord);color.r = mul(_UtR,color);color.g = mul(_UtG,color);color.b = mul(_UtB,color);return color;}ENDCG} }FallBack Off
}

好了,那么后面我们只需要修改_UtR 等3个矩阵点的值,就可以调整颜色线性变换的结果了。

2. 颜色纠正参数

我们先定义下颜色纠正类型,常规/红色/绿色/蓝色,

public enum ColorMappingType
{Normal,Red,Green,Blue,
}

具体的参数怎么去确定呢,参考window的颜色变换,我们只要获取到对应的颜色变换对,就可以通通过矩阵求逆的方式来得到和这个参数了,如下。color为原颜色,colorF为映射得到的函数

private double[,] GetTranslateU(double[,] color, double[,] colorF)
{double[,] colorAthwart = MatrixF.Athwart(color);return MatrixF.MultiplyMatrix(colorF, colorAthwart);
}
// 矩阵运算相关内容是参考的这里
// https://blog.csdn.net/Lynn_whu/article/details/80745634

如果不用矩阵运算也可以,假设原本的颜色为(R1,G1,B1),变换后的颜色为(R2, G2, B2),线性变换矩阵为((a,b,c),(d,e,f),(g,h,i)},那么这个线性变换其实就是如下的结果。3个方程式,只要找到颜色变换对,代入就可以求出这几个参数了。(不过估计还挺难算的。)

R2 = a * R1 + b * G1 + c * B1
G2 = d * R1 + e * G1 + f * B1
B2 = g * R1 + h * G1 + i * B1

那么求逆矩然后再求解之后,可得参数如下:

// 红色
new double[3,3]{{1,0,0}, {0.47,0.49,0.04}, {0.59,-0.68,1.09},
},
// 绿色
new double[3,3]{{1.22,-0.31,0.11}, {0,1,0}, {-0.18,0.17,1},
},
// 蓝色
new double[3,3]{{0.74,-0.39,0.66}, {0.08,0.59,0.33}, {0,0,1},
}

3. 摄像机后处理

场景等物体渲染后再做处理,用摄像机后处理来处理就很方便了。写个脚本控制一下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;namespace GDT
{[RequireComponent(typeof(Camera))]public class ColorMapping : MonoBehaviour{public Material materialMapping;private double[][,] MappingUt;private Material curMaterial;private void Awake(){MappingUt = new double[3][,]{// 红色new double[3,3]{{1,0,0}, {0.47,0.49,0.04}, {0.59,-0.68,1.09},},// 绿色new double[3,3]{{1.22,-0.31,0.11}, {0,1,0}, {-0.18,0.17,1},},// 蓝色new double[3,3]{{0.74,-0.39,0.66}, {0.08,0.59,0.33}, {0,0,1},}};}public void SetMaping(ColorMappingType type){switch (type){case ColorMappingType.Normal:curMaterial = null;break;case ColorMappingType.Red:ChangeShaderColorTraU(MappingUt[0]);curMaterial = materialMapping;break;case ColorMappingType.Green:ChangeShaderColorTraU(MappingUt[1]);curMaterial = materialMapping;break;case ColorMappingType.Blue:ChangeShaderColorTraU(MappingUt[2]);curMaterial = materialMapping;break;}}private void OnRenderImage(RenderTexture source, RenderTexture destination){//https://blog.csdn.net/qq_31042143/article/details/127186310if (curMaterial){Graphics.Blit(source, destination, curMaterial);}else{Graphics.Blit(source, destination);}// R2 = a * R1 + b * G1 + c * B1// G2 = d * R1 + e * G1 + f * B1// B2 = g * R1 + h * G1 + i * B1}private void ChangeShaderColorTraU(double[,] Ut){//Debug.LogError("Ut:" + Ut);materialMapping.SetVector("_UtR", new Vector4((float)Ut[0, 0], (float)Ut[0, 1], (float)Ut[0, 2], 0));materialMapping.SetVector("_UtG", new Vector4((float)Ut[1, 0], (float)Ut[1, 1], (float)Ut[1, 2], 0));materialMapping.SetVector("_UtB", new Vector4((float)Ut[2, 0], (float)Ut[2, 1], (float)Ut[2, 2], 0));}}
}
  • [RequireComponent(typeof(Camera))]
    因为需要进行相机后处理,所以要求了一下组件类型
  • SetMaping 设置颜色纠正方式
  • OnRenderImage 进行摄像机后处理
  • ChangeShaderColorTraU 设置shader参数

然后把脚本挂到摄像机对象上就完成了。

4. 效果

在这里插入图片描述
效果还是比较明显的,下面是参照颜色条,和window 上的变换一致。

实现还是挺简单的,只需要挂在显示的摄像机上就可以了,不会影响到其他shader的处理,场景和游戏对象都不用另外做处理。

5. 结束咯

到这里就结束了。线性变换的参数还是有很大操作空间的,不仅可以用于视觉少数者纠正颜色,也可以用于做一些视觉特殊效果,比如说画面变黄等滤镜效果。只要绑定到特殊的摄像头上,或者直接用于对应物体的材质上就可以了。

希望能够提供参考组作用。


http://www.ppmy.cn/news/418528.html

相关文章

c++捕获异常

catch 块跟在 try 块后面,用于捕获异常。您可以指定想要捕捉的异常类型,这是由 catch 关键字后的括号内的异常声明决定的。 try { // 保护代码 }catch( ExceptionName e ) { // 处理 ExceptionName 异常的代码 } 上面的代码会捕获一个类型为 Exc…

【太遗憾】这些杀毒软件你竟不了解?

卡巴斯基 这款杀毒软件是俄罗斯出品的,就目前国内免杀的情况来看,卡巴斯基是免杀最主要的针对对象(扫描未知病毒非常厉害),我们到网上搜索“免杀”,在返回的页面随处可见形如“某某木马免杀过卡巴”这样的教程。 从其在免杀教程中…

当免费之火燃向杀毒软件

当免费之火燃向杀毒软件 文/王易见 经常使用的互联网服务,究竟有多少是收费的? 在门户看新闻不需要付费,泡社区和论坛不需要付费,收发邮件不需要付费,用QQ、MSN等即时聊天工具不需要付费,用百度和谷歌等搜索…

瑞星杀毒软件、奇虎360杀毒软件、360卫士、百度卫士联手,搞不定弹出广告 恶意广告图标

一位网友说他的电脑最近出了问题:开机后桌面和任务栏上的快速启动栏会出现恶意图标,删除了下次开机又会出现;使用电脑过程中每分钟都会弹出广告。他为电脑安装了瑞星杀毒软件、奇虎360杀毒软件、360卫士、百度卫士,以及广告神盾&a…

这款知名开车软件,居然暗藏大量病毒

想必大家见多了网上有关 Windows 系统宝藏神级软件的种种推荐。 其中有这么一款软件一直占据推荐榜单前列,并且坐拥无数好评。 它就是在 Steam 上售价仅 19 元,表面看起来平平无奇的 Wallpaper Engine (壁纸引擎)。 别看它价格不…

Python 自动化测试五种自动化测试模型实战详解

目录 前言: 自动化测试模型都有哪些? 线性模型 模块化驱动模型 数据驱动模型 关键字驱动模型 行为驱动模型 扩展知识 前言: Python是一种流行的编程语言,广泛应用于自动化测试领域。自动化测试可以帮助测试人员更快、更准确地发…

亚毫秒GC暂停到底有多香?JDK17+ZGC初体验|得物技术

1 前言 垃圾回收器的暂停问题一直是Java工程师关注的重点,特别是对实时响应要求较高的服务来说,CMS和G1等主流垃圾回收器的数十毫秒乃至上百毫秒的暂停时间相当致命。此外,调优门槛也相对较高,需要对垃圾回收器的内部机制有一定的…

暴风电视刷机教程

暴风TV太烂了。 电视坏了, 检测费用就是250元,不包括维修费用。 耍机维修要自己动手。 暴风TV升级步骤 暴风固件下载 55R6固件烧写步骤 首先考虑复位。 转载于:https://www.cnblogs.com/shaohef/p/11410057.html