Unity Shader:白平衡
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shader:白平衡相关的知识,希望对你有一定的参考价值。
参考技术A 白平衡(white balance),字面意义上是白色的平衡,由于显示器的三元色红绿蓝混合后是白色,因此白平衡是描述其白色精确度的一个指标,通过它可以解决色彩还原和色调处理的一系列问题。使用数码摄像机拍照时可能会出现一些问题,如日光灯的房间里拍摄的影像会显得发绿,在室内钨丝灯光下拍摄的影像会偏黄,日光灯阴影处拍摄到的照片则偏蓝,这些都是因为白平衡设置不当。
白平衡修正图像的方法是将白色物体还原为白色,对于偏色情况,加强对应的补色来补偿。
了解白平衡的话还需要了解色温。色温是用开尔文温度来表示色彩。假设一个黑体物质,能够将落在其上的所有热量吸收,没有损失,同时将热量生成的能量以光的形式释放出来,便会因受到热力的高低而变成不同的颜色。如黑体受到的热力相当于500-550℃,就会变成暗红色,达到1050-1150℃时,就会变成黄色,温度继续升高就会变成蓝色。任何光线的色温相当于黑体散发出同样颜色时所受到的温度。色温越高,光色越偏蓝,色温越低则偏红。某一种色光比其它的色光的色温高,说明该色光比其它色光偏蓝,反之偏红。同样,当一种色光比其它色光偏蓝时说明该色光的色温偏高。
由于人眼拥有适应性,所以有时不能发现色温变化,不过在光源改变时会感觉到一会儿,之后就会适应。白平衡就是针对不同的色温条件,抵消偏色,使其更接近人眼的视觉习惯,使白色物体仍是白色。
在Unity中,我们可以看一下shader graph 内置的白平衡节点的实现:
函数通过一个色温和偏移值来改变颜色,并输出颜色。
函数第一二行,将色温和偏移映射到[-1.67,1.67],据说这样效果最好。
之后的三行,使获取CIE测量的白平衡点的色度(颜色的色调和饱和度)坐标,何为白点?维基百科上的解释如下:
其中色度坐标的计算由CIE色度图标完成。
之后一行计算LMS空间的系数。LMS是由人眼的三种锥体的响应表示的颜色空间,以其在长波长,中波长和短波长处的响应度(灵敏度)峰命名。在执行色适应时估计样本在不同光源下的外观时,通常使用LMS色彩空间。
之后的7行是将CIE的xy坐标转换到LMS空间。
之后使用计算的因数来计算白平衡系数。
之后的两个矩阵是在线性颜色空间和LMS颜色空间之间的转换。
最后将线性空间颜色转换为LMS空间,然后乘以白平衡系数,之后转换回线性空间然后输出颜色。
Unity攻击敌人时产生泛白效果
Shader的代码如下,主要是将透明度为1的像素点输出为白色,其中_BeAttack表示角色被攻击的泛白状态
// Upgrade NOTE: replaced ‘mul(UNITY_MATRIX_MVP,*)‘ with ‘UnityObjectToClipPos(*)‘
Shader "Custom/BeAttackTest" {
Properties{
_MainTex("texture", 2D) = "black"{}
_Color("add color", Color) = (1,1,1,1)
//_BeAttack("BeAttack",Int)=0
}
SubShader{
Tags{ "QUEUE" = "Transparent" "IGNOREPROJECTOR" = "true" "RenderType" = "Transparent" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
LOD 100
Cull Off//设置双面渲染,避免角色缩放翻转时无渲染情况
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 _MainTex_ST;
fixed4 _Color;
int _BeAttack;//对外参数表示是否被攻击了
struct vIn {
half4 vertex:POSITION;
float2 texcoord:TEXCOORD0;
fixed4 color : COLOR;
};
struct vOut {
half4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
fixed4 color : COLOR;
};
vOut vert(vIn v) {
vOut o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.color = v.color;
return o;
}
fixed4 frag(vOut i) :COLOR{
fixed4 tex = tex2D(_MainTex, i.uv).rgba;
/*
if (tex.a == 1)return fixed4(1, 1, 1, 1);
else return fixed4(0, 0, 0, 0);
*/
if (_BeAttack==1) {//是否被攻击
if (tex.a == 1)return fixed4(1, 1, 1, 1);//对透明度为1的像素输出为白色
else return fixed4(0, 0, 0, 0);
}
else {
return tex;
}
}
ENDCG
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
角色被攻击的代码如下,通过设置时间参数控制泛白的持续时间:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy01Die : MonoBehaviour,IDie {
SpriteRenderer spriteRenderer;
public float whiteCoolTime;//泛白效果的持续时间长度
float whiteCoolTimer;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
}
void Update()
{
//被攻击状态冷却,设置被攻击参数为0
if (whiteCoolTimer <= 0)
spriteRenderer.material.SetInt("_BeAttack", 0);
else
whiteCoolTimer -= Time.deltaTime;
}
public void Die()
{
Destroy(gameObject);
}
public void BeAttack()
{
//被攻击的时候设置shader的被攻击参数为1
spriteRenderer.material.SetInt("_BeAttack", 1);
whiteCoolTimer = whiteCoolTime;
}
}
public interface IDie
{
void Die();
void BeAttack();
}
以上是关于Unity Shader:白平衡的主要内容,如果未能解决你的问题,请参考以下文章