Monday, June 1, 2020

PlumeriaSC 4

I hope the title of this post got you excited! PlumeriaSC 4 just passed milestone 2. Work started about a year and a half ago and I have had two or three major rewrites. Yep, I have had to rewrite over 90% of the code two or three times for a pure JavaScript application. The last rewrite was probably the worst because I had one task to go and everything fell apart. Along the way I created my own architecture named CURE which greatly reduced bugs. I first tried the CURE paradigm with Galactic Space Junk Arena. Around that same time PlumeriaSC 4 started falling apart on me again so I tried it. It worked wonders on the stability of PlumeriaSC 4 and I have been using ever since. Probably the coolest thing I have learned recently is signed distance field font images (WebGL calls them textures). Pretty much you can use an image with a little pixel shader magic (again WebGL calls them fragment shaders) and it will be pixel perfect no matter how much you zoom into the image. You may remember I talked about Order Independent Transparency in an older post. I thought the computationally expensive OIT was the only way to get good looking characters with an image. Probably five years ago I had seen the original article on the SDF font technique but it never really explained the shader code. Here's the article that finally explained the shader code: Techniques for Rendering Text with WebGL

Below is an example of the shader code. The secret is using the "step" and "discard" functions in the fragment shader to get the pixel perfect look.

Vertex Shader Code:

attribute vec3 a_Vertices;
attribute vec2 a_TexCoords;
uniform mat4 u_ModelViewMatrix;
uniform mat4 u_ProjectionMatrix;
varying vec2 v_TexCoord;

void main()
{
v_TexCoord = a_TexCoords;
vec4 position = u_ModelViewMatrix * vec4(a_Vertices, 1.0);
gl_Position = u_ProjectionMatrix * position;
}

Fragment Shader Code:

uniform sampler2D u_Sampler;
varying vec2 v_TexCoord;

void main()
{
// This can be any channel color (RGB) since we are using a grayscale texture
float red = step(0.5, texture2D(u_Sampler, v_TexCoord).r);
if (red == 0.0)
{
discard;
}
gl_FragColor = vec4(0.5);
}