Why are all the cubes drawn in SharpGL white? - c#

I am writing a program in WPF, using SharpGL, to draw some cubes. In my software, a large number of cubes need to be drawn. Initially, I used the immediate mode rendering method, which makes the app too slow. After that I use the VAO method, the app speed improved a lot. The only problem is that all the cubes are drawn in white. I think the problem is the Shader part. Please help me fix this problem.
private void openGLControl_OpenGLInitialized(object sender, SharpGL.WPF.OpenGLRoutedEventArgs args)
{
OpenGL gL = openGLControl.OpenGL;
gL.Enable(OpenGL.GL_DEPTH_TEST);
gL.ClearColor(0, 0, 0, 0);
gL.MatrixMode(OpenGL.GL_PROJECTION);
gL.LoadIdentity();
myShader = new MyShader(gL);
}
public void SetUpCamera(OpenGL gL)
{
gL.Viewport(0, 0, (int)openGLControl.ActualWidth, (int)openGLControl.ActualHeight);
gL.MatrixMode(OpenGL.GL_PROJECTION);
gL.LoadIdentity();
gL.Perspective(45.0, openGLControl.ActualWidth / openGLControl.ActualHeight, 0.1, 10000.0);
gL.LookAt(0.0, 0.0, 0.1,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
}
private void openGLControl_OpenGLDraw(object sender, SharpGL.WPF.OpenGLRoutedEventArgs args)
{
if (Camera.IsDrawSkip)
{
return;
}
Camera.IsDrawSkip = true;
OpenGL gL = openGLControl.OpenGL;
gL.ClearColor(Colors.DarkGray.ScR, Colors.DarkGray.ScG , Colors.DarkGray.ScB, 0);
gL.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
SetUpCamera(gL);
gL.MatrixMode(OpenGL.GL_MODELVIEW);
gL.LoadIdentity();
gL.Translate(Camera.XTransition, Camera.YTransition, Camera.Zoom);
gL.Rotate(Camera.XRotationAngle, 1, 0, 0);
gL.Rotate(Camera.YRotationAngle, 0, 1, 0);
myShader.Bind();
if (Camera.DrawState == DrawState.Draw)
{
drawObjects(gL);
}
VBOManager.Render(gL);
myShader.Unbind();
gL.EnableVertexAttribArray(1);
gL.Flush();
}
private void drawObjects(OpenGL gL)
{
if(int.TryParse(txtCount.Text, out int count))
{
VBOManager.Vertices.Clear();
int index = cbxShape.SelectedIndex;
if (index == 0)
{
for (int z = 0; z < count; z++)
{
for (int y = 0; y < count; y++)
{
for (int x = 0; x < count; x++)
{
VBOManager.AddCubeValues(x * 5, y * 5, z * 5, Colors.OrangeRed);
}
}
}
}
VBOManager.GenerateGeometry(gL);
}
}
public class MyShader
{
public MyShader(OpenGL gl)
{
gL = gl;
init();
}
#region Property
public OpenGL gL { get; set; }
public uint shader_id;
public uint shader_vp;
public uint shader_fp;
#endregion
public void init()
{
shader_vp = gL.CreateShader(OpenGL.GL_VERTEX_SHADER);
shader_fp = gL.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
gL.ShaderSource(shader_vp, Shader_VERTEX_Text());
gL.ShaderSource(shader_fp, Shader_FRAGMENT_Text());
gL.CompileShader(shader_vp);
gL.CompileShader(shader_fp);
shader_id = gL.CreateProgram();
gL.AttachShader(shader_id, shader_fp);
gL.AttachShader(shader_id, shader_vp);
gL.LinkProgram(shader_id);
gL.BindAttribLocation(shader_id, 0, "in_Position"); // Bind a constant attribute location for positions of vertices
gL.BindAttribLocation(shader_id, 1, "in_Color"); // Bind another constant attribute location, this time for color
}
public void Bind()
{
gL.UseProgram(shader_id);
}
public void Unbind()
{
gL.UseProgram(0);
}
private string Shader_FRAGMENT_Text()
{
return #"#version 150 core
in vec3 pass_Color;
out vec4 out_Color;
void main(void)
{
out_Color = vec4(pass_Color, 1.0);
}";
}
private string Shader_VERTEX_Text()
{
return #"##version 150 core
in vec3 in_Position;
in vec3 in_Color;
out vec3 pass_Color;
void main(void)
{
gl_Position = vec4(in_Position, 1.0);
pass_Color = in_Color;
}";
}
}
public static class VBOManager
{
private static VertexBufferArray m_vertexBuffer = new VertexBufferArray();
public static List<float> Vertices = new List<float>();
public static List<float> Colores = new List<float>();
public static void GenerateGeometry(SharpGL.OpenGL gl)
{
m_vertexBuffer.Create(gl);
m_vertexBuffer.Bind(gl);
GenerateVertexBuffer(gl);
GenerateColourBuffer(gl);
m_vertexBuffer.Unbind(gl);
}
private static void GenerateColourBuffer(SharpGL.OpenGL gl)
{
var vertexDataBuffer = new VertexBuffer();
vertexDataBuffer.Create(gl);
vertexDataBuffer.Bind(gl);
vertexDataBuffer.SetData(gl, 1, Colores.ToArray(), false, 3);
}
private static void GenerateVertexBuffer(SharpGL.OpenGL gl)
{
var vertexDataBuffer = new VertexBuffer();
vertexDataBuffer.Create(gl);
vertexDataBuffer.Bind(gl);
vertexDataBuffer.SetData(gl, 0, Vertices.ToArray(), true, 3);
}
public static void Render(SharpGL.OpenGL gl)
{
m_vertexBuffer.Bind(gl);
gl.DrawArrays(SharpGL.OpenGL.GL_QUADS, 0, Vertices.Count);
m_vertexBuffer.Unbind(gl);
}
#region Cube Part
public static List<VertexV2> Vertexs;
public static void GenerateVertex()
{
float value = 2 / 2.0f;
Vertexs = new List<VertexV2>();
Vertexs.Add(new VertexV2(-value, value, value)); //V1
Vertexs.Add(new VertexV2(value, value, value)); //V2
Vertexs.Add(new VertexV2(value, -value, value)); //V3
Vertexs.Add(new VertexV2(-value, -value, value)); //V4
Vertexs.Add(new VertexV2(-value, value, -value)); //V5
Vertexs.Add(new VertexV2(value, value, -value)); //V6
Vertexs.Add(new VertexV2(value, -value, -value)); //V7
Vertexs.Add(new VertexV2(-value, -value, -value)); //V8
}
public static void AddVertex(int i, float x_Trans, float y_Trans, float z_Trans, Color color)
{
Vertices.Add(Vertexs[i].X + x_Trans);
Vertices.Add(Vertexs[i].Y + y_Trans);
Vertices.Add(Vertexs[i].Z + z_Trans);
Colores.Add(color.ScR);
Colores.Add(color.ScG);
Colores.Add(color.ScB);
}
public static void AddCubeValues(float x_Trans, float y_Trans, float z_Trans, Color color)
{
AddVertex(0, x_Trans,y_Trans,z_Trans, color); //V1
AddVertex(1, x_Trans,y_Trans,z_Trans, color); //V2
AddVertex(2, x_Trans,y_Trans,z_Trans, color); //V3
AddVertex(3, x_Trans, y_Trans, z_Trans, color); //V4
AddVertex(4, x_Trans,y_Trans,z_Trans, color); //V5
AddVertex(5, x_Trans,y_Trans,z_Trans, color); //V6
AddVertex(6, x_Trans,y_Trans,z_Trans, color); //V7
AddVertex(7, x_Trans,y_Trans,z_Trans, color); //V8
AddVertex(0, x_Trans,y_Trans,z_Trans, color); //V1
AddVertex(3, x_Trans,y_Trans,z_Trans, color); //V4
AddVertex(7, x_Trans,y_Trans,z_Trans, color); //V5
AddVertex(4, x_Trans,y_Trans,z_Trans, color); //V8
AddVertex(0, x_Trans,y_Trans,z_Trans, color); //V1
AddVertex(1, x_Trans,y_Trans,z_Trans, color); //V4
AddVertex(5, x_Trans,y_Trans,z_Trans, color); //V5
AddVertex(4, x_Trans,y_Trans,z_Trans, color); //V8
AddVertex(1, x_Trans,y_Trans,z_Trans, color); //V1
AddVertex(2, x_Trans,y_Trans,z_Trans, color); //V4
AddVertex(6, x_Trans,y_Trans,z_Trans, color); //V5
AddVertex(5, x_Trans,y_Trans,z_Trans, color); //V8
AddVertex(2, x_Trans,y_Trans,z_Trans, color); //V3
AddVertex(3, x_Trans,y_Trans,z_Trans, color); //V4
AddVertex(7, x_Trans,y_Trans,z_Trans, color); //V8
AddVertex(6, x_Trans, y_Trans, z_Trans, color); //V7
}
}

This is.. disastrous. Almost completely hopelessly so. But I'll give a shot at explaining some of the problems (it's impossible to detail all the problems with your code, there's so incredibly many).
Stop using the fixed pipeline, your random glMatrixMode and whatnot calls do literally nothing. Set up uniforms in your shaders and pass the projection and world (and view) transform matrices, then use them to transform your vertices.
You have a random glEnableVertexAttribArray in your render function, why? Set up your vertex buffer once and set it up correctly.
When you initialize OpenGL, request a specific version and a specific context type. There's no reason why you wouldn't set it as a 4.6 core context, but who knows what you have?
Detach and delete compiled shaders from your program, you're leaking memory. And for god's sake, check your error codes, because:
Your vertex shader has an invalid #version pre-processor instruction at the beginning, you wrote ##version. Check your error messages! And use a modern OpenGL version context, like #version 460 core.
glUseProgram(0) is undefined behaviour. Just write correct code instead and use DSA to not pollute your OpenGL state machine.
Your vertex buffer is completely wrong, you initialize it twice and set up once the position argument and once the color argument, and at the end your vertex buffer only knows about the color argument. Set it up correctly. What are those two lists doing? Data in OpenGL buffers is laid out interleaved, not in different buffers or one after the other or whatever else you imagine is happening here.
Don't use GL_QUADS, triangulate your data correctly, set up an index buffer and use GL_TRIANGLES.
Everything related to creating the cube vertices, just delete it. You do not understand how cubes work or how lists work (you randomly re-initialize your Vertexs every call, and by the way it's spelled vertexes or vertices), or again how OpenGL buffers work.
Lastly, instantiating an OpenGL context in a Win32 island in a WPF app is extremely inefficient. Both OpenGL and D3d (which is what WPF uses) provide functions to interop with eachother. Hook into WPF's D3D context and render directly into it. And don't use SharpGL, use a modern, portable (.Net5) OpenGL binding library, like OpenTK.

Related

OPENGLES 20 ```GlUniform4fv``` method for coloring an object throwing an exception in C# Android

I am trying to draw a triangle shape in Android Xamarin with C#. The triangle is a class with the method draw. In this draw method, there is an openGL20 method for coloring the triangle object we just created. Whenever the execution in the draw method reaches this color object method, this exception is thrown Java.Lang.IllegalArgumentException Message=length - offset < count*4 < needed.
I really can't understand what that error means but here is the code am using so far
public class MyGLRenderer : Java.Lang.Object, GLSurfaceView.IRenderer
{
//Renderer method to draw the triangle object
public void OnDrawFrame(IGL10 gl)
{
GLES20.GlClear(GLES20.GlColorBufferBit);
Triangle triangle = new Triangle();
triangle.draw();
}
//Method to set the view and the height of the painting window
public void OnSurfaceChanged(IGL10 gl, int width, int height)
{
GLES20.GlViewport(0, 0, width, height);
}
public void OnSurfaceCreated(IGL10 gl, Javax.Microedition.Khronos.Egl.EGLConfig config)
{
//Set the background frame color
GLES20.GlClearColor(0.0f, 0.0f, 1.0f, 0.0f);
GLES20.GlDrawArrays(GLES20.GlColorBufferBit, 2, 10);
}
}
Code below defines the Triangle class and the OPENGL20 color method thats throwing an exception commented upon
public class Triangle
{
private FloatBuffer vertexBuffer;
//Number of co-ordinates per vertex in this context
private static readonly int Coords_per_vert = 3;
private static float[] triangleCoords = new float[] {
0.0f,0.622008459f,0.0f, //top
-0.5f,-0.311004243f,0f , //bottom left
0.5f, -0.311004243f,0.0f //bottom right
};
//Set color with red, green, blue and alpha values
private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f };
private readonly int mProgram;
public Triangle()
{
//Initialize vertex byte buffer for shape co-ordinates
ByteBuffer bb = ByteBuffer.AllocateDirect(triangleCoords.Length * 4);
//Use the device native byte order
bb.Order(ByteOrder.NativeOrder());
FloatBuffer myfloat = bb.AsFloatBuffer();
//Create floating point buffer from ByteBuffer
vertexBuffer = bb.AsFloatBuffer();
vertexBuffer.Put(triangleCoords);
vertexBuffer.Position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GlVertexShader, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GlFragmentShader, fragmentShaderCode);
//Create empty opengles program
mProgram = GLES20.GlCreateProgram();
//Add vertex shader to program
GLES20.GlAttachShader(mProgram, vertexShader);
//Add Fragment to shader
GLES20.GlAttachShader(mProgram, fragmentShader);
//Create openGL program executables
GLES20.GlLinkProgram(mProgram);
}
private readonly string vertexShaderCode = "attribute vec4 vPosition;" +
"void main(){" +
" gl_Position=vPosition;" +
"}";
private readonly string fragmentShaderCode = "precision mediump float;" +
"uniform vec4 vColor;" +
"void main(){" +
"gl_FragColor=vColor;" +
"}";
private int positionHandle, colorHandle;
private readonly int vertexCount = triangleCoords.Length / Coords_per_vert;
private readonly int vertexStride = Coords_per_vert * 4;
//Create a method for drawing the triangle
public void draw()
{
//Add Program to open GLES Environment
GLES20.GlUseProgram(mProgram);
//Get handle to vertex shader's vPosition member
positionHandle = GLES20.GlGetAttribLocation(mProgram, "vPosition");
//Enable a handle to the triangle's vertices
GLES20.GlEnableVertexAttribArray(positionHandle);
//Prepare the triangle co ordinate data
GLES20.GlVertexAttribPointer(positionHandle, Coords_per_vert, GLES20.GlFloat, false, vertexStride, vertexBuffer);
//Get handle to fragment shader's vColor Member
colorHandle = GLES20.GlGetUniformLocation(mProgram, "vColor");
//Set color for drawing the triangle
GLES20.GlUniform4fv(colorHandle, 1, color, 3);
//Draw the triangle, this method causes an exception
GLES20.GlDrawArrays(GLES20.GlTriangles, 0, vertexCount);
//Disable vertex array
GLES20.GlDisableVertexAttribArray(positionHandle);
}
}
Please help me color the triangle object with success, what am i doing wrong
You are using a 3 sized float array for a vec4 uniform.
Add the alpha array to your color array like this
Replace
private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f };
with
private float[] color = new float[] { 0.63671875f, 0.76953125f, 0.22265625f,1.0f};
with the last member of the second array representing the alpha or opacity of the color being drawn

