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
↧