paysages : Progress on bruneton atmospheric model (WIP) + fixed terrain issue.
git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@485 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
parent
6cd5975316
commit
4a6721e2ff
8 changed files with 315 additions and 168 deletions
|
@ -5,6 +5,7 @@
|
||||||
* http://evasion.inrialpes.fr/~Eric.Bruneton/
|
* http://evasion.inrialpes.fr/~Eric.Bruneton/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#include "../tools/cache.h"
|
#include "../tools/cache.h"
|
||||||
#include "../tools/texture.h"
|
#include "../tools/texture.h"
|
||||||
#include "../tools/parallel.h"
|
#include "../tools/parallel.h"
|
||||||
|
#include "../renderer.h"
|
||||||
|
|
||||||
/*********************** Constants ***********************/
|
/*********************** Constants ***********************/
|
||||||
|
|
||||||
|
@ -52,12 +54,8 @@ static const double AVERAGE_GROUND_REFLECTANCE = 0.1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Texture2D* _transmittanceTexture = NULL;
|
Texture2D* _transmittanceTexture = NULL;
|
||||||
Texture2D* _deltaETexture = NULL;
|
|
||||||
Texture2D* _irradianceTexture = NULL;
|
Texture2D* _irradianceTexture = NULL;
|
||||||
Texture3D* _inscatterTexture = NULL;
|
Texture3D* _inscatterTexture = NULL;
|
||||||
Texture3D* _deltaSMTexture = NULL;
|
|
||||||
Texture3D* _deltaSRTexture = NULL;
|
|
||||||
Texture3D* _deltaJTexture = NULL;
|
|
||||||
|
|
||||||
// Rayleigh
|
// Rayleigh
|
||||||
static const double HR = 8.0;
|
static const double HR = 8.0;
|
||||||
|
@ -402,7 +400,7 @@ static void _precomputeTransmittanceTexture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _precomputeIrrDeltaETexture()
|
static void _precomputeIrrDeltaETexture(Texture2D* destination)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
|
@ -423,7 +421,7 @@ static void _precomputeIrrDeltaETexture()
|
||||||
irr.b = trans.b * max(muS, 0.0);
|
irr.b = trans.b * max(muS, 0.0);
|
||||||
irr.a = 1.0;
|
irr.a = 1.0;
|
||||||
|
|
||||||
texture2DSetPixel(_deltaETexture, x, y, irr);
|
texture2DSetPixel(destination, x, y, irr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,7 +542,7 @@ static int _inscatter1Worker(ParallelWork* work, int layer, void* data)
|
||||||
|
|
||||||
/*********************** inscatterS.glsl ***********************/
|
/*********************** inscatterS.glsl ***********************/
|
||||||
|
|
||||||
static Color _inscatterS(double r, double mu, double muS, double nu, int first)
|
static Color _inscatterS(double r, double mu, double muS, double nu, int first, Texture2D* deltaE, Texture3D* deltaSR, Texture3D* deltaSM)
|
||||||
{
|
{
|
||||||
Color raymie = COLOR_BLACK;
|
Color raymie = COLOR_BLACK;
|
||||||
|
|
||||||
|
@ -599,7 +597,7 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first)
|
||||||
gnormal.x = dground * w.x / Rg;
|
gnormal.x = dground * w.x / Rg;
|
||||||
gnormal.y = dground * w.y / Rg;
|
gnormal.y = dground * w.y / Rg;
|
||||||
gnormal.z = r + dground * w.z / Rg;
|
gnormal.z = r + dground * w.z / Rg;
|
||||||
Color girradiance = _irradiance(_deltaETexture, Rg, v3Dot(gnormal, s));
|
Color girradiance = _irradiance(deltaE, Rg, v3Dot(gnormal, s));
|
||||||
|
|
||||||
Color raymie1; /* light arriving at x from direction w */
|
Color raymie1; /* light arriving at x from direction w */
|
||||||
|
|
||||||
|
@ -615,15 +613,15 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first)
|
||||||
* without the phase functions factors; they must be reintroduced here */
|
* without the phase functions factors; they must be reintroduced here */
|
||||||
double pr1 = _phaseFunctionR(nu1);
|
double pr1 = _phaseFunctionR(nu1);
|
||||||
double pm1 = _phaseFunctionM(nu1);
|
double pm1 = _phaseFunctionM(nu1);
|
||||||
Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu1);
|
Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu1);
|
||||||
Color mie1 = _texture4D(_deltaSMTexture, r, w.z, muS, nu1);
|
Color mie1 = _texture4D(deltaSM, r, w.z, muS, nu1);
|
||||||
raymie1.r += ray1.r * pr1 + mie1.r + pm1;
|
raymie1.r += ray1.r * pr1 + mie1.r + pm1;
|
||||||
raymie1.g += ray1.g * pr1 + mie1.g + pm1;
|
raymie1.g += ray1.g * pr1 + mie1.g + pm1;
|
||||||
raymie1.b += ray1.b * pr1 + mie1.b + pm1;
|
raymie1.b += ray1.b * pr1 + mie1.b + pm1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu1);
|
Color col = _texture4D(deltaSR, r, w.z, muS, nu1);
|
||||||
raymie1.r += col.r;
|
raymie1.r += col.r;
|
||||||
raymie1.g += col.g;
|
raymie1.g += col.g;
|
||||||
raymie1.b += col.b;
|
raymie1.b += col.b;
|
||||||
|
@ -645,6 +643,9 @@ static Color _inscatterS(double r, double mu, double muS, double nu, int first)
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Texture3D* result;
|
Texture3D* result;
|
||||||
|
Texture2D* deltaE;
|
||||||
|
Texture3D* deltaSR;
|
||||||
|
Texture3D* deltaSM;
|
||||||
int first;
|
int first;
|
||||||
} jParams;
|
} jParams;
|
||||||
|
|
||||||
|
@ -665,7 +666,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data)
|
||||||
Color raymie;
|
Color raymie;
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
raymie = _inscatterS(r, mu, muS, nu, params->first);
|
raymie = _inscatterS(r, mu, muS, nu, params->first, params->deltaE, params->deltaSR, params->deltaSM);
|
||||||
texture3DSetPixel(params->result, x, y, layer, raymie);
|
texture3DSetPixel(params->result, x, y, layer, raymie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,7 +675,7 @@ static int _jWorker(ParallelWork* work, int layer, void* data)
|
||||||
|
|
||||||
/*********************** irradianceN.glsl ***********************/
|
/*********************** irradianceN.glsl ***********************/
|
||||||
|
|
||||||
void _irradianceNProg(Texture2D* tex, int first)
|
void _irradianceNProg(Texture2D* destination, Texture3D* deltaSR, Texture3D* deltaSM, int first)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
double dphi = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES);
|
double dphi = M_PI / (double)(IRRADIANCE_INTEGRAL_SAMPLES);
|
||||||
|
@ -706,15 +707,15 @@ void _irradianceNProg(Texture2D* tex, int first)
|
||||||
without the phase functions factors; they must be reintroduced here */
|
without the phase functions factors; they must be reintroduced here */
|
||||||
double pr1 = _phaseFunctionR(nu);
|
double pr1 = _phaseFunctionR(nu);
|
||||||
double pm1 = _phaseFunctionM(nu);
|
double pm1 = _phaseFunctionM(nu);
|
||||||
Color ray1 = _texture4D(_deltaSRTexture, r, w.z, muS, nu);
|
Color ray1 = _texture4D(deltaSR, r, w.z, muS, nu);
|
||||||
Color mie1 = _texture4D(_deltaSMTexture, r, w.z, muS, nu);
|
Color mie1 = _texture4D(deltaSM, r, w.z, muS, nu);
|
||||||
result.r += (ray1.r * pr1 + mie1.r * pm1) * w.z * dw;
|
result.r += (ray1.r * pr1 + mie1.r * pm1) * w.z * dw;
|
||||||
result.g += (ray1.g * pr1 + mie1.g * pm1) * w.z * dw;
|
result.g += (ray1.g * pr1 + mie1.g * pm1) * w.z * dw;
|
||||||
result.b += (ray1.b * pr1 + mie1.b * pm1) * w.z * dw;
|
result.b += (ray1.b * pr1 + mie1.b * pm1) * w.z * dw;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Color col = _texture4D(_deltaSRTexture, r, w.z, muS, nu);
|
Color col = _texture4D(deltaSR, r, w.z, muS, nu);
|
||||||
result.r += col.r * w.z * dw;
|
result.r += col.r * w.z * dw;
|
||||||
result.g += col.g * w.z * dw;
|
result.g += col.g * w.z * dw;
|
||||||
result.b += col.b * w.z * dw;
|
result.b += col.b * w.z * dw;
|
||||||
|
@ -722,20 +723,26 @@ void _irradianceNProg(Texture2D* tex, int first)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
texture2DSetPixel(tex, x, y, result);
|
texture2DSetPixel(destination, x, y, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** inscatterN.glsl ***********************/
|
/*********************** inscatterN.glsl ***********************/
|
||||||
|
|
||||||
static Color _integrand2(double r, double mu, double muS, double nu, double t)
|
typedef struct
|
||||||
|
{
|
||||||
|
Texture3D* destination;
|
||||||
|
Texture3D* deltaJ;
|
||||||
|
} InscatterNParams;
|
||||||
|
|
||||||
|
static Color _integrand2(Texture3D* deltaJ, double r, double mu, double muS, double nu, double t)
|
||||||
{
|
{
|
||||||
double ri = sqrt(r * r + t * t + 2.0 * r * mu * t);
|
double ri = sqrt(r * r + t * t + 2.0 * r * mu * t);
|
||||||
double mui = (r * mu + t) / ri;
|
double mui = (r * mu + t) / ri;
|
||||||
double muSi = (nu * t + muS * r) / ri;
|
double muSi = (nu * t + muS * r) / ri;
|
||||||
Color c1, c2;
|
Color c1, c2;
|
||||||
c1 = _texture4D(_deltaJTexture, ri, mui, muSi, nu);
|
c1 = _texture4D(deltaJ, ri, mui, muSi, nu);
|
||||||
c2 = _transmittance3(r, mu, t);
|
c2 = _transmittance3(r, mu, t);
|
||||||
c1.r *= c2.r;
|
c1.r *= c2.r;
|
||||||
c1.g *= c2.g;
|
c1.g *= c2.g;
|
||||||
|
@ -743,16 +750,16 @@ static Color _integrand2(double r, double mu, double muS, double nu, double t)
|
||||||
return c1;
|
return c1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Color _inscatterN(double r, double mu, double muS, double nu)
|
static Color _inscatterN(Texture3D* deltaJ, double r, double mu, double muS, double nu)
|
||||||
{
|
{
|
||||||
Color raymie = COLOR_BLACK;
|
Color raymie = COLOR_BLACK;
|
||||||
double dx = _limit(r, mu) / (double)(INSCATTER_INTEGRAL_SAMPLES);
|
double dx = _limit(r, mu) / (double)(INSCATTER_INTEGRAL_SAMPLES);
|
||||||
Color raymiei = _integrand2(r, mu, muS, nu, 0.0);
|
Color raymiei = _integrand2(deltaJ, r, mu, muS, nu, 0.0);
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i)
|
for (i = 1; i <= INSCATTER_INTEGRAL_SAMPLES; ++i)
|
||||||
{
|
{
|
||||||
double xj = (double)(i) * dx;
|
double xj = (double)(i) * dx;
|
||||||
Color raymiej = _integrand2(r, mu, muS, nu, xj);
|
Color raymiej = _integrand2(deltaJ, r, mu, muS, nu, xj);
|
||||||
raymie.r += (raymiei.r + raymiej.r) / 2.0 * dx;
|
raymie.r += (raymiei.r + raymiej.r) / 2.0 * dx;
|
||||||
raymie.g += (raymiei.r + raymiej.r) / 2.0 * dx;
|
raymie.g += (raymiei.r + raymiej.r) / 2.0 * dx;
|
||||||
raymie.b += (raymiei.r + raymiej.r) / 2.0 * dx;
|
raymie.b += (raymiei.r + raymiej.r) / 2.0 * dx;
|
||||||
|
@ -765,6 +772,8 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data)
|
||||||
{
|
{
|
||||||
UNUSED(work);
|
UNUSED(work);
|
||||||
|
|
||||||
|
InscatterNParams* params = data;
|
||||||
|
|
||||||
double r;
|
double r;
|
||||||
Color dhdH;
|
Color dhdH;
|
||||||
_getLayerParams(layer, &r, &dhdH);
|
_getLayerParams(layer, &r, &dhdH);
|
||||||
|
@ -776,7 +785,7 @@ static int _inscatterNWorker(ParallelWork* work, int layer, void* data)
|
||||||
{
|
{
|
||||||
double mu, muS, nu;
|
double mu, muS, nu;
|
||||||
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
texture3DSetPixel((Texture3D*)data, x, y, layer, _inscatterN(r, mu, muS, nu));
|
texture3DSetPixel(params->destination, x, y, layer, _inscatterN(params->deltaJ, r, mu, muS, nu));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -808,10 +817,9 @@ static int _copyInscatterNWorker(ParallelWork* work, int layer, void* data)
|
||||||
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
_getMuMuSNu((double)x, (double)y, r, dhdH, &mu, &muS, &nu);
|
||||||
Color col1 = texture3DGetLinear(params->source, x / (double)(RES_MU_S * RES_NU), y / (double)(RES_MU), layer + 0.5 / (double)(RES_R));
|
Color col1 = texture3DGetLinear(params->source, x / (double)(RES_MU_S * RES_NU), y / (double)(RES_MU), layer + 0.5 / (double)(RES_R));
|
||||||
Color col2 = texture3DGetPixel(params->destination, x, y, layer);
|
Color col2 = texture3DGetPixel(params->destination, x, y, layer);
|
||||||
col2.r += col1.r * 0.1 / _phaseFunctionR(nu);
|
col2.r += col1.r / _phaseFunctionR(nu);
|
||||||
col2.g += col1.g * 0.1 / _phaseFunctionR(nu);
|
col2.g += col1.g / _phaseFunctionR(nu);
|
||||||
col2.b += col1.b * 0.1 / _phaseFunctionR(nu);
|
col2.b += col1.b / _phaseFunctionR(nu);
|
||||||
col2.a = 1.0;
|
|
||||||
texture3DSetPixel(params->destination, x, y, layer, col2);
|
texture3DSetPixel(params->destination, x, y, layer, col2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,54 +931,53 @@ static Color _getInscatterColor(Vector3* _x, double* _t, Vector3 v, Vector3 s, d
|
||||||
|
|
||||||
/*ground radiance at end of ray x+tv, when sun in direction s
|
/*ground radiance at end of ray x+tv, when sun in direction s
|
||||||
*attenuated bewteen ground and viewer (=R[L0]+R[L*]) */
|
*attenuated bewteen ground and viewer (=R[L0]+R[L*]) */
|
||||||
/*static Color _groundColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu, Color attenuation)
|
static Color _groundColor(Color base, Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu, Vector3 attenuation)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
if (t > 0.0)
|
|
||||||
{ // if ray hits ground surface
|
|
||||||
|
|
||||||
// ground reflectance at end of ray, x0
|
#if 0
|
||||||
Vector3 x0 = v3Add(x, v3Scale(v, t));
|
// ground reflectance at end of ray, x0
|
||||||
float r0 = v3Norm(x0);
|
Vector3 x0 = v3Add(x, v3Scale(v, t));
|
||||||
Vector3 n = v3Scale(x0, 1.0 / r0);
|
float r0 = v3Norm(x0);
|
||||||
vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0);
|
Vector3 n = v3Scale(x0, 1.0 / r0);
|
||||||
Color reflectance;
|
vec2 coords = vec2(atan(n.y, n.x), acos(n.z)) * vec2(0.5, 1.0) / M_PI + vec2(0.5, 0.0);
|
||||||
if (r0 > Rg + 0.01)
|
Color reflectance;
|
||||||
{
|
if (r0 > Rg + 0.01)
|
||||||
reflectance = vec4(0.4, 0.4, 0.4, 0.0);
|
{
|
||||||
}
|
reflectance = vec4(0.4, 0.4, 0.4, 0.0);
|
||||||
else
|
|
||||||
{
|
|
||||||
reflectance = texture2D(reflectanceSampler, coords) * vec4(0.2, 0.2, 0.2, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// direct sun light (radiance) reaching x0
|
|
||||||
float muS = v3Dot(n, s);
|
|
||||||
Color sunLight = _transmittanceWithShadow(r0, muS);
|
|
||||||
|
|
||||||
// precomputed sky light (irradiance) (=E[L*]) at x0
|
|
||||||
Color groundSkyLight = irradiance(irradianceSampler, r0, muS);
|
|
||||||
|
|
||||||
// light reflected at x0 (=(R[L0]+R[L*])/T(x,x0))
|
|
||||||
Color groundColor = reflectance.rgb * (max(muS, 0.0) * sunLight + groundSkyLight) * ISun / M_PI;
|
|
||||||
|
|
||||||
// water specular color due to sunLight
|
|
||||||
if (reflectance.w > 0.0)
|
|
||||||
{
|
|
||||||
vec3 h = normalize(s - v);
|
|
||||||
float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0);
|
|
||||||
float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0);
|
|
||||||
groundColor += reflectance.w * max(waterBrdf, 0.0) * sunLight * ISun;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = attenuation * groundColor; //=R[L0]+R[L*]
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // ray looking at the sky
|
{
|
||||||
return COLOR_BLACK;
|
reflectance = texture2D(reflectanceSampler, coords) * vec4(0.2, 0.2, 0.2, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// direct sun light (radiance) reaching x0
|
||||||
|
float muS = v3Dot(n, s);
|
||||||
|
Color sunLight = _transmittanceWithShadow(r0, muS);
|
||||||
|
|
||||||
|
// precomputed sky light (irradiance) (=E[L*]) at x0
|
||||||
|
Color groundSkyLight = irradiance(irradianceSampler, r0, muS);
|
||||||
|
|
||||||
|
// light reflected at x0 (=(R[L0]+R[L*])/T(x,x0))
|
||||||
|
Color groundColor = reflectance.rgb * (max(muS, 0.0) * sunLight + groundSkyLight) * ISun / M_PI;
|
||||||
|
|
||||||
|
// water specular color due to sunLight
|
||||||
|
if (reflectance.w > 0.0)
|
||||||
|
{
|
||||||
|
vec3 h = normalize(s - v);
|
||||||
|
float fresnel = 0.02 + 0.98 * pow(1.0 - dot(-v, h), 5.0);
|
||||||
|
float waterBrdf = fresnel * pow(max(dot(h, n), 0.0), 150.0);
|
||||||
|
groundColor += reflectance.w * max(waterBrdf, 0.0) * sunLight * ISun;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
result.r = attenuation.x * base.r; //=R[L0]+R[L*]
|
||||||
|
result.g = attenuation.y * base.g;
|
||||||
|
result.b = attenuation.z * base.b;
|
||||||
|
result.a = 1.0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/* direct sun light for ray x+tv, when sun in direction s (=L0) */
|
/* direct sun light for ray x+tv, when sun in direction s (=L0) */
|
||||||
static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu)
|
static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, double mu)
|
||||||
|
@ -991,7 +998,7 @@ static Color _sunColor(Vector3 x, double t, Vector3 v, Vector3 s, double r, doub
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************** Cache methods ***********************/
|
/*********************** Cache/debug methods ***********************/
|
||||||
|
|
||||||
static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order)
|
static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order)
|
||||||
{
|
{
|
||||||
|
@ -999,10 +1006,14 @@ static int _tryLoadCache2D(Texture2D* tex, const char* tag, int order)
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
|
|
||||||
texture2DGetSize(tex, &xsize, &ysize);
|
texture2DGetSize(tex, &xsize, &ysize);
|
||||||
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
|
cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, 0, order);
|
||||||
if (cacheFileIsReadable(cache))
|
if (cacheFileIsReadable(cache))
|
||||||
{
|
{
|
||||||
texture2DLoadFromFile(tex, cacheFileGetPath(cache));
|
PackStream* stream;
|
||||||
|
stream = packReadFile(cacheFileGetPath(cache));
|
||||||
|
texture2DLoad(stream, tex);
|
||||||
|
packCloseStream(stream);
|
||||||
|
|
||||||
cacheFileDeleteAccessor(cache);
|
cacheFileDeleteAccessor(cache);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1029,23 @@ static void _saveCache2D(Texture2D* tex, const char* tag, int order)
|
||||||
CacheFile* cache;
|
CacheFile* cache;
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
|
|
||||||
|
texture2DGetSize(tex, &xsize, &ysize);
|
||||||
|
cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, 0, order);
|
||||||
|
if (cacheFileIsWritable(cache))
|
||||||
|
{
|
||||||
|
PackStream* stream;
|
||||||
|
stream = packWriteFile(cacheFileGetPath(cache));
|
||||||
|
texture2DSave(stream, tex);
|
||||||
|
packCloseStream(stream);
|
||||||
|
}
|
||||||
|
cacheFileDeleteAccessor(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _saveDebug2D(Texture2D* tex, const char* tag, int order)
|
||||||
|
{
|
||||||
|
CacheFile* cache;
|
||||||
|
int xsize, ysize;
|
||||||
|
|
||||||
texture2DGetSize(tex, &xsize, &ysize);
|
texture2DGetSize(tex, &xsize, &ysize);
|
||||||
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
|
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, 0, order);
|
||||||
if (cacheFileIsWritable(cache))
|
if (cacheFileIsWritable(cache))
|
||||||
|
@ -1033,10 +1061,14 @@ static int _tryLoadCache3D(Texture3D* tex, const char* tag, int order)
|
||||||
int xsize, ysize, zsize;
|
int xsize, ysize, zsize;
|
||||||
|
|
||||||
texture3DGetSize(tex, &xsize, &ysize, &zsize);
|
texture3DGetSize(tex, &xsize, &ysize, &zsize);
|
||||||
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
|
cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, zsize, order);
|
||||||
if (cacheFileIsReadable(cache))
|
if (cacheFileIsReadable(cache))
|
||||||
{
|
{
|
||||||
texture3DLoadFromFile(tex, cacheFileGetPath(cache));
|
PackStream* stream;
|
||||||
|
stream = packReadFile(cacheFileGetPath(cache));
|
||||||
|
texture3DLoad(stream, tex);
|
||||||
|
packCloseStream(stream);
|
||||||
|
|
||||||
cacheFileDeleteAccessor(cache);
|
cacheFileDeleteAccessor(cache);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1052,6 +1084,23 @@ static void _saveCache3D(Texture3D* tex, const char* tag, int order)
|
||||||
CacheFile* cache;
|
CacheFile* cache;
|
||||||
int xsize, ysize, zsize;
|
int xsize, ysize, zsize;
|
||||||
|
|
||||||
|
texture3DGetSize(tex, &xsize, &ysize, &zsize);
|
||||||
|
cache = cacheFileCreateAccessor("atmo-br", "cache", tag, xsize, ysize, zsize, order);
|
||||||
|
if (cacheFileIsWritable(cache))
|
||||||
|
{
|
||||||
|
PackStream* stream;
|
||||||
|
stream = packWriteFile(cacheFileGetPath(cache));
|
||||||
|
texture3DSave(stream, tex);
|
||||||
|
packCloseStream(stream);
|
||||||
|
}
|
||||||
|
cacheFileDeleteAccessor(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _saveDebug3D(Texture3D* tex, const char* tag, int order)
|
||||||
|
{
|
||||||
|
CacheFile* cache;
|
||||||
|
int xsize, ysize, zsize;
|
||||||
|
|
||||||
texture3DGetSize(tex, &xsize, &ysize, &zsize);
|
texture3DGetSize(tex, &xsize, &ysize, &zsize);
|
||||||
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
|
cache = cacheFileCreateAccessor("atmo-br", "png", tag, xsize, ysize, zsize, order);
|
||||||
if (cacheFileIsWritable(cache))
|
if (cacheFileIsWritable(cache))
|
||||||
|
@ -1067,115 +1116,104 @@ void brunetonInit()
|
||||||
int x, y, z, order;
|
int x, y, z, order;
|
||||||
ParallelWork* work;
|
ParallelWork* work;
|
||||||
|
|
||||||
|
assert(_inscatterTexture == NULL);
|
||||||
|
|
||||||
/* TODO Deletes */
|
/* TODO Deletes */
|
||||||
|
_transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H);
|
||||||
|
_irradianceTexture = texture2DCreate(SKY_W, SKY_H);
|
||||||
|
_inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
|
|
||||||
|
/* try loading from cache */
|
||||||
|
if (_tryLoadCache2D(_transmittanceTexture, "transmittance", 0)
|
||||||
|
&& _tryLoadCache2D(_irradianceTexture, "irradiance", 0)
|
||||||
|
&& _tryLoadCache3D(_inscatterTexture, "inscatter", 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D* _deltaETexture = texture2DCreate(SKY_W, SKY_H);
|
||||||
|
Texture3D* _deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
|
Texture3D* _deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
|
Texture3D* _deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
||||||
|
|
||||||
/* computes transmittance texture T (line 1 in algorithm 4.1) */
|
/* computes transmittance texture T (line 1 in algorithm 4.1) */
|
||||||
_transmittanceTexture = texture2DCreate(TRANSMITTANCE_W, TRANSMITTANCE_H);
|
_precomputeTransmittanceTexture();
|
||||||
if (!_tryLoadCache2D(_transmittanceTexture, "transmittance", 0))
|
_saveDebug2D(_transmittanceTexture, "transmittance", 0);
|
||||||
{
|
|
||||||
_precomputeTransmittanceTexture();
|
|
||||||
_saveCache2D(_transmittanceTexture, "transmittance", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* computes irradiance texture deltaE (line 2 in algorithm 4.1) */
|
/* computes irradiance texture deltaE (line 2 in algorithm 4.1) */
|
||||||
_deltaETexture = texture2DCreate(SKY_W, SKY_H);
|
_precomputeIrrDeltaETexture(_deltaETexture);
|
||||||
if (!_tryLoadCache2D(_deltaETexture, "deltaE", 0))
|
_saveDebug2D(_deltaETexture, "deltaE", 0);
|
||||||
{
|
|
||||||
_precomputeIrrDeltaETexture();
|
|
||||||
_saveCache2D(_deltaETexture, "deltaE", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* computes single scattering texture deltaS (line 3 in algorithm 4.1)
|
/* computes single scattering texture deltaS (line 3 in algorithm 4.1)
|
||||||
* Rayleigh and Mie separated in deltaSR + deltaSM */
|
* Rayleigh and Mie separated in deltaSR + deltaSM */
|
||||||
_deltaSRTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture};
|
||||||
_deltaSMTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
work = parallelWorkCreate(_inscatter1Worker, RES_R, ¶ms);
|
||||||
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", 0) || !_tryLoadCache3D(_deltaSMTexture, "deltaSM", 0))
|
parallelWorkPerform(work, -1);
|
||||||
{
|
parallelWorkDelete(work);
|
||||||
Inscatter1Params params = {_deltaSRTexture, _deltaSMTexture};
|
_saveDebug3D(_deltaSRTexture, "deltaSR", 0);
|
||||||
work = parallelWorkCreate(_inscatter1Worker, RES_R, ¶ms);
|
_saveDebug3D(_deltaSMTexture, "deltaSM", 0);
|
||||||
parallelWorkPerform(work, -1);
|
|
||||||
parallelWorkDelete(work);
|
|
||||||
|
|
||||||
_saveCache3D(_deltaSRTexture, "deltaSR", 0);
|
|
||||||
_saveCache3D(_deltaSMTexture, "deltaSM", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */
|
/* copies deltaE into irradiance texture E (line 4 in algorithm 4.1) */
|
||||||
/* ??? all black texture (k=0.0) ??? */
|
/* ??? all black texture (k=0.0) ??? */
|
||||||
_irradianceTexture = texture2DCreate(SKY_W, SKY_H);
|
|
||||||
texture2DFill(_irradianceTexture, COLOR_BLACK);
|
texture2DFill(_irradianceTexture, COLOR_BLACK);
|
||||||
|
|
||||||
/* copies deltaS into inscatter texture S (line 5 in algorithm 4.1) */
|
/* copies deltaS into inscatter texture S (line 5 in algorithm 4.1) */
|
||||||
_inscatterTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
||||||
if (!_tryLoadCache3D(_inscatterTexture, "inscatter", 0))
|
|
||||||
{
|
{
|
||||||
for (x = 0; x < RES_MU_S * RES_NU; x++)
|
for (y = 0; y < RES_MU; y++)
|
||||||
{
|
{
|
||||||
for (y = 0; y < RES_MU; y++)
|
for (z = 0; z < RES_R; z++)
|
||||||
{
|
{
|
||||||
for (z = 0; z < RES_R; z++)
|
Color result = texture3DGetPixel(_deltaSRTexture, x, y, z);
|
||||||
{
|
Color mie = texture3DGetPixel(_deltaSMTexture, x, y, z);
|
||||||
Color result = texture3DGetPixel(_deltaSRTexture, x, y, z);
|
result.a = mie.r;
|
||||||
Color mie = texture3DGetPixel(_deltaSMTexture, x, y, z);
|
texture3DSetPixel(_inscatterTexture, x, y, z, result);
|
||||||
result.a = mie.r;
|
|
||||||
texture3DSetPixel(_inscatterTexture, x, y, z, result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_saveCache3D(_inscatterTexture, "inscatter", 0);
|
|
||||||
}
|
}
|
||||||
|
_saveDebug3D(_inscatterTexture, "inscatter", 0);
|
||||||
|
|
||||||
/* loop for each scattering order (line 6 in algorithm 4.1) */
|
/* loop for each scattering order (line 6 in algorithm 4.1) */
|
||||||
for (order = 2; order <= 4; ++order)
|
for (order = 2; order <= 4; ++order)
|
||||||
{
|
{
|
||||||
/* computes deltaJ (line 7 in algorithm 4.1) */
|
/* computes deltaJ (line 7 in algorithm 4.1) */
|
||||||
_deltaJTexture = texture3DCreate(RES_MU_S * RES_NU, RES_MU, RES_R);
|
jParams jparams = {_deltaJTexture, _deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2};
|
||||||
if (!_tryLoadCache3D(_deltaJTexture, "deltaJ", order))
|
work = parallelWorkCreate(_jWorker, RES_R, &jparams);
|
||||||
{
|
parallelWorkPerform(work, -1);
|
||||||
jParams params = {_deltaJTexture, order == 2};
|
parallelWorkDelete(work);
|
||||||
work = parallelWorkCreate(_jWorker, RES_R, ¶ms);
|
_saveDebug3D(_deltaJTexture, "deltaJ", order);
|
||||||
parallelWorkPerform(work, -1);
|
|
||||||
parallelWorkDelete(work);
|
|
||||||
|
|
||||||
_saveCache3D(_deltaJTexture, "deltaJ", order);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* computes deltaE (line 8 in algorithm 4.1) */
|
/* computes deltaE (line 8 in algorithm 4.1) */
|
||||||
_deltaETexture = texture2DCreate(SKY_W, SKY_H);
|
_irradianceNProg(_deltaETexture, _deltaSRTexture, _deltaSMTexture, order == 2);
|
||||||
if (!_tryLoadCache2D(_deltaETexture, "deltaE", order))
|
_saveDebug2D(_deltaETexture, "deltaE", order);
|
||||||
{
|
|
||||||
_irradianceNProg(_deltaETexture, order == 2);
|
|
||||||
_saveCache2D(_deltaETexture, "deltaE", order);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* computes deltaS (line 9 in algorithm 4.1) */
|
/* computes deltaS (line 9 in algorithm 4.1) */
|
||||||
if (!_tryLoadCache3D(_deltaSRTexture, "deltaSR", order))
|
InscatterNParams iparams = {_deltaSRTexture, _deltaJTexture};
|
||||||
{
|
work = parallelWorkCreate(_inscatterNWorker, RES_R, &iparams);
|
||||||
work = parallelWorkCreate(_inscatterNWorker, RES_R, _deltaSRTexture);
|
parallelWorkPerform(work, -1);
|
||||||
parallelWorkPerform(work, -1);
|
parallelWorkDelete(work);
|
||||||
parallelWorkDelete(work);
|
_saveDebug3D(_deltaSRTexture, "deltaSR", order);
|
||||||
|
|
||||||
_saveCache3D(_deltaSRTexture, "deltaSR", order);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adds deltaE into irradiance texture E (line 10 in algorithm 4.1) */
|
/* adds deltaE into irradiance texture E (line 10 in algorithm 4.1) */
|
||||||
if (!_tryLoadCache2D(_irradianceTexture, "irradiance", order))
|
texture2DAdd(_deltaETexture, _irradianceTexture);
|
||||||
{
|
_saveDebug2D(_irradianceTexture, "irradiance", order);
|
||||||
texture2DAdd(_deltaETexture, _irradianceTexture);
|
|
||||||
_saveCache2D(_irradianceTexture, "irradiance", order);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */
|
/* adds deltaS into inscatter texture S (line 11 in algorithm 4.1) */
|
||||||
if (!_tryLoadCache3D(_inscatterTexture, "inscatter", order))
|
CopyInscatterNParams cparams = {_deltaSRTexture, _inscatterTexture};
|
||||||
{
|
work = parallelWorkCreate(_copyInscatterNWorker, RES_R, &cparams);
|
||||||
CopyInscatterNParams params = {_deltaSRTexture, _inscatterTexture};
|
parallelWorkPerform(work, -1);
|
||||||
work = parallelWorkCreate(_copyInscatterNWorker, RES_R, ¶ms);
|
parallelWorkDelete(work);
|
||||||
parallelWorkPerform(work, -1);
|
_saveDebug3D(_inscatterTexture, "inscatter", order);
|
||||||
parallelWorkDelete(work);
|
|
||||||
|
|
||||||
_saveCache3D(_inscatterTexture, "inscatter", order);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_saveCache2D(_transmittanceTexture, "transmittance", 0);
|
||||||
|
_saveCache2D(_irradianceTexture, "irradiance", 0);
|
||||||
|
_saveCache3D(_inscatterTexture, "inscatter", 0);
|
||||||
|
|
||||||
|
texture2DDelete(_deltaETexture);
|
||||||
|
texture3DDelete(_deltaSMTexture);
|
||||||
|
texture3DDelete(_deltaSRTexture);
|
||||||
|
texture3DDelete(_deltaJTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _fixVector(Vector3* v)
|
static inline void _fixVector(Vector3* v)
|
||||||
|
@ -1188,12 +1226,12 @@ static inline void _fixVector(Vector3* v)
|
||||||
|
|
||||||
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)
|
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position)
|
||||||
{
|
{
|
||||||
Vector3 x = {0.0, Rg + eye.y, 0.0};
|
Vector3 x = {0.0, Rg + (eye.y + 20.0) * 0.1, 0.0};
|
||||||
_fixVector(&x);
|
_fixVector(&x);
|
||||||
Vector3 v = v3Normalize(direction);
|
Vector3 v = v3Normalize(direction);
|
||||||
_fixVector(&v);
|
_fixVector(&v);
|
||||||
Vector3 s = v3Normalize(v3Sub(sun_position, eye));
|
_fixVector(&sun_position);
|
||||||
_fixVector(&s);
|
Vector3 s = v3Normalize(v3Sub(sun_position, x));
|
||||||
|
|
||||||
double r = v3Norm(x);
|
double r = v3Norm(x);
|
||||||
double mu = v3Dot(x, v) / r;
|
double mu = v3Dot(x, v) / r;
|
||||||
|
@ -1220,9 +1258,53 @@ Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 attenuation;
|
Vector3 attenuation;
|
||||||
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); //S[L]-T(x,xs)S[l]|xs
|
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
||||||
/*Color groundColor = _groundColor(x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/
|
|
||||||
Color groundColor = COLOR_BLACK;
|
Color groundColor = COLOR_BLACK;
|
||||||
Color sunColor = _sunColor(x, t, v, s, r, mu); //L0
|
Color sunColor = _sunColor(x, 0.0, v, s, r, mu); /* L0 */
|
||||||
return _hdr(sunColor, groundColor, inscatterColor); // Eq (16)
|
return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */
|
||||||
|
}
|
||||||
|
|
||||||
|
Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base)
|
||||||
|
{
|
||||||
|
Vector3 eye = renderer->camera_location;
|
||||||
|
Vector3 direction = v3Scale(v3Sub(location, eye), 0.1);
|
||||||
|
Vector3 sun_position = v3Scale(renderer->atmosphere->getSunDirection(renderer), 149597870.0);
|
||||||
|
|
||||||
|
Vector3 x = {0.0, Rg + (eye.y + 20.0) * 0.1, 0.0};
|
||||||
|
_fixVector(&x);
|
||||||
|
Vector3 v = v3Normalize(direction);
|
||||||
|
_fixVector(&v);
|
||||||
|
_fixVector(&sun_position);
|
||||||
|
Vector3 s = v3Normalize(v3Sub(sun_position, x));
|
||||||
|
|
||||||
|
double r = v3Norm(x);
|
||||||
|
double mu = v3Dot(x, v) / r;
|
||||||
|
/*double t = -r * mu - sqrt(r * r * (mu * mu - 1.0) + Rg * Rg);*/
|
||||||
|
double t = v3Norm(direction);
|
||||||
|
|
||||||
|
Vector3 g = {0.0, 0.0, Rg + 10.0};
|
||||||
|
g = v3Sub(x, g);
|
||||||
|
double a = v.x * v.x + v.y * v.y - v.z * v.z;
|
||||||
|
double b = 2.0 * (g.x * v.x + g.y * v.y - g.z * v.z);
|
||||||
|
double c = g.x * g.x + g.y * g.y - g.z * g.z;
|
||||||
|
double d = -(b + sqrt(b * b - 4.0 * a * c)) / (2.0 * a);
|
||||||
|
int cone = d > 0.0 && fabs(x.z + d * v.z - Rg) <= 10.0;
|
||||||
|
|
||||||
|
if (t > 0.0)
|
||||||
|
{
|
||||||
|
if (cone && d < t)
|
||||||
|
{
|
||||||
|
t = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cone)
|
||||||
|
{
|
||||||
|
t = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 attenuation;
|
||||||
|
Color inscatterColor = _getInscatterColor(&x, &t, v, s, &r, &mu, &attenuation); /* S[L]-T(x,xs)S[l]|xs */
|
||||||
|
Color groundColor = _groundColor(base, x, t, v, s, r, mu, attenuation); //R[L0]+R[L*]*/
|
||||||
|
Color sunColor = _sunColor(x, t, v, s, r, mu); /* L0 */
|
||||||
|
return _hdr(sunColor, groundColor, inscatterColor); /* Eq (16) */
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,9 @@ static void _bindRenderer(AtmosphereRenderer* renderer, AtmosphereDefinition* de
|
||||||
case ATMOSPHERE_MODEL_PREETHAM:
|
case ATMOSPHERE_MODEL_PREETHAM:
|
||||||
renderer->applyAerialPerspective = preethamApplyAerialPerspective;
|
renderer->applyAerialPerspective = preethamApplyAerialPerspective;
|
||||||
break;
|
break;
|
||||||
|
case ATMOSPHERE_MODEL_BRUNETON:
|
||||||
|
renderer->applyAerialPerspective = brunetonApplyAerialPerspective;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
renderer->applyAerialPerspective = _fakeApplyAerialPerspective;
|
renderer->applyAerialPerspective = _fakeApplyAerialPerspective;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
void brunetonInit();
|
void brunetonInit();
|
||||||
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
Color brunetonGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
||||||
|
Color brunetonApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base);
|
||||||
|
|
||||||
Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
Color preethamGetSkyColor(AtmosphereDefinition* definition, Vector3 eye, Vector3 direction, Vector3 sun_position);
|
||||||
Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base);
|
Color preethamApplyAerialPerspective(Renderer* renderer, Vector3 location, Color base);
|
||||||
|
|
|
@ -77,25 +77,25 @@ static double unpack754(uint64_t i, unsigned bits, unsigned expbits)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackStream* packReadFile(char* filepath)
|
PackStream* packReadFile(const char* filepath)
|
||||||
{
|
{
|
||||||
PackStream* result;
|
PackStream* result;
|
||||||
|
|
||||||
result = malloc(sizeof(PackStream));
|
result = malloc(sizeof(PackStream));
|
||||||
result->fd = fopen(filepath, "rb");
|
result->fd = fopen(filepath, "rb");
|
||||||
result->write = 0;
|
result->write = 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackStream* packWriteFile(char* filepath)
|
PackStream* packWriteFile(const char* filepath)
|
||||||
{
|
{
|
||||||
PackStream* result;
|
PackStream* result;
|
||||||
|
|
||||||
result = malloc(sizeof(PackStream));
|
result = malloc(sizeof(PackStream));
|
||||||
result->fd = fopen(filepath, "wb");
|
result->fd = fopen(filepath, "wb");
|
||||||
result->write = 1;
|
result->write = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ void packWriteDouble(PackStream* stream, double* value)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
uint64_t servalue;
|
uint64_t servalue;
|
||||||
|
|
||||||
servalue = pack754_64(*value);
|
servalue = pack754_64(*value);
|
||||||
written = fwrite(&servalue, sizeof(uint64_t), 1, stream->fd);
|
written = fwrite(&servalue, sizeof(uint64_t), 1, stream->fd);
|
||||||
assert(written == 1);
|
assert(written == 1);
|
||||||
|
@ -123,17 +123,17 @@ void packReadDouble(PackStream* stream, double* value)
|
||||||
{
|
{
|
||||||
int read;
|
int read;
|
||||||
uint64_t servalue;
|
uint64_t servalue;
|
||||||
|
|
||||||
read = fread(&servalue, sizeof(uint64_t), 1, stream->fd);
|
read = fread(&servalue, sizeof(uint64_t), 1, stream->fd);
|
||||||
assert(read == 1);
|
assert(read == 1);
|
||||||
|
|
||||||
*value = unpack754_64(servalue);
|
*value = unpack754_64(servalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packWriteInt(PackStream* stream, int* value)
|
void packWriteInt(PackStream* stream, int* value)
|
||||||
{
|
{
|
||||||
int written;
|
int written;
|
||||||
|
|
||||||
written = fprintf(stream->fd, "%d;", *value);
|
written = fprintf(stream->fd, "%d;", *value);
|
||||||
assert(written > 1);
|
assert(written > 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct PackStream PackStream;
|
typedef struct PackStream PackStream;
|
||||||
|
|
||||||
PackStream* packReadFile(char* filepath);
|
PackStream* packReadFile(const char* filepath);
|
||||||
PackStream* packWriteFile(char* filepath);
|
PackStream* packWriteFile(const char* filepath);
|
||||||
void packCloseStream(PackStream* stream);
|
void packCloseStream(PackStream* stream);
|
||||||
|
|
||||||
void packWriteDouble(PackStream* stream, double* value);
|
void packWriteDouble(PackStream* stream, double* value);
|
||||||
|
@ -17,7 +17,7 @@ void packWriteInt(PackStream* stream, int* value);
|
||||||
void packReadInt(PackStream* stream, int* value);
|
void packReadInt(PackStream* stream, int* value);
|
||||||
void packWriteString(PackStream* stream, char* value, int max_length);
|
void packWriteString(PackStream* stream, char* value, int max_length);
|
||||||
void packReadString(PackStream* stream, char* value, int max_length);
|
void packReadString(PackStream* stream, char* value, int max_length);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,8 @@ static void _copyDefinition(TerrainDefinition* source, TerrainDefinition* destin
|
||||||
destination->scaling = source->scaling;
|
destination->scaling = source->scaling;
|
||||||
destination->shadow_smoothing = source->shadow_smoothing;
|
destination->shadow_smoothing = source->shadow_smoothing;
|
||||||
|
|
||||||
|
noiseCopy(source->_height_noise, destination->_height_noise);
|
||||||
|
|
||||||
_validateDefinition(destination);
|
_validateDefinition(destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +53,7 @@ static void _saveDefinition(PackStream* stream, TerrainDefinition* definition)
|
||||||
packWriteDouble(stream, &definition->height);
|
packWriteDouble(stream, &definition->height);
|
||||||
packWriteDouble(stream, &definition->scaling);
|
packWriteDouble(stream, &definition->scaling);
|
||||||
packWriteDouble(stream, &definition->shadow_smoothing);
|
packWriteDouble(stream, &definition->shadow_smoothing);
|
||||||
|
noiseSaveGenerator(stream, definition->_height_noise);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _loadDefinition(PackStream* stream, TerrainDefinition* definition)
|
static void _loadDefinition(PackStream* stream, TerrainDefinition* definition)
|
||||||
|
@ -58,6 +61,7 @@ static void _loadDefinition(PackStream* stream, TerrainDefinition* definition)
|
||||||
packReadDouble(stream, &definition->height);
|
packReadDouble(stream, &definition->height);
|
||||||
packReadDouble(stream, &definition->scaling);
|
packReadDouble(stream, &definition->scaling);
|
||||||
packReadDouble(stream, &definition->shadow_smoothing);
|
packReadDouble(stream, &definition->shadow_smoothing);
|
||||||
|
noiseLoadGenerator(stream, definition->_height_noise);
|
||||||
|
|
||||||
_validateDefinition(definition);
|
_validateDefinition(definition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,6 +157,31 @@ void texture2DAdd(Texture2D* source, Texture2D* destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void texture2DSave(PackStream* stream, Texture2D* tex)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
packWriteInt(stream, &tex->xsize);
|
||||||
|
packWriteInt(stream, &tex->ysize);
|
||||||
|
n = tex->xsize * tex->ysize;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
colorSave(stream, tex->data + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void texture2DLoad(PackStream* stream, Texture2D* tex)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
packReadInt(stream, &tex->xsize);
|
||||||
|
packReadInt(stream, &tex->ysize);
|
||||||
|
n = tex->xsize * tex->ysize;
|
||||||
|
tex->data = realloc(tex->data, sizeof(Color) * n);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
colorLoad(stream, tex->data + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void texture2DSaveToFile(Texture2D* tex, const char* filepath)
|
void texture2DSaveToFile(Texture2D* tex, const char* filepath)
|
||||||
{
|
{
|
||||||
systemSavePictureFile(filepath, (PictureCallbackSavePixel)texture2DGetPixel, tex, tex->xsize, tex->ysize);
|
systemSavePictureFile(filepath, (PictureCallbackSavePixel)texture2DGetPixel, tex, tex->xsize, tex->ysize);
|
||||||
|
@ -325,6 +350,33 @@ void texture3DAdd(Texture3D* source, Texture3D* destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void texture3DSave(PackStream* stream, Texture3D* tex)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
packWriteInt(stream, &tex->xsize);
|
||||||
|
packWriteInt(stream, &tex->ysize);
|
||||||
|
packWriteInt(stream, &tex->zsize);
|
||||||
|
n = tex->xsize * tex->ysize * tex->zsize;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
colorSave(stream, tex->data + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void texture3DLoad(PackStream* stream, Texture3D* tex)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
packReadInt(stream, &tex->xsize);
|
||||||
|
packReadInt(stream, &tex->ysize);
|
||||||
|
packReadInt(stream, &tex->zsize);
|
||||||
|
n = tex->xsize * tex->ysize * tex->zsize;
|
||||||
|
tex->data = realloc(tex->data, sizeof(Color) * n);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
colorLoad(stream, tex->data + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static Color _callbackTex3dSave(Texture3D* tex, int x, int y)
|
static Color _callbackTex3dSave(Texture3D* tex, int x, int y)
|
||||||
{
|
{
|
||||||
int z = y / tex->ysize;
|
int z = y / tex->ysize;
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../color.h"
|
#include "../color.h"
|
||||||
|
#include "../pack.h"
|
||||||
|
|
||||||
typedef struct Texture2D Texture2D;
|
typedef struct Texture2D Texture2D;
|
||||||
typedef struct Texture3D Texture3D;
|
typedef struct Texture3D Texture3D;
|
||||||
|
@ -24,6 +25,8 @@ Color texture2DGetLinear(Texture2D* tex, double dx, double dy);
|
||||||
Color texture2DGetCubic(Texture2D* tex, double dx, double dy);
|
Color texture2DGetCubic(Texture2D* tex, double dx, double dy);
|
||||||
void texture2DFill(Texture2D* tex, Color col);
|
void texture2DFill(Texture2D* tex, Color col);
|
||||||
void texture2DAdd(Texture2D* source, Texture2D* destination);
|
void texture2DAdd(Texture2D* source, Texture2D* destination);
|
||||||
|
void texture2DSave(PackStream* stream, Texture2D* tex);
|
||||||
|
void texture2DLoad(PackStream* stream, Texture2D* tex);
|
||||||
void texture2DSaveToFile(Texture2D* tex, const char* filepath);
|
void texture2DSaveToFile(Texture2D* tex, const char* filepath);
|
||||||
void texture2DLoadFromFile(Texture2D* tex, const char* filepath);
|
void texture2DLoadFromFile(Texture2D* tex, const char* filepath);
|
||||||
|
|
||||||
|
@ -37,6 +40,8 @@ Color texture3DGetLinear(Texture3D* tex, double dx, double dy, double dz);
|
||||||
Color texture3DGetCubic(Texture3D* tex, double dx, double dy, double dz);
|
Color texture3DGetCubic(Texture3D* tex, double dx, double dy, double dz);
|
||||||
void texture3DFill(Texture3D* tex, Color col);
|
void texture3DFill(Texture3D* tex, Color col);
|
||||||
void texture3DAdd(Texture3D* source, Texture3D* destination);
|
void texture3DAdd(Texture3D* source, Texture3D* destination);
|
||||||
|
void texture3DSave(PackStream* stream, Texture3D* tex);
|
||||||
|
void texture3DLoad(PackStream* stream, Texture3D* tex);
|
||||||
void texture3DSaveToFile(Texture3D* tex, const char* filepath);
|
void texture3DSaveToFile(Texture3D* tex, const char* filepath);
|
||||||
void texture3DLoadFromFile(Texture3D* tex, const char* filepath);
|
void texture3DLoadFromFile(Texture3D* tex, const char* filepath);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue