无法在OpenGL中将大多数图像格式加载为纹理

时间:2013-06-11 00:01:35

标签: c# image opengl bitmap textures

我正在尝试加载各种图像格式,以便在OpenGL中使用alpha混合显示我们公司的软件,但我似乎没有运气。我正在尝试加载这样的位图:

private Bitmap LoadBitmap(string filename)
{
    Bitmap original = new Bitmap(filename);
    Bitmap toReturn = new Bitmap(original.Width, original.Height, PixelFormat.Format24bppRgb);
    using (Graphics gr = Graphics.FromImage(toReturn))
    {
        gr.DrawImage(original, new Rectangle(0, 0, toReturn.Width, toReturn.Height));
    }
    original.Dispose();
    return toReturn;
}

将其加载到这样的纹理中:

private uint[] GetTexture(Bitmap convertToTexture)
{
    // Setup return value
    uint[] toReturn = null;

    // Make sure the device and the bitmap exists
    if (convertToTexture != null)
    {
        // Dispose the imagery first
        DisposeTexture();
        mImageryTexture = new uint[1];

        // Setup the bitmap
        Rectangle rect = new Rectangle(Point.Empty, convertToTexture.Size);
        BitmapData bitmapdata = convertToTexture.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

        // Bind the texture
        glGenTextures(1, mImageryTexture);
        glBindTexture(GL_TEXTURE_2D, mImageryTexture[0]);
        glTexImage2D(GL_TEXTURE_2D, 0, (int)GL_RGB8, convertToTexture.Width, convertToTexture.Height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, bitmapdata.Scan0);

        // Linear Filtering
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        // Clamp
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

        // Release the bitmap
        convertToTexture.UnlockBits(bitmapdata);

        // Set the return value to this imagery
        toReturn = mImageryTexture;
    }
    return toReturn;
}

使用这样的纹理:

public bool DrawGLScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    // Test bitmap
    Rectangle rect = new Rectangle();
    rect.Size = testBitmap.Size;
    RenderQuad(testBitmap, rect);
    RenderLines(rect);
    rect.X += rect.Width;

    // Test JPEG
    rect.Size = testJpeg.Size;
    RenderQuad(testJpeg, rect);
    RenderLines(rect);
    rect.X += rect.Width;

    // Test PNG
    rect.Size = testPng.Size;
    RenderQuad(testPng, rect);
    RenderLines(rect);
    rect.X += rect.Width;

    // Test GIF
    rect.Size = testGif.Size;
    RenderQuad(testGif, rect);
    RenderLines(rect);
    return true;
}

private void RenderQuad(Bitmap image, Rectangle rect)
{
    uint[] imageryTexture = GetTexture(image);

    // Color all the vertices white with transparency
    glEnable(GL_TEXTURE_2D);
    glColor4ub(255, 255, 255, 255);

    ///////////////////////////////////////////////////
    // Draw the image of the area.
    ///////////////////////////////////////////////////

    // Fill the path with the background transparent color.
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glBindTexture(GL_TEXTURE_2D, imageryTexture[0]);

    // Building a quad of the image
    glBegin(GL_QUADS);

    // top left of texture
    glTexCoord2f(0, 1);
    glVertex2i(rect.Left, rect.Top);

    // top right of texture
    glTexCoord2f(1, 1);
    glVertex2i(rect.Right, rect.Top);

    // bottom right of texture
    glTexCoord2f(1, 0);
    glVertex2i(rect.Right, rect.Bottom);

    // bottom left of texture
    glTexCoord2f(0, 0);
    glVertex2i(rect.Left, rect.Bottom);

    glEnd();
}

private void RenderLines(Rectangle rect)
{
    // Fill the path with the background transparent color.
    // Color all the vertices transparent gray
    Color LineColor = Color.Tomato;
    glColor4ub(LineColor.R, LineColor.G, LineColor.B, 255);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // Building a quad of the image
    glBegin(GL_QUADS);

    // top left of texture
    glVertex2i(rect.Left, rect.Top);

    // top right of texture
    glVertex2i(rect.Right, rect.Top);

    // bottom right of texture
    glVertex2i(rect.Right, rect.Bottom);

    // bottom left of texture
    glVertex2i(rect.Left, rect.Bottom);

    glEnd();
}

我做错了什么?我可以加载一些位图文件,但不能加载其他文件。 PNG,JPEG和GIF根本不起作用。我得到的只是白色方块(来自顶点颜色)。

