opentk несколько текстур на кубе не работают

Так что в моей программе есть функция для рисования куба. Я использую C# с Monodevelop на Linux. Вот функция:

private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
{
    GL.PushMatrix();

    GL.Translate(x, y, z);
    GL.Rotate(ori, 0, 1, 0);

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);

    GL.Begin(BeginMode.Quads);

    GL.Color3(Color.White);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    //Top
    //GL.ActiveTexture(TextureUnit.Texture0);
    GL.BindTexture(TextureTarget.Texture2D, TopTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    //Bottom
    GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);

    GL.End();
    GL.PopMatrix();

return 6;   // Return number of faces drawn
}

Как вы уже догадались, эта функция рисует куб с положением x, y, z, направление oriи SideTexture по бокам, а также TopTexture и BottomTexture сверху и снизу. Теперь проблема в том, что он рисует куб только с одной текстурой! боковая текстура. Я не знаю в чем проблема. Должен ли я открепить текстуры? все остальное в коде работает отлично, как я уже говорил, что это связано с текстурами. Любая помощь приветствуется.

2 ответа

Решение

Вы не можете позвонить GL.BindTexture() в пределах начальной области. Из документации:

Между glBegin и glEnd можно использовать только подмножество команд GL. Это команды glVertex, glColor, glSecondaryColor, glIndex, glNormal, glFogCoord, glTexCoord, glMultiTexCoord, glVertexAttrib, glEvalCoord, glEvalPoint, glArrayElement, glMaterial и glEdgeFlag. Также допустимо использовать glCallList или glCallLists для выполнения списков отображения, которые включают только предыдущие команды. Если между glBegin и glEnd выполняется какая-либо другая команда GL, устанавливается флаг ошибки, и команда игнорируется.

Если вы проверите GL.GetError() вы увидите, что вы получаете ошибку InvalidOperation. по факту GL.GetError() должна быть вашей первой реакцией, когда что-то не рендерится, как ожидается в OpenGL

Решение:

private int DrawCube(float x, float y, float z, float ori, int SideTexture, int TopTexture, int BottomTexture)
{
    GL.PushMatrix();

    GL.Translate(x, y, z);
    GL.Rotate(ori, 0, 1, 0);

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.Begin(BeginMode.Quads);
    GL.Color3(Color.White);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.End();

    //Top
    GL.BindTexture(TextureTarget.Texture2D, TopTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
    GL.End();

    //Bottom
    GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
    GL.End();

    GL.BindTexture(TextureTarget.Texture2D, SideTexture);
    GL.Begin(BeginMode.Quads);
    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);

    GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
    GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
    GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
    GL.End();

    GL.PopMatrix();

    return 6;   // Return number of faces drawn
}

О да, и для тех, кому это может быть полезно, я использовал неправильные стороны с текстурами. Текстура top была прикреплена к нижней части и т. Д. Вот рабочий код. Код для загрузки текстуры из пути:

static public int UploadTexture(string pathname)
{
    // Create a new OpenGL texture object
    int id = GL.GenTexture();

    // Select the new texture
    GL.BindTexture(TextureTarget.Texture2D, id);

    // Load the image
    Bitmap bmp = new Bitmap(pathname);

    // Lock image data to allow direct access
    BitmapData bmp_data = bmp.LockBits(
            new Rectangle(0, 0, bmp.Width, bmp.Height),
            System.Drawing.Imaging.ImageLockMode.ReadOnly,
            System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    // Import the image data into the OpenGL texture
    GL.TexImage2D(TextureTarget.Texture2D,
                  0,
                  PixelInternalFormat.Rgba,
                  bmp_data.Width,
                  bmp_data.Height,
                  0,
                  OpenTK.Graphics.OpenGL.PixelFormat.Bgra,
                  OpenTK.Graphics.OpenGL.PixelType.UnsignedByte,
                  bmp_data.Scan0);

    // Unlock the image data
    bmp.UnlockBits(bmp_data);

    // Configure minification and magnification filters
    GL.TexParameter(TextureTarget.Texture2D,
            TextureParameterName.TextureMinFilter,
            (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D,
            TextureParameterName.TextureMagFilter,
            (int)TextureMagFilter.Linear);

    // Return the OpenGL object ID for use
    return id;
}

и код для рисования куба с текстурами

private int DrawCube(float x, float y, float z, float ori, int TopTexture, int BottomTexture, params int[] SideTextures)
        {
            GL.PushMatrix();

            GL.Translate(x, y, z);
            GL.Rotate(ori, 0, 1, 0);

            GL.BindTexture(TextureTarget.Texture2D, SideTextures[0]);
            GL.Begin(BeginMode.Quads);
            GL.Color3(Color.White);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
            GL.End();

            //Top
            GL.BindTexture(TextureTarget.Texture2D, SideTextures[1]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, 0);
            GL.End();

            //Bottom
            GL.BindTexture(TextureTarget.Texture2D, BottomTexture);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 0, 0);
            GL.End();

            GL.BindTexture(TextureTarget.Texture2D, SideTextures[2]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, 0);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.End();
            GL.BindTexture(TextureTarget.Texture2D, TopTexture);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(0, 20, 0);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(20, 20, 0);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.End();
            GL.BindTexture(TextureTarget.Texture2D, SideTextures[3]);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0.0f, 1.0f - 0.0f); GL.Vertex3(20, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 0.0f); GL.Vertex3(0, 0, -20);
            GL.TexCoord2(1.0f, 1.0f - 1.0f); GL.Vertex3(0, 20, -20);
            GL.TexCoord2(0.0f, 1.0f - 1.0f); GL.Vertex3(20, 20, -20);
            GL.End();

            GL.PopMatrix();

            return 6;   // Return number of faces drawn
        }
        protected override void OnResize(EventArgs e)
        {
            int w = Width;
            int h = Height;
            float aspect = 1;

            // Calculate aspect ratio, checking for divide by zero
            if (h > 0)
            {
                aspect = (float)w / (float)h;
            }

            // Initialise the projection view matrix
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();

            // Setup a perspective view
            float FOVradians = MathHelper.DegreesToRadians(45);
            Matrix4 perspective = Matrix4.CreatePerspectiveFieldOfView(FOVradians, aspect, 1, 4000);
            GL.MultMatrix(ref perspective);

            // Set the viewport to the whole window
            GL.Viewport(0, 0, w, h);
        }

и ссылки, которые вы должны будете использовать:

using System;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics.OpenGL;

РЕДАКТИРОВАТЬ: В более новой версии OpenTK я считаю, что вам придется использовать PrimitiveType.Quad вместо BeginMode.Quad

Другие вопросы по тегам