Switch to HSL color space for material definition

This commit is contained in:
Michaël Lemaire 2013-09-18 17:10:34 +02:00
parent 7cd74b2c8a
commit c6be386a59
17 changed files with 254 additions and 103 deletions

View file

@ -17,18 +17,21 @@ preview_lighted(&edited)
form_helper->addPreview(ui->preview_lighted, &preview_lighted);
form_helper->addDoubleInputSlider(ui->slider_hue, &edited.hue);
form_helper->addDoubleInputSlider(ui->slider_diffuse, &edited.diffuse);
form_helper->addDoubleInputSlider(ui->slider_hue, &edited.base.h);
form_helper->addDoubleInputSlider(ui->slider_lightness, &edited.base.l);
form_helper->addDoubleInputSlider(ui->slider_saturation, &edited.base.s);
form_helper->addDoubleInputSlider(ui->slider_hardness, &edited.hardness);
form_helper->addDoubleInputSlider(ui->slider_reflection, &edited.reflection);
form_helper->addDoubleInputSlider(ui->slider_specularity, &edited.shininess);
form_helper->addDoubleInputSlider(ui->slider_receive_shadows, &edited.receive_shadows);
form_helper->setRevertButton(ui->button_revert);
form_helper->startManaging();
ui->preview_color->setColor(&edited.base);
ui->preview_color->setColor(&edited._rgb);
connect(ui->button_apply, SIGNAL(clicked()), this, SLOT(accept()));
connect(ui->button_cancel, SIGNAL(clicked()), this, SLOT(reject()));
@ -48,6 +51,7 @@ bool DialogMaterialEditor::getMaterial(QWidget* parent, SurfaceMaterial* materia
void DialogMaterialEditor::refreshFromLocalData()
{
materialValidate(&edited);
ui->preview_color->update();
}

View file

@ -9,7 +9,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>1090</width>
<width>1091</width>
<height>627</height>
</rect>
</property>
@ -58,34 +58,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="diffuseFactorLabel">
<property name="text">
<string>Diffuse factor</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="hardnessToLightLabel">
<property name="text">
<string>Hardness to light</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="WidgetSliderDecimal" name="slider_diffuse">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="WidgetSliderDecimal" name="slider_hardness">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
@ -121,6 +93,48 @@
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="diffuseFactorLabel">
<property name="text">
<string>Colorfulness (saturation)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="WidgetSliderDecimal" name="slider_saturation">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="diffuseFactorLabel_2">
<property name="text">
<string>Diffuse factor (lightness)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="WidgetSliderDecimal" name="slider_lightness">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="hardnessToLightLabel">
<property name="text">
<string>Hardness to light</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="WidgetSliderDecimal" name="slider_hardness">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View file

@ -10,5 +10,17 @@ SmallPreviewHues::SmallPreviewHues(QWidget* parent) : DrawingWidget(parent)
void SmallPreviewHues::doDrawing(QPainter* painter)
{
painter->fillRect(rect(), Qt::blue);
int x;
ColorHSL colhsl;
colhsl.s = 1.0;
colhsl.l = 0.5;
colhsl.a = 1.0;
for (x = 0; x < width(); x++)
{
colhsl.h = (double)x / (double)(width() - 1);
painter->setPen(colorToQColor(colorFromHSL(colhsl)));
painter->drawLine(x, 0, x, height() - 1);
}
}

View file

@ -414,7 +414,7 @@ void WidgetExplorer::paintGL()
// Render water
double water_height = _renderer->terrain->getWaterHeight(_renderer);
glDisable(GL_TEXTURE_2D);
glColor3f(water->material.base.r, water->material.base.g, water->material.base.b);
glColor3f(water->material._rgb.r, water->material._rgb.g, water->material._rgb.b);
glBegin(GL_QUADS);
glVertex3f(camera_location.x - 500.0, water_height, camera_location.z - 500.0);
glVertex3f(camera_location.x - 500.0, water_height, camera_location.z + 500.0);

View file

@ -117,6 +117,8 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
noiseNormalizeAmplitude(definition->_coverage_noise, -1.0, 3.0, 0);
noiseNormalizeAmplitude(definition->_shape_noise, -0.5, 0.5, 0);
noiseNormalizeAmplitude(definition->_edge_noise, -0.5, 0.5, 0);
materialValidate(&definition->material);
}
CloudsLayerDefinition* cloudsLayerCreateDefinition()

