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 :
* 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).

2
TODO
View file

@ -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

View file

@ -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);

View file

@ -374,27 +374,19 @@ Maintenir Ctrl : Plus rapide</translation>
<translation type="unfinished"></translation>
</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>
<translation>Bruit</translation>
<translation type="obsolete">Bruit</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="162"/>
<source>Coverage</source>
<translation>Couverture</translation>
<translation type="obsolete">Couverture</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="163"/>
<source>Scaling</source>
<translation>Echelle</translation>
<translation type="obsolete">Echelle</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="164"/>
<location filename="../gui_qt/formclouds.cpp" line="167"/>
<source>Material</source>
<translation type="unfinished"></translation>
</message>
@ -410,23 +402,58 @@ Maintenir Ctrl : Plus rapide</translation>
<source>Light reflection shininess</source>
<translation type="obsolete">Concentration de la réflexion de lumière</translation>
</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>
<location filename="../gui_qt/formclouds.cpp" line="165"/>
<source>Hardness to light</source>
<source>Edge scaling</source>
<translation type="unfinished"></translation>
</message>
<message>
<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>
<translation>Distance de transparence</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="167"/>
<location filename="../gui_qt/formclouds.cpp" line="170"/>
<source>Light traversal depth</source>
<translation>Distance de traversée de la lumière</translation>
</message>
<message>
<location filename="../gui_qt/formclouds.cpp" line="168"/>
<location filename="../gui_qt/formclouds.cpp" line="171"/>
<source>Minimum lighting</source>
<translation>Eclairage minimal</translation>
</message>

View file

@ -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--)

View file

@ -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