Skip to content

Commit

Permalink
improve planet rings shaders (#5708)
Browse files Browse the repository at this point in the history
* improve planet rings shaders

All rings are assumed to be icy

1) Each object in ring is darker depending of its phase
   (like Moon phases)
2) Each object shines brightly if sun is behind the ring
   (lot of low angle specular reflections)
3) Each object shines brightly if looking from the sun
   (simulating high geometric albedo > 1.0)

* Move phase functions into a library

* Fix black edges of planetary rings
  • Loading branch information
Mc-Pain authored Jan 18, 2024
1 parent 87702bf commit f9a920c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 3 deletions.
19 changes: 19 additions & 0 deletions data/shaders/opengl/lib.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ struct Surface {
float ambientOcclusion;
};

// Phase functions
// https://www.scratchapixel.com/lessons/procedural-generation-virtual-worlds/simulating-sky/simulating-colors-of-the-sky.html
float miePhaseFunction(const float g, const float mu)
{
/*
* Mie phase function:
*/
return 3.f / (8.f * 3.141592) * ((1.f - g * g) * (1.f + mu * mu)) / ((2.f + g * g) * pow(1.f + g * g - 2.f * g * mu, 1.5f));
}

float rayleighPhaseFunction(const float mu)
{
/*
* Rayleigh phase function:
*/
return 3.f / (16.f * 3.141592) * (1 + mu * mu);
}


// Currently used by: hopefully everything
// Evaluates a standard blinn-phong diffuse+specular, with the addition of a
// light intensity term to scale the lighting contribution based on (pre-calculated)
Expand Down
17 changes: 16 additions & 1 deletion data/shaders/opengl/planetrings.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
uniform sampler2D texture0;
in vec2 texCoord0;
in vec4 texCoord1;
in vec4 varyingEyepos;

out vec4 frag_color;

Expand All @@ -16,10 +17,24 @@ void main(void)
vec4 col = vec4(0.0);
vec4 texCol = texture(texture0, texCoord0);

vec3 eyenorm = normalize(varyingEyepos.xyz);

for (int i=0; i<NUM_LIGHTS; ++i) {
float l = findSphereEyeRayEntryDistance(-vec3(texCoord1), vec3(uViewMatrixInverse * uLight[i].position), 1.0);
if (l <= 0.0) {
col = col + texCol*uLight[i].diffuse;
// first term: diffuse light phase (like in full/new moon)
float mu = dot(normalize(vec3(uLight[i].position)), eyenorm);
float diffuse = sqrt((1 - mu) / 2);

// second term: diffuse mie (scattering through ring)
float g = 0.76f;
float phaseThrough = miePhaseFunction(g, mu);

// third term: reflect mie (imitate albedo >= 1.0)
float muRev = dot(-normalize(vec3(uLight[i].position)), eyenorm);
float phaseReflect = miePhaseFunction(g, muRev);

col = col + texCol * (diffuse + phaseThrough + phaseReflect) * uLight[i].diffuse;
}
}
col.a = texCol.a;
Expand Down
2 changes: 2 additions & 0 deletions data/shaders/opengl/planetrings.vert
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@

out vec2 texCoord0;
out vec4 texCoord1;
out vec4 varyingEyepos;

void main(void)
{
gl_Position = matrixTransform();

texCoord0 = a_uv0.xy;
texCoord1 = a_vertex;
varyingEyepos = uViewMatrix * a_vertex;
}
4 changes: 2 additions & 2 deletions src/Planet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ void Planet::GenerateRings(Graphics::Renderer *renderer)
{
Color *row;
row = buf.get();
std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLACK);
std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLANK);
row = buf.get() + (RING_TEXTURE_LENGTH - 1) * RING_TEXTURE_WIDTH;
std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLACK);
std::fill_n(row, RING_TEXTURE_WIDTH, Color::BLANK);
}

const vector3f texSize(RING_TEXTURE_WIDTH, RING_TEXTURE_LENGTH, 0.0f);
Expand Down

0 comments on commit f9a920c

Please sign in to comment.