简体   繁体   English

无法渲染到 GtkGLArea

[英]Can't render to GtkGLArea

I try to render a triangle to a GtkGLArea but I only see the color with which I cleared the frame with glClearColor().我尝试将一个三角形渲染到 GtkGLArea,但我只能看到我使用 glClearColor() 清除帧的颜色。

Please note:请注意:

  • I know that the triangle is so big that it would fill the whole screen, but I also tried smaller ones and it didn't work either.我知道三角形太大了,它会填满整个屏幕,但我也尝试了较小的三角形,但它也不起作用。
  • I also know that I should normally not create the program before each rendering, I only did it here to keep the example short.我也知道我通常不应该在每次渲染之前创建程序,我在这里只是为了保持示例简短。
  • I'm fairly certain that the error is neither in LoadShaders nor in the shaders themselves because I've tried the exact same functions with GLFW and they've worked fine their.我相当确定错误既不在 LoadShaders 也不在着色器本身,因为我已经尝试了与 GLFW 完全相同的功能,并且它们运行良好。

Things which might cause the problem:可能导致问题的事情:

  • I'm not flushing the frame currently or swapping framebuffers because the documentation ( https://developer.gnome.org/gtk3/stable/GtkGLArea.html ) doesn't mention that I have to.我目前没有刷新帧或交换帧缓冲区,因为文档( https://developer.gnome.org/gtk3/stable/GtkGLArea.html )没有提到我必须这样做。 I've tried glFlush() but it didn't help either.我试过 glFlush() 但它也没有帮助。

  • I assume that the screen coordinates go from -1 to 1 on all axis like in normal OpenGL.我假设屏幕坐标在所有轴上从 -1 到 1,就像在普通 OpenGL 中一样。 Maybe that's wrong but I couldn't find anything in the documentation there either.也许那是错误的,但我在那里的文档中也找不到任何内容。

Could somebody help me?有人可以帮助我吗?

This is how I compile it:这是我编译它的方式:

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

This is my code:这是我的代码:

#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;
}

Two things I can think of:我能想到的两件事:

  • You aren't requesting a Core context from the OS.您不是从操作系统请求核心上下文。 Looks like you have to override create-context & create + return a gdk_gl_context_set_required_version 'd GdkGLContext .看起来你必须覆盖create-context & create + return a gdk_gl_context_set_required_version 'd GdkGLContext
  • When you do get a Core context up & going I'm pretty sure you still need a VAO bound even if you're generating geometry entirely within your vertex shader.当您启动并运行Core 上下文时,我很确定您仍然需要 VAO 边界,即使您完全在顶点着色器中生成几何图形。

RE: missing VAOs: RE:缺少 VAO:

With this GLFW program and the VAO creation/bind commented out:用这个 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();
}

Running on Linux with Mesa 13.0.6's llvmpipe backend & the MESA_DEBUG=1 envvar gives me a grey window and this message on stdout:在 Linux 上运行 Mesa 13.0.6 的 llvmpipe 后端和MESA_DEBUG=1 envvar给我一个灰色窗口和 stdout 上的这条消息:

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

Restoring the VAO gives the expected red window.恢复 VAO 会提供预期的红色窗口。

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

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