2013-02-08 172 views
1

我的問題是用OpenGL渲染文本 - 文本渲染成紋理,然後繪製到四邊形上。麻煩的是,紋理邊緣上的像素被繪製爲部分透明。紋理的內部很好。我使用NEAREST(非)插值計算紋理座標來命中我的紋理元素的中心,設置紋理環繞爲CLAMP_TO_EDGE,並設置投影矩陣將我的頂點放置在視口像素的中心。仍然看到這個問題。不透明的OpenGL紋理有透明邊框

我正在使用他們的紋理實用程序在VTK上工作。這些是用來加載紋理GL調用,用調試器逐句通過決定:

glGenTextures(1, &id); 
glBindTexture(GL_TEXTURE_2D, id); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
// Create and bind pixel buffer object here (not shown, lots of indirection in VTK)... 
glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA, xsize, ysize, 0, format, GL_UNSIGNED_BYTE, 0); 
// Unbind PBO -- also omitted 
glBindTexture(GL_TEXTURE_2D, id); 
glAlphaFunc (GL_GREATER, static_cast<GLclampf>(0)); 
glEnable (GL_ALPHA_TEST); 
// I've also tried doing this here for premultiplied alpha, but it made no difference: 
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 
glMatrixMode(GL_TEXTURE); 
glLoadIdentity(); 

渲染代碼:

float p[2] = ...; // point to render text at 

    int imgDims[2] = ...; // Actual dimensions of image 
    float width = ...; // Width of texture in image 
    float height = ...; // Height of texture in image 

    // Prepare the quad 
    float xmin = p[0]; 
    float xmax = xmin + width - 1; 
    float ymin = p[1]; 
    float ymax = ymin + height - 1; 
    float quad[] = { xmin, ymin, 
        xmax, ymin, 
        xmax, ymax, 
        xmin, ymax }; 

    // Calculate the texture coordinates. 
    float smin = 1.0f/(2.0f * (imgDims[0])); 
    float smax = (2.0 * width - 1.0f)/(2.0f * imgDims[0]); 
    float tmin = 1.0f/(2.0f * imgDims[1]); 
    float tmax = (2.0f * height - 1.0f)/(2.0f * imgDims[1]); 

    float texCoord[] = { smin, tmin, 
         smax, tmin, 
         smax, tmax, 
         smin, tmax }; 

    // Set projection matrix to map object coords to pixel centers 
    // (modelview is identity) 
    GLint vp[4]; 
    glGetIntegerv(GL_VIEWPORT, vp); 
    glMatrixMode(GL_PROJECTION); 
    glPushMatrix(); 
    glLoadIdentity(); 
    float offset = 0.5; 
    glOrtho(offset, vp[2] + offset, 
      offset, vp[3] + offset, 
      -1, 1); 

    // Disable polygon smoothing. Why not, I've tried everything else? 
    glDisable(GL_POLYGON_SMOOTH); 

    // Draw the quad 
    glColor4ub(255, 255, 255, 255); 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
    glVertexPointer(2, GL_FLOAT, 0, points); 
    glTexCoordPointer(2, GL_FLOAT, 0, texCoord); 
    glDrawArrays(GL_QUADS, 0, 4); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisableClientState(GL_VERTEX_ARRAY); 

    // Restore projection matrix 
    glMatrixMode(GL_PROJECTION); 
    glPopMatrix(); 

出於調試目的,我已經覆蓋了最texels帶有紅色,下一個帶有綠色的texels內層(否則很難看到大部分白色文本圖像中發生了什麼)。

我使用gdeBugger檢查了內存中的紋理,它看起來和預期的一樣 - 紋理區域周圍的明亮的紅色和綠色邊框(額外的空白區域是填充以使其大小爲2的冪)。供參考:

Good pixels!

這裏的最終渲染圖像的樣子(放大20倍 - 黑色像素是被下調試邊框呈現的文本的遺蹟)。淡紅色的邊框,但仍然是一個大膽的綠色的內邊框:

Bad pixels!

所以它只是受影響的像素的外緣。我不確定是混色還是阿爾法混合,這是搞砸的事情,我不知所措。我注意到,角落像素是邊緣像素的兩倍蒼白,也許這是重要的......也許有人在這裏可以發現錯誤?

+0

如果某物顯示爲「透明」,則必須是因爲混合模式。那麼你在用什麼混合模式? – 2013-02-08 21:27:05

+2

另外,你說你正在使用CLAMP_TO_EDGE等等,但你不顯示代碼。你確定你設置正確嗎? – 2013-02-08 21:28:18

+0

我正在使用VTK並使用它們的紋理類,所以我省略了大部分。我回去完成紋理初始化,並將GL調用添加到帖子中。我現在省略的唯一部分是PBO的初始化,這不應該成爲一個問題,因爲數據正在上傳到圖形內存而沒有問題(如gDEBugger截圖所證明的那樣)。 – dlonie 2013-02-08 22:32:10

回答

0

