implement feature

This commit is contained in:
Thibault Leclercq 2023-10-13 21:17:30 +02:00
parent 61af8e7631
commit 3013d45de1
5 changed files with 211 additions and 35 deletions

View File

@ -116,6 +116,7 @@
#define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3 #define RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR "vertexColor" // Bound by default to shader location: 3
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT "vertexTangent" // Bound by default to shader location: 4
#define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5 #define RL_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD2 "vertexTexCoord2" // Bound by default to shader location: 5
#define RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE "instanceTransform" // Bound by default to shader location: 6
#define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
#define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix #define RL_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix

View File

@ -371,6 +371,7 @@ typedef struct MaterialMap {
// Material, includes shader and maps // Material, includes shader and maps
typedef struct Material { typedef struct Material {
Shader shader; // Material shader Shader shader; // Material shader
Shader shaderInstanced; // Material shader
MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS) MaterialMap *maps; // Material maps array (MAX_MATERIAL_MAPS)
float params[4]; // Material generic parameters (if required) float params[4]; // Material generic parameters (if required)
} Material; } Material;
@ -753,6 +754,7 @@ typedef enum {
SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent
SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color
SHADER_LOC_VERTEX_INSTANCE, // Shader location: vertex attribute: instance (transform)
SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection

View File

@ -896,6 +896,7 @@ Shader LoadShaderFromMemory(const char *vsCode, const char *fsCode)
shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL); shader.locs[SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT); shader.locs[SHADER_LOC_VERTEX_TANGENT] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_TANGENT);
shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR); shader.locs[SHADER_LOC_VERTEX_COLOR] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_COLOR);
shader.locs[SHADER_LOC_VERTEX_INSTANCE] = rlGetLocationAttrib(shader.id, RL_DEFAULT_SHADER_ATTRIB_NAME_INSTANCE);
// Get handles to GLSL uniform locations (vertex shader) // Get handles to GLSL uniform locations (vertex shader)
shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP); shader.locs[SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, RL_DEFAULT_SHADER_UNIFORM_NAME_MVP);
@ -931,6 +932,7 @@ bool IsShaderReady(Shader shader)
// shader.locs[SHADER_LOC_VERTEX_NORMAL] // shader.locs[SHADER_LOC_VERTEX_NORMAL]
// shader.locs[SHADER_LOC_VERTEX_TANGENT] // shader.locs[SHADER_LOC_VERTEX_TANGENT]
// shader.locs[SHADER_LOC_VERTEX_COLOR] // Set by default internal shader // shader.locs[SHADER_LOC_VERTEX_COLOR] // Set by default internal shader
// shader.locs[SHADER_LOC_VERTEX_INSTANCE] // Set by default internal shader instanced
// Vertex shader uniform locations (default) // Vertex shader uniform locations (default)
// shader.locs[SHADER_LOC_MATRIX_MVP] // Set by default internal shader // shader.locs[SHADER_LOC_MATRIX_MVP] // Set by default internal shader

View File

