I am writing an OpenGL ES 2.0 app which renders a 3D island. I already have code to generate a sky dome around the island. This is a hemisphere comprised of triangles which over lay the island with z point upwards.
The dome has some very basic moving clouds created using a perlin noise texture overlaid over itself and moving different speeds.
But ultimately I need the dome to also render:
- Sun (which tracks across the sky) Moon (including phase)
- Stars (at night)
- Distant land as a static texture
- Different colours to simulate night, dawn, dusk, day
I need to do this quite efficiently since it will end up on Android although for the moment its running in a test harness. So the sun, moon and stars for example will just be textures although their points may be plotted with reasonable accuracy.
I already have the code to generate the dome, and code to plot a sun against a date and time. So mostly its the shaders I need and what they're supplied with.
Is there any example which demonstrates these things? I've found plenty which do basic cube maps, or limited stuff, but nothing to the level of sophistication I need. Obviously since this is OpenGL ES 2.0 it has to be done in shaders.
The shader for my existing sky dome renders 2 layers of perlin noise to simulate clouds. The texture wraps continuously so I can compute the u offset based on the angle of a dome's vertex into the xy plane (by feeding the x and y into atan) and the v offset using the dome's vertex z.
The vertex shader demonstrates how I do it:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
attribute vec4 aVertex;
uniform mat4 uPMVMatrix;
uniform float uTime;
uniform float uSkyDomeRadius;
const float PI = 3.1415926535897932384626433832795;
varying vec2 texCoord0, texCoord1;
void main()
{
vec2 centre = vec2(600., 600.);
gl_Position = uPMVMatrix * aVertex;
float slow_time = uTime / 100.;
vec2 dome_point = aVertex.xy - centre;
float tex_u = atan(dome_point.x, dome_point.y);// / (.25 * PI);
float tex_v = aVertex.z / (uSkyDomeRadius * .5);
texCoord0 = vec2(tex_u / 2.0 + slow_time, tex_v / 2.0);
texCoord1 = vec2(tex_u + slow_time / 2.0, tex_v);
}
I also use a time to offset u a bit each frame so the clouds move. This works fine except atan goes from -PI to PI and suddenly the texCoord0 and texCoord1 values the fragment shader interpolates are separated by a large distance which hoses the interpolation.
The best way to describe it is that if I have 16 triangles at my base then interpolation from 0/16 to 1/16 works, 1/16 to 2/16 works and so on. But when I get to 15/16 to 0/16 the interpolator goes backwards and the large variation causes the frag shader to repeat the texture over and over in a small space leading to stripes as shown.
I cannot see any way to have a seamless 360 degree view I think the only way I'll fix this is if I rotate the entire dome so the seam is always behind the camera but it might still show if the camera points straight up to the top of a dome.
A working example with source would be great especially if it addresses these sorts of issues.