以下是完整代码。我使用NeHe的第2课代码作为此代码的基础(因为我无法完整地发布公司软件代码):

public class OpenGLForm : Form
{
    #region Member Variables

    private const string AbsolutePath = @"C:\<path-to-images>\";

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;
    private Bitmap testBitmap = null;
    private Bitmap testJpeg = null;
    private Bitmap testPng = null;
    private Bitmap testGif = null;
    private uint[] mImageryTexture = null;

    private static uint _hwnd    = 0;
    private static uint _hDC    = 0;
    private static uint _hRC    = 0;

    private bool _appActive = true;
    private bool _done = true;

    public bool Done
    {
        get
        {
            return _done;
        }
        set
        {
            _done = value;
        }
    }

    #endregion

    // Lots of OpenGL function and constant declaration here

    #region Win32 Interop

    // Constant values were found in the "WinUser.h" header file.
    public const int WM_ACTIVATEAPP = 0x001C;
    public const int WA_ACTIVE = 1;
    public const int WA_CLICKACTIVE = 2;
    public const int CDS_FULLSCREEN = 0x00000004;    // Flag for ChangeDisplaySettings
    public const int DISP_CHANGE_SUCCESSFUL = 0;            // Return value for ChangeDisplaySettings

    // Constant values were found in the "WinGDI.h" header file.
    public const int CCHDEVICENAME = 32;            // size of a device name string
    public const int CCHFORMNAME = 32;            // size of a form name string
    public const int DM_BITSPERPEL = 0x40000;
    public const int DM_PELSWIDTH = 0x80000;
    public const int DM_PELSHEIGHT = 0x100000;
    public const int BITSPIXEL = 12;            // number of bits per pixel
    public const uint PFD_DOUBLEBUFFER = 0x00000001;    // PIXELFORMATDESCRIPTOR flag
    public const uint PFD_DRAW_TO_WINDOW = 0x00000004;    // PIXELFORMATDESCRIPTOR flag
    public const uint PFD_SUPPORT_OPENGL = 0x00000020;    // PIXELFORMATDESCRIPTOR flag
    public const uint PFD_TYPE_RGBA = 0;            // pixel type
    public const uint PFD_MAIN_PLANE = 0;            // layer type

    [StructLayout(LayoutKind.Sequential)]
    public struct PIXELFORMATDESCRIPTOR
    {
        public ushort nSize;
        public ushort nVersion;
        public uint dwFlags;
        public byte iPixelType;
        public byte cColorBits;
        public byte cRedBits;
        public byte cRedShift;
        public byte cGreenBits;
        public byte cGreenShift;
        public byte cBlueBits;
        public byte cBlueShift;
        public byte cAlphaBits;
        public byte cAlphaShift;
        public byte cAccumBits;
        public byte cAccumRedBits;
        public byte cAccumGreenBits;
        public byte cAccumBlueBits;
        public byte cAccumAlphaBits;
        public byte cDepthBits;
        public byte cStencilBits;
        public byte cAuxBuffers;
        public byte iLayerType;
        public byte bReserved;
        public uint dwLayerMask;
        public uint dwVisibleMask;
        public uint dwDamageMask;
    }

