OpenGL - 如何让这个程序适用于大于 1x1 的纹理?
OpenGL - How can I make this program work for textures larger than 1x1?
我正在编写一个概念验证程序以更加熟悉纹理,但它的行为很奇怪,因为它适用于 1x1 纹理但对所有其他纹理都无效。我多次扫描程序并查看了每个函数的参数,但无法理解为什么它对 1x1 纹理(或较大纹理中的第一个像素)工作正常,但在其他情况下显示白色方块。
这是同一个程序的图片运行 glTexImage2D 的宽度和高度参数分别为 (1, 1) 和 (2,2)。
这是显示白色方块的代码(而预期绘制 2x2 红色、绿色、蓝色、黄色行主要纹理)。
note: in(Comment, Arg)
macro is equivelent to Arg
, it's only used in this particular program because it's tricky to remember arguments of glTexImage2D off the top of your head.
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 2),
in(height, 2),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
如果我将 in(width, 2)
更改为 in(width, 1)
并将 in(height, 2)
更改为 in(height, 1)
,它会显示一个红色方块,并更改 bm
的前三个值数组,它按预期将此颜色映射到立方体。
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 1),
in(height, 1),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
有人可以解释发生了什么以及我该如何解决这个问题吗?
Solution: passed tex to glTexParameteri instead of GL_TEXTURE_2D(side note: and a typo 1.1 to 1.f in glVertex2f)
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 2),
in(height, 2),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
当您指定 2x2 纹理时,您的纹理不是 mipmap 完整的,而是使用了 mip-mapping 缩小过滤器。根据规范,您得到的结果是正确的结果。
您的错误在于您试图设置非 mipmapping GL_NEAREST
过滤器:
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameter
需要纹理绑定点,即 GL_TEXTURE_2D
,而不是纹理名称。因此,此调用将产生 GL_INVALID_ENUM
错误并且没有其他影响。
我正在编写一个概念验证程序以更加熟悉纹理,但它的行为很奇怪,因为它适用于 1x1 纹理但对所有其他纹理都无效。我多次扫描程序并查看了每个函数的参数,但无法理解为什么它对 1x1 纹理(或较大纹理中的第一个像素)工作正常,但在其他情况下显示白色方块。
这是同一个程序的图片运行 glTexImage2D 的宽度和高度参数分别为 (1, 1) 和 (2,2)。
这是显示白色方块的代码(而预期绘制 2x2 红色、绿色、蓝色、黄色行主要纹理)。
note:
in(Comment, Arg)
macro is equivelent toArg
, it's only used in this particular program because it's tricky to remember arguments of glTexImage2D off the top of your head.
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 2),
in(height, 2),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
如果我将 in(width, 2)
更改为 in(width, 1)
并将 in(height, 2)
更改为 in(height, 1)
,它会显示一个红色方块,并更改 bm
的前三个值数组,它按预期将此颜色映射到立方体。
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 1),
in(height, 1),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
有人可以解释发生了什么以及我该如何解决这个问题吗?
Solution: passed tex to glTexParameteri instead of GL_TEXTURE_2D(side note: and a typo 1.1 to 1.f in glVertex2f)
#include <GL/glut.h>
// | reminder decorator macro.
#define in(Comment, Arg) Arg
GLubyte bm[16] = {
0xff, 0x00, 0x00, 0xff,
0x00, 0xff, 0x00, 0xff,
0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff
};
GLuint tex;
void display()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, tex);
glLoadIdentity();
// | make the square smaller to contrast our target from the background.
glScalef(.5f, .5f, 1.f);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0.f, 0.f);
glVertex2f(-1.f, 1.f);
glTexCoord2f(1.f, 0.f);
glVertex2f(1.f, 1.f);
glTexCoord2f(1.f, 1.f);
glVertex2f(1.f, -1.f);
glTexCoord2f(0.f, 1.f);
glVertex2f(-1.f, -1.f);
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE);
glutCreateWindow("");
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D (
in(target, GL_TEXTURE_2D),
in(level, 0),
in(internalFormat, GL_RGBA),
in(width, 2),
in(height, 2),
in(border, 0),
in(format, GL_RGBA),
in(type, GL_UNSIGNED_BYTE),
in(data, bm)
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
当您指定 2x2 纹理时,您的纹理不是 mipmap 完整的,而是使用了 mip-mapping 缩小过滤器。根据规范,您得到的结果是正确的结果。
您的错误在于您试图设置非 mipmapping GL_NEAREST
过滤器:
glTexParameteri(tex, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameter
需要纹理绑定点,即 GL_TEXTURE_2D
,而不是纹理名称。因此,此调用将产生 GL_INVALID_ENUM
错误并且没有其他影响。