@ -467,6 +467,7 @@ typedef enum {
RL_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal RL_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
RL_SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent RL_SHADER_LOC_VERTEX_TANGENT, // Shader location: vertex attribute: tangent
RL_SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color RL_SHADER_LOC_VERTEX_COLOR, // Shader location: vertex attribute: color
RL_SHADER_LOC_VERTEX_INSTANCE, // Shader location: vertex attribute: instance (transform)
RL_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection RL_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
RL_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform) RL_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
RL_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection RL_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection
@ -664,6 +665,8 @@ RLAPI int rlGetFramebufferHeight(void); // Get default framebuff
RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id RLAPI unsigned int rlGetTextureIdDefault(void); // Get default texture id
RLAPI unsigned int rlGetShaderIdDefault(void); // Get default shader id RLAPI unsigned int rlGetShaderIdDefault(void); // Get default shader id
RLAPI int *rlGetShaderLocsDefault(void); // Get default shader locations RLAPI int *rlGetShaderLocsDefault(void); // Get default shader locations
RLAPI unsigned int rlGetShaderInstancedIdDefault(void); // Get default shader instanced id
RLAPI int *rlGetShaderInstancedLocsDefault(void); // Get default shader instanced locations
// Render batch management // Render batch management
// NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode // NOTE: rlgl provides a default render batch to behave like OpenGL 1.1 immediate mode
@ -978,6 +981,10 @@ typedef struct rlglData {
unsigned int defaultFShaderId; // Default fragment shader id (used by default shader program) unsigned int defaultFShaderId; // Default fragment shader id (used by default shader program)
unsigned int defaultShaderId; // Default shader program id, supports vertex color and diffuse texture unsigned int defaultShaderId; // Default shader program id, supports vertex color and diffuse texture
int *defaultShaderLocs; // Default shader locations pointer to be used on rendering int *defaultShaderLocs; // Default shader locations pointer to be used on rendering
unsigned int defaultVShaderInstancedId; // Default vertex shader instanced id (used by default shader instanced program)
unsigned int defaultFShaderInstancedId; // Default fragment shader instanced id (used by default shader instanced program)
unsigned int defaultShaderInstancedId; // Default shader instanced program id, supports vertex color and diffuse texture
int *defaultShaderInstancedLocs; // Default shader instanced locations pointer to be used on rendering
unsigned int currentShaderId; // Current shader id to be used on rendering (by default, defaultShaderId) unsigned int currentShaderId; // Current shader id to be used on rendering (by default, defaultShaderId)
int *currentShaderLocs; // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs) int *currentShaderLocs; // Current shader locations pointer to be used on rendering (by default, defaultShaderLocs)
@ -1055,6 +1062,8 @@ static PFNGLVERTEXATTRIBDIVISOREXTPROC glVertexAttribDivisor = NULL;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
static void rlLoadShaderDefault(void); // Load default shader static void rlLoadShaderDefault(void); // Load default shader
static void rlUnloadShaderDefault(void); // Unload default shader static void rlUnloadShaderDefault(void); // Unload default shader
static void rlLoadShaderInstancedDefault(void); // Load default shaderInstanced
static void rlUnloadShaderInstancedDefault(void); // Unload default shaderInstanced
#if defined(RLGL_SHOW_GL_DETAILS_INFO) #if defined(RLGL_SHOW_GL_DETAILS_INFO)
static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name static char *rlGetCompressedFormatName(int format); // Get compressed format official GL identifier name
#endif // RLGL_SHOW_GL_DETAILS_INFO #endif // RLGL_SHOW_GL_DETAILS_INFO
@ -2093,6 +2102,7 @@ void rlglInit(int width, int height)
// Init default Shader (customized for GL 3.3 and ES2) // Init default Shader (customized for GL 3.3 and ES2)
// Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs // Loaded: RLGL.State.defaultShaderId + RLGL.State.defaultShaderLocs
rlLoadShaderDefault(); rlLoadShaderDefault();
rlLoadShaderInstancedDefault();
RLGL.State.currentShaderId = RLGL.State.defaultShaderId; RLGL.State.currentShaderId = RLGL.State.defaultShaderId;
RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs; RLGL.State.currentShaderLocs = RLGL.State.defaultShaderLocs;
@ -2159,6 +2169,7 @@ void rlglClose(void)
rlUnloadRenderBatch(RLGL.defaultBatch); rlUnloadRenderBatch(RLGL.defaultBatch);
rlUnloadShaderDefault(); // Unload default shader rlUnloadShaderDefault(); // Unload default shader
rlUnloadShaderInstancedDefault(); // Unload default shader
glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture glDeleteTextures(1, &RLGL.State.defaultTextureId); // Unload default texture
TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId); TRACELOG(RL_LOG_INFO, "TEXTURE: [ID %i] Default texture unloaded successfully", RLGL.State.defaultTextureId);
@ -2524,6 +2535,26 @@ int *rlGetShaderLocsDefault(void)
return locs; return locs;
} }
// Get default shader instanced id
unsigned int rlGetShaderInstancedIdDefault(void)
{
unsigned int id = 0;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
id = RLGL.State.defaultShaderInstancedId;
#endif
return id;
}
// Get default shader instanced locs
int *rlGetShaderInstancedLocsDefault(void)
{
int *locs = NULL;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
locs = RLGL.State.defaultShaderInstancedLocs;
#endif
return locs;
}
// Render batch management // Render batch management
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
// Load render batch // Load render batch
@ -4662,6 +4693,136 @@ static void rlUnloadShaderDefault(void)
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId); TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default shader unloaded successfully", RLGL.State.defaultShaderId);
} }
// Load default instanced shader (just vertex positioning and texture coloring)
static void rlLoadShaderInstancedDefault(void)
{
RLGL.State.defaultShaderInstancedLocs = (int *)RL_CALLOC(RL_MAX_SHADER_LOCATIONS, sizeof(int));
// NOTE: All locations must be reseted to -1 (no location)
for (int i = 0; i < RL_MAX_SHADER_LOCATIONS; i++) RLGL.State.defaultShaderInstancedLocs[i] = -1;
// Vertex shader directly defined, no external file required
const char *defaultVShaderInstancedCode =
#if defined(GRAPHICS_API_OPENGL_21)
"#version 120 \n"
"attribute vec3 vertexPosition; \n"
"attribute vec2 vertexTexCoord; \n"
"attribute vec4 vertexColor; \n"
"attribute mat4 instanceTransform; \n"
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
#elif defined(GRAPHICS_API_OPENGL_33)
"#version 330 \n"
"in vec3 vertexPosition; \n"
"in vec2 vertexTexCoord; \n"
"in vec4 vertexColor; \n"
"in mat4 instanceTransform; \n"
"out vec2 fragTexCoord; \n"
"out vec4 fragColor; \n"
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL) (on some browsers)
"attribute vec3 vertexPosition; \n"
"attribute vec2 vertexTexCoord; \n"
"attribute vec4 vertexColor; \n"
"attribute mat4 instanceTransform; \n"
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
#endif
"uniform mat4 mvp; \n"
"void main() \n"
"{ \n"
" fragTexCoord = vertexTexCoord; \n"
" fragColor = vertexColor; \n"
" gl_Position = mvp*instanceTransform*vec4(vertexPosition, 1.0); \n"
"} \n";
// Fragment shader directly defined, no external file required
const char *defaultFShaderInstancedCode =
#if defined(GRAPHICS_API_OPENGL_21)
"#version 120 \n"
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
"uniform sampler2D texture0; \n"
"uniform vec4 colDiffuse; \n"
"void main() \n"
"{ \n"
" vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
" gl_FragColor = texelColor*colDiffuse*fragColor; \n"
"} \n";
#elif defined(GRAPHICS_API_OPENGL_33)
"#version 330 \n"
"in vec2 fragTexCoord; \n"
"in vec4 fragColor; \n"
"out vec4 finalColor; \n"
"uniform sampler2D texture0; \n"
"uniform vec4 colDiffuse; \n"
"void main() \n"
"{ \n"
" vec4 texelColor = texture(texture0, fragTexCoord); \n"
" finalColor = texelColor*colDiffuse*fragColor; \n"
"} \n";
#endif
#if defined(GRAPHICS_API_OPENGL_ES2)
"#version 100 \n"
"precision mediump float; \n" // Precision required for OpenGL ES2 (WebGL)
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
"uniform sampler2D texture0; \n"
"uniform vec4 colDiffuse; \n"
"void main() \n"
"{ \n"
" vec4 texelColor = texture2D(texture0, fragTexCoord); \n"
" gl_FragColor = texelColor*colDiffuse*fragColor; \n"
"} \n";
#endif
// NOTE: Compiled vertex/fragment shaders are not deleted,
// they are kept for re-use as default shaders in case some shader loading fails
RLGL.State.defaultVShaderInstancedId = rlCompileShader(defaultVShaderInstancedCode, GL_VERTEX_SHADER); // Compile default vertex shader
RLGL.State.defaultFShaderInstancedId = rlCompileShader(defaultFShaderInstancedCode, GL_FRAGMENT_SHADER); // Compile default fragment shader
RLGL.State.defaultShaderInstancedId = rlLoadShaderProgram(RLGL.State.defaultVShaderInstancedId, RLGL.State.defaultFShaderInstancedId);
if (RLGL.State.defaultShaderInstancedId > 0)
{
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default instanced shader loaded successfully", RLGL.State.defaultShaderInstancedId);
// Set default shader locations: attributes locations
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_VERTEX_POSITION] = glGetAttribLocation(RLGL.State.defaultShaderInstancedId, "vertexPosition");
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(RLGL.State.defaultShaderInstancedId, "vertexTexCoord");
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_VERTEX_COLOR] = glGetAttribLocation(RLGL.State.defaultShaderInstancedId, "vertexColor");
// For instanced rendering
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_VERTEX_INSTANCE] = glGetAttribLocation(RLGL.State.defaultShaderInstancedId, "instanceTransform");
// Set default shader locations: uniform locations
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_MATRIX_MVP] = glGetUniformLocation(RLGL.State.defaultShaderInstancedId, "mvp");
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_COLOR_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderInstancedId, "colDiffuse");
RLGL.State.defaultShaderInstancedLocs[RL_SHADER_LOC_MAP_DIFFUSE] = glGetUniformLocation(RLGL.State.defaultShaderInstancedId, "texture0");
}
else TRACELOG(RL_LOG_WARNING, "SHADER: [ID %i] Failed to load default instanced shader", RLGL.State.defaultShaderInstancedId);
}
// Unload default instanced shader
// NOTE: Unloads: RLGL.State.defaultShaderInstancedId, RLGL.State.defaultShaderInstancedLocs
static void rlUnloadShaderInstancedDefault(void)
{
glUseProgram(0);
glDetachShader(RLGL.State.defaultShaderInstancedId, RLGL.State.defaultVShaderInstancedId);
glDetachShader(RLGL.State.defaultShaderInstancedId, RLGL.State.defaultFShaderInstancedId);
glDeleteShader(RLGL.State.defaultVShaderInstancedId);
glDeleteShader(RLGL.State.defaultFShaderInstancedId);
glDeleteProgram(RLGL.State.defaultShaderInstancedId);
RL_FREE(RLGL.State.defaultShaderInstancedLocs);
TRACELOG(RL_LOG_INFO, "SHADER: [ID %i] Default instanced shader unloaded successfully", RLGL.State.defaultShaderInstancedId);
}
#if defined(RLGL_SHOW_GL_DETAILS_INFO) #if defined(RLGL_SHOW_GL_DETAILS_INFO)
// Get compressed format official GL identifier name // Get compressed format official GL identifier name
static char *rlGetCompressedFormatName(int format) static char *rlGetCompressedFormatName(int format)

