paysages : HDR rendering (WIP).
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@495 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
4c72cb5ded
commit
2a0e7851d9
11 changed files with 189 additions and 79 deletions
2
TODO
2
TODO
|
@ -1,4 +1,5 @@
|
||||||
Technology Preview 2 :
|
Technology Preview 2 :
|
||||||
|
- Implement High Dynamic Range (with OpenEXR or Radiance file format support ?).
|
||||||
- Fully move layer management from BaseForm to BaseFormLayer.
|
- Fully move layer management from BaseForm to BaseFormLayer.
|
||||||
- Replace terrain canvas editor by full sculpting editor.
|
- Replace terrain canvas editor by full sculpting editor.
|
||||||
=> Add a generation dialog, with fixed resolution.
|
=> Add a generation dialog, with fixed resolution.
|
||||||
|
@ -43,7 +44,6 @@ Technlogy Preview 3 :
|
||||||
Technology Preview 4 :
|
Technology Preview 4 :
|
||||||
- Restore render progress.
|
- Restore render progress.
|
||||||
- Store the terrain canvases in a tree to allow "multi-res" edition.
|
- Store the terrain canvases in a tree to allow "multi-res" edition.
|
||||||
- Implement High Dynamic Range.
|
|
||||||
- Implement Sub Surface Scattering for water.
|
- Implement Sub Surface Scattering for water.
|
||||||
- Use bicubic interpolation for antialiasing.
|
- Use bicubic interpolation for antialiasing.
|
||||||
- Allow for larger renders/antialias (will need several two-pass chunks).
|
- Allow for larger renders/antialias (will need several two-pass chunks).
|
||||||
|
|
|
@ -26,6 +26,7 @@ static void _renderStart(int width, int height, Color background)
|
||||||
|
|
||||||
static void _renderDraw(int x, int y, Color col)
|
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());
|
_current_dialog->pixbuf->setPixel(x, _current_dialog->pixbuf->height() - 1 - y, colorToQColor(col).rgb());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +80,8 @@ DialogRender::DialogRender(QWidget *parent, Renderer* renderer):
|
||||||
_render_thread = NULL;
|
_render_thread = NULL;
|
||||||
_renderer = renderer;
|
_renderer = renderer;
|
||||||
|
|
||||||
|
_hdr_profile = colorProfileCreate();
|
||||||
|
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setWindowTitle(tr("Paysages 3D - Render"));
|
setWindowTitle(tr("Paysages 3D - Render"));
|
||||||
setLayout(new QVBoxLayout());
|
setLayout(new QVBoxLayout());
|
||||||
|
@ -116,6 +119,7 @@ DialogRender::~DialogRender()
|
||||||
|
|
||||||
delete _render_thread;
|
delete _render_thread;
|
||||||
}
|
}
|
||||||
|
colorProfileDelete(_hdr_profile);
|
||||||
delete pixbuf;
|
delete pixbuf;
|
||||||
delete pixbuf_lock;
|
delete pixbuf_lock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include "../lib_paysages/renderer.h"
|
#include "../lib_paysages/renderer.h"
|
||||||
|
#include "../lib_paysages/color.h"
|
||||||
|
|
||||||
class DialogRender : public QDialog
|
class DialogRender : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -25,6 +26,7 @@ public:
|
||||||
QImage* pixbuf;
|
QImage* pixbuf;
|
||||||
QMutex* pixbuf_lock;
|
QMutex* pixbuf_lock;
|
||||||
QWidget* area;
|
QWidget* area;
|
||||||
|
ColorProfile* _hdr_profile;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void applyRenderSize(int width, int height);
|
void applyRenderSize(int width, int height);
|
||||||
|
|
|
@ -302,22 +302,6 @@ static Color _transmittanceWithShadow(double r, double mu)
|
||||||
return mu < -sqrt(1.0 - (Rg / r) * (Rg / r)) ? COLOR_BLACK : _transmittance(r, mu);
|
return mu < -sqrt(1.0 - (Rg / r) * (Rg / r)) ? COLOR_BLACK : _transmittance(r, mu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color _hdr(Color c1, Color c2, Color c3)
|
|
||||||
{
|
|
||||||
Color L = {c1.r + c2.r + c3.r, c1.g + c2.g + c3.g, c1.b + c2.b + c3.b, 1.0};
|
|
||||||
|
|
||||||
L.r *= exposure;
|
|
||||||
L.g *= exposure;
|
|
||||||
L.b *= exposure;
|
|
||||||
L.a = 1.0;
|
|
||||||
|
|
||||||
L.r = L.r < 1.413 ? pow(L.r * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.r);
|
|
||||||
L.g = L.g < 1.413 ? pow(L.g * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.g);
|
|
||||||
L.b = L.b < 1.413 ? pow(L.b * 0.38317, 1.0 / 2.2) : 1.0 - exp(-L.b);
|
|
||||||
|
|
||||||
return L;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, double* muS, double* nu)
|
static void _getMuMuSNu(double x, double y, double r, Color dhdH, double* mu, double* muS, double* nu)
|
||||||
{
|
{
|
||||||
double d;
|
double d;
|
||||||
|
@ -1252,9 +1236,12 @@ Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3
|
||||||
|
|
||||||
Vector3 attenuation;
|
Vector3 attenuation;
|
||||||
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
||||||
Color groundColor = COLOR_BLACK;
|
|
||||||
Color sunColor = _sunColor(x, 0.0, v, s, r, mu); /* L0 */
|
Color sunColor = _sunColor(x, 0.0, v, s, r, mu); /* L0 */
|
||||||
return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */
|
|
||||||
|
inscatterColor.r += sunColor.r;
|
||||||
|
inscatterColor.g += sunColor.g;
|
||||||
|
inscatterColor.b += sunColor.b;
|
||||||
|
return inscatterColor; /* Eq (16) */
|
||||||
}
|
}
|
||||||
|
|
||||||
Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
|
@ -1297,6 +1284,9 @@ Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color
|
||||||
Vector3 attenuation;
|
Vector3 attenuation;
|
||||||
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
||||||
Color groundColor = _groundColor(base, x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/
|
Color groundColor = _groundColor(base, x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/
|
||||||
Color sunColor = COLOR_BLACK;
|
|
||||||
return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */
|
groundColor.r += inscatterColor.r;
|
||||||
|
groundColor.g += inscatterColor.g;
|
||||||
|
groundColor.b += inscatterColor.b;
|
||||||
|
return groundColor; /* Eq (16) */
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,34 +24,34 @@ void atmosphereAutoPreset(AtmosphereDefinition* definition, AtmospherePreset pre
|
||||||
definition->model = ATMOSPHERE_MODEL_BRUNETON;
|
definition->model = ATMOSPHERE_MODEL_BRUNETON;
|
||||||
definition->hour = 15;
|
definition->hour = 15;
|
||||||
definition->minute = 0;
|
definition->minute = 0;
|
||||||
definition->dome_lighting = 0.6;
|
definition->dome_lighting = 0.2;
|
||||||
break;
|
break;
|
||||||
case ATMOSPHERE_PRESET_CLEAR_SUNSET:
|
case ATMOSPHERE_PRESET_CLEAR_SUNSET:
|
||||||
definition->model = ATMOSPHERE_MODEL_BRUNETON;
|
definition->model = ATMOSPHERE_MODEL_BRUNETON;
|
||||||
definition->hour = 17;
|
definition->hour = 17;
|
||||||
definition->minute = 45;
|
definition->minute = 45;
|
||||||
definition->dome_lighting = 0.8;
|
definition->dome_lighting = 0.3;
|
||||||
definition->sun_radius = 0.03;
|
definition->sun_radius = 0.03;
|
||||||
break;
|
break;
|
||||||
case ATMOSPHERE_PRESET_HAZY_MORNING:
|
case ATMOSPHERE_PRESET_HAZY_MORNING:
|
||||||
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
||||||
definition->hour = 8;
|
definition->hour = 8;
|
||||||
definition->minute = 30;
|
definition->minute = 30;
|
||||||
definition->dome_lighting = 0.5;
|
definition->dome_lighting = 0.25;
|
||||||
definition->humidity = 0.3;
|
definition->humidity = 0.3;
|
||||||
break;
|
break;
|
||||||
case ATMOSPHERE_PRESET_FOGGY:
|
case ATMOSPHERE_PRESET_FOGGY:
|
||||||
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
||||||
definition->hour = 15;
|
definition->hour = 15;
|
||||||
definition->minute = 0;
|
definition->minute = 0;
|
||||||
definition->dome_lighting = 0.7;
|
definition->dome_lighting = 0.1;
|
||||||
definition->humidity = 0.6;
|
definition->humidity = 0.6;
|
||||||
break;
|
break;
|
||||||
case ATMOSPHERE_PRESET_STORMY:
|
case ATMOSPHERE_PRESET_STORMY:
|
||||||
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
definition->model = ATMOSPHERE_MODEL_PREETHAM;
|
||||||
definition->hour = 15;
|
definition->hour = 15;
|
||||||
definition->minute = 0;
|
definition->minute = 0;
|
||||||
definition->dome_lighting = 0.3;
|
definition->dome_lighting = 0.05;
|
||||||
definition->humidity = 0.9;
|
definition->humidity = 0.9;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
|
|
||||||
|
/******************************** Color ********************************/
|
||||||
|
|
||||||
Color COLOR_TRANSPARENT = {0.0, 0.0, 0.0, 0.0};
|
Color COLOR_TRANSPARENT = {0.0, 0.0, 0.0, 0.0};
|
||||||
Color COLOR_BLACK = {0.0, 0.0, 0.0, 1.0};
|
Color COLOR_BLACK = {0.0, 0.0, 0.0, 1.0};
|
||||||
Color COLOR_RED = {1.0, 0.0, 0.0, 1.0};
|
Color COLOR_RED = {1.0, 0.0, 0.0, 1.0};
|
||||||
|
@ -14,13 +17,6 @@ Color COLOR_BLUE = {0.0, 0.0, 1.0, 1.0};
|
||||||
Color COLOR_WHITE = {1.0, 1.0, 1.0, 1.0};
|
Color COLOR_WHITE = {1.0, 1.0, 1.0, 1.0};
|
||||||
Color COLOR_GREY = {0.5, 0.5, 0.5, 1.0};
|
Color COLOR_GREY = {0.5, 0.5, 0.5, 1.0};
|
||||||
|
|
||||||
struct ColorGradation
|
|
||||||
{
|
|
||||||
Curve* red;
|
|
||||||
Curve* green;
|
|
||||||
Curve* blue;
|
|
||||||
};
|
|
||||||
|
|
||||||
void colorSave(PackStream* stream, Color* col)
|
void colorSave(PackStream* stream, Color* col)
|
||||||
{
|
{
|
||||||
packWriteDouble(stream, &col->r);
|
packWriteDouble(stream, &col->r);
|
||||||
|
@ -60,48 +56,48 @@ unsigned int colorTo32BitABGR(Color* col)
|
||||||
Color colorFrom32BitRGBA(unsigned int col)
|
Color colorFrom32BitRGBA(unsigned int col)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
|
|
||||||
result.r = ((double)(col & 0x000000FF)) / 255.0;
|
result.r = ((double)(col & 0x000000FF)) / 255.0;
|
||||||
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
||||||
result.b = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
result.b = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
||||||
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color colorFrom32BitBGRA(unsigned int col)
|
Color colorFrom32BitBGRA(unsigned int col)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
|
|
||||||
result.b = ((double)(col & 0x000000FF)) / 255.0;
|
result.b = ((double)(col & 0x000000FF)) / 255.0;
|
||||||
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
||||||
result.r = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
result.r = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
||||||
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color colorFrom32BitARGB(unsigned int col)
|
Color colorFrom32BitARGB(unsigned int col)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
|
|
||||||
result.a = ((double)(col & 0x000000FF)) / 255.0;
|
result.a = ((double)(col & 0x000000FF)) / 255.0;
|
||||||
result.r = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
result.r = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
||||||
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
||||||
result.b = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
result.b = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color colorFrom32BitABGR(unsigned int col)
|
Color colorFrom32BitABGR(unsigned int col)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
|
|
||||||
result.a = ((double)(col & 0x000000FF)) / 255.0;
|
result.a = ((double)(col & 0x000000FF)) / 255.0;
|
||||||
result.b = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
result.b = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
|
||||||
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
|
||||||
result.r = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
result.r = ((double)((col & 0xFF000000) >> 24)) / 255.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +121,20 @@ void colorMask(Color* base, Color* mask)
|
||||||
|
|
||||||
double colorNormalize(Color* col)
|
double colorNormalize(Color* col)
|
||||||
{
|
{
|
||||||
double max = colorGetValue(col);
|
if (col->r > 1.0)
|
||||||
|
{
|
||||||
|
col->r = 1.0;
|
||||||
|
}
|
||||||
|
if (col->g > 1.0)
|
||||||
|
{
|
||||||
|
col->g = 1.0;
|
||||||
|
}
|
||||||
|
if (col->b > 1.0)
|
||||||
|
{
|
||||||
|
col->b = 1.0;
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
/*double max = colorGetValue(col);
|
||||||
|
|
||||||
assert(max >= 0.0);
|
assert(max >= 0.0);
|
||||||
assert(col->r >= 0.0);
|
assert(col->r >= 0.0);
|
||||||
|
@ -139,7 +148,7 @@ double colorNormalize(Color* col)
|
||||||
col->g /= max;
|
col->g /= max;
|
||||||
col->b /= max;
|
col->b /= max;
|
||||||
}
|
}
|
||||||
return max;
|
return max;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
double colorGetValue(Color* col)
|
double colorGetValue(Color* col)
|
||||||
|
@ -158,6 +167,96 @@ double colorGetValue(Color* col)
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************** ColorProfile ********************************/
|
||||||
|
struct ColorProfile
|
||||||
|
{
|
||||||
|
double minvalue;
|
||||||
|
double maxvalue;
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorProfile* colorProfileCreate()
|
||||||
|
{
|
||||||
|
ColorProfile* profile;
|
||||||
|
|
||||||
|
profile = malloc(sizeof(ColorProfile));
|
||||||
|
|
||||||
|
colorProfileClear(profile);
|
||||||
|
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorProfileDelete(ColorProfile* profile)
|
||||||
|
{
|
||||||
|
free(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorProfileSave(PackStream* stream, ColorProfile* profile)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorProfileLoad(PackStream* stream, ColorProfile* profile)
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void colorProfileClear(ColorProfile* profile)
|
||||||
|
{
|
||||||
|
profile->minvalue = 0.0;
|
||||||
|
profile->maxvalue = 3.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colorProfileCollect(ColorProfile* profile, Color pixel)
|
||||||
|
{
|
||||||
|
int changed = 0;
|
||||||
|
double value = pixel.r + pixel.g + pixel.b;
|
||||||
|
|
||||||
|
if (value < profile->minvalue)
|
||||||
|
{
|
||||||
|
profile->minvalue = value;
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
if (value > profile->maxvalue)
|
||||||
|
{
|
||||||
|
profile->maxvalue = value;
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float A = 0.15;
|
||||||
|
float B = 0.50;
|
||||||
|
float C = 0.10;
|
||||||
|
float D = 0.20;
|
||||||
|
float E = 0.02;
|
||||||
|
float F = 0.30;
|
||||||
|
float W = 11.2;
|
||||||
|
|
||||||
|
static double _uncharted2Tonemap(double x)
|
||||||
|
{
|
||||||
|
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color colorProfileApply(ColorProfile* profile, Color pixel)
|
||||||
|
{
|
||||||
|
double exposure_bias = 2.0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************** ColorGradation ********************************/
|
||||||
|
struct ColorGradation
|
||||||
|
{
|
||||||
|
Curve* red;
|
||||||
|
Curve* green;
|
||||||
|
Curve* blue;
|
||||||
|
};
|
||||||
|
|
||||||
ColorGradation* colorGradationCreate()
|
ColorGradation* colorGradationCreate()
|
||||||
{
|
{
|
||||||
ColorGradation* result;
|
ColorGradation* result;
|
||||||
|
@ -166,7 +265,7 @@ ColorGradation* colorGradationCreate()
|
||||||
result->red = curveCreate();
|
result->red = curveCreate();
|
||||||
result->green = curveCreate();
|
result->green = curveCreate();
|
||||||
result->blue = curveCreate();
|
result->blue = curveCreate();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +363,7 @@ Color colorGradationGet(ColorGradation* gradation, double value)
|
||||||
result.g = curveGetValue(gradation->green, value);
|
result.g = curveGetValue(gradation->green, value);
|
||||||
result.b = curveGetValue(gradation->blue, value);
|
result.b = curveGetValue(gradation->blue, value);
|
||||||
result.a = 1.0;
|
result.a = 1.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define _PAYSAGES_COLOR_H_
|
#define _PAYSAGES_COLOR_H_
|
||||||
|
|
||||||
#include "curve.h"
|
#include "curve.h"
|
||||||
|
#include "pack.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -41,6 +42,19 @@ void colorMask(Color* base, Color* mask);
|
||||||
double colorNormalize(Color* col);
|
double colorNormalize(Color* col);
|
||||||
double colorGetValue(Color* col);
|
double colorGetValue(Color* col);
|
||||||
|
|
||||||
|
/* HDR profile for tone-mapping */
|
||||||
|
typedef struct ColorProfile ColorProfile;
|
||||||
|
|
||||||
|
ColorProfile* colorProfileCreate();
|
||||||
|
void colorProfileDelete(ColorProfile* profile);
|
||||||
|
|
||||||
|
void colorProfileSave(PackStream* stream, ColorProfile* profile);
|
||||||
|
void colorProfileLoad(PackStream* stream, ColorProfile* profile);
|
||||||
|
|
||||||
|
void colorProfileClear(ColorProfile* profile);
|
||||||
|
int colorProfileCollect(ColorProfile* profile, Color pixel);
|
||||||
|
Color colorProfileApply(ColorProfile* profile, Color pixel);
|
||||||
|
|
||||||
/* ColorGradation */
|
/* ColorGradation */
|
||||||
typedef struct ColorGradation ColorGradation;
|
typedef struct ColorGradation ColorGradation;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "renderer.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -95,7 +96,7 @@ void renderQuit()
|
||||||
RenderArea* renderCreateArea()
|
RenderArea* renderCreateArea()
|
||||||
{
|
{
|
||||||
RenderArea* result;
|
RenderArea* result;
|
||||||
|
|
||||||
result = malloc(sizeof(RenderArea));
|
result = malloc(sizeof(RenderArea));
|
||||||
result->params.width = 1;
|
result->params.width = 1;
|
||||||
result->params.height = 1;
|
result->params.height = 1;
|
||||||
|
@ -118,7 +119,7 @@ RenderArea* renderCreateArea()
|
||||||
result->callback_start = _callbackStart;
|
result->callback_start = _callbackStart;
|
||||||
result->callback_draw = _callbackDraw;
|
result->callback_draw = _callbackDraw;
|
||||||
result->callback_update = _callbackUpdate;
|
result->callback_update = _callbackUpdate;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +135,7 @@ void renderDeleteArea(RenderArea* area)
|
||||||
void renderSetParams(RenderArea* area, RenderParams params)
|
void renderSetParams(RenderArea* area, RenderParams params)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
width = params.width * params.antialias;
|
width = params.width * params.antialias;
|
||||||
height = params.height * params.antialias;
|
height = params.height * params.antialias;
|
||||||
|
|
||||||
|
@ -178,7 +179,7 @@ void renderClear(RenderArea* area)
|
||||||
RenderFragment* pixel;
|
RenderFragment* pixel;
|
||||||
int x;
|
int x;
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
area->fragment_callbacks_count = 1;
|
area->fragment_callbacks_count = 1;
|
||||||
area->fragment_callbacks[0].function = NULL;
|
area->fragment_callbacks[0].function = NULL;
|
||||||
area->fragment_callbacks[0].data = NULL;
|
area->fragment_callbacks[0].data = NULL;
|
||||||
|
@ -237,7 +238,7 @@ static inline Color _getFinalPixel(RenderArea* area, int x, int y)
|
||||||
Color result, col;
|
Color result, col;
|
||||||
int sx, sy;
|
int sx, sy;
|
||||||
RenderFragment* pixel_data;
|
RenderFragment* pixel_data;
|
||||||
|
|
||||||
result.r = result.g = result.b = 0.0;
|
result.r = result.g = result.b = 0.0;
|
||||||
result.a = 1.0;
|
result.a = 1.0;
|
||||||
for (sx = 0; sx < area->params.antialias; sx++)
|
for (sx = 0; sx < area->params.antialias; sx++)
|
||||||
|
@ -267,7 +268,7 @@ static inline Color _getFinalPixel(RenderArea* area, int x, int y)
|
||||||
result.b += col.b / (double)(area->params.antialias * area->params.antialias);
|
result.b += col.b / (double)(area->params.antialias * area->params.antialias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +276,7 @@ static void _processDirtyPixels(RenderArea* area)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
int down, up, left, right;
|
int down, up, left, right;
|
||||||
|
|
||||||
down = area->dirty_down / area->params.antialias;
|
down = area->dirty_down / area->params.antialias;
|
||||||
up = area->dirty_up / area->params.antialias;
|
up = area->dirty_up / area->params.antialias;
|
||||||
left = area->dirty_left / area->params.antialias;
|
left = area->dirty_left / area->params.antialias;
|
||||||
|
@ -323,7 +324,7 @@ static inline unsigned int _pushCallback(RenderArea* area, FragmentCallback call
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area->fragment_callbacks_count >= 64)
|
if (area->fragment_callbacks_count >= 64)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -339,7 +340,7 @@ static inline unsigned int _pushCallback(RenderArea* area, FragmentCallback call
|
||||||
static void _pushFragment(RenderArea* area, int x, int y, double z, int edge, Vector3 location, int callback)
|
static void _pushFragment(RenderArea* area, int x, int y, double z, int edge, Vector3 location, int callback)
|
||||||
{
|
{
|
||||||
RenderFragment* pixel_data;
|
RenderFragment* pixel_data;
|
||||||
|
|
||||||
if (x >= 0 && x < area->params.width * area->params.antialias && y >= 0 && y < area->params.height * area->params.antialias && z > 1.0)
|
if (x >= 0 && x < area->params.width * area->params.antialias && y >= 0 && y < area->params.height * area->params.antialias && z > 1.0)
|
||||||
{
|
{
|
||||||
pixel_data = area->pixels + (y * area->params.width * area->params.antialias + x);
|
pixel_data = area->pixels + (y * area->params.width * area->params.antialias + x);
|
||||||
|
@ -382,7 +383,7 @@ static void _pushScanPoint(RenderArea* area, ScanPoint* point)
|
||||||
{
|
{
|
||||||
point->x = (int)floor(point->pixel.x);
|
point->x = (int)floor(point->pixel.x);
|
||||||
point->y = (int)floor(point->pixel.y);
|
point->y = (int)floor(point->pixel.y);
|
||||||
|
|
||||||
if (point->x < 0 || point->x >= area->params.width * area->params.antialias)
|
if (point->x < 0 || point->x >= area->params.width * area->params.antialias)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -466,7 +467,7 @@ static void _pushScanLineEdge(RenderArea* area, ScanPoint* point1, ScanPoint* po
|
||||||
_scanInterpolate(point1, &diff, fx / dx, &point);
|
_scanInterpolate(point1, &diff, fx / dx, &point);
|
||||||
|
|
||||||
/*point.pixel.x = (double)curx;*/
|
/*point.pixel.x = (double)curx;*/
|
||||||
|
|
||||||
_pushScanPoint(area, &point);
|
_pushScanPoint(area, &point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,7 +542,7 @@ void renderPushTriangle(RenderArea* area, Vector3 pixel1, Vector3 pixel2, Vector
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
point1.pixel = pixel1;
|
point1.pixel = pixel1;
|
||||||
point1.location = location1;
|
point1.location = location1;
|
||||||
point1.callback = _pushCallback(area, fragment_callback);
|
point1.callback = _pushCallback(area, fragment_callback);
|
||||||
|
@ -553,13 +554,13 @@ void renderPushTriangle(RenderArea* area, Vector3 pixel1, Vector3 pixel2, Vector
|
||||||
point3.pixel = pixel3;
|
point3.pixel = pixel3;
|
||||||
point3.location = location3;
|
point3.location = location3;
|
||||||
point3.callback = _pushCallback(area, fragment_callback);
|
point3.callback = _pushCallback(area, fragment_callback);
|
||||||
|
|
||||||
_clearScanLines(area);
|
_clearScanLines(area);
|
||||||
|
|
||||||
_pushScanLineEdge(area, &point1, &point2);
|
_pushScanLineEdge(area, &point1, &point2);
|
||||||
_pushScanLineEdge(area, &point2, &point3);
|
_pushScanLineEdge(area, &point2, &point3);
|
||||||
_pushScanLineEdge(area, &point3, &point1);
|
_pushScanLineEdge(area, &point3, &point1);
|
||||||
|
|
||||||
mutexAcquire(area->lock);
|
mutexAcquire(area->lock);
|
||||||
_renderScanLines(area);
|
_renderScanLines(area);
|
||||||
mutexRelease(area->lock);
|
mutexRelease(area->lock);
|
||||||
|
@ -584,18 +585,18 @@ void* _renderPostProcessChunk(void* data)
|
||||||
{
|
{
|
||||||
FragmentCallback callback;
|
FragmentCallback callback;
|
||||||
Color col;
|
Color col;
|
||||||
|
|
||||||
callback = chunk->area->fragment_callbacks[fragment->flags.callback];
|
callback = chunk->area->fragment_callbacks[fragment->flags.callback];
|
||||||
if (callback.function)
|
if (callback.function)
|
||||||
{
|
{
|
||||||
col = callback.function(chunk->renderer, fragment->data.location, callback.data);
|
col = callback.function(chunk->renderer, fragment->data.location, callback.data);
|
||||||
colorNormalize(&col);
|
/*colorNormalize(&col);*/
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
col = COLOR_BLACK;
|
col = COLOR_BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment->data.color.r = col.r;
|
fragment->data.color.r = col.r;
|
||||||
fragment->data.color.g = col.g;
|
fragment->data.color.g = col.g;
|
||||||
fragment->data.color.b = col.b;
|
fragment->data.color.b = col.b;
|
||||||
|
|
|
@ -3,12 +3,25 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "renderer.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*RenderCallbackStart)(int width, int height, Color background);
|
||||||
|
typedef void (*RenderCallbackDraw)(int x, int y, Color col);
|
||||||
|
typedef void (*RenderCallbackUpdate)(double progress);
|
||||||
|
|
||||||
|
typedef struct RenderArea RenderArea;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int antialias;
|
||||||
|
int quality;
|
||||||
|
} RenderParams;
|
||||||
|
|
||||||
void renderInit();
|
void renderInit();
|
||||||
void renderQuit();
|
void renderQuit();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "shared/types.h"
|
#include "shared/types.h"
|
||||||
#include "atmosphere/public.h"
|
#include "atmosphere/public.h"
|
||||||
#include "terrain/public.h"
|
#include "terrain/public.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -15,14 +15,6 @@ typedef struct LightStatus LightStatus;
|
||||||
|
|
||||||
typedef Color (*f_RenderFragmentCallback)(struct Renderer* renderer, Vector3 location, void* data);
|
typedef Color (*f_RenderFragmentCallback)(struct Renderer* renderer, Vector3 location, void* data);
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int antialias;
|
|
||||||
int quality;
|
|
||||||
} RenderParams;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
@ -39,12 +31,6 @@ typedef struct
|
||||||
double shininess;
|
double shininess;
|
||||||
} SurfaceMaterial;
|
} SurfaceMaterial;
|
||||||
|
|
||||||
typedef void (*RenderCallbackStart)(int width, int height, Color background);
|
|
||||||
typedef void (*RenderCallbackDraw)(int x, int y, Color col);
|
|
||||||
typedef void (*RenderCallbackUpdate)(double progress);
|
|
||||||
|
|
||||||
typedef struct RenderArea RenderArea;
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int hit;
|
int hit;
|
||||||
|
|
Loading…
Reference in a new issue