2015-09-02 1 views
-4

Я занимаюсь созданием движка игры/рендеринга, и я обнаружил, что у меня может быть класс для объекта шейдера, но если я оберну его VAO в классе, он не будет отображаться.Почему у меня есть класс шейдеров OpenGL, но не класс VAO?

Шейдеры не возвращают ошибок, а VAO и шейдеры являются действительными объектами OpenGL.

Полный Repo находится (см снизу для упрощенной версии) https://github.com/nunziotocci/stackoverflow-question-1

UPDATE

Проблема эта линия:

glBufferData(GL_ARRAY_BUFFER, sizeof(arrFVertex), arrFVertex, GL_STATIC_DRAW); 

Как @BDL предложил в комментариях, я подумал об этом, и я понял, что это должно быть:

glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * intNumVertex * 3, arrFVertex, GL_STATIC_DRAW); 

UPDATE 2 В ответ на который должен быть помещен на удержание, вот Минимальный полный и проверяемый Пример:

#include <OpenGL/gl3.h> 
#include <SDL2/SDL.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

SDL_Window *window = NULL; 
SDL_GLContext openGLRenderer; 
bool bolRunning = true; 
int intGLVersionMajor, intGLVersionMinor; 

GLfloat arrFVertex[] = { 
    0.5f, 0.5f, 0.0f, // Top Right 
    0.5f, -0.5f, 0.0f, // Bottom Right 
    -0.5f, 0.5f, 0.0f, // Top Left 

    0.5f, -0.5f, 0.0f, // Bottom Right 
    -0.5f, -0.5f, 0.0f, // Bottom Left 
    -0.5f, 0.5f, 0.0f // Top Left 
}; 
GLuint intVAO; 
GLuint intVBO; 
GLuint intShaderAttribPosition; 
GLuint intShaderProgram; 
GLuint intNumVertex = 6; 

void loadShaders(const char *strVertexShaderSource, const char *strFragmentShaderSource) { 
    intShaderProgram = glCreateProgram(); 

    GLuint intVertexShader; 
    intVertexShader = glCreateShader(GL_VERTEX_SHADER); 
    glShaderSource(intVertexShader, 1, &strVertexShaderSource, NULL); 
    glCompileShader(intVertexShader); 

    GLuint intFragmentShader; 
    intFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    glShaderSource(intFragmentShader, 1, &strFragmentShaderSource, NULL); 
    glCompileShader(intFragmentShader); 

    glAttachShader(intShaderProgram, intVertexShader); 
    glAttachShader(intShaderProgram, intFragmentShader); 
    glLinkProgram(intShaderProgram); 

    glDeleteShader(intVertexShader); 
    glDeleteShader(intFragmentShader); 
} 

void buildVAO(GLfloat *arrFVertex) { 
    intShaderAttribPosition = glGetAttribLocation(intShaderProgram, "f3Position"); 

    glGenVertexArrays(1, &intVAO); 
    glBindVertexArray(intVAO); 

    glGenBuffers(1, &intVBO); 
    glBindBuffer(GL_ARRAY_BUFFER, intVBO); 

    glVertexAttribPointer(intShaderAttribPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid *)0); 
    glEnableVertexAttribArray(intShaderAttribPosition); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(arrFVertex), arrFVertex, GL_STATIC_DRAW); 

    glBindVertexArray(0); 
} 

