OpenGL渲染纹理全白
Posted
技术标签:
【中文标题】OpenGL渲染纹理全白【英文标题】:OpenGL renders texture all white 【发布时间】:2012-12-13 19:44:08 【问题描述】:我正在尝试将 .png 图像渲染为纹理。但是,正在渲染的只是一个白色方块。
我给我的纹理一个唯一的 int ID,称为 texID,将像素数据读入缓冲区“图像”(在 .h 文件中声明)。我加载我的像素缓冲区,完成我所有的 OpenGL 工作并将该像素缓冲区绑定到 OpenGL 的纹理。然后我使用 glDrawElements 将其全部绘制出来。
当调用它的构造函数时,我还将纹理初始化为 32x32 的大小,因此我怀疑它与二次幂问题有关。
任何人都可以在我的 OpenGL GL_TEXTURE_2D 设置中看到任何可能给我一个白色方块的错误。
#include "Texture.h"
Texture::Texture(int width, int height, string filename)
const char* fnPtr = filename.c_str(); //our image loader accepts a ptr to a char, not a string
printf(fnPtr);
w = width; //give our texture a width and height, the reason that we need to pass in the width and height values manually
h = height;//UPDATE, these MUST be P.O.T.
unsigned error = lodepng::decode(image,w,h,fnPtr);//lodepng's decode function will load the pixel data into image vector
//display any errors with the texture
if(error)
cout << "\ndecoder error " << error << ": " << lodepng_error_text(error) <<endl;
for(int i = 0; i<image.size(); i++)
printf("%i,", image.at(i));
printf("\nImage size is %i", image.size());
//image now contains our pixeldata. All ready for OpenGL to do its thing
//let's get this texture up in the video memory
texGLInit();
void Texture::texGLInit()
//WHERE YOU LEFT OFF: glGenTextures isn't assigning an ID to textures. it stays at zero the whole time
//i believe this is why it's been rendering white
glGenTextures(1, &textures);
printf("\ntexture = %u", textures);
glBindTexture(GL_TEXTURE_2D, textures);//evrything we're about to do is about this texture
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//glDisable(GL_COLOR_MATERIAL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,w,h,0, GL_RGBA, GL_UNSIGNED_BYTE, &image);
//we COULD free the image vectors memory right about now.
void Texture::draw(point centerPoint, point dimensions)
glEnable(GL_TEXTURE_2D);
printf("\nDrawing block at (%f, %f)",centerPoint.x, centerPoint.y);
glBindTexture(GL_TEXTURE_2D, textures);//bind the texture
//create a quick vertex array for the primitive we're going to bind the texture to
printf("TexID = %u",textures);
GLfloat vArray[8] =
centerPoint.x-(dimensions.x/2), centerPoint.y-(dimensions.y/2),//bottom left i0
centerPoint.x-(dimensions.x/2), centerPoint.y+(dimensions.y/2),//top left i1
centerPoint.x+(dimensions.x/2), centerPoint.y+(dimensions.y/2),//top right i2
centerPoint.x+(dimensions.x/2), centerPoint.y-(dimensions.y/2)//bottom right i3
;
//create a quick texture array (we COULD create this on the heap rather than creating/destoying every cycle)
GLfloat tArray[8] =
0.0f,0.0f, //0
0.0f,1.0f, //1
1.0f,1.0f, //2
1.0f,0.0f //3
;
//and finally.. the index array...remember, we draw in triangles....(and we'll go CW)
GLubyte iArray[6] =
0,1,2,
0,2,3
;
//Activate arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
//Give openGL a pointer to our vArray and tArray
glVertexPointer(2, GL_FLOAT, 0, &vArray[0]);
glTexCoordPointer(2, GL_FLOAT, 0, &tArray[0]);
//Draw it all
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, &iArray[0]);
//glDrawArrays(GL_TRIANGLES,0,6);
//Disable the vertex arrays
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
//done!
/*glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex2f(centerPoint.x-(dimensions.x/2), centerPoint.y-(dimensions.y/2));
glTexCoord2f(0.0f,1.0f);
glVertex2f(centerPoint.x-(dimensions.x/2), centerPoint.y+(dimensions.y/2));
glTexCoord2f(1.0f,1.0f);
glVertex2f(centerPoint.x+(dimensions.x/2), centerPoint.y+(dimensions.y/2));
glTexCoord2f(1.0f,0.0f);
glVertex2f(centerPoint.x+(dimensions.x/2), centerPoint.y-(dimensions.y/2));
glEnd();*/
Texture::Texture(void)
Texture::~Texture(void)
我还将包含主类的 init,在此之前我会在其中进行更多的 OGL 设置。
void init(void)
printf("\n......Hello Guy. \n....\nInitilising");
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,XSize,0,YSize);
glEnable(GL_TEXTURE_2D);
myBlock = new Block(0,0,offset);
glClearColor(0,0.4,0.7,1);
glLineWidth(2); // Width of the drawing line
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
printf("\nInitialisation Complete");
更新:在我第一次设置 OpenGL 窗口的地方添加主函数。
int main(int argc, char** argv)
glutInit(&argc, argv); // GLUT Initialization
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); // Initializing the Display mode
glutInitWindowSize(800,600); // Define the window size
glutCreateWindow("Gem Miners"); // Create the window, with caption.
printf("\n========== McLeanTech Systems =========\nBecoming Sentient\n...\n...\n....\nKILL\nHUMAN\nRACE \n");
init(); // All OpenGL initialization
//-- Callback functions ---------------------
glutDisplayFunc(display);
glutKeyboardFunc(mykey);
glutSpecialFunc(processSpecialKeys);
glutSpecialUpFunc(processSpecialUpKeys);
//glutMouseFunc(mymouse);
glutMainLoop(); // Loop waiting for event
【问题讨论】:
让 OpenGL 通过glGenTextures()
为您创建纹理 ID,而不是告诉它使用哪个 ID。
@genpfault,但是我的 Texture 类有多个实例。如果我为生成纹理指定一个数组以放入 ID,那么每个实例都会有所不同吗?还是这个数组被 openGL 假定为静态的?
@GuyJoelMcLean:嗯,通常你希望每个纹理都有一个不同的 ID。您应该考虑将该绘图功能移出纹理类。
【参考方案1】:
以下是纹理变白时的常用清单:
在尝试加载纹理时已创建 OpenGL 上下文并绑定到当前线程?
使用glGenTextures
分配的纹理ID?
参数format
和internal format
到glTex[Sub]Image…
是否允许作为此函数的输入有效的OpenGL 令牌?
是否正在使用 mipmapping?
是:提供所有 mipmap 层 - 最佳设置 glTexParameteri
GL_TEXTURE_BASE_LEVEL 和 GL_TEXTURE_MAX_LEVEL,以及 GL_TEXTURE_MIN_LOD 和 GL_TEXTURE_MAX_LOG。
否:通过将 glTexParameteri
GL_TEXTURE_MIN_FILTER 设置为 GL_NEAREST 或 GL_LINEAR 来关闭 mipmap 过滤。
【讨论】:
在调试检查后,(并检查了以上所有内容并通过 glGenTextures 添加了分配纹理 ID)我注意到存储在无符号字符向量“图像”中的像素数据主要包含相关数字( 0-255),但也有很多乱码。即非字母字符。您认为这可能是 .png 文件的保存方式存在问题吗? @GuyJoelMcLean:纹理的外观应该反映您看到的胡言乱语。所以,不,它不应该是全白的。 你是对的,当我打印将所有组件转换为整数的向量时,它们以完美的 RGBA 格式打印。但是,通过实验我发现可以使用 glColor4f() 为白色块着色 :) 你通常可以用纹理来做吗? 我终于修好了。正如@datenwolf 所说,将来查看此页面的任何人都会遇到类似问题。我在另一个类中全局实例化我的 Texture 实例。我不得不将它移动到代码中的一个点,在 OpenGL 创建上下文之后创建它们。此外,在修复此问题后,我的纹理模糊(如乱码像素)并导致间歇性运行时访问违规。这是因为在我的像素数据的 glTexImage2D 中,我只是传入了对我为它创建的数组的引用。而不是引用...的第一部分 数据。我正在传递它 &image,而传递它 &image[0] 解决了这个问题。我还没有完全设法让 alpha 位正常工作,但总的来说,我是一只非常快乐的兔子。感谢大家的时间和帮助。以上是关于OpenGL渲染纹理全白的主要内容,如果未能解决你的问题,请参考以下文章