0
votes

I'm creating a set of classes to read in 3d objects from COLLADA files. I started with some basic code to read in the positions and normals and plot them with opengl. I added code to scale the vertices successfully and added all the code I need to read in the color or texture connected with each graphics element in the COLLAD file. But now I need to add the code to draw the vertices with color. I have created the buffer object array to house the color array for each of the vertices array and buffer objects. This is the code I have to build the arrays from data I obtain from the COLLADA file: Keep in mind I am still creating this it's not perfect.

// Set vertex coordinate data
        glBindBuffer(GL_ARRAY_BUFFER, vbosPosition[i]);
        glBufferData(GL_ARRAY_BUFFER, col->vectorGeometry[i].map["POSITION"].size,
            scaledData, GL_STATIC_DRAW);
        free(scaledData);


        loc = glGetAttribLocation(program, "in_coords");//get a GLuint for the attribute and put it into GLuint loc.
        glVertexAttribPointer(loc, col->vectorGeometry[i].map["POSITION"].stride, col->vectorGeometry[i].map["POSITION"].type, GL_FALSE, 0, 0);//glVertexAttribPointer — loc specifies the index of the generic vertex attribute to be modified.
        glEnableVertexAttribArray(0);
#ifdef Testing_Mesh3D
        PrintGLVertex(vbosPosition[i], col->vectorGeometry[i].map["POSITION"].size / 4);
#endif      // Set normal vector data
        glBindBuffer(GL_ARRAY_BUFFER, vbosNormal[i]);
        glBufferData(GL_ARRAY_BUFFER, col->vectorGeometry[i].map["NORMAL"].size, col->vectorGeometry[i].map["NORMAL"].data, GL_STATIC_DRAW);
        loc = glGetAttribLocation(program, "in_normals");
        glVertexAttribPointer(loc, col->vectorGeometry[i].map["NORMAL"].stride, col->vectorGeometry[i].map["NORMAL"].type, GL_FALSE, 0, 0);
        glEnableVertexAttribArray(1);
        glBindBuffer(GL_ARRAY_BUFFER, vbosColor[i]);
        Material* material = col->mapGeometryUrlToMaterial2Effect[col->vectorGeometry[i].id];
        if (material->effect1.size() > 0)
        {
            Effect effect1 = material->effect1[0];
            if (effect1.type == enumEffectTypes::color)
            {
                Color color = effect1.color;
                glBufferData(GL_ARRAY_BUFFER, color.length, color.values, GL_STATIC_DRAW);
                loc = glGetAttribLocation(program, "in_colors");
                glVertexAttribPointer(loc, color.length, color.type, GL_FALSE, 0, 0);

            }
            else
            {

            }

        }

    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

// Initialize uniform data
void Mesh3D::InitializeUniforms(GLuint program) {

    GLuint program_index, ubo_index;
    struct LightParameters params;

    // Specify the rotation matrix
    glm::vec4 diff_color = glm::vec4(0.3f, 0.3f, 1.0f, 1.0f);
    GLint location = glGetUniformLocation(program, "diffuse_color");
    glUniform4fv(location, 1, &(diff_color[0]));

    // Initialize UBO data
    params.diffuse_intensity = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f);
    params.ambient_intensity = glm::vec4(0.3f, 0.3f, 0.3f, 1.0f);
    params.light_direction = glm::vec4(-1.0f, -1.0f, 0.25f, 1.0f);

    // Set the uniform buffer object
    glUseProgram(program);
    glGenBuffers(1, &ubo);
    glBindBuffer(GL_UNIFORM_BUFFER, ubo);
    glBufferData(GL_UNIFORM_BUFFER, 3 * sizeof(glm::vec4), &params, GL_STREAM_DRAW);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
    glUseProgram(program);

    // Match the UBO to the uniform block
    glUseProgram(program);
    ubo_index = 0;
    program_index = glGetUniformBlockIndex(program, "LightParameters");
    glUniformBlockBinding(program, program_index, ubo_index);
    glBindBufferRange(GL_UNIFORM_BUFFER, ubo_index, ubo, 0, 3 * sizeof(glm::vec4));
    glUseProgram(program);

