Lighting fix (experimental)

- changed fixed light allocation to prioritized per-use basis
- minor refactoring in CPlanet and CWater
dev-ui
Piotr Dziwinski 2012-09-26 23:18:57 +02:00
parent 2fa4d7b0db
commit 80d3a9bff1
9 changed files with 162 additions and 96 deletions

View File

@ -2810,7 +2810,7 @@ void CEngine::Draw3DScene()
if (m_shadowVisible)
{
m_lightMan->UpdateLightsEnableState(ENG_OBJTYPE_TERRAIN);
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN);
// Draw the terrain
@ -2910,7 +2910,7 @@ void CEngine::Draw3DScene()
if (! IsVisible(objRank))
continue;
m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
@ -2999,7 +2999,7 @@ void CEngine::Draw3DScene()
if (! IsVisible(objRank))
continue;
m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{
@ -3041,7 +3041,7 @@ void CEngine::Draw3DScene()
}
}
m_lightMan->UpdateLightsEnableState(ENG_OBJTYPE_TERRAIN);
m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_NULL);
if (m_waterMode) m_water->DrawSurf(); // draws water surface
@ -3117,7 +3117,7 @@ void CEngine::DrawInterface()
if (! IsVisible(objRank))
continue;
m_lightMan->UpdateLightsEnableState(m_objects[objRank].type);
m_lightMan->UpdateDeviceLights(m_objects[objRank].type);
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
{

View File

@ -18,6 +18,7 @@
#include "graphics/engine/lightman.h"
#include "common/logger.h"
#include "common/iman.h"
#include "graphics/core/device.h"
@ -28,6 +29,7 @@
#include <cmath>
// Graphics module namespace
namespace Gfx {
@ -70,6 +72,7 @@ void LightProgression::SetTarget(float value)
DynamicLight::DynamicLight()
{
used = enabled = false;
priority = LIGHT_PRI_LOW;
includeType = excludeType = ENG_OBJTYPE_NULL;
}
@ -80,7 +83,7 @@ CLightManager::CLightManager(CInstanceManager* iMan, CEngine* engine)
m_iMan = iMan;
m_iMan->AddInstance(CLASS_LIGHT, this);
m_device = NULL;
m_device = nullptr;
m_engine = engine;
m_time = 0.0f;
@ -90,56 +93,54 @@ CLightManager::~CLightManager()
{
m_iMan->DeleteInstance(CLASS_LIGHT, this);
m_iMan = NULL;
m_device = NULL;
m_engine = NULL;
m_iMan = nullptr;
m_device = nullptr;
m_engine = nullptr;
}
void CLightManager::SetDevice(CDevice* device)
{
m_device = device;
m_dynLights = std::vector<DynamicLight>(m_device->GetMaxLightCount(), DynamicLight());
m_lightMap = std::vector<int>(m_device->GetMaxLightCount(), -1);
}
void CLightManager::FlushLights()
{
for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
{
m_dynLights[i].used = false;
m_device->SetLightEnabled(i, false);
}
m_dynLights.clear();
}
/** Returns the index of light created or -1 if all lights are used. */
int CLightManager::CreateLight()
/** Returns the index of light created. */
int CLightManager::CreateLight(LightPriority priority)
{
for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
int index = 0;
for (; index < static_cast<int>( m_dynLights.size() ); index++)
{
if (m_dynLights[i].used) continue;
m_dynLights[i] = DynamicLight();
m_dynLights[i].used = true;
m_dynLights[i].enabled = true;
m_dynLights[i].includeType = ENG_OBJTYPE_NULL;
m_dynLights[i].excludeType = ENG_OBJTYPE_NULL;
m_dynLights[i].light.type = LIGHT_DIRECTIONAL;
m_dynLights[i].light.diffuse = Color(0.5f, 0.5f, 0.5f);
m_dynLights[i].light.position = Math::Vector(-100.0f, 100.0f, -100.0f);
m_dynLights[i].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f);
m_dynLights[i].intensity.Init(1.0f); // maximum
m_dynLights[i].colorRed.Init(0.5f);
m_dynLights[i].colorGreen.Init(0.5f);
m_dynLights[i].colorBlue.Init(0.5f); // gray
return i;
if (! m_dynLights[index].used)
break;
}
return -1;
if (index == static_cast<int>(m_dynLights.size()))
m_dynLights.push_back(DynamicLight());
m_dynLights[index] = DynamicLight();
m_dynLights[index].used = true;
m_dynLights[index].enabled = true;
m_dynLights[index].priority = priority;
m_dynLights[index].includeType = ENG_OBJTYPE_NULL;
m_dynLights[index].excludeType = ENG_OBJTYPE_NULL;
m_dynLights[index].light.type = LIGHT_DIRECTIONAL;
m_dynLights[index].light.diffuse = Color(0.5f, 0.5f, 0.5f);
m_dynLights[index].light.position = Math::Vector(-100.0f, 100.0f, -100.0f);
m_dynLights[index].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f);
m_dynLights[index].intensity.Init(1.0f); // maximum
m_dynLights[index].colorRed.Init(0.5f);
m_dynLights[index].colorGreen.Init(0.5f);
m_dynLights[index].colorBlue.Init(0.5f); // gray
return index;
}
bool CLightManager::DeleteLight(int lightRank)
@ -148,8 +149,6 @@ bool CLightManager::DeleteLight(int lightRank)
return false;
m_dynLights[lightRank].used = false;
m_device->SetLightEnabled(lightRank, false);
return true;
}
@ -357,7 +356,6 @@ void CLightManager::UpdateProgression(float rTime)
}
}
void CLightManager::UpdateLights()
{
for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
@ -366,6 +364,7 @@ void CLightManager::UpdateLights()
continue;
bool enabled = m_dynLights[i].enabled;
if (m_dynLights[i].intensity.current == 0.0f)
enabled = false;
@ -379,23 +378,22 @@ void CLightManager::UpdateLights()
value = m_dynLights[i].colorBlue.current * m_dynLights[i].intensity.current;
m_dynLights[i].light.diffuse.b = value;
m_device->SetLight(i, m_dynLights[i].light);
m_device->SetLightEnabled(i, enabled);
}
else
{
m_dynLights[i].light.diffuse.r = 0.0f;
m_dynLights[i].light.diffuse.g = 0.0f;
m_dynLights[i].light.diffuse.b = 0.0f;
m_device->SetLightEnabled(i, enabled);
}
}
}
void CLightManager::UpdateLightsEnableState(EngineObjectType type)
void CLightManager::UpdateDeviceLights(EngineObjectType type)
{
for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i)
m_lightMap[i] = -1;
// High priority
for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
{
if (! m_dynLights[i].used)
@ -404,17 +402,75 @@ void CLightManager::UpdateLightsEnableState(EngineObjectType type)
continue;
if (m_dynLights[i].intensity.current == 0.0f)
continue;
if (m_dynLights[i].priority == LIGHT_PRI_LOW)
continue;
bool enabled = true;
if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL)
{
bool enabled = (m_dynLights[i].includeType == type);
m_device->SetLightEnabled(i, enabled);
}
enabled = (m_dynLights[i].includeType == type);
if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL)
enabled = (m_dynLights[i].excludeType != type);
if (enabled)
{
bool enabled = (m_dynLights[i].excludeType != type);
m_device->SetLightEnabled(i, enabled);
for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
{
if (m_lightMap[j] == -1)
{
m_lightMap[j] = i;
break;
}
}
}
}
// Low priority
for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
{
if (! m_dynLights[i].used)
continue;
if (! m_dynLights[i].enabled)
continue;
if (m_dynLights[i].intensity.current == 0.0f)
continue;
if (m_dynLights[i].priority == LIGHT_PRI_HIGH)
continue;
bool enabled = true;
if (m_dynLights[i].includeType != ENG_OBJTYPE_NULL)
enabled = (m_dynLights[i].includeType == type);
if (m_dynLights[i].excludeType != ENG_OBJTYPE_NULL)
enabled = (m_dynLights[i].excludeType != type);
if (enabled)
{
for (int j = 0; j < static_cast<int>( m_lightMap.size() ); ++j)
{
if (m_lightMap[j] == -1)
{
m_lightMap[j] = i;
break;
}
}
}
}
GetLogger()->Trace("Light allotment:\n");
for (int i = 0; i < static_cast<int>( m_lightMap.size() ); ++i)
{
int rank = m_lightMap[i];
GetLogger()->Trace("[%d] -> %d\n", i, rank);
if (rank != -1)
{
m_device->SetLight(i, m_dynLights[rank].light);
m_device->SetLightEnabled(i, true);
}
else
{
m_device->SetLightEnabled(i, false);
}
}
}

