I am attempting to use Sean O'Neil's shaders to accomplish atmospheric scattering. For now I am just using SkyFromSpace and GroundFromSpace. The atmosphere works fine but the planet itself is just a giant dark sphere with a white blotch that follows the camera. I think the problem might rest in the "v3Attenuation" variable as when this is removed the sphere is show (albeit without scattering). Here is the vertex shader. Thanks for the time!
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldMatrix;
uniform vec3 m_v3CameraPos; // The camera's current position
uniform vec3 m_v3LightPos; // The direction vector to the light source
uniform vec3 m_v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels
uniform float m_fCameraHeight; // The camera's current height
uniform float m_fCameraHeight2; // fCameraHeight^2
uniform float m_fOuterRadius; // The outer (atmosphere) radius
uniform float m_fOuterRadius2; // fOuterRadius^2
uniform float m_fInnerRadius; // The inner (planetary) radius
uniform float m_fInnerRadius2; // fInnerRadius^2
uniform float m_fKrESun; // Kr * ESun
uniform float m_fKmESun; // Km * ESun
uniform float m_fKr4PI; // Kr * 4 * PI
uniform float m_fKm4PI; // Km * 4 * PI
uniform float m_fScale; // 1 / (fOuterRadius - fInnerRadius)
uniform float m_fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
uniform float m_fScaleOverScaleDepth; // fScale / fScaleDepth
attribute vec4 inPosition;
vec3 v3ELightPos = vec3(g_WorldMatrix * vec4(m_v3LightPos, 1.0));
vec3 v3ECameraPos= vec3(g_WorldMatrix * vec4(m_v3CameraPos, 1.0));
const int nSamples = 2;
const float fSamples = 2.0;
varying vec4 color;
float scale(float fCos)
{
float x = 1.0 - fCos;
return m_fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}
void main(void)
{
gl_Position = g_WorldViewProjectionMatrix * inPosition;
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
vec3 v3Pos = vec3(g_WorldMatrix * inPosition);
vec3 v3Ray = v3Pos - v3ECameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;
// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
float B = 2.0 * dot(m_v3CameraPos, v3Ray);
float C = m_fCameraHeight2 - m_fOuterRadius2;
float fDet = max(0.0, B*B - 4.0 * C);
float fNear = 0.5 * (-B - sqrt(fDet));
// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = m_v3CameraPos + v3Ray * fNear;
fFar -= fNear;
float fDepth = exp((m_fInnerRadius - m_fOuterRadius) / m_fScaleDepth);
float fCameraAngle = dot(-v3Ray, v3Pos) / fFar;
float fLightAngle = dot(v3ELightPos, v3Pos) / fFar;
float fCameraScale = scale(fCameraAngle);
float fLightScale = scale(fLightAngle);
float fCameraOffset = fDepth*fCameraScale;
float fTemp = (fLightScale + fCameraScale);
// Initialize the scattering loop variables
float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * m_fScale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;
// Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
vec3 v3Attenuate;
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(m_fScaleOverScaleDepth * (m_fInnerRadius - fHeight));
float fScatter = fDepth*fTemp - fCameraOffset;
v3Attenuate = exp(-fScatter * (m_v3InvWavelength * m_fKr4PI + m_fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}
vec3 first = v3FrontColor * (m_v3InvWavelength * m_fKrESun + m_fKmESun);
vec3 secondary = v3Attenuate;
color = vec4((first + vec3(0.25,0.25,0.25) * secondary), 1.0);
// ^^ that color is passed to the frag shader and is used as the gl_FragColor
}
Here is also an image of the problem:
Something strange of note: there is a different effect present when I use gl_Color and a varying variable. This is what I get when I use gl_FragColor = vec4( c0 + vec3(0.25,0.25,0.30), 1.0); where c0 is the varying version of "first" below:
and here is the product when gl_Color.rgb is used in place of c0 and c0 is replaced with gl_FrontColor on the vertex side:
And finally when gl_Color and gl_Secondary color are used together the sphere is entirely black with a white blotch as seen above...
EDIT: Here is the section where I create the spheres and apply their corresponding materials:
Mesh plan = makePlanet();
pla = new Geometry("Mesh" , plan);
mat_P = new Material(assetManager, "GroundFromSpace.j3md");
setupGroundMaterial(mat_P);
pla.setMaterial(mat_P);
Mesh atmosphere = makeAtmosphere();
atm = new Geometry("Mesh", atmosphere);
mat_A = new Material(assetManager, "SkyFromSpace.j3md");
mat_A.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Front);
setupSkyMaterial(mat_A);
atm.setMaterial(mat_A);
setUpMaterial(); just enters the scattering parameters into the shaders.
public Mesh makePlanet(){
planet = new Planet(4, new Vector3f(0,0,0));
Mesh pl = new Sphere(128,128,planet.getRadius());
return pl;
}
public Mesh makeAtmosphere(){
Mesh atmosphere = new Sphere(128, 128, planet.getOuterRadius());
return atmosphere;
}
Something interesting. I changed the number of samples taken in ground from space scattering from 4 to 400 and the following result was observed:
The color still isn't right (it's supposed to be (0.25,0.25,0.25)) and this obviously isn't a fix since the number of samples should be much less...But why could this be happening?