Last active
August 27, 2021 07:41
-
-
Save Chlumsky/263c960ae0a7df59afc2da4051eb0553 to your computer and use it in GitHub Desktop.
MSDF Preview
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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