~leinnan/raylibGame unlisted

5bf527b79933cd1e6e8d10b234de88be4ce60c69 — Piotr Siuszko 4 months ago 2ca751b
Working lights
M .clang-format => .clang-format +4 -4
@@ 90,10 90,10 @@ PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
RawStringFormats: 
  - Delimiter:       pb
    Language:        TextProto
    BasedOnStyle:    google
RawStringFormats:
  - Language: TextProto
    BasedOnStyle: Google
    Delimiters: [pb]
ReflowComments:  true
SortIncludes:    true
SortUsingDeclarations: true

M CMakeLists.txt => CMakeLists.txt +8 -8
@@ 15,12 15,12 @@ SET(BUILD_GAMES OFF CACHE BOOL "Build the example games.")
SET(SPDLOG_BUILD_EXAMPLES OFF CACHE BOOL "Build examples")
add_subdirectory(ext/raylib)
add_subdirectory(ext/entt)
add_subdirectory(ext/spdlog)

if(NOT TARGET spdlog)
    # Stand-alone build
    find_package(spdlog REQUIRED)
endif()
#add_subdirectory(ext/spdlog)
#
#if(NOT TARGET spdlog)
#    # Stand-alone build
#    find_package(spdlog REQUIRED)
#endif()

if(${PLATFORM} MATCHES "Web")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 --profiling")


@@ 31,9 31,9 @@ file(COPY ${CMAKE_SOURCE_DIR}/data DESTINATION ${CMAKE_BINARY_DIR}/output)
file(MAKE_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/logs")

include_directories(src ext src/controllers src/components src/systems src/utils src/presets src/factories)
add_executable(${PROJECT_NAME} src/main.cpp src/utils/Arkona.cpp src/utils/JsonParser.cpp  src/systems/SpawnSystem.cpp src/systems/DamageSystem.cpp src/systems/MissileSystem.cpp src/systems/AiSystem.cpp src/systems/CollisionSystem.cpp src/systems/DestroySystem.cpp src/systems/MovementSystem.cpp src/systems/RenderSystem.cpp src/systems/PlayerInputSystem.cpp)
add_executable(${PROJECT_NAME} src/main.cpp src/utils/Arkona.cpp src/utils/JsonParser.cpp  src/systems/SpawnSystem.cpp src/systems/DamageSystem.cpp src/systems/MissileSystem.cpp src/systems/AiSystem.cpp src/systems/CollisionSystem.cpp src/systems/DestroySystem.cpp src/systems/MovementSystem.cpp src/systems/RenderSystem.cpp src/systems/PlayerInputSystem.cpp src/components/GameRestart.hpp src/components/ModelLightsShader.hpp src/systems/RenderLightingSystem.cpp src/systems/RenderLightingSystem.hpp src/components/LightComponent.hpp)
#set(raylib_VERBOSE 1)
target_link_libraries(${PROJECT_NAME} raylib EnTT spdlog::spdlog_header_only)
target_link_libraries(${PROJECT_NAME} raylib EnTT) #spdlog::spdlog_header_only)
if(${PLATFORM} MATCHES "Web")
    set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-s DEMANGLE_SUPPORT=1 --preload-file ${CMAKE_SOURCE_DIR}/data --bind")
endif()

M data/shaders/lighting.fs => data/shaders/lighting.fs +4 -1
@@ 31,6 31,7 @@ struct Light {
    vec3 position;
    vec3 target;
    vec4 color;
    float strength;
};

// Input lighting values


@@ 64,6 65,8 @@ void main()
            {
                light = normalize(lights[i].position - fragPosition);
            }

            light *= lights[i].strength;
            
            float NdotL = max(dot(normal, light), 0.0);
            lightDot += lights[i].color.rgb*NdotL;


@@ 85,5 88,5 @@ void main()
    const float fogDensity = 0.022;
    float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity));
    fogFactor = clamp(fogFactor, 0.0, 1.0);
    finalColor = mix(fogColor, finalColor, fogFactor);;
    finalColor = mix(fogColor, finalColor, fogFactor);
}

A src/components/LightComponent.hpp => src/components/LightComponent.hpp +16 -0
@@ 0,0 1,16 @@
//
// Created by 48785 on 04.06.2020.
//

