Casey Primozic’s Notes

Misc. notes, code, and other content I want to post publicly that don’t warrant a full blog post

By Casey Primozic

Subscribe to RSS

Investigating Hill Noise for Terrain Generation

I’ve been working on some procedural terrain generation for my 3D work in Three.JS lately. I wanted to try out a fresh noise function for generating terrain; everyone has used Perlin noise or some variant of it for decades.

I came across a blog post by Bruce Hill describing a noise function he designed himself - called Hill Noise. It works by combining a bunch of sine waves together with different offsets and rotations. If you add enough of them together, the results can look pretty organic and random.

Read more →

Some Notes and Docs on the Rust Blackjack Procedural Geometry Tool

I’ve been trying out a tool written in Rust called Blackjack for procedural, node-based 3D modelling. It’s a lot like Blender’s geometry nodes.

There aren’t a lot in terms of docs, and it looks like the project isn’t being actively developed right now. Nonetheless, I think it’s an extremely cool project, and the code is very high quality. So, I’ve been spending a bit of time getting familiar with it and trying it out.

Read more →

Fixing WebGL/Three.JS GL_INVALID_ENUM : glDrawElements: type was GL_FLOAT error

The Problem

I was working on some procedural dynamic LOD terrain in Three.JS. As part of this, I was manually constructing indexed BufferGeometry instances. Things were working alright, but when I added in a depth pre-pass I started getting errors like this in the console and the terrain failed to render:

GL ERROR :GL_INVALID_ENUM : glDrawElements: type was GL_FLOAT

The code I had looked something like this:

const vertices = new Float32Array((segments + 1) * (segments + 1) * 3);
const indices = new Float32Array(segments * segments * 6);

// ... compute terrain and populate vertices and indices ...

const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

const mesh = new THREE.Mesh(geometry, material);

The Cause

This error is caused because I accidentally used a Float32Array to store the indices, but I should have used an integer array type. I’m not sure why it originally worked and then stopped working when I added the depth pre-pass though.

Read more →

Debugging WebGL GLSL Shader Behavior Differences Between M1 Mac and AMD GPU

The Problem

I’ve been working on a shader in GLSL for implementing volumetric fog via raytracing. I did the majority of the work for it it on my M1 Macbook laptop while traveling, but I was eager to try it out on my powerful 7900 XTX when I got home to see how it performed.

To my surprise, the results looked extremely different! The lighting was very low-detail on my desktop with the AMD GPU compared to how it looked on my Macbook.

Read more →

Fixing “Could Not Load Openssl” Mastodon Build Error

While trying to update my Mastodon server to the latest v4.2.0 release, I kept running into build failures when running docker-compose build. I got errors like this in the logs:

#20 27.04 Bundler 2.4.10 is running, but your lockfile was generated with 2.4.13. Installing Bundler 2.4.13 and restarting using that version.
#20 27.21 There was an error installing the locked bundler version (2.4.13), rerun with the `--verbose` flag for more details. Going on using bundler 2.4.10.
#20 27.29 Could not load OpenSSL.
#20 27.29 You must recompile Ruby with OpenSSL support.

It was very confusing since the official CI builds seemed to be working fine. Nevertheless, there were multiple issues opened about this, so it’s something people were running into.

Read more →

Fixing pmndrs Postprocessing Recursive Depth Texture Binding

I’ve been working on building 3D scenes and environments in the browser using Three.JS. As part of those, I make pretty heavy use of the pmndrs postprocessing library for post-processing and effects.

I’ve also implemented a custom godrays effect that works with postprocesing called three-good-godrays. It creates a custom pass that is added to the postprocessing EffectComposer which renders volumetric screen-space godrays by reading the depth buffer and shadow map for a light.

Read more →

Fixing “performance is not defined” Issue with Svelte/SvelteKit

The Issue

When building my SvelteKit project, I get lots of errors like this in my console:

ERROR in ./src/graphEditor/nodes/CustomAudio/MIDIToFrequency/MIDIToFrequencySmallView.svelte
Module build failed (from ./node_modules/svelte-loader/index.js):
ReferenceError: performance is not defined
    at now (/home/casey/web-synth/node_modules/svelte/compiler.cjs:7:31)
    at new Stats (/home/casey/web-synth/node_modules/svelte/compiler.cjs:47:21)
    at compile (/home/casey/web-synth/node_modules/svelte/compiler.cjs:45535:16)
    at injectVarsToCode (/home/casey/web-synth/node_modules/svelte-preprocess/dist/transformers/typescript.js:85:45)
    at mixedImportsTranspiler (/home/casey/web-synth/node_modules/svelte-preprocess/dist/transformers/typescript.js:257:26)
    at transformer (/home/casey/web-synth/node_modules/svelte-preprocess/dist/transformers/typescript.js:336:11)
    at transform (/home/casey/web-synth/node_modules/svelte-preprocess/dist/autoProcess.js:46:12)
    at async /home/casey/web-synth/node_modules/svelte-preprocess/dist/autoProcess.js:117:29
    at async script (/home/casey/web-synth/node_modules/svelte-preprocess/dist/autoProcess.js:147:33)
    at async process_single_tag (/home/casey/web-synth/node_modules/svelte/compiler.cjs:45984:21)
    at async Promise.all (index 0)
    at async replace_in_code (/home/casey/web-synth/node_modules/svelte/compiler.cjs:45708:23)
    at async process_tag (/home/casey/web-synth/node_modules/svelte/compiler.cjs:46001:26)
    at async preprocess (/home/casey/web-synth/node_modules/svelte/compiler.cjs:46059:25)

They’re originating from within the Svelte compiler.

Read more →

Fixing “can’t resolve ‘svelte/internal’” Error After Upgrading svelte

I bumped several of the dependencies for one of my projects. It uses Svelte and Webpack, and makes use of svelte-loader to facilitate importing .svelte files.

I upgraded Svelte from v3.57.0 to v4.2.0, and bumped svelte-loader, svelte-preprocess, prettier-plugin-svelte, and many other libraries to their latest versions as well.

After the upgrade, my Webpack dev server started up but failed to load with many errors like these displayed in the console:

Read more →

amdgpu_top: A Modern radeontop Alternative

I’ve been using a tool called radeontop for years to monitor the performance and utilization of my AMD GPUs on Linux. It’s a TUI-based application that renders the value of different performance counters as bar charts:

A screenshot of the radeontop application.  Shows several different bars rendered in a terminal in various colors with labels like Graphics pipe, Event Engine, Scan Converter, Clip Rectangle, and others.

For the most part, it does a good job and it provides a concise overview of GPU utilization.

Read more →

Generating 4K PBR Textures Using Stable Diffusion XL

I’m picking back up the work that I started last year building 3D scenes and sketches with Three.JS.

At that time, it was just after AI image generators like DALL-E and Stable Diffusion were really taking off. I had success running Stable Diffusion locally and using it to generate textures for terrain, buildings, and other environments in the 3D worlds I was building.

I was using Stable Diffusion v1 back then. I had found some prompts that I liked which created images with styles kind of like this: Texture generated with stable diffusion v1.  Shows a mostly black and white image with outset spiraly pieces.  Looks kind of organic but also like rock, and has vibes of an electron microscope image.  The prompt used to generate it was “ridged niobium wall  relic of an ancient alien civilization  long sulfur trenches with deep symmetrical geometric patterned corroded  erosion exposes intricate black crystalline neodymium computer circuitry”

Read more →