I'm trying to write into a Computebuffer in the fragment shader, but it doesn't work. Its pretty hard to get the Depth-Value in the Compute Buffer, so it would be so easy to just use the Pixel/Fragment Shader instead the ComputeShader. But it doesn't seem to work.
Here is what this code is doing: First I'm creating a new Computebuffer and writing into a Computebuffer inside my C# code (a red screen)
After it's been written, I'm reading that buffer from a shader (works)
Next I'm using another shader to fill the buffer with some gradient. This should work - but it doesn't work.
When I'm reading the buffer again - I'm still seeing the red screen.
Does anyone here have an idea why? And how I can get to write things into the Computebuffer while I'm in the Fragment Shader?
My Code: (bufferscript.cs) (bind to Main Camera to test)
using UnityEngine;
using System.Collections;
using System.IO;
[ExecuteInEditMode]
public class bufferScript : MonoBehaviour
{
public bool writeBufferOn;
public bool readBufferOn;
public ComputeBuffer myBuffer;
public Material writeBufferMat;
public Material readBufferMat;
void Update()
{
if (readBufferMat == null)
{
readBufferMat = Resources.Load<Material>("readBufferMat") as Material;
}
if (readBufferMat.shader == null)
{
readBufferMat.shader = Resources.Load<Shader>("readBufferShader") as Shader;
}
if (writeBufferMat == null)
{
writeBufferMat = Resources.Load<Material>("writeBufferMat") as Material;
}
if (writeBufferMat.shader == null)
{
writeBufferMat.shader = Resources.Load<Shader>("writeBufferShader") as Shader;
}
if (myBuffer == null)
{
// initial fill buffer with red pixels
myBuffer = new ComputeBuffer(Camera.main.pixelWidth * Camera.main.pixelHeight, 3*sizeof(float), ComputeBufferType.Default);
float[] v = new float[Camera.main.pixelWidth * Camera.main.pixelHeight * 3];
for (int c = 0; c < Camera.main.pixelWidth * Camera.main.pixelHeight * 3; c+=3)
{
v[c+0] = 1.0f;
v[c+1] = 0.0f;
v[c+2] = 0.0f;
}
myBuffer.SetData(v);
}
}
void OnRenderImage(RenderTexture source, RenderTexture destination)
{
if (writeBufferOn == true)
{
Graphics.ClearRandomWriteTargets();
writeBufferMat.SetPass(0);
writeBufferMat.SetInt("_width", Camera.main.pixelWidth);
writeBufferMat.SetInt("_height", Camera.main.pixelHeight);
writeBufferMat.SetBuffer("_myBuffer", myBuffer);
Graphics.SetRandomWriteTarget(1, myBuffer);
Graphics.Blit(source, destination, writeBufferMat);
Graphics.ClearRandomWriteTargets();
// expecting red/blue to be 0 and green with gradient from 0 to 1 across screen width
float[] v = new float[Camera.main.pixelWidth * Camera.main.pixelHeight * 3];
myBuffer.GetData(v);
if (v[3 * 0 + 0] != 0.0f)
{
print("Still red, write to compute buffer failed!");
}
}
if (readBufferOn == true)
{
Graphics.ClearRandomWriteTargets();
readBufferMat.SetPass(0);
readBufferMat.SetInt("_width", Camera.main.pixelWidth);
readBufferMat.SetInt("_height", Camera.main.pixelHeight);
readBufferMat.SetBuffer("_myBuffer", myBuffer);
Graphics.Blit(source, destination, readBufferMat);
}
}
//garbage collector extra
void OnDisable()
{
if (myBuffer != null)
myBuffer.Dispose();
myBuffer = null;
}
}
My Shader (readBufferShader)
Shader "custom/readBufferShader"
{
SubShader
{
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 5.0
#pragma vertex vert
#pragma fragment frag
struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float4 scrPos : TEXCOORD1;
};
//Vertex Shader
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.scrPos = ComputeScreenPos(o.pos);
o.uv = float4(v.texcoord.xy, v.texcoord.z, 1);
return o;
}
//Fragment Shader
int _width;
int _height;
StructuredBuffer<float3> _myBuffer : register(u1);
half4 frag(v2f i) : COLOR
{
int x = int(i.scrPos.x * _width);
int y = int(i.scrPos.y * _height);
float3 value = _myBuffer[(y * _width) + x]; // reading the buffer works
return half4(value, 1);
}
ENDCG
}
}
}
My other Shader (writeBufferShader)
Shader "custom/writeBufferShader"
{
SubShader
{
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma target 5.0
#pragma vertex vert
#pragma fragment frag
struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float4 scrPos : TEXCOORD1;
};
//Vertex Shader
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.scrPos = ComputeScreenPos(o.pos);
o.uv = float4(v.texcoord.xy, v.texcoord.z, 1);
return o;
}
//Fragment Shader
int _width;
int _height;
RWStructuredBuffer<float3> _myBuffer : register(u1);
half4 frag(v2f i) : COLOR
{
int x = int(i.scrPos.x * _width);
int y = int(i.scrPos.y * _height);
_myBuffer[(y * _width) + x] = float3(0, i.scrPos.x, 0); // buffer should be written here, but nothing happens!
return half4(1,1,1,1);
}
ENDCG
}
}
}