Drawing edited vertex value from VBO

I probably do something really stupid so go ahead and correct me.
I'm trying to make vertex move so...
In OnLoad I'm setting the VBO like you see.
In OnFrameRender I'm trying to edit vertex then i do drawArrays.
But i can't get this changes be visible in OpenTk window. Doing ConsoleWrite(prymi.vertOne) shows me that struct is edited (i do get sin from 0 to 20) so I'm assuming that this values are not updated on GPU. I tryed every VBO BufferUsageHint (Dynamic/Static/Stream(Copy/Draw/Read)) and this is not the case. I have read that i should use BufferSubData (i don't know about this concept yet(so any help would be helpful) but editing the object which is passed as reference with VBO StreamDraw should also do it... or em i wrong?
Thanks all :)
struct TrianglePrymi
{
public Vector2 vertOne;
public Vector2 vertSec;
public Vector2 VertThird;
public TrianglePrymi(Vector2 fi, Vector2 sec, Vector2 thi )
{
vertOne = fi;
vertSec = sec;
VertThird = thi;
}
public void edit(Vector2 a)
{
vertOne = a;
}
public static int retSize()
{
return (3 * Vector2.SizeInBytes);
}
}
protected override void OnLoad(EventArgs e)
{
prymi = new TrianglePrymi(new Vector2(20,20),new Vector2(300,200), new Vector2(530,420));
ttttt = TrianglePrymi.retSize();
VBO = GL.GenBuffer();
GL.BindVertexArray(VAO);
GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)ttttt,ref prymi, BufferUsageHint.DynamicDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
base.OnLoad(e);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
Console.WriteLine(prymi.vertOne[0]);
//Console.WriteLine(prymi.vertSec);
//Console.WriteLine(prymi.VertThird);
magicNumber += 1.00f;
float x = Math.Abs(20 * (float)Math.Sin(magicNumber));
float y = Math.Abs(20 * (float)Math.Cos(magicNumber));
GL.EnableClientState(ArrayCap.VertexArray);
GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);
GL.ClearColor(Color.Gray);
prymi.edit(new Vector2(x, y));
Vector2 vec = new Vector2(magicNumber, 450);
Matrix4 world = Matrix4.CreateOrthographicOffCenter(0, widX, 0, heiY, 0, 2000);
GL.LoadMatrix(ref world);
GL.Color3(Color.Yellow);
prymi.vertOne = vec;
GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
GL.VertexPointer(2, VertexPointerType.Float,Vector2.SizeInBytes, 0);
GL.DrawArrays(BeginMode.Triangles, 0, 3);
GL.End();
GL.Flush();
base.OnRenderFrame(e);
this.SwapBuffers();
}

