瀏覽代碼

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...
pull/132/head
raysan5 8 年之前
父節點
當前提交
7cefbd8a94
共有 4 個文件被更改,包括 109 次插入96 次删除
  1. +1
    -1
      src/raylib.h
  2. +105
    -91
      src/rlgl.c
  3. +2
    -2
      src/rlgl.h
  4. +1
    -2
      src/standard_shader.h

+ 1
- 1
src/raylib.h 查看文件

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

+ 105
- 91
src/rlgl.c 查看文件

@ -260,7 +260,7 @@ static bool texCompASTCSupported = false; // ASTC texture compression support
// Lighting data
static Light lights[MAX_LIGHTS]; // Lights pool
static int lightsCount; // Enabled lights counter
static int lightsCount = 0; // Enabled lights counter
#endif
#if defined(RLGL_OCULUS_SUPPORT)
@ -2454,24 +2454,28 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
Light light = NULL;
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Allocate dynamic memory
light = (Light)malloc(sizeof(LightData));
// Initialize light values with generic values
light->id = lightsCount;
light->type = type;
light->enabled = true;
light->position = position;
light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
light->intensity = 1.0f;
light->diffuse = diffuse;
// Add new light to the array
lights[lightsCount] = light;
// Increase enabled lights count
lightsCount++;
if (lightsCount < MAX_LIGHTS)
{
// Allocate dynamic memory
light = (Light)malloc(sizeof(LightData));
// Initialize light values with generic values
light->id = lightsCount;
light->type = type;
light->enabled = true;
light->position = position;
light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
light->intensity = 1.0f;
light->diffuse = diffuse;
// Add new light to the array
lights[lightsCount] = light;
// Increase enabled lights count
lightsCount++;
}
else TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS);
#else
// TODO: Support OpenGL 1.1 lighting system
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)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Free dynamic memory allocation
free(lights[light->id]);
// Remove *obj from the pointers array
for (int i = light->id; i < lightsCount; i++)
if (light != NULL)
{
// Resort all the following pointers of the array
if ((i + 1) < lightsCount)
// Free dynamic memory allocation
free(lights[light->id]);
// Remove *obj from the pointers array
for (int i = light->id; i < lightsCount; i++)
{
lights[i] = lights[i + 1];
lights[i]->id = lights[i + 1]->id;
// Resort all the following pointers of the array
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
}
@ -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
static void SetShaderLights(Shader shader)
{
int locPoint = glGetUniformLocation(shader.id, "lightsCount");
glUniform1i(locPoint, lightsCount);
int locPoint = -1;
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;
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)
if (lights[i] != NULL) // Only upload registered lights data
{
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);
} 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);
} break;
case LIGHT_SPOT:
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);
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);
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);
memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
locPoint = GetShaderLocation(shader, locName);
glUniform1f(locPoint, lights[i]->coneAngle);
} break;
default: break;
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);
} 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);
} 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);
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);
memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
locPoint = GetShaderLocation(shader, locName);
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
}
}

+ 2
- 2
src/rlgl.h 查看文件

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

+ 1
- 2
src/standard_shader.h 查看文件

@ -78,7 +78,6 @@ static const char fStandardShaderStr[] =
" float radius; \n"
" float coneAngle; }; \n"
"const int maxLights = 8; \n"
"uniform int lightsCount; \n"
"uniform Light lights[maxLights]; \n"
"\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)
" if (useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r);\n"
#endif
" for (int i = 0; i < lightsCount; i++)\n"
" for (int i = 0; i < maxLights; i++)\n"
" {\n"
" if (lights[i].enabled == 1)\n"
" {\n"

Loading…
取消
儲存