diff --git a/TODO b/TODO index 012935b..04b1189 100644 --- a/TODO +++ b/TODO @@ -22,6 +22,7 @@ Technology Preview 3 : - Add basic vegetation system (not sure). - Improve sky rendering (colors and light halo). - Add a progress indicator on previews. +- Multi threaded first pass. Release Candidate : - Polish all features and UI. diff --git a/gui_qt/formclouds.cpp b/gui_qt/formclouds.cpp index da69bb4..568742f 100644 --- a/gui_qt/formclouds.cpp +++ b/gui_qt/formclouds.cpp @@ -158,6 +158,7 @@ FormClouds::FormClouds(QWidget *parent): addInputColor(tr("Base color"), &_layer.material.base); addInputDouble(tr("Light reflection"), &_layer.material.reflection, 0.0, 1.0, 0.01, 0.1); addInputDouble(tr("Light reflection shininess"), &_layer.material.shininess, 0.0, 20.0, 0.1, 1.0); + 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("Light traversal depth"), &_layer.lighttraversal, 0.0, 100.0, 0.5, 5.0); addInputDouble(tr("Minimum lighting"), &_layer.minimumlight, 0.0, 1.0, 0.01, 0.1); diff --git a/i18n/paysages_fr.ts b/i18n/paysages_fr.ts index df8a85e..24915c6 100644 --- a/i18n/paysages_fr.ts +++ b/i18n/paysages_fr.ts @@ -309,16 +309,21 @@ Maintenir Ctrl : Plus rapide + 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 c6b9b7f..c759f7e 100644 --- a/lib_paysages/clouds.c +++ b/lib_paysages/clouds.c @@ -47,6 +47,7 @@ void cloudsSave(PackStream* stream, CloudsDefinition* definition) packWriteDouble(stream, &layer->ymax); noiseSaveGenerator(stream, layer->noise); materialSave(stream, &layer->material); + packWriteDouble(stream, &layer->hardness); packWriteDouble(stream, &layer->transparencydepth); packWriteDouble(stream, &layer->lighttraversal); packWriteDouble(stream, &layer->minimumlight); @@ -75,6 +76,7 @@ void cloudsLoad(PackStream* stream, CloudsDefinition* definition) packReadDouble(stream, &layer->ymax); noiseLoadGenerator(stream, layer->noise); materialLoad(stream, &layer->material); + packReadDouble(stream, &layer->hardness); packReadDouble(stream, &layer->transparencydepth); packReadDouble(stream, &layer->lighttraversal); packReadDouble(stream, &layer->minimumlight); @@ -160,6 +162,7 @@ CloudsLayerDefinition cloudsLayerCreateDefinition() result.material.base.b = 0.7; result.material.reflection = 0.1; result.material.shininess = 2.0; + result.hardness = 0.1; result.transparencydepth = 20.0; result.lighttraversal = 50.0; result.minimumlight = 0.5; @@ -482,10 +485,13 @@ static Color _applyLayerLighting(CloudsLayerDefinition* definition, Renderer* re Vector3 normal; normal = v3Scale(_getNormal(definition, position, 3.0), 0.25); - normal = v3Add(normal, v3Scale(_getNormal(definition, position, 2.0), 0.25)); - normal = v3Add(normal, v3Scale(_getNormal(definition, position, 1.0), 0.25)); + if (renderer->render_quality > 5) + { + normal = v3Add(normal, v3Scale(_getNormal(definition, position, 2.0), 0.25)); + normal = v3Add(normal, v3Scale(_getNormal(definition, position, 1.0), 0.25)); + } normal = v3Add(normal, v3Scale(_getNormal(definition, position, 0.5), 0.25)); - normal = v3Scale(v3Normalize(normal), 0.1); + normal = v3Scale(v3Normalize(normal), definition->hardness); return renderer->applyLightingToSurface(renderer, position, normal, definition->material); } diff --git a/lib_paysages/clouds.h b/lib_paysages/clouds.h index a58d0ff..f8da51a 100644 --- a/lib_paysages/clouds.h +++ b/lib_paysages/clouds.h @@ -23,6 +23,7 @@ struct CloudsLayerDefinition double ymax; NoiseGenerator* noise; SurfaceMaterial material; + double hardness; double transparencydepth; double lighttraversal; double minimumlight; diff --git a/lib_paysages/textures.c b/lib_paysages/textures.c index 239b543..83b34fb 100644 --- a/lib_paysages/textures.c +++ b/lib_paysages/textures.c @@ -191,40 +191,82 @@ void texturesDeleteLayer(TexturesDefinition* definition, int layer) } } -static inline Vector3 _getNormal(TextureLayerDefinition* definition, Renderer* renderer, Vector3 point, double scale) +static inline Vector3 _getPoint(TextureLayerDefinition* definition, Renderer* renderer, double x, double z, Vector3 prenormal, double scale) +{ + Vector3 point; + + point.x = x; + point.z = z; + point.y = renderer->getTerrainHeight(renderer, point.x, point.z); + + return v3Add(point, v3Scale(prenormal, noiseGet2DTotal(definition->bump_noise, point.x / definition->bump_scaling, point.z / definition->bump_scaling) * definition->bump_height)); +} + +static inline Vector3 _getPreNormal(TextureLayerDefinition* definition, Renderer* renderer, Vector3 point, double scale) { Vector3 dpoint, ref, normal; + + /* TODO This method is better suited in terrain.c */ - ref.x = 0.0; ref.y = 0.0; - point.y = renderer->getTerrainHeight(renderer, point.x, point.z) + noiseGet2DTotal(definition->bump_noise, point.x / definition->bump_scaling, point.z / definition->bump_scaling) * definition->bump_height; - - dpoint.x = point.x - scale; - dpoint.z = point.z; - dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x / definition->bump_scaling, dpoint.z / definition->bump_scaling) * definition->bump_height; - ref.z = -1.0; - normal = v3Normalize(v3Cross(ref, v3Sub(dpoint, point))); + point.y = renderer->getTerrainHeight(renderer, point.x, point.z); dpoint.x = point.x + scale; dpoint.z = point.z; - dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x / definition->bump_scaling, dpoint.z / definition->bump_scaling) * definition->bump_height; + dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z); + ref.x = 0.0; ref.z = 1.0; normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point)))); - ref.z = 0.0; - - dpoint.x = point.x; - dpoint.z = point.z - scale; - dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x / definition->bump_scaling, dpoint.z / definition->bump_scaling) * definition->bump_height; - ref.x = 1.0; - normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point)))); - dpoint.x = point.x; dpoint.z = point.z + scale; - dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z) + noiseGet2DTotal(definition->bump_noise, dpoint.x / definition->bump_scaling, dpoint.z / definition->bump_scaling) * definition->bump_height; + dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z); ref.x = -1.0; + ref.z = 0.0; normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point)))); + if (renderer->render_quality > 5) + { + dpoint.x = point.x; + dpoint.z = point.z - scale; + dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z); + ref.x = 1.0; + ref.z = 0.0; + normal = v3Add(normal, v3Normalize(v3Cross(ref, v3Sub(dpoint, point)))); + + dpoint.x = point.x - scale; + dpoint.z = point.z; + dpoint.y = renderer->getTerrainHeight(renderer, dpoint.x, dpoint.z); + ref.x = 0.0; + ref.z = -1.0; + normal = v3Normalize(v3Cross(ref, v3Sub(dpoint, point))); + } + + return v3Normalize(normal); +} + +static inline Vector3 _getPostNormal(TextureLayerDefinition* definition, Renderer* renderer, Vector3 point, Vector3 prenormal, double scale) +{ + Vector3 p0, d1, d2, d3, d4, normal; + + p0 = _getPoint(definition, renderer, point.x, point.z, prenormal, scale); + + d1 = v3Normalize(v3Sub(_getPoint(definition, renderer, point.x + scale, point.z, prenormal, scale), p0)); + d3 = v3Normalize(v3Sub(_getPoint(definition, renderer, point.x, point.z + scale, prenormal, scale), p0)); + if (renderer->render_quality > 5) + { + d2 = v3Normalize(v3Sub(_getPoint(definition, renderer, point.x - scale, point.z, prenormal, scale), p0)); + d4 = v3Normalize(v3Sub(_getPoint(definition, renderer, point.x, point.z - scale, prenormal, scale), p0)); + } + + normal = v3Cross(d3, d1); + if (renderer->render_quality > 5) + { + normal = v3Add(normal, v3Cross(d1, d4)); + normal = v3Add(normal, v3Cross(d4, d2)); + normal = v3Add(normal, v3Cross(d2, d3)); + } + return v3Normalize(normal); } @@ -232,7 +274,7 @@ double texturesGetLayerCoverage(TextureLayerDefinition* definition, Renderer* re { Vector3 normal; - normal = _getNormal(definition, renderer, location, detail * 0.1); + normal = _getPreNormal(definition, renderer, location, detail * 0.1); return zoneGetValue(definition->zone, location, normal); } @@ -244,11 +286,12 @@ Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* render double coverage; result = COLOR_TRANSPARENT; - normal = _getNormal(definition, renderer, location, detail * 0.1); + normal = _getPreNormal(definition, renderer, location, detail * 0.1); coverage = zoneGetValue(definition->zone, location, normal); if (coverage > 0.0) { + normal = _getPostNormal(definition, renderer, location, normal, detail * 0.1); result = renderer->applyLightingToSurface(renderer, location, normal, definition->material); result.a = coverage; }