View File

@ -64,6 +64,16 @@ struct LightProgression
void SetTarget(float value);
};
/**
* \enum LightPriority
* \brief Priority in light assignment
*/
enum LightPriority
{
LIGHT_PRI_HIGH,
LIGHT_PRI_LOW
};
/**
\struct DynamicLight
\brief Dynamic light in 3D scene
@ -77,6 +87,9 @@ struct DynamicLight
//! Whether the light is turned on
bool enabled;
//! Priority in assignment
LightPriority priority;
//! Configuration of the light
Light light;
@ -123,7 +136,7 @@ public:
//! Clears and disables all lights
void FlushLights();
//! Creates a new dynamic light and returns its index (lightRank)
int CreateLight();
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
@ -161,7 +174,7 @@ public:
//! 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);
Color GetLightColor(int lightRank);
//! Sets the rate of change for dynamic light colors (RGB)
bool SetLightColorSpeed(int lightRank, float speed);
@ -170,7 +183,7 @@ public:
//! Updates (recalculates) all dynamic lights
void UpdateLights();
//! Enables or disables dynamic lights affecting the given object type
void UpdateLightsEnableState(EngineObjectType type);
void UpdateDeviceLights(EngineObjectType type);
protected:
CInstanceManager* m_iMan;
@ -181,6 +194,8 @@ protected:
float m_time;
//! List of dynamic lights
std::vector<DynamicLight> m_dynLights;
//! Map of current light allotment: graphics light -> dynamic light
std::vector<int> m_lightMap;
};
}; // namespace Gfx

View File

@ -147,7 +147,8 @@ void CPlanet::Draw()
}
void CPlanet::Create(int mode, Math::Point start, float dim, float speed,
float dir, const std::string& name, Math::Point uv1, Math::Point uv2)
float dir, const std::string& name, Math::Point uv1, Math::Point uv2,
bool transparent)
{
if (mode < 0) mode = 0;
if (mode > 1) mode = 1;
@ -164,7 +165,7 @@ void CPlanet::Create(int mode, Math::Point start, float dim, float speed,
planet.uv1 = uv1;
planet.uv2 = uv2;
planet.transparent = planet.name.find("planet") != std::string::npos;
planet.transparent = transparent;
m_planet[mode].push_back(planet);

View File

@ -91,7 +91,8 @@ public:
bool EventProcess(const Event &event);
//! Creates a new planet
void Create(int mode, Math::Point start, float dim, float speed, float dir,
const std::string& name, Math::Point uv1, Math::Point uv2);
const std::string& name, Math::Point uv1, Math::Point uv2,
bool transparent);
//! Indicates if there is at least one planet
bool PlanetExist();
//! Load all the textures for the planets

View File

@ -279,11 +279,9 @@ void CWater::DrawBack()
material.ambient = m_ambient;
m_engine->SetMaterial(material);
m_engine->SetTexture("", 0); // TODO: disable texturing
CDevice* device = m_engine->GetDevice();
m_engine->SetState(ENG_RSTATE_NORMAL);
m_engine->SetState(Gfx::ENG_RSTATE_OPAQUE_COLOR);
float deep = m_engine->GetDeepView(0);
m_engine->SetDeepView(deep*2.0f, 0);
@ -310,17 +308,14 @@ void CWater::DrawBack()
p1.y = -50.0f;
p2.y = m_level;
Math::Vector n;
n.x = (lookat.x-eye.x)/dist;
n.z = (lookat.z-eye.z)/dist;
n.y = 0.0f;
Gfx::Color white = Gfx::Color(1.0f, 1.0f, 1.0f, 0.0f);
Vertex vertices[4] =
VertexCol vertices[4] =
{
Vertex(Math::Vector(p1.x, p2.y, p1.z), n),
Vertex(Math::Vector(p1.x, p1.y, p1.z), n),
Vertex(Math::Vector(p2.x, p2.y, p2.z), n),
Vertex(Math::Vector(p2.x, p1.y, p2.z), n)
VertexCol(Math::Vector(p1.x, p2.y, p1.z), white),
VertexCol(Math::Vector(p1.x, p1.y, p1.z), white),
VertexCol(Math::Vector(p2.x, p2.y, p2.z), white),
VertexCol(Math::Vector(p2.x, p1.y, p2.z), white)
};
device->DrawPrimitive(PRIMITIVE_TRIANGLE_STRIP, vertices, 4);
@ -480,8 +475,8 @@ void CWater::CreateLine(int x, int y, int len)
}
void CWater::Create(WaterType type1, WaterType type2, const std::string& fileName,
Color diffuse, Color ambient,
float level, float glint, Math::Vector eddy)
Color diffuse, Color ambient,
float level, float glint, Math::Vector eddy)
{
m_type[0] = type1;
m_type[1] = type2;

View File

@ -169,10 +169,10 @@ protected:
protected:
CInstanceManager* m_iMan;
CEngine* m_engine;
CDevice* m_device;
CTerrain* m_terrain;
CParticle* m_particule;
CEngine* m_engine;
CDevice* m_device;
CTerrain* m_terrain;
CParticle* m_particule;
CSoundInterface* m_sound;
WaterType m_type[2];
@ -184,9 +184,9 @@ protected:
//! Amplitude of swirls
Math::Vector m_eddy;
//! Diffuse color
Color m_diffuse;
Color m_diffuse;
//! Ambient color
Color m_ambient;
Color m_ambient;
float m_time;
float m_lastLava;
int m_subdiv;
@ -201,7 +201,7 @@ protected:
bool m_draw;
bool m_lava;
Color m_color;
Color m_color;
};

View File

@ -117,9 +117,6 @@ bool CGLDevice::Create()
// So turn it on permanently
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
// To use separate specular color in drawing primitives
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
// To avoid problems with scaling & lighting
glEnable(GL_RESCALE_NORMAL);
@ -136,13 +133,13 @@ bool CGLDevice::Create()
glGetIntegerv(GL_MAX_LIGHTS, &numLights);
m_lights = std::vector<Light>(numLights, Light());
m_lightsEnabled = std::vector<bool> (numLights, false);
m_lightsEnabled = std::vector<bool> (numLights, false);
int maxTextures = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures);
m_currentTextures = std::vector<Texture> (maxTextures, Texture());
m_texturesEnabled = std::vector<bool> (maxTextures, false);
m_texturesEnabled = std::vector<bool> (maxTextures, false);
m_textureStageParams = std::vector<TextureStageParams>(maxTextures, TextureStageParams());
GetLogger()->Info("CDevice created successfully\n");
@ -310,8 +307,9 @@ void CGLDevice::SetLight(int index, const Light &light)
if (light.type == LIGHT_SPOT)
{
glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle);
glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
// TODO: fix spotlight problems
//glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle);
//glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
}
else
{
@ -326,10 +324,8 @@ void CGLDevice::UpdateLightPosition(int index)
assert(index >= 0);
assert(index < static_cast<int>( m_lights.size() ));
if ((! m_lighting) || (! m_lightsEnabled[index]))
return;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

View File

@ -3908,7 +3908,9 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
OpFloat(line, "dir", 0.0f),
name,
Math::Point(uv1.x, uv1.z),
Math::Point(uv2.x, uv2.z));
Math::Point(uv2.x, uv2.z),
strstr(name, "planet") != nullptr // TODO: add transparent op or modify textures
);
}
if (Cmd(line, "FrontsizeName") && !resetObject)
@ -4843,7 +4845,7 @@ int CRobotMain::CreateLight(Math::Vector direction, Gfx::Color color)
light.type = Gfx::LIGHT_DIRECTIONAL;
light.diffuse = color;
light.direction = direction;
int obj = m_lightMan->CreateLight();
int obj = m_lightMan->CreateLight(Gfx::LIGHT_PRI_HIGH);
m_lightMan->SetLight(obj, light);
return obj;
@ -4866,7 +4868,7 @@ int CRobotMain::CreateSpot(Math::Vector pos, Gfx::Color color)
light.attenuation0 = 2.0f;
light.attenuation1 = 0.0f;
light.attenuation2 = 0.0f;
int obj = m_lightMan->CreateLight();
int obj = m_lightMan->CreateLight(Gfx::LIGHT_PRI_HIGH);
m_lightMan->SetLight(obj, light);
return obj;