OpenGL ES 3.0之Texturing紋理詳解(二)


  Texture Filtering and Mipmapping 紋理過濾與多級紋理

  前面我們已經講了單個2D圖像的2D紋理的介紹,這篇文章主要講解多級紋理。紋理坐標是用於生成一個2D索引,當放大和縮小設置為GL_NEAREST時,將發生一個單一紋理將匹配到紋理坐標位置中,這是一個最近點的采樣。

  當使用一個多級紋理時,我們可以設置過濾模式,,為了達到屏幕像素和紋理圖片像素更合適的比例,減少鋸齒。因為多級紋理貼圖的成功過濾,當在更遠處觀察時,我們向貼圖鏈后移動,鋸齒減少,實現高質量的圖像。

   

// Load mipmap level 0
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
level = 1;
prevImage = &pixels[0];
while(width > 1 && height > 1)
{
  int newWidth,
  newHeight;
  // Generate the next mipmap level
  GenMipMap2D( prevImage, &newImage, width, height, &newWidth,
  &newHeight);
  // Load the mipmap level
  glTexImage2D(GL_TEXTURE_2D, level, GL_RGB,
  newWidth, newHeight, 0, GL_RGB,
  GL_UNSIGNED_BYTE, newImage);
  // Free the previous image
  free(prevImage);
  // Set the previous image for the next iteration
  prevImage = newImage;
  level++;
  // Half the width and height
  width = newWidth;
  height = newHeight;
}
free(newlmage);

  GenMipMap2D用於用於實現多級紋理。紋理過濾有2種:放大和縮小。當屏幕上設計的多邊形的大小小於紋理圖像時,我們使用縮小紋理。反之使用放大。使用過濾類型由具體硬件自動選擇,但是API也提供了過濾控制,放大處理是不相關的,因為我們總是使用最大
可用的級別。對於縮小,有各種的采樣模式可以使用。哪種模式的使用選擇基於你需要實現的可視質量和你想要實現多大性能的紋理過濾來決定的。過濾模式使用glTexParameter[i|f][v]來指定。

  

  

  放大過濾可以是GL_NEAREST 或 GL_LINEAR。在GL_NEAREST 放大過濾模式,紋理最近的單點將做紋理坐標。在GL_LINEAR 模式,雙線性(四個點平均)作為紋理坐標。

  縮小過濾可以是下列值:

  •• GL_NEAREST—Takes a single point sample from the texture nearest to the texture coordinate.

  •• GL_LINEAR—Takes a bilinear sample from the texture nearest to the texture coordinate.

  •• GL_NEAREST_MIPMAP_NEAREST—Takes a single point sample from the closest mip level chosen.
  •• GL_NEAREST_MIPMAP_LINEAR—Takes a sample from the two closest mip levels and interpolates between those samples.
  •• GL_LINEAR_MIPMAP_NEAREST—Takes a bilinear fetch from the closest mip level chosen.
  •• GL_LINEAR_MIPMAP_LINEAR—Takes a bilinear fetch from each of the two closest mip levels and then interpolates between them. This last mode, which is typically referred to as trilinear filtering, produces the best quality of all modes.

  GL_NEAREST 和 GL_LINEAR 是唯一不需要完整多級紋理的縮小過濾模式,其他都需要完整的多級處理。

  

GL_NEAREST 和GL_LINEAR_MIPMAP_LINEAR的過濾設置。

  值得一提的是一些性能將影響你選擇的紋理過濾模式。對於大多數硬件來說,使用多級紋理是最好的選擇。

  Seamless Cubemap Filtering

  它是3.0新特性。當一個線性過濾核心在一個立方體紋理的邊框時,這個過濾只發生在線所在立方體的一面中。你不需要設置Seamless Cubemap Filtering,線性過濾會自動使用它。

  

  自動多級紋理生成

  前面我們已經創建了一個level為0的多級紋理,這是一種方法。另外也提供了自動多級紋理生成函數 glGenerateMipmap。

  

我們隊綁定的紋理對象調用glGenerateMipmap,它會為我們生成從原始圖像到level為0的多級紋理鏈。當你使用framebuffer對象時,自動多級紋理生成變得尤為重要。當渲染一個紋理時,我們不想將紋理讀回CPU中生成多級紋理。glGenerateMipmap可以解決這個問題。

 

  Texture Coordinate Wrapping

  當紋理坐標超過了范圍[0.0, 1.0] 時,使用紋理包裝來實現。紋理包裝模式使用glTexParameter[i|f][v]來指定。

  

  紋理包裝模式能被獨立的設定為s坐標和t坐標。GL_TEXTURE_WRAP_S模式定義s 坐標超出范圍[0.0, 1.0]的情況,GL_TEXTURE_WRAP_T 設定t 坐標超出范圍[0.0, 1.0]的情況。有三種包裝模式供選擇

  

   注意,紋理包裝模式對過濾行為有影響。例如紋理坐標是邊緣時,雙線性過濾將掃描紋理的邊緣。這時包裝模式將決定哪個紋理是紋理邊緣的外面而應用於過濾算法。如果你不想要任何形式的重復,應該使用GL_CLAMP_TO_EDGE。

  下圖是使用紋理繪制正方形在三種包裝模式中的效果圖

  

   

//
void Draw ( ESContext *esContext )
{
   UserData *userData = esContext->userData;
   GLfloat vVertices[] = { -0.3f,  0.3f, 0.0f, 1.0f,  // Position 0
                           -1.0f,  -1.0f,              // TexCoord 0
                           -0.3f, -0.3f, 0.0f, 1.0f, // Position 1
                           -1.0f,  2.0f,              // TexCoord 1
                           0.3f, -0.3f, 0.0f, 1.0f, // Position 2
                           2.0f,  2.0f,              // TexCoord 2
                           0.3f,  0.3f, 0.0f, 1.0f,  // Position 3
                           2.0f,  -1.0f               // TexCoord 3
                         };
   GLushort indices[] = { 0, 1, 2, 0, 2, 3 };

   // Set the viewport
   glViewport ( 0, 0, esContext->width, esContext->height );

   // Clear the color buffer
   glClear ( GL_COLOR_BUFFER_BIT );

   // Use the program object
   glUseProgram ( userData->programObject );

   // Load the vertex position
   glVertexAttribPointer ( 0, 4, GL_FLOAT,
                           GL_FALSE, 6 * sizeof ( GLfloat ), vVertices );
   // Load the texture coordinate
   glVertexAttribPointer ( 1, 2, GL_FLOAT,
                           GL_FALSE, 6 * sizeof ( GLfloat ), &vVertices[4] );

   glEnableVertexAttribArray ( 0 );
   glEnableVertexAttribArray ( 1 );

   // Bind the texture
   glActiveTexture ( GL_TEXTURE0 );
   glBindTexture ( GL_TEXTURE_2D, userData->textureId );

   // Set the sampler texture unit to 0
   glUniform1i ( userData->samplerLoc, 0 );

   // Draw quad with repeat wrap mode
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
   glUniform1f ( userData->offsetLoc, -0.7f );
   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );

   // Draw quad with clamp to edge wrap mode
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
   glUniform1f ( userData->offsetLoc, 0.0f );
   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );

   // Draw quad with mirrored repeat
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT );
   glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT );
   glUniform1f ( userData->offsetLoc, 0.7f );
   glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices );
}

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM