paysages: Refactored rendering to use a RenderArea.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@252 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
e5a64ebf9f
commit
878614e13c
29 changed files with 481 additions and 531 deletions
2
TODO
2
TODO
|
@ -1,7 +1,7 @@
|
||||||
|
- Restore render interrupt and progress
|
||||||
- Clouds are lighted without filtering from ground (clouds lighted at night !)
|
- Clouds are lighted without filtering from ground (clouds lighted at night !)
|
||||||
- Camera should respect ratio aspect of render area.
|
- Camera should respect ratio aspect of render area.
|
||||||
- All noises should use the same entropy pool (saved separately), and avoid reallocs.
|
- All noises should use the same entropy pool (saved separately), and avoid reallocs.
|
||||||
- Implement light multi-sampling (mainly for skydome).
|
- Implement light multi-sampling (mainly for skydome).
|
||||||
- Remove all global variables (render_quality, render_width...), it should all be set in Renderer.
|
|
||||||
- Implement scaling and scrolling on previews.
|
- Implement scaling and scrolling on previews.
|
||||||
- Water and terrain LOD moves with the camera, fix it like in the wanderer.
|
- Water and terrain LOD moves with the camera, fix it like in the wanderer.
|
||||||
|
|
16
cli/main.c
16
cli/main.c
|
@ -3,16 +3,17 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../lib_paysages/auto.h"
|
#include "../lib_paysages/auto.h"
|
||||||
|
#include "../lib_paysages/main.h"
|
||||||
#include "../lib_paysages/render.h"
|
#include "../lib_paysages/render.h"
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
|
|
||||||
void startRender(Renderer* renderer, char* outputpath)
|
void startRender(Renderer* renderer, char* outputpath, int width, int height, int quality)
|
||||||
{
|
{
|
||||||
printf("\rRendering %s ... \n", outputpath);
|
printf("\rRendering %s ... \n", outputpath);
|
||||||
autoRenderSceneTwoPass(renderer, 0);
|
rendererStart(renderer, width, height, quality);
|
||||||
printf("\rSaving %s ... \n", outputpath);
|
printf("\rSaving %s ... \n", outputpath);
|
||||||
remove(outputpath);
|
remove(outputpath);
|
||||||
renderSaveToFile(outputpath);
|
renderSaveToFile(renderer->render_area, outputpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void displayHelp()
|
void displayHelp()
|
||||||
|
@ -97,20 +98,21 @@ int main(int argc, char** argv)
|
||||||
printf("Initializing ...\n");
|
printf("Initializing ...\n");
|
||||||
paysagesInit();
|
paysagesInit();
|
||||||
|
|
||||||
renderer = sceneryGetStandardRenderer(conf_render_quality);
|
renderer = sceneryCreateStandardRenderer();
|
||||||
renderSetSize(conf_render_width, conf_render_height);
|
rendererSetPreviewCallbacks(&renderer, NULL, NULL, _previewUpdate);
|
||||||
renderSetPreviewCallbacks(NULL, NULL, NULL, _previewUpdate);
|
|
||||||
|
|
||||||
for (outputcount = 0; outputcount < conf_nb_pictures; outputcount++)
|
for (outputcount = 0; outputcount < conf_nb_pictures; outputcount++)
|
||||||
{
|
{
|
||||||
autoSetDaytimeFraction(conf_daytime_start);
|
autoSetDaytimeFraction(conf_daytime_start);
|
||||||
|
|
||||||
sprintf(outputpath, "output/pic%05d.png", outputcount);
|
sprintf(outputpath, "output/pic%05d.png", outputcount);
|
||||||
startRender(&renderer, outputpath);
|
startRender(&renderer, outputpath, conf_render_width, conf_render_height, conf_render_quality);
|
||||||
|
|
||||||
conf_daytime_start += conf_daytime_step;
|
conf_daytime_start += conf_daytime_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rendererDelete(&renderer);
|
||||||
|
|
||||||
printf("\rDone. \n");
|
printf("\rDone. \n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -4,46 +4,21 @@
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include "tools.h"
|
||||||
|
|
||||||
#include "../lib_paysages/render.h"
|
|
||||||
#include "../lib_paysages/scenery.h"
|
#include "../lib_paysages/scenery.h"
|
||||||
#include "../lib_paysages/auto.h"
|
#include "../lib_paysages/auto.h"
|
||||||
|
|
||||||
class RenderThread:public QThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RenderThread(Renderer* renderer):QThread()
|
|
||||||
{
|
|
||||||
_renderer = renderer;
|
|
||||||
}
|
|
||||||
void run()
|
|
||||||
{
|
|
||||||
autoRenderSceneTwoPass(_renderer, 0);
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
Renderer* _renderer;
|
|
||||||
};
|
|
||||||
|
|
||||||
static DialogRender* _current_dialog;
|
static DialogRender* _current_dialog;
|
||||||
|
|
||||||
static void _renderResize(int width, int height)
|
static void _renderStart(int width, int height, Color background)
|
||||||
{
|
{
|
||||||
delete _current_dialog->pixbuf;
|
_current_dialog->pixbuf->fill(colorToQColor(background).rgb());
|
||||||
_current_dialog->pixbuf = new QImage(width, height, QImage::Format_ARGB32);
|
|
||||||
_current_dialog->area->setMinimumSize(width, height);
|
|
||||||
_current_dialog->area->setMaximumSize(width, height);
|
|
||||||
_current_dialog->area->resize(width, height);
|
|
||||||
_current_dialog->scroll->setMinimumSize(width > 800 ? 850 : width + 50, height > 600 ? 650 : height + 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _renderClear(Color col)
|
|
||||||
{
|
|
||||||
_current_dialog->pixbuf->fill(QColor(col.r * 255.0, col.g * 255.0, col.b * 255.0).rgb());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _renderDraw(int x, int y, Color col)
|
static void _renderDraw(int x, int y, Color col)
|
||||||
{
|
{
|
||||||
_current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, QColor(col.r * 255.0, col.g * 255.0, col.b * 255.0).rgb());
|
_current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, colorToQColor(col).rgb());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _renderUpdate(double progress)
|
static void _renderUpdate(double progress)
|
||||||
|
@ -52,6 +27,27 @@ static void _renderUpdate(double progress)
|
||||||
_current_dialog->progress_value = progress * 1000.0;
|
_current_dialog->progress_value = progress * 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RenderThread:public QThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RenderThread(Renderer* renderer, int width, int height, int quality):QThread()
|
||||||
|
{
|
||||||
|
_renderer = renderer;
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
_quality = quality;
|
||||||
|
}
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
rendererStart(_renderer, _width, _height, _quality);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Renderer* _renderer;
|
||||||
|
int _width;
|
||||||
|
int _height;
|
||||||
|
int _quality;
|
||||||
|
};
|
||||||
|
|
||||||
class RenderArea:public QWidget
|
class RenderArea:public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -76,6 +72,7 @@ DialogRender::DialogRender(QWidget *parent):
|
||||||
pixbuf = new QImage(1, 1, QImage::Format_ARGB32);
|
pixbuf = new QImage(1, 1, QImage::Format_ARGB32);
|
||||||
_current_dialog = this;
|
_current_dialog = this;
|
||||||
render_thread = NULL;
|
render_thread = NULL;
|
||||||
|
renderer = sceneryCreateStandardRenderer();
|
||||||
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setWindowTitle("Paysages 3D - Render");
|
setWindowTitle("Paysages 3D - Render");
|
||||||
|
@ -99,23 +96,29 @@ DialogRender::~DialogRender()
|
||||||
{
|
{
|
||||||
if (render_thread)
|
if (render_thread)
|
||||||
{
|
{
|
||||||
renderInterrupt();
|
rendererInterrupt(&renderer);
|
||||||
render_thread->wait();
|
render_thread->wait();
|
||||||
|
|
||||||
renderSetPreviewCallbacks(NULL, NULL, NULL, NULL);
|
rendererSetPreviewCallbacks(&renderer, NULL, NULL, NULL);
|
||||||
|
|
||||||
delete render_thread;
|
delete render_thread;
|
||||||
}
|
}
|
||||||
|
rendererDelete(&renderer);
|
||||||
delete pixbuf;
|
delete pixbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogRender::startRender(int quality, int width, int height)
|
void DialogRender::startRender(int quality, int width, int height)
|
||||||
{
|
{
|
||||||
renderer = sceneryGetStandardRenderer(quality);
|
delete pixbuf;
|
||||||
renderSetSize(width, height);
|
pixbuf = new QImage(width, height, QImage::Format_ARGB32);
|
||||||
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate);
|
area->setMinimumSize(width, height);
|
||||||
|
area->setMaximumSize(width, height);
|
||||||
|
area->resize(width, height);
|
||||||
|
scroll->setMinimumSize(width > 800 ? 850 : width + 50, height > 600 ? 650 : height + 50);
|
||||||
|
|
||||||
render_thread = new RenderThread(&renderer);
|
rendererSetPreviewCallbacks(&renderer, _renderStart, _renderDraw, _renderUpdate);
|
||||||
|
|
||||||
|
render_thread = new RenderThread(&renderer, width, height, quality);
|
||||||
render_thread->start();
|
render_thread->start();
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
|
@ -124,7 +127,7 @@ void DialogRender::startRender(int quality, int width, int height)
|
||||||
void DialogRender::loadLastRender()
|
void DialogRender::loadLastRender()
|
||||||
{
|
{
|
||||||
progress->hide();
|
progress->hide();
|
||||||
renderSetPreviewCallbacks(_renderResize, _renderClear, _renderDraw, _renderUpdate);
|
//renderSetPreviewCallbacks(_renderStart, _renderDraw, _renderUpdate);
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ void FormRender::saveRender()
|
||||||
filepath = QFileDialog::getSaveFileName(this, "Choose a filename to save the last render");
|
filepath = QFileDialog::getSaveFileName(this, "Choose a filename to save the last render");
|
||||||
if (!filepath.isNull())
|
if (!filepath.isNull())
|
||||||
{
|
{
|
||||||
renderSaveToFile((char*)filepath.toStdString().c_str());
|
//renderSaveToFile((char*)filepath.toStdString().c_str());
|
||||||
QMessageBox::information(this, "Message", "The picture " + filepath + " has been saved.");
|
QMessageBox::information(this, "Message", "The picture " + filepath + " has been saved.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
PreviewEast(QWidget* parent):
|
PreviewEast(QWidget* parent):
|
||||||
Preview(parent)
|
Preview(parent)
|
||||||
{
|
{
|
||||||
_renderer = rendererGetFake();
|
_renderer = rendererCreate();
|
||||||
_preview_definition = skyCreateDefinition();
|
_preview_definition = skyCreateDefinition();
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
@ -50,7 +50,7 @@ public:
|
||||||
PreviewWest(QWidget* parent):
|
PreviewWest(QWidget* parent):
|
||||||
Preview(parent)
|
Preview(parent)
|
||||||
{
|
{
|
||||||
_renderer = rendererGetFake();
|
_renderer = rendererCreate();
|
||||||
_preview_definition = skyCreateDefinition();
|
_preview_definition = skyCreateDefinition();
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -40,7 +40,7 @@ class PreviewTerrainColor:public Preview
|
||||||
public:
|
public:
|
||||||
PreviewTerrainColor(QWidget* parent):Preview(parent)
|
PreviewTerrainColor(QWidget* parent):Preview(parent)
|
||||||
{
|
{
|
||||||
_renderer = rendererGetFake();
|
_renderer = rendererCreate();
|
||||||
_renderer.applyTextures = _applyTextures;
|
_renderer.applyTextures = _applyTextures;
|
||||||
_renderer.getTerrainHeight = _getTerrainHeight;
|
_renderer.getTerrainHeight = _getTerrainHeight;
|
||||||
/*_renderer.applyLightingToSurface = _applyLightingToSurface;*/
|
/*_renderer.applyLightingToSurface = _applyLightingToSurface;*/
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
lightingAddLight(&_lighting, light);
|
lightingAddLight(&_lighting, light);
|
||||||
lightingValidateDefinition(&_lighting);
|
lightingValidateDefinition(&_lighting);
|
||||||
|
|
||||||
_renderer = rendererGetFake();
|
_renderer = rendererCreate();
|
||||||
_renderer.rayWalking = _rayWalking;
|
_renderer.rayWalking = _rayWalking;
|
||||||
_renderer.applyLightingToSurface = _applyLightingToSurface;
|
_renderer.applyLightingToSurface = _applyLightingToSurface;
|
||||||
_renderer.customData[0] = &_water;
|
_renderer.customData[0] = &_water;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
|
@ -20,8 +19,6 @@
|
||||||
#include "water.h"
|
#include "water.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
|
|
||||||
static int _is_rendering = 0;
|
|
||||||
|
|
||||||
void autoSetDaytime(int hour, int minute)
|
void autoSetDaytime(int hour, int minute)
|
||||||
{
|
{
|
||||||
autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0);
|
autoSetDaytimeFraction((double)hour / 24.0 + (double)minute / 1440.0);
|
||||||
|
@ -231,66 +228,3 @@ void autoGenRealisticLandscape(int seed)
|
||||||
scenerySetAtmosphere(&atmosphere);
|
scenerySetAtmosphere(&atmosphere);
|
||||||
atmosphereDeleteDefinition(&atmosphere);
|
atmosphereDeleteDefinition(&atmosphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* _renderFirstPass(void* data)
|
|
||||||
{
|
|
||||||
sceneryRenderFirstPass((Renderer*)data);
|
|
||||||
_is_rendering = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void autoRenderSceneTwoPass(Renderer* renderer, int postonly)
|
|
||||||
{
|
|
||||||
Thread* thread;
|
|
||||||
int loops;
|
|
||||||
|
|
||||||
if (!postonly)
|
|
||||||
{
|
|
||||||
renderClear();
|
|
||||||
|
|
||||||
_is_rendering = 1;
|
|
||||||
thread = threadCreate(_renderFirstPass, renderer);
|
|
||||||
loops = 0;
|
|
||||||
|
|
||||||
while (_is_rendering)
|
|
||||||
{
|
|
||||||
timeSleepMs(100);
|
|
||||||
|
|
||||||
if (++loops >= 10)
|
|
||||||
{
|
|
||||||
renderUpdate();
|
|
||||||
loops = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
threadJoin(thread);
|
|
||||||
}
|
|
||||||
sceneryRenderSecondPass(renderer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _postProcessRayTracingOverlay(RenderFragment* fragment)
|
|
||||||
{
|
|
||||||
Vector3 terrain_hit, look;
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
/*look = v3Sub(fragment->vertex.location, camera_location);
|
|
||||||
if (!terrainProjectRay(camera_location, look, &terrain_hit, &fragment->vertex.color))
|
|
||||||
{
|
|
||||||
fragment->vertex.color = skyProjectRay(camera_location, look);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void autoRenderSceneRayTracing()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
/*renderClear();
|
|
||||||
cameraPushOverlay(COLOR_RED, _postProcessRayTracingOverlay);
|
|
||||||
renderUpdate();
|
|
||||||
|
|
||||||
if (renderSetNextProgressStep(0.0, 1.0))
|
|
||||||
{
|
|
||||||
renderPostProcess(_cpu_count);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,8 +10,6 @@ extern "C" {
|
||||||
void autoSetDaytime(int hour, int minute);
|
void autoSetDaytime(int hour, int minute);
|
||||||
void autoSetDaytimeFraction(double daytime);
|
void autoSetDaytimeFraction(double daytime);
|
||||||
void autoGenRealisticLandscape(int seed);
|
void autoGenRealisticLandscape(int seed);
|
||||||
void autoRenderSceneTwoPass(Renderer* renderer, int postonly);
|
|
||||||
void autoRenderSceneRayTracing();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "euclid.h"
|
#include "euclid.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "scenery.h"
|
#include "scenery.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
@ -211,25 +210,25 @@ void cameraRotateRoll(CameraDefinition* camera, double value)
|
||||||
cameraValidateDefinition(camera, 0);
|
cameraValidateDefinition(camera, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 cameraProject(CameraDefinition* camera, Vector3 point)
|
Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point)
|
||||||
{
|
{
|
||||||
point = m4Transform(camera->project, point);
|
point = m4Transform(camera->project, point);
|
||||||
point.x = (point.x + 1.0) * 0.5 * (double)render_width;
|
point.x = (point.x + 1.0) * 0.5 * (double)renderer->render_width;
|
||||||
point.y = (-point.y + 1.0) * 0.5 * (double)render_height;
|
point.y = (-point.y + 1.0) * 0.5 * (double)renderer->render_height;
|
||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point)
|
Vector3 cameraUnproject(CameraDefinition* camera, Renderer* renderer, Vector3 point)
|
||||||
{
|
{
|
||||||
point.x = (point.x / (0.5 * (double)render_width) - 1.0);
|
point.x = (point.x / (0.5 * (double)renderer->render_width) - 1.0);
|
||||||
point.y = -(point.y / (0.5 * (double)render_height) - 1.0);
|
point.y = -(point.y / (0.5 * (double)renderer->render_height) - 1.0);
|
||||||
return m4Transform(camera->unproject, point);
|
return m4Transform(camera->unproject, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result)
|
void cameraProjectToFragment(CameraDefinition* camera, Renderer* renderer, double x, double y, double z, RenderFragment* result)
|
||||||
{
|
{
|
||||||
Vector3 point = {x, y, z};
|
Vector3 point = {x, y, z};
|
||||||
point = cameraProject(camera, point);
|
point = cameraProject(camera, renderer, point);
|
||||||
result->x = lround(point.x);
|
result->x = lround(point.x);
|
||||||
result->y = lround(point.y);
|
result->y = lround(point.y);
|
||||||
result->z = point.z;
|
result->z = point.z;
|
||||||
|
@ -242,9 +241,9 @@ void cameraProjectToFragment(CameraDefinition* camera, double x, double y, doubl
|
||||||
* @param col Color of the polygon.
|
* @param col Color of the polygon.
|
||||||
* @param callback Post-processing callback.
|
* @param callback Post-processing callback.
|
||||||
*/
|
*/
|
||||||
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback)
|
/*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback)
|
||||||
{
|
{
|
||||||
/*Vertex v1, v2, v3, v4;
|
Vertex v1, v2, v3, v4;
|
||||||
Vector3 v;
|
Vector3 v;
|
||||||
|
|
||||||
v.x = 0.0;
|
v.x = 0.0;
|
||||||
|
@ -275,5 +274,5 @@ void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCall
|
||||||
v4.color = col;
|
v4.color = col;
|
||||||
v4.callback = callback;
|
v4.callback = callback;
|
||||||
|
|
||||||
renderPushQuad(&v1, &v2, &v3, &v4);*/
|
renderPushQuad(&v1, &v2, &v3, &v4);
|
||||||
}
|
}*/
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#ifndef _PAYSAGES_CAMERA_H_
|
#ifndef _PAYSAGES_CAMERA_H_
|
||||||
#define _PAYSAGES_CAMERA_H_
|
#define _PAYSAGES_CAMERA_H_
|
||||||
|
|
||||||
#include "shared/types.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "shared/types.h"
|
||||||
|
#include "renderer.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -48,10 +49,10 @@ void cameraRotateYaw(CameraDefinition* camera, double value);
|
||||||
void cameraRotatePitch(CameraDefinition* camera, double value);
|
void cameraRotatePitch(CameraDefinition* camera, double value);
|
||||||
void cameraRotateRoll(CameraDefinition* camera, double value);
|
void cameraRotateRoll(CameraDefinition* camera, double value);
|
||||||
|
|
||||||
Vector3 cameraProject(CameraDefinition* camera, Vector3 point);
|
Vector3 cameraProject(CameraDefinition* camera, Renderer* renderer, Vector3 point);
|
||||||
Vector3 cameraUnproject(CameraDefinition* camera, Vector3 point);
|
Vector3 cameraUnproject(CameraDefinition* camera, Renderer* renderer, Vector3 point);
|
||||||
void cameraProjectToFragment(CameraDefinition* camera, double x, double y, double z, RenderFragment* result);
|
void cameraProjectToFragment(CameraDefinition* camera, Renderer* renderer, double x, double y, double z, RenderFragment* result);
|
||||||
void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);
|
/*void cameraPushOverlay(CameraDefinition* camera, Color col, f_RenderFragmentCallback callback);*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "euclid.h"
|
#include "euclid.h"
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
|
|
||||||
#include "auto.h"
|
#include "auto.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
|
@ -11,164 +11,145 @@
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
int render_width;
|
struct RenderArea
|
||||||
int render_height;
|
{
|
||||||
int render_quality;
|
int width;
|
||||||
static int _pixel_count;
|
int height;
|
||||||
static Array* render_zone = NULL;
|
int pixel_count;
|
||||||
static RenderFragment* scanline_up;
|
Array* pixels;
|
||||||
static RenderFragment* scanline_down;
|
RenderFragment* scanline_up;
|
||||||
static int scanline_left;
|
RenderFragment* scanline_down;
|
||||||
static int scanline_right;
|
int scanline_left;
|
||||||
static Color background_color;
|
int scanline_right;
|
||||||
static volatile int _dirty_left;
|
Color background_color;
|
||||||
static volatile int _dirty_right;
|
volatile int dirty_left;
|
||||||
static volatile int _dirty_up;
|
volatile int dirty_right;
|
||||||
static volatile int _dirty_down;
|
volatile int dirty_up;
|
||||||
static volatile int _dirty_count;
|
volatile int dirty_down;
|
||||||
static Mutex* _lock;
|
volatile int dirty_count;
|
||||||
|
Mutex* lock;
|
||||||
static volatile int _interrupt = 0;
|
RenderCallbackStart callback_start;
|
||||||
static volatile int _progress_pixels;
|
RenderCallbackDraw callback_draw;
|
||||||
static volatile double _progress = 0.0;
|
RenderCallbackUpdate callback_update;
|
||||||
static volatile double _progress_step_start = 0.0;
|
};
|
||||||
static volatile double _progress_step_length = 1.0;
|
|
||||||
|
|
||||||
/*#define RENDER_INVERSE 1*/
|
/*#define RENDER_INVERSE 1*/
|
||||||
#define RENDER_WIREFRAME 1
|
#define RENDER_WIREFRAME 1
|
||||||
|
|
||||||
static void _previewResize(int width, int height) {}
|
static void _callbackStart(int width, int height, Color background) {}
|
||||||
static void _previewClear(Color col) {}
|
static void _callbackDraw(int x, int y, Color col) {}
|
||||||
static void _previewDraw(int x, int y, Color col) {}
|
static void _callbackUpdate(double progress) {}
|
||||||
static void _previewUpdate(double progress) {}
|
|
||||||
|
|
||||||
static PreviewCallbackResize _cb_preview_resize = _previewResize;
|
|
||||||
static PreviewCallbackClear _cb_preview_clear = _previewClear;
|
|
||||||
static PreviewCallbackDraw _cb_preview_draw = _previewDraw;
|
|
||||||
static PreviewCallbackUpdate _cb_preview_update = _previewUpdate;
|
|
||||||
|
|
||||||
void renderSave(FILE* f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderLoad(FILE* f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderInit()
|
void renderInit()
|
||||||
{
|
{
|
||||||
_lock = mutexCreate();
|
|
||||||
renderSetBackgroundColor(&COLOR_BLACK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderSetSize(int width, int height)
|
RenderArea* renderCreateArea()
|
||||||
|
{
|
||||||
|
RenderArea* result;
|
||||||
|
|
||||||
|
result = malloc(sizeof(RenderArea));
|
||||||
|
result->width = 1;
|
||||||
|
result->height = 1;
|
||||||
|
result->pixel_count = 1;
|
||||||
|
result->pixels = malloc(sizeof(Array));
|
||||||
|
arrayCreate(result->pixels, sizeof(RenderFragment));
|
||||||
|
result->scanline_up = malloc(sizeof(RenderFragment));
|
||||||
|
result->scanline_down = malloc(sizeof(RenderFragment));
|
||||||
|
result->scanline_left = 0;
|
||||||
|
result->scanline_right = 0;
|
||||||
|
result->background_color = COLOR_TRANSPARENT;
|
||||||
|
result->dirty_left = 1;
|
||||||
|
result->dirty_right = -1;
|
||||||
|
result->dirty_down = 1;
|
||||||
|
result->dirty_up = -1;
|
||||||
|
result->dirty_count = 0;
|
||||||
|
result->lock = mutexCreate();
|
||||||
|
result->callback_start = _callbackStart;
|
||||||
|
result->callback_draw = _callbackDraw;
|
||||||
|
result->callback_update = _callbackUpdate;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderDeleteArea(RenderArea* area)
|
||||||
|
{
|
||||||
|
mutexDestroy(area->lock);
|
||||||
|
arrayDelete(area->pixels);
|
||||||
|
free(area->scanline_up);
|
||||||
|
free(area->scanline_down);
|
||||||
|
free(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderSetSize(RenderArea* area, int width, int height)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
if (render_zone != NULL)
|
for (x = 0; x < area->width; x++)
|
||||||
{
|
{
|
||||||
/* Delete previous render zone */
|
for (y = 0; y < area->height; y++)
|
||||||
for (x = 0; x < render_width; x++)
|
|
||||||
{
|
{
|
||||||
for (y = 0; y < render_height; y++)
|
arrayDelete(area->pixels + (y * area->width + x));
|
||||||
{
|
|
||||||
arrayDelete(render_zone + (y * render_width + x));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
free(render_zone);
|
|
||||||
free(scanline_up);
|
|
||||||
free(scanline_down);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render_width = width;
|
area->width = width;
|
||||||
render_height = height;
|
area->height = height;
|
||||||
render_zone = malloc(sizeof(Array) * width * height);
|
area->pixels = realloc(area->pixels, sizeof(Array) * width * height);
|
||||||
|
area->pixel_count = width * height;
|
||||||
|
|
||||||
scanline_left = 0;
|
area->scanline_left = 0;
|
||||||
scanline_right = render_width - 1;
|
area->scanline_right = width - 1;
|
||||||
scanline_up = malloc(sizeof(RenderFragment) * width);
|
area->scanline_up = realloc(area->scanline_up, sizeof(RenderFragment) * width);
|
||||||
scanline_down = malloc(sizeof(RenderFragment) * width);
|
area->scanline_down = realloc(area->scanline_down, sizeof(RenderFragment) * width);
|
||||||
|
|
||||||
_dirty_left = render_width;
|
area->dirty_left = width;
|
||||||
_dirty_right = -1;
|
area->dirty_right = -1;
|
||||||
_dirty_down = render_height;
|
area->dirty_down = height;
|
||||||
_dirty_up = -1;
|
area->dirty_up = -1;
|
||||||
_dirty_count = 0;
|
area->dirty_count = 0;
|
||||||
|
|
||||||
_pixel_count = render_width * render_height;
|
|
||||||
|
|
||||||
for (y = 0; y < height; y++)
|
for (y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < width; x++)
|
for (x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
arrayCreate(render_zone + (y * width + x), sizeof(RenderFragment));
|
arrayCreate(area->pixels + (y * width + x), sizeof(RenderFragment));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cb_preview_resize(render_width, render_height);
|
|
||||||
_cb_preview_clear(background_color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int renderSetQuality(int quality)
|
void renderSetBackgroundColor(RenderArea* area, Color* col)
|
||||||
{
|
{
|
||||||
if (quality < 1)
|
area->background_color = *col;
|
||||||
{
|
|
||||||
render_quality = 1;
|
|
||||||
}
|
|
||||||
else if (quality > 10)
|
|
||||||
{
|
|
||||||
render_quality = 10;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
render_quality = quality;
|
|
||||||
}
|
|
||||||
return render_quality;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderClear()
|
void renderClear(RenderArea* area)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
for (x = 0; x < render_width; x++)
|
for (x = 0; x < area->width; x++)
|
||||||
{
|
{
|
||||||
for (y = 0; y < render_height; y++)
|
for (y = 0; y < area->height; y++)
|
||||||
{
|
{
|
||||||
arrayClear(render_zone + (y * render_width + x));
|
arrayClear(area->pixels + (y * area->width + x));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scanline_left = 0;
|
area->scanline_left = 0;
|
||||||
scanline_right = render_width - 1;
|
area->scanline_right = area->width - 1;
|
||||||
|
|
||||||
_progress = 0.0;
|
area->callback_start(area->width, area->height, area->background_color);
|
||||||
_progress_step_start = 0.0;
|
|
||||||
_progress_step_length = 0.0;
|
|
||||||
_interrupt = 0;
|
|
||||||
|
|
||||||
_cb_preview_clear(background_color);
|
area->dirty_left = area->width;
|
||||||
_cb_preview_update(_progress * _progress_step_length + _progress_step_start);
|
area->dirty_right = -1;
|
||||||
|
area->dirty_down = area->height;
|
||||||
_dirty_left = render_width;
|
area->dirty_up = -1;
|
||||||
_dirty_right = -1;
|
area->dirty_count = 0;
|
||||||
_dirty_down = render_height;
|
|
||||||
_dirty_up = -1;
|
|
||||||
_dirty_count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderInterrupt()
|
/*static int _sortRenderFragment(void const* a, void const* b)
|
||||||
{
|
|
||||||
_interrupt = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderSetBackgroundColor(Color* col)
|
|
||||||
{
|
|
||||||
background_color = *col;
|
|
||||||
}
|
|
||||||
|
|
||||||
int _sortRenderFragment(void const* a, void const* b)
|
|
||||||
{
|
{
|
||||||
double za, zb;
|
double za, zb;
|
||||||
za = ((RenderFragment*)a)->z;
|
za = ((RenderFragment*)a)->z;
|
||||||
|
@ -185,12 +166,11 @@ int _sortRenderFragment(void const* a, void const* b)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
static Color _getPixelColor(Array* pixel_data)
|
static Color _getPixelColor(Color base, Array* pixel_data)
|
||||||
{
|
{
|
||||||
RenderFragment* fragment;
|
RenderFragment* fragment;
|
||||||
Color result = background_color;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (pixel_data->length > 0)
|
if (pixel_data->length > 0)
|
||||||
|
@ -198,84 +178,91 @@ static Color _getPixelColor(Array* pixel_data)
|
||||||
for (i = 0; i < pixel_data->length; i++)
|
for (i = 0; i < pixel_data->length; i++)
|
||||||
{
|
{
|
||||||
fragment = ((RenderFragment*)pixel_data->data) + i;
|
fragment = ((RenderFragment*)pixel_data->data) + i;
|
||||||
colorMask(&result, &(fragment->vertex.color));
|
colorMask(&base, &(fragment->vertex.color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _setDirtyPixel(Array* pixel_data, int x, int y)
|
static inline void _setDirtyPixel(RenderArea* area, Array* pixel_data, int x, int y)
|
||||||
{
|
{
|
||||||
pixel_data->dirty = 1;
|
pixel_data->dirty = 1;
|
||||||
if (x < _dirty_left)
|
if (x < area->dirty_left)
|
||||||
{
|
{
|
||||||
_dirty_left = x;
|
area->dirty_left = x;
|
||||||
}
|
}
|
||||||
if (x > _dirty_right)
|
if (x > area->dirty_right)
|
||||||
{
|
{
|
||||||
_dirty_right = x;
|
area->dirty_right = x;
|
||||||
}
|
}
|
||||||
if (y < _dirty_down)
|
if (y < area->dirty_down)
|
||||||
{
|
{
|
||||||
_dirty_down = y;
|
area->dirty_down = y;
|
||||||
}
|
}
|
||||||
if (y > _dirty_up)
|
if (y > area->dirty_up)
|
||||||
{
|
{
|
||||||
_dirty_up = y;
|
area->dirty_up = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirty_count++;
|
area->dirty_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _processDirtyPixels()
|
static void _processDirtyPixels(RenderArea* area)
|
||||||
{
|
{
|
||||||
Color col;
|
Color col;
|
||||||
Array* pixel_data;
|
Array* pixel_data;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
for (y = _dirty_down; y <= _dirty_up; y++)
|
for (y = area->dirty_down; y <= area->dirty_up; y++)
|
||||||
{
|
{
|
||||||
for (x = _dirty_left; x <= _dirty_right; x++)
|
for (x = area->dirty_left; x <= area->dirty_right; x++)
|
||||||
{
|
{
|
||||||
pixel_data = render_zone + y * render_width + x;
|
pixel_data = area->pixels + y * area->width + x;
|
||||||
if (pixel_data->dirty)
|
if (pixel_data->dirty)
|
||||||
{
|
{
|
||||||
col = _getPixelColor(pixel_data);
|
col = _getPixelColor(area->background_color, pixel_data);
|
||||||
_cb_preview_draw(x, y, col);
|
area->callback_draw(x, y, col);
|
||||||
pixel_data->dirty = 0;
|
pixel_data->dirty = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_cb_preview_update(_progress * _progress_step_length + _progress_step_start);
|
area->callback_update(0.0);
|
||||||
|
|
||||||
_dirty_left = render_width;
|
area->dirty_left = area->width;
|
||||||
_dirty_right = -1;
|
area->dirty_right = -1;
|
||||||
_dirty_down = render_height;
|
area->dirty_down = area->height;
|
||||||
_dirty_up = -1;
|
area->dirty_up = -1;
|
||||||
_dirty_count = 0;
|
area->dirty_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setAllDirty()
|
void renderUpdate(RenderArea* area)
|
||||||
|
{
|
||||||
|
mutexAcquire(area->lock);
|
||||||
|
_processDirtyPixels(area);
|
||||||
|
mutexRelease(area->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _setAllDirty(RenderArea* area)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
_dirty_left = 0;
|
area->dirty_left = 0;
|
||||||
_dirty_right = render_width - 1;
|
area->dirty_right = area->width - 1;
|
||||||
_dirty_down = 0;
|
area->dirty_down = 0;
|
||||||
_dirty_up = render_height - 1;
|
area->dirty_up = area->height - 1;
|
||||||
|
|
||||||
for (y = _dirty_down; y <= _dirty_up; y++)
|
for (y = area->dirty_down; y <= area->dirty_up; y++)
|
||||||
{
|
{
|
||||||
for (x = _dirty_left; x <= _dirty_right; x++)
|
for (x = area->dirty_left; x <= area->dirty_right; x++)
|
||||||
{
|
{
|
||||||
(render_zone + y * render_width + x)->dirty = 1;
|
(area->pixels + y * area->width + x)->dirty = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderAddFragment(RenderFragment* fragment)
|
void renderAddFragment(RenderArea* area, RenderFragment* fragment)
|
||||||
{
|
{
|
||||||
Array* pixel_data;
|
Array* pixel_data;
|
||||||
int x = fragment->x;
|
int x = fragment->x;
|
||||||
|
@ -287,9 +274,9 @@ void renderAddFragment(RenderFragment* fragment)
|
||||||
RenderFragment* fragments;
|
RenderFragment* fragments;
|
||||||
|
|
||||||
dirty = 0;
|
dirty = 0;
|
||||||
if (x >= 0 && x < render_width && y >= 0 && y < render_height && z > 1.0)
|
if (x >= 0 && x < area->width && y >= 0 && y < area->height && z > 1.0)
|
||||||
{
|
{
|
||||||
pixel_data = render_zone + (y * render_width + x);
|
pixel_data = area->pixels + (y * area->width + x);
|
||||||
fragments = (RenderFragment*)pixel_data->data;
|
fragments = (RenderFragment*)pixel_data->data;
|
||||||
fragments_count = pixel_data->length;
|
fragments_count = pixel_data->length;
|
||||||
|
|
||||||
|
@ -336,12 +323,12 @@ void renderAddFragment(RenderFragment* fragment)
|
||||||
|
|
||||||
if (dirty)
|
if (dirty)
|
||||||
{
|
{
|
||||||
_setDirtyPixel(pixel_data, x, y);
|
_setDirtyPixel(area, pixel_data, x, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderPushFragment(int x, int y, double z, Vertex* vertex)
|
void renderPushFragment(RenderArea* area, int x, int y, double z, Vertex* vertex)
|
||||||
{
|
{
|
||||||
RenderFragment fragment;
|
RenderFragment fragment;
|
||||||
|
|
||||||
|
@ -350,7 +337,7 @@ void renderPushFragment(int x, int y, double z, Vertex* vertex)
|
||||||
fragment.z = z;
|
fragment.z = z;
|
||||||
fragment.vertex = *vertex;
|
fragment.vertex = *vertex;
|
||||||
|
|
||||||
renderAddFragment(&fragment);
|
renderAddFragment(area, &fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __vertexGetDiff(Vertex* v1, Vertex* v2, Vertex* result)
|
static void __vertexGetDiff(Vertex* v1, Vertex* v2, Vertex* result)
|
||||||
|
@ -385,43 +372,43 @@ static void __vertexInterpolate(Vertex* v1, Vertex* diff, double value, Vertex*
|
||||||
result->callback_data = v1->callback_data;
|
result->callback_data = v1->callback_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __pushScanLinePoint(RenderFragment point)
|
static void __pushScanLinePoint(RenderArea* area, RenderFragment point)
|
||||||
{
|
{
|
||||||
if (point.x < 0 || point.x >= render_width)
|
if (point.x < 0 || point.x >= area->width)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (point.x > scanline_right)
|
if (point.x > area->scanline_right)
|
||||||
{
|
{
|
||||||
scanline_right = point.x;
|
area->scanline_right = point.x;
|
||||||
scanline_up[scanline_right] = point;
|
area->scanline_up[area->scanline_right] = point;
|
||||||
scanline_down[scanline_right] = point;
|
area->scanline_down[area->scanline_right] = point;
|
||||||
if (point.x < scanline_left)
|
if (point.x < area->scanline_left)
|
||||||
{
|
{
|
||||||
scanline_left = point.x;
|
area->scanline_left = point.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (point.x < scanline_left)
|
else if (point.x < area->scanline_left)
|
||||||
{
|
{
|
||||||
scanline_left = point.x;
|
area->scanline_left = point.x;
|
||||||
scanline_up[scanline_left] = point;
|
area->scanline_up[area->scanline_left] = point;
|
||||||
scanline_down[scanline_left] = point;
|
area->scanline_down[area->scanline_left] = point;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (point.y > scanline_up[point.x].y)
|
if (point.y > area->scanline_up[point.x].y)
|
||||||
{
|
{
|
||||||
scanline_up[point.x] = point;
|
area->scanline_up[point.x] = point;
|
||||||
}
|
}
|
||||||
if (point.y < scanline_down[point.x].y)
|
if (point.y < area->scanline_down[point.x].y)
|
||||||
{
|
{
|
||||||
scanline_down[point.x] = point;
|
area->scanline_down[point.x] = point;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* vertex2)
|
static void __pushScanLineEdge(RenderArea* area, Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex* vertex2)
|
||||||
{
|
{
|
||||||
double dx, dy, dz, fx;
|
double dx, dy, dz, fx;
|
||||||
Vertex diff;
|
Vertex diff;
|
||||||
|
@ -432,9 +419,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
|
||||||
|
|
||||||
if (endx < startx)
|
if (endx < startx)
|
||||||
{
|
{
|
||||||
__pushScanLineEdge(v2, v1, vertex2, vertex1);
|
__pushScanLineEdge(area, v2, v1, vertex2, vertex1);
|
||||||
}
|
}
|
||||||
else if (endx < 0 || startx >= render_width)
|
else if (endx < 0 || startx >= area->width)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -445,14 +432,14 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
|
||||||
fragment.z = v1.z;
|
fragment.z = v1.z;
|
||||||
fragment.vertex = *vertex1;
|
fragment.vertex = *vertex1;
|
||||||
|
|
||||||
__pushScanLinePoint(fragment);
|
__pushScanLinePoint(area, fragment);
|
||||||
|
|
||||||
fragment.x = endx;
|
fragment.x = endx;
|
||||||
fragment.y = lround(v2.y);
|
fragment.y = lround(v2.y);
|
||||||
fragment.z = v2.z;
|
fragment.z = v2.z;
|
||||||
fragment.vertex = *vertex2;
|
fragment.vertex = *vertex2;
|
||||||
|
|
||||||
__pushScanLinePoint(fragment);
|
__pushScanLinePoint(area, fragment);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -460,9 +447,9 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
|
||||||
{
|
{
|
||||||
startx = 0;
|
startx = 0;
|
||||||
}
|
}
|
||||||
if (endx >= render_width)
|
if (endx >= area->width)
|
||||||
{
|
{
|
||||||
endx = render_width - 1;
|
endx = area->width - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dx = v2.x - v1.x;
|
dx = v2.x - v1.x;
|
||||||
|
@ -486,41 +473,41 @@ static void __pushScanLineEdge(Vector3 v1, Vector3 v2, Vertex* vertex1, Vertex*
|
||||||
fragment.z = v1.z + dz * fx / dx;
|
fragment.z = v1.z + dz * fx / dx;
|
||||||
__vertexInterpolate(vertex1, &diff, fx / dx, &(fragment.vertex));
|
__vertexInterpolate(vertex1, &diff, fx / dx, &(fragment.vertex));
|
||||||
|
|
||||||
__pushScanLinePoint(fragment);
|
__pushScanLinePoint(area, fragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __clearScanLines()
|
static void __clearScanLines(RenderArea* area)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
for (x = scanline_left; x <= scanline_right; x++)
|
for (x = area->scanline_left; x <= area->scanline_right; x++)
|
||||||
{
|
{
|
||||||
scanline_up[x].y = -1;
|
area->scanline_up[x].y = -1;
|
||||||
scanline_down[x].y = render_height;
|
area->scanline_down[x].y = area->height;
|
||||||
}
|
}
|
||||||
scanline_left = render_width;
|
area->scanline_left = area->width;
|
||||||
scanline_right = -1;
|
area->scanline_right = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __renderScanLines()
|
static void __renderScanLines(RenderArea* area)
|
||||||
{
|
{
|
||||||
int x, starty, endy, cury;
|
int x, starty, endy, cury;
|
||||||
Vertex diff;
|
Vertex diff;
|
||||||
double dy, dz, fy;
|
double dy, dz, fy;
|
||||||
RenderFragment up, down, current;
|
RenderFragment up, down, current;
|
||||||
|
|
||||||
if (scanline_right > 0)
|
if (area->scanline_right > 0)
|
||||||
{
|
{
|
||||||
for (x = scanline_left; x <= scanline_right; x++)
|
for (x = area->scanline_left; x <= area->scanline_right; x++)
|
||||||
{
|
{
|
||||||
up = scanline_up[x];
|
up = area->scanline_up[x];
|
||||||
down = scanline_down[x];
|
down = area->scanline_down[x];
|
||||||
|
|
||||||
starty = down.y;
|
starty = down.y;
|
||||||
endy = up.y;
|
endy = up.y;
|
||||||
|
|
||||||
if (endy < 0 || starty >= render_height)
|
if (endy < 0 || starty >= area->height)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -529,9 +516,9 @@ static void __renderScanLines()
|
||||||
{
|
{
|
||||||
starty = 0;
|
starty = 0;
|
||||||
}
|
}
|
||||||
if (endy >= render_height)
|
if (endy >= area->height)
|
||||||
{
|
{
|
||||||
endy = render_height - 1;
|
endy = area->height - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dy = (double)(up.y - down.y);
|
dy = (double)(up.y - down.y);
|
||||||
|
@ -554,21 +541,16 @@ static void __renderScanLines()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
renderAddFragment(¤t);
|
renderAddFragment(area, ¤t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3)
|
void renderPushTriangle(RenderArea* area, Vertex* v1, Vertex* v2, Vertex* v3, Vector3 p1, Vector3 p2, Vector3 p3)
|
||||||
{
|
{
|
||||||
Vector3 p1, p2, p3;
|
double limit_width = (double)(area->width - 1);
|
||||||
double limit_width = (double)(render_width - 1);
|
double limit_height = (double)(area->height - 1);
|
||||||
double limit_height = (double)(render_height - 1);
|
|
||||||
|
|
||||||
p1 = renderer->projectPoint(renderer, v1->location);
|
|
||||||
p2 = renderer->projectPoint(renderer, v2->location);
|
|
||||||
p3 = renderer->projectPoint(renderer, v3->location);
|
|
||||||
|
|
||||||
/* Filter if outside screen */
|
/* Filter if outside screen */
|
||||||
if (p1.z < 1.0 || p2.z < 1.0 || p3.z < 1.0 || (p1.x < 0.0 && p2.x < 0.0 && p3.x < 0.0) || (p1.y < 0.0 && p2.y < 0.0 && p3.y < 0.0) || (p1.x > limit_width && p2.x > limit_width && p3.x > limit_width) || (p1.y > limit_height && p2.y > limit_height && p3.y > limit_height))
|
if (p1.z < 1.0 || p2.z < 1.0 || p3.z < 1.0 || (p1.x < 0.0 && p2.x < 0.0 && p3.x < 0.0) || (p1.y < 0.0 && p2.y < 0.0 && p3.y < 0.0) || (p1.x > limit_width && p2.x > limit_width && p3.x > limit_width) || (p1.y > limit_height && p2.y > limit_height && p3.y > limit_height))
|
||||||
|
@ -576,19 +558,13 @@ void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__clearScanLines();
|
__clearScanLines(area);
|
||||||
__pushScanLineEdge(p1, p2, v1, v2);
|
__pushScanLineEdge(area, p1, p2, v1, v2);
|
||||||
__pushScanLineEdge(p2, p3, v2, v3);
|
__pushScanLineEdge(area, p2, p3, v2, v3);
|
||||||
__pushScanLineEdge(p3, p1, v3, v1);
|
__pushScanLineEdge(area, p3, p1, v3, v1);
|
||||||
mutexAcquire(_lock);
|
mutexAcquire(area->lock);
|
||||||
__renderScanLines();
|
__renderScanLines(area);
|
||||||
mutexRelease(_lock);
|
mutexRelease(area->lock);
|
||||||
}
|
|
||||||
|
|
||||||
void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
|
|
||||||
{
|
|
||||||
renderPushTriangle(renderer, v2, v3, v1);
|
|
||||||
renderPushTriangle(renderer, v4, v1, v3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -599,6 +575,7 @@ typedef struct {
|
||||||
int finished;
|
int finished;
|
||||||
int interrupt;
|
int interrupt;
|
||||||
Thread* thread;
|
Thread* thread;
|
||||||
|
RenderArea* area;
|
||||||
Renderer* renderer;
|
Renderer* renderer;
|
||||||
} RenderChunk;
|
} RenderChunk;
|
||||||
|
|
||||||
|
@ -618,7 +595,7 @@ void* _renderPostProcessChunk(void* data)
|
||||||
{
|
{
|
||||||
for (x = chunk->startx; x <= chunk->endx; x++)
|
for (x = chunk->startx; x <= chunk->endx; x++)
|
||||||
{
|
{
|
||||||
pixel_data = render_zone + (y * render_width + x);
|
pixel_data = chunk->area->pixels + (y * chunk->area->width + x);
|
||||||
fragments = (RenderFragment*)pixel_data->data;
|
fragments = (RenderFragment*)pixel_data->data;
|
||||||
dirty = 0;
|
dirty = 0;
|
||||||
for (i = 0; i < pixel_data->length; i++)
|
for (i = 0; i < pixel_data->length; i++)
|
||||||
|
@ -627,7 +604,6 @@ void* _renderPostProcessChunk(void* data)
|
||||||
{
|
{
|
||||||
if (fragments[i].vertex.callback(fragments + i, chunk->renderer, fragments[i].vertex.callback_data))
|
if (fragments[i].vertex.callback(fragments + i, chunk->renderer, fragments[i].vertex.callback_data))
|
||||||
{
|
{
|
||||||
/* TODO Store over-exposure */
|
|
||||||
colorNormalize(&fragments[i].vertex.color);
|
colorNormalize(&fragments[i].vertex.color);
|
||||||
dirty = 1;
|
dirty = 1;
|
||||||
}
|
}
|
||||||
|
@ -635,11 +611,11 @@ void* _renderPostProcessChunk(void* data)
|
||||||
}
|
}
|
||||||
if (dirty)
|
if (dirty)
|
||||||
{
|
{
|
||||||
mutexAcquire(_lock);
|
mutexAcquire(chunk->area->lock);
|
||||||
_setDirtyPixel(pixel_data, x, y);
|
_setDirtyPixel(chunk->area, pixel_data, x, y);
|
||||||
mutexRelease(_lock);
|
mutexRelease(chunk->area->lock);
|
||||||
}
|
}
|
||||||
_progress_pixels++;
|
/* chunk->area->progress_pixels++; */
|
||||||
}
|
}
|
||||||
if (chunk->interrupt)
|
if (chunk->interrupt)
|
||||||
{
|
{
|
||||||
|
@ -652,12 +628,13 @@ void* _renderPostProcessChunk(void* data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_CHUNKS 8
|
#define MAX_CHUNKS 8
|
||||||
void renderPostProcess(Renderer* renderer, int nbchunks)
|
void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks)
|
||||||
{
|
{
|
||||||
volatile RenderChunk chunks[MAX_CHUNKS];
|
volatile RenderChunk chunks[MAX_CHUNKS];
|
||||||
int i;
|
int i;
|
||||||
int x, y, dx, dy, nx, ny;
|
int x, y, dx, dy, nx, ny;
|
||||||
int loops, running;
|
int loops, running;
|
||||||
|
int _interrupt = 0; /* TEMP */
|
||||||
|
|
||||||
if (nbchunks > MAX_CHUNKS)
|
if (nbchunks > MAX_CHUNKS)
|
||||||
{
|
{
|
||||||
|
@ -670,15 +647,16 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
|
||||||
|
|
||||||
nx = 10;
|
nx = 10;
|
||||||
ny = 10;
|
ny = 10;
|
||||||
dx = render_width / nx;
|
dx = area->width / nx;
|
||||||
dy = render_height / ny;
|
dy = area->height / ny;
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
_progress_pixels = 0;
|
/*_progress_pixels = 0;*/
|
||||||
|
|
||||||
for (i = 0; i < nbchunks; i++)
|
for (i = 0; i < nbchunks; i++)
|
||||||
{
|
{
|
||||||
chunks[i].thread = NULL;
|
chunks[i].thread = NULL;
|
||||||
|
chunks[i].area = area;
|
||||||
chunks[i].renderer = renderer;
|
chunks[i].renderer = renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,7 +689,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
|
||||||
chunks[i].startx = x * dx;
|
chunks[i].startx = x * dx;
|
||||||
if (x == nx)
|
if (x == nx)
|
||||||
{
|
{
|
||||||
chunks[i].endx = render_width - 1;
|
chunks[i].endx = area->width - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -720,7 +698,7 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
|
||||||
chunks[i].starty = y * dy;
|
chunks[i].starty = y * dy;
|
||||||
if (y == ny)
|
if (y == ny)
|
||||||
{
|
{
|
||||||
chunks[i].endy = render_height - 1;
|
chunks[i].endy = area->height - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -740,27 +718,20 @@ void renderPostProcess(Renderer* renderer, int nbchunks)
|
||||||
|
|
||||||
if (++loops >= 10)
|
if (++loops >= 10)
|
||||||
{
|
{
|
||||||
mutexAcquire(_lock);
|
mutexAcquire(area->lock);
|
||||||
_progress = (double)_progress_pixels / (double)_pixel_count;
|
/*_progress = (double)_progress_pixels / (double)_pixel_count;*/
|
||||||
_processDirtyPixels();
|
_processDirtyPixels(area);
|
||||||
mutexRelease(_lock);
|
mutexRelease(area->lock);
|
||||||
|
|
||||||
loops = 0;
|
loops = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_progress = 1.0;
|
/*_progress = 1.0;*/
|
||||||
_processDirtyPixels();
|
_processDirtyPixels(area);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderUpdate()
|
void renderSaveToFile(RenderArea* area, const char* path)
|
||||||
{
|
|
||||||
mutexAcquire(_lock);
|
|
||||||
_processDirtyPixels();
|
|
||||||
mutexRelease(_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderSaveToFile(const char* path)
|
|
||||||
{
|
{
|
||||||
ILuint image_id;
|
ILuint image_id;
|
||||||
ilGenImages(1, &image_id);
|
ilGenImages(1, &image_id);
|
||||||
|
@ -768,22 +739,22 @@ void renderSaveToFile(const char* path)
|
||||||
Color result;
|
Color result;
|
||||||
ILuint x, y;
|
ILuint x, y;
|
||||||
ILuint rgba;
|
ILuint rgba;
|
||||||
ILuint data[render_height * render_width];
|
ILuint data[area->height * area->width];
|
||||||
ILenum error;
|
ILenum error;
|
||||||
Array* pixel_data;
|
Array* pixel_data;
|
||||||
|
|
||||||
for (y = 0; y < render_height; y++)
|
for (y = 0; y < area->height; y++)
|
||||||
{
|
{
|
||||||
for (x = 0; x < render_width; x++)
|
for (x = 0; x < area->width; x++)
|
||||||
{
|
{
|
||||||
pixel_data = render_zone + (y * render_width + x);
|
pixel_data = area->pixels + (y * area->width + x);
|
||||||
result = _getPixelColor(pixel_data);
|
result = _getPixelColor(area->background_color, pixel_data);
|
||||||
rgba = colorTo32BitRGBA(&result);
|
rgba = colorTo32BitRGBA(&result);
|
||||||
data[y * render_width + x] = rgba;
|
data[y * area->width + x] = rgba;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ilTexImage((ILuint)render_width, (ILuint)render_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, data);
|
ilTexImage((ILuint)area->width, (ILuint)area->height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, data);
|
||||||
ilSaveImage(path);
|
ilSaveImage(path);
|
||||||
|
|
||||||
ilDeleteImages(1, &image_id);
|
ilDeleteImages(1, &image_id);
|
||||||
|
@ -794,46 +765,16 @@ void renderSaveToFile(const char* path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClear clear, PreviewCallbackDraw draw, PreviewCallbackUpdate update)
|
void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update)
|
||||||
{
|
{
|
||||||
_cb_preview_resize = resize ? resize : _previewResize;
|
area->callback_start = start ? start : _callbackStart;
|
||||||
_cb_preview_clear = clear ? clear : _previewClear;
|
area->callback_draw = draw ? draw : _callbackDraw;
|
||||||
_cb_preview_draw = draw ? draw : _previewDraw;
|
area->callback_update = update ? update : _callbackUpdate;
|
||||||
_cb_preview_update = update ? update : _previewUpdate;
|
|
||||||
|
|
||||||
_cb_preview_resize(render_width, render_height);
|
area->callback_start(area->width, area->height, area->background_color);
|
||||||
_cb_preview_clear(background_color);
|
|
||||||
|
|
||||||
_setAllDirty();
|
_setAllDirty(area);
|
||||||
_processDirtyPixels();
|
_processDirtyPixels(area);
|
||||||
|
|
||||||
_cb_preview_update(1.0);
|
area->callback_update(0.0);
|
||||||
}
|
|
||||||
|
|
||||||
int renderSetNextProgressStep(double start, double end)
|
|
||||||
{
|
|
||||||
if (_interrupt)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_progress = 0.0;
|
|
||||||
_progress_step_start = start;
|
|
||||||
_progress_step_length = end - start;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int renderTellProgress(double progress)
|
|
||||||
{
|
|
||||||
if (_interrupt)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_progress = progress;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,23 +10,21 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void renderInit();
|
void renderInit();
|
||||||
void renderSave(FILE* f);
|
RenderArea* renderCreateArea();
|
||||||
void renderLoad(FILE* f);
|
void renderDeleteArea(RenderArea* area);
|
||||||
void renderSetSize(int width, int height);
|
|
||||||
int renderSetQuality(int quality);
|
void renderSetSize(RenderArea* area, int width, int height);
|
||||||
void renderClear();
|
void renderSetBackgroundColor(RenderArea* area, Color* col);
|
||||||
void renderUpdate();
|
void renderClear(RenderArea* area);
|
||||||
void renderInterrupt();
|
void renderUpdate(RenderArea* area);
|
||||||
void renderSetBackgroundColor(Color* col);
|
|
||||||
void renderAddFragment(RenderFragment* fragment);
|
void renderAddFragment(RenderArea* area, RenderFragment* fragment);
|
||||||
void renderPushFragment(int x, int y, double z, Vertex* vertex);
|
void renderPushFragment(RenderArea* area, int x, int y, double z, Vertex* vertex);
|
||||||
void renderPushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3);
|
void renderPushTriangle(RenderArea* area, Vertex* v1, Vertex* v2, Vertex* v3, Vector3 p1, Vector3 p2, Vector3 p3);
|
||||||
void renderPushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4);
|
|
||||||
void renderPostProcess(Renderer* renderer, int nbchunks);
|
void renderPostProcess(RenderArea* area, Renderer* renderer, int nbchunks);
|
||||||
void renderSaveToFile(const char* path);
|
void renderSaveToFile(RenderArea* area, const char* path);
|
||||||
void renderSetPreviewCallbacks(PreviewCallbackResize resize, PreviewCallbackClear clear, PreviewCallbackDraw draw, PreviewCallbackUpdate update);
|
void renderSetPreviewCallbacks(RenderArea* area, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update);
|
||||||
int renderSetNextProgressStep(double start, double end);
|
|
||||||
int renderTellProgress(double progress);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -1,10 +1,59 @@
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "scenery.h"
|
||||||
|
|
||||||
RayCastingResult _RAYCASTING_NULL = {0};
|
RayCastingResult _RAYCASTING_NULL = {0};
|
||||||
HeightInfo _WATER_HEIGHT_INFO = {-1000000.0, -1000000.0, -1000000.0};
|
HeightInfo _WATER_HEIGHT_INFO = {-1000000.0, -1000000.0, -1000000.0};
|
||||||
|
|
||||||
|
static void* _renderFirstPass(void* data)
|
||||||
|
{
|
||||||
|
Renderer* renderer = (Renderer*)data;
|
||||||
|
|
||||||
|
sceneryRenderFirstPass(renderer);
|
||||||
|
renderer->is_rendering = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _addRenderProgress(Renderer* renderer, double progress)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double _getPrecision(Renderer* renderer, Vector3 location)
|
||||||
|
{
|
||||||
|
return 0.001;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
||||||
|
{
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
|
||||||
|
{
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _pushTriangle(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3)
|
||||||
|
{
|
||||||
|
Vector3 p1, p2, p3;
|
||||||
|
|
||||||
|
p1 = renderer->projectPoint(renderer, v1->location);
|
||||||
|
p2 = renderer->projectPoint(renderer, v2->location);
|
||||||
|
p3 = renderer->projectPoint(renderer, v3->location);
|
||||||
|
|
||||||
|
renderPushTriangle(renderer->render_area, v1, v2, v3, p1, p2, p3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _pushQuad(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4)
|
||||||
|
{
|
||||||
|
renderer->pushTriangle(renderer, v2, v3, v1);
|
||||||
|
renderer->pushTriangle(renderer, v4, v1, v3);
|
||||||
|
}
|
||||||
|
|
||||||
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
static Color _filterLight(Renderer* renderer, Color light_color, Vector3 at_location, Vector3 light_location, Vector3 direction_to_light)
|
||||||
{
|
{
|
||||||
return light_color;
|
return light_color;
|
||||||
|
@ -50,40 +99,88 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
Renderer rendererCreate()
|
||||||
{
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
|
|
||||||
{
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _getPrecision(Renderer* renderer, Vector3 location)
|
|
||||||
{
|
|
||||||
return 0.001;
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer rendererGetFake()
|
|
||||||
{
|
{
|
||||||
Renderer result;
|
Renderer result;
|
||||||
|
|
||||||
result.render_quality = 5;
|
result.render_quality = 5;
|
||||||
|
result.render_width = 1;
|
||||||
|
result.render_height = 1;
|
||||||
|
result.render_interrupt = 0;
|
||||||
|
result.render_progress = 0.0;
|
||||||
|
result.is_rendering = 0;
|
||||||
result.camera_location = VECTOR_ZERO;
|
result.camera_location = VECTOR_ZERO;
|
||||||
|
result.render_area = renderCreateArea();
|
||||||
|
renderSetSize(result.render_area, 1, 1);
|
||||||
|
|
||||||
|
result.addRenderProgress = _addRenderProgress;
|
||||||
|
result.getPrecision = _getPrecision;
|
||||||
|
result.projectPoint = _projectPoint;
|
||||||
|
result.unprojectPoint = _unprojectPoint;
|
||||||
|
result.pushTriangle = _pushTriangle;
|
||||||
|
result.pushQuad = _pushQuad;
|
||||||
|
|
||||||
result.filterLight = _filterLight;
|
|
||||||
result.maskLight = _maskLight;
|
|
||||||
result.applyLightingToSurface = _applyLightingToSurface;
|
|
||||||
result.rayWalking = _rayWalking;
|
result.rayWalking = _rayWalking;
|
||||||
result.getTerrainHeight = _getTerrainHeight;
|
result.getTerrainHeight = _getTerrainHeight;
|
||||||
result.getWaterHeightInfo = _getWaterHeightInfo;
|
result.getWaterHeightInfo = _getWaterHeightInfo;
|
||||||
result.applyTextures = _applyTextures;
|
result.applyTextures = _applyTextures;
|
||||||
result.applyAtmosphere = _applyAtmosphere;
|
result.applyAtmosphere = _applyAtmosphere;
|
||||||
result.applyClouds = _applyClouds;
|
result.applyClouds = _applyClouds;
|
||||||
result.projectPoint = _projectPoint;
|
|
||||||
result.unprojectPoint = _unprojectPoint;
|
result.filterLight = _filterLight;
|
||||||
result.getPrecision = _getPrecision;
|
result.maskLight = _maskLight;
|
||||||
|
result.applyLightingToSurface = _applyLightingToSurface;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rendererDelete(Renderer* renderer)
|
||||||
|
{
|
||||||
|
renderDeleteArea(renderer->render_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update)
|
||||||
|
{
|
||||||
|
renderSetPreviewCallbacks(renderer->render_area, start, draw, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rendererStart(Renderer* renderer, int width, int height, int quality)
|
||||||
|
{
|
||||||
|
Thread* thread;
|
||||||
|
int loops;
|
||||||
|
int core_count = systemGetCoreCount();
|
||||||
|
|
||||||
|
renderer->render_quality = quality;
|
||||||
|
renderer->render_width = width;
|
||||||
|
renderer->render_height = height;
|
||||||
|
renderer->render_interrupt = 0;
|
||||||
|
renderer->render_progress = 0.0;
|
||||||
|
|
||||||
|
renderSetBackgroundColor(renderer->render_area, &COLOR_BLACK);
|
||||||
|
renderSetSize(renderer->render_area, width, height);
|
||||||
|
renderClear(renderer->render_area);
|
||||||
|
|
||||||
|
renderer->is_rendering = 1;
|
||||||
|
thread = threadCreate(_renderFirstPass, renderer);
|
||||||
|
loops = 0;
|
||||||
|
|
||||||
|
while (renderer->is_rendering)
|
||||||
|
{
|
||||||
|
timeSleepMs(100);
|
||||||
|
|
||||||
|
if (++loops >= 10)
|
||||||
|
{
|
||||||
|
renderUpdate(renderer->render_area);
|
||||||
|
loops = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
threadJoin(thread);
|
||||||
|
|
||||||
|
renderer->is_rendering = 1;
|
||||||
|
renderPostProcess(renderer->render_area, renderer, core_count);
|
||||||
|
renderer->is_rendering = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rendererInterrupt(Renderer* renderer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -11,14 +11,23 @@ typedef struct Renderer Renderer;
|
||||||
|
|
||||||
struct Renderer
|
struct Renderer
|
||||||
{
|
{
|
||||||
/* Quality configuration */
|
/* Render base configuration */
|
||||||
int render_quality;
|
int render_quality;
|
||||||
|
int render_width;
|
||||||
|
int render_height;
|
||||||
Vector3 camera_location;
|
Vector3 camera_location;
|
||||||
|
|
||||||
/* Render related */
|
/* Render related */
|
||||||
|
RenderArea* render_area;
|
||||||
|
double render_progress;
|
||||||
|
int render_interrupt;
|
||||||
|
int is_rendering;
|
||||||
double (*getPrecision)(Renderer* renderer, Vector3 location);
|
double (*getPrecision)(Renderer* renderer, Vector3 location);
|
||||||
Vector3 (*projectPoint)(Renderer* renderer, Vector3 point);
|
Vector3 (*projectPoint)(Renderer* renderer, Vector3 point);
|
||||||
Vector3 (*unprojectPoint)(Renderer* renderer, Vector3 point);
|
Vector3 (*unprojectPoint)(Renderer* renderer, Vector3 point);
|
||||||
|
int (*addRenderProgress)(Renderer* renderer, double progress);
|
||||||
|
void (*pushTriangle)(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3);
|
||||||
|
void (*pushQuad)(Renderer* renderer, Vertex* v1, Vertex* v2, Vertex* v3, Vertex* v4);
|
||||||
|
|
||||||
/* Scenery related */
|
/* Scenery related */
|
||||||
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
RayCastingResult (*rayWalking)(Renderer* renderer, Vector3 location, Vector3 direction, int terrain, int water, int sky, int clouds);
|
||||||
|
@ -37,7 +46,11 @@ struct Renderer
|
||||||
void* customData[10];
|
void* customData[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
Renderer rendererGetFake();
|
Renderer rendererCreate();
|
||||||
|
void rendererDelete(Renderer* renderer);
|
||||||
|
void rendererSetPreviewCallbacks(Renderer* renderer, RenderCallbackStart start, RenderCallbackDraw draw, RenderCallbackUpdate update);
|
||||||
|
void rendererStart(Renderer* renderer, int width, int height, int quality);
|
||||||
|
void rendererInterrupt(Renderer* renderer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -177,29 +177,21 @@ void sceneryGetWater(WaterDefinition* water)
|
||||||
|
|
||||||
void sceneryRenderFirstPass(Renderer* renderer)
|
void sceneryRenderFirstPass(Renderer* renderer)
|
||||||
{
|
{
|
||||||
if (!renderSetNextProgressStep(0.0, 0.01))
|
/*if (!renderSetNextProgressStep(0.0, 0.01))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
skyRender(&_sky, renderer, renderTellProgress);
|
skyRender(&_sky, renderer);
|
||||||
if (!renderSetNextProgressStep(0.01, 0.085))
|
/*if (!renderSetNextProgressStep(0.01, 0.085))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
terrainRender(&_terrain, renderer, renderTellProgress);
|
terrainRender(&_terrain, renderer);
|
||||||
if (!renderSetNextProgressStep(0.085, 0.1))
|
/*if (!renderSetNextProgressStep(0.085, 0.1))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
waterRender(&_water, renderer, renderTellProgress);
|
waterRender(&_water, renderer);
|
||||||
}
|
|
||||||
|
|
||||||
void sceneryRenderSecondPass(Renderer* renderer)
|
|
||||||
{
|
|
||||||
if (renderSetNextProgressStep(0.1, 1.0))
|
|
||||||
{
|
|
||||||
renderPostProcess(renderer, systemGetCoreCount());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,34 +269,32 @@ static Color _applyClouds(Renderer* renderer, Color base, Vector3 start, Vector3
|
||||||
|
|
||||||
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
static Vector3 _projectPoint(Renderer* renderer, Vector3 point)
|
||||||
{
|
{
|
||||||
return cameraProject(&_camera, point);
|
return cameraProject(&_camera, renderer, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
|
static Vector3 _unprojectPoint(Renderer* renderer, Vector3 point)
|
||||||
{
|
{
|
||||||
return cameraUnproject(&_camera, point);
|
return cameraUnproject(&_camera, renderer, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
static double _getPrecision(Renderer* renderer, Vector3 location)
|
static double _getPrecision(Renderer* renderer, Vector3 location)
|
||||||
{
|
{
|
||||||
Vector3 projected;
|
Vector3 projected;
|
||||||
|
|
||||||
projected = cameraProject(&_camera, location);
|
projected = cameraProject(&_camera, renderer, location);
|
||||||
projected.x += 1.0;
|
projected.x += 1.0;
|
||||||
//projected.y += 1.0;
|
//projected.y += 1.0;
|
||||||
|
|
||||||
return v3Norm(v3Sub(cameraUnproject(&_camera, projected), location)); // / (double)render_quality;
|
return v3Norm(v3Sub(cameraUnproject(&_camera, renderer, projected), location)); // / (double)render_quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer sceneryGetStandardRenderer(int quality)
|
Renderer sceneryCreateStandardRenderer()
|
||||||
{
|
{
|
||||||
Renderer result;
|
Renderer result;
|
||||||
|
|
||||||
quality = (quality > 10) ? 10 : quality;
|
result = rendererCreate();
|
||||||
quality = (quality < 1) ? 1 : quality;
|
|
||||||
|
|
||||||
result.camera_location = _camera.location;
|
result.camera_location = _camera.location;
|
||||||
result.render_quality = quality;
|
|
||||||
|
|
||||||
result.filterLight = _filterLight;
|
result.filterLight = _filterLight;
|
||||||
result.maskLight = _maskLight;
|
result.maskLight = _maskLight;
|
||||||
|
|
|
@ -51,9 +51,8 @@ void sceneryGetTextures(TexturesDefinition* textures);
|
||||||
void scenerySetWater(WaterDefinition* water);
|
void scenerySetWater(WaterDefinition* water);
|
||||||
void sceneryGetWater(WaterDefinition* water);
|
void sceneryGetWater(WaterDefinition* water);
|
||||||
|
|
||||||
Renderer sceneryGetStandardRenderer(int quality);
|
Renderer sceneryCreateStandardRenderer();
|
||||||
void sceneryRenderFirstPass(Renderer* renderer);
|
void sceneryRenderFirstPass(Renderer* renderer);
|
||||||
void sceneryRenderSecondPass(Renderer* renderer);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
#ifndef _PAYSAGES_GLOBALS_H_
|
|
||||||
#define _PAYSAGES_GLOBALS_H_
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int render_width;
|
|
||||||
extern int render_height;
|
|
||||||
extern int render_quality;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -100,11 +100,11 @@ typedef struct
|
||||||
|
|
||||||
typedef struct Zone Zone;
|
typedef struct Zone Zone;
|
||||||
|
|
||||||
typedef void (*PreviewCallbackResize)(int width, int height);
|
typedef void (*RenderCallbackStart)(int width, int height, Color background);
|
||||||
typedef void (*PreviewCallbackClear)(Color col);
|
typedef void (*RenderCallbackDraw)(int x, int y, Color col);
|
||||||
typedef void (*PreviewCallbackDraw)(int x, int y, Color col);
|
typedef void (*RenderCallbackUpdate)(double progress);
|
||||||
typedef void (*PreviewCallbackUpdate)(double progress);
|
|
||||||
typedef int (*RenderProgressCallback)(double progress);
|
typedef struct RenderArea RenderArea;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "clouds.h"
|
#include "clouds.h"
|
||||||
|
@ -182,7 +181,7 @@ static int _postProcessFragment(RenderFragment* fragment, Renderer* renderer, vo
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
void skyRender(SkyDefinition* definition, Renderer* renderer)
|
||||||
{
|
{
|
||||||
int res_i, res_j;
|
int res_i, res_j;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -203,7 +202,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall
|
||||||
|
|
||||||
for (j = 0; j < res_j; j++)
|
for (j = 0; j < res_j; j++)
|
||||||
{
|
{
|
||||||
if (!callback((double)j / (double)(res_j - 1)))
|
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +250,7 @@ void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCall
|
||||||
vertex4.callback_data = definition;
|
vertex4.callback_data = definition;
|
||||||
|
|
||||||
/* TODO Triangles at poles */
|
/* TODO Triangles at poles */
|
||||||
renderPushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2);
|
renderer->pushQuad(renderer, &vertex1, &vertex4, &vertex3, &vertex2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ void skyValidateDefinition(SkyDefinition* definition);
|
||||||
|
|
||||||
int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights);
|
int skyGetLights(SkyDefinition* sky, LightDefinition* lights, int max_lights);
|
||||||
Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look);
|
Color skyGetColor(SkyDefinition* definition, Renderer* renderer, Vector3 eye, Vector3 look);
|
||||||
void skyRender(SkyDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
|
void skyRender(SkyDefinition* definition, Renderer* renderer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "euclid.h"
|
#include "euclid.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
@ -322,7 +321,7 @@ static void _renderQuad(TerrainDefinition* definition, Renderer* renderer, doubl
|
||||||
|
|
||||||
if (v1.location.y > water_height || v2.location.y > water_height || v3.location.y > water_height || v4.location.y > water_height)
|
if (v1.location.y > water_height || v2.location.y > water_height || v3.location.y > water_height || v4.location.y > water_height)
|
||||||
{
|
{
|
||||||
renderPushQuad(renderer, &v1, &v2, &v3, &v4);
|
renderer->pushQuad(renderer, &v1, &v2, &v3, &v4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +348,7 @@ Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double
|
||||||
return _getColor(definition, renderer, point, detail);
|
return _getColor(definition, renderer, point, detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
void terrainRender(TerrainDefinition* definition, Renderer* renderer)
|
||||||
{
|
{
|
||||||
int chunk_factor, chunk_count, i;
|
int chunk_factor, chunk_count, i;
|
||||||
double cx = renderer->camera_location.x;
|
double cx = renderer->camera_location.x;
|
||||||
|
@ -371,7 +370,7 @@ void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProg
|
||||||
|
|
||||||
while (radius_ext < 1000.0)
|
while (radius_ext < 1000.0)
|
||||||
{
|
{
|
||||||
if (!callback(radius_ext / 1000.0))
|
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ int terrainProjectRay(TerrainDefinition* definition, Renderer* renderer, Vector3
|
||||||
double terrainGetHeight(TerrainDefinition* definition, double x, double z);
|
double terrainGetHeight(TerrainDefinition* definition, double x, double z);
|
||||||
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z);
|
double terrainGetHeightNormalized(TerrainDefinition* definition, double x, double z);
|
||||||
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail);
|
Color terrainGetColor(TerrainDefinition* definition, Renderer* renderer, double x, double z, double detail);
|
||||||
void terrainRender(TerrainDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
|
void terrainRender(TerrainDefinition* definition, Renderer* renderer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "euclid.h"
|
#include "euclid.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "shared/constants.h"
|
#include "shared/constants.h"
|
||||||
#include "shared/globals.h"
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "euclid.h"
|
#include "euclid.h"
|
||||||
#include "render.h"
|
#include "render.h"
|
||||||
|
@ -266,10 +265,10 @@ static void _renderQuad(WaterDefinition* definition, Renderer* renderer, double
|
||||||
v2 = _getFirstPassVertex(definition, x, z + size, size);
|
v2 = _getFirstPassVertex(definition, x, z + size, size);
|
||||||
v3 = _getFirstPassVertex(definition, x + size, z + size, size);
|
v3 = _getFirstPassVertex(definition, x + size, z + size, size);
|
||||||
v4 = _getFirstPassVertex(definition, x + size, z, size);
|
v4 = _getFirstPassVertex(definition, x + size, z, size);
|
||||||
renderPushQuad(renderer, &v1, &v2, &v3, &v4);
|
renderer->pushQuad(renderer, &v1, &v2, &v3, &v4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback)
|
void waterRender(WaterDefinition* definition, Renderer* renderer)
|
||||||
{
|
{
|
||||||
int chunk_factor, chunk_count, i;
|
int chunk_factor, chunk_count, i;
|
||||||
double cx = renderer->camera_location.x;
|
double cx = renderer->camera_location.x;
|
||||||
|
@ -286,7 +285,7 @@ void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgress
|
||||||
|
|
||||||
while (radius_ext < 1000.0)
|
while (radius_ext < 1000.0)
|
||||||
{
|
{
|
||||||
if (!callback(radius_ext / 1000.0))
|
if (!renderer->addRenderProgress(renderer, 0.0))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ HeightInfo waterGetHeightInfo(WaterDefinition* definition);
|
||||||
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
Color waterLightFilter(WaterDefinition* definition, Renderer* renderer, Color light, Vector3 location, Vector3 light_location, Vector3 direction_to_light);
|
||||||
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
WaterResult waterGetColorDetail(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
||||||
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
Color waterGetColor(WaterDefinition* definition, Renderer* renderer, Vector3 location, Vector3 look);
|
||||||
void waterRender(WaterDefinition* definition, Renderer* renderer, RenderProgressCallback callback);
|
void waterRender(WaterDefinition* definition, Renderer* renderer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue