Search code examples
c++openglglslassimp

Passing color to Assimp model's GLSL shader 1.40 on Intel HD 4000


I'm trying to pass color attributes to each point of a 3d model imported by assimp via the vertex shader.

Attempted solutions:

  1. Pass in via layout (location = 0) in vec3 color;

My laptop has Intel HD 4000 graphics which do not support #extension ARB_explicit_attrib_location : require. I am running GLSL 140 which requires the #extension for layout to work.

  1. Have a separate vector of color values whose indices match those of the points and pass in as another attribute.

Did not work. **Edit (what didn't work): ** the shader never received the color passed by main.cpp.

My code

part of main.cpp

GLuint program_id = LoadShaders("pointcloud.vert", "pointcloud.frag");
ObjLoader *obj_loader = new ObjLoader();
int result = 0;
if (argc > 1) result = obj_loader->loadAsset(argv[1]);
else{ result = obj_loader->loadAsset("obj_samples/Heart.stl"); rotateY = 0.75f; rotateX = 0.5f;}
if (result){glfwTerminate(); exit(EXIT_FAILURE);}
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

GLuint matrix_id = glGetUniformLocation(program_id, "MVP");//get the location for our "MVP" uniform variable
GLfloat *g_vertex_buffer_data = (GLfloat*)malloc(obj_loader->getNumVertices()*sizeof(GLfloat));//use a large buffer to store the entire scene
obj_loader->loadVertices(g_vertex_buffer_data);//load the scene into the vertex buffer
GLint attribute_vertex = glGetAttribLocation(program_id, "vertex_pos");//get the location for the attribute variables
GLuint vertex_array_id;//generate the Vertex Array Object (Depedency: GLEW)
GLuint vertex_buffer[2];//initialize the vertex buffer memory (similar to malloc)
GLuint color_buffer;
glGenVertexArrays(1, &vertex_array_id); //create the VAO
glBindVertexArray(vertex_array_id); // bind the VAO
glGenBuffers(1, vertex_buffer); //create vertex buffer
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]); //bind the buffer
glBufferData(GL_ARRAY_BUFFER, obj_loader->getNumVertices()*sizeof(GLfloat), g_vertex_buffer_data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vec3d), 0);
glEnableVertexAttribArray(attribute_vertex);//enable
glUseProgram(program_id);//use our shader
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glPointSize(3.0f);

LoadShaders():

GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path){//load the shader programs and return the id
GLuint vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);//create the vertex and fragment shaders
GLuint fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
std::string vertex_shader_code = readSourceFile(vertex_file_path);//read the shader and fragment programs into string
if(vertex_shader_code == "")return 0; //failed because empty string
printf("Compiling Vertex shader : %s\n", vertex_file_path);
CompileShader(vertex_shader_code, vertex_shader_id);
std::string fragment_shader_code = readSourceFile(fragment_file_path);//load the fragment program (optional)
if(fragment_shader_code == "")return 0; //failed: empty string
printf("Compiling Fragment shader : %s\n", fragment_file_path);//compile the fragment shader
CompileShader(fragment_shader_code, fragment_shader_id);
GLint result = GL_FALSE;
int infolog_length;
printf("Linking program\n");//link the program
GLuint program_id = glCreateProgram();
glAttachShader(program_id, vertex_shader_id);
glAttachShader(program_id, fragment_shader_id);
glLinkProgram(program_id);
glGetProgramiv(program_id, GL_LINK_STATUS, &result);//check the program and ensure that the program is linked properly
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &infolog_length);
if ( infolog_length > 0 ){
    std::vector<char> program_error_msg(infolog_length+1);
    glGetProgramInfoLog(program_id, infolog_length, NULL, &program_error_msg[0]);
    printf("%s\n", &program_error_msg[0]);
}else{
    printf("Linked Successfully\n");
}
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
return program_id;

}

pointcloud.vert:

#version 140
uniform mat4 MVP;
out vec4 colorV;
in vec3 vertex_pos;

void main(){
    gl_Position =  MVP * vec4(vertex_pos, 1.0f);// Output position of the vertex, in clip space : MVP * position
    colorV = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}

I have a std::vector of rgb values I'd like to pass to the shader - any recommendations to achieve this seemingly simple behavior?


Solution

  • Judging from your comment I assume that I misunderstood the problem. If you want to pass vertex-colors from assimp into the shader, you need to define another vertex attribute. To do this, you need to create another buffer after the vertex buffer:

    GLfloat* colorData = (GLfloat*)malloc(sizeof(GLfloat)*obj_loader->getNumVertices()*3);
    obj_loader->loadColors(colorData);//or however you named it
    Gluint colorBuffer;
    glGenBuffers(1, &colorBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Glfloat)*obj_loader->getNumVertices()*3, colorData, GL_STATIC_DRAW);
    glBindAttribLocation(program_id, 0, "vertex_pos");
    glBindAttribLocation(program_id, 1, "colorData");
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    //... continue with your code
    

    Vertex Shader:

    #version 140
    in vec3 vertex_pos;
    in vec3 colorData;
    out vec4 colorV;
    
    uniform mat4 MVP;
    
    void main()
    {
     //...
    }