#ifndef RAYLIBECS_LIGHTCOMPONENT_HPP
#define RAYLIBECS_LIGHTCOMPONENT_HPP
#include "raylib.h"
namespace Components {
    struct Light {
    Light(const Color &color, float strength) : color(color), strength(strength) {}
    Light(){}
    Color color;
    float strength;
    };
}
#endif //RAYLIBECS_LIGHTCOMPONENT_HPP

M src/components/ModelLightsShader.hpp => src/components/ModelLightsShader.hpp +2 -0
@@ 3,6 3,8 @@

namespace Components {
    struct ModelLightsShader {
        ModelLightsShader(){}
        ModelLightsShader(const Shader &shader) : shader(shader){};
        Shader shader;
    };
}
\ No newline at end of file

M src/components/Transform.hpp => src/components/Transform.hpp +2 -0
@@ 4,6 4,8 @@

namespace Components {
struct Transform final {
    Transform(){}
    Transform(const Vector3 &pos, float angle) : pos(pos), angle(angle) {}
    Vector3 pos;
    float angle;
};

M src/main.cpp => src/main.cpp +17 -18
@@ 10,6 10,7 @@
#include "systems/MissileSystem.hpp"
#include "systems/MovementSystem.hpp"
#include "systems/PlayerInputSystem.hpp"
#include "systems/RenderLightingSystem.hpp"
#include "systems/RenderSystem.hpp"
#include "systems/SpawnSystem.hpp"
#include "utils/JsonParser.hpp"


@@ 26,6 27,7 @@ const char *CONFIG_PATH = "data/mod.ini";

void UpdateDrawFrame(void);

Systems::RenderLightingSystem renderLightingSystem;
Systems::RenderSystem renderSystem;
Systems::SpawnSystem spawnSystem;
Systems::PlayerInputSystem playerInputSystem;


@@ 39,8 41,7 @@ entt::registry<> registry;
Camera camera;
std::string jsonFile;

void resetCamera()
{
void resetCamera() {
    camera = {0};
    camera.target = (Vector3){0.0f, 0.5f, 0.0f};
    camera.up = (Vector3){0.0f, 1.0f, 0.0f};


@@ 49,21 50,21 @@ void resetCamera()
    camera.position = {0.0f, 0.f, 0.0f};
}

void restartGame()
{
void restartGame() {
    registry.reset();
    resetCamera();
    renderLightingSystem.Prepare(registry);
    Components::readFromFile(registry, jsonFile.c_str());
}

int main(int argc, char **argv) {
    INIReader reader(argc == 2 ? argv[1] : CONFIG_PATH);
//    auto fileLogger = spdlog::basic_logger_mt("basic_logger", "logs/game.log");
//    spdlog::set_default_logger(fileLogger);
//    spdlog::set_pattern("[%H:%M:%S] %v");
    //    auto fileLogger = spdlog::basic_logger_mt("basic_logger", "logs/game.log");
    //    spdlog::set_default_logger(fileLogger);
    //    spdlog::set_pattern("[%H:%M:%S] %v");

    if(reader.ParseError() != 0) {
//        spdlog::error("Some error message with arg: {}", argc == 2 ? argv[1] : CONFIG_PATH);
        //        spdlog::error("Some error message with arg: {}", argc == 2 ? argv[1] : CONFIG_PATH);
        return 1;
    }
    const auto windowName = reader.Get("game", "name", "Raylib");


@@ 72,22 73,22 @@ int main(int argc, char **argv) {
    int flags = FLAG_WINDOW_RESIZABLE;
    if(reader.GetBoolean("gfx", "fullscreen", false))
        flags |= FLAG_FULLSCREEN_MODE;
//    if(reader.GetBoolean("gfx", "msaa", false))
//        flags |= FLAG_MSAA_4X_HINT;
    //    if(reader.GetBoolean("gfx", "msaa", false))
    //        flags |= FLAG_MSAA_4X_HINT;

    SetConfigFlags(flags);
    InitWindow(reader.GetInteger("gfx", "width", SCREEN_WIDTH), reader.GetInteger("gfx", "height", SCREEN_HEIGHT),
               windowName.c_str());
    renderLightingSystem.Init(registry);
    renderSystem.Init(registry);
    collisionSystem.Init(registry);
    aiSystem.Init(registry);
    damageSystem.Init();

//    spdlog::info("Loading files");
    //    spdlog::info("Loading files");
    Factories::UnitFactory::getInstance().loadFromFile(reader.Get("game", "units", "units.json"));
    restartGame();
//    spdlog::info("Loading files ended");

    //    spdlog::info("Loading files ended");

#if defined(PLATFORM_WEB)
    emscripten_set_main_loop(UpdateDrawFrame, 0, 1);


@@ 118,13 119,11 @@ void UpdateDrawFrame(void) {
    aiSystem.Update(registry, GetFrameTime());
    movementSystem.Update(registry);
    collisionSystem.Update(registry);
    renderLightingSystem.Update(registry, camera);
    renderSystem.Update(registry, camera);
    bool restartRequired = false;
    registry.view<Components::GameRestart>().each([&](const auto, const auto &component){
        restartRequired = true;
    });
    if(restartRequired)
    {
    registry.view<Components::GameRestart>().each([&](const auto, const auto &component) { restartRequired = true; });
    if(restartRequired) {
        restartGame();
    }
}

M src/systems/RenderLightingSystem.cpp => src/systems/RenderLightingSystem.cpp +52 -10
@@ 2,25 2,67 @@
// Created by 48785 on 04.06.2020.
//
#include "RenderLightingSystem.hpp"
#include "components/LightComponent.hpp"
#include "components/ModelLightsShader.hpp"

#include "components/Transform.hpp"
#include "utils/lightArkona.h"
namespace Systems {
void RenderLightingSystem::Init(entt::registry<> &registry) {
    registry.construction<Components::ModelLightsShader>().connect<&RenderLightingSystem::LoadLightingShader>(this);
    registry.destruction<Components::ModelLightsShader>().connect<&RenderLightingSystem::UnloadLightingShader>(this);
}

void RenderLightingSystem::LoadLightingShader(entt::registry<> & registry, std::uint32_t entity){
    auto object = registry.get<Components::ModelLightsShader>(entity);
    object.shader = LoadShader("data/shaders/base_lighting.vs", "data/shaders/lighting.fs");
    object.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(object.shader, "matModel");
    object.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(object.shader, "viewPos");
    const int ambientLoc = GetShaderLocation(object.shader, "ambient");
    const float values[4]{ 0.2f, 0.2f, 0.2f, 1.0f };
void RenderLightingSystem::Update(entt::registry<> &registry, Camera &camera) {
    const float cameraPos[3] = {camera.position.x, camera.position.y, camera.position.z};
    int entityNr = -1;
    registry.view<Components::ModelLightsShader>().each([&](const auto entity, const auto &shader) {
        entityNr = entity;
    });
    if(entityNr < 0) {
        return;
    }
    auto shader = registry.get<Components::ModelLightsShader>(entityNr);
    const auto vectorViewLoc = shader.shader.locs[LOC_VECTOR_VIEW];
    SetShaderValue(shader.shader, vectorViewLoc, cameraPos, UNIFORM_VEC3);
    int counter = 0;
    registry.view<Components::Light, Components::Transform>().each(
        [&](const auto, const auto &light, const auto &transform) {
            const auto newLight = light::CreateLight(transform.pos, light.color, light.strength);
            light::UpdateLightValues(shader.shader, newLight, counter);
            counter++;
        });
}
void RenderLightingSystem::Prepare(entt::registry<> &registry) {
    {
        auto id = registry.create();
        registry.assign<Components::ModelLightsShader>(id);
    }
    auto createLight = [&](Vector3 pos, Color color, float strength){
        auto id = registry.create();
        Components::Light ligth(color,strength);
        registry.assign<Components::Light>(id,ligth);
        registry.assign<Components::Transform>(id,Components::Transform(pos,0.0f));
    };

    createLight({ 4, 2, 15 }, WHITE, 1.f);
    createLight({ 4, 2, 4 }, RED, 1.f);
    createLight({ 0, 4, 2 }, GREEN, 1.f);
    createLight({ 0, 4, 2 }, BLUE, 1.f);
}

void RenderLightingSystem::LoadLightingShader(entt::registry<> &registry, std::uint32_t entity) {
    auto newShader = LoadShader("data/shaders/base_lighting.vs", "data/shaders/lighting.fs");
    newShader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(newShader, "matModel");
    newShader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(newShader, "viewPos");
    const int ambientLoc = GetShaderLocation(newShader, "ambient");
    const float values[4]{0.2f, 0.2f, 0.2f, 1.0f};

    SetShaderValue(object.shader, ambientLoc, values, UNIFORM_VEC4);
    SetShaderValue(newShader, ambientLoc, values, UNIFORM_VEC4);
    registry.assign_or_replace<Components::ModelLightsShader>(entity, newShader);
}

void RenderLightingSystem::UnloadLightingShader(entt::registry<> & registry, std::uint32_t entity){
void RenderLightingSystem::UnloadLightingShader(entt::registry<> &registry, std::uint32_t entity) {
    auto object = registry.get<Components::ModelLightsShader>(entity);
    UnloadShader(object.shader);
}
} // namespace Systems
\ No newline at end of file

M src/systems/RenderLightingSystem.hpp => src/systems/RenderLightingSystem.hpp +8 -3
@@ 5,15 5,20 @@
#ifndef RAYLIBECS_RENDERLIGHTINGSYSTEM_HPP
#define RAYLIBECS_RENDERLIGHTINGSYSTEM_HPP
#include <entt/entity/registry.hpp>
#include "raylib.h"


namespace Systems {
class RenderLightingSystem {
  public:
    void Init(entt::registry<> &registry);
    void Prepare(entt::registry<> &registry);
    void Update(entt::registry<> &registry, Camera &camera);

  private:
    void LoadLightingShader(entt::registry<> &registry, std::uint32_t entity);
    void UnloadLightingShader(entt::registry<> &registry, std::uint32_t entity);
private:

};
}




M src/systems/RenderSystem.cpp => src/systems/RenderSystem.cpp +31 -44
@@ 6,29 6,17 @@
#include "components/CylinderRenderer.hpp"
#include "components/DamageBox.hpp"
#include "components/MeshRenderer.hpp"
#include "components/ModelLightsShader.hpp"
#include "components/PlayerInput.hpp"
#include "components/RectangleVeil.hpp"
#include "components/Transform.hpp"
#include "components/WorldScreenText.hpp"
#include "raymath.h"
#include <cmath>
#include <iostream>
#include "raymath.h"

namespace Systems {
void RenderSystem::Init(entt::registry<> &registry) {
    modelLightsShader = LoadShader("data/shaders/base_lighting.vs", "data/shaders/lighting.fs");
    modelLightsShader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(modelLightsShader, "matModel");
    modelLightsShader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(modelLightsShader, "viewPos");
    int ambientLoc = GetShaderLocation(modelLightsShader, "ambient");
    const float values[4]{ 0.2f, 0.2f, 0.2f, 1.0f };
    SetShaderValue(modelLightsShader, ambientLoc, values, UNIFORM_VEC4);


    lights[0] = light::CreateLight(light::LIGHT_POINT, (Vector3){ 4, 2, 4 }, Vector3Zero(), WHITE, modelLightsShader);
    lights[1] = light::CreateLight(light::LIGHT_POINT, (Vector3){ 4, 2, 4 }, Vector3Zero(), RED, modelLightsShader);
    lights[2] = light::CreateLight(light::LIGHT_POINT, (Vector3){ 0, 4, 2 }, Vector3Zero(), GREEN, modelLightsShader);
    lights[3] = light::CreateLight(light::LIGHT_POINT, (Vector3){ 0, 4, 2 }, Vector3Zero(), BLUE, modelLightsShader);

    registry.construction<Components::BillboardRenderer>().connect<&RenderSystem::LoadEntityTexture>(this);
    registry.destruction<Components::BillboardRenderer>().connect<&RenderSystem::UnloadEntityTexture>(this);
    registry.construction<Components::MeshRenderer>().connect<&RenderSystem::LoadEntityTexture>(this);


@@ 38,18 26,13 @@ void RenderSystem::Init(entt::registry<> &registry) {
void RenderSystem::Update(entt::registry<> &registry, Camera &camera) {
    const float w = GetScreenWidth();
    const float h = GetScreenHeight();
    const float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z };

    UpdateLightValues(modelLightsShader, lights[0]);
    UpdateLightValues(modelLightsShader, lights[1]);
    UpdateLightValues(modelLightsShader, lights[2]);
    UpdateLightValues(modelLightsShader, lights[3]);

    SetShaderValue(modelLightsShader, modelLightsShader.locs[LOC_VECTOR_VIEW], cameraPos, UNIFORM_VEC3);

    auto target = LoadRenderTexture(w,h);
    Shader modelLightsShader;
    registry.view<Components::ModelLightsShader>().each(
        [&](const auto entity, const auto &shader) { modelLightsShader = shader.shader; });
    auto target = LoadRenderTexture(w, h);
    auto fxShader = LoadShader(0, "data/shaders/pixelizer.fs");
    UpdateCamera(registry,camera);
    UpdateCamera(registry, camera);
    BeginDrawing();
    ClearBackground(SKYBLUE);
    BeginTextureMode(target);


@@ 85,9 68,7 @@ void RenderSystem::Update(entt::registry<> &registry, Camera &camera) {
    EndMode3D();
    EndTextureMode();
    BeginShaderMode(fxShader);
    {
        DrawTextureRec(target.texture, {0,0,w,-h},{0,0},WHITE);
    }
    { DrawTextureRec(target.texture, {0, 0, w, -h}, {0, 0}, WHITE); }
    EndShaderMode();
    registry.view<Components::WorldScreenText, Components::Transform>().each(
        [&](const auto, const auto &screenText, const auto &transform) {


@@ 100,22 81,26 @@ void RenderSystem::Update(entt::registry<> &registry, Camera &camera) {
            DrawText(textToShow, textScreenPos.x - MeasureText(textToShow, screenText.fontSize) / 2, textScreenPos.y,
                     screenText.fontSize, GOLD);
        });
    DrawText("Debug build", 10, 10, 10, {230, 102, 1, 255});
    registry.view<Components::RectangleVeil>().each(
        [&](const auto, Components::RectangleVeil &rectVeil) {
            rectVeil.elapsed += GetFrameTime();// TODO- move outside render system to UI system
            for(int i = 0; i < rectVeil.rectanglesInX;++i)
            {
                for(int j = 0;j < rectVeil.getRectangleInY();++j)
                {
                    const float startFrame = rectVeil.frameDelay * j;
                    const float endFrame = startFrame + rectVeil.rectAnimDuration;
                    const float sizeModifier = rectVeil.elapsed < startFrame ? 1.0f : (rectVeil.elapsed > endFrame ? 0.0f : 1.0f - ((rectVeil.elapsed - startFrame) / rectVeil.rectAnimDuration));
                    const float offset = (rectVeil.getRectangleSize() / 2.0f * (1.0f - sizeModifier));
                    DrawRectangle(i * rectVeil.getRectangleSize() + offset, j * rectVeil.getRectangleSize() + offset,rectVeil.getRectangleSize() * sizeModifier, rectVeil.getRectangleSize() * sizeModifier, BLACK);
                }
    DrawText("Debug build", 10, 10, 15, {230, 102, 1, 255});
    registry.view<Components::RectangleVeil>().each([&](const auto, Components::RectangleVeil &rectVeil) {
        rectVeil.elapsed += GetFrameTime(); // TODO- move outside render system to UI system
        for(int i = 0; i < rectVeil.rectanglesInX; ++i) {
            for(int j = 0; j < rectVeil.getRectangleInY(); ++j) {
                const float startFrame = rectVeil.frameDelay * j;
                const float endFrame = startFrame + rectVeil.rectAnimDuration;
                const float sizeModifier =
                    rectVeil.elapsed < startFrame
                        ? 1.0f
                        : (rectVeil.elapsed > endFrame
                               ? 0.0f
                               : 1.0f - ((rectVeil.elapsed - startFrame) / rectVeil.rectAnimDuration));
                const float offset = (rectVeil.getRectangleSize() / 2.0f * (1.0f - sizeModifier));
                DrawRectangle(i * rectVeil.getRectangleSize() + offset, j * rectVeil.getRectangleSize() + offset,
                              rectVeil.getRectangleSize() * sizeModifier, rectVeil.getRectangleSize() * sizeModifier,
                              BLACK);
            }
        });
        }
    });
    EndDrawing();
    UnloadRenderTexture(target);
    UnloadShader(fxShader);


@@ 139,8 124,11 @@ void RenderSystem::LoadEntityTexture(entt::registry<> &registry, std::uint32_t e

        if(!mesh.diffusePath.empty()) {
            mesh.diffuse = LoadTexture(mesh.diffusePath.c_str());
            if(mesh.model.materialCount > 0){
            if(mesh.model.materialCount > 0) {
                mesh.model.materials[0].maps[MAP_DIFFUSE].texture = mesh.diffuse;
                Shader modelLightsShader;
                registry.view<Components::ModelLightsShader>().each(
                    [&](const auto entity, const auto &shader) { modelLightsShader = shader.shader; });
                mesh.model.materials[0].shader = modelLightsShader;
            }
        }


@@ 181,4 169,3 @@ void RenderSystem::UpdateCamera(entt::registry<> &registry, Camera &camera) {
        });
}
} // namespace Systems
  // Systems

M src/systems/RenderSystem.hpp => src/systems/RenderSystem.hpp +0 -2
@@ 17,8 17,6 @@ class RenderSystem {

  private:
    void UpdateCamera(entt::registry<> &registry, Camera &camera);
    Shader modelLightsShader;
    light::Light lights[light::MAX_LIGHTS] = { 0 };
};
} // namespace Systems
  // Systems

M src/utils/lightArkona.h => src/utils/lightArkona.h +36 -38
@@ 10,6 10,7 @@ namespace light {
        Vector3 target;
        Color color;
        bool enabled;
        float strength;

        // Shader locations
        int enabledLoc;


@@ 17,6 18,7 @@ namespace light {
        int posLoc;
        int targetLoc;
        int colorLoc;
        int strengthLoc;
    } Light;

    // Light type


@@ 25,15 27,39 @@ namespace light {
        LIGHT_POINT
    } LightType;

    static int lightsCount = 0;    // Current amount of created lights

    // Send light properties to shader
    // NOTE: Light shader locations should be available
    static void UpdateLightValues(Shader shader, Light light)
    static void UpdateLightValues(Shader shader, Light light, int lightNr)
    {
        if(lightNr >= MAX_LIGHTS)
        {
            return;
        }
        char enabledName[32] = "lights[x].enabled\0";
        char typeName[32] = "lights[x].type\0";
        char posName[32] = "lights[x].position\0";
        char targetName[32] = "lights[x].target\0";
        char colorName[32] = "lights[x].color\0";
        char strengthName[32] = "lights[x].strength\0";

        // Set location name [x] depending on lights count
        enabledName[7] = '0' + lightNr;
        typeName[7] = '0' + lightNr;
        posName[7] = '0' + lightNr;
        targetName[7] = '0' + lightNr;
        colorName[7] = '0' + lightNr;
        strengthName[7] = '0' + lightNr;

        light.enabledLoc = GetShaderLocation(shader, enabledName);
        light.typeLoc = GetShaderLocation(shader, typeName);
        light.posLoc = GetShaderLocation(shader, posName);
        light.targetLoc = GetShaderLocation(shader, targetName);
        light.colorLoc = GetShaderLocation(shader, colorName);
        light.strengthLoc = GetShaderLocation(shader, strengthName);
        // Send to shader light enabled state and type
        SetShaderValue(shader, light.enabledLoc, &light.enabled, UNIFORM_INT);
        SetShaderValue(shader, light.typeLoc, &light.type, UNIFORM_INT);
        SetShaderValue(shader, light.strengthLoc, &light.strength, UNIFORM_FLOAT);

        // Send to shader light position values
        const float position[3] = { light.position.x, light.position.y, light.position.z };


@@ 50,44 76,16 @@ namespace light {
    }

    // Create a light and get shader locations
    static Light CreateLight(int type, Vector3 position, Vector3 target, Color color, Shader shader)
    static Light CreateLight(const Vector3 position, const Color color, const float strength)
    {
        Light light = { 0 };

        if (lightsCount < MAX_LIGHTS)
        {
            light.enabled = true;
            light.type = type;
            light.position = position;
            light.target = target;
            light.color = color;

            // TODO: Below code doesn't look good to me,
            // it assumes a specific shader naming and structure
            // Probably this implementation could be improved
            char enabledName[32] = "lights[x].enabled\0";
            char typeName[32] = "lights[x].type\0";
            char posName[32] = "lights[x].position\0";
            char targetName[32] = "lights[x].target\0";
            char colorName[32] = "lights[x].color\0";

            // Set location name [x] depending on lights count
            enabledName[7] = '0' + lightsCount;
            typeName[7] = '0' + lightsCount;
            posName[7] = '0' + lightsCount;
            targetName[7] = '0' + lightsCount;
            colorName[7] = '0' + lightsCount;

            light.enabledLoc = GetShaderLocation(shader, enabledName);
            light.typeLoc = GetShaderLocation(shader, typeName);
            light.posLoc = GetShaderLocation(shader, posName);
            light.targetLoc = GetShaderLocation(shader, targetName);
            light.colorLoc = GetShaderLocation(shader, colorName);

            UpdateLightValues(shader, light);

            lightsCount++;
        }
        light.enabled = true;
        light.type = LIGHT_POINT;
        light.position = position;
        light.strength = strength;
        light.target = { 0.0f, 0.0f, 0.0f };
        light.color = color;

        return light;
    }