0

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
        }

    }

Reza 110
  • 31
  • 4
  • There is a typo in the vertex shader: `##version 150 core` -> `#version 150 core` – Rabbid76 Feb 25 '21 at 22:16
  • The vertices are not automatically transformed by the fixed function matrices. You have to multiply the vertex coordinate by `gl_ModelViewProjectionMatrix`. However you have to use a `compatibility` profile: `#version 150 compatibility` and `gl_Position = gl_ModelViewProjectionMatrix * vec4(in_Position, 1.0);` – Rabbid76 Feb 25 '21 at 22:20
  • I changed ##version 150 core to #version 150 core, now all of the screen become orangeRad. – Reza 110 Feb 25 '21 at 22:24
  • can you give me the right code – Reza 110 Feb 25 '21 at 22:25
  • @HassanSoleimani Read my comment! `#version 150 compatibility` and `gl_Position = gl_ModelViewProjectionMatrix * vec4(in_Position, 1.0);` – Rabbid76 Feb 25 '21 at 22:26
  • Its work. thank you very much. – Reza 110 Feb 25 '21 at 22:27
  • Rabbid76 thanks. do you have any comment for my code to improve the speed. – Reza 110 Feb 25 '21 at 22:29

1 Answers1

0

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).

  1. 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.

  2. You have a random glEnableVertexAttribArray in your render function, why? Set up your vertex buffer once and set it up correctly.

  3. 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?

  4. Detach and delete compiled shaders from your program, you're leaking memory. And for god's sake, check your error codes, because:

  5. 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.

  6. glUseProgram(0) is undefined behaviour. Just write correct code instead and use DSA to not pollute your OpenGL state machine.

  7. 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.

  8. Don't use GL_QUADS, triangulate your data correctly, set up an index buffer and use GL_TRIANGLES.

  9. 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.

  10. 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.

Blindy
  • 65,249
  • 10
  • 91
  • 131