2013-11-09 17:46:34 +00:00
|
|
|
#include "SoftwareRenderer.h"
|
|
|
|
|
2013-11-14 17:47:03 +00:00
|
|
|
#include "CameraDefinition.h"
|
2013-11-10 16:04:38 +00:00
|
|
|
#include "Scenery.h"
|
2013-11-11 14:42:11 +00:00
|
|
|
#include "FluidMediumManager.h"
|
2013-11-12 20:34:35 +00:00
|
|
|
#include "AtmosphereRenderer.h"
|
2013-11-15 23:27:40 +00:00
|
|
|
#include "AtmosphereDefinition.h"
|
2013-12-08 19:54:34 +00:00
|
|
|
#include "AtmosphereResult.h"
|
2013-12-01 18:24:53 +00:00
|
|
|
#include "CloudsRenderer.h"
|
2013-12-15 12:59:21 +00:00
|
|
|
#include "CloudsDefinition.h"
|
2013-12-08 19:54:34 +00:00
|
|
|
#include "TerrainRenderer.h"
|
|
|
|
#include "TexturesRenderer.h"
|
|
|
|
#include "WaterRenderer.h"
|
2013-12-01 18:24:53 +00:00
|
|
|
#include "SkyRasterizer.h"
|
2013-12-05 15:44:18 +00:00
|
|
|
#include "TerrainRasterizer.h"
|
2013-12-08 17:05:18 +00:00
|
|
|
#include "WaterRasterizer.h"
|
2013-12-26 14:36:15 +00:00
|
|
|
#include "NightSky.h"
|
2013-12-08 19:54:34 +00:00
|
|
|
#include "LightStatus.h"
|
|
|
|
#include "LightingManager.h"
|
2013-12-09 10:59:57 +00:00
|
|
|
#include "System.h"
|
|
|
|
#include "Thread.h"
|
2013-11-12 20:34:35 +00:00
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
SoftwareRenderer::SoftwareRenderer(Scenery* scenery)
|
2013-11-17 21:36:18 +00:00
|
|
|
{
|
2013-12-09 10:59:57 +00:00
|
|
|
RenderArea::RenderParams params = {1, 1, 1, 5};
|
2013-11-17 21:36:18 +00:00
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
render_quality = 5;
|
|
|
|
render_width = 1;
|
|
|
|
render_height = 1;
|
|
|
|
render_interrupt = 0;
|
|
|
|
render_progress = 0.0;
|
|
|
|
is_rendering = 0;
|
|
|
|
render_camera = new CameraDefinition;
|
|
|
|
render_area = new RenderArea(this);
|
|
|
|
render_area->setParams(params);
|
2013-11-09 17:46:34 +00:00
|
|
|
|
2013-11-12 20:34:35 +00:00
|
|
|
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
2013-12-01 18:24:53 +00:00
|
|
|
clouds_renderer = new CloudsRenderer(this);
|
2013-12-08 19:54:34 +00:00
|
|
|
terrain_renderer = new TerrainRenderer(this);
|
|
|
|
textures_renderer = new TexturesRenderer(this);
|
|
|
|
water_renderer = new WaterRenderer(this);
|
2013-11-12 20:34:35 +00:00
|
|
|
|
2013-12-26 14:36:15 +00:00
|
|
|
nightsky_renderer = new NightSky(this);
|
|
|
|
|
2013-11-11 14:42:11 +00:00
|
|
|
fluid_medium = new FluidMediumManager(this);
|
2013-12-09 10:59:57 +00:00
|
|
|
lighting = new LightingManager();
|
2013-11-10 16:04:38 +00:00
|
|
|
|
2013-12-17 22:45:09 +00:00
|
|
|
lighting->registerFilter(terrain_renderer);
|
|
|
|
lighting->registerFilter(water_renderer);
|
|
|
|
lighting->registerFilter(clouds_renderer);
|
|
|
|
|
2013-12-15 17:44:54 +00:00
|
|
|
this->scenery = new Scenery;
|
2013-11-10 16:04:38 +00:00
|
|
|
if (scenery)
|
|
|
|
{
|
2013-12-15 17:44:54 +00:00
|
|
|
scenery->copy(this->scenery);
|
2013-11-10 16:04:38 +00:00
|
|
|
}
|
2013-11-09 17:46:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SoftwareRenderer::~SoftwareRenderer()
|
|
|
|
{
|
2013-12-09 10:59:57 +00:00
|
|
|
delete render_camera;
|
|
|
|
delete render_area;
|
|
|
|
|
2013-12-17 22:45:09 +00:00
|
|
|
delete fluid_medium;
|
|
|
|
delete lighting;
|
|
|
|
|
2013-12-26 14:36:15 +00:00
|
|
|
delete nightsky_renderer;
|
|
|
|
|
2013-11-12 20:34:35 +00:00
|
|
|
delete atmosphere_renderer;
|
2013-12-01 18:24:53 +00:00
|
|
|
delete clouds_renderer;
|
2013-12-08 19:54:34 +00:00
|
|
|
delete terrain_renderer;
|
|
|
|
delete textures_renderer;
|
|
|
|
delete water_renderer;
|
2013-11-12 20:34:35 +00:00
|
|
|
|
2013-12-15 17:44:54 +00:00
|
|
|
delete scenery;
|
2013-11-09 17:46:34 +00:00
|
|
|
}
|
2013-11-10 16:04:38 +00:00
|
|
|
|
2013-11-17 21:36:18 +00:00
|
|
|
void SoftwareRenderer::setScenery(Scenery* scenery)
|
|
|
|
{
|
|
|
|
scenery->copy(this->scenery);
|
|
|
|
}
|
|
|
|
|
2013-11-12 20:34:35 +00:00
|
|
|
void SoftwareRenderer::prepare()
|
2013-11-10 16:04:38 +00:00
|
|
|
{
|
2013-12-15 13:45:38 +00:00
|
|
|
scenery->getCamera()->copy(render_camera);
|
|
|
|
|
2013-11-12 20:34:35 +00:00
|
|
|
// Prepare sub renderers
|
2013-12-17 22:45:09 +00:00
|
|
|
// TODO Don't recreate the renderer each time
|
2013-11-12 20:34:35 +00:00
|
|
|
delete atmosphere_renderer;
|
2013-12-15 13:28:46 +00:00
|
|
|
if (getScenery()->getAtmosphere()->model == AtmosphereDefinition::ATMOSPHERE_MODEL_BRUNETON)
|
|
|
|
{
|
|
|
|
atmosphere_renderer = new SoftwareBrunetonAtmosphereRenderer(this);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
|
|
|
}
|
2013-11-12 20:34:35 +00:00
|
|
|
|
2013-12-01 18:24:53 +00:00
|
|
|
clouds_renderer->update();
|
2013-12-17 22:45:09 +00:00
|
|
|
terrain_renderer->update();
|
|
|
|
water_renderer->update();
|
|
|
|
textures_renderer->update();
|
2013-11-12 20:34:35 +00:00
|
|
|
|
2013-12-26 14:36:15 +00:00
|
|
|
nightsky_renderer->update();
|
|
|
|
|
2013-11-12 20:34:35 +00:00
|
|
|
// Prepare global tools
|
|
|
|
fluid_medium->clearMedia();
|
2013-11-11 14:42:11 +00:00
|
|
|
//fluid_medium->registerMedium(water_renderer);
|
2013-11-10 16:04:38 +00:00
|
|
|
}
|
2013-11-11 14:42:11 +00:00
|
|
|
|
2013-12-01 18:24:53 +00:00
|
|
|
void SoftwareRenderer::rasterize()
|
2013-11-11 14:42:11 +00:00
|
|
|
{
|
2013-12-05 15:44:18 +00:00
|
|
|
TerrainRasterizer terrain(this);
|
|
|
|
terrain.renderSurface();
|
|
|
|
|
2013-12-08 17:05:18 +00:00
|
|
|
WaterRasterizer water(this);
|
|
|
|
water.renderSurface();
|
2013-12-01 18:24:53 +00:00
|
|
|
|
|
|
|
SkyRasterizer sky(this);
|
|
|
|
sky.rasterize();
|
|
|
|
}
|
|
|
|
|
2013-12-15 12:59:21 +00:00
|
|
|
void SoftwareRenderer::disableClouds()
|
|
|
|
{
|
|
|
|
scenery->getClouds()->clear();
|
|
|
|
}
|
|
|
|
|
2013-12-20 16:30:27 +00:00
|
|
|
void SoftwareRenderer::disableAtmosphere()
|
|
|
|
{
|
|
|
|
LightComponent light;
|
|
|
|
std::vector<LightComponent> lights;
|
|
|
|
|
|
|
|
light.color.r = 1.5;
|
|
|
|
light.color.g = 1.5;
|
|
|
|
light.color.b = 1.5;
|
|
|
|
light.direction.x = -1.0;
|
2013-12-29 17:18:18 +00:00
|
|
|
light.direction.y = -0.3;
|
2013-12-20 16:30:27 +00:00
|
|
|
light.direction.z = 1.0;
|
|
|
|
light.direction = light.direction.normalize();
|
|
|
|
light.altered = 1;
|
|
|
|
light.reflection = 0.0;
|
|
|
|
lights.push_back(light);
|
|
|
|
|
2013-12-29 17:44:12 +00:00
|
|
|
light.color.r = 0.25;
|
|
|
|
light.color.g = 0.25;
|
|
|
|
light.color.b = 0.265;
|
2013-12-20 16:30:27 +00:00
|
|
|
light.direction.x = 1.0;
|
|
|
|
light.direction.y = -0.5;
|
|
|
|
light.direction.z = -1.0;
|
|
|
|
light.direction = light.direction.normalize();
|
|
|
|
light.altered = 0;
|
|
|
|
light.reflection = 0.0;
|
|
|
|
lights.push_back(light);
|
|
|
|
|
|
|
|
disableAtmosphere(lights);
|
|
|
|
}
|
|
|
|
|
2013-12-15 13:28:46 +00:00
|
|
|
void SoftwareRenderer::disableAtmosphere(const std::vector<LightComponent> &lights)
|
|
|
|
{
|
|
|
|
scenery->getAtmosphere()->model = AtmosphereDefinition::ATMOSPHERE_MODEL_DISABLED;
|
|
|
|
|
|
|
|
delete atmosphere_renderer;
|
|
|
|
atmosphere_renderer = new BaseAtmosphereRenderer(this);
|
|
|
|
atmosphere_renderer->setStaticLights(lights);
|
|
|
|
}
|
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
void SoftwareRenderer::setPreviewCallbacks(RenderArea::RenderCallbackStart start, RenderArea::RenderCallbackDraw draw, RenderArea::RenderCallbackUpdate update)
|
|
|
|
{
|
|
|
|
render_area->setPreviewCallbacks(start, draw, update);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void* _renderFirstPass(void* data)
|
|
|
|
{
|
|
|
|
SoftwareRenderer* renderer = (SoftwareRenderer*)data;
|
|
|
|
renderer->rasterize();
|
2013-12-10 22:06:57 +00:00
|
|
|
renderer->is_rendering = 0;
|
2013-12-09 10:59:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SoftwareRenderer::start(RenderArea::RenderParams params)
|
|
|
|
{
|
|
|
|
Thread thread(_renderFirstPass);
|
|
|
|
int loops;
|
|
|
|
int core_count = System::getCoreCount();
|
|
|
|
|
|
|
|
params.antialias = (params.antialias < 1) ? 1 : params.antialias;
|
|
|
|
params.antialias = (params.antialias > 4) ? 4 : params.antialias;
|
|
|
|
|
|
|
|
render_quality = params.quality;
|
|
|
|
render_width = params.width * params.antialias;
|
|
|
|
render_height = params.height * params.antialias;
|
|
|
|
render_interrupt = 0;
|
|
|
|
render_progress = 0.0;
|
|
|
|
|
2013-12-15 13:45:38 +00:00
|
|
|
prepare();
|
|
|
|
|
2013-12-09 10:59:57 +00:00
|
|
|
render_camera->setRenderSize(render_width, render_height);
|
|
|
|
|
|
|
|
render_area->setBackgroundColor(COLOR_BLACK);
|
|
|
|
render_area->setParams(params);
|
|
|
|
render_area->clear();
|
|
|
|
|
|
|
|
is_rendering = 1;
|
|
|
|
thread.start(this);
|
|
|
|
loops = 0;
|
|
|
|
|
|
|
|
while (is_rendering)
|
|
|
|
{
|
|
|
|
Thread::timeSleepMs(100);
|
|
|
|
|
|
|
|
if (++loops >= 10)
|
|
|
|
{
|
|
|
|
render_area->update();
|
|
|
|
loops = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
thread.join();
|
|
|
|
|
|
|
|
is_rendering = 1;
|
|
|
|
render_area->postProcess(core_count);
|
|
|
|
is_rendering = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SoftwareRenderer::interrupt()
|
|
|
|
{
|
|
|
|
render_interrupt = 1;
|
|
|
|
}
|
|
|
|
|
2013-12-08 19:54:34 +00:00
|
|
|
Color SoftwareRenderer::applyLightingToSurface(const Vector3 &location, const Vector3 &normal, const SurfaceMaterial &material)
|
|
|
|
{
|
2013-12-09 10:59:57 +00:00
|
|
|
LightStatus status(lighting, location, getCameraLocation(location));
|
2013-12-08 19:54:34 +00:00
|
|
|
atmosphere_renderer->getLightingStatus(&status, normal, 0);
|
|
|
|
return status.apply(normal, material);
|
|
|
|
}
|
|
|
|
|
2013-12-01 18:24:53 +00:00
|
|
|
Color SoftwareRenderer::applyMediumTraversal(Vector3 location, Color color)
|
|
|
|
{
|
2013-12-08 19:54:34 +00:00
|
|
|
color = atmosphere_renderer->applyAerialPerspective(location, color).final;
|
2013-12-09 10:59:57 +00:00
|
|
|
color = clouds_renderer->getColor(getCameraLocation(location), location, color);
|
2013-12-01 18:24:53 +00:00
|
|
|
return color;
|
|
|
|
|
|
|
|
/*Vector3 eye = cameraGetLocation(scenery->getCamera());
|
|
|
|
return fluid_medium->applyTraversal(eye, location, color);*/
|
|
|
|
}
|
2013-12-08 16:56:59 +00:00
|
|
|
|
2013-12-08 19:54:34 +00:00
|
|
|
RayCastingResult SoftwareRenderer::rayWalking(const Vector3 &location, const Vector3 &direction, int, int, int, int)
|
2013-12-08 16:56:59 +00:00
|
|
|
{
|
2013-12-08 19:54:34 +00:00
|
|
|
RayCastingResult result;
|
|
|
|
Color sky_color;
|
|
|
|
|
|
|
|
result = terrain_renderer->castRay(location, direction);
|
|
|
|
if (!result.hit)
|
|
|
|
{
|
|
|
|
sky_color = atmosphere_renderer->getSkyColor(direction).final;
|
|
|
|
|
|
|
|
result.hit = 1;
|
2013-12-11 10:32:10 +00:00
|
|
|
result.hit_location = location.add(direction.scale(1000.0));
|
2013-12-08 19:54:34 +00:00
|
|
|
result.hit_color = clouds_renderer->getColor(location, result.hit_location, sky_color);
|
|
|
|
}
|
|
|
|
|
2013-12-08 16:56:59 +00:00
|
|
|
return result;
|
|
|
|
}
|
2013-12-09 10:59:57 +00:00
|
|
|
|
|
|
|
int SoftwareRenderer::addRenderProgress(double)
|
|
|
|
{
|
|
|
|
return not render_interrupt;
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
Vector3 SoftwareRenderer::getCameraLocation(const Vector3 &)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
return render_camera->getLocation();
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
Vector3 SoftwareRenderer::getCameraDirection(const Vector3 &)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
return render_camera->getDirectionNormalized();
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
double SoftwareRenderer::getPrecision(const Vector3 &location)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
Vector3 projected;
|
|
|
|
|
|
|
|
projected = render_camera->project(location);
|
|
|
|
projected.x += 1.0;
|
|
|
|
//projected.y += 1.0;
|
|
|
|
|
2013-12-11 10:32:10 +00:00
|
|
|
return render_camera->unproject(projected).sub(location).getNorm(); // / (double)render_quality;
|
2013-12-09 10:59:57 +00:00
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
Vector3 SoftwareRenderer::projectPoint(const Vector3 &point)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
return render_camera->project(point);
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
Vector3 SoftwareRenderer::unprojectPoint(const Vector3 &point)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
return render_camera->unproject(point);
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
void SoftwareRenderer::pushTriangle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, RenderArea::f_RenderFragmentCallback callback, void* callback_data)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
Vector3 p1, p2, p3;
|
|
|
|
|
|
|
|
p1 = projectPoint(v1);
|
|
|
|
p2 = projectPoint(v2);
|
|
|
|
p3 = projectPoint(v3);
|
|
|
|
|
|
|
|
render_area->pushTriangle(p1, p2, p3, v1, v2, v3, callback, callback_data);
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
void SoftwareRenderer::pushQuad(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, RenderArea::f_RenderFragmentCallback callback, void* callback_data)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
pushTriangle(v2, v3, v1, callback, callback_data);
|
|
|
|
pushTriangle(v4, v1, v3, callback, callback_data);
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
void SoftwareRenderer::pushDisplacedTriangle(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, RenderArea::f_RenderFragmentCallback callback, void* callback_data)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
Vector3 p1, p2, p3;
|
|
|
|
|
|
|
|
p1 = projectPoint(v1);
|
|
|
|
p2 = projectPoint(v2);
|
|
|
|
p3 = projectPoint(v3);
|
|
|
|
|
|
|
|
render_area->pushTriangle(p1, p2, p3, ov1, ov2, ov3, callback, callback_data);
|
|
|
|
}
|
|
|
|
|
2013-12-11 11:46:39 +00:00
|
|
|
void SoftwareRenderer::pushDisplacedQuad(const Vector3 &v1, const Vector3 &v2, const Vector3 &v3, const Vector3 &v4, const Vector3 &ov1, const Vector3 &ov2, const Vector3 &ov3, const Vector3 &ov4, RenderArea::f_RenderFragmentCallback callback, void* callback_data)
|
2013-12-09 10:59:57 +00:00
|
|
|
{
|
|
|
|
pushDisplacedTriangle(v2, v3, v1, ov2, ov3, ov1, callback, callback_data);
|
|
|
|
pushDisplacedTriangle(v4, v1, v3, ov4, ov1, ov3, callback, callback_data);
|
|
|
|
}
|