dwmkerr / sharpgl

Use OpenGL in .NET applications. SharpGL wraps all modern OpenGL features and offers a powerful scene graph to aid development.
MIT License
755 stars 299 forks source link

Use of GL_COLOR_MATERIAL with VBOs? #120

Open dragon42 opened 8 years ago

dragon42 commented 8 years ago

I have my program set up to use VBOs, which works nicely. I'm specifying per-vertex colors as part of the VBO definition and would like to be able to view the colorized object using GL_COLOR_MATERIAL. The problem is that I've tried many combinations of gl.ColorMaterial() and gl.Light() settings. No matter what I do I see either a flat shaded gray or red object when I try to use ColorMaterial. There is no surface shading or indication that my color array is being read. Can anyone suggest the appropriate gl.Light()and gl.ColorMaterial() calls to get this to work? I am aware that the placement and ordering of the lighting and gl.ColorMaterial() calls relative to the VBO definition may be important. I Just can't figure it out. My VBO definition is shown below. I've also tried defining the color array as a float (0 to 1.0) array rather than a byte (0 to 255) array, but the end result is the same.

            // Get id for VBO vertex array
            m_vertexVBOID = new uint[1];
            gl.GenBuffers(1, m_vertexVBOID);
            gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, m_vertexVBOID[0]);

            // Allocate vertex array
            int vboSize = (m_vcl_vertices.Length * sizeof(float)) + (m_vcl_normals.Length * sizeof(float));
            gl.BufferData(OpenGL.GL_ARRAY_BUFFER, vboSize, IntPtr.Zero, OpenGL.GL_STATIC_DRAW);

            // Copy vertex data to VBO.
            IntPtr vertexArray = GCHandle.Alloc(m_vcl_vertices, GCHandleType.Pinned).AddrOfPinnedObject();
            int vertexArraySize = m_vcl_vertices.Length * sizeof(float);
            gl.BufferSubData(OpenGL.GL_ARRAY_BUFFER, 0, vertexArraySize, vertexArray);

            // Copy normal data to VBO.
            IntPtr normalArray = GCHandle.Alloc(m_vcl_normals, GCHandleType.Pinned).AddrOfPinnedObject();
            int normalArraySize = m_vcl_normals.Length * sizeof(float);
            gl.BufferSubData(OpenGL.GL_ARRAY_BUFFER, vertexArraySize, normalArraySize, normalArray);

            // Copy color data to VBO.
            IntPtr colorArray = GCHandle.Alloc(m_vcl_colors, GCHandleType.Pinned).AddrOfPinnedObject();
            int colorArraySize = m_vcl_colors.Length * sizeof(byte);
            gl.BufferSubData(OpenGL.GL_ARRAY_BUFFER, vertexArraySize + normalArraySize, colorArraySize, colorArray);

            // Set pointer to vertex data
            gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY);
            gl.VertexPointer(3, OpenGL.GL_FLOAT, 0, IntPtr.Zero);

            // Set pointer to normal data
            gl.EnableClientState(OpenGL.GL_NORMAL_ARRAY);
            IntPtr normalOffset = new IntPtr(vertexArraySize);
            gl.NormalPointer(OpenGL.GL_FLOAT, 0, normalOffset);

            // Set pointer to color data
            gl.EnableClientState(OpenGL.GL_COLOR_ARRAY);
            IntPtr colorOffset = new IntPtr(vertexArraySize + normalArraySize);
            gl.ColorPointer(4, OpenGL.GL_BYTE, 0, colorOffset);

            if (m_indexVBOID != null)
            {
                gl.DeleteBuffers(1, m_indexVBOID);
            }

            // Get id for VBO index array
            m_indexVBOID = new uint[1];
            gl.GenBuffers(1, m_indexVBOID);
            gl.BindBuffer(OpenGL.GL_ELEMENT_ARRAY_BUFFER, m_indexVBOID[0]);

            // VBO index size = size of vertex array + size of normal array + size of color array
            int indexSize = m_vcl_indices.Length * sizeof(int);
            IntPtr indexArray = GCHandle.Alloc(m_vcl_indices, GCHandleType.Pinned).AddrOfPinnedObject();
            gl.BufferData(OpenGL.GL_ELEMENT_ARRAY_BUFFER, indexSize, indexArray, OpenGL.GL_STATIC_DRAW);

Here is an example of the lighting and GL_COLOR_MATERIAL calls I have tried (both before and after the VBO definition.

            gl.Enable(OpenGL.GL_LIGHTING);
            gl.Enable(OpenGL.GL_LIGHT0);

            float[] light_ambient = { 0.2F, 0.2F, 0.2F, 1.0F };
            float[] light_diffuse= { 1.0F, 1.0F, 1.0F, 1.0F };

            gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_AMBIENT, light_ambient);
            gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_DIFFUSE, light_diffuse);

            gl.ColorMaterial(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_AMBIENT);
            gl.ColorMaterial(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_DIFFUSE);

            gl.Enable(OpenGL.GL_COLOR_MATERIAL);