首页 > 解决方案 > 为什么用 SharpGL 绘制的所有立方体都是白色的?

问题描述

我正在使用 SharpGL 在 WPF 中编写一个程序来绘制一些立方体。在我的软件中,需要绘制大量的立方体。最初,我使用即时模式渲染方法,这使得应用程序太慢。之后我使用了VAO方法,应用程序的速度提高了很多。唯一的问题是所有的立方体都是用白色绘制的。我认为问题在于着色器部分。请帮我解决这个问题。

        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
        }

    }

标签: c#wpfopenglsharpgl

解决方案


这是……灾难性的。几乎完全绝望。但是我将尝试解释一些问题(不可能详细说明您的代码的所有问题,数量之多令人难以置信)。

  1. 停止使用固定管道,您的随机glMatrixMode调用和诸如此类的调用实际上什么都不做。在着色器中设置制服并传递投影和世界(和视图)变换矩阵,然后使用它们来变换顶点。

  2. 你的渲染函数中有一个随机glEnableVertexAttribArray数,为什么?设置一次顶点缓冲区并正确设置。

  3. 初始化 OpenGL 时,请求特定版本和特定上下文类型。您没有理由不将其设置为 4.6 核心上下文,但谁知道您拥有什么?

  4. 从程序中分离并删除已编译的着色器,您正在泄漏内存。看在上帝的份上,请检查您的错误代码,因为:

  5. 你的顶点着色器在开始时有一个无效的#version预处理器指令,你写道##version。检查您的错误信息!并使用现代 OpenGL 版本上下文,例如#version 460 core.

  6. glUseProgram(0)是未定义的行为。只需编写正确的代码并使用 DSA 就不会污染您的 OpenGL 状态机。

  7. 您的顶点缓冲区完全错误,您对其进行了两次初始化并设置了一次位置参数和一次颜色参数,最后您的顶点缓冲区只知道颜色参数。正确设置。这两个列表在做什么?OpenGL 缓冲区中的数据是交错布局的,而不是在不同的缓冲区中或一个接一个或您想象的任何其他缓冲区中。

  8. 不要使用GL_QUADS,正确地对数据进行三角测量,设置索引缓冲区并使用GL_TRIANGLES.

  9. 与创建立方体顶点相关的所有内容,只需将其删除即可。您不了解多维数据集如何工作或列表如何工作(您随机重新初始化您的Vertexs每次调用,以及拼写顶点或顶点的方式),或者再次了解 OpenGL 缓冲区如何工作。

  10. 最后,在 WPF 应用程序的 Win32 岛中实例化 OpenGL 上下文效率极低。OpenGL 和 D3d(这是 WPF 使用的)都提供了相互操作的函数。挂钩到 WPF 的 D3D 上下文并直接渲染到其中。并且不要使用 SharpGL,使用现代的、可移植的 (.Net5) OpenGL 绑定库,如 OpenTK。


推荐阅读