繁体   English   中英

无法渲染到 GtkGLArea

[英]Can't render to GtkGLArea

我尝试将一个三角形渲染到 GtkGLArea,但我只能看到我使用 glClearColor() 清除帧的颜色。

请注意:

  • 我知道三角形太大了,它会填满整个屏幕,但我也尝试了较小的三角形,但它也不起作用。
  • 我也知道我通常不应该在每次渲染之前创建程序,我在这里只是为了保持示例简短。
  • 我相当确定错误既不在 LoadShaders 也不在着色器本身,因为我已经尝试了与 GLFW 完全相同的功能,并且它们运行良好。

可能导致问题的事情:

  • 我目前没有刷新帧或交换帧缓冲区,因为文档( https://developer.gnome.org/gtk3/stable/GtkGLArea.html )没有提到我必须这样做。 我试过 glFlush() 但它也没有帮助。

  • 我假设屏幕坐标在所有轴上从 -1 到 1,就像在普通 OpenGL 中一样。 也许那是错误的,但我在那里的文档中也找不到任何内容。

有人可以帮助我吗?

这是我编译它的方式:

g++ -O3 -s -o main main.cpp -isystem include -Llibs -DNDEBUG `pkg-config --cflags gtk+-3.0` `pkg-config --libs gtk+-3.0` -lepoxy -lm

这是我的代码:

#include <gtk/gtk.h>
#include <epoxy/gl.h>
#include <epoxy/glx.h>
#include <iostream>
#include <vector>

GLuint LoadShaders(char const* vertex, char const* fragment){

    // Create the shaders
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

    GLint Result = GL_FALSE;
    int InfoLogLength;

    // Compile Vertex Shader
    glShaderSource(VertexShaderID, 1, &vertex , NULL);
    glCompileShader(VertexShaderID);

    // Check Vertex Shader
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> VertexShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
        printf("%s\n", &VertexShaderErrorMessage[0]);
    }

    // Compile Fragment Shader
    glShaderSource(FragmentShaderID, 1, &fragment , NULL);
    glCompileShader(FragmentShaderID);

    // Check Fragment Shader
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
        glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
        printf("%s\n", &FragmentShaderErrorMessage[0]);
    }

    // Link the program
    GLuint ProgramID = glCreateProgram();
    glAttachShader(ProgramID, VertexShaderID);
    glAttachShader(ProgramID, FragmentShaderID);
    glLinkProgram(ProgramID);

    // Check the program
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    if ( InfoLogLength > 0 ){
        std::vector<char> ProgramErrorMessage(InfoLogLength+1);
        glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
        printf("%s\n", &ProgramErrorMessage[0]);
    }

    glDetachShader(ProgramID, VertexShaderID);
    glDetachShader(ProgramID, FragmentShaderID);

    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);

    return ProgramID;
}

char const* vertShader = R"GLSL(
#version 330 core
void main(){
    gl_Position.z = 0.0;
    gl_Position.w = 1.0;
    if (0 == gl_VertexID) {
        gl_Position.x = -100.0;
        gl_Position.y = -100.0;
    }
    if (2 == gl_VertexID) {
        gl_Position.x =  0.0;
        gl_Position.y =  100.0;
    }
    if (1 == gl_VertexID) {
        gl_Position.x =  100.0;
        gl_Position.y = -100.0;
    }
}
)GLSL";

char const* fragShader = R"GLSL(
#version 330 core
layout(location = 0) out vec4 color;
void main(){
    color = vec4(1.0, 0.0, 0.0, 1.0);
}
)GLSL";

gboolean
render(GtkGLArea*, GdkGLContext*, gpointer) {
    glClearColor(0.5, 0.5, 0.5, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    GLuint programID;
    programID = LoadShaders(vertShader, fragShader);

    glUseProgram(programID);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    //glFlush();
    glDeleteProgram(programID);
    return TRUE;
}

int
main(int argc, char** argv) {
    gtk_init(&argc, &argv);

    auto window{gtk_window_new(GTK_WINDOW_TOPLEVEL)};
    auto glWidget{gtk_gl_area_new()};
    gtk_container_add(GTK_CONTAINER(window), glWidget);
    g_signal_connect (glWidget, "render", G_CALLBACK(render), nullptr);
    gtk_widget_show_all(window);

    gtk_main();

    return EXIT_SUCCESS;
}

我能想到的两件事:

  • 您不是从操作系统请求核心上下文。 看起来你必须覆盖create-context & create + return a gdk_gl_context_set_required_version 'd GdkGLContext
  • 当您启动并运行Core 上下文时,我很确定您仍然需要 VAO 边界,即使您完全在顶点着色器中生成几何图形。

RE:缺少 VAO:

用这个 GLFW 程序和 VAO 创建/绑定注释掉:

#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <iostream>

void CheckStatus( GLuint obj, bool isShader )
{
    GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
    ( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
    ( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
    if( status == GL_TRUE ) return;
    std::cerr << (GLchar*)log << "\n";
    std::exit( EXIT_FAILURE );
}

void AttachShader( GLuint program, GLenum type, const char* src )
{
    GLuint shader = glCreateShader( type );
    glShaderSource( shader, 1, &src, NULL );
    glCompileShader( shader );
    CheckStatus( shader, true );
    glAttachShader( program, shader );
    glDeleteShader( shader );
}

const char* vert = 1 + R"GLSL(
#version 330 core
void main(){
    gl_Position.z = 0.0;
    gl_Position.w = 1.0;
    if (0 == gl_VertexID) {
        gl_Position.x = -100.0;
        gl_Position.y = -100.0;
    }
    if (2 == gl_VertexID) {
        gl_Position.x =  0.0;
        gl_Position.y =  100.0;
    }
    if (1 == gl_VertexID) {
        gl_Position.x =  100.0;
        gl_Position.y = -100.0;
    }
}
)GLSL";

const char* frag = 1 + R"GLSL(
#version 330 core
layout(location = 0) out vec4 color;
void main(){
    color = vec4(1.0, 0.0, 0.0, 1.0);
}
)GLSL";

int main( int, char** )
{
    glfwSetErrorCallback( []( int, const char* desc ) { std::cerr << desc << "\n"; std::exit( EXIT_FAILURE ); } );
    glfwInit();
    glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
    glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
    glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE );
    glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
    GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
    glfwMakeContextCurrent( window );
    gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress );

    //GLuint vao = 0;
    //glGenVertexArrays( 1, &vao );
    //glBindVertexArray( vao );

    GLuint prog = glCreateProgram();
    AttachShader( prog, GL_VERTEX_SHADER, vert );
    AttachShader( prog, GL_FRAGMENT_SHADER, frag );
    glLinkProgram( prog );
    CheckStatus( prog, false );

    while( !glfwWindowShouldClose( window ) )
    {
        glfwPollEvents();
        int w, h;
        glfwGetFramebufferSize( window, &w, &h );
        glViewport( 0, 0, w, h );

        glClearColor( 0.5, 0.5, 0.5, 0 );
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        glUseProgram( prog );
        glDrawArrays( GL_TRIANGLES, 0, 3 );
        glfwSwapBuffers( window );
    }

    glfwTerminate();
}

在 Linux 上运行 Mesa 13.0.6 的 llvmpipe 后端和MESA_DEBUG=1 envvar给我一个灰色窗口和 stdout 上的这条消息:

Mesa: User error: GL_INVALID_OPERATION in glDrawArrays(no VAO bound)

恢复 VAO 会提供预期的红色窗口。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM