Quantcast
Channel: Questions in topic: "compute shader"
Viewing all articles
Browse latest Browse all 287

How should i draw a bezier curve in a compute shader? (Already works in c#)

$
0
0
Okay, so i've made this mess of c# code; it loops through all the pixels in the texture and and calculates the distance from points along the bezier curve (defined by vx and vy). This works fine in c#, but i'd like to convert it to shader-code for some added performance. However I am (clearly) not that great with computeshaders, and i cant wrap my head around what i'm missing... EDIT: the values i used for the vectors were; 1=(0,0) 2=(0.5,1) 3=(1,0), and the precision is 100. ---------- Here is the c# code and the output it can produce, bear with me, I'm not too good at producing readable code; using UnityEngine; public class DrawOnTex : MonoBehaviour { public int width = 256; public int height = 256; Vector2 vec1; Vector2 vec2; Vector2 vec3; public Transform t1; public Transform t2; public Transform t3; public int perlinSize = 10; public int precision = 10; Renderer r; #region valueCheckers int oldW; int oldH; Vector2 oldV1; Vector2 oldV2; Vector2 oldV3; int oldPr; bool ValuesChanged() { bool dimensionsMatch = (width == oldW && height == oldH); bool vectorsMatch = (vec1 == oldV1 && vec2 == oldV2 && vec3 == oldV3); bool othersMatch = (precision == oldPr); //Debug.Log(dimensionsMatch +" "+ vectorsMatch + " " + othersMatch); return !(dimensionsMatch && vectorsMatch && othersMatch); } #endregion private void Start() { r = GetComponent(); } private void Update() { PlaceVectors(); if (ValuesChanged()) { r.material.mainTexture = GenerateTex(); //Debug.Log("generated"); } oldW = width; oldH = height; oldV1 = vec1; oldV2 = vec2; oldV3 = vec3; oldPr = precision; } void PlaceVectors() { vec1 = t1.position; vec2 = t2.position; vec3 = t3.position; } RenderTexture GenerateTexCompute() { RunShader(); return rTex; } Texture2D GenerateTex() { Texture2D tex = new Texture2D(width, height); Color[] values = new Color[width * height]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Color col = BezierCalc(vec1, vec2, vec3, x, y); values[y * height + x] = col; } } tex.SetPixels(values); tex.Apply(); tex.filterMode = FilterMode.Point; return tex; } Color BezierCalc(Vector2 a, Vector2 b, Vector2 c, int x, int y) { float xCoord = (float)x / width; float yCoord = (float)y / height; float v = 10000; for (int i = 0; i < precision; i++) { float t = (float)i / precision; float vx = a.x - 2 * t * a.x + (t * t) * a.x + 2 * t * b.x - 2 * (t * t) * b.x + (t * t) * c.x; float vy = a.y - 2 * t * a.y + (t * t) * a.y + 2 * t * b.y - 2 * (t * t) * b.y + (t * t) * c.y; Vector2 bz = new Vector2(vx, vy); Vector2 xy = new Vector2(xCoord, yCoord); float l = (bz - xy).magnitude; v = Mathf.Min(v, l); } return new Color(v, v, v, 1); } } ![alt text][1] ---------- And here is the compute shader code and its output; using UnityEngine; public class DrawOnTex : MonoBehaviour { public int width = 256; public int height = 256; Vector2 vec1; Vector2 vec2; Vector2 vec3; public Transform t1; public Transform t2; public Transform t3; public int perlinSize = 10; public int precision = 10; Renderer r; RenderTexture rTex; #region ComputeshaderTest public ComputeShader shader; void RunShader() { int kernel = shader.FindKernel("CSMain"); shader.SetTexture(kernel, Shader.PropertyToID("Result"), rTex); shader.SetFloat("width", width); shader.SetFloat("height", height); shader.SetVector("a", vec1); shader.SetVector("b", vec2); shader.SetVector("c", vec3); shader.SetInt("p", precision); shader.Dispatch(kernel, width, height, 1); } #endregion #region valueCheckers int oldW; int oldH; Vector2 oldV1; Vector2 oldV2; Vector2 oldV3; int oldPr; bool ValuesChanged() { bool dimensionsMatch = (width == oldW && height == oldH); bool vectorsMatch = (vec1 == oldV1 && vec2 == oldV2 && vec3 == oldV3); bool othersMatch = (precision == oldPr); //Debug.Log(dimensionsMatch +" "+ vectorsMatch + " " + othersMatch); return !(dimensionsMatch && vectorsMatch && othersMatch); } #endregion private void Start() { r = GetComponent(); rTex = new RenderTexture(width, height, 0); rTex.enableRandomWrite = true; rTex.Create(); } private void Update() { PlaceVectors(); if (ValuesChanged()) { r.material.mainTexture = GenerateTexCompute(); Debug.Log("generated"); } oldW = width; oldH = height; oldV1 = vec1; oldV2 = vec2; oldV3 = vec3; oldPr = precision; } void PlaceVectors() { vec1 = t1.position; vec2 = t2.position; vec3 = t3.position; } RenderTexture GenerateTexCompute() { RunShader(); return rTex; } } And the shader code itself; #pragma kernel CSMain RWTexture2D Result; float width; float height; float2 a; float2 b; float2 c; int p = 10; [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID) { float xCoord = id.x / width; float yCoord = id.y / height; float v = 10000; for (int i = 0; i < p; i++) { float t = i / (uint)p; float vx = a.x - 2 * t * a.x + (t * t) * a.x + 2 * t * b.x - 2 * (t * t) * b.x + (t * t) * c.x; float vy = a.y - 2 * t * a.y + (t * t) * a.y + 2 * t * b.y - 2 * (t * t) * b.y + (t * t) * c.y; float2 bz = float2(vx, vy); float2 xy = float2(xCoord, yCoord); float l = length((bz-xy)); v = min(v, l); } Result[id.xy] = float4(v,v,v,1); } Btw, the result from the computeshader isnt inverted as the c# example is. ![alt text][2] ---------- [1]: /storage/temp/112615-aaaplz0.png [2]: /storage/temp/112616-aaaplz1.png

Viewing all articles
Browse latest Browse all 287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>