This is a hearder file containing the two string literals I housing the strings used to build the vertex and fragment shader. Again I am new to this and not sure how I need to modify the shader to include colored vertices, I have started by adding an input vec4 for the four float colour ( includes alpha). Any help?

#pragma once
#ifndef Included_shaders
#define Included_shaders

#include<stdio.h>
#include<iostream>
static std::string  shaderVert = "#version 330\n"
"in vec3 in_coords;\n"
"in vec3 in_normals;\n"
"in vec4 in_colors; \n"//added by me
"out vec3 vertex_normal;\n"
"void main(void) {\n"
"vertex_normal = in_normals;\n"
"gl_Position = vec4(in_coords, 1.0);\n"
"}\n";

static std::string shaderFrag = "#version 330\n"
"in vec3 vertex_normal;\n"
"out vec4 output_color;\n"
"layout(std140) uniform LightParameters{\n"
"vec4 diffuse_intensity;\n"
"vec4 ambient_intensity;\n"
"vec4 light_direction;\n"
"};\n"
"uniform vec4 diffuse_color;\n"
"void main() {\n"
"/* Compute cosine of angle of incidence */\n"
"float cos_incidence = dot(vertex_normal, light_direction.xyz);\n"
"cos_incidence = clamp(cos_incidence, 0, 1);\n"
"/* Compute Blinn term */\n"
"vec3 view_direction = vec3(0, 0, 1);\n"
"vec3 half_angle = normalize(light_direction.xyz + view_direction);\n"
"float blinn_term = dot(vertex_normal, half_angle);\n"
"blinn_term = clamp(blinn_term, 0, 1);\n"
"blinn_term = pow(blinn_term, 1.0);\n"
"/* Set specular color and compute final color */\n"
"vec4 specular_color = vec4(0.25, 0.25, 0.25, 1.0);\n"
"output_color = ambient_intensity * diffuse_color +\n"
"diffuse_intensity * diffuse_color * cos_incidence +\n"
"diffuse_intensity * specular_color * blinn_term;\n"
"}\n";
#endif

Finally this is the funciton I am modifying to draw the colored elements

void Mesh3D::DrawToParent()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw elements of each mesh in the vector
    for (int i = 0; i<nVectorGeometry; i++)
    {
        glBindVertexArray(vaos[i]);
        glDrawElements(col->vectorGeometry[i].primitive/*This is 4 for GL_Triangles*/, col->vectorGeometry[i].index_count,
            GL_UNSIGNED_SHORT, col->vectorGeometry[i].indices);
    }
    glBindVertexArray(0);
    glutSwapBuffers();
}

am getting a little confused about the glVertexAttribPointer and glGetAttribLocation though I think I get the basic idea. Am I using this right.

Am I setting up the buffer object for colors correctly. Am I correct I have a color for each vertex in this buffer, right now I have only placed the single color that applies to all associated buffers in this array and probably need to change that?

How exactly do I go about drawing the colored vertices when I call glDrawElements?

Don't just refer me to the resources for opengl a lot of the wordy explanations make little sense to me.

1
Kinda offtopic: You should store your shaders in files. Makes them easier to code and you can swap them at runtime if you don't hardcode them.Joonazan
You say you don't want OpenGL resources, but have you tried this one? opengl-tutorial.org/intermediate-tutorials/…Joonazan

1 Answers

0
votes

Make your vertex shader output color and make the fragment shader take it as input. The color will be interpolated between vertices.

Yes, it seems you have understood glAttribPointer correctly.

DrawElements takes the indices of the vertices you want to draw. The last argument should not contain the indices. Instead, it should probably be null. The indices should be specified with glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...).

If the color buffer is correctly bound you don't need to do anything special id drawElements for the colors. The shaders will get all the enabled attribarrays.

I can help you better if you run the code and you tell me what problems you get. It would also help if the code was easier to read. If you split it into functions under ten lines in length you may spot some errors yourself and possibly remove some duplication.