Не удается отобразить в GtkGLArea - PullRequest
2 голосов
/ 26 марта 2019

Я пытаюсь отобразить треугольник в 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;
}

1 Ответ

2 голосов
/ 26 марта 2019

Две вещи, о которых я могу думать:

  • Вы не запрашиваете основной контекст из ОС. Похоже, вам нужно переопределить create-context и создать + вернуть gdk_gl_context_set_required_version 'd GdkGLContext.
  • Когда вы делаете запускаете и работаете с базовым контекстом, я почти уверен, что вам все еще нужен предел 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 с бэкэндом llvmpipe в Mesa 13.0.6 & MESA_DEBUG=1 envvar дает мне серое окно и это сообщение на stdout:

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

Восстановление VAO дает ожидаемое красное окно.

...