I am trying to find a fast (well performing) way to draw a bunch of lines based on two sets of xyz coordinates. I would like them to be each separate lines defined by two points, NOT a connected poly-line as you can do with a Limit SOP. In Processing I did this by calling an iteration inside of a gl.glBegin(GL.GL_LINES) call, and then I can just call the vertices and colors inside the iteration loop, and then end the GL_LINES.
I can’t seem to get a Copy SOP to perform particularly well. The performance is slow, and its rather difficult to use the parameter stamping to specify the xyz coordinates of the two points out of a single CHOP.
Ideally I’d love to have some kind of component that I can pass two CHOPs or sets of coordinates to that contain the two sets of points and have it generate the lines similarly to how I’ve done it with Processing. I am going to work a bit more on the problem and post with some progress, but I am worried that there may not be a way in Touch right now that will allow me to enact the open GL method that I used before.
Does anyone have any pointers or thoughts about this?
I’m attaching one attempt using a copy SOP which seems to be running smoother, but not working completely. I converted the template from a Grid SOP to a CHOP and back because I will most likely be pulling my source geometry from a CHOP elsewhere. The approach is to use the template as one set of points, and stamp the other points with another grid that has been SOPtoCHOP’d (previously I was trying to parameter stamp both sets of coordinates).
I used the param() expression as talked about in the Copy SOP wiki, but its does not seem to be affecting each individual point. I have the two grids rotating at different speeds, so the lines should be crossing eachother, but it looks as if their two sets of points are just rotating at the same speed. The source line is rotating, so it seems that the param() expression is trickling back down the network to the line…
I’m wondering if I’m using parameter stamping incorrectly in the Copy SOP. line_array_test001.tox (1.58 KB)
try using $PT instead of $CY (I think $CY only gets filled when not using template geometry)
Anyway, as it’s all CPU based, it’s gonna be slow. try instancing a line SOP and then, in vertex shader, use instanceID to lookup your positions from a bunch of texture buffer objects. Or just instance a single point, and draw the lines in the geometry shader (again using tbo to lookup coordinates)
One of the problems is that your are using $CY which is the number of the copy when specifying the cpoies via the copy parameter in the Copy SOP were you would want to use $PT which is the point number of your template (the grid).
If I understood you correctly though, you would want to copy the line 400 times and then stamp not only the values for point b but also for point A. So here is your tox slightly changed…
I’ll try to think of a different way to achieve what you want in the meantime.
here is another approach at this. I’m using an Expression CHOP to interweave the 2 into 1 long CHOP and then use a Channel SOP to transform the points of the line which i copied 400 times before that.
The fastest would be to combine to the two. Instance a single point N times (however many lines you want). The points can all be at the same point since you won’t be using the input point position anyway. Use input type of Point and Output type as lines for the geometry shader.
Output one line per instance using texture buffers to source the line’s vertex positions.
The reason this is faster is that geometry shaders will slow down a lot if they output more than a few vertices, so you want to have only one line output per executation of the geometry shader.
Markus’s second .tox works well, though I suppose there are a few OPs whose cook times I could see getting a bit bulky when added with a bunch of other parts to my project.
I don’t have the time until later today, but I will try and work on the shader solution when I do and post some more progress. I haven’t touched TBOs yet, but recall a post from Achim ( [url]Setting color of instances? - General TouchDesigner Discussion - TouchDesigner forum ) in another thread starting to talk about texture buffer objects. So I will go from there.
One other question, that I’m sure I will figure out when I get into it, but just wanted to put out there. TBO’s had been suggested to me when I remarked a limit in the size of the uniform array method of using GLSL to set instance colors, is there any sort of size limit for a TBO? If I wanted to do more than 1024 lines using TBO’s would I need to split up the work or think of something else?
here is yet another approach that is faster then the last one just using SOPs and CHOPs. This time I avoid the expression CHOP since it was a bit slow. I divide the points form the 400 lines into 2 groups via the Group SOPs and then transform the points via 2 Channel SOPs. To get the transformation correct i have to change the length of the CHOPs to match the total point number via a Trim CHOP.
I haven’t had that much time to try out the geometry shader/TBO method, but I wanted to post what I have so far and get some feedback on proper methods ( as my shader is erroring for the time being).
The CHOPs for the TBO are derived in the same way as for the channel SOP method. Instancing is on in the geo COMP for 400 instances.
I assume that I am not specifying or using the CHOPs/TBOs correctly in the shader and GLSL MAT. Should I be calling them out as vec4’s or vec3’s? If so, how do I know that tx, ty, tz are in the right order as vector components? Will the CHOP even be read in this fashion (as a vector with channels as components) in the shader? If they need to be vec4’s does another channel need to be added to both CHOPs for the w component? (btw, I didn’t know there was a w component for 3D points these days, what is that?) Whew…
Anyways, just a few questions about how it all works. My geometry shader is relatively simple, so I’m not sure if I’m missing something there or somewhere else, but I imagine my questions above have the most to do with why it isn’t working right now.
you had a couple of issues, but are on a good way. There isn’t much info about all this available (even outside of touch), so it’s a painfully learning experience.
As your geometry shader uses TBOs and is a geometry shader, you need to add both lines at the beginning
#extension GL_EXT_geometry_shader4 : enable
#extension GL_EXT_gpu_shader4 : enable
Second, as the compiler said, gl_instanceID is not available in the GS, so you need to pass it as a varying from the vertex shader
Finally, you need to make sure your line has a w value of 1. In this case I just added an additional channel to the TBO. You could also take care of this in code, then you would only need to use a vec3 TBO. I’m not sure about the use of w (think it’s used for nurbs curves), but the important thing to know is that it always needs to be 1.
As to your other question, the order in which the channels are listed in the CHOP (MMB on the node to see it) will determine how the vec4 array gets filled, so
tbo.x = chan0, tbo.y = chan1, …
The w coordinate is part of the linear algebra that’s used for vector/point transformations. A point is defined by (x,y,z,1) and a vector is defined by(x,y,z,0). It’s not specific to graphics, but to all linear algebra. If you are multiplying a vector by a mat4 and it’s w coordinate isn’t 0, then you will get incorrect results. Casting the matrix to a mat3 avoids that potential oversight though.
In practice what this does is cause the translation portion of a transform matrix to be applied to a point, but not to a vector (since vectors have no notion of position). Rotation and scale still gets applied to both though.
Thanks Achim and malcom for the help, it is much appreciated.
I have very little time today, and I’m not even at my Touch computer to check out the .tox you attached, but that all makes sense and I will post back when I’ve got more progress!
I am trying to color the instances using a texture like the spheres in the other post. Since these are lines, and a bit abstract, I don’t think I need to use any of the lighting stuff from a more standard pixel shader. I also figured I would try and do the coloring in the pixel shader since each line will basically be a single color. Don’t know if that’s a sounds approach or not.
In the attached .tox the lines are changing color, but it seems that the instanceID varying is not actually ‘varying’ it is just pulling from one texel (correct term?) in the texture, as all the lines are the same color. I read up a bit in the GLSL manual and learned a bit about the interpolation instructions, and learned that an integer needs to be declared as flat when it goes to the pixel shader (same as fragment shader right?).
*edit * I’m pretty sure my math is correct for locating the correct texel based on the instance (since it is pulling from a square texture, instead of linear one, I have to modulo and divide the instance id with the number of rows, and the instances to get the location). So I don’t think this is the problem, though I could have messed something up there. edit
So it seems that somewhere the pixel shader is only getting one vertex’s instanceID, and not changing with each instance. I am guessing this is either a conflict with the GS using the same varying, or I am not sending the data correctly between the shaders. When I tried doing the color instancing in the VS and then setting the fragColor to gl_Color in the PS I was just getting black lines. Should I still be setting the instance in the VS and not the pixel shader? I guess I am still unclear of the exact flow between the three, because it seems that GS has to happen before the VS in order for it to register the vertices created by the GS, but obviously the VS is responsible for passing varyings to both of the other two. Anyways, seems like more GLSL learning curve stuff. I’m going to keep going through the manual, but any pointers, examples or tweaks would be great!
Thanks
PS - I saw Scott Pagano at the LA NAMM party last night with his new Touch work, and it looked fantastic! archop_line_test_glsl3.tox (4.92 KB)
just had a very quick look at the file, maybe this is getting you closer. PS: moving the texture lookup to the vertex shader should be faster lines.toe (8.74 KB)
Thanks Achim, makes sense that you have to pass the variables through the GS if you’re using it.
Also makes sense that doing the color instancing in the VS would be faster, I have tried setting the gl_frontColor to the right color either by just setting it equal to the other color, or multiplying gl_Color by the texture lookup. I have also tried setting all the colors (back and secondaries) In all cases I am setting the fragColor in the PS to just gl_Color, and in all cases the lines show up as black. Is there something going on with the fact that I am rendering lines instead of polygons?
Or perhaps something to do with how the geometry shader creates more vertices and the gl_Color for each isn’t getting set so it remains at zero?
Not sure if these questions are getting to the point or not. I am attaching where it is currently, with trying to get the VS to implement the instance coloring. lines_VSinstance_color_attempt1.1.toe (9.07 KB)
Progress update. With an edit and problem almost solved!
Okay I posted the following paragraph just a second ago, and then installed the new build and started it up again, and the VS color instancing works with the GS! Either its the new build, or somethign happened when I restarted Touch. I believe i was working in 4917, possibly 4898, and now it seems to work in 4922.
Now the only trick is that it seems I’m not referencing the color texture exactly right, as when I stop everything from moving around it doesn’t look like the radial ramp that I’m pulling the colors from, probably something with how i’m doing the math to find my texture lookup. Thanks so much for the help!*
original post, just for kicks:
Extending the logic of needing to pass information through the geometry shader, I discovered I have to set the frontColor in the geometry shader. The problem now is that we’re back to only getting one instance’s color for all the instances. Seems like the GS is only getting the gl_Color for one instance and setting all of them to that. I’ve been combing through GLSL pages and forums with no success. Not sure if there is something missing to make sure that each instance’s color is getting passed, or if I’ve just got a typo or incorrect code in the VS or GS. New file is attached.
The previously described techniques required you to write GLS shaders etc. to draw lines from CHOPs.
There’s an easy way. You had 2 CHOPs of 400 samples, each CHOP containing channels tx ty tz. You send each CHOP to a Limit SOP, giving a 400-point open polygon. Then Merge CHOP them together giving two 400 point polygons. Finally use the Skin SOP to change the connectivity of the 800 points into 400 lines of 2 points. Use the bullseye icon on the parameter box to see what parameters are non-default. Then give that SOP to a Render TOP.
(Don’t ask why it’s a Limit SOP and you can’t use a CHOP to SOP. CHOP to SOP currently requires a SOP input, which we will fix for 077 to allow a simple CHOP array to make a simple SOP line.) archop_line_test_glsl.4.toe (8.85 KB)