inline float GammaToLinearSpaceExact (float value)
{
if (value <= 0.04045F)
return value / 12.92F;
else if (value < 1.0F)
return pow((value + 0.055F)/1.055F, 2.4F);
else
return pow(value, 2.2F);
}
inline half3 GammaToLinearSpace (half3 sRGB)
{
// Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);
// Precise version, useful for debugging.
//return half3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
}
inline float LinearToGammaSpaceExact (float value)
{
if (value <= 0.0F)
return 0.0F;
else if (value <= 0.0031308F)
return 12.92F * value;
else if (value < 1.0F)
return 1.055F * pow(value, 0.4166667F) - 0.055F;
else
return pow(value, 0.45454545F);
}
inline half3 LinearToGammaSpace (half3 linRGB)
{
linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
// An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h);
// Exact version, useful for debugging.
//return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b))
}
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "UI/Default"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
_StencilComp ("Stencil Comparison", Float) = 8
_Stencil ("Stencil ID", Float) = 0
_StencilOp ("Stencil Operation", Float) = 0
_StencilWriteMask ("Stencil Write Mask", Float) = 255
_StencilReadMask ("Stencil Read Mask", Float) = 255
_ColorMask ("Color Mask", Float) = 15
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
};
fixed4 _Color;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = UnityObjectToClipPos(IN.vertex);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
#endif
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
half4 color = tex2D(_MainTex, IN.texcoord) * IN.color;
clip (color.a - 0.01);
//color.a = pow(color.a + 0.055, 2.4) / 1.13711896582;
color.a = pow(color.a, 2.2);
return color;
}
ENDCG
}
}
}
这个脚本挂到主相机上,其上添加UI相机和材质球(shader在下面)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class GammaSpaceUI : MonoBehaviour
{
public Camera UICamera;
public Material UICompositeMaterial;
private int uitex_id = Shader.PropertyToID("_UITex");
void Awake()
{
UICamera.enabled = false;
}
void OnRenderImage(RenderTexture src, RenderTexture dst)
{
RenderTexture UIRenderTexture = RenderTexture.GetTemporary(src.width, src.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
UICamera.targetTexture = UIRenderTexture;
UICamera.Render();
UICamera.targetTexture = null;
UICompositeMaterial.SetTexture(uitex_id, UIRenderTexture);
// GL.sRGBWrite used to avoid an additional conversion in the shader. Probably won't work on mobile.
#if !UNITY_ANDROID && !UNITY_IOS
GL.sRGBWrite = false;
#endif
Graphics.Blit(src, dst, UICompositeMaterial, 0);
#if !UNITY_ANDROID && !UNITY_IOS
GL.sRGBWrite = true;
#endif
RenderTexture.ReleaseTemporary(UIRenderTexture);
}
}
Shader "Hidden/GammaSpaceUI"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_UITex ("Texture", 2D) = "black" {}
}
SubShader
{
Cull Off ZWrite Off ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#if defined(SHADER_API_METAL) || defined(SHADER_API_GLES3)
#define MOBILE_USE_POST_CORRECTION 1
#endif
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
sampler2D _MainTex, _UITex;
half3 LinearToGammaSpace3(half3 col)
{
col.r = LinearToGammaSpaceExact(col.r);
col.g = LinearToGammaSpaceExact(col.g);
col.b = LinearToGammaSpaceExact(col.b);
return col;
}
half3 GammaToLinearSpace3(half3 col)
{
col.r = GammaToLinearSpaceExact(col.r);
col.g = GammaToLinearSpaceExact(col.g);
col.b = GammaToLinearSpaceExact(col.b);
return col;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
col.rgb = LinearToGammaSpace3(col.rgb);
fixed4 ui = tex2D(_UITex, i.uv);
col.rgb = col.rgb * (1.0 - ui.a) + ui.rgb;
// need conversion back to linear space if GL.sRGBWrite doesn't work on your platform (mobile)
#if defined(MOBILE_USE_POST_CORRECTION)
col.rgb = GammaToLinearSpace3(col.rgb);
#endif
return col;
}
ENDCG
}
}
}