OpenTK drawing to FBO, coloring not as expected

I have a utility class for Framebuffer objects which i use to generate FBO's, bind them, render to them, and render them to screen as 2d textures.
When using this class, i can successfully make fbo textures, render to them, and render them to screen.
However, the colors seem messed up once i render them to screen.
What seems to be happening is that the color i set as drawing color ends up as the background color of the FBO (but only if i make an actual draw call after setting the color), and the drawing i made always ends up black.
What i am expecting based on my code, is a texture with a white background, and two small colored rectangles (one purple and one cyan) on them, drawn to the screen two times.
what i am getting is this :
a cyan background with two small black rectangles.
Source code follows :
FboRenderTexture.cs
public class FboRenderTexture : IDisposable
{
public int textureId = 0;
private int fboId = 0;
public int Width;
public int Height;
public FboRenderTexture(int width, int height)
{
Width = width;
Height = height;
Init();
}
//semi pseudocode
public void DrawToScreen(float xoffset = 0, float yoffset = 0)
{
if (textureId != -1)
{
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.Begin(BeginMode.Quads);
//todo : might also flip the texture since fbo's have right handed coordinate systems
GL.TexCoord2(0.0, 0.0);
GL.Vertex3(xoffset, yoffset, 0.0);
GL.TexCoord2(0.0, 1.0);
GL.Vertex3(xoffset, yoffset+Height, 0.0);
GL.TexCoord2(1.0, 1.0);
GL.Vertex3(xoffset+Width, yoffset+Height, 0.0);
GL.TexCoord2(1.0, 0.0);
GL.Vertex3(xoffset+Width, yoffset, 0.0);
GL.End();
}
}
private void Init()
{
// Generate the texture.
textureId = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToBorder);
// Create a FBO and attach the texture.
GL.Ext.GenFramebuffers(1, out fboId);
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, fboId);
GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt,
FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, textureId, 0);
// Disable rendering into the FBO
GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
}
// Track whether Dispose has been called.
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// Clean up what we allocated before exiting
if (textureId != 0)
GL.DeleteTextures(1, ref textureId);
if (fboId != 0)
GL.Ext.DeleteFramebuffers(1, ref fboId);
disposed = true;
}
}
}
public void BeginDrawing()
{
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, fboId);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
GL.PushAttrib(AttribMask.ViewportBit);
GL.Viewport(0, 0, Width, Height);
}
public void EndDrawing()
{
GL.PopAttrib();
GL.Ext.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0); // disable rendering into the FBO
}
}
usage
public class Buffers : CreativeSharp.core.CSInstance //inherits from OpenTK.GameWindow, adds some simple drawing stuff.
{
private FboRenderTexture buffer;
public Buffers() : base(800, 600, "buffers")
{
GL.Enable(EnableCap.Texture2D);
buffer = new FboRenderTexture(128, 128);
NoStroke();
this.Closed += Buffers_Closed;
}
private void SetupBuffer()
{
buffer.BeginDrawing();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL.Color4(1f, 0f, 1f, 0f);
DrawRectangle(10,10, 30, 30);
GL.Color4(0f, 1f, 1f, 1f);
DrawRectangle(50, 10, 30, 30);
GL.Color4(1f, 1f, 1f);
buffer.EndDrawing();
}
void Buffers_Closed(object sender, EventArgs e)
{
buffer.Dispose();
}
public override void DrawContent()
{
SetupBuffer();
GL.ClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL.Color4(1f, 1f, 1f, 1f);
buffer.DrawToScreen(0,0);
buffer.DrawToScreen(512,0);
}
public override void Update()
{
}
private void DrawRectangle(float x, float y, float w, float h)
{
GL.Begin(PrimitiveType.Quads);
GL.Vertex3(x, y, 0);
GL.Vertex3(x + w, y, 0);
GL.Vertex3(x + w, y + h, 0);
GL.Vertex3(x, y + h, 0);
GL.End();
}
}
Somewhat embarrassingly, the cause of my problems was that i was not setting white as drawing color before drawing the fbo's texture.
This caused the colors to come out all wrong.

