I have a relatively big Texture, and I try to find a certain color pixels pattern: eg. White, Black, White, Green . They are lying next to each other,
If I use Texture2d.Getpixels() on every pixel every frame its possible, but way too slow.
Is there a "real good" way to do this? For example a shader way?
The "big idea" is to make a game which is "remote-playable". For example through Twitch or of a streamed youtube video. The user should not be connected to the server in any way, Instead he is sending messages or not.
For this I have to find a health bar. This health bar has the left-upper corner in black-> white -> black -> green pixels lying next to each other.
In the shader I CAN find these colors, but I dont really know the coordinates. Also I think there "should" be a solution with a ... compute shader? I dont really want to render new stuff. Just check pixel colors. I just want to know where these pixel colors are.
I imagined something like this:
If PixelColorIsWhite(x,y) { If PixelColorIsBlack(x+1,y) { If PixelColorIsWhite(x+2,y) { If PixelColorIsGreen(x+3,y) { return x+20,y+100 //because the player is 20 pixels right and 100 pixels below }}}}
In a shader i guess i can access the current coordinate, but I cant access the other pixels. Its paralell processing... right? So its impossible to access the "entire thing" in one go , right?
I think it must work somehow with... getting the big "chunk" of texture data, a very long array of pixels, giving it to a compute shader, and letting the CS find it.
I hope I could clarify the problem now :)
_-----------------------------------
Update:
I found out it (at least) should work with a compute shader.
I feel like im so close to the solution, yet im getting errors. :-(
So...
This is my C# Code:
public ComputeShader shader;
public Material thisMat;
public RenderTexture ScreenTex;
public int x;
public int y;
public const string INPUTTEX = "InputTexture";
private void Update()
{
RunShader();
}
public void RunShader()
{
RenderTexture tex = new RenderTexture(1024, 786, 24);
tex.enableRandomWrite = true;
tex.Create();
shader.SetTexture(0, INPUTTEX, ScreenTex);
shader.SetFloat("_ScreenWidth", Camera.main.pixelWidth);
shader.SetFloat("_ScreenHeight", Camera.main.pixelHeight);
int[] data = new int[2];
ComputeBuffer buffer = new ComputeBuffer(data.Length, sizeof(int)*2);
buffer.SetData(data);
shader.SetBuffer(0, "readWriteIntBuffer", buffer);
thisMat.mainTexture = tex;
int kernelHandle = shader.FindKernel("CSMain");
shader.SetTexture(kernelHandle, "Result", tex);
shader.Dispatch(kernelHandle, 1024 / 8, 786 / 8, 1);
buffer.GetData(data);
x = data[0];
y = data[1];
buffer.Release();}
And this is my ComputeShader Code:
-------------------
#pragma kernel CSMain
RWTexture2D<float4> Result;
RWStructuredBuffer<int> readWriteIntBuffer;
Texture2D<float4> InputTexture;
float _ScreenWidth;
float _ScreenHeight;
[numthreads(8, 8, 1)]
void CSMain(uint3 id : SV_DispatchThreadID)
{
if (id.x >= (uint)(_ScreenWidth*_ScreenHeight))
{
return;
}
int y = id.x / int(_ScreenWidth);
int x = id.x % int(_ScreenWidth);
readWriteIntBuffer[0] = 999; //some debug-testnumbers that show me that there were no colors found
readWriteIntBuffer[1] = 998;
if (InputTexture[float2(x,y)].r == 1.0f && InputTexture[float2(x, y)].g == 0.0f && InputTexture[float2(x, y)].b == 0.0f)
{
float2 coordinates = float2((float)id.x / (float)_ScreenWidth, (float)id.y / (float)_ScreenHeight);
readWriteIntBuffer[0] = coordinates.x;
readWriteIntBuffer[1] = coordinates.y;
}
}
This Computeshader checks if a single pixel in a texture is red and writs it in a buffer. The buffer gets read by C# with getdata. -- it seems we're almost getting there! But "something" seems to be wrong, since I dont seem to get the colors i want. But the compute shader seems to work, since i also get the triange-pattern in my material.