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
This commit is contained in:
Michaël Lemaire 2012-06-10 09:30:30 +00:00 committed by ThunderK
parent 0a0fe193a5
commit cb929bcd87
6 changed files with 137 additions and 74 deletions

View file

@ -12,6 +12,7 @@ Previews :
Scenery : Scenery :
* Added clouds hardness to light. * Added clouds hardness to light.
* Added sun halo control. * Added sun halo control.
* New cloud model with 2 noises : one for the global shape and one for edges.
Rendering : Rendering :
* New texture model (perpendicular displacement and thickness). * New texture model (perpendicular displacement and thickness).

2
TODO
View file

@ -3,6 +3,7 @@ Technology Preview 2 :
- Remove color gradations (replace with automatic boolean and simple colors). - Remove color gradations (replace with automatic boolean and simple colors).
- Replace zone ranges with curves (with curve input and curve dialog). - Replace zone ranges with curves (with curve input and curve dialog).
- Interface for textures thickness, slope_range and thickness_transparency (and correct slider ranges). - 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. - Render tab previews should not rerender when changing render options.
- Add layer sorting/naming. - Add layer sorting/naming.
- Disable specular lighting in explorer (and everything camera dependent). - Disable specular lighting in explorer (and everything camera dependent).
@ -14,6 +15,7 @@ Technology Preview 2 :
- Use the curve editor in noise editor - Use the curve editor in noise editor
- Add a noise filler (and maybe noise intervals ?). - Add a noise filler (and maybe noise intervals ?).
- Add a popup when rendering is complete (with stats), except for quick render. - 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. - Fix the distorted sun appearance.
- Improve curve editor. - Improve curve editor.
=> Add curve modes => Add curve modes

View file

@ -112,8 +112,8 @@ protected:
cloudsLayerCopyDefinition(&_layer, &_preview_layer); cloudsLayerCopyDefinition(&_layer, &_preview_layer);
_preview_layer.ymax = (_preview_layer.ymax - _preview_layer.ymin) / 2.0; _preview_layer.ymax = (_preview_layer.ymax - _preview_layer.ymin) / 2.0;
_preview_layer.ymin = -_preview_layer.ymin; _preview_layer.ymin = -_preview_layer.ymin;
curveClear(_preview_layer.density_altitude); curveClear(_preview_layer.coverage_by_altitude);
_preview_layer.customcoverage = _coverageFunc; _preview_layer._custom_coverage = _coverageFunc;
} }
private: private:
Renderer _renderer; 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("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); 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); addInputDouble(tr("Max coverage"), &_layer.base_coverage, 0.0, 1.0, 0.01, 0.1);
addInputNoise(tr("Noise"), _layer.noise); addInputCurve(tr("Coverage by altitude"), _layer.coverage_by_altitude, 0.0, 1.0, 0.0, 1.0);
addInputDouble(tr("Coverage"), &_layer.coverage, 0.0, 1.0, 0.01, 0.1); addInputNoise(tr("Shape noise"), _layer.shape_noise);
addInputDouble(tr("Scaling"), &_layer.scaling, 1.0, 100.0, 0.5, 5.0); 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); addInputMaterial(tr("Material"), &_layer.material);
addInputDouble(tr("Hardness to light"), &_layer.hardness, 0.0, 1.0, 0.01, 0.1); 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); addInputDouble(tr("Transparency depth"), &_layer.transparencydepth, 0.0, 100.0, 0.5, 5.0);

View file

