I'm trying to generate realistic stars for an open source game I'm working on. I'm generating the stars using principles covered here. I'm using the three.js library in a Chromium engine (NW.js). The problem I've found is that the star glow fades into black instead of into transparency.
Whilst it looks nice for single star,
multiple stars have a serious problem:
Vertex shader
attribute vec3 glow;
varying vec3 vGlow;
void main() {
vGlow = glow;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_PointSize = 100.0;
gl_Position = projectionMatrix * mvPosition;
}
Fragment shader
varying vec3 vGlow;
void main() {
float starLuminosity = 250.0;
float invRadius = 60.0;
float invGlowRadius = 2.5;
// Get position relative to center.
vec2 position = gl_PointCoord;
position.x -= 0.5;
position.y -= 0.5;
// Airy disk calculation.
float diskScale = length(position) * invRadius;
vec3 glow = vGlow / pow(diskScale, invGlowRadius);
glow *= starLuminosity;
gl_FragColor = vec4(glow, 1.0);
}
I've tried discarding pixels that are darker, but this does not solve the problem, it only hides it a tad:
if (gl_FragColor.r < 0.1 && gl_FragColor.g < 0.1 && gl_FragColor.b < 0.1) {
discard;
}
The actual effect I'm after is as follows,
but I have no idea how to achieve this.
Any advice will be appreciated.
You cannot achieve this effect in the fragment shader because you are rendering multiple meshes or primitives. You have to enable Blending before rendering the geometry:
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
Also make sure that the Depth test is disabled.
Additionally you must set the alpha channel from. e.g.:
gl_FragColor = vec4(glow, 1.0);
vec4(glow, (glow.r+glow.g.+glow.b)/3.0 * 1.1 - 0.1);