From 80d3a9bff1d5999ec5504b50103be7687672227a Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 26 Sep 2012 23:18:57 +0200 Subject: Lighting fix (experimental) - changed fixed light allocation to prioritized per-use basis - minor refactoring in CPlanet and CWater --- src/graphics/engine/engine.cpp | 10 +-- src/graphics/engine/lightman.cpp | 146 +++++++++++++++++++++++++++------------ src/graphics/engine/lightman.h | 21 +++++- src/graphics/engine/planet.cpp | 5 +- src/graphics/engine/planet.h | 3 +- src/graphics/engine/water.cpp | 23 +++--- src/graphics/engine/water.h | 14 ++-- src/graphics/opengl/gldevice.cpp | 16 ++--- src/object/robotmain.cpp | 8 ++- 9 files changed, 156 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c170922..80fbebc 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -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( 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( 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( p2.next.size() ); l3++) { diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp index 02719de..dbf9d34 100644 --- a/src/graphics/engine/lightman.cpp +++ b/src/graphics/engine/lightman.cpp @@ -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 +// 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(m_device->GetMaxLightCount(), DynamicLight()); + m_lightMap = std::vector(m_device->GetMaxLightCount(), -1); } void CLightManager::FlushLights() { - for (int i = 0; i < static_cast( 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( m_dynLights.size() ); i++) + int index = 0; + for (; index < static_cast( m_dynLights.size() ); index++) { - if (m_dynLights[i].used) continue; - - m_dynLights[i] = DynamicLight(); + if (! m_dynLights[index].used) + break; + } - m_dynLights[i].used = true; - m_dynLights[i].enabled = true; + if (index == static_cast(m_dynLights.size())) + m_dynLights.push_back(DynamicLight()); - m_dynLights[i].includeType = ENG_OBJTYPE_NULL; - m_dynLights[i].excludeType = ENG_OBJTYPE_NULL; + m_dynLights[index] = DynamicLight(); + m_dynLights[index].used = true; + m_dynLights[index].enabled = true; + m_dynLights[index].priority = priority; - 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[index].includeType = ENG_OBJTYPE_NULL; + m_dynLights[index].excludeType = ENG_OBJTYPE_NULL; - 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 + 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); - return i; - } + 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 -1; + 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( 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( m_lightMap.size() ); ++i) + m_lightMap[i] = -1; + + // High priority for (int i = 0; i < static_cast( 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) + 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].includeType == type); - m_device->SetLightEnabled(i, enabled); + for (int j = 0; j < static_cast( m_lightMap.size() ); ++j) + { + if (m_lightMap[j] == -1) + { + m_lightMap[j] = i; + break; + } + } } + } + + // Low priority + for (int i = 0; i < static_cast( 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( 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( 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 { - bool enabled = (m_dynLights[i].excludeType != type); - m_device->SetLightEnabled(i, enabled); + m_device->SetLightEnabled(i, false); } } } diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index c50d176..3b96e51 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -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 m_dynLights; + //! Map of current light allotment: graphics light -> dynamic light + std::vector m_lightMap; }; }; // namespace Gfx diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 0ac2524..3b9aa6c 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -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); diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 82c3aea..1b16da0 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -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 diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 81034a3..18811eb 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -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; diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index a43c740..21d96d4 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -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; }; diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index bbad0a7..29a0104 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -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(numLights, Light()); - m_lightsEnabled = std::vector (numLights, false); + m_lightsEnabled = std::vector (numLights, false); int maxTextures = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures); m_currentTextures = std::vector (maxTextures, Texture()); - m_texturesEnabled = std::vector (maxTextures, false); + m_texturesEnabled = std::vector (maxTextures, false); m_textureStageParams = std::vector(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( m_lights.size() )); - if ((! m_lighting) || (! m_lightsEnabled[index])) - return; - glMatrixMode(GL_MODELVIEW); + glPushMatrix(); glLoadIdentity(); diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index d6f2d2d..10733f7 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -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; -- cgit v1.2.3-1-g7c22