OpenTK 纹理立方体显示为黑色?

OpenTK textured Cubes show up black?

我试着按照这里的说明 http://neokabuto.blogspot.com/2014/07/opentk-tutorial-6-part-3-putting-it-all.html (backup http://web.archive.org/web/20190125230120/http://neokabuto.blogspot.com/2014/07/opentk-tutorial-6-part-3-putting-it-all.html)但是我已经被扔了一百次代码但我仍然​​不断得到黑色立方体 :(.

这是我的洞项目的下载 link https://mega.nz/folder/t8NAxDRJ#MEIlwc96FZEPi_pUuB2xaA

这是它的样子

这是我的主要脚本,可能其中有错误?

  using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenTK;
//using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.IO;
using OpenTK.Input;
using System.Windows.Media.Imaging;
using System.Drawing.Imaging;
//using System.Windows.Input;
 
namespace OpenTKTutorial1
{
    class Game: GameWindow
    {
        public Game() : base(1000,500, new OpenTK.Graphics.GraphicsMode(32,24,0,4))
        {
            
        }
        
        //Just like we had a Dictionary to allow us to use strings to 
        //organize our shaders, we'll use another to keep track of our
        //texture IDs. Add this to the Game class:
        Dictionary<string, int> textures = new Dictionary<string, int>();

        Vector2[] texcoorddata;
        Camera cam;
        
        Vector2 lastMousePos = new Vector2();
        
        float time = 0.0f;
        
        int ibo_elements;
        
        Dictionary<string, ShaderProgram> shaders = new Dictionary<string, ShaderProgram>();
        string activeShader = "default";
        
        Vector3[] vertdata;
        Vector3[] coldata;
        List<Volume> objects = new List<Volume>();
        
        int[] indicedata;
        
        protected override void OnLoad(EventArgs e)
        {
          base.OnLoad(e);
            cam = new Camera();
            initProgram();
 
            Title = "Hello OpenTK!";
            GL.ClearColor(Color.CornflowerBlue);
            GL.PointSize(5f);
        }
        
    void initProgram()
    {           
          lastMousePos = new Vector2(Mouse.X, Mouse.Y);
     
            GL.GenBuffers(1, out ibo_elements);
                 
            shaders.Add("default", new ShaderProgram("Shaders/vs.glsl", "Shaders/fs.glsl", true));
            shaders.Add("textured", new ShaderProgram("Shaders/vs_tex.glsl", "Shaders/fs_tex.glsl", true));
             
            activeShader = "textured";
         
            textures.Add("pictures/opentksquare.png", loadImage("pictures/opentksquare.png"));
            textures.Add("pictures/opentksquare2.png", loadImage("pictures/opentksquare2.png"));
         
            TexturedCube tc = new TexturedCube();
            tc.TextureID = textures["pictures/opentksquare.png"];
            objects.Add(tc);
         
            TexturedCube tc2 = new TexturedCube();
            tc2.Position += new Vector3(1f, 1f, 1f);
            tc2.TextureID = textures["pictures/opentksquare2.png"];
            objects.Add(tc2);
         
            cam.Position += new Vector3(0f, 0f, 3f);
    }


        
        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);
            GL.Viewport(0, 0, Width, Height);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Enable(EnableCap.DepthTest);
 
 
           shaders[activeShader].EnableVertexAttribArrays();
 
              int indiceat = 0;
                
           foreach (Volume v in objects)
            {
                GL.ActiveTexture(TextureUnit.Texture0);
                GL.BindTexture(TextureTarget.Texture2D, v.TextureID);
                GL.UniformMatrix4(shaders[activeShader].GetUniform("modelview"), false, ref v.ModelViewProjectionMatrix);
             
                if (shaders[activeShader].GetUniform("maintexture") != -1)
                {
                    GL.Uniform1(shaders[activeShader].GetUniform("maintexture"), 0);
                }
             
                GL.DrawElements(BeginMode.Triangles, v.IndiceCount, DrawElementsType.UnsignedInt, indiceat * sizeof(uint));
                indiceat += v.IndiceCount;
            }
 
