下图显示了该面片占用的像素个数为147456
。
因为面片的大小为1,坐标为(0,0.5f,0)。相机为正交视角,OrthoSize为1. 面片完全显示且高度为 (768/2)^2 = 384^2 = 147456。
另外,可以推测,pixel shader渲染会在所有对象的vertex shader计算结束后开始。
即使面片被遮挡,但如果没做处理依然存在渲染的开销。【放置两个面片发现占用的像素个数数量加倍】。disable其中一个对象后,像素个数变回原值。
过程
使用了 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];
private int ctargetID = 1;
private ComputeBuffer countBuf;
private int[] cData = new int[1];
public int count;
void OnEnable()
{
Setup();
}
void OnDisable()
{
Graphics.ClearRandomWriteTargets(); //this prevent crash
if (fieldbuf != null)
{
fieldbuf.Release();
fieldbuf.Dispose();
fieldbuf = null;
}
if(countBuf != null)
{
countBuf.Release();
countBuf.Dispose();
countBuf = null;
}
}
void Setup()
{
if (fieldbuf == null)
{
fieldbuf = new ComputeBuffer(4, sizeof(float), ComputeBufferType.Default);
}
if(countBuf== null)
{
countBuf = new ComputeBuffer(1,sizeof(int), ComputeBufferType.Default);
}
}
void OnRenderObject()
{
Graphics.ClearRandomWriteTargets();
Setup();
mat.SetPass(0);
//名字和shader中的RWBuffer无关
mat.SetBuffer("Field1", fieldbuf);
mat.SetBuffer("Count2", countBuf);
Graphics.SetRandomWriteTarget(targetID, fieldbuf);
Graphics.SetRandomWriteTarget(ctargetID, countBuf);
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";
}
countBuf.GetData(cData);
text.text += cData[0] + "\n";
}
}
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"
RWStructuredBuffer<int> Count : register(u1); //match with C# script "targetID"
#endif
v2f vert(appdata v)
{
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
Field[0] = c.r;
Field[1] = c.g;
Field[2] = c.b;
#endif
InterlockedAdd(Count[0],1);
float4 col = tex2D(_MainTex, i.uv);
col.rgb *= c;
return col;
}
ENDCG
}
}
}
参考
https://github.com/cinight/MinimalCompute
https://forum.unity.com/threads/setting-buffer-data-from-inside-fragment-shader-to-be-read-from-c-script-urp.1229175/