@ -374,27 +374,19 @@ Maintenir Ctrl : Plus rapide</translation>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="160"/>
<source>Density by altitude</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="161"/>
<source>Noise</source> <source>Noise</source>
<translation>Bruit</translation> <translation type="obsolete">Bruit</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="162"/>
<source>Coverage</source> <source>Coverage</source>
<translation>Couverture</translation> <translation type="obsolete">Couverture</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="163"/>
<source>Scaling</source> <source>Scaling</source>
<translation>Echelle</translation> <translation type="obsolete">Echelle</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="164"/> <location filename="../gui_qt/formclouds.cpp" line="167"/>
<source>Material</source> <source>Material</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -410,23 +402,58 @@ Maintenir Ctrl : Plus rapide</translation>
<source>Light reflection shininess</source> <source>Light reflection shininess</source>
<translation type="obsolete">Concentration de la réflexion de lumière</translation> <translation type="obsolete">Concentration de la réflexion de lumière</translation>
</message> </message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="160"/>
<source>Max coverage</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="161"/>
<source>Coverage by altitude</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="162"/>
<source>Shape noise</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="163"/>
<source>Shape scaling</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="164"/>
<source>Edge noise</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="165"/> <location filename="../gui_qt/formclouds.cpp" line="165"/>
<source>Hardness to light</source> <source>Edge scaling</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="166"/> <location filename="../gui_qt/formclouds.cpp" line="166"/>
<source>Edge length</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="168"/>
<source>Hardness to light</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="169"/>
<source>Transparency depth</source> <source>Transparency depth</source>
<translation>Distance de transparence</translation> <translation>Distance de transparence</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="167"/> <location filename="../gui_qt/formclouds.cpp" line="170"/>
<source>Light traversal depth</source> <source>Light traversal depth</source>
<translation>Distance de traversée de la lumière</translation> <translation>Distance de traversée de la lumière</translation>
</message> </message>
<message> <message>
<location filename="../gui_qt/formclouds.cpp" line="168"/> <location filename="../gui_qt/formclouds.cpp" line="171"/>
<source>Minimum lighting</source> <source>Minimum lighting</source>
<translation>Eclairage minimal</translation> <translation>Eclairage minimal</translation>
</message> </message>

View file

