开发过程中遇到同一个mesh,同一个shader,但是出现渲染结果不一致的情况。
初步猜测是光栅化后,像素中心对应物体的位置不同,uv通过插值生成,从而导致渲染结果不一致。
下文验证了uv会随着物体的位置不同,而发生改变。
验证
使用了 https://github.com/cinight/MinimalCompute 项目中的 05_1_UAVInShader 例子。
using UnityEngine;
using System.Collections;
using UnityEngine.Rendering;
public class UAVInShader : MonoBehaviour
{
public Material mat;
public TextMesh text;
private int targetID = 6; //match with shader "register(u6)"
private ComputeBuffer fieldbuf;
private float[] fdata = new float[3] { 1f, 1f, 1f };
public int count;
public bool ResetValue;
void OnEnable()
{
Setup();
}
void OnDisable()
{
fieldbuf.SetData(new float[] { 1f, 1f, 1f });
Graphics.ClearRandomWriteTargets(); //this prevent crash
if (fieldbuf != null)
{
fieldbuf.Release();
fieldbuf.Dispose();
fieldbuf = null;
}
}
void Setup()
{
if (fieldbuf == null)
{
fieldbuf = new ComputeBuffer(4, sizeof(float), ComputeBufferType.Default);
}
}
void OnRenderObject()
{
Graphics.ClearRandomWriteTargets();
Setup();
mat.SetPass(0);
//名字和shader中的RWBuffer无关
mat.SetBuffer("Field1", fieldbuf);
Graphics.SetRandomWriteTarget(targetID, fieldbuf);
fieldbuf.GetData(fdata);
text.text = "From shader, the RGB value of rainbow color \n";
for (int i = 0; i < fdata.Length; i++)
{
text.text += i + ": " + fdata[i] + "\n";
}
if(ResetValue)
{
fieldbuf.SetData(new float[] { 1f,1f,1f});
}
}
}
Shader "UAVTest/VertFrag"
{
Properties
{
_MainTex("_MainTex (RGBA)", 2D) = "white" {}
_Speed("_Speed",Range(0,0.5)) = 0.5
}
SubShader
{
Tags{ "RenderType" = "Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 5.0
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Speed;
#ifdef UNITY_COMPILER_HLSL
RWStructuredBuffer<float> Field : register(u6); //match with C# script "targetID"
#endif
v2f vert(appdata v)
{
//Field[0] = 1;
//Field[1] = 1;
//Field[2] = 1;
Count[0] = 0;
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//Rainbow color
float3 c;
c.r = frac(sin(_Time.x*_Speed));
c.g = frac(sin(_Time.z*_Speed));
c.b = frac(sin(_Time.w*_Speed));
#ifdef UNITY_COMPILER_HLSL
// 最终结果会是正确的
if(i.uv.x < Field[1])
{
Field[0] = i.vertex.x;
Field[1] = i.uv.x;
Field[2] = i.uv.y;
}
#endif
float4 col = tex2D(_MainTex, i.uv);
col.rgb *= c;
return col;
}
ENDCG
}
}
}
shader中的比较并赋值,虽然会有竞争的问题,但通过每帧的计算,缓冲池中存储的最小的uv会达到最终的正确性。
显示结果
1 存储了最小u的值 2存储了u对应v的值
可以看到拖动物体,该物体显示最小u的像素中的u的值随之发生变化。