Unity Shader的Color Property存在的精度问题以及修改方案
目录
背景
有时候我们希望将某个color转化为一个texture。这个时候我们会使用Graphic.DrawMesh将颜色转化为RenderTexture。
但Unity Shader的Color属性精度非常低,传入0.005这样平平无奇的float数值,最后存储在texture里面的也可能由于精度问题变为0。
本篇文章将会对不同的精度设置进行测试,查看并对比返回的像素值。
正文
准备
下面给出渲染texture使用的 C#代码 以及 对应的Shader代码。
private static void RenderCore(RenderTexture targetTexture, Material material)
{
renderCamera.targetTexture = targetTexture;
Graphics.DrawMesh(blitQuad, Vector3.zero, Quaternion.identity, material, SF_PreviewWindow.Layer_INT, renderCamera);
renderCamera.Render();
renderCamera.targetTexture = null;
}
Shader "Hidden/Shader Forge/FillColor" {
Properties {
//[HDR] _Color ("Color", Color) = (1,1,1,1)
_Color ("Color", Color) = (1,1,1,1)
}
SubShader {
Tags {
"RenderType"="Opaque"
}
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#define UNITY_PASS_FORWARDBASE
#include "UnityCG.cginc"
#pragma target 3.0
uniform float4 _Color;
struct VertexInput {
float4 vertex : POSITION;
float2 texcoord0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv = v.texcoord0;
o.pos = UnityObjectToClipPos(v.vertex );
return o;
}
float4 frag(VertexOutput i) : COLOR {
return _Color;
}
ENDCG
}
}
}
接着我们可以使用下面的代码,将RenderTexture转化为Texture2D,并检验像素的值。
var texture = PreviewTexture.ToTexture2D();
var color = texture.GetPixel(0, 0);
Debug.Log($"RenderPreviewTexture Node={TypeName4UI} pixel={color}");
Texture2D.DestroyImmediate(texture);
准备工作完成后,我们将对不同的精度设置,测试GetPixel返回的像素的值。
精度测试
Color Property
首先就是上文代码对应的Color(ARGB32)精度,每个channel为8bit,传入0.005,返回的值是0。
[HDR] Color Property
接着,我们对Color Property添加 [HDR] 前缀。 传入0.005,返回的值为0.004。
Vector Property
我们将 Color Property 改成 Vector Property。 得出的结果和 [HDR] Color Property 相同。
[HDR] Color Property 并且设置相机 allowHDR,texture的format设置为RGBAFloat
RenderTexture rt = new RenderTexture(256, 256, 0 , RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear );
_renderCamera.allowHDR = true;
var texture = PreviewTexture.ToTexture2D(TextureFormat.RGBAFloat);
如果我们基于 [HDR] Color Property, 将用于渲染的camera设置为允许HDR,并将读取像素的Texture2D也设置为一个channel 有32bit的RGBAFloat格式。
基本上 传入什么值,返回的也是那个值。
参考
https://discussions.unity.com/t/get-high-precision-output-from-shader/679345

浙公网安备 33010602011771号