GL.BindTexture表现得很奇怪

时间:2015-12-25 20:56:44

标签: c# opengl opentk

我在敲了近3天之后就遇到了一件奇怪的事情。

我基本上试图创建一个地图应用程序,实际上首先将地图纹理绘制到OpenTK.GLControl,然后创建几个"点"在此地图上表示实体,然后最后打印每个点旁边的实体名称。

我终于设法做到了这一点,请看image here

以下是实现此目的的绘画方法:

    private void glControl_Paint(object sender, PaintEventArgs e)
    {
        if (!glControlLoaded)
            return;

        GL.Clear(ClearBufferMask.ColorBufferBit);

        if (currentMapImage != null)
        {
            GL.BindTexture(TextureTarget.Texture2D, mapTextureId);

            GL.Enable(EnableCap.Texture2D);
            GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Decal);
            GL.Begin(PrimitiveType.Quads);
            GL.TexCoord2(currentZoomRectangle.Left, currentZoomRectangle.Top); GL.Vertex3(0, 0, 0.0f);
            GL.TexCoord2(currentZoomRectangle.Right, currentZoomRectangle.Top); GL.Vertex3(glControl.Width, 0, 0.0f);
            GL.TexCoord2(currentZoomRectangle.Right, currentZoomRectangle.Bottom); GL.Vertex3(glControl.Width, glControl.Height, 0.0f);
            GL.TexCoord2(currentZoomRectangle.Left, currentZoomRectangle.Bottom); GL.Vertex3(0, glControl.Height, 0.0f);
            GL.End();
            GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate);
            GL.Disable(EnableCap.Texture2D);
        }

        GL.Begin(PrimitiveType.Points);
        foreach (Entity entity in entityList)
        {
            if (filtersForm.getShowEntity(entity.Name))
            {
                if (filtersForm.getShowDot(entity.TypeConverted))
                {
                    Color dotColor = settingsForm.getDotColor(entity.TypeConverted);
                    GL.Color3(dotColor);

                    PointF? dotGlControlPos = getGlControlPos(entity.ZeroToOnePosition);
                    if (dotGlControlPos != null)
                    {
                        GL.Vertex3(dotGlControlPos.Value.X, dotGlControlPos.Value.Y, 0.0);
                    }
                }
            }
        }
        GL.End();

        using (Graphics gfx = Graphics.FromImage(textBitmap))
        {
            gfx.Clear(Color.Transparent);
            gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

            foreach (Entity entity in entityList)
            {
                if (filtersForm.getShowEntity(entity.Name))
                {
                    if (filtersForm.getShowDot(entity.TypeConverted))
                    {
                        if (filtersForm.getShowName(entity.TypeConverted))
                        {
                            PointF? nameGlControlPos = getGlControlPos(entity.ZeroToOnePosition);
                            if (nameGlControlPos != null)
                            {
                                Color nameColor = nameColor = settingsForm.getNameColor(entity.TypeConverted);
                                nameGlControlPos = new PointF(nameGlControlPos.Value.X + 5, nameGlControlPos.Value.Y - settingsForm.EntityFontHeightInPixels - 5);
                                gfx.DrawString(entity.Name, settingsForm.EntityFont, new SolidBrush(nameColor), nameGlControlPos.Value);
                            }
                        }
                    }
                }
            }
        }

        GL.BindTexture(TextureTarget.Texture2D, textTextureId);

        System.Drawing.Imaging.BitmapData data = textBitmap.LockBits(new Rectangle(0, 0, textBitmap.Width, textBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, glControl.Width, glControl.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
        textBitmap.UnlockBits(data);

        GL.Enable(EnableCap.Texture2D);
        GL.Enable(EnableCap.Blend);
        GL.BlendFunc(BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha);

        GL.Begin(PrimitiveType.Quads);
        GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0, 0, -0.1f);
        GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(glControl.Width, 0, -0.1f);
        GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(glControl.Width, glControl.Height, -0.1f);
        GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0, glControl.Height, -0.1f);
        GL.End();

        GL.BindTexture(TextureTarget.Texture2D, mapTextureId);

        glControl.SwapBuffers();
    }

现在有趣的是,如果我删除最后一个GL.BindTexture() - 调用上面的方法(就是glControl.SwapBuffers()之前的那个 - 调用),就像这样:

private void glControl_Paint(object sender, PaintEventArgs e)
{
    ...
    ...
    ...

    //GL.BindTexture(TextureTarget.Texture2D, mapTextureId);

    glControl.SwapBuffers();
}

我得到this as a result

我不清楚我是如何提出首先添加该调用的想法的。它对我没有任何意义......我想我实际上只需要调用一次(在我实际绘制地图纹理的开始时)。

所以我想我的问题是,有谁能告诉我这里发生了什么?

1 个答案:

答案 0 :(得分:0)

在您尝试渲染地图之前,您没有绑定mapTextureId

请注意,当您执行GL.BindTexture(TextureTarget.Texture2D, textTextureId);时,这意味着所有进一步渲染将使用该纹理。好吧,直到下一个bind命令。你刚才注释掉了。

你第一次创建纹理时唯一的另一个绑定mapTextureId的时间;除了你注释掉的那一行之外,你再也没有绑定它了。

OpenGL中的状态不会因为您忘记而改变。您的代码工作的原因是因为您注释掉了该行。通过绑定纹理,您可以说任何未来的渲染命令都将使用该纹理。即使那些未来的渲染命令发生在下一帧

基本上,你的代码是偶然的。

你应该做的是绑定纹理,渲染你想要用该纹理渲染的东西,然后取消绑定纹理(通过绑定0)。