            shaders[activeShader].DisableVertexAttribArrays();
 
 
            GL.Flush();
            SwapBuffers();
        }
        
        private void ProcessInput()
        {
            if(OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Escape))
            {
                Exit();
            }
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.W))
            {
                cam.Move(0f, 0.1f, 0f);
            }
         
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.S))
            {
                cam.Move(0f, -0.1f, 0f);
            }
         
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.A))
            {
                cam.Move(-0.1f, 0f, 0f);
            }
         
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.D))
            {
                cam.Move(0.1f, 0f, 0f);
            }
         
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Q))
            {
                cam.Move(0f, 0f, 0.1f);
            }
         
            if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.E))
            {
                cam.Move(0f, 0f, -0.1f);
            }
            
            if (Focused)
            {
                Vector2 delta = lastMousePos - new Vector2(OpenTK.Input.Mouse.GetState().X, OpenTK.Input.Mouse.GetState().Y);
                lastMousePos += delta;
             
                cam.AddRotation(delta.X, delta.Y);
                lastMousePos = new Vector2(OpenTK.Input.Mouse.GetState().X, OpenTK.Input.Mouse.GetState().Y);
            }
        }

        
        protected override void OnUpdateFrame (FrameEventArgs e){
            time += (float)e.Time;
            ProcessInput();
        //  base.OnUpdateFrame();
            
            Vector2[] texcoorddata;
            List<Vector3> verts = new List<Vector3>();
            List<int> inds = new List<int>();
            List<Vector3> colors = new List<Vector3>();
            List<Vector2> texcoords = new List<Vector2>();
            
            int vertcount = 0;
             
            foreach (Volume v in objects)
            {
                verts.AddRange(v.GetVerts().ToList());
                inds.AddRange(v.GetIndices(vertcount).ToList());
                colors.AddRange(v.GetColorData().ToList());
                texcoords.AddRange(v.GetTextureCoords());
                texcoorddata = texcoords.ToArray();
                
                
            //  texcoords.AddRange(v.GetTextureCoords());
                
                vertcount += v.VertCount;
                
            }
            
            
 
            vertdata = verts.ToArray();
            indicedata = inds.ToArray();
            coldata = colors.ToArray();
                
            texcoorddata = texcoords.ToArray();
            
             GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("vPosition"));
 
            GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(vertdata.Length * Vector3.SizeInBytes), vertdata, BufferUsageHint.StaticDraw);
            GL.VertexAttribPointer(shaders[activeShader].GetAttribute("vPosition"), 3, VertexAttribPointerType.Float, false, 0, 0);
 
            if (shaders[activeShader].GetAttribute("vColor") != -1)
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("vColor"));
                GL.BufferData<Vector3>(BufferTarget.ArrayBuffer, (IntPtr)(coldata.Length * Vector3.SizeInBytes), coldata, BufferUsageHint.StaticDraw);
                GL.VertexAttribPointer(shaders[activeShader].GetAttribute("vColor"), 3, VertexAttribPointerType.Float, true, 0, 0);
            }
            
            
            
            if (shaders[activeShader].GetAttribute("texcoord") != -1)
            {
                GL.BindBuffer(BufferTarget.ArrayBuffer, shaders[activeShader].GetBuffer("texcoord"));
                GL.BufferData<Vector2>(BufferTarget.ArrayBuffer, (IntPtr)(texcoorddata.Length * Vector2.SizeInBytes), texcoorddata, BufferUsageHint.StaticDraw);
                GL.VertexAttribPointer(shaders[activeShader].GetAttribute("texcoord"), 2, VertexAttribPointerType.Float, true, 0, 0);
            }
            
          //   objects[0].Position = new Vector3(0.3f, -0.5f + (float) Math.Sin(time), -3.0f);
            objects[0].Rotation = new Vector3(0.55f * time, 0.25f * time, 0);
            objects[0].Scale = new Vector3(1, 1, 1);
 
            objects[1].Position = new Vector3(-5f, 0.5f + (float)Math.Cos(time), -2.0f);
            objects[1].Rotation = new Vector3(-0.25f * time, -0.35f * time, 0);
            objects[1].Scale = new Vector3(2, 1, 2);
 
            foreach (Volume v in objects)
            {
                v.CalculateModelMatrix();
                    
                v.ViewProjectionMatrix = cam.GetViewMatrix() * Matrix4.CreatePerspectiveFieldOfView(1.3f, ClientSize.Width / (float)ClientSize.Height, 1.0f, 40.0f);
                v.ModelViewProjectionMatrix = v.ModelMatrix * v.ViewProjectionMatrix;
            }
            
            //GL.UniformMatrix4(uniform_mview, false, ref mviewdata[0]);
              
            GL.UseProgram(shaders[activeShader].ProgramID);
 
 
 
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
            
              GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo_elements);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indicedata.Length * sizeof(int)), indicedata, BufferUsageHint.StaticDraw);

        }
        
        protected override void OnResize(EventArgs e)
        {
 
            base.OnResize(e);
 
            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
 
            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
 
            GL.MatrixMode(MatrixMode.Projection);
 
            GL.LoadMatrix(ref projection);
        }
        
        void loadShader(String filename,ShaderType type, int program, out int address)
        {
            address = GL.CreateShader(type);
            try{
            using (StreamReader sr = new StreamReader(filename))
            {
                GL.ShaderSource(address, sr.ReadToEnd());
            }
            }
            catch (Exception ex){
                
                Console.WriteLine("error loading shader : " + ex);
            }
            GL.CompileShader(address);
            GL.AttachShader(program, address);
            Console.WriteLine(GL.GetShaderInfoLog(address));
        }
        
            ///
    
            ///This function will load an image as a bitmap, 
            /// and then store the data of it in the graphics 
            /// card's memory. It returns an int, the address 
            /// of the texture so that we can retrieve the data 
            /// when we want to draw the texture.
            int loadImage(Bitmap image){
                int texID = GL.GenTexture();
 
                GL.BindTexture(TextureTarget.Texture2D, texID);
                BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
                    ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
             
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
                    OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
             
                image.UnlockBits(data);
             
                GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
             
                return texID;
        }
        
        
        int loadImage(string filename)
        {
            try
            {
                Bitmap file = new Bitmap(filename);
                return loadImage(file);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                return -1;
            }
        }
    }
}

你可以在图片中看到我对项目的所有参考

错误很简单。属性 TextureID 存在两次。拳头声明在class Volume:

public abstract class Volume
{
   // [...]

   public int TextureID;

   // [...]
}

然后在 class TexturedCube 中声明了一个同名属性,它(间接)派生​​自 Volume:

public class TexturedCube : Cube 
{
    // [...]

    public int TextureID;

    // [...]
}

因此第二个属性覆盖了第一个。从 class TexturedCube:

中删除属性


顺便说一句,这同样适用于 IsTexturedTextureCoordsCount 属性。