我在敲了近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。
我不清楚我是如何提出首先添加该调用的想法的。它对我没有任何意义......我想我实际上只需要调用一次(在我实际绘制地图纹理的开始时)。
所以我想我的问题是,有谁能告诉我这里发生了什么?
答案 0 :(得分:0)
在您尝试渲染地图之前,您没有绑定mapTextureId
。
请注意,当您执行GL.BindTexture(TextureTarget.Texture2D, textTextureId);
时,这意味着所有进一步渲染将使用该纹理。好吧,直到下一个bind命令。你刚才注释掉了。
你第一次创建纹理时唯一的另一个绑定mapTextureId
的时间;除了你注释掉的那一行之外,你再也没有绑定它了。
OpenGL中的状态不会因为您忘记而改变。您的代码工作的原因是因为您注释掉了该行。通过绑定纹理,您可以说任何未来的渲染命令都将使用该纹理。即使那些未来的渲染命令发生在下一帧。
基本上,你的代码是偶然的。
你应该做的是绑定纹理,渲染你想要用该纹理渲染的东西,然后取消绑定纹理(通过绑定0)。