@ -41,15 +41,18 @@ void cloudsSave(PackStream* stream, CloudsDefinition* definition)
packWriteDouble(stream, &layer->ymin); packWriteDouble(stream, &layer->ymin);
packWriteDouble(stream, &layer->ymax); packWriteDouble(stream, &layer->ymax);
curveSave(stream, layer->density_altitude); curveSave(stream, layer->coverage_by_altitude);
noiseSaveGenerator(stream, layer->noise); noiseSaveGenerator(stream, layer->shape_noise);
noiseSaveGenerator(stream, layer->edge_noise);
materialSave(stream, &layer->material); materialSave(stream, &layer->material);
packWriteDouble(stream, &layer->hardness); packWriteDouble(stream, &layer->hardness);
packWriteDouble(stream, &layer->transparencydepth); packWriteDouble(stream, &layer->transparencydepth);
packWriteDouble(stream, &layer->lighttraversal); packWriteDouble(stream, &layer->lighttraversal);
packWriteDouble(stream, &layer->minimumlight); packWriteDouble(stream, &layer->minimumlight);
packWriteDouble(stream, &layer->scaling); packWriteDouble(stream, &layer->shape_scaling);
packWriteDouble(stream, &layer->coverage); 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->ymin);
packReadDouble(stream, &layer->ymax); packReadDouble(stream, &layer->ymax);
curveLoad(stream, layer->density_altitude); curveLoad(stream, layer->coverage_by_altitude);
noiseLoadGenerator(stream, layer->noise); noiseLoadGenerator(stream, layer->shape_noise);
noiseLoadGenerator(stream, layer->edge_noise);
materialLoad(stream, &layer->material); materialLoad(stream, &layer->material);
packReadDouble(stream, &layer->hardness); packReadDouble(stream, &layer->hardness);
packReadDouble(stream, &layer->transparencydepth); packReadDouble(stream, &layer->transparencydepth);
packReadDouble(stream, &layer->lighttraversal); packReadDouble(stream, &layer->lighttraversal);
packReadDouble(stream, &layer->minimumlight); packReadDouble(stream, &layer->minimumlight);
packReadDouble(stream, &layer->scaling); packReadDouble(stream, &layer->shape_scaling);
packReadDouble(stream, &layer->coverage); 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 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.ymin = 4.0;
result.ymax = 10.0; result.ymax = 10.0;
result.density_altitude = curveCreate(); result.coverage_by_altitude = curveCreate();
curveQuickAddPoint(result.density_altitude, 0.0, 0.0); curveQuickAddPoint(result.coverage_by_altitude, 0.0, 0.0);
curveQuickAddPoint(result.density_altitude, 0.3, 1.0); curveQuickAddPoint(result.coverage_by_altitude, 0.3, 1.0);
curveQuickAddPoint(result.density_altitude, 0.5, 1.0); curveQuickAddPoint(result.coverage_by_altitude, 0.5, 1.0);
curveQuickAddPoint(result.density_altitude, 1.0, 0.0); curveQuickAddPoint(result.coverage_by_altitude, 1.0, 0.0);
result.material.base.r = 0.7; result.material.base.r = 0.7;
result.material.base.g = 0.7; result.material.base.g = 0.7;
result.material.base.b = 0.7; result.material.base.b = 0.7;
@ -157,33 +163,25 @@ CloudsLayerDefinition cloudsLayerCreateDefinition()
result.transparencydepth = 1.5; result.transparencydepth = 1.5;
result.lighttraversal = 7.0; result.lighttraversal = 7.0;
result.minimumlight = 0.4; result.minimumlight = 0.4;
result.scaling = 3.5; result.shape_scaling = 3.5;
result.coverage = 0.45; result.edge_scaling = 0.1;
result.noise = noiseCreateGenerator(); result.edge_length = 0.25;
noiseGenerateBaseNoise(result.noise, 262144); result.base_coverage = 0.35;
noiseAddLevelSimple(result.noise, 1.0, 1.0); result.shape_noise = noiseCreateGenerator();
noiseAddLevelSimple(result.noise, 1.0 / 2.0, 0.6); noiseGenerateBaseNoise(result.shape_noise, 20000);
noiseAddLevelSimple(result.noise, 1.0 / 4.0, 0.3); noiseAddLevelsSimple(result.shape_noise, 4, 1.0, 1.0);
noiseAddLevelSimple(result.noise, 1.0 / 10.0, 0.15); result.edge_noise = noiseCreateGenerator();
noiseAddLevelSimple(result.noise, 1.0 / 20.0, 0.09); noiseGenerateBaseNoise(result.edge_noise, 20000);
noiseAddLevelSimple(result.noise, 1.0 / 40.0, 0.06); noiseAddLevelsSimple(result.edge_noise, 8, 1.0, 1.0);
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.customcoverage = _standardCoverageFunc; result._custom_coverage = _standardCoverageFunc;
return result; return result;
} }
void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition) void cloudsLayerDeleteDefinition(CloudsLayerDefinition* definition)
{ {
noiseDeleteGenerator(definition->noise); noiseDeleteGenerator(definition->shape_noise);
} }
void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination) void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinition* destination)
@ -198,22 +196,29 @@ void cloudsLayerCopyDefinition(CloudsLayerDefinition* source, CloudsLayerDefinit
temp = *destination; temp = *destination;
*destination = *source; *destination = *source;
destination->noise = temp.noise; destination->shape_noise = temp.shape_noise;
noiseCopy(source->noise, destination->noise); noiseCopy(source->shape_noise, destination->shape_noise);
destination->density_altitude = temp.density_altitude; destination->edge_noise = temp.edge_noise;
curveCopy(source->density_altitude, destination->density_altitude); 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) 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) 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) 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 = 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) if (render_precision > max_total_length / 10.0)
{ {
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); direction = v3Normalize(direction);
result = COLOR_TRANSPARENT; 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); 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--) for (i = segment_count - 1; i >= 0; i--)

View file

@ -20,16 +20,19 @@ struct CloudsLayerDefinition
{ {
double ymin; double ymin;
double ymax; double ymax;
Curve* density_altitude; double base_coverage;
NoiseGenerator* noise; Curve* coverage_by_altitude;
NoiseGenerator* shape_noise;
double shape_scaling;
NoiseGenerator* edge_noise;
double edge_scaling;
double edge_length;
SurfaceMaterial material; SurfaceMaterial material;
double hardness; double hardness;
double transparencydepth; double transparencydepth;
double lighttraversal; double lighttraversal;
double minimumlight; double minimumlight;
double scaling; CloudCoverageFunc _custom_coverage;
double coverage;
CloudCoverageFunc customcoverage;
}; };
typedef struct typedef struct