I'm working on a 3D model loader. It can loads my own format. I wrote my own exporter for Blender, it works well. The model format can handle multiple meshes(objects) in one model. Each mesh can have a different texture. I've already written a loader which is working well, but doesn't use shaders.
I switched to shaders, but something is going wrong, the textures aren't appear correctly. Here is my drawing function, I'm sure the mistake is somewhere here:
void CModel::draw(glm::mat4 &MVP)
{
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
for(unsigned int i=0; i<m_numObjects; i++)
{
glUseProgram(m_programID);
glUniformMatrix4fv(m_matrixUniform, 1, GL_FALSE, &MVP[0][0]);
glBindTexture(GL_TEXTURE_2D, m_textureIDs[i]);
glUniform1i(m_textureUniform, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
// vertices
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0, // must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
sizeof(float)*8, // stride
(void*)0 // array buffer offset
);
// UVs
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(float)*8,
(void*)6
);
glDrawArrays(GL_TRIANGLES, 0, m_numElements[i]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_TEXTURE_2D);
}
The vertex and fragment shaders are also working well.
The previous version (without shaders) was this (this worked well):
void CModel::draw()
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
for(unsigned int i=0; i<m_numObjects; i++)
{
glBindTexture(GL_TEXTURE_2D, m_textureIDs[i]);
glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
glTexCoordPointer(2, GL_FLOAT, sizeof(float)*8, (float*)(sizeof(float)*6));
glNormalPointer( GL_FLOAT, sizeof(float)*8, (float*)(sizeof(float)*3));
glVertexPointer( 3, GL_FLOAT, sizeof(float)*8, 0);
glDrawArrays(GL_TRIANGLES, 0, m_numElements[i]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
Here is the entire class:
#include "global.h"
#include "CModel.h"
#include "CModelLoader.h"
#include "CShaderLoader.h"
CModel::CModel(){}
CModel::~CModel()
{
// TODO free memory
}
/** @brief Load mbm file
*
* @fileName: mdm model file name we want to load and draw
*/
void CModel::init(char *fileName)
{
CModelLoader loader;
CShaderLoader shaders;
loader.loadData(fileName);
loader.createDataArray( m_dataArray,
m_dataArraySizes,
m_numObjects,
m_numElements,
m_textureIDs );
glGenVertexArrays(1, &m_vertexArrayID);
glBindVertexArray(m_vertexArrayID);
m_programID = shaders.loadShaders("vertexshader.vert", "fragmentshader.frag");
m_bufferIDs = new unsigned int[m_numObjects];
glGenBuffers(m_numObjects, m_bufferIDs);
for(unsigned int i=0; i<m_numObjects; i++)
{
glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*m_dataArraySizes[i], m_dataArray[i], GL_STATIC_DRAW);
}
}
/** @brief Drawing the mdm model
*
*/
void CModel::draw(glm::mat4 &MVP)
{
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
for(unsigned int i=0; i<m_numObjects; i++)
{
glUseProgram(m_programID);
unsigned int matrixUniform = glGetUniformLocation(m_programID, "MVP");
unsigned int textureUniform = glGetUniformLocation(m_programID, "myTextureSampler");
glUniformMatrix4fv(matrixUniform, 1, GL_FALSE, &MVP[0][0]);
glUniform1i(textureUniform, 0);
glBindTexture(GL_TEXTURE_2D, m_textureIDs[i]);
glBindBuffer(GL_ARRAY_BUFFER, m_bufferIDs[i]);
// vertices
glEnableVertexAttribArray(0);
glVertexAttribPointer(
0, // must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
sizeof(float)*8, // stride
(void*)0 // array buffer offset
);
// UVs
glEnableVertexAttribArray(1);
glVertexAttribPointer(
1,
2,
GL_FLOAT,
GL_FALSE,
sizeof(float)*8,
(void*)6
);
glDrawArrays(GL_TRIANGLES, 0, m_numElements[i]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_TEXTURE_2D);
}
Finally I solved it. The problem was that I used one array for vertices, normals and texture coordinates instead of storing in separate arrays and bind them separately.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.