clouds: Precision fixes
This commit is contained in:
parent
330ac54ac9
commit
24a9145bb3
3 changed files with 72 additions and 23 deletions
|
@ -87,7 +87,7 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
|||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||
noiseAddLevelsSimple(definition->_shape_noise, 7, 1.0, 0.0, 1.0, 0.5);
|
||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.4, 0.0);
|
||||
noiseAddLevelsSimple(definition->_edge_noise, 2, 1.0, -0.5, 0.5, 0.5);
|
||||
noiseAddLevelsSimple(definition->_edge_noise, 4, 1.0, -0.5, 0.5, 0.5);
|
||||
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, 0.8, 0.0);
|
||||
break;
|
||||
case CLOUDS_TYPE_STRATOCUMULUS:
|
||||
|
@ -95,7 +95,7 @@ void cloudsLayerValidateDefinition(CloudsLayerDefinition* definition)
|
|||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.2, 1.0);
|
||||
curveQuickAddPoint(definition->_coverage_by_altitude, 0.5, 1.0);
|
||||
curveQuickAddPoint(definition->_coverage_by_altitude, 1.0, 0.0);
|
||||
noiseAddLevelsSimple(definition->_shape_noise, 2, 1.0, 0.0, 1.0, 0.5);
|
||||
noiseAddLevelsSimple(definition->_shape_noise, 4, 1.0, 0.0, 1.0, 0.5);
|
||||
noiseSetFunctionParams(definition->_shape_noise, NOISE_FUNCTION_SIMPLEX, 0.3, 0.0);
|
||||
noiseAddLevelsSimple(definition->_edge_noise, 6, 1.0, -0.5, 0.5, 0.5);
|
||||
noiseSetFunctionParams(definition->_edge_noise, NOISE_FUNCTION_SIMPLEX, 0.5, 0.0);
|
||||
|
|
|
@ -4,28 +4,39 @@
|
|||
|
||||
double cloudsGetLayerCoverage(CloudsLayerDefinition* layer, Vector3 location)
|
||||
{
|
||||
if (layer->base_coverage == 0.0)
|
||||
if (layer->base_coverage <= 0.0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double coverage = noiseGet2DTotal(layer->_coverage_noise, location.x / layer->shape_scaling, location.z / layer->shape_scaling);
|
||||
double coverage = 0.5 + noiseGet2DTotal(layer->_coverage_noise, location.x / layer->shape_scaling, location.z / layer->shape_scaling);
|
||||
coverage -= (1.0 - layer->base_coverage);
|
||||
|
||||
coverage *= curveGetValue(layer->_coverage_by_altitude, (location.y - layer->lower_altitude) / layer->thickness);
|
||||
|
||||
return (coverage <= 0.0) ? 0.0 : coverage;
|
||||
if (coverage < 0.0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else if (coverage >= 1.0)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return coverage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double cloudsGetLayerDensity(CloudsLayerDefinition* layer, Vector3 location, double coverage)
|
||||
{
|
||||
if (coverage == 0.0)
|
||||
if (coverage <= 0.0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else if (coverage == 1.0)
|
||||
else if (coverage >= 1.0)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
@ -39,11 +50,11 @@ double cloudsGetLayerDensity(CloudsLayerDefinition* layer, Vector3 location, dou
|
|||
|
||||
double cloudsGetEdgeDensity(CloudsLayerDefinition* layer, Vector3 location, double layer_density)
|
||||
{
|
||||
if (layer_density == 0.0)
|
||||
if (layer_density <= 0.0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
else if (layer_density == 1.0)
|
||||
else if (layer_density >= 1.0)
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
|
|
@ -36,11 +36,30 @@ typedef struct
|
|||
static void _walkerFilterCallback(CloudsWalker* walker)
|
||||
{
|
||||
CloudWalkerStepInfo* segment = cloudsWalkerGetLastSegment(walker);
|
||||
Renderer* renderer = segment->renderer;
|
||||
AccumulatedLightData* data = (AccumulatedLightData*)segment->data;
|
||||
|
||||
assert(data != NULL);
|
||||
|
||||
double density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
||||
double density_integral;
|
||||
if (segment->subdivided)
|
||||
{
|
||||
density_integral = segment->length * (segment->start.local_density + segment->end.local_density) / 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!segment->refined && segment->start.global_density == 0.0 && segment->end.global_density > 0.0)
|
||||
{
|
||||
cloudsWalkerOrderRefine(walker, 1.0 / (double)renderer->render_quality);
|
||||
return;
|
||||
}
|
||||
else if ((segment->start.global_density > 0.0 || segment->end.global_density > 0.0) && (segment->start.global_density < 1.0 || segment->end.global_density < 1.0))
|
||||
{
|
||||
cloudsWalkerOrderSubdivide(walker, renderer->render_quality + 1);
|
||||
return;
|
||||
}
|
||||
density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
||||
}
|
||||
|
||||
data->out_scattering += 0.3 * density_integral;
|
||||
|
||||
|
@ -78,12 +97,13 @@ static int _alterLight(Renderer* renderer, LightDefinition* light, Vector3 locat
|
|||
|
||||
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
||||
cloudsWalkerSetStepSize(walker, -1.0);
|
||||
cloudsWalkerSetVoidSkipping(walker, 1);
|
||||
cloudsStartWalking(walker, _walkerFilterCallback, &data);
|
||||
cloudsDeleteWalker(walker);
|
||||
}
|
||||
}
|
||||
|
||||
double max_power = colorGetPower(&light->color) - data.out_scattering;
|
||||
double max_power = data.light_power - data.out_scattering;
|
||||
if (max_power < 0.0)
|
||||
{
|
||||
light->color = COLOR_BLACK;
|
||||
|
@ -100,6 +120,8 @@ typedef struct
|
|||
{
|
||||
double out_scattering; /* Amount of light scattered away by heavy particles */
|
||||
Color in_scattering; /* Amount of light redirected toward the viewer */
|
||||
int entry_found; /* 1 if a cloud entry has been found */
|
||||
Vector3 entry; /* Point of entry in the clouds */
|
||||
} AccumulatedMaterialData;
|
||||
|
||||
static inline void _applyOutScattering(Color* col, double out_scattering)
|
||||
|
@ -132,7 +154,12 @@ static void _walkerMaterialCallback(CloudsWalker* walker)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((segment->start.global_density > 0.0 || segment->end.global_density > 0.0) && (segment->start.global_density < 1.0 || segment->end.global_density < 1.0))
|
||||
if (!segment->refined && segment->start.global_density == 0.0 && segment->end.global_density > 0.0)
|
||||
{
|
||||
cloudsWalkerOrderRefine(walker, 1.0 / (double)(renderer->render_quality * renderer->render_quality));
|
||||
return;
|
||||
}
|
||||
else if ((segment->start.global_density > 0.0 || segment->end.global_density > 0.0) && (segment->start.global_density < 1.0 || segment->end.global_density < 1.0))
|
||||
{
|
||||
cloudsWalkerOrderSubdivide(walker, renderer->render_quality + 3);
|
||||
return;
|
||||
|
@ -140,17 +167,26 @@ static void _walkerMaterialCallback(CloudsWalker* walker)
|
|||
density_integral = segment->length * (segment->start.global_density + segment->end.global_density) / 2.0;
|
||||
}
|
||||
|
||||
data->out_scattering += 0.5 * density_integral;
|
||||
if (density_integral > 0.0)
|
||||
{
|
||||
data->out_scattering += 0.3 * density_integral;
|
||||
|
||||
Color in_scattering = renderer->applyLightingToSurface(renderer, segment->start.location, VECTOR_ZERO, &layer->material);
|
||||
in_scattering.r *= density_integral * 5.0;
|
||||
in_scattering.g *= density_integral * 5.0;
|
||||
in_scattering.b *= density_integral * 5.0;
|
||||
_applyOutScattering(&in_scattering, data->out_scattering);
|
||||
Color in_scattering = renderer->applyLightingToSurface(renderer, segment->start.location, VECTOR_ZERO, &layer->material);
|
||||
in_scattering.r *= density_integral * 5.0;
|
||||
in_scattering.g *= density_integral * 5.0;
|
||||
in_scattering.b *= density_integral * 5.0;
|
||||
_applyOutScattering(&in_scattering, data->out_scattering);
|
||||
|
||||
data->in_scattering.r += in_scattering.r;
|
||||
data->in_scattering.g += in_scattering.g;
|
||||
data->in_scattering.b += in_scattering.b;
|
||||
data->in_scattering.r += in_scattering.r;
|
||||
data->in_scattering.g += in_scattering.g;
|
||||
data->in_scattering.b += in_scattering.b;
|
||||
|
||||
if (!data->entry_found)
|
||||
{
|
||||
data->entry_found = 1;
|
||||
data->entry = segment->start.location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 end)
|
||||
|
@ -182,9 +218,12 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en
|
|||
AccumulatedMaterialData data;
|
||||
data.out_scattering = 0.0;
|
||||
data.in_scattering = COLOR_BLACK;
|
||||
data.entry = ostart;
|
||||
data.entry_found = 0;
|
||||
|
||||
walker = cloudsCreateWalker(renderer, layer, ostart, oend);
|
||||
cloudsWalkerSetStepSize(walker, -1.0);
|
||||
cloudsWalkerSetVoidSkipping(walker, 1);
|
||||
cloudsStartWalking(walker, _walkerMaterialCallback, &data);
|
||||
cloudsDeleteWalker(walker);
|
||||
|
||||
|
@ -197,8 +236,7 @@ static Color _getColor(Renderer* renderer, Color base, Vector3 start, Vector3 en
|
|||
base.b += data.in_scattering.b;
|
||||
|
||||
/* Apply aerial perspective approximation */
|
||||
/* TODO This should be done at cloud entry */
|
||||
base = renderer->atmosphere->applyAerialPerspective(renderer, ostart, base).final;
|
||||
base = renderer->atmosphere->applyAerialPerspective(renderer, data.entry, base).final;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue