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

这篇具有很好参考价值的文章主要介绍了[游戏开发]Unity颜色矫正无障碍方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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 frag

            sampler2D _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/127186310
            if (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. 效果

[游戏开发]Unity颜色矫正无障碍方案,游戏开发,unity,c#,游戏
效果还是比较明显的,下面是参照颜色条,和window 上的变换一致。

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

5. 结束咯

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

希望能够提供参考组作用。文章来源地址https://www.toymoban.com/news/detail-605478.html

到了这里,关于[游戏开发]Unity颜色矫正无障碍方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 应用自动开启辅助(无障碍)功能并使用辅助(无障碍)功能

    目录 一.背景 二.前提条件 三.将普通应用转换成系统应用 1.在AndroidManifest文件中添加

    2024年02月09日
    浏览(43)
  • Android 12.0默认开启无障碍服务权限和打开默认apk无障碍服务

    在12.0的系统rom定制化开发中,在第三方app开发中,需要开启无障碍服务功能,就不需要在代码中开启无障碍服务了, 为了简便就需要在系统中开启无障碍服务,来实现开启无障碍服务功能

    2024年02月07日
    浏览(54)
  • Android 无障碍服务自动点击

    业余时间了解了Android无障碍服务的一些有趣功能,比如微信自动抢红包、应用宝的一键安装功能等。大致原理是监听手机窗体内容变化,拿到对应的View,进行点击、长按等Touch操作,下面我们就借助 AccessibilityService 这个服务类实现模拟点击功能。  1、继承AccessibilityService,

    2024年02月05日
    浏览(38)
  • unidbg-补环境之无障碍模式

    2024年02月16日
    浏览(41)
  • auto.js autojs pro9 autox.js实现adb自动化测试脚本开发自动生成代码 防无障碍检测

    不需要开无障碍就可以实现自动化 ,功能上和无障碍效果一样, 但是可以过目标app的检测,因为软件基本上都不检测adb(usb调试), 游戏脚本的福音 ,最主要是可以 直接生成自动化代码 ,所以写adb的自动化脚本 和无障碍的自动化脚本都同样简单高效,傻瓜式操作。 对于

    2024年01月19日
    浏览(56)
  • 手机APP-小米手机无障碍功能开启失败

    在设置中关闭以下三个设置: 不要设置为全面屏模式,不过可以在打开无障碍功能后再换回来。     ————————————————————— 以上就是今日博客的全部内容了 创作不易,若对您有帮助,可否点赞、关注一二呢, 感谢支持

    2024年02月08日
    浏览(78)
  • 无障碍工具条在前端项目中的使用

    一、使用的工具 https://gitee.com/tywAmblyopia/ToolsUI 二、使用 VUE中使用 -1.拉取代码 -2.将 canyou 文件夹放到 public 目录下 -3.在 public 文件夹下的 index.html 文件中 /head标签前,引用v1.8以上的jquery.min.js(原网站已引用v1.8以上的jquery跳过此步骤)。 -4.在 public 文件夹下的 index.html 文件中 /he

    2024年02月14日
    浏览(49)
  • Facebook的可访问性使命:构建无障碍社交空间

    在当今数字时代,社交媒体不仅是人们交流、分享和连接的平台,更是构建开放、包容社交环境的关键。Facebook,作为全球最大的社交媒体平台之一,积极推动着可访问性使命,致力于构建一个无障碍的社交空间,使每个用户都能平等参与其中。本文将深入探讨Facebook在可访问

    2024年01月23日
    浏览(52)
  • flutter flutter_accessibility_service无障碍服务

    flutter_accessibility_service a plugin for interacting with Accessibility Service in Android. Accessibility services are intended to assist users with disabilities in using Android devices and apps, or I can say to get android os events like keyboard key press events or notification received events etc. for more info check Accessibility Service Installation

    2024年02月10日
    浏览(47)
  • 有 AI,无障碍,AIoT 设备为视障人群提供便利

    据世界卫生组织统计,全球共 22 亿人视力受损,包含 2.85 亿视障人群和 3,900 万全盲人群。而且,这一数字将随老龄化加剧不断增加。 虽然视障人群面临着诸多不便,但是针对视障人群的辅助设备却存在成本高、维护困难、操作复杂等问题,很难满足他们的生活需求。 为此,

    2024年02月08日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包