Updated lighting system...

...to avoid dynamic conditions on for loop (lightsCount) on standard
shader, it seems GLSL 100 doesn't support that feature... on some GPUs
like RaspberryPi...
This commit is contained in:
raysan5 2016-07-06 20:33:46 +02:00
parent e2a3a52ad6
commit 7cefbd8a94
4 changed files with 109 additions and 96 deletions

View file

@ -431,8 +431,8 @@ typedef struct Model {
// Light type // Light type
typedef struct LightData { typedef struct LightData {
unsigned int id; // Light unique id unsigned int id; // Light unique id
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
bool enabled; // Light enabled bool enabled; // Light enabled
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
Vector3 position; // Light position Vector3 position; // Light position
Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)

View file

@ -260,7 +260,7 @@ static bool texCompASTCSupported = false; // ASTC texture compression support
// Lighting data // Lighting data
static Light lights[MAX_LIGHTS]; // Lights pool static Light lights[MAX_LIGHTS]; // Lights pool
static int lightsCount; // Enabled lights counter static int lightsCount = 0; // Enabled lights counter
#endif #endif
#if defined(RLGL_OCULUS_SUPPORT) #if defined(RLGL_OCULUS_SUPPORT)
@ -2454,24 +2454,28 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
Light light = NULL; Light light = NULL;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Allocate dynamic memory if (lightsCount < MAX_LIGHTS)
light = (Light)malloc(sizeof(LightData)); {
// Allocate dynamic memory
// Initialize light values with generic values light = (Light)malloc(sizeof(LightData));
light->id = lightsCount;
light->type = type; // Initialize light values with generic values
light->enabled = true; light->id = lightsCount;
light->type = type;
light->position = position; light->enabled = true;
light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
light->intensity = 1.0f; light->position = position;
light->diffuse = diffuse; light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
light->intensity = 1.0f;
// Add new light to the array light->diffuse = diffuse;
lights[lightsCount] = light;
// Add new light to the array
// Increase enabled lights count lights[lightsCount] = light;
lightsCount++;
// Increase enabled lights count
lightsCount++;
}
else TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS);
#else #else
// TODO: Support OpenGL 1.1 lighting system // TODO: Support OpenGL 1.1 lighting system
TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1"); TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1");
@ -2484,23 +2488,26 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
void DestroyLight(Light light) void DestroyLight(Light light)
{ {
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Free dynamic memory allocation if (light != NULL)
free(lights[light->id]);
// Remove *obj from the pointers array
for (int i = light->id; i < lightsCount; i++)
{ {
// Resort all the following pointers of the array // Free dynamic memory allocation
if ((i + 1) < lightsCount) free(lights[light->id]);
// Remove *obj from the pointers array
for (int i = light->id; i < lightsCount; i++)
{ {
lights[i] = lights[i + 1]; // Resort all the following pointers of the array
lights[i]->id = lights[i + 1]->id; if ((i + 1) < lightsCount)
{
lights[i] = lights[i + 1];
lights[i]->id = lights[i + 1]->id;
}
else free(lights[i]);
} }
else free(lights[i]);
// Decrease enabled physic objects count
lightsCount--;
} }
// Decrease enabled physic objects count
lightsCount--;
#endif #endif
} }
@ -3625,72 +3632,79 @@ static void UnloadDefaultBuffers(void)
// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f // NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f
static void SetShaderLights(Shader shader) static void SetShaderLights(Shader shader)
{ {
int locPoint = glGetUniformLocation(shader.id, "lightsCount"); int locPoint = -1;
glUniform1i(locPoint, lightsCount);
char locName[32] = "lights[x].position\0"; char locName[32] = "lights[x].position\0";
for (int i = 0; i < lightsCount; i++) for (int i = 0; i < MAX_LIGHTS; i++)
{ {
locName[7] = '0' + i; locName[7] = '0' + i;
memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1); if (lights[i] != NULL) // Only upload registered lights data
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);
switch (lights[i]->type)
{ {
case LIGHT_POINT: 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);
switch (lights[i]->type)
{ {
memcpy(&locName[10], "position\0", strlen("position\0") + 1); case LIGHT_POINT:
locPoint = GetShaderLocation(shader, locName); {
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); memcpy(&locName[10], "position\0", strlen("position\0") + 1);
locPoint = GetShaderLocation(shader, locName);
memcpy(&locName[10], "radius\0", strlen("radius\0") + 2); glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
locPoint = GetShaderLocation(shader, locName);
glUniform1f(locPoint, lights[i]->radius); memcpy(&locName[10], "radius\0", strlen("radius\0") + 2);
} break; locPoint = GetShaderLocation(shader, locName);
case LIGHT_DIRECTIONAL: glUniform1f(locPoint, lights[i]->radius);
{ } break;
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); case LIGHT_DIRECTIONAL:
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 }; memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
VectorNormalize(&direction); locPoint = GetShaderLocation(shader, locName);
glUniform3f(locPoint, direction.x, direction.y, direction.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 };
} break; VectorNormalize(&direction);
case LIGHT_SPOT: glUniform3f(locPoint, direction.x, direction.y, direction.z);
{ } break;
memcpy(&locName[10], "position\0", strlen("position\0") + 1); case LIGHT_SPOT:
locPoint = GetShaderLocation(shader, locName); {
glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); memcpy(&locName[10], "position\0", strlen("position\0") + 1);
locPoint = GetShaderLocation(shader, locName);
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2); glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
locPoint = GetShaderLocation(shader, locName);
memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
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 }; locPoint = GetShaderLocation(shader, locName);
VectorNormalize(&direction);
glUniform3f(locPoint, direction.x, direction.y, direction.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);
memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0")); glUniform3f(locPoint, direction.x, direction.y, direction.z);
locPoint = GetShaderLocation(shader, locName);
glUniform1f(locPoint, lights[i]->coneAngle); memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
} break; locPoint = GetShaderLocation(shader, locName);
default: break; glUniform1f(locPoint, lights[i]->coneAngle);
} break;
default: break;
}
// TODO: Pass to the shader any other required data from LightData struct
}
else // Not enabled lights
{
memcpy(&locName[10], "enabled\0", strlen("enabled\0") + 1);
locPoint = GetShaderLocation(shader, locName);
glUniform1i(locPoint, 0);
} }
// TODO: Pass to the shader any other required data from LightData struct
} }
} }

View file

@ -218,9 +218,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
// Light type // Light type
typedef struct LightData { typedef struct LightData {
unsigned int id; // Light unique id unsigned int id; // Light unique id
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
bool enabled; // Light enabled bool enabled; // Light enabled
int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
Vector3 position; // Light position Vector3 position; // Light position
Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
float radius; // Light attenuation radius light intensity reduced with distance (world distance) float radius; // Light attenuation radius light intensity reduced with distance (world distance)

View file

@ -78,7 +78,6 @@ static const char fStandardShaderStr[] =
" float radius; \n" " float radius; \n"
" float coneAngle; }; \n" " float coneAngle; }; \n"
"const int maxLights = 8; \n" "const int maxLights = 8; \n"
"uniform int lightsCount; \n"
"uniform Light lights[maxLights]; \n" "uniform Light lights[maxLights]; \n"
"\n" "\n"
"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" "vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n"
@ -157,7 +156,7 @@ static const char fStandardShaderStr[] =
#elif defined(GRAPHICS_API_OPENGL_33) #elif defined(GRAPHICS_API_OPENGL_33)
" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n" " if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n"
#endif #endif
" for (int i = 0; i < lightsCount; i++)\n" " for (int i = 0; i < maxLights; i++)\n"
" {\n" " {\n"
" if (lights[i].enabled == 1)\n" " if (lights[i].enabled == 1)\n"
" {\n" " {\n"