使用glTexImage2D的奇怪结果
Odd results using glTexImage2D
我一直在试图弄清楚glTexImage2D
是如何工作的,并从一些非常清晰的代码中看到一些奇怪的结果。我的代码只是将一个粗糙的圆绘制成一个256*256长度的无符号数组,然后将该数据发送出去成为纹理。然而,无论我在图像创建循环中选择什么组合,显示的纹理都是红色和橙色的变化:
unsigned* data = new unsigned[256*256];
for (int y = 0; y < 256; ++y)
for (int x = 0; x < 256; ++x)
if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75)
data[256*y + x] = ((156 << 24) | (256 << 16) | (156 << 8) | (200 << 0));
else
data[256*y + x] = 0; // I'd expect this to be transparent and the above to be slightly transparent and green, but it's red somehow.
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data);
OpenGL选项: glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE);
//glEnable(GL_BLEND);
//glDisable(GL_CULL_FACE);
glGenTextures(1, &leaf[0]);
createLeaf(leaf[0]); // createLeaf(GLuint& texid) is posted entirely above
代码的其余部分除了在窗口中的单个四边形上显示纹理外什么也不做。(这个主题x64)
编辑:我尝试了瑞卡德的解决方案,我仍然得到一个紫色的圆圈。
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data);
首先是积极的事情。您使用了一个有大小的内部格式(GL_RGBA8,而不是GL_RGBA)。这很好;继续这样做。您清楚地了解内部格式(GL_RGBA8)和像素传输格式(GL_RGBA)之间的区别。这也不错。
问题是这样的。你告诉OpenGL你的数据是一个无符号字节流。但它是而不是一个无符号字节流;它是一个无符号整数流。这样声明data
,这样填充data
。那你为什么要对OpenGL撒谎?问题是你的颜色。这是你的颜色值之一:
((156 << 24) | (256 << 16) | (156 << 8) | (200 << 0))
首先,256不是有效的颜色。256在十六进制中是0x100,这是两个字节,而不是一个。
从这里得到的无符号整数是:
0x9D009CC8
如果这些是RGBA颜色的顺序,那么红色是0x9D,绿色是0x00,蓝色是0x9C, alpha是0xC8。
现在,因为你可能在一台小端计算机上工作,这4个字节被翻转存储,像这样:
0xC89C009D
当你告诉OpenGL假装这是一个字节数组(它不是),你失去了小端转换。OpenGL看到字节数组从0xC8开始,这是红色的值。等等。
你需要告诉OpenGL你实际上在做什么:你将四个8位无符号值存储在一个32位无符号整数中。要做到这一点,使用以下命令:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (GLvoid*)data);
GL_UNSIGNED_INT_8_8_8_8表示你正在向OpenGL提供一个无符号32位整数数组(你是)。32位整数的前8位是红色,第二个是绿色,第三个是蓝色,第四个是alpha。
所以,要完全修复你的代码,你需要这样做:GLuint* data = new GLuint[256*256]; //Use OpenGL's types
for (int y = 0; y < 256; ++y)
for (int x = 0; x < 256; ++x)
if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75)
data[256*y + x] = ((0x9C << 24) | (0xFF << 16) | (0x9C << 8) | (0xC8 << 0));
else
data[256*y + x] = 0; // I'd expect this to be transparent and the above to be slightly transparent and green, but it's red somehow.
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); //Always set the base and max mipmap levels of a texture.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (GLvoid*)data);
//我希望这是透明的,上面是稍微透明和绿色的,但它是红色的。
Alpha不代表透明;除非你赋予它意义,否则它毫无意义。只有当你使用混合并设置混合模式时,Alpha才代表透明度,从而使事物变得透明。否则,它没有任何意义。
如果我像你一样做同样的事情,我会使用一个无符号字符数组,而不是长度为4倍的无符号整型数组。
unsigned char* data = new unsigned char[256*256*4];
for (int y = 0; y < 256; ++y)
for (int x = 0; x < 256; ++x)
if ((x - 100)*(x - 100) + (y - 156)*(y - 156) < 75*75){
data[(256*y + x)*4+0] = 156;
data[(256*y + x)*4+1] = 256;
data[(256*y + x)*4+2] = 156;
data[(256*y + x)*4+3] = 200;
}else{
data[(256*y + x)*4+0] = 0;
data[(256*y + x)*4+1] = 0;
data[(256*y + x)*4+2] = 0;
data[(256*y + x)*4+3] = 0;
}
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)data);
但是你的代码对我来说是正确的,我不确定上面的代码是否会改变什么。如果结果相同,那么尝试将GL_RGBA8更改为GL_RGBA。文本的变量类型是什么。我总是通过引用(&texid)调用glBindTexture,但如果你的texid是一个指向GLuint (GLuint *texid;)的指针,那么我想那部分是可以的。(编辑:只是意识到我错了最后一部分,我正在考虑glGenTexture而不是glBindTexture)
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- 用C++20 fmt限制结果的总大小
- 如何返回一个类的两个对象相加的结果
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 序列化,没有库的整数,得到奇怪的结果
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 在更改for循环的第三部分后,未使用for循环结果
- 使用++运算符会导致意外的结果
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- C++Brute Force攻击函数不会返回结果
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 算术运算的结果类似于:C浮点变量中的1/3
- ";结果类型必须是可从输入范围的值类型""构造的;创建std::vector时
- 密码登录程序将永远循环并显示不正确的结果
- 如何让C++'tally up'结果并制定计划?
- 返回stbi_load函数的结果并将其用于glTexImage2D会导致内存冲突
- 使用glTexImage2D的奇怪结果