Changed textures displacement to use FractalNoise
This commit is contained in:
parent
f9d0918bcb
commit
897f20b1ea
12 changed files with 127 additions and 106 deletions
|
@ -128,6 +128,12 @@ double FractalNoise::get3d(double detail, double x, double y, double z) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FractalNoise::estimateRange(double *min, double *max) const {
|
||||||
|
// TODO Better estimate
|
||||||
|
*max = height;
|
||||||
|
*min = -*max;
|
||||||
|
}
|
||||||
|
|
||||||
double FractalNoise::getBase1d(double x) const {
|
double FractalNoise::getBase1d(double x) const {
|
||||||
return getBase2d(x, 0.0);
|
return getBase2d(x, 0.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,11 @@ class BASICSSHARED_EXPORT FractalNoise {
|
||||||
double get2d(double detail, double x, double y) const;
|
double get2d(double detail, double x, double y) const;
|
||||||
double get3d(double detail, double x, double y, double z) const;
|
double get3d(double detail, double x, double y, double z) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate the range of values this generator will yield with a very small detail value.
|
||||||
|
*/
|
||||||
|
void estimateRange(double *min, double *max) const;
|
||||||
|
|
||||||
virtual double getBase1d(double x) const;
|
virtual double getBase1d(double x) const;
|
||||||
virtual double getBase2d(double x, double y) const;
|
virtual double getBase2d(double x, double y) const;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
#include "TextureLayerDefinition.h"
|
#include "TextureLayerDefinition.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include "Zone.h"
|
#include "Zone.h"
|
||||||
#include "NoiseGenerator.h"
|
|
||||||
#include "SurfaceMaterial.h"
|
#include "SurfaceMaterial.h"
|
||||||
#include "PackStream.h"
|
#include "PackStream.h"
|
||||||
#include "Scenery.h"
|
#include "Scenery.h"
|
||||||
#include "TerrainDefinition.h"
|
#include "TerrainDefinition.h"
|
||||||
#include "Color.h"
|
#include "Color.h"
|
||||||
|
#include "FractalNoise.h"
|
||||||
#include "NoiseNode.h"
|
#include "NoiseNode.h"
|
||||||
|
|
||||||
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const string &name)
|
TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const string &name)
|
||||||
: DefinitionNode(parent, name, "texturelayer") {
|
: DefinitionNode(parent, name, "texturelayer") {
|
||||||
terrain_zone = new Zone;
|
terrain_zone = new Zone;
|
||||||
_displacement_noise = new NoiseGenerator;
|
|
||||||
material = new SurfaceMaterial;
|
material = new SurfaceMaterial;
|
||||||
|
|
||||||
displacement_height = 0.0;
|
displacement_noise = new NoiseNode(this, "displacement");
|
||||||
displacement_scaling = 1.0;
|
displacement_noise->setConfig(0.0);
|
||||||
|
|
||||||
detail_noise = new NoiseNode(this, "detail");
|
detail_noise = new NoiseNode(this, "detail");
|
||||||
detail_noise->setConfig(0.01);
|
detail_noise->setConfig(0.01);
|
||||||
|
@ -24,22 +24,12 @@ TextureLayerDefinition::TextureLayerDefinition(DefinitionNode *parent, const str
|
||||||
|
|
||||||
TextureLayerDefinition::~TextureLayerDefinition() {
|
TextureLayerDefinition::~TextureLayerDefinition() {
|
||||||
delete terrain_zone;
|
delete terrain_zone;
|
||||||
delete _displacement_noise;
|
|
||||||
delete material;
|
delete material;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::validate() {
|
void TextureLayerDefinition::validate() {
|
||||||
DefinitionNode::validate();
|
DefinitionNode::validate();
|
||||||
|
|
||||||
if (displacement_scaling < 0.000001) {
|
|
||||||
displacement_scaling = 0.000001;
|
|
||||||
}
|
|
||||||
|
|
||||||
_displacement_noise->clearLevels();
|
|
||||||
_displacement_noise->addLevelsSimple(9, 1.0, -1.0, 1.0, 0.0);
|
|
||||||
_displacement_noise->normalizeAmplitude(-1.0, 1.0, 0);
|
|
||||||
_displacement_noise->validate();
|
|
||||||
|
|
||||||
material->validate();
|
material->validate();
|
||||||
|
|
||||||
/* Update zone height range */
|
/* Update zone height range */
|
||||||
|
@ -57,11 +47,7 @@ void TextureLayerDefinition::copy(DefinitionNode *destination) const {
|
||||||
if (auto tex_destination = static_cast<TextureLayerDefinition *>(destination)) {
|
if (auto tex_destination = static_cast<TextureLayerDefinition *>(destination)) {
|
||||||
terrain_zone->copy(tex_destination->terrain_zone);
|
terrain_zone->copy(tex_destination->terrain_zone);
|
||||||
|
|
||||||
tex_destination->displacement_scaling = displacement_scaling;
|
|
||||||
tex_destination->displacement_height = displacement_height;
|
|
||||||
*tex_destination->material = *material;
|
*tex_destination->material = *material;
|
||||||
|
|
||||||
_displacement_noise->copy(tex_destination->_displacement_noise);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,42 +55,34 @@ void TextureLayerDefinition::save(PackStream *stream) const {
|
||||||
DefinitionNode::save(stream);
|
DefinitionNode::save(stream);
|
||||||
|
|
||||||
terrain_zone->save(stream);
|
terrain_zone->save(stream);
|
||||||
stream->write(&displacement_scaling);
|
|
||||||
stream->write(&displacement_height);
|
|
||||||
material->save(stream);
|
material->save(stream);
|
||||||
|
|
||||||
_displacement_noise->save(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::load(PackStream *stream) {
|
void TextureLayerDefinition::load(PackStream *stream) {
|
||||||
DefinitionNode::load(stream);
|
DefinitionNode::load(stream);
|
||||||
|
|
||||||
terrain_zone->load(stream);
|
terrain_zone->load(stream);
|
||||||
stream->read(&displacement_scaling);
|
|
||||||
stream->read(&displacement_height);
|
|
||||||
material->load(stream);
|
material->load(stream);
|
||||||
|
|
||||||
_displacement_noise->load(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenerator &random) {
|
void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenerator &random) {
|
||||||
_displacement_noise->randomizeOffsets(random);
|
displacement_noise->randomize(random);
|
||||||
detail_noise->randomize(random);
|
detail_noise->randomize(random);
|
||||||
|
|
||||||
terrain_zone->clear();
|
terrain_zone->clear();
|
||||||
|
|
||||||
switch (preset) {
|
switch (preset) {
|
||||||
case TEXTURES_LAYER_PRESET_MUD:
|
case TEXTURES_LAYER_PRESET_MUD:
|
||||||
displacement_height = 0.02;
|
displacement_noise->setConfig(0.05, 0.1, 0.3);
|
||||||
displacement_scaling = 3.0;
|
detail_noise->setConfig(0.01, 0.03);
|
||||||
material->setColor(0.015, 0.014, 0.014, 1.0);
|
material->setColor(0.015, 0.014, 0.014, 1.0);
|
||||||
material->reflection = 0.003;
|
material->reflection = 0.003;
|
||||||
material->shininess = 4.0;
|
material->shininess = 4.0;
|
||||||
break;
|
break;
|
||||||
case TEXTURES_LAYER_PRESET_ROCK:
|
case TEXTURES_LAYER_PRESET_ROCK:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 1.0, 1.0);
|
terrain_zone->addHeightRangeQuick(1.0, 0.6, 0.7, 1.0, 1.0);
|
||||||
displacement_height = 0.3;
|
displacement_noise->setConfig(1.0, 0.3, 0.5, 0.85);
|
||||||
displacement_scaling = 2.0;
|
detail_noise->setConfig(0.02, 0.04);
|
||||||
material->setColor(0.6, 0.55, 0.57, 1.0);
|
material->setColor(0.6, 0.55, 0.57, 1.0);
|
||||||
material->reflection = 0.006;
|
material->reflection = 0.006;
|
||||||
material->shininess = 6.0;
|
material->shininess = 6.0;
|
||||||
|
@ -112,8 +90,8 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
case TEXTURES_LAYER_PRESET_GRASS:
|
case TEXTURES_LAYER_PRESET_GRASS:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.45, 0.5, 0.8, 1.0);
|
terrain_zone->addHeightRangeQuick(1.0, 0.45, 0.5, 0.8, 1.0);
|
||||||
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4);
|
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.05, 0.4);
|
||||||
displacement_height = 0.0;
|
displacement_noise->setConfig(0.4, 0.05);
|
||||||
displacement_scaling = 1.0;
|
detail_noise->setConfig(0.01, 0.1);
|
||||||
material->setColor(0.12, 0.19, 0.035, 1.0);
|
material->setColor(0.12, 0.19, 0.035, 1.0);
|
||||||
material->reflection = 0.001;
|
material->reflection = 0.001;
|
||||||
material->shininess = 4.0;
|
material->shininess = 4.0;
|
||||||
|
@ -121,8 +99,8 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
case TEXTURES_LAYER_PRESET_SAND:
|
case TEXTURES_LAYER_PRESET_SAND:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.495, 0.505, 0.56, 0.63);
|
terrain_zone->addHeightRangeQuick(1.0, 0.495, 0.505, 0.56, 0.63);
|
||||||
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 0.4);
|
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.1, 0.4);
|
||||||
displacement_height = 0.05;
|
displacement_noise->setConfig(0.04, 0.1, 0.5, 0.3);
|
||||||
displacement_scaling = 5.0;
|
detail_noise->setConfig(0.004, 0.08);
|
||||||
material->setColor(1.2, 1.1, 0.9, 1.0);
|
material->setColor(1.2, 1.1, 0.9, 1.0);
|
||||||
material->reflection = 0.008;
|
material->reflection = 0.008;
|
||||||
material->shininess = 1.0;
|
material->shininess = 1.0;
|
||||||
|
@ -130,8 +108,8 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
case TEXTURES_LAYER_PRESET_SNOW:
|
case TEXTURES_LAYER_PRESET_SNOW:
|
||||||
terrain_zone->addHeightRangeQuick(1.0, 0.77, 0.85, 1.0, 1.0);
|
terrain_zone->addHeightRangeQuick(1.0, 0.77, 0.85, 1.0, 1.0);
|
||||||
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.2, 1.0);
|
terrain_zone->addSlopeRangeQuick(1.0, 0.0, 0.0, 0.2, 1.0);
|
||||||
displacement_height = 0.1;
|
displacement_noise->setConfig(0.4, 0.07);
|
||||||
displacement_scaling = 1.0;
|
detail_noise->setConfig(0.01, 0.03);
|
||||||
material->setColor(5.0, 5.0, 5.0, 1.0);
|
material->setColor(5.0, 5.0, 5.0, 1.0);
|
||||||
material->reflection = 0.02;
|
material->reflection = 0.02;
|
||||||
material->shininess = 0.6;
|
material->shininess = 0.6;
|
||||||
|
@ -140,3 +118,13 @@ void TextureLayerDefinition::applyPreset(TextureLayerPreset preset, RandomGenera
|
||||||
|
|
||||||
validate();
|
validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextureLayerDefinition::hasDisplacement() const {
|
||||||
|
return displacement_noise->getGenerator()->getHeight() > 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double TextureLayerDefinition::getMaximalDisplacement() const {
|
||||||
|
double neg, pos;
|
||||||
|
displacement_noise->getGenerator()->estimateRange(&neg, &pos);
|
||||||
|
return max(fabs(neg), fabs(pos));
|
||||||
|
}
|
||||||
|
|
|
@ -31,19 +31,29 @@ class DEFINITIONSHARED_EXPORT TextureLayerDefinition : public DefinitionNode {
|
||||||
|
|
||||||
void applyPreset(TextureLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
void applyPreset(TextureLayerPreset preset, RandomGenerator &random = RandomGeneratorDefault);
|
||||||
|
|
||||||
|
inline NoiseNode *propDisplacementNoise() const {
|
||||||
|
return displacement_noise;
|
||||||
|
}
|
||||||
inline NoiseNode *propDetailNoise() const {
|
inline NoiseNode *propDetailNoise() const {
|
||||||
return detail_noise;
|
return detail_noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the texture applies a displacement noise on terrain.
|
||||||
|
*/
|
||||||
|
bool hasDisplacement() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximal (positive or negative) displacement this layer may apply on terrain.
|
||||||
|
*/
|
||||||
|
double getMaximalDisplacement() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Zone *terrain_zone;
|
Zone *terrain_zone;
|
||||||
double displacement_scaling;
|
|
||||||
double displacement_height;
|
|
||||||
SurfaceMaterial *material;
|
SurfaceMaterial *material;
|
||||||
|
|
||||||
NoiseGenerator *_displacement_noise;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
NoiseNode *displacement_noise;
|
||||||
NoiseNode *detail_noise;
|
NoiseNode *detail_noise;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ double TexturesDefinition::getMaximalDisplacement() {
|
||||||
double result = 0.0;
|
double result = 0.0;
|
||||||
int n = getLayerCount();
|
int n = getLayerCount();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
result += getTextureLayer(i)->displacement_height;
|
result += getTextureLayer(i)->getMaximalDisplacement();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "FractalNoise.h"
|
#include "FractalNoise.h"
|
||||||
#include "RandomGenerator.h"
|
#include "RandomGenerator.h"
|
||||||
#include "NoiseFunctionSimplex.h"
|
#include "NoiseFunctionSimplex.h"
|
||||||
|
#include "Zone.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -101,16 +102,11 @@ static void testGroundShadowQuality() {
|
||||||
scenery.getAtmosphere()->setDayTime(16, 45);
|
scenery.getAtmosphere()->setDayTime(16, 45);
|
||||||
scenery.getTextures()->clear();
|
scenery.getTextures()->clear();
|
||||||
TextureLayerDefinition texture(NULL, "test");
|
TextureLayerDefinition texture(NULL, "test");
|
||||||
texture.displacement_height = 0.3;
|
texture.applyPreset(TextureLayerDefinition::TEXTURES_LAYER_PRESET_ROCK);
|
||||||
texture.displacement_scaling = 2.0;
|
texture.terrain_zone->clear();
|
||||||
texture.material->setColor(0.6, 0.55, 0.57, 1.0);
|
|
||||||
texture.material->reflection = 0.006;
|
|
||||||
texture.material->shininess = 6.0;
|
|
||||||
texture.validate();
|
|
||||||
scenery.getTextures()->addLayer(texture);
|
scenery.getTextures()->addLayer(texture);
|
||||||
scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0));
|
scenery.getCamera()->setLocation(Vector3(10.0, 10.0, -10.0));
|
||||||
scenery.getCamera()->setTarget(VECTOR_ZERO);
|
scenery.getCamera()->setTarget(VECTOR_ZERO);
|
||||||
scenery.validate();
|
|
||||||
|
|
||||||
SoftwareCanvasRenderer renderer(&scenery);
|
SoftwareCanvasRenderer renderer(&scenery);
|
||||||
renderer.setSize(400, 300);
|
renderer.setSize(400, 300);
|
||||||
|
@ -376,6 +372,41 @@ static void testOpenGLVegetationImpostor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testTextures() {
|
||||||
|
Scenery scenery;
|
||||||
|
scenery.autoPreset(162);
|
||||||
|
scenery.getAtmosphere()->setDayTime(10);
|
||||||
|
scenery.getClouds()->clear();
|
||||||
|
scenery.getTerrain()->propWaterHeight()->setValue(-1.0);
|
||||||
|
scenery.getCamera()->setLocationCoords(0.0, 20.0, 0.0);
|
||||||
|
scenery.getCamera()->setTargetCoords(0.0, 0.0, -20.0);
|
||||||
|
|
||||||
|
SoftwareCanvasRenderer renderer(&scenery);
|
||||||
|
renderer.setSize(600, 600);
|
||||||
|
renderer.setQuality(0.5);
|
||||||
|
|
||||||
|
// TODO Customize terrain function
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
TextureLayerDefinition layer(NULL, "test");
|
||||||
|
layer.applyPreset(static_cast<TextureLayerDefinition::TextureLayerPreset>(i));
|
||||||
|
layer.terrain_zone->clear();
|
||||||
|
scenery.getTextures()->clear();
|
||||||
|
scenery.getTextures()->addLayer(layer);
|
||||||
|
startTestRender(&renderer, "texture", i * 2);
|
||||||
|
|
||||||
|
layer.propDetailNoise()->setConfig(0.0);
|
||||||
|
scenery.getTextures()->clear();
|
||||||
|
scenery.getTextures()->addLayer(layer);
|
||||||
|
startTestRender(&renderer, "texture", i * 2 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
scenery.getTextures()->applyPreset(static_cast<TexturesDefinition::TexturesPreset>(i));
|
||||||
|
startTestRender(&renderer, "texture_comp", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void runTestSuite() {
|
void runTestSuite() {
|
||||||
testAtmosphereBruneton();
|
testAtmosphereBruneton();
|
||||||
testCloudQuality();
|
testCloudQuality();
|
||||||
|
@ -386,5 +417,6 @@ void runTestSuite() {
|
||||||
testNoise();
|
testNoise();
|
||||||
testOpenGLVegetationImpostor();
|
testOpenGLVegetationImpostor();
|
||||||
testRasterizationQuality();
|
testRasterizationQuality();
|
||||||
|
testTextures();
|
||||||
testVegetationModels();
|
testVegetationModels();
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,7 +267,7 @@ void OpenGLRenderer::cameraChangeEvent(CameraDefinition *camera) {
|
||||||
}
|
}
|
||||||
|
|
||||||
double OpenGLRenderer::getPrecision(const Vector3 &) {
|
double OpenGLRenderer::getPrecision(const Vector3 &) {
|
||||||
return 0.0000001;
|
return 0.001;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color OpenGLRenderer::applyMediumTraversal(const Vector3 &, const Color &color) {
|
Color OpenGLRenderer::applyMediumTraversal(const Vector3 &, const Color &color) {
|
||||||
|
|
|
@ -97,7 +97,7 @@ bool OpenGLTerrainChunk::maintain() {
|
||||||
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0) {
|
if (_texture_current_size <= 1 || i % 2 != 0 || j % 2 != 0) {
|
||||||
double x = _startx + factor * to_double(i);
|
double x = _startx + factor * to_double(i);
|
||||||
double z = _startz + factor * to_double(j);
|
double z = _startz + factor * to_double(j);
|
||||||
Color color = _renderer->getTexturesRenderer()->applyToTerrain(x, z).final_color;
|
Color color = _renderer->getTexturesRenderer()->applyToTerrain(x, z, 0.001).final_color;
|
||||||
new_image->setPixel(i, j, Color(color.r * 0.2, color.g * 0.2, color.b * 0.2).normalized().to32BitRGBA());
|
new_image->setPixel(i, j, Color(color.r * 0.2, color.g * 0.2, color.b * 0.2).normalized().to32BitRGBA());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ double SoftwareRenderer::getPrecision(const Vector3 &location) {
|
||||||
projected.x += 1.0;
|
projected.x += 1.0;
|
||||||
// projected.y += 1.0;
|
// projected.y += 1.0;
|
||||||
|
|
||||||
return render_camera->unproject(projected).sub(location).getNorm(); // / to_double(render_quality);
|
return render_camera->unproject(projected).sub(location).getNorm() * 0.1 / to_double(render_quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 SoftwareRenderer::projectPoint(const Vector3 &point) {
|
Vector3 SoftwareRenderer::projectPoint(const Vector3 &point) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ static inline Vector3 _getNormal2(Vector3 center, Vector3 east, Vector3 south) {
|
||||||
|
|
||||||
TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bool with_painting, bool with_textures) {
|
TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bool with_painting, bool with_textures) {
|
||||||
TerrainResult result;
|
TerrainResult result;
|
||||||
double detail = 0.001; /* TODO */
|
double offset = 0.001;
|
||||||
|
|
||||||
/* Normal */
|
/* Normal */
|
||||||
Vector3 center, north, east, south, west;
|
Vector3 center, north, east, south, west;
|
||||||
|
@ -71,21 +71,21 @@ TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bo
|
||||||
center.z = z;
|
center.z = z;
|
||||||
center.y = getHeight(center.x, center.z, with_painting);
|
center.y = getHeight(center.x, center.z, with_painting);
|
||||||
|
|
||||||
east.x = x + detail;
|
east.x = x + offset;
|
||||||
east.z = z;
|
east.z = z;
|
||||||
east.y = getHeight(east.x, east.z, with_painting);
|
east.y = getHeight(east.x, east.z, with_painting);
|
||||||
|
|
||||||
south.x = x;
|
south.x = x;
|
||||||
south.z = z + detail;
|
south.z = z + offset;
|
||||||
south.y = getHeight(south.x, south.z, with_painting);
|
south.y = getHeight(south.x, south.z, with_painting);
|
||||||
|
|
||||||
if (parent->render_quality > 6) {
|
if (parent->render_quality > 6) {
|
||||||
west.x = x - detail;
|
west.x = x - offset;
|
||||||
west.z = z;
|
west.z = z;
|
||||||
west.y = getHeight(west.x, west.z, with_painting);
|
west.y = getHeight(west.x, west.z, with_painting);
|
||||||
|
|
||||||
north.x = x;
|
north.x = x;
|
||||||
north.z = z - detail;
|
north.z = z - offset;
|
||||||
north.y = getHeight(north.x, north.z, with_painting);
|
north.y = getHeight(north.x, north.z, with_painting);
|
||||||
|
|
||||||
result.normal = _getNormal4(center, north, east, south, west);
|
result.normal = _getNormal4(center, north, east, south, west);
|
||||||
|
@ -110,23 +110,20 @@ TerrainRenderer::TerrainResult TerrainRenderer::getResult(double x, double z, bo
|
||||||
north = parent->getTexturesRenderer()->displaceTerrain(getResult(north.x, north.z, with_painting, 0));
|
north = parent->getTexturesRenderer()->displaceTerrain(getResult(north.x, north.z, with_painting, 0));
|
||||||
|
|
||||||
result.normal = _getNormal4(center, north, east, south, west);
|
result.normal = _getNormal4(center, north, east, south, west);
|
||||||
} else if (parent->render_quality > 2) {
|
} else {
|
||||||
/* Use 3 points on displaced terrain */
|
/* Use 3 points on displaced terrain */
|
||||||
east = parent->getTexturesRenderer()->displaceTerrain(getResult(east.x, east.z, with_painting, 0));
|
east = parent->getTexturesRenderer()->displaceTerrain(getResult(east.x, east.z, with_painting, 0));
|
||||||
south = parent->getTexturesRenderer()->displaceTerrain(getResult(south.x, south.z, with_painting, 0));
|
south = parent->getTexturesRenderer()->displaceTerrain(getResult(south.x, south.z, with_painting, 0));
|
||||||
|
|
||||||
result.normal = _getNormal2(center, east, south);
|
result.normal = _getNormal2(center, east, south);
|
||||||
} else {
|
|
||||||
/* TODO Use texture noise directly, as if terrain was a plane */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Color TerrainRenderer::getFinalColor(const Vector3 &location, double) {
|
Color TerrainRenderer::getFinalColor(const Vector3 &location, double precision) {
|
||||||
/* TODO Restore precision control */
|
TexturesRenderer::TexturesResult textures = parent->getTexturesRenderer()->applyToTerrain(location.x, location.z, precision);
|
||||||
TexturesRenderer::TexturesResult textures = parent->getTexturesRenderer()->applyToTerrain(location.x, location.z);
|
|
||||||
return parent->applyMediumTraversal(textures.final_location, textures.final_color);
|
return parent->applyMediumTraversal(textures.final_location, textures.final_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,27 +30,10 @@ double TexturesRenderer::getLayerBasePresence(TextureLayerDefinition *layer,
|
||||||
/*
|
/*
|
||||||
* Get triplanar noise value, depending on the normal direction.
|
* Get triplanar noise value, depending on the normal direction.
|
||||||
*/
|
*/
|
||||||
double TexturesRenderer::getTriplanarNoise(const FractalNoise *noise, const Vector3 &location, const Vector3 &normal) {
|
double TexturesRenderer::getTriplanarNoise(const FractalNoise *noise, const Vector3 &location, const Vector3 &normal, double detail) {
|
||||||
// TODO Detail control
|
double noiseXY = noise->get2d(detail, location.x, location.y);
|
||||||
double noiseXY = noise->get2d(0.001, location.x, location.y);
|
double noiseXZ = noise->get2d(detail, location.x, location.z);
|
||||||
double noiseXZ = noise->get2d(0.001, location.x, location.z);
|
double noiseYZ = noise->get2d(detail, location.y, location.z);
|
||||||
double noiseYZ = noise->get2d(0.001, location.y, location.z);
|
|
||||||
|
|
||||||
double mXY = fabs(normal.z);
|
|
||||||
double mXZ = fabs(normal.y);
|
|
||||||
double mYZ = fabs(normal.x);
|
|
||||||
double total = 1.0 / (mXY + mXZ + mYZ);
|
|
||||||
mXY *= total;
|
|
||||||
mXZ *= total;
|
|
||||||
mYZ *= total;
|
|
||||||
|
|
||||||
return noiseXY * mXY + noiseXZ * mXZ + noiseYZ * mYZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
static double _compatGetTriplanarNoise(NoiseGenerator *noise, const Vector3 &location, const Vector3 &normal) {
|
|
||||||
double noiseXY = noise->get2DTotal(location.x, location.y);
|
|
||||||
double noiseXZ = noise->get2DTotal(location.x, location.z);
|
|
||||||
double noiseYZ = noise->get2DTotal(location.y, location.z);
|
|
||||||
|
|
||||||
double mXY = fabs(normal.z);
|
double mXY = fabs(normal.z);
|
||||||
double mXZ = fabs(normal.y);
|
double mXZ = fabs(normal.y);
|
||||||
|
@ -69,9 +52,9 @@ double TexturesRenderer::getMaximalDisplacement(TexturesDefinition *textures) {
|
||||||
n = textures->getLayerCount();
|
n = textures->getLayerCount();
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||||
|
double layer_disp = layer->getMaximalDisplacement();
|
||||||
if (layer->displacement_height > 0.0) {
|
if (layer_disp > 0.0) {
|
||||||
disp += layer->displacement_height;
|
disp += layer_disp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return disp;
|
return disp;
|
||||||
|
@ -98,10 +81,9 @@ static inline Vector3 _getNormal2(Vector3 center, Vector3 east, Vector3 south) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Vector3 _getDetailNormal(SoftwareRenderer *renderer, Vector3 base_location, Vector3 base_normal,
|
static Vector3 _getDetailNormal(SoftwareRenderer *renderer, Vector3 base_location, Vector3 base_normal,
|
||||||
TextureLayerDefinition *layer) {
|
TextureLayerDefinition *layer, double precision) {
|
||||||
TexturesRenderer *textures = renderer->getTexturesRenderer();
|
TexturesRenderer *textures = renderer->getTexturesRenderer();
|
||||||
Vector3 result;
|
Vector3 result;
|
||||||
double offset = 0.01;
|
|
||||||
|
|
||||||
/* Find guiding vectors in the appoximated local plane */
|
/* Find guiding vectors in the appoximated local plane */
|
||||||
Vector3 dx, dy;
|
Vector3 dx, dy;
|
||||||
|
@ -117,22 +99,24 @@ static Vector3 _getDetailNormal(SoftwareRenderer *renderer, Vector3 base_locatio
|
||||||
/* Apply detail noise locally */
|
/* Apply detail noise locally */
|
||||||
Vector3 center, north, east, south, west;
|
Vector3 center, north, east, south, west;
|
||||||
auto detail_noise = layer->propDetailNoise()->getGenerator();
|
auto detail_noise = layer->propDetailNoise()->getGenerator();
|
||||||
|
double detail = precision;
|
||||||
|
double offset = precision * 0.1;
|
||||||
|
|
||||||
center =
|
center =
|
||||||
base_location.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, base_location, base_normal)));
|
base_location.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, base_location, base_normal, detail)));
|
||||||
|
|
||||||
east = base_location.add(dx.scale(offset));
|
east = base_location.add(dx.scale(offset));
|
||||||
east = east.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, east, base_normal)));
|
east = east.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, east, base_normal, detail)));
|
||||||
|
|
||||||
south = base_location.add(dy.scale(offset));
|
south = base_location.add(dy.scale(offset));
|
||||||
south = south.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, south, base_normal)));
|
south = south.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, south, base_normal, detail)));
|
||||||
|
|
||||||
if (renderer->render_quality > 6) {
|
if (renderer->render_quality > 6) {
|
||||||
west = base_location.add(dx.scale(-offset));
|
west = base_location.add(dx.scale(-offset));
|
||||||
west = west.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, west, base_normal)));
|
west = west.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, west, base_normal, detail)));
|
||||||
|
|
||||||
north = base_location.add(dy.scale(-offset));
|
north = base_location.add(dy.scale(-offset));
|
||||||
north = north.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, north, base_normal)));
|
north = north.add(base_normal.scale(textures->getTriplanarNoise(detail_noise, north, base_normal, detail)));
|
||||||
|
|
||||||
result = _getNormal4(center, north, east, south, west);
|
result = _getNormal4(center, north, east, south, west);
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,13 +138,10 @@ Vector3 TexturesRenderer::displaceTerrain(const TerrainRenderer::TerrainResult &
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
TextureLayerDefinition *layer = textures->getTextureLayer(i);
|
||||||
|
|
||||||
if (layer->displacement_height > 0.0) {
|
if (layer->hasDisplacement()) {
|
||||||
double presence = getLayerBasePresence(layer, terrain);
|
double presence = getLayerBasePresence(layer, terrain);
|
||||||
Vector3 location = {terrain.location.x / layer->displacement_scaling,
|
auto noise = layer->propDisplacementNoise()->getGenerator();
|
||||||
terrain.location.y / layer->displacement_scaling,
|
offset += getTriplanarNoise(noise, terrain.location, terrain.normal, 0.001) * presence;
|
||||||
terrain.location.z / layer->displacement_scaling};
|
|
||||||
offset += _compatGetTriplanarNoise(layer->_displacement_noise, location, terrain.normal) * presence *
|
|
||||||
layer->displacement_height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,12 +153,14 @@ double TexturesRenderer::getBasePresence(int layer, const TerrainRenderer::Terra
|
||||||
return getLayerBasePresence(layerdef, terrain);
|
return getLayerBasePresence(layerdef, terrain);
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturesRenderer::TexturesResult TexturesRenderer::applyToTerrain(double x, double z) {
|
TexturesRenderer::TexturesResult TexturesRenderer::applyToTerrain(double x, double z, double precision) {
|
||||||
TexturesDefinition *textures = parent->getScenery()->getTextures();
|
TexturesDefinition *textures = parent->getScenery()->getTextures();
|
||||||
TexturesResult result;
|
TexturesResult result;
|
||||||
|
|
||||||
// Displacement
|
// Displacement
|
||||||
TerrainRenderer::TerrainResult terrain = parent->getTerrainRenderer()->getResult(x, z, 1, 1);
|
// FIXME
|
||||||
|
TerrainRenderer::TerrainResult raw_terrain = parent->getTerrainRenderer()->getResult(x, z, true, false);
|
||||||
|
TerrainRenderer::TerrainResult terrain = parent->getTerrainRenderer()->getResult(x, z, true, true);
|
||||||
|
|
||||||
// TODO Displaced textures had their presence already computed before, store that result and use it
|
// TODO Displaced textures had their presence already computed before, store that result and use it
|
||||||
|
|
||||||
|
@ -188,7 +171,7 @@ TexturesRenderer::TexturesResult TexturesRenderer::applyToTerrain(double x, doub
|
||||||
TexturesLayerResult &layer = result.layers[i];
|
TexturesLayerResult &layer = result.layers[i];
|
||||||
|
|
||||||
layer.definition = textures->getTextureLayer(i);
|
layer.definition = textures->getTextureLayer(i);
|
||||||
layer.presence = getBasePresence(i, terrain);
|
layer.presence = getBasePresence(i, raw_terrain);
|
||||||
if (layer.presence > 0.9999) {
|
if (layer.presence > 0.9999) {
|
||||||
start = i;
|
start = i;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +188,7 @@ TexturesRenderer::TexturesResult TexturesRenderer::applyToTerrain(double x, doub
|
||||||
TexturesLayerResult &layer = result.layers[i];
|
TexturesLayerResult &layer = result.layers[i];
|
||||||
|
|
||||||
if (layer.presence > 0.0) {
|
if (layer.presence > 0.0) {
|
||||||
Vector3 normal = _getDetailNormal(parent, terrain.location, terrain.normal, layer.definition);
|
Vector3 normal = _getDetailNormal(parent, terrain.location, terrain.normal, layer.definition, precision);
|
||||||
Vector3 location(x, terrain.location.y, z);
|
Vector3 location(x, terrain.location.y, z);
|
||||||
layer.color = parent->applyLightingToSurface(location, normal, *layer.definition->material);
|
layer.color = parent->applyLightingToSurface(location, normal, *layer.definition->material);
|
||||||
layer.color.a = layer.presence;
|
layer.color.a = layer.presence;
|
||||||
|
|
|
@ -35,11 +35,11 @@ class SOFTWARESHARED_EXPORT TexturesRenderer {
|
||||||
|
|
||||||
virtual double getMaximalDisplacement(TexturesDefinition *textures);
|
virtual double getMaximalDisplacement(TexturesDefinition *textures);
|
||||||
virtual double getLayerBasePresence(TextureLayerDefinition *layer, const TerrainRenderer::TerrainResult &terrain);
|
virtual double getLayerBasePresence(TextureLayerDefinition *layer, const TerrainRenderer::TerrainResult &terrain);
|
||||||
virtual double getTriplanarNoise(const FractalNoise *noise, const Vector3 &location, const Vector3 &normal);
|
virtual double getTriplanarNoise(const FractalNoise *noise, const Vector3 &location, const Vector3 &normal, double detail);
|
||||||
|
|
||||||
virtual Vector3 displaceTerrain(const TerrainRenderer::TerrainResult &terrain);
|
virtual Vector3 displaceTerrain(const TerrainRenderer::TerrainResult &terrain);
|
||||||
virtual double getBasePresence(int layer, const TerrainRenderer::TerrainResult &terrain);
|
virtual double getBasePresence(int layer, const TerrainRenderer::TerrainResult &terrain);
|
||||||
virtual TexturesResult applyToTerrain(double x, double z);
|
virtual TexturesResult applyToTerrain(double x, double z, double precision);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SoftwareRenderer *parent;
|
SoftwareRenderer *parent;
|
||||||
|
|
Loading…
Reference in a new issue