View file

@ -26,10 +26,7 @@ void cloudsLayerAutoPreset(CloudsLayerDefinition* definition, CloudsLayerPreset
noiseRandomizeOffsets(definition->_edge_noise);
noiseRandomizeOffsets(definition->_shape_noise);
definition->material.base.r = 0.7;
definition->material.base.g = 0.7;
definition->material.base.b = 0.7;
definition->material.base.a = 1.0;
definition->material.base = colorToHSL(colorFromValues(0.7, 0.7, 0.7, 1.0));
switch (preset)
{

View file

@ -3,6 +3,7 @@
#include <time.h>
#include "tools/color.h"
#include "tools/euclid.h"
#include "terrain/ter_raster.h"
#include "render.h"
#include "system.h"

View file

@ -61,7 +61,7 @@ Renderer* terrainCreatePreviewRenderer()
textures = TexturesDefinitionClass.create();
TexturesLayerDefinition* layer = layersGetLayer(textures->layers, layersAddLayer(textures->layers, NULL));
layer->displacement_height = 0.0;
layer->material.base = COLOR_WHITE;
layer->material.base = colorToHSL(COLOR_WHITE);
layer->material.reflection = 0.05;
layer->material.shininess = 2.0;
noiseClearLevels(layer->_detail_noise);

View file

@ -65,6 +65,8 @@ static void _layerValidateDefinition(TexturesLayerDefinition* definition)
noiseAddLevelsSimple(definition->_detail_noise, 7, 0.01, -1.0, 1.0, 0.0);
noiseNormalizeAmplitude(definition->_detail_noise, -0.008, 0.008, 0);
noiseValidate(definition->_detail_noise);
materialValidate(&definition->material);
}
static TexturesLayerDefinition* _layerCreateDefinition()

View file

@ -44,9 +44,7 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP
definition->displacement_height = 0.3;
definition->displacement_scaling = 2.0;
definition->displacement_offset = 0.0;
definition->material.base.r = 0.6;
definition->material.base.g = 0.55;
definition->material.base.b = 0.57;
definition->material.base = colorToHSL(colorFromValues(0.6, 0.55, 0.57, 1.0));
definition->material.reflection = 0.006;
definition->material.shininess = 6.0;
break;
@ -56,9 +54,7 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP
definition->displacement_height = 0.0;
definition->displacement_scaling = 1.0;
definition->displacement_offset = 0.0;
definition->material.base.r = 0.12;
definition->material.base.g = 0.19;
definition->material.base.b = 0.035;
definition->material.base = colorToHSL(colorFromValues(0.12, 0.19, 0.035, 1.0));
definition->material.reflection = 0.001;
definition->material.shininess = 4.0;
break;
@ -68,9 +64,7 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP
definition->displacement_height = 0.0;
definition->displacement_scaling = 1.0;
definition->displacement_offset = 0.0;
definition->material.base.r = 0.30;
definition->material.base.g = 0.28;
definition->material.base.b = 0.02;
definition->material.base = colorToHSL(colorFromValues(0.30, 0.28, 0.02, 1.0));
definition->material.reflection = 0.008;
definition->material.shininess = 6.0;
break;
@ -80,9 +74,7 @@ void texturesLayerAutoPreset(TexturesLayerDefinition* definition, TexturesLayerP
definition->displacement_height = 0.0;
definition->displacement_scaling = 1.0;
definition->displacement_offset = 0.0;
definition->material.base.r = 1.0;
definition->material.base.g = 1.0;
definition->material.base.b = 1.0;
definition->material.base = colorToHSL(colorFromValues(1.0, 1.0, 1.0, 1.0));
definition->material.reflection = 0.25;
definition->material.shininess = 0.6;
break;

View file

@ -32,34 +32,46 @@ void colorLoad(PackStream* stream, Color* col)
packReadDouble(stream, &col->a);
}
Color colorFromValues(double r, double g, double b, double a)
{
Color result;
result.r = r;
result.g = g;
result.b = b;
result.a = a;
return result;
}
unsigned int colorTo32BitRGBA(Color* col)
{
return (((unsigned int)(col->a * 255.0)) << 24) | (((unsigned int)(col->b * 255.0)) << 16) | (((unsigned int)(col->g * 255.0)) << 8) | ((unsigned int)(col->r * 255.0));
return (((unsigned int) (col->a * 255.0)) << 24) | (((unsigned int) (col->b * 255.0)) << 16) | (((unsigned int) (col->g * 255.0)) << 8) | ((unsigned int) (col->r * 255.0));
}
unsigned int colorTo32BitBGRA(Color* col)
{
return (((unsigned int)(col->a * 255.0)) << 24) | (((unsigned int)(col->r * 255.0)) << 16) | (((unsigned int)(col->g * 255.0)) << 8) | ((unsigned int)(col->b * 255.0));
return (((unsigned int) (col->a * 255.0)) << 24) | (((unsigned int) (col->r * 255.0)) << 16) | (((unsigned int) (col->g * 255.0)) << 8) | ((unsigned int) (col->b * 255.0));
}
unsigned int colorTo32BitARGB(Color* col)
{
return (((unsigned int)(col->b * 255.0)) << 24) | (((unsigned int)(col->g * 255.0)) << 16) | (((unsigned int)(col->r * 255.0)) << 8) | ((unsigned int)(col->a * 255.0));
return (((unsigned int) (col->b * 255.0)) << 24) | (((unsigned int) (col->g * 255.0)) << 16) | (((unsigned int) (col->r * 255.0)) << 8) | ((unsigned int) (col->a * 255.0));
}
unsigned int colorTo32BitABGR(Color* col)
{
return (((unsigned int)(col->r * 255.0)) << 24) | (((unsigned int)(col->g * 255.0)) << 16) | (((unsigned int)(col->b * 255.0)) << 8) | ((unsigned int)(col->a * 255.0));
return (((unsigned int) (col->r * 255.0)) << 24) | (((unsigned int) (col->g * 255.0)) << 16) | (((unsigned int) (col->b * 255.0)) << 8) | ((unsigned int) (col->a * 255.0));
}
Color colorFrom32BitRGBA(unsigned int col)
{
Color result;
result.r = ((double)(col & 0x000000FF)) / 255.0;
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
result.b = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
result.r = ((double) (col & 0x000000FF)) / 255.0;
result.g = ((double) ((col & 0x0000FF00) >> 8)) / 255.0;
result.b = ((double) ((col & 0x00FF0000) >> 16)) / 255.0;
result.a = ((double) ((col & 0xFF000000) >> 24)) / 255.0;
return result;
}
@ -68,10 +80,10 @@ Color colorFrom32BitBGRA(unsigned int col)
{
Color result;
result.b = ((double)(col & 0x000000FF)) / 255.0;
result.g = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
result.r = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
result.a = ((double)((col & 0xFF000000) >> 24)) / 255.0;
result.b = ((double) (col & 0x000000FF)) / 255.0;
result.g = ((double) ((col & 0x0000FF00) >> 8)) / 255.0;
result.r = ((double) ((col & 0x00FF0000) >> 16)) / 255.0;
result.a = ((double) ((col & 0xFF000000) >> 24)) / 255.0;
return result;
}
@ -80,10 +92,10 @@ Color colorFrom32BitARGB(unsigned int col)
{
Color result;
result.a = ((double)(col & 0x000000FF)) / 255.0;
result.r = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
result.b = ((double)((col & 0xFF000000) >> 24)) / 255.0;
result.a = ((double) (col & 0x000000FF)) / 255.0;
result.r = ((double) ((col & 0x0000FF00) >> 8)) / 255.0;
result.g = ((double) ((col & 0x00FF0000) >> 16)) / 255.0;
result.b = ((double) ((col & 0xFF000000) >> 24)) / 255.0;
return result;
}
@ -92,10 +104,10 @@ Color colorFrom32BitABGR(unsigned int col)
{
Color result;
result.a = ((double)(col & 0x000000FF)) / 255.0;
result.b = ((double)((col & 0x0000FF00) >> 8)) / 255.0;
result.g = ((double)((col & 0x00FF0000) >> 16)) / 255.0;
result.r = ((double)((col & 0xFF000000) >> 24)) / 255.0;
result.a = ((double) (col & 0x000000FF)) / 255.0;
result.b = ((double) ((col & 0x0000FF00) >> 8)) / 255.0;
result.g = ((double) ((col & 0x00FF0000) >> 16)) / 255.0;
result.r = ((double) ((col & 0xFF000000) >> 24)) / 255.0;
return result;
}
@ -203,7 +215,7 @@ struct ColorProfile
{
double minvalue;
double maxvalue;
Color (*mapper)(Color col, double exposure);
Color(*mapper)(Color col, double exposure);
double exposure;
};
@ -211,7 +223,7 @@ ColorProfile* colorProfileCreate()
{
ColorProfile* profile;
profile = malloc(sizeof(ColorProfile));
profile = malloc(sizeof (ColorProfile));
colorProfileSetToneMapping(profile, TONE_MAPPING_UNCHARTED, 2.0);
colorProfileClear(profile);
@ -233,7 +245,7 @@ static inline double _uncharted2Tonemap(double x)
double E = 0.02;
double F = 0.30;
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
}
static Color _toneMappingUncharted(Color pixel, double exposure)
@ -335,7 +347,7 @@ ColorGradation* colorGradationCreate()
{
ColorGradation* result;
result = malloc(sizeof(ColorGradation));
result = malloc(sizeof (ColorGradation));
result->red = curveCreate();
result->green = curveCreate();
result->blue = curveCreate();
@ -441,3 +453,88 @@ Color colorGradationGet(ColorGradation* gradation, double value)
return result;
}
/******************************** HSL Color Space ********************************/
static double _hue2rgb(double p, double q, double t)
{
if (t < 0.0) t += 1;
if (t > 1.0) t -= 1;
if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;
if (t < 1.0 / 2.0) return q;
if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
return p;
}
Color colorFromHSL(ColorHSL col)
{
Color result;
if (col.s == 0)
{
result.r = result.g = result.b = col.l;
}
else
{
double q = col.l < 0.5 ? col.l * (1.0 + col.s) : col.l + col.s - col.l * col.s;
double p = 2 * col.l - q;
result.r = _hue2rgb(p, q, col.h + 1.0 / 3.0);
result.g = _hue2rgb(p, q, col.h);
result.b = _hue2rgb(p, q, col.h - 1.0 / 3.0);
}
result.a = col.a;
return result;
}
ColorHSL colorToHSL(Color col)
{
ColorHSL result;
double min, max;
max = col.r > col.g ? col.r : col.g;
max = col.b > max ? col.b : max;
min = col.r < col.g ? col.r : col.g;
min = col.b < min ? col.b : min;
result.h = result.s = result.l = (max + min) / 2.0;
if (max == min)
{
result.h = result.s = 0.0;
}
else
{
double d = max - min;
result.s = result.l > 0.5 ? d / (2.0 - max - min) : d / (max + min);
if (max == col.r)
{
result.h = (col.g - col.b) / d + (col.g < col.b ? 6.0 : 0);
}
else if (max == col.g)
{
result.h = (col.b - col.r) / d + 2.0;
}
else
{
result.h = (col.r - col.g) / d + 4.0;
}
result.h /= 6.0;
}
result.a = col.a;
return result;
}
ColorHSL colorHSLFromValues(double h, double s, double l, double a)
{
ColorHSL result;
result.h = h;
result.s = s;
result.l = l;
result.a = a;
return result;
}

View file

@ -27,6 +27,7 @@ extern Color COLOR_GREY;
/* Color */
void colorSave(PackStream* stream, Color* col);
void colorLoad(PackStream* stream, Color* col);
Color colorFromValues(double r, double g, double b, double a);
unsigned int colorTo32BitRGBA(Color* col);
unsigned int colorTo32BitBGRA(Color* col);
@ -90,6 +91,20 @@ void colorGradationQuickAddRgb(ColorGradation* gradation, double value, double r
Color colorGradationGet(ColorGradation* gradation, double value);
/* HSL color space */
typedef struct
{
double h;
double s;
double l;
double a;
} ColorHSL;
Color colorFromHSL(ColorHSL col);
ColorHSL colorToHSL(Color col);
ColorHSL colorHSLFromValues(double h, double s, double l, double a);
#ifdef __cplusplus
}
#endif

View file

@ -162,9 +162,9 @@ Color lightingApplyOneLight(LightDefinition* light, Vector3 eye, Vector3 locatio
diffuse = (diffuse + (1.0 - normal_norm)) / (1.0 + (1.0 - normal_norm));
if (diffuse > 0.0)
{
result.r += diffuse * material->base.r * light_color.r;
result.g += diffuse * material->base.g * light_color.g;
result.b += diffuse * material->base.b * light_color.b;
result.r += diffuse * material->_rgb.r * light_color.r;
result.g += diffuse * material->_rgb.g * light_color.g;
result.b += diffuse * material->_rgb.b * light_color.b;
}
/* specular reflection */
@ -215,14 +215,33 @@ Vector3 lightingGetStatusLocation(LightStatus* status)
void materialSave(PackStream* stream, SurfaceMaterial* material)
{
colorSave(stream, &material->base);
packWriteDouble(stream, &material->base.h);
packWriteDouble(stream, &material->base.l);
packWriteDouble(stream, &material->base.s);
packWriteDouble(stream, &material->hardness);
packWriteDouble(stream, &material->reflection);
packWriteDouble(stream, &material->shininess);
packWriteDouble(stream, &material->receive_shadows);
}
void materialLoad(PackStream* stream, SurfaceMaterial* material)
{
colorLoad(stream, &material->base);
packReadDouble(stream, &material->base.h);
packReadDouble(stream, &material->base.l);
packReadDouble(stream, &material->base.s);
packReadDouble(stream, &material->hardness);
packReadDouble(stream, &material->reflection);
packReadDouble(stream, &material->shininess);
packReadDouble(stream, &material->receive_shadows);
materialValidate(material);
}
void materialValidate(SurfaceMaterial* material)
{
material->_rgb = colorFromHSL(material->base);
}

View file

@ -11,16 +11,15 @@ extern "C" {
typedef struct
{
double hue;
double diffuse;
double hardness;
ColorHSL base;
double hardness;
double reflection;
double shininess;
double receive_shadows;
Color base;
Color _rgb;
} SurfaceMaterial;
typedef struct
@ -51,6 +50,7 @@ Color lightingApplyOneLight(LightDefinition* light, Vector3 eye, Vector3 locatio
void materialSave(PackStream* stream, SurfaceMaterial* material);
void materialLoad(PackStream* stream, SurfaceMaterial* material);
void materialValidate(SurfaceMaterial* material);
#ifdef __cplusplus
}

View file

@ -16,6 +16,9 @@ static void _validateDefinition(WaterDefinition* definition)
}
noiseSetFunctionParams(definition->_waves_noise, NOISE_FUNCTION_SIMPLEX, -definition->turbulence, 0.0);
noiseValidate(definition->_waves_noise);
materialValidate(&definition->material);
materialValidate(&definition->foam_material);
}
static WaterDefinition* _createDefinition()

View file

@ -9,9 +9,7 @@ void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
definition->transparency = 0.5;
definition->reflection = 0.4;
definition->transparency_depth = 4.0;
definition->material.base.r = 0.08;
definition->material.base.g = 0.15;
definition->material.base.b = 0.2;
definition->material.base = colorToHSL(colorFromValues(0.08, 0.15, 0.2, 1.0));
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.1;
definition->depth_color.b = 0.1;
@ -27,9 +25,7 @@ void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
definition->transparency = 0.4;
definition->reflection = 0.35;
definition->transparency_depth = 3.0;
definition->material.base.r = 0.05;
definition->material.base.g = 0.18;
definition->material.base.b = 0.2;
definition->material.base = colorToHSL(colorFromValues(0.05, 0.18, 0.2, 1.0));
definition->depth_color.r = 0.0;
definition->depth_color.g = 0.18;
definition->depth_color.b = 0.15;
@ -45,10 +41,7 @@ void waterAutoPreset(WaterDefinition* definition, WaterPreset preset)
definition->material.base.a = 1.0;
definition->material.reflection = 1.0;
definition->material.shininess = 16.0;
definition->foam_material.base.r = 0.8;
definition->foam_material.base.g = 0.8;
definition->foam_material.base.b = 0.8;
definition->foam_material.base.a = 1.0;
definition->foam_material.base = colorToHSL(colorFromValues(0.8, 0.8, 0.8, 1.0));
definition->foam_material.reflection = 0.1;
definition->foam_material.shininess = 1.5;

View file

@ -291,7 +291,7 @@ static WaterResult _realGetResult(Renderer* renderer, double x, double z)
/* Bring color to the camera */
color = renderer->applyMediumTraversal(renderer, location, color);
result.base = definition->material.base;
result.base = definition->material._rgb;
result.final = color;
return result;