int main(int argc, char **argv) { 
    SDL_Init(SDL_INIT_EVERYTHING); 

    window = SDL_CreateWindow("GSEngine", 
           SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 
           640, 480, 
           SDL_WINDOW_OPENGL); 

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); 
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 

    if (window == NULL) { 
     printf("Could not create window: %s\n", SDL_GetError()); 
     exit(1); 
    } 

    openGLRenderer = SDL_GL_CreateContext(window); 

    SDL_GL_MakeCurrent(window, openGLRenderer); 
    glViewport(0, 0, 640, 480); 

    loadShaders("#version 330 core\n\ 
       in vec3 f3Position;\n\ 
       void main() {\n\ 
        gl_Position = vec4(f3Position, 1.0);\n\ 
       }", "#version 330 core\n\ 
       out vec4 f4Color;\n\ 
       void main() {\n\ 
        f4Color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n\ 
       }"); 

    buildVAO(arrFVertex); 

    while (bolRunning) { 
     SDL_Event event; 
     while (SDL_PollEvent(&event)) { 
      if (event.type == SDL_QUIT) { 
       bolRunning = false; 
      } 
     } 

     SDL_GL_MakeCurrent(window, openGLRenderer); 
     glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

     glUseProgram(intShaderProgram); 
     glDrawArrays(GL_TRIANGLES, 0, intNumVertex); 

     SDL_GL_SwapWindow(window); 
    } 

    glDeleteBuffers(1, &intVBO); 
    glDeleteVertexArrays(1, &intVAO); 
    glDeleteShader(intShaderProgram); 

    SDL_GL_DeleteContext(openGLRenderer); 
    SDL_DestroyWindow(window); 
    SDL_Quit(); 

    return 0; 
} 
+1

Приобретение кода в классе или его отсутствие не имеет значения, пока вызываются все правильные команды OpenGL. Я думаю, вам стоит попытаться сделать [MCVE] (http://stackoverflow.com/help/mcve) вместо того, чтобы ожидать, что мы загрузим весь ваш репозиторий. Кроме того, когда вы меняете код, эти вопросы становятся бесполезными для будущих читателей. – vesan

+0

Я планировал оставить это репо в одиночку, и я не уверен, как сделать его более минимальным, но я попробую. –

+0

ОК, справедливо. Вы отмечаете, что это не сработает, когда вы завершаете свое VAO в классе. Означает ли это, что вы пробовали версию без класса VAO, и это сработало? Если это так, может быть полезно найти различия в этом коде. – vesan

ответ

2

Проблема не имеет ничего общего с ВАО, но с VBO. Так как вы передаете указатель на конструктор:

void GSMesh::build(GLfloat *arrFVertex, GSShader *shader, int _intNumVertex) 
{ 
    glBufferData(GL_ARRAY_BUFFER, sizeof(arrFVertex), arrFVertex, GL_STATIC_DRAW); 
} 

sizeof(arrFVertex) = sizeof(void*) который является размер указателя, а не размер массива указал. Правильный код будет выглядеть следующим образом:

glBufferData(GL_ARRAY_BUFFER, 
      sizeof(GLfloat) * _intNumVertex * 3, arrFVertex, 
      GL_STATIC_DRAW); 

В общем, я должен добавить, что это не так, как вопросы следует задавать на SO. Было бы хорошо, если бы вы включили по крайней мере часть кода в свой вопрос.

+0

Единственная причина, по которой я делал репозиторий github, заключался в том, что я не делал вопрос слишком длинным, а также, я не был уверен, какая функция конкретно была проблемой, но вы показали мне, и сейчас это супер очевидно , –

+0

Отвечая на них, вы призываете людей задавать такие вопросы. –

+0

Определенно верно. – BDL

1

Несмотря на то, что говорит спецификации, с некоторыми драйверами вы должны включить шейдер, прежде чем вы можете получить расположение атрибута или униформы. Это может быть причиной ваших проблем.

В коде это будет означать, в методе GSmesh :: построения добавления:

shader->use(); 

До:

intShaderAttribPosition = glGetAttribLocation(shader->intShaderProgram, "f3Position"); 

Лично если версия OpenGL, который вы используете имеет поддержку Vertex Attribute Indexes I Вместо этого используйте их.

В вершинном шейдере вы могли бы иметь что-то вроде:

layout (location = 0) in vec3 position; 
layout (location = 1) in vec2 tex_coords; 

А потом в классе сетки все, что вам нужно:

struct Vertex 
{ 
    glm::vec3 position; 
    glm::vec2 tex_coords; 
}; 

glEnableVertexAttribArray(0); 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, position); 

glEnableVertexAttribArray(1); 
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, tex_coords)); 
Смежные вопросы