Skip to content

Minifying & Obfuscating Shaders

Regular JS minification & obfuscation does not alter the shader code generated by TypeGPU. This is why we provide specific options for transforming shaders.

unplugin-typegpu collects function metadata, which is later used for WGSL code generation. With the { unstable_obfuscate: true } option, all saved identifiers will be obfuscated:

  • In the AST, all parameters and variables will have their names changed to a, b, c, …
  • Externals (the captured scope used by the function) will also have their respective identifiers changed.

As an example, take a look at the following function:

const
const coneVolume: TgpuFn<(radius: d.F32, height: d.F32) => d.F32>
coneVolume
=
const tgpu: {
const: typeof import("node_modules/typegpu/src/core/constant/tgpuConstant").constant;
fn: typeof import("node_modules/typegpu/src/core/function/tgpuFn").fn;
comptime: typeof import("node_modules/typegpu/src/core/function/comptime").comptime;
resolve: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolve;
resolveWithContext: typeof import("node_modules/typegpu/src/core/resolve/tgpuResolve").resolveWithContext;
init: typeof import("node_modules/typegpu/src/core/root/init").init;
initFromDevice: typeof import("node_modules/typegpu/src/core/root/init").initFromDevice;
slot: typeof import("node_modules/typegpu/src/core/slot/slot").slot;
lazy: typeof import("node_modules/typegpu/src/core/slot/lazy").lazy;
... 10 more ...;
'~unstable': typeof import("node_modules/typegpu/src/tgpuUnstable");
}

@module ― typegpu

tgpu
.
fn: <[d.F32, d.F32], d.F32>(argTypes: [d.F32, d.F32], returnType: d.F32) => TgpuFnShell<[d.F32, d.F32], d.F32> (+2 overloads)
fn
([
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
,
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
],
import d
d
.
const f32: d.F32
export f32

A schema that represents a 32-bit float value. (equivalent to f32 in WGSL)

Can also be called to cast a value to an f32.

@example const value = f32(); // 0

@example const value = f32(1.23); // 1.23

@example const value = f32(true); // 1

f32
)((
radius: number
radius
,
height: number
height
) => {
'use gpu';
const
const baseArea: number
baseArea
=
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.PI: number

Pi. This is the ratio of the circumference of a circle to its diameter.

PI
*
radius: number
radius
** 2;
const
const volume: number
volume
= (
const baseArea: number
baseArea
*
height: number
height
) / 3;
return
const volume: number
volume
;
});

When obfuscated and resolved, it will look like this:

fn item(a: f32, b: f32) -> f32 {
let c = (3.141592653589793f * pow(a, 2f));
let e = ((c * b) / 3f);
return e;
}

Runtime minification removes all comments (possibly present in raw-WGSL implemented functions), and all redundant whitespaces.

To enable minification, set the { unstable_minify: true } option in either tgpu.resolve, or in tgpu.init where it will act as a default for all rooted resolves.

As an example, the coneVolume function would look like this when minified:

fn coneVolume(radius:f32,height:f32)->f32{let baseArea=(3.141592653589793f*pow(radius,2f));let volume=((baseArea*height)/3f);return volume;}

Of course, minification and obfuscation can be combined to achieve the following:

fn item(a:f32,b:f32)->f32{let c=(3.141592653589793f*pow(a,2f));let e=((c*b)/3f);return e;}