faeophyta faeophyta - 3 months ago 10
C++ Question

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?

Answer

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()
{
 //...
}