2015-12-25 69 views
0

我已經撞了近3天,現在已經碰到了一件奇怪的事情。GL.BindTexture表演奇怪

我基本上試圖創建一個地圖應用程序,本質上首先繪製地圖紋理到OpenTK.GLControl,然後在這個地圖上創建幾個「點」來表示實體,然後最後打印出實體旁邊的實體名稱每個點。

我終於設法做到了,看到這個image here

這裏是實現這一目標的paint方法:

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

發生了什麼事是您在嘗試渲染地圖之前沒有綁定mapTextureId

看,當你做GL.BindTexture(TextureTarget.Texture2D, textTextureId);,那就意味着所有進一步渲染的都會使用那個紋理。那麼,直到下一個綁定命令。你剛剛註釋掉了。

唯一的其他時間你綁定mapTextureId是當你第一次創建紋理;除了你註釋掉的行外,你再也沒有綁定過它。

OpenGL中的狀態不會因爲您忘記它而改變。你的代碼工作原因是因爲你註釋掉了這一行。通過綁定紋理,你會說任何未來的渲染命令都會使用該紋理。即使那些未來的渲染命令發生在下一幀

基本上,您的代碼意外工作。

你應該做的是綁定紋理,渲染你想渲染的東西與紋理,然後解除綁定紋理(綁定0)。

+0

我確實將地圖貼圖綁定到了每個paint上(參見第10行,包括空行)。順便說一句,「currentMapImage」測試是假的(它從不爲空,甚至在if範圍內都沒有使用)。刪除了。然而,正確的你是關於OpenGL的所有**狀態**。我開始調查,當你把我的思想放在正確的軌道上。原來是另一個函數替換了未綁定它的貼圖紋理,導致它覆蓋了文本紋理(因爲這是Paint-callback的最後綁定紋理)。無論如何,感謝一堆尼科爾。保存了我的第四天! – Greenshoe