如果我正在编写自己的函数来检查着色器编译错误,或者执行任何与OpenGL API交互但最终由于我的应用程序代码返回的操作,则应使用C ++ voidGLvoid吗? IE

GLvoid Shader::check_compile_errors(GLuint ComputeShader, std::string type)
{
    const GLint log_length{ 1024 };
    GLchar info_log[log_length];
    GLint success;

    if (type == "PROGRAM")
    {
        glGetProgramiv(ComputeShader, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(ComputeShader, log_length, nullptr, info_log);
            std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << info_log << "\n ---- " << std::endl;
        }
    }
 // Here the return is implicitly void, but from C++ not OpenGL!
}


我在这里意识到GLvoid是类型定义为无效的,但是我想知道是否有任何情况下使用GL类型会导致问题尚不清楚这些值是来自OpenGL。另一个示例是将图像写入文件(来自glReadPixels)。如果我在标头中设置字段(通常采用unsigned char的形式),我应该将其更改为GLuchar吗?

#1 楼

是的,在与OpenGL交互时有时会不使用GL类型:GLvoid。完全没有理由使用这种类型。

对于其他所有功能(假设您使用的是“标准” OpenGL加载器),在与OpenGL进行对话时都应使用OpenGL的类型。也就是说,传递给OpenGL函数的值应为OpenGL的类型。这可能意味着与OpenGL对话的函数可能在其函数参数列表中需要OpenGL数据类型。应该尽可能避免这种情况,以防止您在OpenGL代码和非OpenGL代码之间创建依赖关系。

但是,如果您不介意应用程序的大部分依赖于OpenGL,则可以在整个代码中可能会使用OpenGL的数据类型。

OpenGL的数据类型被指定为具有特定的位深度。这样,它们就可以指针转换为<stdint.h>/<cstdint>中定义的某些类型(从概念上来说,如果严格来讲不是严格的C ++)。实际上,许多OpenGL标头都会检查此标头的存在,并在可用于定义OpenGL数据类型的任何地方使用它。因此,如果您想要一个固定的位深整数,除了使用OpenGL的数据类型外,您还有选择的余地。


我想知道在任何情况下使用GL类型是否会引起问题?并不清楚是否来自OpenGL。


OpenGL是C,不是魔术。 C语言中的函数无法控制调用它的函数的返回值。甚至C ++函数也不能;充其量,它可以引发异常,但这仍然与调用方的返回值无关。

评论


$ \ begingroup $
因此,总而言之,即使在与OpenGL对话时,也不要使用GLvoid,而在与OpenGL对话时仅使用GLtypes。如果您的代码中需要不与OpenGL对话的固定位深整数,请使用cstdint?
$ \ endgroup $
– Startec
17年11月12日在2:32



$ \ begingroup $
为什么不使用GLvoid?
$ \ endgroup $
– Startec
17年11月12日在2:37

$ \ begingroup $
GLuint的含义不同于基本类型unsigned int。 GLvoid和void没有什么不同。
$ \ endgroup $
–尼科尔·波拉斯(Nicol Bolas)
17年11月12日在2:47

$ \ begingroup $
@Startec:标头将根据其使用的平台重新定义GLuint。 GLvoid将始终被定义为void。
$ \ endgroup $
–尼科尔·波拉斯(Nicol Bolas)
17年11月13日在20:18

$ \ begingroup $
@Startec您也可以使用问题中使用的逻辑来查看它。 GLuint很有意义,因为您可以将该值传达给GL,因此可以将其放入GL函数中,也可以从GL函数返回它。但是那个GLvoid函数是您的函数,一个C ++函数无论如何都不会返回任何东西,更不用说GL值了,您不会返回glWhatever(...);,因为您不会返回任何东西。 void只是不是有意义的数据类型,其表示形式将具有任何相关性,因为它没有任何意义。
$ \ endgroup $
–克里斯蒂安·劳(Christian Rau)
17年11月15日在10:58



#2 楼

GL的类型不是真实类型,但平台类型为typedef。因此,当您考虑GLuintunsigned int时,应该以与unsigned intuint32_t相同的方式考虑。如果您只为单个平台编写,则应阅读系统的GL/gl.h,并注意以下内容:

typedef unsigned int    GLenum;
typedef unsigned char   GLboolean;
typedef unsigned int    GLbitfield;
typedef void        GLvoid;
typedef signed char GLbyte;     /* 1-byte signed */
typedef short       GLshort;    /* 2-byte signed */
typedef int     GLint;      /* 4-byte signed */
typedef unsigned char   GLubyte;    /* 1-byte unsigned */
typedef unsigned short  GLushort;   /* 2-byte unsigned */
typedef unsigned int    GLuint;     /* 4-byte unsigned */
typedef int     GLsizei;    /* 4-byte signed */
typedef float       GLfloat;    /* single precision float */
typedef float       GLclampf;   /* single precision float in [0,1] */
typedef double      GLdouble;   /* double precision float */
typedef double      GLclampd;   /* double precision float in [0,1] */


如果编码标准说明您应该始终使用旧的C类型而不是像uint32_t这样的保证宽度类型,并且应该避免不必要的强制转换,也许只使用适当的本机类型而不是GL名称是有意义的。正如Nicol Bolas所说,它避免了必须包含GL/gl.h。如果您的编码标准更喜欢使用保证宽度类型,则可能有必要继续在非GL代码中使用它们,并在将它们传递给采用GL类型名称的函数时进行更仔细的考虑。 />如果您尽可能避免显式强制转换,并且在启用警告的情况下进行编译,则切换到typedef有所不同的新平台会容易得多,因为编译器会警告您有关可能会丢失信息的数值转换。如果您将GLint从(例如)显式转换为int,然后移至int是16位且GLinttypedef的平台,则显式转换将停止编译器警告您变窄转换。 >