    // by marking the structure with CharSet.Auto, the structure will get marshaled as Unicode characters
    // on Unicode platforms, if not the name fields would always get marshaled as arrays of ANSI characters
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class DEVMODE
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHDEVICENAME)]
        public char[] dmDeviceName;
        public short dmSpecVersion;
        public short dmDriverVersion;
        public short dmSize;
        public short dmDriverExtra;
        public int dmFields;
        public DEVMODE_UNION u;
        public short dmColor;
        public short dmDuplex;
        public short dmYResolution;
        public short dmTTOption;
        public short dmCollate;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = CCHFORMNAME)]
        public char[] dmFormName;
        public short dmLogPixels;
        public int dmBitsPerPel;
        public int dmPelsWidth;
        public int dmPelsHeight;
        public int dmDisplayFlagsOrdmNup;        // union of dmDisplayFlags and dmNup
        public int dmDisplayFrequency;
        public int dmICMMethod;
        public int dmICMIntent;
        public int dmMediaType;
        public int dmDitherType;
        public int dmReserved1;
        public int dmReserved2;
        public int dmPanningWidth;
        public int dmPanningHeight;
    }

    // modeling a union in C#, each possible struct data type starts at FieldOffset 0
    [StructLayout(LayoutKind.Explicit)]
    public struct DEVMODE_UNION
    {
        [FieldOffset(0)]
        public short dmOrientation;
        [FieldOffset(2)]
        public short dmPaperSize;
        [FieldOffset(4)]
        public short dmPaperLength;
        [FieldOffset(6)]
        public short dmPaperWidth;
        [FieldOffset(8)]
        public short dmScale;
        [FieldOffset(10)]
        public short dmCopies;
        [FieldOffset(12)]
        public short dmDefaultSource;
        [FieldOffset(14)]
        public short dmPrintQuality;

        [FieldOffset(0)]
        public int dmPosition_x;
        [FieldOffset(4)]
        public int dmPosition_y;

        [FieldOffset(0)]
        public int dmDisplayOrientation;

        [FieldOffset(0)]
        public int dmDisplayFixedOutput;
    }

    #endregion

    #region OpenGLSetup

    private bool SetupPixelFormat(ref uint hdc)
    {
        PIXELFORMATDESCRIPTOR    pfd    = new PIXELFORMATDESCRIPTOR();

        ushort    pfdSize = (ushort)Marshal.SizeOf(typeof(PIXELFORMATDESCRIPTOR));        // sizeof(PIXELFORMATDESCRIPTOR)

        pfd.nSize = pfdSize;                                                             // size of pfd
        pfd.nVersion = 1;                                                                // version number
        pfd.dwFlags = (PFD_SUPPORT_OPENGL |  PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER);    // flags
        pfd.iPixelType = (byte)PFD_TYPE_RGBA;                                            // RGBA type
        pfd.cColorBits = (byte)GetDeviceCaps(hdc, BITSPIXEL);                            // color depth
        pfd.cRedBits = 0;                                                                // color bits ignored
        pfd.cRedShift = 0;
        pfd.cGreenBits = 0;
        pfd.cGreenShift = 0;
        pfd.cBlueBits = 0;
        pfd.cBlueShift = 0;
        pfd.cAlphaBits = 0;                                                                // no alpha buffer
        pfd.cAlphaShift = 0;                                                            // shift bit ignored
        pfd.cAccumBits = 0;                                                                // no accumulation buffer 
        pfd.cAccumRedBits = 0;                                                            // accum bits ignored
        pfd.cAccumGreenBits = 0;
        pfd.cAccumBlueBits = 0;
        pfd.cAccumAlphaBits = 0;
        pfd.cDepthBits = 32;                                                            // 32-bit z-buffer
        pfd.cStencilBits = 0;                                                            // no stencil buffer
        pfd.cAuxBuffers = 0;                                                            // no auxiliary buffer
        pfd.iLayerType = (byte)PFD_MAIN_PLANE;                                            // main layer
        pfd.bReserved = 0;                                                                // reserved
        pfd.dwLayerMask = 0;                                                            // layer masks ignored
        pfd.dwVisibleMask = 0;
        pfd.dwDamageMask = 0;

        int pixelformat = ChoosePixelFormat(hdc, ref pfd);
        if (pixelformat == 0)                                                            // Did Windows Find A Matching Pixel Format?
        {
            MessageBox.Show("Can't Find A Suitable PixelFormat.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }

        if (SetPixelFormat(hdc, pixelformat, ref pfd) == 0)                                // Are We Able To Set The Pixel Format?
        {
            MessageBox.Show("Can't Set The PixelFormat.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
        return true;
    }

    private bool InitGL()                                            // All Setup For OpenGL Goes Here
    {
        glShadeModel(GL_SMOOTH);                                    // Enable Smooth Shading
        glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                        // Black Background
        glClearDepth(1.0f);                                            // Depth Buffer Setup

        // Add alpha blending support
        glDepthFunc(GL_LEQUAL);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        return true;                                                // Initialization Went OK
    }

    public bool SetupRenderingContext()
    {
        if (!CreateGLWindow())
        {
            return false;                            // initialization failed, quit
        }

        _hwnd = (uint)((this.Handle).ToInt32());
        _hDC = GetDC(_hwnd);
        if (_hDC == 0)
        {
            MessageBox.Show("Can't Create A GL Device Context", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }

        // not doing the following wglSwapBuffers() on the DC will result in a failure to subsequently create the RC
        wglSwapBuffers(_hDC);

        if (!SetupPixelFormat(ref _hDC))
        {
            return false;
        }

        // create the rendering context and make it current
        _hRC = wglCreateContext(_hDC);
        if (_hRC == 0)                                // Are We Able To Get A Rendering Context?
        {
            MessageBox.Show("Can't Create A GL Rendering Context.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }
        if (!wglMakeCurrent(_hDC, _hRC))            // Try To Activate The Rendering Context
        {
            MessageBox.Show("Can't Activate The GL Rendering Context.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return false;
        }

        OpenGLForm_Resize(this, new EventArgs());    // Set up the perspective GL screen

        return InitGL();                            // Initialize Our Newly Created GL Window
    }

    #endregion
    #region FormSetup

    private bool CreateGLWindow()
    {
        Resize += new EventHandler(OpenGLForm_Resize);

        TopMost = false;
        WindowState = System.Windows.Forms.FormWindowState.Normal;
        FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;

        // The cursor is displayed only if the display count is greater than or equal to 0
        do
        {
        }while (ShowCursor(true) < 0);

        return true;
    }

    #endregion
    #region Constructor/Destructor

    public OpenGLForm()
    {
        //
        // Required for Windows Form Designer support
        //
        InitializeComponent();
        testBitmap = LoadBitmap(AbsolutePath + "bitmap.bmp");
        testJpeg = LoadBitmap(AbsolutePath + "jpeg.jpg");
        testPng = LoadBitmap(AbsolutePath + "png.png");
        testGif = LoadBitmap(AbsolutePath + "gif.gif");
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (components != null) 
            {
                components.Dispose();
            }

            if (_hRC != 0)                                        // Do We Have A Rendering Context?
            {
                if (!wglMakeCurrent(0, 0))                        // Are We Able To Release The DC And RC Contexts?
                {
                    MessageBox.Show("Release Of DC And RC Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

                if (!wglDeleteContext(_hRC))                    // Are We Able To Delete The RC?
                {
                    MessageBox.Show("Release Rendering Context Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            if (_hDC != 0 && ReleaseDC(_hwnd, _hDC) == 0)        // Are We Able To Release The DC
            {
                MessageBox.Show("Release Device Context Failed.", "Shutdown Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        base.Dispose(disposing);
    }

    private Bitmap LoadBitmap(string filename)
    {
        Bitmap original = new Bitmap(filename);
        Bitmap toReturn = new Bitmap(original.Width, original.Height, PixelFormat.Format24bppRgb);
        using (Graphics gr = Graphics.FromImage(toReturn))
        {
            gr.DrawImage(original, new Rectangle(0, 0, toReturn.Width, toReturn.Height));
        }
        original.Dispose();
        return toReturn;
    }

    #endregion
    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        // 
        // OpenGLForm
        // 
        this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
        this.ClientSize = new System.Drawing.Size(632, 453);
        this.KeyPreview = true;
        this.Name = "OpenGLForm";
        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        this.Text = "\"NeHe\'s First Polygon Tutorial\"";
        this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.OpenGLForm_KeyUp);

    }

    #endregion
    #region Events

    protected override void WndProc(ref System.Windows.Forms.Message m) 
    {
        // Listen for operating system messages.
        switch (m.Msg)
        {
            // The WM_ACTIVATEAPP message occurs when the application
            // becomes the active application or becomes inactive.
            case WM_ACTIVATEAPP:
            {
                // The WParam value identifies what is occurring.
                _appActive = ((int)m.WParam == WA_ACTIVE || (int)m.WParam == WA_CLICKACTIVE);

                // Invalidate to get new scene painted.
                Invalidate();
                break;
            }
            default:
            {
                break;
            }
        }
        base.WndProc(ref m);
    }

    /*!
        This will stop the display from flickering on Paint event
    */
    protected override void OnPaintBackground(PaintEventArgs e)
    {
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // make sure the app is active
        if (_appActive)
        {
            DrawGLScene();
            wglSwapBuffers(_hDC);
            Invalidate();
        }
    }

    private void OpenGLForm_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Escape:
            {
                Close();
                break;
            }
            default:
            {
                break;
            }
        }
    }

    private void OpenGLForm_Resize(object sender, EventArgs e)        // Resize And Initialize The GL Window
    {
        int width = ClientRectangle.Width;
        int height = ClientRectangle.Height;

        if (height == 0)                                            // Prevent A Divide By Zero By
        {
            height = 1;                                                // Making Height Equal One
        }

        // Switch to projection mode
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        // Change to ortho-graphic camera, with top left as (0, 0) coordinate,
        // and bottom right as the control size
        gluOrtho2D(0, ClientRectangle.Width, ClientRectangle.Height, 0);
        glViewport(0, 0, ClientRectangle.Width, ClientRectangle.Height);

        // Switch back to model view
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();                                            // Reset The Modelview Matrix
    }

    #endregion

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main() 
    {
        while (true)
        {
            OpenGLForm form = new OpenGLForm();                // create the form

            if (!form.SetupRenderingContext())                // setup form and OpenGL
            {
                break;                                        // initialization failed, quit
            }

            Application.Run(form);

            if (form.Done)                                    // Was There A Quit Received?
            {
                form.DisposeTexture();
                break;
            }
        }
    }

    public bool DrawGLScene()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        // Test bitmap
        Rectangle rect = new Rectangle();
        rect.Size = testBitmap.Size;
        RenderQuad(testBitmap, rect);
        RenderLines(rect);
        rect.X += rect.Width;

        // Test JPEG
        rect.Size = testJpeg.Size;
        RenderQuad(testJpeg, rect);
        RenderLines(rect);
        rect.X += rect.Width;

        // Test PNG
        rect.Size = testPng.Size;
        RenderQuad(testPng, rect);
        RenderLines(rect);
        rect.X += rect.Width;

        // Test GIF
        rect.Size = testGif.Size;
        RenderQuad(testGif, rect);
        RenderLines(rect);
        return true;
    }

    private void RenderQuad(Bitmap image, Rectangle rect)
    {
        uint[] imageryTexture = GetTexture(image);

        // Color all the vertices white with transparency
        glEnable(GL_TEXTURE_2D);
        glColor4ub(255, 255, 255, 255);

        ///////////////////////////////////////////////////
        // Draw the image of the area.
        ///////////////////////////////////////////////////

        // Fill the path with the background transparent color.
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        glBindTexture(GL_TEXTURE_2D, imageryTexture[0]);

        // Building a quad of the image
        glBegin(GL_QUADS);

        // top left of texture
        glTexCoord2f(0, 1);
        glVertex2i(rect.Left, rect.Top);

        // top right of texture
        glTexCoord2f(1, 1);
        glVertex2i(rect.Right, rect.Top);

        // bottom right of texture
        glTexCoord2f(1, 0);
        glVertex2i(rect.Right, rect.Bottom);

        // bottom left of texture
        glTexCoord2f(0, 0);
        glVertex2i(rect.Left, rect.Bottom);

        glEnd();
    }

    private void RenderLines(Rectangle rect)
    {
        // Fill the path with the background transparent color.
        // Color all the vertices transparent gray
        Color LineColor = Color.Tomato;
        glColor4ub(LineColor.R, LineColor.G, LineColor.B, 255);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

        // Building a quad of the image
        glBegin(GL_QUADS);

        // top left of texture
        glVertex2i(rect.Left, rect.Top);

        // top right of texture
        glVertex2i(rect.Right, rect.Top);

        // bottom right of texture
        glVertex2i(rect.Right, rect.Bottom);

        // bottom left of texture
        glVertex2i(rect.Left, rect.Bottom);

        glEnd();
    }

    // Creates a texture from a given bitmap.
    private uint[] GetTexture(Bitmap convertToTexture)
    {
        // Setup return value
        uint[] toReturn = null;

        // Make sure the device and the bitmap exists
        if (convertToTexture != null)
        {
            // Dispose the imagery first
            DisposeTexture();
            mImageryTexture = new uint[1];

            // Setup the bitmap
            Rectangle rect = new Rectangle(Point.Empty, convertToTexture.Size);
            BitmapData bitmapdata = convertToTexture.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            // Bind the texture
            glGenTextures(1, mImageryTexture);
            glBindTexture(GL_TEXTURE_2D, mImageryTexture[0]);
            glTexImage2D(GL_TEXTURE_2D, 0, (int)GL_RGB8, convertToTexture.Width, convertToTexture.Height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, bitmapdata.Scan0);

            // Linear Filtering
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

            // Clamp
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

            // Release the bitmap
            convertToTexture.UnlockBits(bitmapdata);

            // Set the return value to this imagery
            toReturn = mImageryTexture;
        }
        return toReturn;
    }

    // Disposes the currently held texture.
    public void DisposeTexture()
    {
        if (mImageryTexture != null)
        {
            glDeleteTextures(1, mImageryTexture);
            mImageryTexture = null;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

事实证明,如果图像尺寸是2的幂,我的代码确实有效。看起来我必须生成尺寸设置为2的幂的更大图像,并更改UV值以删除新添加的尺寸。