2
votes

Situation: I am drawing with OpenGL in C# with the library OpenTK.

.

Problem: I cannot choose which one of my buffers/sets of vertices to draw.

.

Setup-Function:

var vertices = new Vertex[..];

Create the vertices

foreach( .. ) 
{
 Byte4 color = new Byte4();
 color.R     = 255;
 color.G     = 0;
 color.B     = 0;
 color.A     = 100;

 Vertex vertex;
 vertex.Position = new Vector3(.....);
 vertex.Color    = color;

 vertices[index] = vertex;
}

Generate / bind buffers.

vbo_size = vertices.Length;
GL.GenBuffers(1, out vbo_id);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
GL.BufferData<Vertex>(BufferTarget.ArrayBuffer, (IntPtr)(vbo_size * Vertex.SizeInBytes), vertices, BufferUsageHint.StaticDraw);
GL.InterleavedArrays(InterleavedArrayFormat.C4ubV3f, 0, IntPtr.Zero);

* Vertex.SizeInBytes is 16 if this matters.

.

Render-code:

GL.Enable(EnableCap.DepthTest);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
..
GL.Enable(EnableCap.ColorArray);
GL.DrawArrays(BeginMode.Points, 0, vbo_size);
GL.Disable(EnableCap.ColorArray);
..
glControl1.SwapBuffers();

.

What id like to do:

In the setup-code i create my vertices (Vertex include position and color). I create one set right now, but i would like to create one more (just the same code with different color-values). I did this, and of course it is fine to create it and bind it to a secondary buffer (vbo_id/vbo_secondary_id). But how do I draw it?

Something like this is what I am looking for:

RenderNormalColors()
{
  GL.UseVboId(vbo_id);
  GL.DrawArrays(BeginMode.Points, 0, vbo_size);
}

RenderAlternativeColors()
{
  GL.UseVboId(vbo_id_secondary);
  GL.DrawArrays(BeginMode.Points, 0, vbo_size);
}

The GL.DrawArrays seems to take everything without control of what to draw.

Everything in the vertices/arrays will/is be identical apart from the colors. I just need to render the same objects - thousands of points - with another "colorscheme".

Any help would be appriciated.

2

2 Answers

2
votes

So I fixed it. Kind of how I originally thought the solution would be.

I created one array for the vertices (positions) and two separate arrays with colors (C# "Color").

  vertices  = new Vector3[evaluations.Count];
  colors    = new int[evaluations.Count];
  altcolors = new int[evaluations.Count];

Then I bound them to different buffers.

  vbo_size = vertices.Length; // Necessary for rendering later on
  GL.GenBuffers(1, out vbo_id);
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
  GL.BufferData(BufferTarget.ArrayBuffer,
                new IntPtr(vertices.Length * BlittableValueType.StrideOf(vertices)), // strideof means what?
                vertices, BufferUsageHint.StaticDraw);

  GL.GenBuffers(1, out vbo_color_id);
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color_id);
  GL.BufferData(BufferTarget.ArrayBuffer,
                new IntPtr(colors.Length * BlittableValueType.StrideOf(vertices)),
                colors, BufferUsageHint.StaticDraw);

  GL.GenBuffers(1, out vbo_color_id_alt);
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color_id_alt);
  GL.BufferData(BufferTarget.ArrayBuffer,
                new IntPtr(altcolors.Length * BlittableValueType.StrideOf(vertices)),
                altcolors, BufferUsageHint.StaticDraw);

Notice the "vbo_color_id" and "vbo_color_id_alt". These are used in the Render()

selected_vbo = either color_id_alt or color_id

  GL.BindBuffer(BufferTarget.ArrayBuffer, selected_vbo);
  GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);
  GL.EnableClientState(ArrayCap.ColorArray);

  GL.EnableClientState(ArrayCap.VertexArray);
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
  GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
  GL.DrawArrays(BeginMode.Points, 0, vbo_size);
0
votes

I used this to be able to select points in a point cloud. Every point gets, in the alternative colorscheme, an unique color (stored in a dictionary which points to the points id (index)).

When I click the mouse it retreives the current pixel and checks the list. If it finds a color that are present in the set it will know what point was clicked.

This is pretty good since I did not have to use raycasting or octtrees or similar checks. Worth noticing though is that this will make it impossible to find anything behind the points that are currently showed on the screen.

I render the alternative colors, pick the pixel-under-mouse-color but I do not use "swapbuffer()" so it will never show on the screen. Then I render it again with the corerct colors.

Pretty nifty.

public void RenderAlternativeColorsAndPick(int x, int y)
{
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_color_id_alt);
  GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(int), IntPtr.Zero);
  GL.EnableClientState(ArrayCap.ColorArray);

  GL.EnableClientState(ArrayCap.VertexArray);
  GL.BindBuffer(BufferTarget.ArrayBuffer, vbo_id);
  GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
  GL.DrawArrays(BeginMode.Points, 0, vbo_size);

  // Psuedo code sorry
  GL.GetPixelColor(x,y)
  SelectedPoint    = dictionary<color,int>.findValuebyKey(thePixelsColor)
}

Hope this helps someone in the future.