opengl- Vbo colors are mixing between objects

I have a class called PointCloud that is a vbo buffer object and I'm rendering a couple of these with different data, one as a sphere and one as a dataset of xyz, the dataset has colors and sphere is without colors. the problem is both seem to share the same colors, instead of having individual sets of colors, the colors for the sphere are actually set as null so I'm confused as to why color is being applied to it.
What I'm trying to do is draw the sphere 'white' while the other pointcloud is it's respective color.
if you can't see the image try this (http://s8.postimg.org/q1j0nlkol/pcerror.png)
http://pastebin.com/3fM9K87A
My question is can anybody explain why this is happening and what I'm doing wrong?
here is the pointcloud class:
using System;
using OpenTK.Graphics.OpenGL;
using OpenTK;
internal class PointCloud : IDisposable
{
protected int[] vbo_id = new int[2];
protected int vbo_size;
public bool HasColor;
public float[] Vertices = null;
public int[] Colors = null;
public float PointSize { get; set; }
public bool Visible { get; set; }
~PointCloud()
{
EmptyBuffer();
}
private void EmptyBuffer()
{
Vertices = (float[])null;
Colors = (int[])null;
}
public void Delete()
{
Dispose();
}
public PointCloud(float[] points)
{
this.vbo_size = points.Length;
GL.GenBuffers(2, this.vbo_id);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(points.Length * BlittableValueType.StrideOf<float>(points)), points, BufferUsageHint.StaticDraw);
Vertices = points;
}
public void ApplyColorMap(int[] colors)
{
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
GL.BufferData<int>(BufferTarget.ArrayBuffer, new IntPtr(colors.Length * BlittableValueType.StrideOf<int>(colors)), colors, BufferUsageHint.StaticDraw);
Colors = colors;
this.HasColor = true;
}
public void Render(FrameEventArgs e)
{
GL.EnableClientState(ArrayCap.VertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
if (!this.HasColor)
{
return;
}
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[1]);
GL.ColorPointer(4, ColorPointerType.UnsignedByte, 4, IntPtr.Zero);
GL.EnableClientState(ArrayCap.ColorArray);
}
public void Dispose()
{
EmptyBuffer();
GL.DeleteBuffers(vbo_id.Length, vbo_id);
this.vbo_id = new int[2];
}
}
this is my render code:
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.MatrixMode(MatrixMode.Modelview);
GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
GL.LoadMatrix(ref this.CameraMatrix);
GL.PushMatrix();
this.pointclouds.ForEach((Action<PointCloud>)(i =>
{
//blend
GL.Enable(EnableCap.Blend);
if (i.Visible)
{
GL.PushMatrix();
GL.PointSize(2.0f);
if (!i.HasColor)
{
GL.Color4(Color.White);
}
i.Render(e);
GL.PopMatrix();
}
}));
GL.PopMatrix();
}
The reason that it is not working is that you never disable clientState(ArrayCap.ColorArray). This will cause OpenGL to reuse this information endlessly.
A good approach is before you leave your render method to ALWAYS disable all client states that you enabled at the beginning of your function.
In your case you can simplify things by removing your color VBO completely, since your points only have a single color anyway. You already try to do this for !hasColor case anyway
Secondly, and I'm not sure if it was on purpose. In your render function you never set the correct color: When you call drawArrays you sent the information to the GPU, and after that you load the colors. This will cause the next point to have the previous color.
Something like this:
public void Render(FrameEventArgs e)
{
GL.EnableClientState(ArrayCap.VertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, this.vbo_id[0]);
GL.VertexPointer(3, VertexPointerType.Float, Vector3.SizeInBytes, new IntPtr(0));
if (!this.HasColor) GL.Color4f(0,0,0);
else GL.Color4f(putcolorvalue);
GL.DrawArrays(BeginMode.Points, 0, this.vbo_size);
GL.DisableClientState(ArrayCap.VertexArray);
}
I think you have to disable the ArrayCap.ColorArray state, if not the latest applied color array will be used:
GL.DisableClientState(ArrayCap.ColorArray);

