diff --git a/ChangeLog b/ChangeLog index d983521..c8f051f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,8 +2,9 @@ ------------------------------- * Previews scaling is now logarithmic (slower when zoomed). * Previews drawing now takes advantage of multiple CPUs. -* New displacement mode for textures (perpendicular to local ground surface). +* New texture model (perpendicular displacement and thickness). * Added clouds hardness to light. +* Version management in saved files. 2012-04-20 Technology Preview 1 ------------------------------- diff --git a/TODO b/TODO index 6f4a14b..7d4e65a 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,9 @@ Technology Preview 2 : +- Interface for textures thickness and slope_range. - Render tab previews should not rerender when changing render options. -- Compute shadows only once for all textures at a same location (need an intermediary light status). +- Compute shadows only once for all textures at a same location. + => Add an intermediary light status (two pass lighting). +- Don't change opacity when scrolling previews. - Add layer sorting/naming. - Save GUI config (views, render params). - Add an OSD ability on previews and use it for camera location and user landmarks. @@ -9,21 +12,30 @@ Technology Preview 2 : - Add a terrain modifier dialog with zones. - Add a noise filler (and maybe noise intervals ?). - Improve curve editor. + => Add curve modes + => Improve curve rendering + => Add axis labels - Water and terrain LOD moves with the camera, fix it like in the wanderer. - Pause previews drawing of main window when a dialog is opened. - Interrupt preview chunk renderings that will be discarded at commit, or that are no more visible. - Can't overwrite picture files (ILError). - Fix "RGB parameters out of range" (and segfault) on preview while moving render params fast in render tab. + => May need to change the updateData system. + => Previews need to be paused while updating data. - When there are two previews in the same view, balance rendering between the two. +- Lock some previews together (eg: terrain height and colored preview). +- Find a new licence. Technology Preview 3 : - Restore render progress. - Add antialiasing option (pay attention to memory usage). -- Add basic vegetation system (not sure). +- Add basic vegetation system ? +- Texture shadowing and self-shadowing ? - Improve sky rendering (colors and light halo). - Add a progress indicator on previews. - Multi threaded first pass. - Fix potential holes in land rendering. +- Progressive final render. Release Candidate : - Polish all features and UI. diff --git a/gui_qt/formrender.cpp b/gui_qt/formrender.cpp index ca5b325..48e3247 100644 --- a/gui_qt/formrender.cpp +++ b/gui_qt/formrender.cpp @@ -76,7 +76,7 @@ private: static Color _applyTextures(Renderer* renderer, Vector3 location, double precision) { - return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location, precision); + return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); } static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material) diff --git a/gui_qt/formterrain.cpp b/gui_qt/formterrain.cpp index 5ff78db..e910f95 100644 --- a/gui_qt/formterrain.cpp +++ b/gui_qt/formterrain.cpp @@ -120,7 +120,7 @@ private: static Color _applyTextures(Renderer* renderer, Vector3 location, double precision) { - return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location, precision); + return texturesGetColor((TexturesDefinition*)(renderer->customData[1]), renderer, location.x, location.z, precision); } static Color _applyLightingToSurface(Renderer* renderer, Vector3 location, Vector3 normal, SurfaceMaterial material) diff --git a/lib_paysages/auto.c b/lib_paysages/auto.c index e5c5286..c6b522f 100644 --- a/lib_paysages/auto.c +++ b/lib_paysages/auto.c @@ -96,8 +96,8 @@ void autoGenRealisticLandscape(int seed) water.depth_color.b = 0.3; water.depth_color.a = 1.0; water.lighting_depth = 3.0; - water.waves_noise_height = 0.015; - water.waves_noise_scale = 0.2; + water.waves_noise_height = 0.005; + water.waves_noise_scale = 0.07; noiseGenerateBaseNoise(water.waves_noise, 262144); noiseAddLevelsSimple(water.waves_noise, 2, 1.0, 1.0); noiseAddLevelsSimple(water.waves_noise, 3, 0.15, 0.1); @@ -139,7 +139,7 @@ void autoGenRealisticLandscape(int seed) /* Terrain */ terrain = terrainCreateDefinition(); noiseGenerateBaseNoise(terrain.height_noise, 1048576); - noiseAddLevelsSimple(terrain.height_noise, 10, 1.0, 1.0); + noiseAddLevelsSimple(terrain.height_noise, 12, 1.0, 1.0); terrain.height_factor = 12.0 / noiseGetMaxValue(terrain.height_noise); terrain.scaling = 10.0; scenerySetTerrain(&terrain); @@ -152,35 +152,44 @@ void autoGenRealisticLandscape(int seed) zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 5.0, 5.0); noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseAddLevelsSimple(texture->bump_noise, 8, 1.0, 1.0); - texture->bump_height = 0.1; - texture->bump_scaling = 0.15; + texture->bump_height = 0.01; + texture->bump_scaling = 0.015; texture->material.base.r = 0.6; texture->material.base.g = 0.55; texture->material.base.b = 0.57; texture->material.reflection = 0.2; texture->material.shininess = 3.0; + texture->thickness = 0.001; + texture->slope_range = 0.001; texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); zoneAddHeightRangeQuick(texture->zone, 1.0, -1.0, 0.0, 3.0, 15.0); - zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 0.2, 0.3); + zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 0.1, 0.7); noiseGenerateBaseNoise(texture->bump_noise, 102400); noiseAddLevelsSimple(texture->bump_noise, 5, 1.0, 0.4); noiseAddLevelsSimple(texture->bump_noise, 2, 0.03, 0.08); - texture->bump_height = 0.02; - texture->bump_scaling = 0.1; + texture->bump_height = 0.002; + texture->bump_scaling = 0.01; texture->material.base.r = 0.12; texture->material.base.g = 0.19; texture->material.base.b = 0.035; texture->material.reflection = 0.1; texture->material.shininess = 2.0; - /*texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); - zoneAddHeightRange(texture->zone, 1.0, 3.0, 4.0, 100.0, 100.0); + texture->thickness = 0.02; + texture->slope_range = 0.03; + texture = texturesGetLayer(&textures, texturesAddLayer(&textures)); + zoneAddHeightRangeQuick(texture->zone, 1.0, 4.0, 5.0, 100.0, 100.0); + zoneAddSlopeRangeQuick(texture->zone, 1.0, 0.0, 0.0, 0.2, 1.0); noiseGenerateBaseNoise(texture->bump_noise, 102400); - noiseAddLevelsSimple(texture->bump_noise, 6, 0.04, 0.003); - texture->color.r = 1.0; - texture->color.g = 1.0; - texture->color.b = 1.0; - texturesSetDefinition(layer, texture); - texturesDeleteDefinition(texture);*/ + noiseAddLevelsSimple(texture->bump_noise, 6, 1.0, 1.0); + texture->bump_height = 0.002; + texture->bump_scaling = 0.03; + texture->material.base.r = 1.0; + texture->material.base.g = 1.0; + texture->material.base.b = 1.0; + texture->material.reflection = 0.25; + texture->material.shininess = 0.6; + texture->thickness = 0.05; + texture->slope_range = 0.3; scenerySetTextures(&textures); texturesDeleteDefinition(&textures); diff --git a/lib_paysages/scenery.c b/lib_paysages/scenery.c index cf46a41..1ae6107 100644 --- a/lib_paysages/scenery.c +++ b/lib_paysages/scenery.c @@ -285,7 +285,7 @@ static HeightInfo _getWaterHeightInfo(Renderer* renderer) static Color _applyTextures(Renderer* renderer, Vector3 location, double precision) { - return texturesGetColor(&_textures, renderer, location, precision); + return texturesGetColor(&_textures, renderer, location.x, location.z, precision); } static Color _applyAtmosphere(Renderer* renderer, Vector3 location, Color base) diff --git a/lib_paysages/textures.c b/lib_paysages/textures.c index 72bcb72..3adea80 100644 --- a/lib_paysages/textures.c +++ b/lib_paysages/textures.c @@ -37,6 +37,8 @@ void texturesSave(PackStream* stream, TexturesDefinition* definition) packWriteDouble(stream, &definition->textures[i].bump_height); packWriteDouble(stream, &definition->textures[i].bump_scaling); materialSave(stream, &definition->textures[i].material); + packWriteDouble(stream, &definition->textures[i].thickness); + packWriteDouble(stream, &definition->textures[i].slope_range); } } @@ -60,6 +62,8 @@ void texturesLoad(PackStream* stream, TexturesDefinition* definition) packReadDouble(stream, &layer->bump_height); packReadDouble(stream, &layer->bump_scaling); materialLoad(stream, &layer->material); + packReadDouble(stream, &definition->textures[i].thickness); + packReadDouble(stream, &definition->textures[i].slope_range); } texturesValidateDefinition(definition); @@ -120,6 +124,8 @@ TextureLayerDefinition texturesLayerCreateDefinition() result.material.base = COLOR_WHITE; result.material.reflection = 0.0; result.material.shininess = 0.0; + result.thickness = 0.0; + result.slope_range = 0.001; return result; } @@ -135,6 +141,8 @@ void texturesLayerCopyDefinition(TextureLayerDefinition* source, TextureLayerDef destination->material = source->material; destination->bump_height = source->bump_height; destination->bump_scaling = source->bump_scaling; + destination->thickness = source->thickness; + destination->slope_range = source->slope_range; noiseCopy(source->bump_noise, destination->bump_noise); zoneCopy(source->zone, destination->zone); } @@ -145,6 +153,10 @@ void texturesLayerValidateDefinition(TextureLayerDefinition* definition) { definition->bump_scaling = 0.000001; } + if (definition->slope_range < 0.001) + { + definition->slope_range = 0.001; + } } int texturesGetLayerCount(TexturesDefinition* definition) @@ -191,128 +203,181 @@ void texturesDeleteLayer(TexturesDefinition* definition, int layer) } } -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.y = 0.0; - 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); - ref.x = 0.0; - ref.z = 1.0; - 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); - 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 = v3Add(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); -} - -double texturesGetLayerCoverage(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail) -{ - Vector3 normal; - - normal = _getPreNormal(definition, renderer, location, detail * 0.1); - - return zoneGetValue(definition->zone, location, normal); -} - Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail) { Color result; Vector3 normal; - double coverage; + double coverage, noise; result = COLOR_TRANSPARENT; - normal = _getPreNormal(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; - } + if (coverage < 1.0) + { + noise = noiseGet2DTotal(definition->border_noise, location.x * 1000.0, location.z * 1000.0); + coverage = -1.0 + 2.0 * coverage + noise * (1.0 - coverage); + } + if (coverage > 0.0) + { + normal = _getPostNormal(definition, renderer, location, normal, detail * 0.1); + result = renderer->applyLightingToSurface(renderer, location, normal, definition->material); + result.a = coverage < 0.1 ? coverage / 0.1 : 1.0; + } + }*/ return result; } -Color texturesGetColor(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail) + + +static inline Vector3 _getNormal4(Vector3 center, Vector3 north, Vector3 east, Vector3 south, Vector3 west) { - Color result, tex_color; + Vector3 dnorth, deast, dsouth, dwest, normal; + + dnorth = v3Sub(north, center); + deast = v3Sub(east, center); + dsouth = v3Sub(south, center); + dwest = v3Sub(west, center); + + normal = v3Cross(deast, dnorth); + normal = v3Add(normal, v3Cross(dsouth, deast)); + normal = v3Add(normal, v3Cross(dwest, dsouth)); + normal = v3Add(normal, v3Cross(dnorth, dwest)); + + return v3Normalize(normal); +} + +static inline Vector3 _getNormal2(Vector3 center, Vector3 east, Vector3 south) +{ + return v3Normalize(v3Cross(v3Sub(south, center), v3Sub(east, center))); +} + +static inline TextureResult _getTerrainResult(Renderer* renderer, double x, double z, double detail) +{ + TextureResult result; + Vector3 center, north, east, south, west; + + /* TODO This method is better suited in terrain.c */ + + center.x = x; + center.z = z; + center.y = renderer->getTerrainHeight(renderer, center.x, center.z); + + east.x = x + detail; + east.z = z; + east.y = renderer->getTerrainHeight(renderer, east.x, east.z); + + south.x = x; + south.z = z + detail; + south.y = renderer->getTerrainHeight(renderer, south.x, south.z); + + if (renderer->render_quality > 5) + { + west.x = x - detail; + west.z = z; + west.y = renderer->getTerrainHeight(renderer, west.x, west.z); + + north.x = x; + north.z = z - detail; + north.y = renderer->getTerrainHeight(renderer, north.x, north.z); + + result.normal = _getNormal4(center, north, east, south, west); + } + else + { + result.normal = _getNormal2(center, east, south); + } + + result.location = center; + result.color = COLOR_GREEN; + result.thickness = -100.0; + + return result; +} + +static inline void _getLayerThickness(TextureLayerDefinition* definition, Renderer* renderer, double x, double z, TextureResult* result) +{ + TextureResult base; + double coverage; + + base = _getTerrainResult(renderer, x, z, definition->slope_range); + coverage = zoneGetValue(definition->zone, base.location, base.normal); + if (coverage > 0.0) + { + result->thickness = coverage * definition->thickness; + result->thickness += noiseGet2DTotal(definition->bump_noise, base.location.x / definition->bump_scaling, base.location.z / definition->bump_scaling) * definition->bump_height; + + result->location = v3Add(base.location, v3Scale(base.normal, result->thickness)); + } + else + { + result->thickness = -1000.0; + result->location = base.location; + } +} + +static inline TextureResult _getLayerResult(TextureLayerDefinition* definition, Renderer* renderer, double x, double z, double detail) +{ + TextureResult result_center, result_north, result_east, result_south, result_west; + + _getLayerThickness(definition, renderer, x, z, &result_center); + _getLayerThickness(definition, renderer, x + detail, z, &result_east); + _getLayerThickness(definition, renderer, x, z + detail, &result_south); + + if (renderer->render_quality > 5) + { + _getLayerThickness(definition, renderer, x - detail, z, &result_west); + _getLayerThickness(definition, renderer, x, z - detail, &result_north); + + result_center.normal = _getNormal4(result_center.location, result_north.location, result_east.location, result_south.location, result_west.location); + } + else + { + result_center.normal = _getNormal2(result_center.location, result_east.location, result_south.location); + } + + result_center.color = renderer->applyLightingToSurface(renderer, result_center.location, result_center.normal, definition->material); + + return result_center; +} + +static int _cmpResults(const void* result1, const void* result2) +{ + return ((TextureResult*)result1)->thickness > ((TextureResult*)result2)->thickness; +} + +double texturesGetLayerCoverage(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail) +{ + TextureResult base = _getTerrainResult(renderer, location.x, location.z, definition->slope_range); + return zoneGetValue(definition->zone, base.location, base.normal); +} + +Color texturesGetColor(TexturesDefinition* definition, Renderer* renderer, double x, double z, double detail) +{ + TextureResult results[TEXTURES_MAX_LAYERS + 1]; + Color result; int i; - result = COLOR_GREEN; + /* TODO Do not compute layers fully covered */ + /* TODO Optimize : each layer computes the same shadows */ + + detail *= 0.1; + + results[0] = _getTerrainResult(renderer, x, z, detail); + for (i = 0; i < definition->nbtextures; i++) { - /* TODO Do not compute layers fully covered */ - /* TODO Optimize : each layer computes the same shadows */ - tex_color = texturesGetLayerColor(definition->textures + i, renderer, location, detail); - if (tex_color.a > 0.0001) - { - colorMask(&result, &tex_color); - } + results[i + 1] = _getLayerResult(definition->textures + i, renderer, x, z, detail); + } + + qsort(results, definition->nbtextures + 1, sizeof(TextureResult), _cmpResults); + + result = results[0].color; + for (i = 0; i < definition->nbtextures; i++) + { + colorMask(&result, &results[i + 1].color); } return result; diff --git a/lib_paysages/textures.h b/lib_paysages/textures.h index ec87f5e..685ac14 100644 --- a/lib_paysages/textures.h +++ b/lib_paysages/textures.h @@ -20,6 +20,8 @@ typedef struct double bump_scaling; double bump_height; SurfaceMaterial material; + double thickness; + double slope_range; } TextureLayerDefinition; typedef struct @@ -28,6 +30,14 @@ typedef struct TextureLayerDefinition textures[TEXTURES_MAX_LAYERS]; } TexturesDefinition; +typedef struct +{ + Vector3 location; + Vector3 normal; + double thickness; + Color color; +} TextureResult; + void texturesInit(); void texturesQuit(); void texturesSave(PackStream* stream, TexturesDefinition* definition); @@ -50,7 +60,7 @@ void texturesDeleteLayer(TexturesDefinition* definition, int layer); double texturesGetLayerCoverage(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail); Color texturesGetLayerColor(TextureLayerDefinition* definition, Renderer* renderer, Vector3 location, double detail); -Color texturesGetColor(TexturesDefinition* definition, Renderer* renderer, Vector3 location, double detail); +Color texturesGetColor(TexturesDefinition* definition, Renderer* renderer, double x, double z, double detail); #ifdef __cplusplus }