paysages : WIP on several parts.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@516 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
22ed375111
commit
47ebc90552
20 changed files with 273 additions and 94 deletions
|
@ -64,7 +64,7 @@ bool BaseExplorerChunk::maintain()
|
|||
_texture_changed = true;
|
||||
_lock_data.unlock();
|
||||
|
||||
if (_texture_current_size < 8 && _texture_current_size < _texture_max_size)
|
||||
if (_texture_current_size < 4 && _texture_current_size < _texture_max_size)
|
||||
{
|
||||
maintain();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
#include <QColor>
|
||||
#include <QPainter>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QListWidget>
|
||||
#include <QPushButton>
|
||||
#include "tools.h"
|
||||
|
||||
#include "../lib_paysages/scenery.h"
|
||||
|
@ -26,7 +30,6 @@ static void _renderStart(int width, int height, Color background)
|
|||
|
||||
static void _renderDraw(int x, int y, Color col)
|
||||
{
|
||||
col = colorProfileApply(_current_dialog->_hdr_profile, col);
|
||||
_current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, colorToQColor(col).rgb());
|
||||
}
|
||||
|
||||
|
@ -80,8 +83,6 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer):
|
|||
_render_thread = NULL;
|
||||
_renderer = renderer;
|
||||
|
||||
_hdr_profile = colorProfileCreate();
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Paysages 3D - Render"));
|
||||
setLayout(new QVBoxLayout());
|
||||
|
@ -92,6 +93,7 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer):
|
|||
_scroll->setWidget(area);
|
||||
layout()->addWidget(_scroll);
|
||||
|
||||
// Status bar
|
||||
_info = new QWidget(this);
|
||||
_info->setLayout(new QHBoxLayout());
|
||||
layout()->addWidget(_info);
|
||||
|
@ -106,8 +108,31 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer):
|
|||
_progress->setValue(0);
|
||||
_info->layout()->addWidget(_progress);
|
||||
|
||||
// Action bar
|
||||
_actions = new QWidget(this);
|
||||
_actions->setLayout(new QHBoxLayout());
|
||||
layout()->addWidget(_actions);
|
||||
|
||||
_actions->layout()->addWidget(new QLabel(tr("Tone-mapping: "), _actions));
|
||||
_tonemapping_control = new QComboBox(_actions);
|
||||
_tonemapping_control->addItems(QStringList(tr("Uncharted")) << tr("Reinhard"));
|
||||
_actions->layout()->addWidget(_tonemapping_control);
|
||||
|
||||
_actions->layout()->addWidget(new QLabel(tr("Exposure: "), _actions));
|
||||
_exposure_control = new QSlider(Qt::Horizontal, _actions);
|
||||
_exposure_control->setRange(0, 1000);
|
||||
_exposure_control->setValue(200);
|
||||
_actions->layout()->addWidget(_exposure_control);
|
||||
|
||||
_save_button = new QPushButton(QIcon("images/save.png"), tr("Save picture"), _actions);
|
||||
_actions->layout()->addWidget(_save_button);
|
||||
|
||||
// Connections
|
||||
connect(this, SIGNAL(renderSizeChanged(int, int)), this, SLOT(applyRenderSize(int, int)));
|
||||
connect(this, SIGNAL(progressChanged(double)), this, SLOT(applyProgress(double)));
|
||||
connect(_save_button, SIGNAL(clicked()), this, SLOT(saveRender()));
|
||||
connect(_tonemapping_control, SIGNAL(currentIndexChanged(int)), this, SLOT(toneMappingChanged()));
|
||||
connect(_exposure_control, SIGNAL(valueChanged(int)), this, SLOT(toneMappingChanged()));
|
||||
}
|
||||
|
||||
DialogRender::~DialogRender()
|
||||
|
@ -119,7 +144,6 @@ DialogRender::~DialogRender()
|
|||
|
||||
delete _render_thread;
|
||||
}
|
||||
colorProfileDelete(_hdr_profile);
|
||||
delete pixbuf;
|
||||
delete pixbuf_lock;
|
||||
}
|
||||
|
@ -147,6 +171,33 @@ void DialogRender::startRender(RenderParams params)
|
|||
exec();
|
||||
}
|
||||
|
||||
void DialogRender::saveRender()
|
||||
{
|
||||
QString filepath;
|
||||
|
||||
filepath = QFileDialog::getSaveFileName(this, tr("Paysages 3D - Choose a filename to save the last render"), QString(), tr("Images (*.png *.jpg)"));
|
||||
if (!filepath.isNull())
|
||||
{
|
||||
if (!filepath.toLower().endsWith(".jpg") && !filepath.toLower().endsWith(".jpeg") && !filepath.toLower().endsWith(".png"))
|
||||
{
|
||||
filepath = filepath.append(".png");
|
||||
}
|
||||
if (renderSaveToFile(_renderer->render_area, (char*)filepath.toStdString().c_str()))
|
||||
{
|
||||
QMessageBox::information(this, "Message", QString(tr("The picture %1 has been saved.")).arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Message", QString(tr("Can't write to file : %1")).arg(filepath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DialogRender::toneMappingChanged()
|
||||
{
|
||||
renderSetToneMapping(_renderer->render_area, (ToneMappingOperator)_tonemapping_control->currentIndex(), ((double)_exposure_control->value()) * 0.01);
|
||||
}
|
||||
|
||||
void DialogRender::loadLastRender()
|
||||
{
|
||||
//applyRenderSize(_renderer->render_width, _renderer->render_height);
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <QThread>
|
||||
#include <QProgressBar>
|
||||
#include <QScrollArea>
|
||||
#include <QSlider>
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QMutex>
|
||||
#include "../lib_paysages/renderer.h"
|
||||
|
@ -26,11 +28,12 @@ public:
|
|||
QImage* pixbuf;
|
||||
QMutex* pixbuf_lock;
|
||||
QWidget* area;
|
||||
ColorProfile* _hdr_profile;
|
||||
|
||||
private slots:
|
||||
void applyRenderSize(int width, int height);
|
||||
void applyProgress(double value);
|
||||
void saveRender();
|
||||
void toneMappingChanged();
|
||||
|
||||
signals:
|
||||
void renderSizeChanged(int width, int height);
|
||||
|
@ -39,6 +42,10 @@ signals:
|
|||
private:
|
||||
QScrollArea* _scroll;
|
||||
QWidget* _info;
|
||||
QWidget* _actions;
|
||||
QComboBox* _tonemapping_control;
|
||||
QSlider* _exposure_control;
|
||||
QPushButton* _save_button;
|
||||
QThread* _render_thread;
|
||||
QLabel* _timer;
|
||||
Renderer* _renderer;
|
||||
|
|
|
@ -8,15 +8,21 @@ ExplorerChunkSky::ExplorerChunkSky(Renderer* renderer, double size, SkyboxOrient
|
|||
{
|
||||
_box_size = size;
|
||||
_orientation = orientation;
|
||||
_center = VECTOR_ZERO;
|
||||
|
||||
setMaxTextureSize(256);
|
||||
maintain();
|
||||
}
|
||||
|
||||
void ExplorerChunkSky::onCameraEvent(CameraDefinition* camera)
|
||||
{
|
||||
_center = camera->location;
|
||||
}
|
||||
|
||||
void ExplorerChunkSky::onRenderEvent(QGLWidget*)
|
||||
{
|
||||
double size = _box_size;
|
||||
Vector3 camera = renderer()->getCameraLocation(renderer(), VECTOR_ZERO);
|
||||
Vector3 camera = _center;
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
switch(_orientation)
|
||||
|
@ -72,14 +78,14 @@ void ExplorerChunkSky::onRenderEvent(QGLWidget*)
|
|||
glVertex3d(camera.x + size, camera.y + size, camera.z + size);
|
||||
break;
|
||||
case SKYBOX_BOTTOM:
|
||||
glTexCoord2d(0.0, 0.0);
|
||||
/*glTexCoord2d(0.0, 0.0);
|
||||
glVertex3d(camera.x - size, camera.y - size, camera.z - size);
|
||||
glTexCoord2d(0.0, 1.0);
|
||||
glVertex3d(camera.x - size, camera.y - size, camera.z + size);
|
||||
glTexCoord2d(1.0, 1.0);
|
||||
glVertex3d(camera.x + size, camera.y - size, camera.z + size);
|
||||
glTexCoord2d(1.0, 0.0);
|
||||
glVertex3d(camera.x + size, camera.y - size, camera.z - size);
|
||||
glVertex3d(camera.x + size, camera.y - size, camera.z - size);*/
|
||||
break;
|
||||
}
|
||||
glEnd();
|
||||
|
|
|
@ -20,6 +20,7 @@ class ExplorerChunkSky:public BaseExplorerChunk
|
|||
public:
|
||||
ExplorerChunkSky(Renderer* renderer, double size, SkyboxOrientation orientation);
|
||||
|
||||
void onCameraEvent(CameraDefinition* camera);
|
||||
void onRenderEvent(QGLWidget* widget);
|
||||
double getDisplayedSizeHint(CameraDefinition* camera);
|
||||
Color getTextureColor(double x, double y);
|
||||
|
@ -27,7 +28,7 @@ public:
|
|||
private:
|
||||
SkyboxOrientation _orientation;
|
||||
double _box_size;
|
||||
|
||||
Vector3 _center;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,13 +4,18 @@
|
|||
#include "baseexplorerchunk.h"
|
||||
#include "../lib_paysages/camera.h"
|
||||
|
||||
ExplorerChunkTerrain::ExplorerChunkTerrain(Renderer* renderer, double x, double z, double size, int nbchunks) : BaseExplorerChunk(renderer)
|
||||
ExplorerChunkTerrain::ExplorerChunkTerrain(Renderer* renderer, double x, double z, double size, int nbchunks, double water_height) : BaseExplorerChunk(renderer)
|
||||
{
|
||||
_startx = x;
|
||||
_startz = z;
|
||||
_size = size;
|
||||
_overall_step = size * (double)nbchunks;
|
||||
|
||||
_distance_to_camera = 0.0;
|
||||
|
||||
_water_height = water_height;
|
||||
_overwater = false;
|
||||
|
||||
_tessellation_max_size = 32;
|
||||
_tessellation = new double[(_tessellation_max_size + 1) * (_tessellation_max_size + 1)];
|
||||
_tessellation_current_size = 0;
|
||||
|
@ -31,6 +36,7 @@ ExplorerChunkTerrain::~ExplorerChunkTerrain()
|
|||
void ExplorerChunkTerrain::onResetEvent()
|
||||
{
|
||||
_tessellation_current_size = 0;
|
||||
_overwater = false;
|
||||
}
|
||||
|
||||
bool ExplorerChunkTerrain::onMaintainEvent()
|
||||
|
@ -50,6 +56,10 @@ bool ExplorerChunkTerrain::onMaintainEvent()
|
|||
if (_tessellation_current_size == 0 || i % old_tessellation_inc != 0 || j % old_tessellation_inc != 0)
|
||||
{
|
||||
double height = renderer->terrain->getHeight(renderer, _startx + _tessellation_step * (double)i, _startz + _tessellation_step * (double)j, 1);
|
||||
if (height >= _water_height)
|
||||
{
|
||||
_overwater = true;
|
||||
}
|
||||
_tessellation[j * (_tessellation_max_size + 1) + i] = height;
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +69,7 @@ bool ExplorerChunkTerrain::onMaintainEvent()
|
|||
_tessellation_current_size = new_tessellation_size;
|
||||
_lock_data.unlock();
|
||||
|
||||
if (_tessellation_current_size < 8 && _tessellation_current_size < _tessellation_max_size)
|
||||
if (_tessellation_current_size < 4 && _tessellation_current_size < _tessellation_max_size)
|
||||
{
|
||||
onMaintainEvent();
|
||||
}
|
||||
|
@ -96,6 +106,9 @@ void ExplorerChunkTerrain::onCameraEvent(CameraDefinition* camera)
|
|||
_startz -= _overall_step;
|
||||
askReset();
|
||||
}
|
||||
|
||||
_distance_to_camera = v3Norm(v3Sub(getCenter(), camera->location));
|
||||
|
||||
_lock_data.unlock();
|
||||
}
|
||||
|
||||
|
@ -106,7 +119,7 @@ void ExplorerChunkTerrain::onRenderEvent(QGLWidget*)
|
|||
double tsize = 1.0 / (double)_tessellation_max_size;
|
||||
_lock_data.unlock();
|
||||
|
||||
if (tessellation_size <= 1)
|
||||
if (tessellation_size <= 1 or not _overwater)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -131,11 +144,16 @@ double ExplorerChunkTerrain::getDisplayedSizeHint(CameraDefinition* camera)
|
|||
double distance;
|
||||
Vector3 center;
|
||||
|
||||
if (not _overwater)
|
||||
{
|
||||
return -1000.0;
|
||||
}
|
||||
|
||||
center = getCenter();
|
||||
|
||||
if (cameraIsBoxInView(camera, center, _size, 40.0, _size))
|
||||
{
|
||||
distance = v3Norm(v3Sub(camera->location, center));
|
||||
distance = _distance_to_camera;
|
||||
distance = distance < 0.1 ? 0.1 : distance;
|
||||
return (int)ceil(120.0 - distance / 1.5);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
class ExplorerChunkTerrain:public BaseExplorerChunk
|
||||
{
|
||||
public:
|
||||
ExplorerChunkTerrain(Renderer* renderer, double x, double z, double size, int nbchunks);
|
||||
ExplorerChunkTerrain(Renderer* renderer, double x, double z, double size, int nbchunks, double water_height);
|
||||
~ExplorerChunkTerrain();
|
||||
|
||||
void onCameraEvent(CameraDefinition* camera);
|
||||
|
@ -26,6 +26,10 @@ private:
|
|||
double _size;
|
||||
double _overall_step;
|
||||
|
||||
double _distance_to_camera;
|
||||
double _water_height;
|
||||
bool _overwater;
|
||||
|
||||
double* _tessellation;
|
||||
int _tessellation_max_size;
|
||||
int _tessellation_current_size;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "formrender.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include "dialogrender.h"
|
||||
#include "inputcamera.h"
|
||||
#include "tools.h"
|
||||
|
@ -120,8 +118,6 @@ FormRender::FormRender(QWidget *parent) :
|
|||
connect(button, SIGNAL(clicked()), this, SLOT(startRender()));
|
||||
button = addButton(tr("Show last render"));
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(showRender()));
|
||||
button = addButton(tr("Save last render"));
|
||||
connect(button, SIGNAL(clicked()), this, SLOT(saveRender()));
|
||||
|
||||
revertConfig();
|
||||
}
|
||||
|
@ -215,28 +211,3 @@ void FormRender::showRender()
|
|||
delete dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void FormRender::saveRender()
|
||||
{
|
||||
if (_renderer_inited)
|
||||
{
|
||||
QString filepath;
|
||||
|
||||
filepath = QFileDialog::getSaveFileName(this, tr("Paysages 3D - Choose a filename to save the last render"), QString(), tr("Images (*.png *.jpg)"));
|
||||
if (!filepath.isNull())
|
||||
{
|
||||
if (!filepath.toLower().endsWith(".jpg") && !filepath.toLower().endsWith(".jpeg") && !filepath.toLower().endsWith(".png"))
|
||||
{
|
||||
filepath = filepath.append(".png");
|
||||
}
|
||||
if (renderSaveToFile(_renderer->render_area, (char*)filepath.toStdString().c_str()))
|
||||
{
|
||||
QMessageBox::information(this, "Message", QString(tr("The picture %1 has been saved.")).arg(filepath));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, "Message", QString(tr("Can't write to file : %1")).arg(filepath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ protected slots:
|
|||
private slots:
|
||||
void startRender();
|
||||
void showRender();
|
||||
void saveRender();
|
||||
|
||||
private:
|
||||
RenderParams _params;
|
||||
|
|
|
@ -238,7 +238,7 @@ FormWater::FormWater(QWidget *parent):
|
|||
addPreview(previewCoverage, tr("Coverage preview"));
|
||||
addPreview(previewColor, tr("Rendered preview"));
|
||||
|
||||
addInputDouble(tr("Height"), &_definition.height, -10.0, 10.0, 0.1, 1.0);
|
||||
addInputDouble(tr("Height"), &_definition.height, -15.0, 15.0, 0.1, 1.0);
|
||||
addInputMaterial(tr("Surface material"), &_definition.material);
|
||||
addInputColor(tr("Depth color"), &_definition.depth_color);
|
||||
addInputDouble(tr("Transparency"), &_definition.transparency, 0.0, 1.0, 0.001, 0.1);
|
||||
|
|
|
@ -53,6 +53,11 @@ static Color _applyTextures(Renderer* renderer, Vector3 location, double precisi
|
|||
return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision);
|
||||
}
|
||||
|
||||
static Vector3 _getCameraLocation(Renderer* renderer, Vector3)
|
||||
{
|
||||
return ((CameraDefinition*)renderer->customData[2])->location;
|
||||
}
|
||||
|
||||
WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
||||
QGLWidget(parent)
|
||||
{
|
||||
|
@ -70,8 +75,10 @@ WidgetExplorer::WidgetExplorer(QWidget *parent, CameraDefinition* camera):
|
|||
_renderer = sceneryCreateStandardRenderer();
|
||||
_renderer->render_quality = 3;
|
||||
_renderer->customData[1] = &_textures;
|
||||
_renderer->customData[2] = _base_camera;
|
||||
_renderer->customData[3] = &_water;
|
||||
_renderer->applyTextures = _applyTextures;
|
||||
_renderer->getCameraLocation = _getCameraLocation;
|
||||
|
||||
_inited = false;
|
||||
_updated = false;
|
||||
|
@ -100,14 +107,15 @@ void WidgetExplorer::startRendering()
|
|||
{
|
||||
// Add terrain
|
||||
int chunks = 20;
|
||||
double size = 200.0;
|
||||
double size = 400.0;
|
||||
double chunksize = size / (double)chunks;
|
||||
double start = -size / 2.0;
|
||||
double water_height = _renderer->getWaterHeightInfo(_renderer).base_height;
|
||||
for (int i = 0; i < chunks; i++)
|
||||
{
|
||||
for (int j = 0; j < chunks; j++)
|
||||
{
|
||||
ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(_renderer, start + chunksize * (double)i, start + chunksize * (double)j, chunksize, chunks);
|
||||
ExplorerChunkTerrain* chunk = new ExplorerChunkTerrain(_renderer, start + chunksize * (double)i, start + chunksize * (double)j, chunksize, chunks, water_height);
|
||||
_chunks.append(chunk);
|
||||
_updateQueue.append(chunk);
|
||||
}
|
||||
|
@ -326,7 +334,6 @@ void WidgetExplorer::wheelEvent(QWheelEvent* event)
|
|||
{
|
||||
cameraStrafeForward(&_current_camera, (double)event->delta() * factor);
|
||||
updateGL();
|
||||
|
||||
}
|
||||
event->accept();
|
||||
}
|
||||
|
@ -396,6 +403,7 @@ void WidgetExplorer::paintGL()
|
|||
QTime start_time;
|
||||
double frame_time;
|
||||
|
||||
cameraCopyDefinition(&_current_camera, &_renderer->render_camera);
|
||||
cameraValidateDefinition(&_current_camera, 1);
|
||||
|
||||
start_time = QTime::currentTime();
|
||||
|
|
|
@ -65,7 +65,8 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
|||
noiseClearLevels(definition->_edge_noise);
|
||||
noiseClearLevels(definition->_coverage_noise);
|
||||
|
||||
noiseAddLevelsSimple(definition->_coverage_noise, 3, 1.0, 0.0, 1.0, 0.0);
|
||||
noiseAddLevelsSimple(definition->_coverage_noise, 2, 10.0, 0.0, 1.0, 0.0);
|
||||
noiseAddLevelsSimple(definition->_coverage_noise, 2, 1.0, 0.0, 1.0, 0.0);
|
||||
noiseSetFunctionParams(definition->_coverage_noise, NOISE_FUNCTION_NAIVE, 0.0, 0.0);
|
||||
switch (definition->type)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef struct
|
|||
|
||||
struct RenderArea
|
||||
{
|
||||
ColorProfile* hdr_mapping;
|
||||
RenderParams params;
|
||||
int pixel_count;
|
||||
RenderFragment* pixels;
|
||||
|
@ -96,6 +97,7 @@ RenderArea* renderCreateArea()
|
|||
RenderArea* result;
|
||||
|
||||
result = malloc(sizeof(RenderArea));
|
||||
result->hdr_mapping = colorProfileCreate();
|
||||
result->params.width = 1;
|
||||
result->params.height = 1;
|
||||
result->params.antialias = 1;
|
||||
|
@ -123,6 +125,7 @@ RenderArea* renderCreateArea()
|
|||
|
||||
void renderDeleteArea(RenderArea* area)
|
||||
{
|
||||
colorProfileDelete(area->hdr_mapping);
|
||||
mutexDestroy(area->lock);
|
||||
free(area->pixels);
|
||||
free(area->scanline_up);
|
||||
|
@ -130,6 +133,14 @@ void renderDeleteArea(RenderArea* area)
|
|||
free(area);
|
||||
}
|
||||
|
||||
static void _setAllDirty(RenderArea* area)
|
||||
{
|
||||
area->dirty_left = 0;
|
||||
area->dirty_right = area->params.width * area->params.antialias - 1;
|
||||
area->dirty_down = 0;
|
||||
area->dirty_up = area->params.height * area->params.antialias - 1;
|
||||
}
|
||||
|
||||
void renderSetParams(RenderArea* area, RenderParams params)
|
||||
{
|
||||
int width, height;
|
||||
|
@ -155,6 +166,13 @@ void renderSetParams(RenderArea* area, RenderParams params)
|
|||
renderClear(area);
|
||||
}
|
||||
|
||||
void renderSetToneMapping(RenderArea* area, ToneMappingOperator tonemapper, double exposure)
|
||||
{
|
||||
colorProfileSetToneMapping(area->hdr_mapping, tonemapper, exposure);
|
||||
_setAllDirty(area);
|
||||
renderUpdate(area);
|
||||
}
|
||||
|
||||
void renderSetBackgroundColor(RenderArea* area, Color* col)
|
||||
{
|
||||
area->background_color = *col;
|
||||
|
@ -264,6 +282,8 @@ static inline Color _getFinalPixel(RenderArea* area, int x, int y)
|
|||
result.r += col.r / (double)(area->params.antialias * area->params.antialias);
|
||||
result.g += col.g / (double)(area->params.antialias * area->params.antialias);
|
||||
result.b += col.b / (double)(area->params.antialias * area->params.antialias);
|
||||
|
||||
result = colorProfileApply(area->hdr_mapping, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,14 +324,6 @@ void renderUpdate(RenderArea* area)
|
|||
mutexRelease(area->lock);
|
||||
}
|
||||
|
||||
static void _setAllDirty(RenderArea* area)
|
||||
{
|
||||
area->dirty_left = 0;
|
||||
area->dirty_right = area->params.width * area->params.antialias - 1;
|
||||
area->dirty_down = 0;
|
||||
area->dirty_up = area->params.height * area->params.antialias - 1;
|
||||
}
|
||||
|
||||
static inline unsigned int _pushCallback(RenderArea* area, FragmentCallback callback)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -32,6 +32,7 @@ RenderArea* renderCreateArea();
|
|||
void renderDeleteArea(RenderArea* area);
|
||||
|
||||
void renderSetParams(RenderArea* area, RenderParams params);
|
||||
void renderSetToneMapping(RenderArea* area, ToneMappingOperator tonemapper, double exposure);
|
||||
void renderSetBackgroundColor(RenderArea* area, Color* col);
|
||||
void renderClear(RenderArea* area);
|
||||
void renderUpdate(RenderArea* area);
|
||||
|
|
|
@ -83,6 +83,7 @@ int systemSavePictureFile(const char* filepath, PictureCallbackSavePixel callbac
|
|||
for (x = 0; x < width; x++)
|
||||
{
|
||||
result = callback_pixel(data, x, y);
|
||||
colorNormalize(&result);
|
||||
rgba = colorTo32BitRGBA(&result);
|
||||
pixels[y * width + x] = rgba;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../tools/memory.h"
|
||||
#include "../tools.h"
|
||||
|
||||
TerrainHeightMap* terrainHeightMapCreate(TerrainDefinition* terrain)
|
||||
{
|
||||
|
@ -143,10 +144,35 @@ void terrainHeightmapLoad(PackStream* stream, TerrainHeightMap* heightmap)
|
|||
|
||||
static inline int _checkDataHit(TerrainHeightMapChunk* chunk, double x, double z, double* result)
|
||||
{
|
||||
if (x > (double)chunk->rect.xstart && x < (double)chunk->rect.xend && z > (double)chunk->rect.zstart && z < (double)chunk->rect.zend)
|
||||
if (x >= (double)chunk->rect.xstart && x <= (double)chunk->rect.xend && z >= (double)chunk->rect.zstart && z <= (double)chunk->rect.zend)
|
||||
{
|
||||
/* TODO Get interpolated value */
|
||||
*result = 0.0;
|
||||
double stencil[16];
|
||||
int ix, iz, cx, cz;
|
||||
int xmax = chunk->rect.xsize - 1;
|
||||
int zmax = chunk->rect.zsize - 1;
|
||||
int xlow;
|
||||
int zlow;
|
||||
|
||||
x -= chunk->rect.xstart;
|
||||
z -= chunk->rect.zstart;
|
||||
|
||||
xlow = floor(x);
|
||||
zlow = floor(z);
|
||||
|
||||
for (ix = xlow - 1; ix <= xlow + 2; ix++)
|
||||
{
|
||||
for (iz = zlow - 1; iz <= zlow + 2; iz++)
|
||||
{
|
||||
cx = ix < 0 ? 0 : ix;
|
||||
cx = cx > xmax ? xmax : cx;
|
||||
cz = iz < 0 ? 0 : iz;
|
||||
cz = cz > zmax ? zmax : cz;
|
||||
stencil[(iz - (zlow - 1)) * 4 + ix - (xlow - 1)] = chunk->data[cz * chunk->rect.xsize + cx];
|
||||
}
|
||||
}
|
||||
|
||||
*result = toolsBicubicInterpolate(stencil, x - (double)xlow, z - (double)zlow);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
@ -240,7 +266,7 @@ static void _prepareBrushStroke(TerrainHeightMap* heightmap, TerrainBrush* brush
|
|||
new_size = sizeof(double) * heightmap->floating_data.rect.xsize * heightmap->floating_data.rect.zsize;
|
||||
heightmap->floating_data.data = realloc(heightmap->floating_data.data, new_size);
|
||||
|
||||
_resetRect(heightmap, 0, 0, heightmap->floating_data.rect.xsize - 1, heightmap->floating_data.rect.zsize - 1);
|
||||
_resetRect(heightmap, 0, heightmap->floating_data.rect.xsize - 1, 0, heightmap->floating_data.rect.zsize - 1);
|
||||
|
||||
heightmap->floating_used = 1;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ void terrainAutoPreset(TerrainDefinition* definition, TerrainPreset preset)
|
|||
case TERRAIN_PRESET_STANDARD:
|
||||
noiseRandomizeOffsets(definition->_height_noise);
|
||||
noiseClearLevels(definition->_height_noise);
|
||||
noiseAddLevelsSimple(definition->_height_noise, resolution, pow(2.0, resolution - 1), -12.5, 12.5, 0.5);
|
||||
noiseAddLevelSimple(definition->_height_noise, pow(2.0, resolution + 1), -15.0, 15.0);
|
||||
noiseAddLevelsSimple(definition->_height_noise, resolution - 2, pow(2.0, resolution - 1), -10.0, 10.0, 0.5);
|
||||
noiseNormalizeAmplitude(definition->_height_noise, -15.0, 15.0, 0);
|
||||
noiseSetFunctionParams(definition->_height_noise, NOISE_FUNCTION_SIMPLEX, 0.0, 0.0);
|
||||
definition->scaling = 1.0;
|
||||
definition->height = 1.0;
|
||||
|
|
|
@ -184,6 +184,8 @@ struct ColorProfile
|
|||
{
|
||||
double minvalue;
|
||||
double maxvalue;
|
||||
Color (*mapper)(Color col, double exposure);
|
||||
double exposure;
|
||||
};
|
||||
|
||||
ColorProfile* colorProfileCreate()
|
||||
|
@ -192,6 +194,7 @@ ColorProfile* colorProfileCreate()
|
|||
|
||||
profile = malloc(sizeof(ColorProfile));
|
||||
|
||||
colorProfileSetToneMapping(profile, TONE_MAPPING_UNCHARTED, 2.0);
|
||||
colorProfileClear(profile);
|
||||
|
||||
return profile;
|
||||
|
@ -202,6 +205,52 @@ void colorProfileDelete(ColorProfile* profile)
|
|||
free(profile);
|
||||
}
|
||||
|
||||
static inline double _uncharted2Tonemap(double x)
|
||||
{
|
||||
double A = 0.15;
|
||||
double B = 0.50;
|
||||
double C = 0.10;
|
||||
double D = 0.20;
|
||||
double E = 0.02;
|
||||
double F = 0.30;
|
||||
|
||||
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
|
||||
}
|
||||
|
||||
static Color _toneMappingUncharted(Color pixel, double exposure)
|
||||
{
|
||||
double W = 11.2;
|
||||
double white_scale = 1.0 / _uncharted2Tonemap(W);
|
||||
|
||||
pixel.r = pow(_uncharted2Tonemap(pixel.r * exposure) * white_scale, 1.0 / 2.2);
|
||||
pixel.g = pow(_uncharted2Tonemap(pixel.g * exposure) * white_scale, 1.0 / 2.2);
|
||||
pixel.b = pow(_uncharted2Tonemap(pixel.b * exposure) * white_scale, 1.0 / 2.2);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
static Color _toneMappingReinhard(Color pixel, double exposure)
|
||||
{
|
||||
pixel.r = (pixel.r * exposure) / (1.0 + pixel.r * exposure);
|
||||
pixel.g = (pixel.g * exposure) / (1.0 + pixel.g * exposure);
|
||||
pixel.b = (pixel.b * exposure) / (1.0 + pixel.b * exposure);
|
||||
|
||||
return pixel;
|
||||
}
|
||||
|
||||
void colorProfileSetToneMapping(ColorProfile* profile, ToneMappingOperator tonemapper, double exposure)
|
||||
{
|
||||
if (tonemapper == TONE_MAPPING_REIHNARD)
|
||||
{
|
||||
profile->mapper = _toneMappingReinhard;
|
||||
}
|
||||
else
|
||||
{
|
||||
profile->mapper = _toneMappingUncharted;
|
||||
}
|
||||
profile->exposure = exposure;
|
||||
}
|
||||
|
||||
void colorProfileSave(PackStream* stream, ColorProfile* profile)
|
||||
{
|
||||
/* TODO */
|
||||
|
@ -236,37 +285,9 @@ int colorProfileCollect(ColorProfile* profile, Color pixel)
|
|||
return changed;
|
||||
}
|
||||
|
||||
static double _uncharted2Tonemap(double x)
|
||||
{
|
||||
double A = 0.15;
|
||||
double B = 0.50;
|
||||
double C = 0.10;
|
||||
double D = 0.20;
|
||||
double E = 0.02;
|
||||
double F = 0.30;
|
||||
|
||||
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
|
||||
}
|
||||
|
||||
Color colorProfileApply(ColorProfile* profile, Color pixel)
|
||||
{
|
||||
/*pixel.r *= 0.4;
|
||||
pixel.g *= 0.4;
|
||||
pixel.b *= 0.4;
|
||||
pixel.r = pixel.r < 1.413 ? pow(pixel.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-pixel.r);
|
||||
pixel.g = pixel.g < 1.413 ? pow(pixel.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-pixel.g);
|
||||
pixel.b = pixel.b < 1.413 ? pow(pixel.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-pixel.b);
|
||||
return pixel;*/
|
||||
|
||||
double exposure_bias = 2.0;
|
||||
double W = 11.2;
|
||||
double white_scale = 1.0 / _uncharted2Tonemap(W);
|
||||
|
||||
pixel.r = pow(_uncharted2Tonemap(pixel.r * exposure_bias) * white_scale, 1.0 / 2.2);
|
||||
pixel.g = pow(_uncharted2Tonemap(pixel.g * exposure_bias) * white_scale, 1.0 / 2.2);
|
||||
pixel.b = pow(_uncharted2Tonemap(pixel.b * exposure_bias) * white_scale, 1.0 / 2.2);
|
||||
|
||||
return pixel;
|
||||
return profile->mapper(pixel, profile->exposure);
|
||||
}
|
||||
|
||||
/******************************** ColorGradation ********************************/
|
||||
|
|
|
@ -44,10 +44,17 @@ double colorGetValue(Color* col);
|
|||
|
||||
/* HDR profile for tone-mapping */
|
||||
typedef struct ColorProfile ColorProfile;
|
||||
typedef enum
|
||||
{
|
||||
TONE_MAPPING_UNCHARTED,
|
||||
TONE_MAPPING_REIHNARD
|
||||
} ToneMappingOperator;
|
||||
|
||||
ColorProfile* colorProfileCreate();
|
||||
void colorProfileDelete(ColorProfile* profile);
|
||||
|
||||
void colorProfileSetToneMapping(ColorProfile* profile, ToneMappingOperator tonemapper, double exposure);
|
||||
|
||||
void colorProfileSave(PackStream* stream, ColorProfile* profile);
|
||||
void colorProfileLoad(PackStream* stream, ColorProfile* profile);
|
||||
|
||||
|
|
|
@ -1,11 +1,54 @@
|
|||
#include "memory.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void* memory2dRealloc(void* data, int datasize, int oldxsize, int oldysize, int newxsize, int newysize, int xoffset, int yoffset)
|
||||
{
|
||||
/* TODO Move remaining part*/
|
||||
return realloc(data, datasize * newxsize * newysize);
|
||||
int xstart, xend, xlen;
|
||||
int ystart, yend, y;
|
||||
void* result = malloc(datasize * newxsize * newysize);
|
||||
|
||||
/* Move remaining part*/
|
||||
ystart = yoffset;
|
||||
yend = yoffset + oldysize;
|
||||
if (yend >= 0 && ystart < newysize)
|
||||
{
|
||||
if (ystart < 0)
|
||||
{
|
||||
ystart = 0;
|
||||
}
|
||||
if (yend > newysize - 1)
|
||||
{
|
||||
yend = newysize - 1;
|
||||
}
|
||||
|
||||
xstart = xoffset;
|
||||
xend = xoffset + oldxsize;
|
||||
if (xend >= 0 && xstart < newxsize)
|
||||
{
|
||||
if (xstart < 0)
|
||||
{
|
||||
xstart = 0;
|
||||
}
|
||||
if (xend > newxsize - 1)
|
||||
{
|
||||
xend = newxsize - 1;
|
||||
}
|
||||
|
||||
xlen = xend - xstart + 1;
|
||||
if (xlen > 0)
|
||||
{
|
||||
for (y = ystart; y <= yend; y++)
|
||||
{
|
||||
memcpy(result + (y * newxsize + xstart) * datasize, data + ((y - ystart) * oldxsize) * datasize, xlen * datasize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
void memory2dScrolling(void* data, int datasize, int xsize, int ysize, int xoffset, int yoffset)
|
||||
|
|
Loading…
Reference in a new issue