2

I would like to create a wire frame effect using a shader program written in AGAL for Stage3D.

I have been Googling and I understand that I can determine how close a pixel is to the edge of a triangle using barycentric coordinates (BC) passed into the fragment program via the vertex program, then colour it accordingly if it is close enough.

My confusion is in what method I would use to pass this information into the shader program. I have a simple example set up with a cube, 8 vertices and an index buffer to draw triangles between using them.

If I was to place the BC's into the vertex buffer then that wouldn't make sense as they would need to be different depending on which triangle was being rendered; e.g. Vetex1 might need (1,0,0) when rendered with Vetex2 and Vetex3, but another value when rendered with Vetex5 and Vetex6. Perhaps I am not understanding the method completely.

Do I need to duplicate vertex positions and add the aditional data into the vertex buffer, essentially making 3 vertices per triangle and tripling my vertex count? Do I always give the vertex a (1,0,0), (0,1,0) or (0,0,1) value or is this just an example? Am I over complicating this and is there an easier way to do wire-frame with shaders and Stage3d?

Hope that fully explains my problems. Answers are much appreciated, thanks!

JimmyDeemo
  • 313
  • 1
  • 15

2 Answers2

3

It all depends on your geomtery, and this problem is in fact a problem of graph vertex coloring: you need your geometry graph to be 3-colorable. The good starting point is the Wikipedia article.

Just for example, let's assume that (1, 0, 0) basis vector is red, (0, 1, 0) is green and (0, 0, 1) is blue. It's obvious that if you build your geometry using the following basic element

basic graph element

then you can avoid duplicating vertices, because such graph will be 3-colorable (i.e. each edge, and thus each triangle, will have differently colored vertices). You can tile this basic element in any direction, and the graph will remain 3-colorable:

tiling example

skozin
  • 3,789
  • 2
  • 21
  • 24
1

You've stumbled upon the thing that drives me nuts about AGAL/Stage3D. Limitations in the API prevent you from using shared vertices in many circumstances. Wireframe rendering is one example where things break down...but simple flat shading is another example as well. What you need to do is create three unique vertices for each triangle in your mesh. For each vertex, add an extra param (or design your engine to accept vertex normals and reuse those, since you wont likely be shading your wireframe).

Assign each triangle a unit vector A[1,0,0], B[0,1,0], or C[0,0,1] respectively. This will get you started. Note, the obvious solution (thresholding in the fragment shader and conditionally drawing pixels) produces pretty ugly aliased results. Check out this page for some insight in techniques to anti-alias your fragment program rendered wireframes:

http://cgg-journal.com/2008-2/06/index.html

As I mentioned, you need to employ a similar technique (unique vertices for each triangle) if you wish to implement flat shading. Since there is no equivalent to GL_FLAT and no way to make the varying registers return an average, the only way to implement flat shading is for each vertex pass for a given triangle to calculate the same lighting...which implies that each vertex needs the same vertex normal.

jordancpaul
  • 2,954
  • 1
  • 18
  • 27
  • Thanks for the reply. So to summarize, I would need to duplicate vertices and provide the extra information in the vertex buffer? In a similar way that I would have to do when providing normal's for lighting? Thanks for the link re: aliasing. – JimmyDeemo Jan 21 '13 at 10:28
  • 1
    You don't _need_ to duplicate the vertices for lighting if you calculate vertex normals and perform smooth/gouraud/phong shading. The similarity between barycentric coord's and normal mapping comes when you attempt to implement flat shading. In this case, you have to duplicate the vertices for each triangle and set all three (per triangle) vertex normals to the triangle face normal. To solve your barycentric problem, you set the "normal" vectors to A[1,0,0], B[0,1,0], and C[0,0,1]. Now, when the fragment shader interpolates, you will always be able to figure out where you are in the triangle. – jordancpaul Jan 22 '13 at 19:10