Embedding GLSL shader in hugo
Prakash
Having recently got into the wild world of glsl shaders, I wanted to experiment if I could get glsl shaders rendering in my hugo blog.
It was surprisingly easier that I expected it to be. The centre piece of all the heavy lifter for this purpose is the javascript library GlslCanvas
You simply create a canvas tag like so
<canvas class="glslCanvas"
data-fragment="<the shader code>">
</canvas>
And include the library like so
<script src="https://cdn.jsdelivr.net/npm/glslCanvas@0.2.6/dist/GlslCanvas.js"></script>
We can automate this whole process by creating a hugo shortcode
{{ $path := .Get "src" }}
{{ $file := resources.Get $path }}
{{ if $file }}
{{ $height := .Get "height" | default "400px" }}
<div class="shader-wrapper" style="width: 100%; margin: 1.5rem 0;">
<canvas class="glslCanvas" data-fragment="{{ $file.Content }}" style="width: 100%; height: {{ $height }}; border-radius: 8px; display: block;"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/glslCanvas@0.2.6/dist/GlslCanvas.js"></script>
<script>
const canvas = document.querySelector(".glslCanvas");
if (typeof GlslCanvas === "undefined") {
console.error("GlslCanvas failed to load");
} else {
new GlslCanvas(canvas);
}
</script>
{{ else }}
<p style="color: red;">Shader file not found: {{ $path }} and file {{ $file }}</p>
{{ end }}
This shortcode can be used like so
{{ < add-glsl src="shaders/test.frag" height="400px" >}}
With the file
HUGO_ROOT
assets
└── shaders
└── test.frag
Where the content of test.frag is
precision mediump float;
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
void main() {
vec2 st = (gl_FragCoord.xy*2.0 - 1.0) / u_resolution.xy;
vec3 color = vec3(
st.x * abs(sin(u_time * 0.5)),
st.y * abs(cos(u_time * 0.7)),
abs(sin(u_time))
);
gl_FragColor = vec4(color, 1.0);
}
Will result in
Is this not awesome?