Problem: vertices with normals pointing into sun's direction are lit even when the sun is on the other side of planet. |
Now, a few words about planet - we decided to go that way because we thought it will add a nice realistic touch to how players experience the world - for example, they can actually go around and arrive at the same place from which they departed. There are a lot of other cool things about having a planet, but it also introduces new problems. One of them is how diffuse sunlight works.
First problem was easily solved - our sun was static and didn't really move. It turned out that all the code for moving was already written by Milcho, but Update() function for the planet wasn't called. Once I fixed it we got a day/night cycle with sun circling around the planet (its of course not how it happens in real world, but moving planet around the sun would be much harder and not really worth the effort, so we use usual simplistic model), but one major problem remained - because some vertex normals pointed downwards towards the planet core, they were lit by the sun while it was on the other side of the planet! This is the reason of strangely lit holes on our screenshot page.
After a quick brain storm we found some solution that had a slight chance of success - we needed a "horizon" of some kind. Because we no longer had a flat terrain, we couldn't just hardcode horizon to be, for example along XZ plane. For each vertex on the planet's surface, horizon will be different. This is what we came up with:
Problem: vertex is lit even at night because its normal points towards the sun |
Solution: adding a "fake" horizon that determines area where the sun is "active" for a given vertex |
Our horizon is a plane that goes through vertex position and is perpendicular to vertex up vector. We compute dot product of up vector (U) and vertex to sun vector (VS). If the result of dot product is negative, it means sun is outside of our horizon (night), if its positive or zero - its in the horizon (day).
Pseudo-code in GLSL vertex shader looks like this:
vertexToSun = normalize(sunPosition - vertexPosition)
sunInHorizon = dot(upVector, vertexToSun)
sunIntensity = 1.0
sunFade = 0.2 // sunlight will fade when the dot product is less or equal 0.2
if (sunInHorizon < 0)
{
// no diffuse light
sunIntensity = 0.0
}
else
{
// we fade sunlight
if (sunInHorizon <= sunFade)
{
sunIntensity = sunInHorizon / sunFade
}
}
diffuse = sunIntensity * diffuseLight
This way we solved problem of lighting vertices that have normals pointing into sun direction while sun is on wrong side of the planet and achieved a nice day/night transition over the whole planet. Timelapse of this effect can be seen on this video:
Its probably still far from perfect, but works ok for now. In next part of day/night series I'd like to optimize and correct some things presented today and also add day/night effects to our skydome, which right now remains white despite time of day change.