[OpenGL] render mesh with shaders

Started by
1 comment, last by Dark Engineer 11 years ago

I have code where i initialize mesh:


#ifndef Mesh_h
#define Mesh_h

#include "Texture.h"
#include "Technique.h"
#include <map>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <list>
#include <assimp/Importer.hpp>      // C++ importer interface
#include <assimp/scene.h>       // Output data structure
#include <assimp/postprocess.h> // Post processing flags

struct Vertex
{
    glm::vec3 m_pos;
    glm::vec2 m_tex;
    glm::vec3 m_normal;

    Vertex() {}

    Vertex(const glm::vec3& pos, const glm::vec2& tex, const glm::vec3& normal)
    {
        m_pos    = pos;
        m_tex    = tex;
        m_normal = normal;
    }
};

class Mesh : public Technique
{
	bool init();
	bool initFromScene(const aiScene* pScene, const std::string &Filename);
	void initMesh(unsigned int index, const aiMesh* paiMesh);
	bool initMaterials(const aiScene* pScene, const std::string &Filename);
	void clear();

#define INVALID_MATERIAL 0xFFFFFFFF

	struct MeshEntry
	{
		MeshEntry();

		~MeshEntry();

		void init(const std::vector<Vertex> & vertices, const std::vector<unsigned int> & indices);

		GLuint VB;
		GLuint IB;
		unsigned int numIndices;
		unsigned int materialIndex;
	};
	GLint gSamplerLocation;
	GLint WVPLocation;
	std::vector <MeshEntry> m_Entries;
	std::vector <Texture*> m_Textures;


public:
	Mesh();

	~Mesh();
	
	bool loadMesh(const std::string &filename);

	void render();
};
#endif

#include "Mesh.h"


Mesh::Mesh()
{
}

Mesh::~Mesh()
{
	clear();
}

void Mesh::clear()
{
		for(unsigned int i = 0; i < m_Textures.size(); i++)
			delete m_Textures;
}

Mesh::MeshEntry::MeshEntry()
{
	VB = GL_INVALID_ENUM;
	IB = GL_INVALID_ENUM;
	numIndices = 0;
	materialIndex = INVALID_MATERIAL;
}

Mesh::MeshEntry::~MeshEntry()
{
	if(VB != GL_INVALID_ENUM)
		glDeleteBuffers(1, &VB);
	if(IB != GL_INVALID_ENUM)
		glDeleteBuffers(1, &IB);
}

void Mesh::MeshEntry::init(const std::vector<Vertex> & vertices, const std::vector<unsigned int> & indices)
{
	numIndices = indices.size();
	glGenBuffers(1, &VB);
	glBindBuffer(GL_ARRAY_BUFFER, VB);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * vertices.size(), &vertices[0], GL_STATIC_DRAW);

	glGenBuffers(1, &IB);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * numIndices, &indices[0], GL_STATIC_DRAW);


}

bool Mesh::loadMesh(const std::string & filename)
{
	clear();
	
	bool Ret = false;
	Assimp::Importer importer;

	const aiScene* pScene = importer.ReadFile(filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs);
	if(pScene)
		Ret = initFromScene(pScene, filename);
	else
		std::cout << "Error passing " << filename << " : " << importer.GetErrorString() << std::endl;
	return Ret;
}

bool Mesh::init()
{
	if(!Technique::init())
		return false;
	if(!addShader(Shader::VERTEX_SHADER, "vs.glsl"))
		return false;
	if(!addShader(Shader::FRAGMENT_SHADER, "fs.glsl"))
		return false;
	if(!finalize())
		return false;

	gSamplerLocation = getUniformLocation("gSampler");
	WVPLocation = getUniformLocation("gWVP");

	if(gSamplerLocation == 0xFFFFFFFF || WVPLocation == 0xFFFFFFFF)
		return false;

	return true;
}

bool Mesh::initFromScene(const aiScene* pScene, const std::string &filename)
{
	m_Entries.resize(pScene->mNumMeshes);
	m_Textures.resize(pScene->mNumMaterials);

	for(unsigned int i = 0; i < m_Entries.size(); i++)
	{
		const aiMesh* paiMesh = pScene->mMeshes;
		initMesh(i, paiMesh);
	}
		

	return initMaterials(pScene, filename);
}

void Mesh::initMesh(unsigned int index, const aiMesh* paiMesh)
{
	if(!init())
		std::cout << "Failed to initialize shaders" << std::endl;
	m_Entries[index].materialIndex = paiMesh->mMaterialIndex;

	std::vector <Vertex> vertices;
	std::vector <unsigned int> indices;

	const aiVector3D zero3D(0.0f, 0.0f, 0.0f);

	for(unsigned int i = 0; i < paiMesh->mNumVertices; i++)
	{
		const aiVector3D * pPos = &(paiMesh->mVertices);
		const aiVector3D *pNormal = &(paiMesh->mNormals);
		const aiVector3D *pTextCoord = paiMesh->HasTextureCoords(0) ? &(paiMesh->mTextureCoords[0]) : &zero3D;

		Vertex v(glm::vec3(pPos->x, pPos->y, pPos->z), glm::vec2(pTextCoord->x, pTextCoord->y), glm::vec3(pNormal->x, pNormal->y, pNormal->z));
		vertices.push_back(v);
	}

	for(unsigned int i = 0; i < paiMesh->mNumFaces; i++)
	{
		const aiFace &face = paiMesh->mFaces;
		indices.push_back(face.mIndices[0]);
		indices.push_back(face.mIndices[1]);
		indices.push_back(face.mIndices[2]);
	}

	m_Entries[index].init(vertices, indices);
}

bool Mesh::initMaterials(const aiScene* pScene, const std::string &filename)
{
	 std::string::size_type SlashIndex = filename.find_last_of("/");
    std::string Dir;

    if (SlashIndex == std::string::npos) {
        Dir = ".";
    }
    else if (SlashIndex == 0) {
        Dir = "/";
    }
    else {
        Dir = filename.substr(0, SlashIndex);
    }

    bool Ret = true;

	for(unsigned int i = 0; i < pScene->mNumMaterials; i++)
	{
		const aiMaterial *pMaterial = pScene->mMaterials;
		m_Textures = NULL;
		if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) 
		{
            aiString path;
				

			if(pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS)
			{
				std::string fullPath = Dir + "/" + path.data;

				m_Textures = new Texture(GL_TEXTURE_2D, path.C_Str());
				if(!m_Textures->Load())
				{
					
					std::cout << "Error Loading texture " << path.C_Str() << std::endl;
					delete m_Textures;
					m_Textures = NULL;
					Ret = false;
				}
				else
					std::cout << "Loaded texture " << path.C_Str() << std::endl;
				
			}
		}

		if(!m_Textures)
		{
			std::cout << "No textures" << std::endl;
			m_Textures = new Texture(GL_TEXTURE_2D, "/white.png");
			Ret = m_Textures->Load();
		}
	}

	return Ret;
}

void Mesh::render()
{
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);

	for(unsigned int i = 0; i < m_Entries.size(); i++)
	{
		glBindBuffer(GL_ARRAY_BUFFER, m_Entries.VB);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)12);
		glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)20);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_Entries.IB);

		const unsigned int materialIndex = m_Entries.materialIndex;

		if( materialIndex < m_Textures.size() && m_Textures[materialIndex])
		{
			m_Textures[materialIndex]->Bind(GL_TEXTURE0);
		}

		glDrawElements(GL_TRIANGLES, m_Entries.numIndices, GL_UNSIGNED_INT, 0);
	}

	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glDisableVertexAttribArray(2);
}


but when i try to render it with this methods in render() function it doesn't work, how can i change this code to get it working? Can i make shaders and use it?

Edit// On the screen i see only white color? What to do?

Advertisement

this looks like code from a popular opengl tutorial... if it's the one I think I would suggest to you starting with his first tutorial on getting the triangle to the screen and moving forward from there.. This is using assimp to import a mesh you need to have shaders with certain uniforms in them.. its all easy enough but you should prolly start from before this point... here is a link to the tutorial just in case you got the source from somewhere else...

http://ogldev.atspace.co.uk/

thanks for advice, i'm using this site but not from the beginning, i will try to study it again

This topic is closed to new replies.

Advertisement