|
|
@ -740,6 +740,24 @@ void rlDisableDepthTest(void) |
|
|
|
glDisable(GL_DEPTH_TEST); |
|
|
|
} |
|
|
|
|
|
|
|
// Enable wire mode |
|
|
|
void rlEnableWireMode(void) |
|
|
|
{ |
|
|
|
#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) |
|
|
|
// NOTE: glPolygonMode() not available on OpenGL ES |
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Disable wire mode |
|
|
|
void rlDisableWireMode(void) |
|
|
|
{ |
|
|
|
#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) |
|
|
|
// NOTE: glPolygonMode() not available on OpenGL ES |
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Unload texture from GPU memory |
|
|
|
void rlDeleteTextures(unsigned int id) |
|
|
|
{ |
|
|
@ -1033,175 +1051,15 @@ void rlglClose(void) |
|
|
|
void rlglDraw(void) |
|
|
|
{ |
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |
|
|
|
UpdateDefaultBuffers(); |
|
|
|
DrawDefaultBuffers(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Draw a 3d mesh with material and transform |
|
|
|
void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) |
|
|
|
{ |
|
|
|
#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) |
|
|
|
// NOTE: glPolygonMode() not available on OpenGL ES |
|
|
|
if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_11) |
|
|
|
glEnable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); |
|
|
|
|
|
|
|
// NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model |
|
|
|
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array |
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array |
|
|
|
if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array |
|
|
|
if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array |
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array |
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array |
|
|
|
if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array |
|
|
|
if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array |
|
|
|
|
|
|
|
rlPushMatrix(); |
|
|
|
rlMultMatrixf(MatrixToFloat(transform)); |
|
|
|
rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); |
|
|
|
|
|
|
|
if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); |
|
|
|
else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); |
|
|
|
rlPopMatrix(); |
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array |
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array |
|
|
|
if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array |
|
|
|
if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array |
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |
|
|
|
glUseProgram(material.shader.id); |
|
|
|
|
|
|
|
// At this point the modelview matrix just contains the view matrix (camera) |
|
|
|
// That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() |
|
|
|
Matrix matView = modelview; // View matrix (camera) |
|
|
|
Matrix matProjection = projection; // Projection matrix (perspective) |
|
|
|
|
|
|
|
// Calculate model-view matrix combining matModel and matView |
|
|
|
Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates |
|
|
|
|
|
|
|
// Calculate model-view-projection matrix (MVP) |
|
|
|
Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates |
|
|
|
|
|
|
|
// Send combined model-view-projection matrix to shader |
|
|
|
glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); |
|
|
|
|
|
|
|
// Apply color tinting (material.colDiffuse) |
|
|
|
// NOTE: Just update one uniform on fragment shader |
|
|
|
float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; |
|
|
|
glUniform4fv(material.shader.tintColorLoc, 1, vColor); |
|
|
|
|
|
|
|
// Set shader textures (diffuse, normal, specular) |
|
|
|
glActiveTexture(GL_TEXTURE0); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); |
|
|
|
glUniform1i(material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 |
|
|
|
|
|
|
|
if ((material.texNormal.id != 0) && (material.shader.mapNormalLoc != -1)) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE1); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texNormal.id); |
|
|
|
glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 |
|
|
|
} |
|
|
|
|
|
|
|
if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE2); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); |
|
|
|
glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 |
|
|
|
} |
|
|
|
|
|
|
|
if (vaoSupported) |
|
|
|
{ |
|
|
|
glBindVertexArray(mesh.vaoId); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Bind mesh VBO data: vertex position (shader-location = 0) |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); |
|
|
|
glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.vertexLoc); |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords (shader-location = 1) |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); |
|
|
|
glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.texcoordLoc); |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex normals (shader-location = 2, if available) |
|
|
|
if (material.shader.normalLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); |
|
|
|
glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.normalLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available) |
|
|
|
if (material.shader.colorLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); |
|
|
|
glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.colorLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) |
|
|
|
if (material.shader.tangentLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); |
|
|
|
glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.tangentLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) |
|
|
|
if (material.shader.texcoord2Loc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); |
|
|
|
glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.texcoord2Loc); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw call! |
|
|
|
if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw |
|
|
|
else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); |
|
|
|
|
|
|
|
if (material.texNormal.id != 0) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE1); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
} |
|
|
|
|
|
|
|
if (material.texSpecular.id != 0) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE2); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
} |
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures |
|
|
|
|
|
|
|
if (vaoSupported) glBindVertexArray(0); // Unbind VAO |
|
|
|
else |
|
|
|
/* |
|
|
|
for (int i = 0; i < modelsCount; i++) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs |
|
|
|
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
|
|
|
rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); |
|
|
|
} |
|
|
|
|
|
|
|
glUseProgram(0); // Unbind shader program |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) |
|
|
|
// NOTE: glPolygonMode() not available on OpenGL ES |
|
|
|
if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); |
|
|
|
*/ |
|
|
|
// NOTE: Default buffers always drawn at the end |
|
|
|
UpdateDefaultBuffers(); |
|
|
|
DrawDefaultBuffers(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
@ -1776,6 +1634,245 @@ void rlglLoadMesh(Mesh *mesh) |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Update vertex data on GPU (upload new data to one buffer) |
|
|
|
void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) |
|
|
|
{ |
|
|
|
// Activate mesh VAO |
|
|
|
if (vaoSupported) glBindVertexArray(mesh.vaoId); |
|
|
|
|
|
|
|
switch (buffer) |
|
|
|
{ |
|
|
|
case 0: // Update vertices (vertex position) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.vertices, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.vertices); |
|
|
|
|
|
|
|
} break; |
|
|
|
case 1: // Update texcoords (vertex texture coordinates) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords); |
|
|
|
|
|
|
|
} break; |
|
|
|
case 2: // Update normals (vertex normals) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.normals, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.normals); |
|
|
|
|
|
|
|
} break; |
|
|
|
case 3: // Update colors (vertex colors) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*numVertex, mesh.colors, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*numVertex, mesh.colors); |
|
|
|
|
|
|
|
} break; |
|
|
|
case 4: // Update tangents (vertex tangents) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.tangents, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.tangents); |
|
|
|
} break; |
|
|
|
case 5: // Update texcoords2 (vertex second texture coordinates) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); |
|
|
|
if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords2, GL_DYNAMIC_DRAW); |
|
|
|
else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords2); |
|
|
|
} break; |
|
|
|
default: break; |
|
|
|
} |
|
|
|
|
|
|
|
// Unbind the current VAO |
|
|
|
if (vaoSupported) glBindVertexArray(0); |
|
|
|
|
|
|
|
// Another option would be using buffer mapping... |
|
|
|
//mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); |
|
|
|
// Now we can modify vertices |
|
|
|
//glUnmapBuffer(GL_ARRAY_BUFFER); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw a 3d mesh with material and transform |
|
|
|
void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) |
|
|
|
{ |
|
|
|
#if defined(GRAPHICS_API_OPENGL_11) |
|
|
|
glEnable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); |
|
|
|
|
|
|
|
// NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model |
|
|
|
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array |
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array |
|
|
|
if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array |
|
|
|
if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array |
|
|
|
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array |
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array |
|
|
|
if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array |
|
|
|
if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array |
|
|
|
|
|
|
|
rlPushMatrix(); |
|
|
|
rlMultMatrixf(MatrixToFloat(transform)); |
|
|
|
rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); |
|
|
|
|
|
|
|
if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); |
|
|
|
else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); |
|
|
|
rlPopMatrix(); |
|
|
|
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array |
|
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array |
|
|
|
if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array |
|
|
|
if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array |
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_2D); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) |
|
|
|
glUseProgram(material.shader.id); |
|
|
|
|
|
|
|
// At this point the modelview matrix just contains the view matrix (camera) |
|
|
|
// That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() |
|
|
|
Matrix matView = modelview; // View matrix (camera) |
|
|
|
Matrix matProjection = projection; // Projection matrix (perspective) |
|
|
|
|
|
|
|
// Calculate model-view matrix combining matModel and matView |
|
|
|
Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates |
|
|
|
|
|
|
|
// Calculate model-view-projection matrix (MVP) |
|
|
|
Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates |
|
|
|
|
|
|
|
// Send combined model-view-projection matrix to shader |
|
|
|
glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); |
|
|
|
|
|
|
|
// Apply color tinting (material.colDiffuse) |
|
|
|
// NOTE: Just update one uniform on fragment shader |
|
|
|
float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; |
|
|
|
glUniform4fv(material.shader.tintColorLoc, 1, vColor); |
|
|
|
|
|
|
|
// Set shader textures (diffuse, normal, specular) |
|
|
|
glActiveTexture(GL_TEXTURE0); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); |
|
|
|
glUniform1i(material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 |
|
|
|
|
|
|
|
if ((material.texNormal.id != 0) && (material.shader.mapNormalLoc != -1)) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE1); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texNormal.id); |
|
|
|
glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 |
|
|
|
} |
|
|
|
|
|
|
|
if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE2); |
|
|
|
glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); |
|
|
|
glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 |
|
|
|
} |
|
|
|
|
|
|
|
if (vaoSupported) |
|
|
|
{ |
|
|
|
glBindVertexArray(mesh.vaoId); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
// Bind mesh VBO data: vertex position (shader-location = 0) |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); |
|
|
|
glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.vertexLoc); |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords (shader-location = 1) |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); |
|
|
|
glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.texcoordLoc); |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex normals (shader-location = 2, if available) |
|
|
|
if (material.shader.normalLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); |
|
|
|
glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.normalLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available) |
|
|
|
if (material.shader.colorLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); |
|
|
|
glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.colorLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) |
|
|
|
if (material.shader.tangentLoc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); |
|
|
|
glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.tangentLoc); |
|
|
|
} |
|
|
|
|
|
|
|
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) |
|
|
|
if (material.shader.texcoord2Loc != -1) |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); |
|
|
|
glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); |
|
|
|
glEnableVertexAttribArray(material.shader.texcoord2Loc); |
|
|
|
} |
|
|
|
|
|
|
|
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); |
|
|
|
} |
|
|
|
|
|
|
|
// Draw call! |
|
|
|
if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw |
|
|
|
else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); |
|
|
|
|
|
|
|
if (material.texNormal.id != 0) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE1); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
} |
|
|
|
|
|
|
|
if (material.texSpecular.id != 0) |
|
|
|
{ |
|
|
|
glActiveTexture(GL_TEXTURE2); |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); |
|
|
|
} |
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 |
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures |
|
|
|
|
|
|
|
if (vaoSupported) glBindVertexArray(0); // Unbind VAO |
|
|
|
else |
|
|
|
{ |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs |
|
|
|
if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); |
|
|
|
} |
|
|
|
|
|
|
|
glUseProgram(0); // Unbind shader program |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
// Unload mesh data from CPU and GPU |
|
|
|
void rlglUnloadMesh(Mesh *mesh) |
|
|
|
{ |
|
|
|
if (mesh->vertices != NULL) free(mesh->vertices); |
|
|
|
if (mesh->texcoords != NULL) free(mesh->texcoords); |
|
|
|
if (mesh->normals != NULL) free(mesh->normals); |
|
|
|
if (mesh->colors != NULL) free(mesh->colors); |
|
|
|
if (mesh->tangents != NULL) free(mesh->tangents); |
|
|
|
if (mesh->texcoords2 != NULL) free(mesh->texcoords2); |
|
|
|
if (mesh->indices != NULL) free(mesh->indices); |
|
|
|
|
|
|
|
rlDeleteBuffers(mesh->vboId[0]); // vertex |
|
|
|
rlDeleteBuffers(mesh->vboId[1]); // texcoords |
|
|
|
rlDeleteBuffers(mesh->vboId[2]); // normals |
|
|
|
rlDeleteBuffers(mesh->vboId[3]); // colors |
|
|
|
rlDeleteBuffers(mesh->vboId[4]); // tangents |
|
|
|
rlDeleteBuffers(mesh->vboId[5]); // texcoords2 |
|
|
|
rlDeleteBuffers(mesh->vboId[6]); // indices |
|
|
|
|
|
|
|
rlDeleteVertexArrays(mesh->vaoId); |
|
|
|
} |
|
|
|
|
|
|
|
// Read screen pixel data (color buffer) |
|
|
|
unsigned char *rlglReadScreenPixels(int width, int height) |
|
|
|
{ |
|
|
|