Skip to content

Commit 2caeb3f

Browse files
committed
experimental: pre-calculate integral density
1 parent 4d602ce commit 2caeb3f

File tree

7 files changed

+155
-2
lines changed

7 files changed

+155
-2
lines changed

data/shaders/opengl/rayleigh_accurate.frag

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
uniform int NumShadows;
1010
uniform sampler2D scatterLUT;
11+
uniform sampler2D rayleighLUT;
12+
uniform sampler2D mieLUT;
1113

1214
in vec4 varyingEyepos;
1315
in vec4 vertexColor;
@@ -54,4 +56,21 @@ void main(void)
5456

5557
frag_color = toSRGB(1 - exp(-color));
5658

59+
#if 1
60+
frag_color = vec4(0.f, 0.f, 0.f, 1.f);
61+
62+
// gl_FragCoord: [0-1280], [0, 720]
63+
64+
frag_color.x = texelFetch(rayleighLUT, ivec2(gl_FragCoord.x - 512, gl_FragCoord.y - 232), 0).x;
65+
//frag_color.y = texture(mieLUT, vec2(gl_FragCoord.x / (64 * 2), gl_FragCoord.y / (36 * 256))).x;
66+
// draw border
67+
bool outer_range = (136 < gl_FragCoord.x) || (620 < gl_FragCoord.y);
68+
bool inner_range = (gl_FragCoord.x < 128) && (gl_FragCoord.y < 612);
69+
70+
if (!inner_range && !outer_range) {
71+
frag_color.xyz = vec3(0.f, 0.f, 0.25f);
72+
}
73+
74+
//frag_color.xyz = texelFetch(scatterLUT, ivec2(gl_FragCoord.x / 64, gl_FragCoord.y / 36), 0).x == 0 ? vec3(0.1f, 0.0f, 0.1f) : vec3(0.0f, 0.0f, 0.1f);
75+
#endif
5776
}

data/shaders/opengl/rayleigh_accurate.shaderdef

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
Shader rayleigh_accurate
55

66
Texture sampler2D scatterLUT
7+
Texture sampler2D rayleighLUT
8+
Texture sampler2D mieLUT
79

810
Buffer LightData binding=0
911
Buffer DrawData binding=1

src/BaseSphere.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,46 @@ void BaseSphere::SetMaterialParameters(const matrix4x4d &trans, const float radi
143143
static_cast<void *>(buf.get()), texSize,
144144
Graphics::TEXTURE_R32);
145145

146+
std::unique_ptr<float, FreeDeleter> bufR(
147+
static_cast<float *>(malloc((DENSITY_STEPS + 1) * (DENSITY_STEPS + 1) * sizeof(float))));
148+
std::unique_ptr<float, FreeDeleter> bufM(
149+
static_cast<float *>(malloc((DENSITY_STEPS + 1) * (DENSITY_STEPS + 1) * sizeof(float))));
150+
151+
for (int i = 0; i <= DENSITY_STEPS; ++i) {
152+
for (int j = 0; j <= DENSITY_STEPS; ++j) {
153+
int index = i * (DENSITY_STEPS + 1) + j;
154+
155+
bufR.get()[index] = 0.5 + (ap.logDensityMapR[index] / 256);
156+
bufM.get()[index] = 0.5 + (ap.logDensityMapM[index] / 256);
157+
}
158+
}
159+
160+
const vector3f texSizeR(DENSITY_STEPS + 1, DENSITY_STEPS + 1, 0.f);
161+
const vector3f texSizeM(DENSITY_STEPS + 1, DENSITY_STEPS + 1, 0.f);
162+
const Graphics::TextureDescriptor texDescR(
163+
Graphics::TEXTURE_R32, texSizeR, Graphics::LINEAR_CLAMP, false, true, true, 0, Graphics::TEXTURE_2D);
164+
const Graphics::TextureDescriptor texDescM(
165+
Graphics::TEXTURE_R32, texSizeM, Graphics::LINEAR_CLAMP, false, true, true, 0, Graphics::TEXTURE_2D);
166+
167+
m_scatteringTextureR.Reset(Pi::renderer->CreateTexture(texDescR));
168+
m_scatteringTextureR->Update(static_cast<void *>(bufR.get()), texSizeR, Graphics::TEXTURE_R32);
169+
170+
m_scatteringTextureM.Reset(Pi::renderer->CreateTexture(texDescM));
171+
m_scatteringTextureM->Update(static_cast<void *>(bufM.get()), texSizeM, Graphics::TEXTURE_R32);
172+
146173
// FIXME: these two should share the same buffer data instead of making two separate allocs
147174
m_surfaceMaterial->SetBufferDynamic(s_baseSphereData, &matData);
148175
m_surfaceMaterial->SetPushConstant(s_numShadows, int(shadows.size()));
149176
m_surfaceMaterial->SetTexture("scatterLUT"_hash, m_scatteringTexture.Get());
177+
m_surfaceMaterial->SetTexture("rayleighLUT"_hash, m_scatteringTextureR.Get());
178+
m_surfaceMaterial->SetTexture("mieLUT"_hash, m_scatteringTextureM.Get());
150179

151180
if (m_atmosphereMaterial.Valid() && ap.atmosDensity > 0.0) {
152181
m_atmosphereMaterial->SetBufferDynamic(s_baseSphereData, &matData);
153182
m_atmosphereMaterial->SetPushConstant(s_numShadows, int(shadows.size()));
154183
m_atmosphereMaterial->SetTexture("scatterLUT"_hash, m_scatteringTexture.Get());
184+
m_atmosphereMaterial->SetTexture("rayleighLUT"_hash, m_scatteringTextureR.Get());
185+
m_atmosphereMaterial->SetTexture("mieLUT"_hash, m_scatteringTextureM.Get());
155186
}
156187
}
157188

src/BaseSphere.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ class BaseSphere {
6666
AtmosphereParameters m_atmosphereParameters;
6767

6868
RefCountedPtr<Graphics::Texture> m_scatteringTexture;
69+
RefCountedPtr<Graphics::Texture> m_scatteringTextureR;
70+
RefCountedPtr<Graphics::Texture> m_scatteringTextureM;
6971

7072
private:
7173
static void ResetAtmosphereGeometry(Graphics::Renderer *renderer);

src/galaxy/AtmosphereParameters.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct AtmosphereParameters {
1717
vector3f mieCoefficients;
1818
vector2f scaleHeight;
1919
vector2f logDensityMap[DENSITY_STEPS + 1];
20+
float logDensityMapR[(DENSITY_STEPS + 1)*(DENSITY_STEPS + 1)];
21+
float logDensityMapM[(DENSITY_STEPS + 1)*(DENSITY_STEPS + 1)];
2022
};
2123

2224
#endif // ATMOSPHEREPARAMETERS_H_INCLUDED

src/galaxy/StarSystemGenerator.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,9 @@ void StarSystemCustomGenerator::CustomGetKidsOf(RefCountedPtr<StarSystem::Genera
429429

430430
if (kid->GetType() != SystemBody::TYPE_STARPORT_SURFACE) {
431431
if (kid->GetSuperType() == SystemBody::SUPERTYPE_STARPORT) {
432-
fixed lowestOrbit = fixed().FromDouble(parent->CalcAtmosphereParams().atmosRadius + 500000.0 / EARTH_RADIUS);
432+
const double parentAtmosRadius = 1.0 + parent->GetAtmRadius() / parent->GetRadius();
433+
434+
fixed lowestOrbit = fixed().FromDouble(parentAtmosRadius + 500000.0 / EARTH_RADIUS);
433435
if (kid->GetOrbit().GetSemiMajorAxis() < lowestOrbit.ToDouble()) {
434436
Error("%s's orbit is too close to its parent (%.2f/%.2f)", kid->m_name.c_str(), kid->GetOrbit().GetSemiMajorAxis(), lowestOrbit.ToFloat());
435437
}
@@ -1661,7 +1663,9 @@ void PopulateStarSystemGenerator::PopulateAddStations(SystemBody *sbody, StarSys
16611663

16621664
if (sbody->GetPopulationAsFixed() < fixed(1, 1000)) return;
16631665
fixed orbMaxS = fixed(1, 4) * fixed(CalcHillRadius(sbody));
1664-
fixed orbMinS = fixed().FromDouble((sbody->CalcAtmosphereParams().atmosRadius + +500000.0 / EARTH_RADIUS)) * AU_EARTH_RADIUS;
1666+
1667+
const double sbodyAtmosRadius = 1.0 + sbody->GetAtmRadius() / sbody->GetRadius();
1668+
fixed orbMinS = fixed().FromDouble((sbodyAtmosRadius + +500000.0 / EARTH_RADIUS)) * AU_EARTH_RADIUS;
16651669
if (sbody->GetNumChildren() > 0)
16661670
orbMaxS = std::min(orbMaxS, fixed(1, 2) * sbody->GetChildren()[0]->GetOrbMinAsFixed());
16671671

src/galaxy/SystemBody.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,33 @@ vector3f SystemBody::GetCoefficients(const double radius, const double atmHeight
413413
return vector3f(k, b, c);
414414
}
415415

416+
/*
417+
* given ray and a circle, calculate points where ray intersects a circle
418+
* r - radius of a circle
419+
* v - ray start, given circle center is at origin
420+
* dir - ray direction, pre-normalized
421+
* x1, x2 - solutions
422+
*
423+
* returns false if circle is not intersected
424+
*/
425+
bool rayCircleIntersection(double *x1, double *x2, const vector2d v, const double radius, const vector2d dir)
426+
{
427+
double b = -(v.x * dir.x + v.y * dir.y);
428+
double det = (b * b) - v.LengthSqr() + (radius * radius);
429+
//Output("DEBUG: v = [%lf, %lf], radius = %lf, dir = [%lf, %lf], b = %lf, det = %lf\n", v.x, v.y, radius, dir.x, dir.y, b, det);
430+
431+
if (det >= 0) {
432+
double sdet = sqrt(det);
433+
434+
*x1 = b - sdet;
435+
*x2 = b + sdet;
436+
437+
return true;
438+
} else {
439+
return false;
440+
}
441+
}
442+
416443
// Calculate parameters used in the atmospheric model for shaders
417444
AtmosphereParameters SystemBody::CalcAtmosphereParams() const
418445
{
@@ -493,6 +520,72 @@ AtmosphereParameters SystemBody::CalcAtmosphereParams() const
493520
params.logDensityMap[i] = vector2f(rLogDensity, mLogDensity);
494521
}
495522

523+
// tests
524+
double tx1, tx2;
525+
if (GetName() == "Mars") {
526+
rayCircleIntersection(&tx1, &tx2, vector2d(0.0, 4.0), 5.0, vector2d(0.0, 1.0));
527+
//Output("%s: test intersections %lf, %lf\n", GetName().c_str(), tx1, tx2);
528+
rayCircleIntersection(&tx1, &tx2, vector2d(0.0, 4.0), 5.0, vector2d(1.0, 0.0));
529+
//Output("%s: test intersections %lf, %lf\n", GetName().c_str(), tx1, tx2);
530+
}
531+
532+
Output("%s: generating density model\n", GetName());
533+
534+
// pre-calculate density LUT based on current height and angle to horizon
535+
for (int i = 0; i <= DENSITY_STEPS; ++i) {
536+
double startHeight = i * atmosHeight / DENSITY_STEPS;
537+
538+
for (int j = 0; j <= DENSITY_STEPS; ++j) {
539+
// pitch in radians
540+
double pitch = M_PI * ((1.0 * j / DENSITY_STEPS) - 0.5);
541+
vector2d direction = vector2d(1.0, 0.0).Rotate(pitch); // calculate in 2d space
542+
vector2d tCurrent = vector2d(0.0, startHeight + radiusPlanet_in_m);
543+
544+
double atm1 = 0.0, atm2 = 0.0;
545+
bool atmIntersection = rayCircleIntersection(&atm1, &atm2, tCurrent, radiusPlanet_in_m * params.atmosRadius, direction);
546+
547+
if (!atmIntersection)
548+
continue;
549+
550+
double planet1 = 0.0, planet2 = 0.0;
551+
bool planetIntersection = rayCircleIntersection(&planet1, &planet2, tCurrent, radiusPlanet_in_m - 0.01, direction);
552+
553+
double startRay = 0.0, finishRay = atm2;
554+
if (planetIntersection) {
555+
if (planet1 >= 0) finishRay = planet1; // we hit the planet
556+
557+
// otherwise we would hit the planet while tracing *backwards*
558+
}
559+
560+
int numSamples = 16;
561+
double segment = (finishRay - startRay) / numSamples;
562+
double rDensity = 0.0, mDensity = 0.0;
563+
for (int k = 0; k < numSamples; ++k) {
564+
vector2d samplePosition = tCurrent + (segment * 0.5) * direction;
565+
double sampleHeight = samplePosition.Length() - radiusPlanet_in_m;
566+
567+
double sampleDensityR = GetAtmDensity(sampleHeight, GetAtmPressure(sampleHeight));
568+
double sampleDensityM = GetAtmDensity(6.66 * sampleHeight, GetAtmPressure(6.66 * sampleHeight));
569+
if (std::isnan(sampleDensityM))
570+
sampleDensityM = 0.0;
571+
572+
rDensity += segment * sampleDensityR;
573+
mDensity += segment * sampleDensityM;
574+
575+
tCurrent += direction * segment;
576+
}
577+
578+
double rLogDensity, mLogDensity;
579+
580+
rLogDensity = rDensity > 0.0 ? log(rDensity) : -128.0;
581+
mLogDensity = mDensity > 0.0 ? log(mDensity) : -128.0;
582+
583+
if (GetName() == "Mars") {
584+
//Output("%s: calculated density for ray (height = %lf, pitch = %lf): log(r) = %lf, log(m) = %lf\n\n", GetName().c_str(), startHeight, pitch, rLogDensity, mLogDensity);
585+
}
586+
}
587+
}
588+
496589
return params;
497590
}
498591

0 commit comments

Comments
 (0)