colobot/colobot-base/graphics/engine/lightman.h

248 lines
7.6 KiB
C++

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file graphics/engine/lightman.h
* \brief Dynamic light manager - CLightManager class
*/
#pragma once
#include "graphics/core/light.h"
#include <vector>
#include <glm/glm.hpp>
// Graphics module namespace
namespace Gfx
{
class CDevice;
class CEngine;
struct Color;
enum EngineObjectType : unsigned char;
/**
* \struct LightProgression
* \brief Describes the progression of light parameters change
*/
struct LightProgression
{
//! Starting value
float starting;
//! Ending (destination) value
float ending;
//! Current value
float current;
//! Progress from start to end
float progress;
//! Speed of progression
float speed;
LightProgression()
: starting(0.0f)
, ending(0.0f)
, current(0.0f)
, progress(0.0f)
, speed(0.0f)
{}
//! Initializes the progression
void Init(float value);
//! Updates the progression
void Update(float rTime);
//! Sets the new end value (starting is set to current)
void SetTarget(float value);
};
/**
* \enum LightPriority
* \brief Priority in light assignment
*/
enum LightPriority
{
LIGHT_PRI_HIGHEST = 0, //!< always highest weight (always picked)
LIGHT_PRI_HIGH = 1, //!< high weight
LIGHT_PRI_LOW = 2 //!< low weight
};
/**
* \struct DynamicLight
* \brief Dynamic light in 3D scene
*
* It is an extension over standard light properties. Added are dynamic progressions for light
* colors and intensity and types of objects included/excluded in lighting.
*/
struct DynamicLight
{
//! Rank (index)
int rank;
//! Whether the light is used
bool used;
//! Whether the light is turned on
bool enabled;
//! Priority in assignment
LightPriority priority;
//! Configuration of the light
Light light;
//! Progression of intensity [0, 1]
LightProgression intensity;
//! Progression of red diffuse color
LightProgression colorRed;
//! Progression of green diffuse color
LightProgression colorGreen;
//! Progression of blue diffuse color
LightProgression colorBlue;
//! Type of objects included in lighting with this light; if ENG_OBJTYPE_NULL is used, it is ignored
EngineObjectType includeType;
//! Type of objects excluded from lighting with this light; if ENG_OBJTYPE_NULL is used, it is ignored
EngineObjectType excludeType;
DynamicLight()
: rank(0)
, used(false)
, enabled(false)
, priority(LIGHT_PRI_LOW)
, includeType{}
, excludeType{}
{}
};
/**
* \class CLightManager
* \brief Manager for dynamic lights in 3D scene
*
* The class is responsible for managing dynamic lights (struct DynamicLight) used in 3D scene.
* The dynamic lights are created, updated and deleted through the class' interface.
*
* Since there is a limit on total number of lights available in OpenGL (usually up to 8), the dynamic lights
* must be emulated by displaying only some of them. All functions normally operate only on DynamicLight structs,
* updating the models with new values, while only one function, UpdateDeviceLights(), performs the actual
* synchronization to the device. It allocates device's light slots as necessary, with two priority levels
* for lights.
*/
class CLightManager
{
public:
//! Constructor
CLightManager(CEngine* engine);
//! Destructor
virtual ~CLightManager();
//! Sets the device to be used
void SetDevice(CDevice* device);
//! Prints debug info
void DebugDumpLights();
//! Clears and disables all lights
void FlushLights();
//! Creates a new dynamic light and returns its index (lightRank)
int CreateLight(LightPriority priority = LIGHT_PRI_LOW);
//! Deletes and disables the given dynamic light
bool DeleteLight(int lightRank);
//! Sets the light parameters for dynamic light
bool SetLight(int lightRank, const Light &light);
//! Returns the light parameters for given dynamic light
bool GetLight(int lightRank, Light &light);
//! Enables/disables the given dynamic light
bool SetLightEnabled(int lightRank, bool enabled);
//! Changes the light priority
bool SetLightPriority(int lightRank, LightPriority priority);
//! Sets what objects are included in given dynamic light
bool SetLightIncludeType(int lightRank, EngineObjectType type);
//! Sets what objects are excluded from given dynamic light
bool SetLightExcludeType(int lightRank, EngineObjectType type);
//! Sets the position of dynamic light
bool SetLightPos(int lightRank, const glm::vec3 &pos);
//! Returns the position of dynamic light
glm::vec3 GetLightPos(int lightRank);
//! Sets the direction of dynamic light
bool SetLightDir(int lightRank, const glm::vec3 &dir);
//! Returns the direction of dynamic light
glm::vec3 GetLightDir(int lightRank);
//! Sets the destination intensity for dynamic light's intensity progression
bool SetLightIntensity(int lightRank, float value);
//! Returns the current light intensity
float GetLightIntensity(int lightRank);
//! Sets the rate of change for dynamic light intensity
bool SetLightIntensitySpeed(int lightRank, float speed);
//! Adjusts the color of all dynamic lights
void AdaptLightColor(const Color &color, float factor);
//! Sets the destination color for dynamic light's color progression
bool SetLightColor(int lightRank, const Color &color);
//! Returns current light color
Color GetLightColor(int lightRank);
//! Sets the rate of change for dynamic light colors (RGB)
bool SetLightColorSpeed(int lightRank, float speed);
//! Updates progression of dynamic lights
void UpdateProgression(float rTime);
//! Updates (recalculates) all dynamic lights
void UpdateLights();
//! Enables or disables dynamic lights affecting the given object type
void UpdateDeviceLights(EngineObjectType type);
protected:
class CLightsComparator
{
public:
CLightsComparator(glm::vec3 eyePos, EngineObjectType objectType);
bool operator()(const DynamicLight& left, const DynamicLight& right);
private:
float GetLightWeight(const DynamicLight& dynLight);
glm::vec3 m_eyePos = { 0, 0, 0 };
EngineObjectType m_objectType;
};
protected:
CEngine* m_engine;
CDevice* m_device;
//! Current time
float m_time;
//! List of dynamic lights
std::vector<DynamicLight> m_dynLights;
//! Map of current light allocation: graphics light -> dynamic light
std::vector<int> m_lightMap;
};
} // namespace Gfx