View File

@ -1539,12 +1539,12 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
unsigned int instancesVboId = 0; unsigned int instancesVboId = 0;
// Bind shader program // Bind shader program
rlEnableShader(material.shader.id); rlEnableShader(material.shaderInstanced.id);
// Send required data to shader (matrices, values) // Send required data to shader (matrices, values)
//----------------------------------------------------- //-----------------------------------------------------
// Upload to shader material.colDiffuse // Upload to shader material.colDiffuse
if (material.shader.locs[SHADER_LOC_COLOR_DIFFUSE] != -1) if (material.shaderInstanced.locs[SHADER_LOC_COLOR_DIFFUSE] != -1)
{ {
float values[4] = { float values[4] = {
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f, (float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,
@ -1553,11 +1553,11 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f (float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f
}; };
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1); rlSetUniform(material.shaderInstanced.locs[SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);
} }
// Upload to shader material.colSpecular (if location available) // Upload to shader material.colSpecular (if location available)
if (material.shader.locs[SHADER_LOC_COLOR_SPECULAR] != -1) if (material.shaderInstanced.locs[SHADER_LOC_COLOR_SPECULAR] != -1)
{ {
float values[4] = { float values[4] = {
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f, (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.r/255.0f,
@ -1566,7 +1566,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
(float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f (float)material.maps[SHADER_LOC_COLOR_SPECULAR].color.a/255.0f
}; };
rlSetUniform(material.shader.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1); rlSetUniform(material.shaderInstanced.locs[SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);
} }
// Get a copy of current matrices to work with, // Get a copy of current matrices to work with,
@ -1580,8 +1580,11 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
Matrix matProjection = rlGetMatrixProjection(); Matrix matProjection = rlGetMatrixProjection();
// Upload view and projection matrices (if locations available) // Upload view and projection matrices (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_VIEW], matView); if (material.shaderInstanced.locs[SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shaderInstanced.locs[SHADER_LOC_MATRIX_VIEW], matView);
if (material.shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection); if (material.shaderInstanced.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shaderInstanced.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
// Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL (identity in case of instanced rendering)
rlSetUniformMatrix(material.shaderInstanced.locs[SHADER_LOC_MATRIX_MODEL], MatrixIdentity());
// Create instances buffer // Create instances buffer
instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16)); instanceTransforms = (float16 *)RL_MALLOC(instances*sizeof(float16));
@ -1598,12 +1601,12 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
// no faster, since we're transferring all the transform matrices anyway // no faster, since we're transferring all the transform matrices anyway
instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false); instancesVboId = rlLoadVertexBuffer(instanceTransforms, instances*sizeof(float16), false);
// Instances transformation matrices are send to shader attribute location: SHADER_LOC_MATRIX_MODEL // Instances transformation matrices are send to shader attribute location: SHADER_LOC_VERTEX_INSTANCE
for (unsigned int i = 0; i < 4; i++) for (unsigned int i = 0; i < 4; i++)
{ {
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_INSTANCE] + i);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 4, RL_FLOAT, 0, sizeof(Matrix), (void *)(i*sizeof(Vector4))); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_INSTANCE] + i, 4, RL_FLOAT, 0, sizeof(Matrix), (void *)(i*sizeof(Vector4)));
rlSetVertexAttributeDivisor(material.shader.locs[SHADER_LOC_MATRIX_MODEL] + i, 1); rlSetVertexAttributeDivisor(material.shaderInstanced.locs[SHADER_LOC_VERTEX_INSTANCE] + i, 1);
} }
rlDisableVertexBuffer(); rlDisableVertexBuffer();
@ -1614,7 +1617,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
matModelView = MatrixMultiply(rlGetMatrixTransform(), matView); matModelView = MatrixMultiply(rlGetMatrixTransform(), matView);
// Upload model normal matrix (if locations available) // Upload model normal matrix (if locations available)
if (material.shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel))); if (material.shaderInstanced.locs[SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shaderInstanced.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
//----------------------------------------------------- //-----------------------------------------------------
// Bind active texture maps (if available) // Bind active texture maps (if available)
@ -1631,7 +1634,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
(i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id); (i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);
else rlEnableTexture(material.maps[i].texture.id); else rlEnableTexture(material.maps[i].texture.id);
rlSetUniform(material.shader.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1); rlSetUniform(material.shaderInstanced.locs[SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);
} }
} }
@ -1641,62 +1644,62 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
{ {
// Bind mesh VBO data: vertex position (shader-location = 0) // Bind mesh VBO data: vertex position (shader-location = 0)
rlEnableVertexBuffer(mesh.vboId[0]); rlEnableVertexBuffer(mesh.vboId[0]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_POSITION]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_POSITION]);
// Bind mesh VBO data: vertex texcoords (shader-location = 1) // Bind mesh VBO data: vertex texcoords (shader-location = 1)
rlEnableVertexBuffer(mesh.vboId[1]); rlEnableVertexBuffer(mesh.vboId[1]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TEXCOORD01], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD01]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TEXCOORD01]);
if (material.shader.locs[SHADER_LOC_VERTEX_NORMAL] != -1) if (material.shaderInstanced.locs[SHADER_LOC_VERTEX_NORMAL] != -1)
{ {
// Bind mesh VBO data: vertex normals (shader-location = 2) // Bind mesh VBO data: vertex normals (shader-location = 2)
rlEnableVertexBuffer(mesh.vboId[2]); rlEnableVertexBuffer(mesh.vboId[2]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_NORMAL]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_NORMAL]);
} }
// Bind mesh VBO data: vertex colors (shader-location = 3, if available) // Bind mesh VBO data: vertex colors (shader-location = 3, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_COLOR] != -1) if (material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR] != -1)
{ {
if (mesh.vboId[3] != 0) if (mesh.vboId[3] != 0)
{ {
rlEnableVertexBuffer(mesh.vboId[3]); rlEnableVertexBuffer(mesh.vboId[3]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR], 4, RL_UNSIGNED_BYTE, 1, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR]);
} }
else else
{ {
// Set default value for unused attribute // Set default value for unused attribute
// NOTE: Required when using default shader and no VAO support // NOTE: Required when using default shader and no VAO support
float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; float value[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
rlSetVertexAttributeDefault(material.shader.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4); rlSetVertexAttributeDefault(material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR], value, SHADER_ATTRIB_VEC4, 4);
rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); rlDisableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR]);
} }
} }
// Bind mesh VBO data: vertex tangents (shader-location = 4, if available) // Bind mesh VBO data: vertex tangents (shader-location = 4, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TANGENT] != -1) if (material.shaderInstanced.locs[SHADER_LOC_VERTEX_TANGENT] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[4]); rlEnableVertexBuffer(mesh.vboId[4]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TANGENT], 4, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TANGENT]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TANGENT]);
} }
// Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available)
if (material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1) if (material.shaderInstanced.locs[SHADER_LOC_VERTEX_TEXCOORD02] != -1)
{ {
rlEnableVertexBuffer(mesh.vboId[5]); rlEnableVertexBuffer(mesh.vboId[5]);
rlSetVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0); rlSetVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TEXCOORD02], 2, RL_FLOAT, 0, 0, 0);
rlEnableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_TEXCOORD02]); rlEnableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_TEXCOORD02]);
} }
if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]); if (mesh.indices != NULL) rlEnableVertexBufferElement(mesh.vboId[6]);
} }
// WARNING: Disable vertex attribute color input if mesh can not provide that data (despite location being enabled in shader) // WARNING: Disable vertex attribute color input if mesh can not provide that data (despite location being enabled in shader)
if (mesh.vboId[3] == 0) rlDisableVertexAttribute(material.shader.locs[SHADER_LOC_VERTEX_COLOR]); if (mesh.vboId[3] == 0) rlDisableVertexAttribute(material.shaderInstanced.locs[SHADER_LOC_VERTEX_COLOR]);
int eyeCount = 1; int eyeCount = 1;
if (rlIsStereoRenderEnabled()) eyeCount = 2; if (rlIsStereoRenderEnabled()) eyeCount = 2;
@ -1714,7 +1717,7 @@ void DrawMeshInstanced(Mesh mesh, Material material, const Matrix *transforms, i
} }
// Send combined model-view-projection matrix to shader // Send combined model-view-projection matrix to shader
rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection); rlSetUniformMatrix(material.shaderInstanced.locs[SHADER_LOC_MATRIX_MVP], matModelViewProjection);
// Draw mesh instanced // Draw mesh instanced
if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances); if (mesh.indices != NULL) rlDrawVertexArrayElementsInstanced(0, mesh.triangleCount*3, 0, instances);
@ -1927,6 +1930,9 @@ Material LoadMaterialDefault(void)
material.shader.id = rlGetShaderIdDefault(); material.shader.id = rlGetShaderIdDefault();
material.shader.locs = rlGetShaderLocsDefault(); material.shader.locs = rlGetShaderLocsDefault();
material.shaderInstanced.id = rlGetShaderInstancedIdDefault();
material.shaderInstanced.locs = rlGetShaderInstancedLocsDefault();
// Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap) // Using rlgl default texture (1x1 pixel, UNCOMPRESSED_R8G8B8A8, 1 mipmap)
material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 }; material.maps[MATERIAL_MAP_DIFFUSE].texture = (Texture2D){ rlGetTextureIdDefault(), 1, 1, 1, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 };
//material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set //material.maps[MATERIAL_MAP_NORMAL].texture; // NOTE: By default, not set
@ -1941,8 +1947,9 @@ Material LoadMaterialDefault(void)
// Check if a material is ready // Check if a material is ready
bool IsMaterialReady(Material material) bool IsMaterialReady(Material material)
{ {
return ((material.maps != NULL) && // Validate material contain some map return ((material.maps != NULL) && // Validate material contain some map
(material.shader.id > 0)); // Validate material shader is valid (material.shader.id > 0) && // Validate material shader is valid
(material.shaderInstanced.id > 0)) ; // Validate material shader instanced is valid
} }
// Unload material from memory // Unload material from memory
@ -1951,6 +1958,9 @@ void UnloadMaterial(Material material)
// Unload material shader (avoid unloading default shader, managed by raylib) // Unload material shader (avoid unloading default shader, managed by raylib)
if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader); if (material.shader.id != rlGetShaderIdDefault()) UnloadShader(material.shader);
// Unload material shader (avoid unloading default shader, managed by raylib)
if (material.shaderInstanced.id != rlGetShaderInstancedIdDefault()) UnloadShader(material.shaderInstanced);
// Unload loaded texture maps (avoid unloading default texture, managed by raylib) // Unload loaded texture maps (avoid unloading default texture, managed by raylib)
if (material.maps != NULL) if (material.maps != NULL)
{ {