本文介绍了OpenGL 2 纹理内部格式 GL_RGB8I、GL_RGB32UI 等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重写我的大部分纹理代码.我希望能够指定某些内部格式:GL_RGB8I、GL_RGB8UI、GL_RGB16I、GL_RGB16UI、GL_RGB32I 和 GL_RGB32UI.这些令牌在 OpenGL 2 中不存在.

将这些内部格式指定为 glTexImage2D 的参数时,纹理处理失败(纹理显示为白色).检查错误时,我得到 1282(无效操作").我认为这意味着 OpenGL 仍在将 OpenGL 2 用于 glTexImage2D,因此调用失败.显然,它需要使用更新的版本才能成功.GL_RGB、GL_RGBA 和(奇怪的)GL_RGB32F、GL_RGBA32F 之类的枚举按预期工作.

我配置为使用 GLEW 或 Glee 进行扩展.我可以在其他地方毫无问题地使用 OpenGL 4 调用(例如,glPatchParameteri、glBindFramebuffer 等),并且有问题的枚举肯定存在.为完整起见,glGetString(GL_VERSION) 返回4.2.0".我的问题:我可以强制这些扩展库之一使用 OpenGL 4.2 版本吗?如果是,怎么办?

代码太复杂,无法发布,但这里有一个使用 GLee 的简单、自包含的示例,也演示了该问题:

#include #include #include #include //对于Windows#pragma 注释(lib,GLee.lib")#pragma 注释(lib,opengl32.lib")#pragma 注释(lib,glu32.lib")#pragma 注释(lib,glut32.lib")#include #include const int screen_size[2] = {512,512};#define TEXTURE_SIZE 64//选择一个选项.如果您看到黑色,则纹理正在起作用.如果您看到红色,则表示四边形未绘制.如果您看到白色,则纹理已失败.#定义类型1无效错误检查(无效){GLnum error_code = glGetError();const GLubyte* error_string = gluErrorString(error_code);(error_string==NULL) ?printf("%d = (无法识别的错误——扩展错误?)
",error_code) : printf("%d = "%s"
",error_code,error_string);}#if TYPE==1//############ 8 位测试############内联 GLenum get_type(int which) { return (which==1)?GL_RGB8:GL_RGB;}//作品#elif 类型==2内联 GLenum get_type(int which) { return (which==1)?GL_RGBA8:GL_RGBA;}//作品#elif 类型==3内联 GLenum get_type(int which) { return (which==1)?GL_RGB8UI:GL_RGB;}//不起作用(无效的操作)#elif 类型==4内联 GLenum get_type(int which) { return (which==1)?GL_RGB8I:GL_RGB;}//不起作用(无效的操作)#elif 类型==5内联 GLenum get_type(int which) { return (which==1)?GL_RGBA8UI:GL_RGBA;}//不起作用(无效的操作)#elif 类型==6内联 GLenum get_type(int which) { return (which==1)?GL_RGBA8I:GL_RGBA;}//不起作用(无效的操作)#elif TYPE==7//############ 16 位测试############内联 GLenum get_type(int which) { return (which==1)?GL_RGB16:GL_RGB;}//作品#elif 类型==8内联 GLenum get_type(int which) { return (which==1)?GL_RGBA16:GL_RGBA;}//作品#elif 类型==9内联 GLenum get_type(int which) { return (which==1)?GL_RGB16UI:GL_RGB;}//不起作用(无效的操作)#elif 类型==10内联 GLenum get_type(int which) { return (which==1)?GL_RGB16I:GL_RGB;}//不起作用(无效的操作)#elif 类型==11内联 GLenum get_type(int which) { return (which==1)?GL_RGBA16UI:GL_RGBA;}//不起作用(无效的操作)#elif 类型==12内联 GLenum get_type(int which) { return (which==1)?GL_RGBA16I:GL_RGBA;}//不起作用(无效的操作)#elif TYPE==13//############ 32 位测试############内联 GLenum get_type(int which) { return (which==1)?GL_RGB32:GL_RGB;}//令牌不存在#elif 类型==14内联 GLenum get_type(int which) { return (which==1)?GL_RGBA32:GL_RGBA;}//令牌不存在#elif 类型==15内联 GLenum get_type(int which) { return (which==1)?GL_RGB32UI:GL_RGB;}//不起作用(无效的操作)#elif 类型==16内联 GLenum get_type(int which) { return (which==1)?GL_RGB32I:GL_RGB;}//不起作用(无效的操作)#elif 类型==17内联 GLenum get_type(int which) { return (which==1)?GL_RGBA32UI:GL_RGBA;}//不起作用(无效的操作)#elif 类型==18内联 GLenum get_type(int which) { return (which==1)?GL_RGBA32I:GL_RGBA;}//不起作用(无效的操作)#elif TYPE==19//############ 32 位浮点数############内联 GLenum get_type(int which) { return (which==1)?GL_RGB32F:GL_RGB;}//作品#elif 类型==20内联 GLenum get_type(int which) { return (which==1)?GL_RGBA32F:GL_RGBA;}//作品#万一胶质质地;无效创建纹理(无效){printf(" 纹理设置前的状态:");错误检查();glGenTextures(1,&texture);glBindTexture(GL_TEXTURE_2D,纹理);printf(" 纹理创建后的状态:");错误检查();GLenum data_type = GL_UNSIGNED_BYTE;int data_length = TEXTURE_SIZE*TEXTURE_SIZE*4;//最大通道数,所以它适用于一切无符号字符*数据=新无符号字符[数据长度];for (int i=0;i<data_length;++i) {数据[i] = (无符号字符)(0);};glTexImage2D(GL_TEXTURE_2D,0,get_type(1), TEXTURE_SIZE,TEXTURE_SIZE, 0,get_type(2),data_type,data);printf(" glTexImage2D 后的状态:");错误检查();删除[]数据;glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);printf(" 定义纹理过滤器后的状态:");错误检查();}无效键盘(无符号字符键,int x,int y){开关(键){case 27://esc退出(0);休息;}}无效绘制(无效){glClearColor(1.0,0.0,0.0,1.0);//如果四边形没有绘制glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glViewport(0,0,screen_size[0],screen_size[1]);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(0,screen_size[0],0,screen_size[1]);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glBegin(GL_QUADS);glTexCoord2f(0,0);glVertex2f(0,0);glTexCoord2f(2,0);glVertex2f(screen_size[0],0);glTexCoord2f(2,2);glVertex2f(screen_size[0],screen_size[1]);glTexCoord2f(0,2);glVertex2f(0,screen_size[1]);glEnd();glutSwapBuffers();}int main(int argc, char* argv[]) {glutInit(&argc,argv);glutInitWindowSize(screen_size[0],screen_size[1]);glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);glutCreateWindow("纹理类型 - 伊恩马利特");glEnable(GL_DEPTH_TEST);glEnable(GL_TEXTURE_2D);printf("OpenGL 设置后的状态:");错误检查();创建纹理();printf("纹理设置后的状态:");错误检查();glutDisplayFunc(画);glutIdleFunc(画);glutKeyboardFunc(键盘);glutMainLoop();返回0;}
解决方案

OpenGL 错误 理解起来并不复杂.GL_INVALID_ENUM/VALUE 在您传递一个意外的、不受支持的或超出范围的枚举或值时被抛出.如果您将17"作为内部格式传递给 glTexImage2D,您将得到 GL_INVALID_ENUM,因为 17 不是内部格式的有效枚举数.如果您将 103,422 作为宽度传递给 glTexImage2D,您将得到 GL_INVALID_VALUE,因为 103,422 几乎肯定大于 GL_MAX_TEXTURE_2D 的大小.>

GL_INVALID_OPERATION 总是用于组合出错的状态.要么有一些先前设置的上下文状态与您正在调用的函数不匹配,要么两个或多个参数组合导致了问题.后者就是你这里的情况.

如果您的实现根本不支持整数纹理,那么您将获得 INVALID_ENUM(因为内部格式不是有效格式).获得 INVALID_OPERATION 意味着其他地方出了问题.

也就是说,这个:

glTexImage2D(GL_TEXTURE_2D,0,get_type(1), TEXTURE_SIZE,TEXTURE_SIZE, 0,get_type(2),data_type,data);

您的 get_type(2) 调用在所有情况下都返回 GL_RGBGL_RGBA.但是,当使用完整的图像格式时,您必须 使用 _INTEGER 结尾的像素传输格式.

所以你的 get_type(2) 需要是这样的:

inline GLenum get_type(int which) { return (which==1)?GL_RGB16UI:GL_RGB_INTEGER;}

对于其他完整的图像格式也是如此.

I'm rewriting a large part of my texturing code. I would like to be able to specify certain internal formats: GL_RGB8I, GL_RGB8UI, GL_RGB16I, GL_RGB16UI, GL_RGB32I, and GL_RGB32UI. These tokens do not exist in OpenGL 2.

When specifying these internal formats as arguments to glTexImage2D, the texturing fails (the texture appears as white). When checking for errors, I get [EDIT:] 1282 ("invalid operation"). I take this to mean that the OpenGL is still using OpenGL 2 for glTexImage2D, and so the call is failing. Obviously, it will need to use a newer version to succeed. Enums like GL_RGB, GL_RGBA, and (oddly) GL_RGB32F, GL_RGBA32F work as expected.

I configure to use GLEW or GLee for extensions. I can use OpenGL 4 calls with no problem elsewhere (e.g., glPatchParameteri, glBindFramebuffer, etc.), and the enums in question certainly exist. For completeness, glGetString(GL_VERSION) returns "4.2.0". My question: can I force one of these extension libraries to use the OpenGL 4.2 version? If so, how?

EDIT: The code is too complicated to post, but here is a simple, self-contained example using GLee that also demonstrates the problem:

#include <GLee5_4/GLee.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <gl/glut.h>
//For Windows
#pragma comment(lib,"GLee.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glut32.lib")

#include <stdlib.h>
#include <stdio.h>

const int screen_size[2] = {512,512};
#define TEXTURE_SIZE 64

//Choose a selection.  If you see black, then texturing is working.  If you see red, then the quad isn't drawing.  If you see white, texturing has failed.
#define TYPE 1

void error_check(void) {
    GLenum error_code = glGetError();
    const GLubyte* error_string = gluErrorString(error_code);
    (error_string==NULL) ? printf("%d = (unrecognized error--an extension error?)
",error_code) : printf("%d = "%s"
",error_code,error_string);
}

#if   TYPE==1 //############ 8-BIT TESTS ############
    inline GLenum get_type(int which) { return (which==1)?    GL_RGB8: GL_RGB; } //works
#elif TYPE==2
    inline GLenum get_type(int which) { return (which==1)?   GL_RGBA8:GL_RGBA; } //works
#elif TYPE==3
    inline GLenum get_type(int which) { return (which==1)?  GL_RGB8UI: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==4
    inline GLenum get_type(int which) { return (which==1)?   GL_RGB8I: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==5
    inline GLenum get_type(int which) { return (which==1)? GL_RGBA8UI:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==6
    inline GLenum get_type(int which) { return (which==1)?  GL_RGBA8I:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==7 //############ 16-BIT TESTS ############
    inline GLenum get_type(int which) { return (which==1)?   GL_RGB16: GL_RGB; } //works
#elif TYPE==8
    inline GLenum get_type(int which) { return (which==1)?  GL_RGBA16:GL_RGBA; } //works
#elif TYPE==9
    inline GLenum get_type(int which) { return (which==1)? GL_RGB16UI: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==10
    inline GLenum get_type(int which) { return (which==1)?  GL_RGB16I: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==11
    inline GLenum get_type(int which) { return (which==1)?GL_RGBA16UI:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==12
    inline GLenum get_type(int which) { return (which==1)? GL_RGBA16I:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==13 //############ 32-BIT TESTS ############
    inline GLenum get_type(int which) { return (which==1)?   GL_RGB32: GL_RGB; } //token doesn't exist
#elif TYPE==14
    inline GLenum get_type(int which) { return (which==1)?  GL_RGBA32:GL_RGBA; } //token doesn't exist
#elif TYPE==15
    inline GLenum get_type(int which) { return (which==1)? GL_RGB32UI: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==16
    inline GLenum get_type(int which) { return (which==1)?  GL_RGB32I: GL_RGB; } //doesn't work (invalid op)
#elif TYPE==17
    inline GLenum get_type(int which) { return (which==1)?GL_RGBA32UI:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==18
    inline GLenum get_type(int which) { return (which==1)? GL_RGBA32I:GL_RGBA; } //doesn't work (invalid op)
#elif TYPE==19 //############ 32-BIT FLOAT ############
    inline GLenum get_type(int which) { return (which==1)?  GL_RGB32F: GL_RGB; } //works
#elif TYPE==20
    inline GLenum get_type(int which) { return (which==1)? GL_RGBA32F:GL_RGBA; } //works
#endif

GLuint texture;
void create_texture(void) {
    printf("    Status before texture setup: "); error_check();

    glGenTextures(1,&texture);
    glBindTexture(GL_TEXTURE_2D,texture);

    printf("    Status after texture created: "); error_check();

    GLenum data_type = GL_UNSIGNED_BYTE;
    int data_length = TEXTURE_SIZE*TEXTURE_SIZE*4; //maximum number of channels, so it will work for everything
    unsigned char* data = new unsigned char[data_length];
    for (int i=0;i<data_length;++i) {
        data[i] = (unsigned char)(0);
    };

    glTexImage2D(GL_TEXTURE_2D,0,get_type(1), TEXTURE_SIZE,TEXTURE_SIZE, 0,get_type(2),data_type,data);

    printf("    Status after glTexImage2D: "); error_check();

    delete [] data;

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    printf("    Status after texture filters defined: "); error_check();
}

void keyboard(unsigned char key, int x, int y) {
    switch (key) {
        case 27: //esc
            exit(0);
            break;
    }
}

void draw(void) {
    glClearColor(1.0,0.0,0.0,1.0); //in case the quad doesn't draw
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glViewport(0,0,screen_size[0],screen_size[1]);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0,screen_size[0],0,screen_size[1]);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glBegin(GL_QUADS);
    glTexCoord2f(0,0); glVertex2f(0,0);
    glTexCoord2f(2,0); glVertex2f(screen_size[0],0);
    glTexCoord2f(2,2); glVertex2f(screen_size[0],screen_size[1]);
    glTexCoord2f(0,2); glVertex2f(0,screen_size[1]);
    glEnd();

    glutSwapBuffers();
}

int main(int argc, char* argv[]) {
    glutInit(&argc,argv);
    glutInitWindowSize(screen_size[0],screen_size[1]);
    glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
    glutCreateWindow("Texture Types - Ian Mallett");

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);

    printf("Status after OpenGL setup: "); error_check();

    create_texture();

    printf("Status after texture setup: "); error_check();

    glutDisplayFunc(draw);
    glutIdleFunc(draw);
    glutKeyboardFunc(keyboard);

    glutMainLoop();

    return 0;
}
解决方案

OpenGL errors are not that complex to understand. GL_INVALID_ENUM/VALUE are thrown when you pass something an enum or value that is unexpected, unsupported, or out-of-range. If you pass "17" as the internal format to glTexImage2D, you will get GL_INVALID_ENUM, because 17 is not a valid enum number for an internal format. If you pass 103,422 as the width to glTexImage2D, you will get GL_INVALID_VALUE, because 103,422 is almost certainly larger than GL_MAX_TEXTURE_2D's size.

GL_INVALID_OPERATION is always used for combinations of state that go wrong. Either there is some context state previously set that doesn't mesh with the function you're calling, or two or more parameters combined are causing a problem. The latter is the case you have here.

If your implementation didn't support integer textures at all, then you would get INVALID_ENUM (because the internal format is not a valid format). Getting INVALID_OPERATION means that something else is wrong.

Namely, this:

glTexImage2D(GL_TEXTURE_2D,0,get_type(1), TEXTURE_SIZE,TEXTURE_SIZE, 0,get_type(2),data_type,data);

Your get_type(2) call returns GL_RGB or GL_RGBA in all cases. However, when using integral image formats, you must use a pixel transfer format with _INTEGER at the end.

So your get_type(2) needs to be this:

inline GLenum get_type(int which) { return (which==1)? GL_RGB16UI: GL_RGB_INTEGER; }

And similarly for other integral image formats.

这篇关于OpenGL 2 纹理内部格式 GL_RGB8I、GL_RGB32UI 等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 13:25