diff --git a/src/render/software/LightComponent.cpp b/src/render/software/LightComponent.cpp new file mode 100644 index 0000000..bc21dca --- /dev/null +++ b/src/render/software/LightComponent.cpp @@ -0,0 +1,5 @@ +#include "LightComponent.h" + +/*LightComponent::LightComponent() +{ +}*/ diff --git a/src/render/software/LightComponent.h b/src/render/software/LightComponent.h new file mode 100644 index 0000000..1c18663 --- /dev/null +++ b/src/render/software/LightComponent.h @@ -0,0 +1,31 @@ +#ifndef LIGHTCOMPONENT_H +#define LIGHTCOMPONENT_H + +#include "software_global.h" + +#include "Color.h" +#include "Vector3.h" + +namespace paysages { +namespace software { + +/** + * @brief One component of a LightStatus. + * + * A light component represents the amount of light received at a point from a given direction. + */ +class SOFTWARESHARED_EXPORT LightComponent +{ +public: + //LightComponent(); + + Color color; // Light power + Vector3 direction; // Direction the light is travelling + double reflection; /* Reflected factor of the light (for specular lighting) */ + bool altered; /* Should the light be filtered or masked (by atmosphere, water, ground, clouds...) */ +}; + +} +} + +#endif // LIGHTCOMPONENT_H diff --git a/src/render/software/LightFilter.cpp b/src/render/software/LightFilter.cpp new file mode 100644 index 0000000..7128c75 --- /dev/null +++ b/src/render/software/LightFilter.cpp @@ -0,0 +1,6 @@ +#include "LightFilter.h" + +bool LightFilter::applyLightFilter(LightComponent &, const Vector3 &) +{ + return false; +} diff --git a/src/render/software/LightFilter.h b/src/render/software/LightFilter.h new file mode 100644 index 0000000..3add5fa --- /dev/null +++ b/src/render/software/LightFilter.h @@ -0,0 +1,27 @@ +#ifndef LIGHTFILTER_H +#define LIGHTFILTER_H + +#include "software_global.h" + +namespace paysages { +namespace software { + +/** + * @brief Interface for rendering parts that can alter light. + */ +class SOFTWARESHARED_EXPORT LightFilter +{ +public: + /** + * @brief Apply filtering on a light component. + * + * This will alter the component and return if the component is still + * useful. + */ + bool applyLightFilter(LightComponent &light, const Vector3 &at); +}; + +} +} + +#endif // LIGHTFILTER_H diff --git a/src/render/software/LightStatus.cpp b/src/render/software/LightStatus.cpp new file mode 100644 index 0000000..262e04d --- /dev/null +++ b/src/render/software/LightStatus.cpp @@ -0,0 +1,29 @@ +#include "LightStatus.h" + +LightStatus::LightStatus(LightingManager *manager, const Vector3 &location, const Vector3 &eye) +{ + this->manager = manager; + this->location = location; + this->eye = eye; +} + +void LightStatus::pushComponent(LightComponent component) +{ + if (manager->filter(&component, location)) + { + components.add(component); + } +} + +Color LightStatus::apply(const Vector3 &normal, const SurfaceMaterial &material) +{ + Color final(); + + for (auto component: components) + { + final.add(manager->applyFinalComponent(component, eye, location, normal, material)); + } + + final.a = material->base.a; + return final; +} diff --git a/src/render/software/LightStatus.h b/src/render/software/LightStatus.h new file mode 100644 index 0000000..5bbc3b3 --- /dev/null +++ b/src/render/software/LightStatus.h @@ -0,0 +1,33 @@ +#ifndef LIGHTSTATUS_H +#define LIGHTSTATUS_H + +#include "software_global.h" + +#include "LightComponent.h" + +namespace paysages { +namespace software { + +/** + * @brief Light status at a given point. + * + * The light status is the combination of all LightComponent received at a given location. + */ +class SOFTWARESHARED_EXPORT LightStatus +{ +public: + LightStatus(LightingManager *manager, const Vector3 &location, const Vector3 &eye); + + void pushComponent(LightComponent component); + +private: + LightingManager* manager; + Vector3 location; + Vector3 eye; + std::vector components; +}; + +} +} + +#endif // LIGHTSTATUS_H diff --git a/src/render/software/LightingManager.cpp b/src/render/software/LightingManager.cpp new file mode 100644 index 0000000..cff702e --- /dev/null +++ b/src/render/software/LightingManager.cpp @@ -0,0 +1,113 @@ +#include "LightingManager.h" + +#include "LightFilter.h" +#include "LightComponent.h" +#include "Color.h" + +LightingManager::LightingManager() +{ + specularity = true; +} + +void LightingManager::registerFilter(LightFilter* filter) +{ + if (not filters.contains(filter)) + { + filters.add(filter); + } +} + +bool LightingManager::alterLight(LightComponent &component, const Vector3 &location) +{ + if (component.altered) + { + for (auto filter:filters) + { + if (not filter.app(component, location)) + { + return false; + } + } + } + + if (not specularity) + { + component.reflection = 0.0; + } + + return component.color.getPower() > 0.0001; +} + +void LightingManager::setSpecularity(bool enabled) +{ + specularity = enabled; +} + +void applyFinalComponent(const LightComponent &component, const Vector3 &eye, const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material) +{ + Color result, light_color; + double normal_norm; + Vector3 direction_inv; + + light_color = component->color; + direction_inv = v3Scale(v3Normalize(component->direction), -1.0); + + normal_norm = v3Norm(normal); + if (normal_norm > 1.0) + { + normal_norm = 1.0; + } + normal = v3Normalize(normal); + + result = COLOR_BLACK; + + /* diffused light */ + double diffuse = v3Dot(direction_inv, normal); + diffuse = (diffuse + (1.0 - normal_norm)) / (1.0 + (1.0 - normal_norm)); + if (diffuse > 0.0) + { + result.r += diffuse * material->_rgb.r * light_color.r; + result.g += diffuse * material->_rgb.g * light_color.g; + result.b += diffuse * material->_rgb.b * light_color.b; + } + + /* specular reflection */ + if (material->reflection > 0.0 && light->reflection > 0.0) + { + Vector3 view = v3Normalize(v3Sub(location, eye)); + Vector3 reflect = v3Sub(direction_inv, v3Scale(normal, 2.0 * v3Dot(direction_inv, normal))); + double specular = v3Dot(reflect, view); + if (specular > 0.0) + { + specular = pow(specular, material->shininess) * material->reflection * light->reflection * normal_norm; + if (specular > 0.0) + { + result.r += specular * light_color.r; + result.g += specular * light_color.g; + result.b += specular * light_color.b; + } + } + } + + /* specular reflection with fresnel effect */ + /*if (material->reflection > 0.0 && light->reflection > 0.0) + { + Vector3 view = v3Normalize(v3Sub(location, eye)); + Vector3 h = v3Normalize(v3Sub(direction_inv, view)); + double fresnel = 0.02 + 0.98 * pow(1.0 - v3Dot(v3Scale(view, -1.0), h), 5.0); + double refl = v3Dot(h, normal); + if (refl > 0.0) + { + double waterBrdf = fresnel * pow(refl, material->shininess); + if (waterBrdf > 0.0) + { + refl = material->reflection * waterBrdf * light->reflection; + result.r += refl * light_color.r; + result.g += refl * light_color.g; + result.b += refl * light_color.b; + } + } + }*/ + + return result; +} diff --git a/src/render/software/LightingManager.h b/src/render/software/LightingManager.h new file mode 100644 index 0000000..b26b9e2 --- /dev/null +++ b/src/render/software/LightingManager.h @@ -0,0 +1,49 @@ +#ifndef LIGHTINGMANAGER_H +#define LIGHTINGMANAGER_H + +#include "software_global.h" + +namespace paysages { +namespace software { + +/** + * @brief Global lighting manager. + * + * This manager handles the light filters and final light rendering. + */ +class SOFTWARESHARED_EXPORT LightingManager +{ +public: + LightingManager(); + + /** + * @brief Register a filter that will receive all alterable lights. + */ + void registerFilter(LightFilter* filter); + + /** + * @brief Alter the light component at a given location. + * @return true if the light is useful + */ + bool alterLight(LightComponent &component, const Vector3 &location); + + /** + * @brief Enable or disable the specularity lighting. + */ + void setSpecularity(bool enabled); + + /** + * @brief Apply a final component on a surface material. + */ + void applyFinalComponent(const LightComponent &component, const Vector3 &eye, const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material); + +private: + int specularity; + + std::vector filters; +}; + +} +} + +#endif // LIGHTINGMANAGER_H diff --git a/src/render/software/SoftwareRenderer.cpp b/src/render/software/SoftwareRenderer.cpp index 742971e..c35f4ed 100644 --- a/src/render/software/SoftwareRenderer.cpp +++ b/src/render/software/SoftwareRenderer.cpp @@ -154,3 +154,12 @@ Color SoftwareRenderer::applyMediumTraversal(Vector3 location, Color color) /*Vector3 eye = cameraGetLocation(scenery->getCamera()); return fluid_medium->applyTraversal(eye, location, color);*/ } + +Color SoftwareRenderer::applyLightingToSurface(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material) +{ + LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location)); + renderer->atmosphere->getLightingStatus(renderer, light, normal, 0); + Color result = lightingApplyStatus(light, normal, material); + lightingDeleteStatus(light); + return result; +} diff --git a/src/render/software/SoftwareRenderer.h b/src/render/software/SoftwareRenderer.h index 7fef971..9089263 100644 --- a/src/render/software/SoftwareRenderer.h +++ b/src/render/software/SoftwareRenderer.h @@ -46,6 +46,7 @@ public: inline FluidMediumManager* getFluidMediumManager() const {return fluid_medium;} virtual Color applyMediumTraversal(Vector3 location, Color color) override; + virtual Color applyLightingToSurface(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material); private: Scenery* scenery; diff --git a/src/render/software/software.pro b/src/render/software/software.pro index cfbdb55..36b819b 100644 --- a/src/render/software/software.pro +++ b/src/render/software/software.pro @@ -24,7 +24,11 @@ SOURCES += SoftwareRenderer.cpp \ clouds/BaseCloudsModel.cpp \ clouds/CloudModelStratoCumulus.cpp \ TerrainRasterizer.cpp \ - WaterRasterizer.cpp + WaterRasterizer.cpp \ + LightingManager.cpp \ + LightStatus.cpp \ + LightFilter.cpp \ + LightComponent.cpp HEADERS += SoftwareRenderer.h\ software_global.h \ @@ -38,7 +42,11 @@ HEADERS += SoftwareRenderer.h\ clouds/BaseCloudsModel.h \ clouds/CloudModelStratoCumulus.h \ TerrainRasterizer.h \ - WaterRasterizer.h + WaterRasterizer.h \ + LightingManager.h \ + LightStatus.h \ + LightFilter.h \ + LightComponent.h unix:!symbian { maemo5 { diff --git a/src/render/software/software_global.h b/src/render/software/software_global.h index 2920249..c2badc8 100644 --- a/src/render/software/software_global.h +++ b/src/render/software/software_global.h @@ -28,6 +28,11 @@ namespace software { class SkyRasterizer; class TerrainRasterizer; + + class LightingManager; + class LightStatus; + class LightFilter; + class LightComponent; } } diff --git a/src/rendering/atmosphere/public.h b/src/rendering/atmosphere/public.h index 6125156..58a9061 100644 --- a/src/rendering/atmosphere/public.h +++ b/src/rendering/atmosphere/public.h @@ -4,7 +4,6 @@ #include "rendering_global.h" #include "../rendering_global.h" -#include "../tools/lighting.h" #include "../shared/types.h" #include "Color.h" @@ -18,7 +17,6 @@ typedef struct Color final; } AtmosphereResult; -typedef void (*FuncAtmosphereGetLightingStatus)(Renderer* renderer, LightStatus* status, Vector3 normal, int opaque); typedef AtmosphereResult (*FuncAtmosphereApplyAerialPerspective)(Renderer* renderer, Vector3 location, Color base); typedef AtmosphereResult (*FuncAtmosphereGetSkyColor)(Renderer* renderer, Vector3 direction); typedef Vector3 (*FuncAtmosphereGetSunDirection)(Renderer* renderer); @@ -28,7 +26,6 @@ class AtmosphereRenderer public: AtmosphereDefinition* definition; - FuncAtmosphereGetLightingStatus getLightingStatus; FuncAtmosphereApplyAerialPerspective applyAerialPerspective; FuncAtmosphereGetSkyColor getSkyColor; FuncAtmosphereGetSunDirection getSunDirection; diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index bcaf07b..e1d0720 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -1,6 +1,5 @@ #include "renderer.h" -#include "tools/lighting.h" #include "System.h" #include "Thread.h" #include "render.h" @@ -91,16 +90,6 @@ static RayCastingResult _rayWalking(Renderer*, Vector3, Vector3, int, int, int, return _RAYCASTING_NULL; } -static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material) -{ - LightStatus* light = lightingCreateStatus(renderer->lighting, location, renderer->getCameraLocation(renderer, location)); - renderer->atmosphere->getLightingStatus(renderer, light, normal, 0); - Color result = lightingApplyStatus(light, normal, material); - lightingDeleteStatus(light); - return result; -} - - @@ -133,8 +122,6 @@ Renderer::Renderer() rayWalking = _rayWalking; - applyLightingToSurface = _applyLightingToSurface; - lighting = lightingManagerCreate(); atmosphere = (AtmosphereRenderer*)AtmosphereRendererClass.create(); @@ -161,6 +148,11 @@ Color Renderer::applyMediumTraversal(Vector3, Color color) return color; } +Color applyLightingToSurface(const Vector3 &, const Vector3 &, const SurfaceMaterial &material) +{ + return material.base; +} + diff --git a/src/rendering/renderer.h b/src/rendering/renderer.h index 145cd57..60ed86e 100644 --- a/src/rendering/renderer.h +++ b/src/rendering/renderer.h @@ -44,7 +44,7 @@ public: void (*pushDisplacedQuad)(Renderer* renderer, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Vector3 ov1, Vector3 ov2, Vector3 ov3, Vector3 ov4, f_RenderFragmentCallback callback, void* callback_data); /* Shortcuts */ - Color(*applyLightingToSurface)(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial* material); + virtual Color applyLightingToSurface(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material); virtual Color applyMediumTraversal(Vector3 location, Color color); /* Scenery related */ diff --git a/src/rendering/rendering.pro b/src/rendering/rendering.pro index b1c661f..28ec3ed 100644 --- a/src/rendering/rendering.pro +++ b/src/rendering/rendering.pro @@ -20,7 +20,6 @@ SOURCES += main.cpp \ textures/tex_preview.cpp \ tools/texture.cpp \ tools/parallel.cpp \ - tools/lighting.cpp \ tools/data.cpp \ tools/cache.cpp \ water/wat_render.cpp \ @@ -40,7 +39,6 @@ HEADERS += \ textures/private.h \ tools/texture.h \ tools/parallel.h \ - tools/lighting.h \ tools/data.h \ tools/cache.h \ water/public.h \ diff --git a/src/rendering/textures/public.h b/src/rendering/textures/public.h index 7ad85ca..51f1ba6 100644 --- a/src/rendering/textures/public.h +++ b/src/rendering/textures/public.h @@ -3,7 +3,6 @@ #include "../rendering_global.h" #include "Layers.h" -#include "tools/lighting.h" #include "terrain/public.h" #include "SurfaceMaterial.h" diff --git a/src/rendering/tools/lighting.cpp b/src/rendering/tools/lighting.cpp deleted file mode 100644 index ca9db29..0000000 --- a/src/rendering/tools/lighting.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "lighting.h" - -#include -#include -#include -#include -#include "PackStream.h" -#include "SurfaceMaterial.h" - -#define MAX_CALLBACK_COUNT 10 -#define MAX_LIGHT_COUNT 30 - -typedef struct -{ - FuncLightingAlterLight filter; - void* data; -} LightFilterCallback; - -class LightingManager -{ -public: - int specularity_enabled; - int callbacks_count; - LightFilterCallback callbacks[MAX_CALLBACK_COUNT]; -}; - -struct LightStatus -{ - LightingManager* manager; - Vector3 location; - Vector3 eye; - int light_count; - LightDefinition lights[MAX_LIGHT_COUNT]; -}; - -LightingManager* lightingManagerCreate() -{ - LightingManager* result; - - result = new LightingManager; - result->callbacks_count = 0; - result->specularity_enabled = 1; - - return result; -} - -void lightingManagerDelete(LightingManager* filter) -{ - delete filter; -} - -void lightingManagerRegisterFilter(LightingManager* filter, FuncLightingAlterLight callback, void* data) -{ - int i; - - for (i = 0; i < filter->callbacks_count; i++) - { - if (filter->callbacks[i].filter == callback) - { - filter->callbacks[i].data = data; - return; - } - } - - if (filter->callbacks_count < MAX_CALLBACK_COUNT) - { - filter->callbacks[filter->callbacks_count].filter = callback; - filter->callbacks[filter->callbacks_count].data = data; - filter->callbacks_count++; - } -} - -void lightingManagerDisableSpecularity(LightingManager* manager) -{ - manager->specularity_enabled = 0; -} - -LightStatus* lightingCreateStatus(LightingManager* manager, Vector3 location, Vector3 eye) -{ - LightStatus* result; - - result = new LightStatus; - result->manager = manager; - result->location = location; - result->eye = eye; - result->light_count = 0; - - return result; -} - -void lightingDeleteStatus(LightStatus* status) -{ - delete status; -} - -void lightingPushLight(LightStatus* status, LightDefinition* light) -{ - if (status->light_count < MAX_LIGHT_COUNT) - { - int i; - LightingManager* manager = status->manager; - LightDefinition final = *light; - - if (light->altered) - { - for (i = 0; i < manager->callbacks_count; i++) - { - LightFilterCallback callback = manager->callbacks[i]; - LightDefinition temp = final; - if (callback.filter(callback.data, &temp, status->location)) - { - final = temp; - } - } - } - - if (!status->manager->specularity_enabled) - { - final.reflection = 0.0; - } - - status->lights[status->light_count++] = final; - } -} - -Color lightingApplyStatus(LightStatus* status, Vector3 normal, SurfaceMaterial* material) -{ - int i; - Color final, result; - - final.r = final.g = final.b = 0.0; - final.a = material->base.a; - - for (i = 0; i < status->light_count; i++) - { - result = lightingApplyOneLight(status->lights + i, status->eye, status->location, normal, material); - final.r += result.r; - final.g += result.g; - final.b += result.b; - } - - return final; -} - -Color lightingApplyOneLight(LightDefinition* light, Vector3 eye, Vector3 location, Vector3 normal, SurfaceMaterial* material) -{ - Color result, light_color; - double normal_norm; - Vector3 direction_inv; - - light_color = light->color; - direction_inv = v3Scale(v3Normalize(light->direction), -1.0); - - normal_norm = v3Norm(normal); - if (normal_norm > 1.0) - { - normal_norm = 1.0; - } - normal = v3Normalize(normal); - - result = COLOR_BLACK; - - /* diffused light */ - double diffuse = v3Dot(direction_inv, normal); - diffuse = (diffuse + (1.0 - normal_norm)) / (1.0 + (1.0 - normal_norm)); - if (diffuse > 0.0) - { - result.r += diffuse * material->_rgb.r * light_color.r; - result.g += diffuse * material->_rgb.g * light_color.g; - result.b += diffuse * material->_rgb.b * light_color.b; - } - - /* specular reflection */ - if (material->reflection > 0.0 && light->reflection > 0.0) - { - Vector3 view = v3Normalize(v3Sub(location, eye)); - Vector3 reflect = v3Sub(direction_inv, v3Scale(normal, 2.0 * v3Dot(direction_inv, normal))); - double specular = v3Dot(reflect, view); - if (specular > 0.0) - { - specular = pow(specular, material->shininess) * material->reflection * light->reflection * normal_norm; - if (specular > 0.0) - { - result.r += specular * light_color.r; - result.g += specular * light_color.g; - result.b += specular * light_color.b; - } - } - } - - /* specular reflection with fresnel effect */ - /*if (material->reflection > 0.0 && light->reflection > 0.0) - { - Vector3 view = v3Normalize(v3Sub(location, eye)); - Vector3 h = v3Normalize(v3Sub(direction_inv, view)); - double fresnel = 0.02 + 0.98 * pow(1.0 - v3Dot(v3Scale(view, -1.0), h), 5.0); - double refl = v3Dot(h, normal); - if (refl > 0.0) - { - double waterBrdf = fresnel * pow(refl, material->shininess); - if (waterBrdf > 0.0) - { - refl = material->reflection * waterBrdf * light->reflection; - result.r += refl * light_color.r; - result.g += refl * light_color.g; - result.b += refl * light_color.b; - } - } - }*/ - - return result; -} - -Vector3 lightingGetStatusLocation(LightStatus* status) -{ - return status->location; -} diff --git a/src/rendering/tools/lighting.h b/src/rendering/tools/lighting.h deleted file mode 100644 index 610a74d..0000000 --- a/src/rendering/tools/lighting.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _PAYSAGES_TOOLS_LIGHTING_H_ -#define _PAYSAGES_TOOLS_LIGHTING_H_ - -#include "../rendering_global.h" -#include "Color.h" -#include "Vector3.h" - -typedef struct -{ - Vector3 direction; /* Global direction of the light */ - Color color; /* Main color of the light */ - double reflection; /* Reflected factor of the light (for specular lighting) */ - int altered; /* Should the light be filtered or masked (by atmosphere, water, ground, clouds...) */ -} LightDefinition; - -typedef int (*FuncLightingAlterLight)(void* data, LightDefinition* light, Vector3 at); - -class LightingManager; -typedef struct LightStatus LightStatus; - -RENDERINGSHARED_EXPORT LightingManager* lightingManagerCreate(); -RENDERINGSHARED_EXPORT void lightingManagerDelete(LightingManager* filter); -RENDERINGSHARED_EXPORT void lightingManagerRegisterFilter(LightingManager* filter, FuncLightingAlterLight callback, void* data); -RENDERINGSHARED_EXPORT void lightingManagerDisableSpecularity(LightingManager* manager); - -RENDERINGSHARED_EXPORT LightStatus* lightingCreateStatus(LightingManager* manager, Vector3 location, Vector3 eye); -RENDERINGSHARED_EXPORT void lightingDeleteStatus(LightStatus* status); -RENDERINGSHARED_EXPORT void lightingPushLight(LightStatus* status, LightDefinition* light); -RENDERINGSHARED_EXPORT Color lightingApplyStatus(LightStatus* status, Vector3 normal, SurfaceMaterial* material); -RENDERINGSHARED_EXPORT Vector3 lightingGetStatusLocation(LightStatus* status); - -RENDERINGSHARED_EXPORT Color lightingApplyOneLight(LightDefinition* light, Vector3 eye, Vector3 location, Vector3 normal, SurfaceMaterial* material); - -#endif diff --git a/src/rendering/water/public.h b/src/rendering/water/public.h index 26ec700..ccd1e50 100644 --- a/src/rendering/water/public.h +++ b/src/rendering/water/public.h @@ -3,7 +3,6 @@ #include "../rendering_global.h" #include "../shared/types.h" -#include "../tools/lighting.h" #include "TerrainDefinition.h" typedef struct