|
|
@ -337,6 +337,8 @@ static int screenHeight; // Default framebuffer height |
|
|
|
// Lighting data |
|
|
|
static Light lights[MAX_LIGHTS]; // Lights pool |
|
|
|
static int lightsCount = 0; // Enabled lights counter |
|
|
|
static int lightsLocs[MAX_LIGHTS][8]; // 8 possible location points per light: |
|
|
|
// enabled, type, position, target, radius, diffuse, intensity, coneAngle |
|
|
|
|
|
|
|
//---------------------------------------------------------------------------------- |
|
|
|
// Module specific Functions Declaration |
|
|
@ -362,9 +364,10 @@ static void SetStereoConfig(VrDeviceInfo info); |
|
|
|
// Set internal projection and modelview matrix depending on eyes tracking data |
|
|
|
static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); |
|
|
|
|
|
|
|
static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array |
|
|
|
static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS) |
|
|
|
static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights |
|
|
|
|
|
|
|
static char *ReadTextFile(const char *fileName); // Read chars array from text file |
|
|
|
static char *ReadTextFile(const char *fileName); // Read chars array from text file |
|
|
|
#endif |
|
|
|
|
|
|
|
#if defined(RLGL_OCULUS_SUPPORT) |
|
|
@ -1939,9 +1942,14 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) |
|
|
|
glUseProgram(material.shader.id); |
|
|
|
|
|
|
|
// Upload to shader material.colDiffuse |
|
|
|
float vColorDiffuse[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, vColorDiffuse); |
|
|
|
glUniform4f(material.shader.colDiffuseLoc, (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255); |
|
|
|
|
|
|
|
// Upload to shader material.colAmbient (if available) |
|
|
|
if (material.shader.colAmbientLoc != -1) glUniform4f(material.shader.colAmbientLoc, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); |
|
|
|
|
|
|
|
// Upload to shader material.colSpecular (if available) |
|
|
|
if (material.shader.colSpecularLoc != -1) glUniform4f(material.shader.colSpecularLoc, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); |
|
|
|
|
|
|
|
// 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) |
|
|
@ -1950,32 +1958,35 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) |
|
|
|
// Calculate model-view matrix combining matModel and matView |
|
|
|
Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates |
|
|
|
|
|
|
|
// Check if using standard shader to get location points |
|
|
|
// NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations) |
|
|
|
if (material.shader.id == standardShader.id) |
|
|
|
// If not using default shader, we check for some additional location points |
|
|
|
// NOTE: This method is quite inefficient... it's a temporal solution while looking for a better one |
|
|
|
if (material.shader.id != defaultShader.id) |
|
|
|
{ |
|
|
|
// Transpose and inverse model transformations matrix for fragment normal calculations |
|
|
|
Matrix transInvTransform = transform; |
|
|
|
MatrixTranspose(&transInvTransform); |
|
|
|
MatrixInvert(&transInvTransform); |
|
|
|
|
|
|
|
// Send model transformations matrix to shader |
|
|
|
glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transInvTransform)); |
|
|
|
|
|
|
|
// Send view transformation matrix to shader. View matrix 8, 9 and 10 are view direction vector axis values (target - position) |
|
|
|
glUniform3f(glGetUniformLocation(material.shader.id, "viewDir"), matView.m8, matView.m9, matView.m10); |
|
|
|
|
|
|
|
// Setup shader uniforms for lights |
|
|
|
SetShaderLights(material.shader); |
|
|
|
|
|
|
|
// Upload to shader material.colAmbient |
|
|
|
glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); |
|
|
|
|
|
|
|
// Upload to shader material.colSpecular |
|
|
|
glUniform4f(glGetUniformLocation(material.shader.id, "colSpecular"), (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); |
|
|
|
|
|
|
|
// Upload to shader glossiness |
|
|
|
glUniform1f(glGetUniformLocation(material.shader.id, "glossiness"), material.glossiness); |
|
|
|
// Check if model matrix is located in shader and upload value |
|
|
|
int modelMatrixLoc = glGetUniformLocation(material.shader.id, "modelMatrix"); |
|
|
|
if (modelMatrixLoc != -1) |
|
|
|
{ |
|
|
|
// Transpose and inverse model transformations matrix for fragment normal calculations |
|
|
|
Matrix transInvTransform = transform; |
|
|
|
MatrixTranspose(&transInvTransform); |
|
|
|
MatrixInvert(&transInvTransform); |
|
|
|
|
|
|
|
// Send model transformations matrix to shader |
|
|
|
glUniformMatrix4fv(modelMatrixLoc, 1, false, MatrixToFloat(transInvTransform)); |
|
|
|
} |
|
|
|
|
|
|
|
// Check if view direction is located in shader and upload value |
|
|
|
// NOTE: View matrix values m8, m9 and m10 are view direction vector axis (target - position) |
|
|
|
int viewDirLoc = glGetUniformLocation(material.shader.id, "viewDir"); |
|
|
|
if (viewDirLoc != -1) glUniform3f(viewDirLoc, matView.m8, matView.m9, matView.m10); |
|
|
|
|
|
|
|
// Check if glossiness is located in shader and upload value |
|
|
|
int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness"); |
|
|
|
if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness); |
|
|
|
|
|
|
|
// Set shader lights values for enabled lights |
|
|
|
// NOTE: Lights array location points are obtained on shader loading (if available) |
|
|
|
if (lightsCount > 0) SetShaderLightsValues(material.shader); |
|
|
|
} |
|
|
|
|
|
|
|
// Set shader textures (diffuse, normal, specular) |
|
|
@ -3100,7 +3111,7 @@ static Shader LoadStandardShader(void) |
|
|
|
shader = GetDefaultShader(); |
|
|
|
} |
|
|
|
#else |
|
|
|
shader = defaultShader; |
|
|
|
shader = GetDefaultShader(); |
|
|
|
TraceLog(WARNING, "[SHDR ID %i] Standard shader not available, using default shader", shader.id); |
|
|
|
#endif |
|
|
|
|
|
|
@ -3112,12 +3123,12 @@ static Shader LoadStandardShader(void) |
|
|
|
static void LoadDefaultShaderLocations(Shader *shader) |
|
|
|
{ |
|
|
|
// NOTE: Default shader attrib locations have been fixed before linking: |
|
|
|
// vertex position location = 0 |
|
|
|
// vertex texcoord location = 1 |
|
|
|
// vertex normal location = 2 |
|
|
|
// vertex color location = 3 |
|
|
|
// vertex tangent location = 4 |
|
|
|
// vertex texcoord2 location = 5 |
|
|
|
// vertex position location = 0 |
|
|
|
// vertex texcoord location = 1 |
|
|
|
// vertex normal location = 2 |
|
|
|
// vertex color location = 3 |
|
|
|
// vertex tangent location = 4 |
|
|
|
// vertex texcoord2 location = 5 |
|
|
|
|
|
|
|
// Get handles to GLSL input attibute locations |
|
|
|
shader->vertexLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); |
|
|
@ -3131,10 +3142,18 @@ static void LoadDefaultShaderLocations(Shader *shader) |
|
|
|
shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); |
|
|
|
|
|
|
|
// Get handles to GLSL uniform locations (fragment shader) |
|
|
|
shader->tintColorLoc = glGetUniformLocation(shader->id, "colDiffuse"); |
|
|
|
shader->colDiffuseLoc = glGetUniformLocation(shader->id, "colDiffuse"); |
|
|
|
shader->colAmbientLoc = glGetUniformLocation(shader->id, "colAmbient"); |
|
|
|
shader->colSpecularLoc = glGetUniformLocation(shader->id, "colSpecular"); |
|
|
|
|
|
|
|
shader->mapTexture0Loc = glGetUniformLocation(shader->id, "texture0"); |
|
|
|
shader->mapTexture1Loc = glGetUniformLocation(shader->id, "texture1"); |
|
|
|
shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2"); |
|
|
|
|
|
|
|
// TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) |
|
|
|
|
|
|
|
// Try to get lights location points (if available) |
|
|
|
GetShaderLightsLocations(*shader); |
|
|
|
} |
|
|
|
|
|
|
|
// Unload default shader |
|
|
@ -3425,7 +3444,7 @@ static void DrawDefaultBuffers(int eyesCount) |
|
|
|
Matrix matMVP = MatrixMultiply(modelview, projection); |
|
|
|
|
|
|
|
glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); |
|
|
|
glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); |
|
|
|
glUniform4f(currentShader.colDiffuseLoc, 1.0f, 1.0f, 1.0f, 1.0f); |
|
|
|
glUniform1i(currentShader.mapTexture0Loc, 0); |
|
|
|
|
|
|
|
// NOTE: Additional map textures not considered for default buffers drawing |
|
|
@ -3620,82 +3639,100 @@ static void UnloadDefaultBuffers(void) |
|
|
|
free(quads.indices); |
|
|
|
} |
|
|
|
|
|
|
|
// Setup shader uniform values for lights array |
|
|
|
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f |
|
|
|
static void SetShaderLights(Shader shader) |
|
|
|
// Get shader locations for lights (up to MAX_LIGHTS) |
|
|
|
static void GetShaderLightsLocations(Shader shader) |
|
|
|
{ |
|
|
|
int locPoint = -1; |
|
|
|
char locName[32] = "lights[x].position\0"; |
|
|
|
|
|
|
|
char locName[32] = "lights[x].\0"; |
|
|
|
char locNameUpdated[64]; |
|
|
|
|
|
|
|
for (int i = 0; i < MAX_LIGHTS; i++) |
|
|
|
{ |
|
|
|
locName[7] = '0' + i; |
|
|
|
|
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "enabled\0"); |
|
|
|
lightsLocs[i][0] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "type\0"); |
|
|
|
lightsLocs[i][1] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "position\0"); |
|
|
|
lightsLocs[i][2] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "direction\0"); |
|
|
|
lightsLocs[i][3] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "radius\0"); |
|
|
|
lightsLocs[i][4] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "diffuse\0"); |
|
|
|
lightsLocs[i][5] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "intensity\0"); |
|
|
|
lightsLocs[i][6] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
|
|
|
|
locNameUpdated[0] = '\0'; |
|
|
|
strcpy(locNameUpdated, locName); |
|
|
|
strcat(locNameUpdated, "coneAngle\0"); |
|
|
|
lightsLocs[i][7] = glGetUniformLocation(shader.id, locNameUpdated); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (lights[i] != NULL) // Only upload registered lights data |
|
|
|
// Set shader uniform values for lights |
|
|
|
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0 |
|
|
|
static void SetShaderLightsValues(Shader shader) |
|
|
|
{ |
|
|
|
for (int i = 0; i < MAX_LIGHTS; i++) |
|
|
|
{ |
|
|
|
if (i < lightsCount) |
|
|
|
{ |
|
|
|
memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform1i(locPoint, lights[i]->enabled); |
|
|
|
|
|
|
|
memcpy(&locName[10], "type\0", strlen("type\0") + 1); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform1i(locPoint, lights[i]->type); |
|
|
|
|
|
|
|
memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2); |
|
|
|
locPoint = glGetUniformLocation(shader.id, locName); |
|
|
|
glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); |
|
|
|
|
|
|
|
memcpy(&locName[10], "intensity\0", strlen("intensity\0")); |
|
|
|
locPoint = glGetUniformLocation(shader.id, locName); |
|
|
|
glUniform1f(locPoint, lights[i]->intensity); |
|
|
|
glUniform1i(lightsLocs[i][0], lights[i]->enabled); |
|
|
|
|
|
|
|
glUniform1i(lightsLocs[i][1], lights[i]->type); |
|
|
|
glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); |
|
|
|
glUniform1f(lightsLocs[i][6], lights[i]->intensity); |
|
|
|
|
|
|
|
switch (lights[i]->type) |
|
|
|
{ |
|
|
|
case LIGHT_POINT: |
|
|
|
{ |
|
|
|
memcpy(&locName[10], "position\0", strlen("position\0") + 1); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); |
|
|
|
|
|
|
|
memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform1f(locPoint, lights[i]->radius); |
|
|
|
glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); |
|
|
|
glUniform1f(lightsLocs[i][4], lights[i]->radius); |
|
|
|
} break; |
|
|
|
case LIGHT_DIRECTIONAL: |
|
|
|
{ |
|
|
|
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; |
|
|
|
VectorNormalize(&direction); |
|
|
|
glUniform3f(locPoint, direction.x, direction.y, direction.z); |
|
|
|
glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); |
|
|
|
} break; |
|
|
|
case LIGHT_SPOT: |
|
|
|
{ |
|
|
|
memcpy(&locName[10], "position\0", strlen("position\0") + 1); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); |
|
|
|
|
|
|
|
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); |
|
|
|
|
|
|
|
Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z }; |
|
|
|
VectorNormalize(&direction); |
|
|
|
glUniform3f(locPoint, direction.x, direction.y, direction.z); |
|
|
|
glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); |
|
|
|
|
|
|
|
memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform1f(locPoint, lights[i]->coneAngle); |
|
|
|
glUniform1f(lightsLocs[i][7], lights[i]->coneAngle); |
|
|
|
} break; |
|
|
|
default: break; |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Pass to the shader any other required data from LightData struct |
|
|
|
} |
|
|
|
else // Not enabled lights |
|
|
|
else |
|
|
|
{ |
|
|
|
memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); |
|
|
|
locPoint = GetShaderLocation(shader, locName); |
|
|
|
glUniform1i(locPoint, 0); |
|
|
|
glUniform1i(lightsLocs[i][0], 0); // Light disabled |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|