From cb929bcd8716187c4a592f58429848473c206309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 10 Jun 2012 09:30:30 +0000 Subject: [PATCH] paysages : New cloud model with two noises (base shape and edge). git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@345 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- ChangeLog | 1 + TODO | 2 + gui_qt/formclouds.cpp | 15 +++--- i18n/paysages_fr.ts | 57 ++++++++++++++------ lib_paysages/clouds.c | 123 +++++++++++++++++++++++++----------------- lib_paysages/clouds.h | 13 +++-- 6 files changed, 137 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9bb81b6..4d99d30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,7 @@ Previews : Scenery : * Added clouds hardness to light. * Added sun halo control. + * New cloud model with 2 noises : one for the global shape and one for edges. Rendering : * New texture model (perpendicular displacement and thickness). diff --git a/TODO b/TODO index 71ae6e5..e0aaa6b 100644 --- a/TODO +++ b/TODO @@ -3,6 +3,7 @@ Technology Preview 2 : - Remove color gradations (replace with automatic boolean and simple colors). - Replace zone ranges with curves (with curve input and curve dialog). - Interface for textures thickness, slope_range and thickness_transparency (and correct slider ranges). +- Add "hardness to light" and shadow control ("minimum lighting") to material. - Render tab previews should not rerender when changing render options. - Add layer sorting/naming. - Disable specular lighting in explorer (and everything camera dependent). @@ -14,6 +15,7 @@ Technology Preview 2 : - Use the curve editor in noise editor - Add a noise filler (and maybe noise intervals ?). - Add a popup when rendering is complete (with stats), except for quick render. +- Optimize the use of noiseGetMaxValue (limit its use or cache it). - Fix the distorted sun appearance. - Improve curve editor. => Add curve modes diff --git a/gui_qt/formclouds.cpp b/gui_qt/formclouds.cpp index ec568e1..12dead1 100644 --- a/gui_qt/formclouds.cpp +++ b/gui_qt/formclouds.cpp @@ -112,8 +112,8 @@ protected: cloudsLayerCopyDefinition(&_layer, &_preview_layer); _preview_layer.ymax = (_preview_layer.ymax - _preview_layer.ymin) / 2.0; _preview_layer.ymin = -_preview_layer.ymin; - curveClear(_preview_layer.density_altitude); - _preview_layer.customcoverage = _coverageFunc; + curveClear(_preview_layer.coverage_by_altitude); + _preview_layer._custom_coverage = _coverageFunc; } private: Renderer _renderer; @@ -157,10 +157,13 @@ FormClouds::FormClouds(QWidget *parent): addInputDouble(tr("Lower altitude"), &_layer.ymin, -10.0, 50.0, 0.5, 5.0); addInputDouble(tr("Upper altitude"), &_layer.ymax, -10.0, 50.0, 0.5, 5.0); - addInputCurve(tr("Density by altitude"), _layer.density_altitude, 0.0, 1.0, 0.0, 1.0); - addInputNoise(tr("Noise"), _layer.noise); - addInputDouble(tr("Coverage"), &_layer.coverage, 0.0, 1.0, 0.01, 0.1); - addInputDouble(tr("Scaling"), &_layer.scaling, 1.0, 100.0, 0.5, 5.0); + addInputDouble(tr("Max coverage"), &_layer.base_coverage, 0.0, 1.0, 0.01, 0.1); + addInputCurve(tr("Coverage by altitude"), _layer.coverage_by_altitude, 0.0, 1.0, 0.0, 1.0); + addInputNoise(tr("Shape noise"), _layer.shape_noise); + addInputDouble(tr("Shape scaling"), &_layer.shape_scaling, 1.0, 10.0, 0.1, 1.0); + addInputNoise(tr("Edge noise"), _layer.edge_noise); + addInputDouble(tr("Edge scaling"), &_layer.edge_scaling, 0.02, 0.5, 0.01, 0.1); + addInputDouble(tr("Edge length"), &_layer.edge_length, 0.0, 1.0, 0.01, 0.1); addInputMaterial(tr("Material"), &_layer.material); addInputDouble(tr("Hardness to light"), &_layer.hardness, 0.0, 1.0, 0.01, 0.1); addInputDouble(tr("Transparency depth"), &_layer.transparencydepth, 0.0, 100.0, 0.5, 5.0); diff --git a/i18n/paysages_fr.ts b/i18n/paysages_fr.ts index e9ba179..362cce1 100644 --- a/i18n/paysages_fr.ts +++ b/i18n/paysages_fr.ts @@ -374,27 +374,19 @@ Maintenir Ctrl : Plus rapide - - Density by altitude - - - - Noise - Bruit + Bruit - Coverage - Couverture + Couverture - Scaling - Echelle + Echelle - + Material @@ -410,23 +402,58 @@ Maintenir Ctrl : Plus rapide Light reflection shininess Concentration de la réflexion de lumière + + + Max coverage + + + + + Coverage by altitude + + + + + Shape noise + + + + + Shape scaling + + + + + Edge noise + + - Hardness to light + Edge scaling + Edge length + + + + + Hardness to light + + + + Transparency depth Distance de transparence - + Light traversal depth Distance de traversée de la lumière - + Minimum lighting Eclairage minimal diff --git a/lib_paysages/clouds.c b/lib_paysages/clouds.c index 5232e30..fe97ab7 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -41,15 +41,18 @@ void cloudsSave(PackStream* stream, CloudsDefinition* definition) packWriteDouble(stream, &layer->ymin); packWriteDouble(stream, &layer->ymax); - curveSave(stream, layer->density_altitude); - noiseSaveGenerator(stream, layer->noise); + curveSave(stream, layer->coverage_by_altitude); + noiseSaveGenerator(stream, layer->shape_noise); + noiseSaveGenerator(stream, layer->edge_noise); materialSave(stream, &layer->material); packWriteDouble(stream, &layer->hardness); packWriteDouble(stream, &layer->transparencydepth); packWriteDouble(stream, &layer->lighttraversal); packWriteDouble(stream, &layer->minimumlight); - packWriteDouble(stream, &layer->scaling); - packWriteDouble(stream, &layer->coverage); + packWriteDouble(stream, &layer->shape_scaling); + packWriteDouble(stream, &layer->edge_scaling); + packWriteDouble(stream, &layer->edge_length); + packWriteDouble(stream, &layer->base_coverage); } } @@ -70,15 +73,18 @@ void cloudsLoad(PackStream* stream, CloudsDefinition* definition) packReadDouble(stream, &layer->ymin); packReadDouble(stream, &layer->ymax); - curveLoad(stream, layer->density_altitude); - noiseLoadGenerator(stream, layer->noise); + curveLoad(stream, layer->coverage_by_altitude); + noiseLoadGenerator(stream, layer->shape_noise); + noiseLoadGenerator(stream, layer->edge_noise); materialLoad(stream, &layer->material); packReadDouble(stream, &layer->hardness); packReadDouble(stream, &layer->transparencydepth); packReadDouble(stream, &layer->lighttraversal); packReadDouble(stream, &layer->minimumlight); - packReadDouble(stream, &layer->scaling); - packReadDouble(stream, &layer->coverage); + packReadDouble(stream, &layer->shape_scaling); + packReadDouble(stream, &layer->edge_scaling); + packReadDouble(stream, &layer->edge_length); + packReadDouble(stream, &layer->base_coverage); } } @@ -132,7 +138,7 @@ static double _standardCoverageFunc(CloudsLayerDefinition* layer, Vector3 positi } else { - return layer->coverage * curveGetValue(layer->density_altitude, (position.y - layer->ymin) / (layer->ymax - layer->ymin)); + return layer->base_coverage * curveGetValue(layer->coverage_by_altitude, (position.y - layer->ymin) / (layer->ymax - layer->ymin)); } } @@ -142,11 +148,11 @@ CloudsLayerDefinition cloudsLayerCreateDefinition() result.ymin = 4.0; result.ymax = 10.0; - result.density_altitude = curveCreate(); - curveQuickAddPoint(result.density_altitude, 0.0, 0.0); - curveQuickAddPoint(result.density_altitude, 0.3, 1.0); - curveQuickAddPoint(result.density_altitude, 0.5, 1.0); - curveQuickAddPoint(result.density_altitude, 1.0, 0.0); + result.coverage_by_altitude = curveCreate(); + curveQuickAddPoint(result.coverage_by_altitude, 0.0, 0.0); + curveQuickAddPoint(result.coverage_by_altitude, 0.3, 1.0); + curveQuickAddPoint(result.coverage_by_altitude, 0.5, 1.0); + curveQuickAddPoint(result.coverage_by_altitude, 1.0, 0.0); result.material.base.r = 0.7; result.material.base.g = 0.7; result.material.base.b = 0.7; @@ -157,33 +163,25 @@ CloudsLayerDefinition cloudsLayerCreateDefinition() result.transparencydepth = 1.5; result.lighttraversal = 7.0; result.minimumlight = 0.4; - result.scaling = 3.5; - result.coverage = 0.45; - result.noise = noiseCreateGenerator(); - noiseGenerateBaseNoise(result.noise, 262144); - noiseAddLevelSimple(result.noise, 1.0, 1.0); - noiseAddLevelSimple(result.noise, 1.0 / 2.0, 0.6); - noiseAddLevelSimple(result.noise, 1.0 / 4.0, 0.3); - noiseAddLevelSimple(result.noise, 1.0 / 10.0, 0.15); - noiseAddLevelSimple(result.noise, 1.0 / 20.0, 0.09); - noiseAddLevelSimple(result.noise, 1.0 / 40.0, 0.06); - noiseAddLevelSimple(result.noise, 1.0 / 60.0, 0.03); - noiseAddLevelSimple(result.noise, 1.0 / 80.0, 0.015); - noiseAddLevelSimple(result.noise, 1.0 / 100.0, 0.06); - noiseAddLevelSimple(result.noise, 1.0 / 150.0, 0.015); - noiseAddLevelSimple(result.noise, 1.0 / 200.0, 0.009); - noiseAddLevelSimple(result.noise, 1.0 / 400.0, 0.024); - noiseAddLevelSimple(result.noise, 1.0 / 800.0, 0.003); - noiseAddLevelSimple(result.noise, 1.0 / 1000.0, 0.0015); + result.shape_scaling = 3.5; + result.edge_scaling = 0.1; + result.edge_length = 0.25; + result.base_coverage = 0.35; + result.shape_noise = noiseCreateGenerator(); + noiseGenerateBaseNoise(result.shape_noise, 20000); + noiseAddLevelsSimple(result.shape_noise, 4, 1.0, 1.0); + result.edge_noise = noiseCreateGenerator(); + noiseGenerateBaseNoise(result.edge_noise, 20000); + noiseAddLevelsSimple(result.edge_noise, 8, 1.0, 1.0); - result.customcoverage = _standardCoverageFunc; + result._custom_coverage = _standardCoverageFunc; return result; } void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition) { - noiseDeleteGenerator(definition->noise); + noiseDeleteGenerator(definition->shape_noise); } void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination) @@ -198,22 +196,29 @@ void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinit temp = *destination; *destination = *source; - destination->noise = temp.noise; - noiseCopy(source->noise, destination->noise); - - destination->density_altitude = temp.density_altitude; - curveCopy(source->density_altitude, destination->density_altitude); + destination->shape_noise = temp.shape_noise; + noiseCopy(source->shape_noise, destination->shape_noise); + + destination->edge_noise = temp.edge_noise; + noiseCopy(source->edge_noise, destination->edge_noise); + + destination->coverage_by_altitude = temp.coverage_by_altitude; + curveCopy(source->coverage_by_altitude, destination->coverage_by_altitude); } void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition) { - if (definition->scaling < 0.0001) + if (definition->shape_scaling < 0.0001) { - definition->scaling = 0.00001; + definition->shape_scaling = 0.00001; } - if (definition->customcoverage == NULL) + if (definition->edge_scaling < 0.0001) { - definition->customcoverage = _standardCoverageFunc; + definition->edge_scaling = 0.00001; + } + if (definition->_custom_coverage == NULL) + { + definition->_custom_coverage = _standardCoverageFunc; } } @@ -266,11 +271,33 @@ void cloudsDeleteLayer(CloudsDefinition* definition, int layer) static inline double _getDistanceToBorder(CloudsLayerDefinition* layer, Vector3 position) { - double val; + double density, coverage, val; - val = 0.5 * noiseGet3DTotal(layer->noise, position.x / layer->scaling, position.y / layer->scaling, position.z / layer->scaling) / noiseGetMaxValue(layer->noise); + val = noiseGet3DTotal(layer->shape_noise, position.x / layer->shape_scaling, position.y / layer->shape_scaling, position.z / layer->shape_scaling) / noiseGetMaxValue(layer->shape_noise); + coverage = layer->_custom_coverage(layer, position); + density = 0.5 * val - 0.5 + coverage; + + if (density <= 0.0) + { + /* outside the main shape */ + return density * layer->shape_scaling; + } + else + { + /* inside the main shape, using edge noise */ + density /= coverage; + if (density < layer->edge_length) + { + val = 0.5 * noiseGet3DTotal(layer->edge_noise, position.x / layer->edge_scaling, position.y / layer->edge_scaling, position.z / layer->edge_scaling) / noiseGetMaxValue(layer->edge_noise); + val = (val - 0.5 + density / layer->edge_length) * layer->edge_scaling; - return (val - 0.5 + layer->customcoverage(layer, position)) * layer->scaling; + return val; + } + else + { + return density * coverage * layer->shape_scaling; + } + } } static inline Vector3 _getNormal(CloudsLayerDefinition* layer, Vector3 position, double detail) @@ -404,7 +431,7 @@ static int _findSegments(CloudsLayerDefinition* definition, Renderer* renderer, } render_precision = 15.2 - 1.5 * (double)renderer->render_quality; - render_precision = render_precision * definition->scaling / 50.0; + render_precision = render_precision * definition->shape_scaling / 50.0; if (render_precision > max_total_length / 10.0) { render_precision = max_total_length / 10.0; @@ -532,7 +559,7 @@ Color cloudsGetLayerColor(CloudsLayerDefinition* definition, Renderer* renderer, direction = v3Normalize(direction); result = COLOR_TRANSPARENT; - detail = renderer->getPrecision(renderer, start) / definition->scaling; + detail = renderer->getPrecision(renderer, start) / definition->shape_scaling; segment_count = _findSegments(definition, renderer, start, direction, detail, 20, definition->transparencydepth, max_length, &inside_length, &total_length, segments); for (i = segment_count - 1; i >= 0; i--) diff --git a/lib_paysages/clouds.h b/lib_paysages/clouds.h index 26d7da7..44c8b7f 100644 --- a/lib_paysages/clouds.h +++ b/lib_paysages/clouds.h @@ -20,16 +20,19 @@ struct CloudsLayerDefinition { double ymin; double ymax; - Curve* density_altitude; - NoiseGenerator* noise; + double base_coverage; + Curve* coverage_by_altitude; + NoiseGenerator* shape_noise; + double shape_scaling; + NoiseGenerator* edge_noise; + double edge_scaling; + double edge_length; SurfaceMaterial material; double hardness; double transparencydepth; double lighttraversal; double minimumlight; - double scaling; - double coverage; - CloudCoverageFunc customcoverage; + CloudCoverageFunc _custom_coverage; }; typedef struct