[WIP] Refactoring lighting

This commit is contained in:
Michaël Lemaire 2013-12-08 17:56:59 +01:00
parent 50d499d10f
commit fca6f4c96e
20 changed files with 324 additions and 274 deletions

View file

@ -0,0 +1,5 @@
#include "LightComponent.h"
/*LightComponent::LightComponent()
{
}*/

View file

@ -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

View file

@ -0,0 +1,6 @@
#include "LightFilter.h"
bool LightFilter::applyLightFilter(LightComponent &, const Vector3 &)
{
return false;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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<LightComponent> components;
};
}
}
#endif // LIGHTSTATUS_H

View file

@ -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;
}

View file

@ -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<LightFilter*> filters;
};
}
}
#endif // LIGHTINGMANAGER_H

View file

@ -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;
}

View file

@ -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;

View file

@ -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 {

View file

@ -28,6 +28,11 @@ namespace software {
class SkyRasterizer;
class TerrainRasterizer;
class LightingManager;
class LightStatus;
class LightFilter;
class LightComponent;
}
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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 */

View file

@ -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 \

View file

@ -3,7 +3,6 @@
#include "../rendering_global.h"
#include "Layers.h"
#include "tools/lighting.h"
#include "terrain/public.h"
#include "SurfaceMaterial.h"

View file

@ -1,217 +0,0 @@
#include "lighting.h"
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <string.h>
#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;
}

View file

@ -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

View file

@ -3,7 +3,6 @@
#include "../rendering_global.h"
#include "../shared/types.h"
#include "../tools/lighting.h"
#include "TerrainDefinition.h"
typedef struct