Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Chlumsky
Last active August 27, 2021 07:41
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Chlumsky/263c960ae0a7df59afc2da4051eb0553 to your computer and use it in GitHub Desktop.
Save Chlumsky/263c960ae0a7df59afc2da4051eb0553 to your computer and use it in GitHub Desktop.
MSDF Preview
#include <math_constants>
#include <median>
#include <billboard>
#include <affine_transform>
glsl float linearStep(float a, float b, float x) {
return clamp((x-a)/(b-a), 0.0, 1.0);
}
param float pxRange = 2.0 : logrange(0.25, 256.0);
param float thickness : range(-1.0, +1.0);
param float border = 0.125 : range(0.0, 0.25);
param vec2 shadowVector = vec2(+0.0625, -0.03125) : range(-0.25, +0.25);
param float shadowSoftness = 0.5 : range(0.0, 1.0);
param float shadowOpacity = 0.5 : range(0.0, 1.0);
image MSDF = file() : filter(linear), map(clamp);
const vec3 bottomColor = vec3(0.0, 0.21875, 0.375);
const vec3 topColor = vec3(0.0, 0.625, 1.0);
const vec3 borderColor = vec3(0.0);
// Render shape from MSDF
glsl vec4 renderMsdf(vec2 p) {
vec2 msdfSize = vec2(textureSize(MSDF, 0));
float pxSize = min(0.5/pxRange*(fwidth(p.x)*msdfSize.x+fwidth(p.y)*msdfSize.y), 0.25);
vec3 msd = texture(MSDF, p).rgb;
float sd = 2.0*median(msd.r, msd.g, msd.b)-1.0 + thickness;
float inside = linearStep(-border-pxSize, -border+pxSize, sd);
float outsideBorder = border > 0.0 ? linearStep(+border-pxSize, +border+pxSize, sd) : 1.0;
vec4 fg = vec4(mix(borderColor, mix(bottomColor, topColor, p.y), outsideBorder), inside);
msd = texture(MSDF, p-shadowVector).rgb;
sd = 2.0*median(msd.r, msd.g, msd.b)-1.0 + border+thickness;
float shadow = shadowOpacity*linearStep(-shadowSoftness-pxSize, +shadowSoftness+pxSize, sd);
return vec4(mix(vec3(0.0), fg.rgb, fg.a), shadow-shadow*fg.a+fg.a);
}
image Preview2D = glsl(renderMsdf, 512, 512*sizeof(MSDF).y/sizeof(MSDF).x);
// 3D view
const float viewDistance = 3.0;
const float NEAR = 1.0/256.0, FAR = 256.0;
glsl vec4 vertexShader(out vec2 texCoord, int index) {
vec3 coord = billboardCoord(index);
texCoord = billboardTexCoord(index);
ivec2 inputSize = sizeof(MSDF);
float inputAspect = float(inputSize.x)/float(inputSize.y);
coord.x *= inputAspect;
vec2 rotation = vec2(0.375, -0.375) + 0.0078125*shadron_Mouse.xy;
coord = rotateX(coord, rotation.y);
coord = rotateY(coord, rotation.x);
coord = translate(coord, vec3(0.0, 0.0, -viewDistance));
float fov = 0.5*PI-atan(0.0625*shadron_Mouse.z);
return projectPerspectiveHFOV(coord, fov, NEAR, FAR);
}
model Preview3D :
fragment_data(vec2),
vertex(vertexShader, triangles, BILLBOARD_VERTEX_COUNT),
fragment(renderMsdf),
background(vec4(1.0)),
blend(transparency);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment