Jump to content

  • Log In with Google      Sign In   
  • Create Account

How can I use multiple shaders in one mesh?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
3 replies to this topic

#1 ShotoReaper   Members   -  Reputation: 149

Like
0Likes
Like

Posted 20 December 2012 - 06:16 PM

Hi!
I want to apply multiple shader to one mesh. I get the vertex from OBJ file, I load with VAO, IBO and I draw with glElementsDraw()

class Cube,
class Mesh
Mesh::Mesh(){}
Mesh::~Mesh()
{
    glDeleteBuffers(2, &BufferIds[1]);
glDeleteVertexArrays(1, &BufferIds[0]);
ExitOnGLError("ERROR: No se pueden destruir los buffer objects");
}
void Mesh::Initialize()
{
    // Creamos el VAO
    glGenVertexArrays(1, &BufferIds[0]);
    ExitOnGLError("ERROR: No se puede generar el VAO");
    glBindVertexArray(BufferIds[0]);
    ExitOnGLError("ERROR: No se puede bindear el VAO");
    // Activamos dos vertex attribute locations
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    ExitOnGLError("ERROR: No se puede activar los vertex attributes");
    // Creamos los VBO
    glGenBuffers(2, &BufferIds[1]);
    ExitOnGLError("ERROR: No se pueden generar los buffer objects");
    // Bindeamos el VBO al VAO
    glBindBuffer(GL_ARRAY_BUFFER, BufferIds[1]);
    glBufferData(GL_ARRAY_BUFFER, vtn.size()*sizeof(VertexTextureNormal), &vtn[0], GL_STATIC_DRAW);
    ExitOnGLError("ERROR: No se puede bindear el VBO al VAO");
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vtn[0]) ,0);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vtn[0]) , (GLvoid*) sizeof(vtn[0].position));
    ExitOnGLError("ERROR: Could not set VAO attributes");
    // Creamos el IBO
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, BufferIds[2]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices.front(), GL_STATIC_DRAW);
    ExitOnGLError("ERROR: No se puede bindear el IBO al VAO");
    glBindVertexArray(0);
}
void Mesh::Draw()
{
    glBindVertexArray(BufferIds[0]);
    ExitOnGLError("ERROR: No se puede bindear el VAO para dibujar");
    glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (GLvoid*)0);
    ExitOnGLError("ERROR: No se puede dibujar el mesh");
    glBindVertexArray(0);
}
void Mesh::Load(std::string filename)
{
    // ifstream: clase para leer archivos que recibe como parametros
    //la ruta del archivo y  un indicador del tipo de operacion
    std::string mesh_source = OpenFile(filename, std::ios::in);
    std::istringstream iss(mesh_source);
    std::vector<glm::vec4> f_vertices;
    std::vector<glm::vec2> f_texcoords;
    std::vector<glm::vec3> f_normals;
    std::vector<int> f_indices;
    // string que representa una linea del archivo
    std::string line;
    // Avanzamos linea a linea del archivo
    while(std::getline(iss, line))
    {
	    // Si es un vertice
	    if (line.substr(0,2) == "v ")
	    {
		    // istringstream: para hacer operaciones de stream sobre una cadena. Recibe como parametro el string
		    std::istringstream s(line.substr(2));
		    glm::vec4 t_v;
		    s >> t_v.x;
		    s >> t_v.y;
		    s >> t_v.z;
		    t_v.w = 1.0f;
		    f_vertices.push_back(t_v);
	    }else
	    if(line.substr(0,2) == "vt")    // si es un texcoord
	    {
		    // istringstream: para hacer operaciones de stream sobre una cadena. Recibe como parametro el string
		    std::istringstream s(line.substr(2));
		    glm::vec2 t_vt;
		    s >> t_vt.x;
		    s >> t_vt.y;
		    f_texcoords.push_back(t_vt);
	    }else
	    if(line.substr(0,2) == "vn")    // si es un normal
	    {
		    // istringstream: para hacer operaciones de stream sobre una cadena. Recibe como parametro el string
		    std::istringstream s(line.substr(2));
		    glm::vec3 t_vn;
		    s >> t_vn.x;
		    s >> t_vn.y;
		    s >> t_vn.z;
		    f_normals.push_back(t_vn);
	    }else
	    if(line.substr(0,2) == "f ")    // Si son indices
	    {
		    std::string s;
		    int i = 0;
		    while (i < line.length())
		    {
			    s.clear();
			    while (isdigit(line[i]))
				    s += line[i++];
			    if (s.length()>0)
				    f_indices.push_back(atoi(s.c_str())-1);
			    i++;
		    }
	    }
    }
    // Asignamos a cada vertice su posicion, texcoord y normal correspondiente
    //a partir de su indice
    std::vector<VertexTextureNormal> vectorVertex;
    int t=0;
    for(register int i = 0; i < f_indices.size(); i+=3)
    {
	    // Generamos un vtn temporal
	    VertexTextureNormal t_vtn;
	    t_vtn.position = f_vertices[f_indices[i]];
	    t_vtn.texcoord = f_texcoords[f_indices[i+1]];
	    vectorVertex.push_back(t_vtn);
	    std::cout<<f_indices[i]+1<<" ";
	    t++;
	    if(t==3)
	    {
		    std::cout<<std::endl;
		    t = 0;
	    }
    }
    //ordenamos los vertices y obtenemos los indices
    indexVBO(vectorVertex, vtn, indices);
    // Inicializamos el mesh en el OpenGL
    Initialize();
}
void Mesh::indexVBO(
				    std::vector<VertexTextureNormal> &in_vtn,
				    std::vector<VertexTextureNormal> &out_vtn,
				    std::vector<GLuint>			  &out_indices
				    )
{
    std::map<VertexTextureNormal,GLuint> VertexToOutIndex;
    // Recorremos los vertices
    for(register int i = 0; i < in_vtn.size(); i++)
    {
	    VertexTextureNormal temp_vtn = in_vtn[i];
	    // Buscamos si hay un vertice similar
	    GLuint index;
	    bool found = getSimilarVertexIndex(temp_vtn, VertexToOutIndex, index);
	    if(found){
		    out_indices.push_back(index);
	    }else{
		    out_vtn.push_back( in_vtn[i] );
		    GLuint newIndex = (GLuint)out_vtn.size() - 1;
		    out_indices.push_back( newIndex );
		    VertexToOutIndex[temp_vtn] = newIndex;
	    }
    }
}
// Funcion que busca un vertice igual al enviado en un mapa y devuelve su valor si lo encuentra
bool Mesh::getSimilarVertexIndex(
VertexTextureNormal &packed,
std::map<VertexTextureNormal,GLuint> &VertexToOutIndex,
GLuint &result
){
// Si encuentra el packed, asigna al index(result) el val
std::map<VertexTextureNormal,GLuint>::iterator it= VertexToOutIndex.find(packed);
if ( it == VertexToOutIndex.end() ){
  return false;
}else{
  result = it->second;
  return true;
}
}


Sponsor:

#2 MarkS   Prime Members   -  Reputation: 887

Like
0Likes
Like

Posted 21 December 2012 - 01:06 AM

My understanding, although I have never done it personally, is that you can have as many shaders as you like, but only one main function.

 

So, you could have:

 

//shader1.fs <- Separate files
SomeShaderFunc1()
{
}

//shader2.fs <- Separate files

SomeShaderFunc2()
{
}

//shader3.fs <- Separate files

SomeShaderFunc3()
{
}

//shader4.fs <- Separate files

main()
{
SomeShaderFunc1();
SomeShaderFunc2();
SomeShaderFunc3();
}

 

But not:

 

//shader1.fs <- Separate files

SomeShaderFunc1()
{
}

main()
{
SomeShaderFunc1();
}
 
//shader2.fs <- Separate files

SomeShaderFunc2()
{
}

main()
{
SomeShaderFunc2();
}
 
//shader3.fs <- Separate files

SomeShaderFunc3()
{
}
 
main()
{
SomeShaderFunc3();
}

 

 

And that is one main function in your fragment shader(s) and one in your vertex shader(s).


Edited by MarkS, 21 December 2012 - 01:10 AM.


#3 CaptainMurphy   Members   -  Reputation: 262

Like
0Likes
Like

Posted 21 December 2012 - 01:40 AM

If you mean to combine the results of multiple shader programs into one, I think you will have to render the mesh to a texture with each shader program, and then blend the results together (probably using another shader program).



#4 C0lumbo   Crossbones+   -  Reputation: 2498

Like
0Likes
Like

Posted 21 December 2012 - 02:24 AM

Did you mean you want parts of your mesh to use one shader and parts of your mesh to use a different one? If that's the problem, then your only real solution is to organise your data in such a way that you can setup the first shader, then draw the required verts. Then setup the second shader and do another draw call.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS