Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
488 views
in Technique[技术] by (71.8m points)

c++ - Why can I have an OpenGL shader class, but not a VAO class?

I have been fiddling around with making a game/rendering engine, and I have found that I can have a class for a shader object, but if I wrap a VAO in a class, it won't render.

The shaders return no errors, and the VAO and shaders are valid OpenGL objects.

UPDATE

The problem is this line:

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

As @BDL suggested in the comments, I thought about it and I realized, it should be:

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

UPDATE 2 In response to being put on hold, here is a Minimum Complete and Verifiable Example:

#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
", SDL_GetError());
        exit(1);
    }
    
    openGLRenderer = SDL_GL_CreateContext(window);
    
    SDL_GL_MakeCurrent(window, openGLRenderer);
    glViewport(0, 0, 640, 480);
    
    loadShaders("#version 330 core

                in vec3 f3Position;

                void main() {

                    gl_Position = vec4(f3Position, 1.0);

                }", "#version 330 core

                out vec4 f4Color;

                void main() {

                    f4Color = vec4(1.0f, 0.5f, 0.2f, 1.0f);

                }");
    
    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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The problem has nothing to do with the VAO, but with the VBO. Since you pass a pointer to the constructor:

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

sizeof(arrFVertex) = sizeof(GLfloat*) which is the size of the pointer, not the size of the array pointed to. The correct code will look like this:

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

In general I have to add, that this is not the way how questions should be asked on SO. It would have been good if you would have included at least the relevant parts of the code in your question.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...