Can someone who has experience with compute shaders explain what is an id parameter?
void CSMain (uint3 id : SV_DispatchThreadID)
I believe it's an index, but an index of what? How do you manipulate certain texture pixels in compute shader? How do you access them?
Let's say I have an 8x8 image and whenever I click on the texture I want to colorize the clicked on pixel and its surrounding pixels depending on the radius.
I have created this simple EditorWindow, where I listen for clicks and if I click I Dispatch the compute shader to process all the data
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
public class DrawingEditor : EditorWindow
{
bool pressed = false;
ComputeShader computeShader = null;
RenderTexture dest;
bool dragged = false;
int radius = 5;
Color color = Color.black;
[MenuItem("Window/Drawing Editor")]
public static void Open()
{
var window = EditorWindow.GetWindow<DrawingEditor>();
window.ShowUtility();
}
private void OnEnable()
{
dest = new RenderTexture(1200, 514, 0, RenderTextureFormat.ARGB32, 0);
dest.enableRandomWrite = true; dest.Create();
}
private void OnGUI()
{
var tex = new Rect(0, 0, 350, 150);
GUI.DrawTexture(tex, dest);
var shader = new Rect(25, tex.y + tex.height + 25, tex.width - 50, 17);
computeShader = (ComputeShader)EditorGUI.ObjectField(shader, new GUIContent("Shader"), computeShader, typeof(ComputeShader), allowSceneObjects: false);
var rad = new Rect(25, shader.y + shader.height + 25, tex.width - 50, 17);
radius = EditorGUI.IntSlider(rad, radius, 1, 50);
var col = new Rect(25, rad.y + rad.height + 25, tex.width - 50, 17);
color = EditorGUI.ColorField(col, color);
var e = Event.current; bool paint = false;
if (e.rawType == EventType.MouseDown)
{
pressed = true;
}
else if (e.rawType == EventType.MouseUp && pressed)
{
if (!dragged)
{
paint = true;
}
pressed = false; dragged = false;
}
if (e.rawType == EventType.MouseDrag && pressed)
{
paint = true;
dragged = true;
}
if (paint)
{
Paint(new Vector2Int(Convert.ToInt32(e.mousePosition.x), Convert.ToInt32(e.mousePosition.y)), tex);
}
}
void Paint(Vector2Int mousePos, Rect canvas)
{
var p = mousePos;
var xP = p.x / canvas.width;
var yP = p.y / canvas.height;
if (computeShader)
{
computeShader.SetTexture(0, "Result", dest);
computeShader.SetFloat("mouseX", dest.width * xP); computeShader.SetFloat("mouseY", dest.height * yP);
computeShader.SetInt("radius", radius);
computeShader.SetVector("color", color);
computeShader.SetInt("width", dest.width); computeShader.SetInt("height", dest.height);
computeShader.Dispatch(0, dest.width / 8, dest.height / 8, 1);
Repaint();
}
}
}
And this is the compute shader:
#pragma kernel CSMain
RWTexture2D<float4> Result;
float mouseX, mouseY;
int radius;
float4 color;
int width, height;
float4 Calc(uint x, uint y, float4 de)
{
if (x >= mouseX - ((float)radius / 2) && x < mouseX + radius)
{
if (y >= mouseY - ((float)radius / 2) && y < mouseY + radius)
{
return color;
}
}
return de;
}
[numthreads(8,8,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
Result[id.xy] = Calc(id.x, id.y, Result[id.xy]);
}
Nothing is happening when I dispatch the compute shader, so I reckon I am doing something really wrong here.
How do you alter specific pixels? Can someone help me understand how things work with compute shaders?