C# OpenTK GLSL Crashing on attempting to render

I've been trying to implement GLSL into my program, however given that i have never used GLSL before, i decided I would try following a tutorial. Unfortunately following tutorials aren't my forte, and I am stuck here with my program crashing when 'RenderTerrain()' is called (in the second line of code of the function (GL.DrawElements))
Now this obviously all the code in the program, there is A LOT more, there's no chance any of you would go through 20k lines to find my problem :P But if you need to ask questions about any of it, please comment :)
So my question simply is, is there anything wrong with this code? Why would it be crashing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK.Graphics.OpenGL;
using OpenTK;
namespace HoardOfUpgrades
{
public class Shaders
{
private static string TerrainVertexShaderText = #"
#version 140
// object space to camera space transformation
uniform mat4 modelview_matrix;
// camera space to clip coordinates
uniform mat4 projection_matrix;
// incoming vertex position
in vec3 vertex_position;
// incoming vertex normal
in vec3 vertex_normal;
// incoming vertex_color
in vec3 vertex_color
// transformed vertex normal
out vec3 normal;
void main(void)
{
//not a proper transformation if modelview_matrix involves non-uniform scaling
normal = ( modelview_matrix * vec4( vertex_normal, 0 ) ).xyz;
// transforming the incoming vertex position
gl_Position = projection_matrix * modelview_matrix * vec4( vertex_position, 1 );
}
";
private static string TerrainFragmentShaderText = #"
#version 140
precision highp float;
const vec3 ambient = vec3( 0.1, 0.1, 0.1 );
const vec3 lightVecNormalized = normalize( vec3( 0.5, 0.5, 2 ) );
const vec3 lightColor = vec3( 1.0, 0.8, 0.2 );
in vec3 normal;
out vec4 out_frag_color;
void main(void)
{
float diffuse = clamp( dot( lightVecNormalized, normalize( normal ) ), 0.0, 1.0 );
out_frag_color = vec4( ambient + diffuse * lightColor, 1.0 );
}
";
public static int TerrainFragmentShaderHandle, TerrainVertexShaderHandle, TerrainProgramHandle, ProjectionMatrixLocation, ModelviewMatrixLocation, TerrainNormHandle, TerrainPosHandle, TerrainColorHandle, TerrainIndicesHandle, TerrainIndiceCount;
public static void Load(Vector3[] position, Vector3[] normals, Vector3[] colors, int[] indices)
{
LoadShaders();
LoadProgram();
LoadVertexPositions(position);
LoadVertexNormals(normals);
LoadVertexColors(colors);
LoadIndexer(indices);
}
static void LoadProgram()
{
TerrainProgramHandle = GL.CreateProgram();
GL.AttachShader(TerrainProgramHandle, TerrainVertexShaderHandle);
GL.AttachShader(TerrainProgramHandle, TerrainVertexShaderHandle);
GL.LinkProgram(TerrainProgramHandle);
}
static void LoadShaders()
{
TerrainVertexShaderHandle = GL.CreateShader( ShaderType.VertexShader );
TerrainFragmentShaderHandle = GL.CreateShader( ShaderType.FragmentShader );
GL.ShaderSource(TerrainVertexShaderHandle, TerrainVertexShaderText);
GL.ShaderSource(TerrainFragmentShaderHandle, TerrainFragmentShaderText);
GL.CompileShader(TerrainVertexShaderHandle);
GL.CompileShader(TerrainFragmentShaderHandle);
}
private static void QueryMatrixLocations()
{
ProjectionMatrixLocation = GL.GetUniformLocation(TerrainProgramHandle, "projection_matrix");
ModelviewMatrixLocation = GL.GetUniformLocation(TerrainProgramHandle, "modelview_matrix");
}
public static void SetModelviewMatrix(Matrix4 matrix)
{
GL.UniformMatrix4(ModelviewMatrixLocation, false, ref matrix);
}
public static void SetProjectionMatrix(Matrix4 matrix)
{
GL.UniformMatrix4(ProjectionMatrixLocation, false, ref matrix);
}
private static void LoadVertexPositions(Vector3[] data)
{
GL.GenBuffers(1, out TerrainPosHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainPosHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.BindAttribLocation(TerrainProgramHandle, 0, "vertex_position");
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadVertexNormals(Vector3[] data)
{
GL.GenBuffers(1, out TerrainNormHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainNormHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(1);
GL.BindAttribLocation(TerrainProgramHandle, 1, "vertex_normal");
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadVertexColors(Vector3[] data)
{
GL.GenBuffers(1, out TerrainColorHandle);
GL.BindBuffer(BufferTarget.ArrayBuffer, TerrainColorHandle);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(data.Length * Vector3.SizeInBytes),
data, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(1);
GL.BindAttribLocation(TerrainProgramHandle, 1, "vertex_color");
GL.VertexAttribPointer(2, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
}
private static void LoadIndexer(int[] data)
{
TerrainIndiceCount = data.Length;
GL.GenBuffers(1, out TerrainIndicesHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, TerrainIndicesHandle);
GL.BufferData<int>(BufferTarget.ElementArrayBuffer,
new IntPtr(data.Length * sizeof(int)),
data, BufferUsageHint.StaticDraw);
}
public static void RenderTerrain()
{
GL.UseProgram(TerrainProgramHandle);
GL.DrawElements(BeginMode.Triangles, TerrainIndiceCount,
DrawElementsType.UnsignedInt, IntPtr.Zero);
GL.UseProgram(0);
}
}
}
These lines of code must be included:
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.TextureCoordArray);
Arrays were enabled, they must be disabled to use the GL.DrawElements() function

Categories