[游戏开发]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日
    浏览(12)
  • Android 12.0默认开启无障碍服务权限和打开默认apk无障碍服务

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

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

    Android 无障碍服务自动点击

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

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

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

    auto.js autojs pro9 autox.js实现adb自动化测试脚本开发自动生成代码 防无障碍检测

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

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

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

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

    Facebook的可访问性使命:构建无障碍社交空间

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

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

    无障碍工具条在前端项目中的使用

    一、使用的工具 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日
    浏览(12)
  • 有 AI,无障碍,AIoT 设备为视障人群提供便利

    有 AI,无障碍,AIoT 设备为视障人群提供便利

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

    2024年02月08日
    浏览(18)
  • 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日
    浏览(13)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包