可能是一個「像素完美」的問題。 OpenGL將一行的中心定義爲光柵化成像素的點。中間是1點的整數和未來之間正好一半的方式...獲取像素(X,Y),以顯示「像素完美」 ...修理你的座標是:

x=(int)x+0.5f; // x is a float.. makes 0.0 into 0.5, 16.343 into 16.5, etc. 
y=(int)y+0.5f; 

這可能是什麼正在搞混合。我在紋理調製方面遇到了同樣的問題......在底部和右邊緣有一個稍微暗淡的線條或一系列像素。

0

好的,我在過去的幾天裏一直在努力。有幾個想法根本不起作用。唯一有效的就是承認這個「完美像素」存在並試圖欺騙它。不好,我不能投票給你的答案宇宙培根。但是,即使它看起來不錯,你的回答也會在遊戲等特殊程序中破壞一切。我的答案是 - 改進你的。

這裏的解決方案:

第一步:請繪製紋理,你需要和只使用它繪製的方法。並將0.5f添加到每個座標。看:

public void render(Texture tex,float x1,float y1,float x2,float y2) 
{ 
    tex.bind(); 
    GL11.glBegin(GL11.GL_QUADS); 
    GL11.glTexCoord2f(0,0); 
    GL11.glVertex2f(x1+0.5f,y1+0.5f); 
    GL11.glTexCoord2f(1,0); 
    GL11.glVertex2f(x2+0.5f,y1+0.5f); 
    GL11.glTexCoord2f(1,1); 
    GL11.glVertex2f(x2+0.5f,y2+0.5f); 
    GL11.glTexCoord2f(0,1); 
    GL11.glVertex2f(x1+0.5f,y2+0.5f); 
    GL11.glEnd(); 
} 

第二步:如果你打算使用「的glTranslatef(somethin1,somethin2,0)」這將是很好使,克服「Translatef」並沒有讓攝影機繼續前進的方法分數距離。導致相機移動的可能性很小,比方說,0.3 - 遲早你會再次看到這個問題(多次,我想)。接下來的代碼使相機遵循有X和Y和攝像頭的對象將永遠不會失去的對象從它的視線:

public void LookFollow(Block AF) 
{ 
    float some=5;//changing me will cause camera to move faster/slower 
    float mx=0,my=0; 

    //Right-Left 
    if(LookCorX!=AF.getX()) 
    { 
     if(AF.getX()>LookCorX) 
     { 
      if(AF.getX()<LookCorX+2) 
       mx=AF.getX()-LookCorX; 
      if(AF.getX()>LookCorX+2) 
       mx=(AF.getX()-LookCorX)/some; 
     } 
     if(AF.getX()<LookCorX) 
     { 
      if(2+AF.getX()>LookCorX) 
       mx=AF.getX()-LookCorX; 
      if(2+AF.getX()<LookCorX) 
       mx=(AF.getX()-LookCorX)/some; 
     } 
    } 

    //Up-Down 
    if(LookCorY!=AF.getY()) 
    { 
     if(AF.getY()>LookCorY) 
     { 
      if(AF.getY()<LookCorY+2) 
       my=AF.getY()-LookCorY; 
      if(AF.getY()>LookCorY+2) 
       my=(AF.getY()-LookCorY)/some; 
     } 
     if(AF.getY()<LookCorY) 
     { 
      if(2+AF.getY()>LookCorY) 
       my=AF.getY()-LookCorY; 
      if(2+AF.getY()<LookCorY) 
       my=(AF.getY()-LookCorY)/some; 
     } 
    } 

    //Evading "Perfect Pixel" 
    mx=(int)mx; 
    my=(int)my; 

    //Moving Camera 
    GL11.glTranslatef(-mx,-my,0); 

    //Saving up Position of camera. 
    LookCorX+=mx; 
    LookCorY+=my; 
} 
float LookCorX=300,LookCorY=200; //camera's starting position 

其結果是 - 我們收到一個攝像頭,移動有點尖銳,導致步驟可以」 t小於1個像素,有時需要縮小一步,但紋理看起來不錯,而且這是一個偉大的進步!

對不起,一個真正的大答案。我仍在研究一個好的解決方案。一旦我找到更好更短的東西 - 這會被我抹去。

+0

這條評論是在評論中自動產生的。 Stackoverflow是問答網站,而不是論壇。所以,如果你有問題,你需要創建一個新的點擊「問問題」。如果它包含問題的重要部分,您也可以鏈接到此問題。根據規則,您的答案遲早會被刪除。 – Dmitry 2015-04-04 16:02:15

+0

哦,夥計。我在這裏尋找答案。你的規則很糟糕!我們可以在這裏刪除所有無用的東西,但一旦我的文章有一條信息 - 讓我們保持一段時間!我不是爲了「聲譽」而競選的。我遇到了一個麻煩,而且我對自己製作的帖子看起來不錯。相信我,一旦完成「交易」,我將清理我所做的所有垃圾。 – 2015-04-06 12:08:34

+0

是的,謝謝你,夥計們,我已經被阻止回答。看起來你更喜歡建立一個良好的社區,而不是尋找答案。繼續,你做對了! – 2015-04-06 14:13:31