Refactor & improve

This commit is contained in:
Andras Schmelczer 2023-05-01 12:14:36 +01:00
commit b3d9229af5
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
22 changed files with 713 additions and 334 deletions

View file

@ -0,0 +1,93 @@
import { Random } from '../../random';
import { setUpFullScreenQuad } from '../full-screen-quad/full-screen-quad';
import random from '../random.wgsl';
import { smartCompile } from '../smart-compile';
import noise from './fbm-noise.wgsl';
const textureCache = new Map<string, GPUTexture>();
export const generateFbmNoise = ({
device,
width = 1024,
height = 1024,
octaves = 8,
lacunarity = 2,
amplitude = 0.5,
gain = 0.5,
}: {
device: GPUDevice;
width?: number;
height?: number;
octaves?: number;
lacunarity?: number;
amplitude?: number;
gain?: number;
}): GPUTextureView => {
const constants = {
octaves,
lacunarity,
amplitude,
gain,
seedR: Random.getRandom(),
seedG: Random.getRandom(),
seedB: Random.getRandom(),
seedA: Random.getRandom(),
};
const cacheKey = `${width}x${height}x${JSON.stringify(constants)}`;
if (!textureCache.has(cacheKey)) {
const { buffer, vertex } = setUpFullScreenQuad(device);
const quadVertexBuffer = buffer;
const pipeline = device.createRenderPipeline({
layout: 'auto',
vertex,
fragment: {
module: smartCompile(device, random, noise),
entryPoint: 'fragment',
constants,
targets: [
{
format: 'rgba16float',
},
],
},
primitive: {
topology: 'triangle-strip',
},
});
const colorTexture = device.createTexture({
size: {
width,
height,
depthOrArrayLayers: 1,
},
format: 'rgba16float',
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.RENDER_ATTACHMENT,
});
const renderPassDescriptor: GPURenderPassDescriptor = {
colorAttachments: [
{
view: colorTexture.createView(),
clearValue: { r: 1.0, g: 1.0, b: 1.0, a: 1.0 },
loadOp: 'clear',
storeOp: 'store',
},
],
};
const commandEncoder = device.createCommandEncoder();
const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor);
passEncoder.setPipeline(pipeline);
passEncoder.setVertexBuffer(0, quadVertexBuffer);
passEncoder.draw(4, 1);
passEncoder.end();
device.queue.submit([commandEncoder.finish()]);
textureCache.set(cacheKey, colorTexture);
}
return textureCache.get(cacheKey).createView();
};

View file

@ -1,6 +1,6 @@
import { ErrorHandler, Severity } from '../error-handler';
export const initializeGPU = async (): Promise<GPUDevice> => {
export const initializeGpu = async (): Promise<GPUDevice> => {
const gpu = navigator.gpu;
if (!gpu) {
throw new Error('WebGPU is not supported in your browser');

View file

@ -1,8 +1,6 @@
import { Random } from '../../random';
import { setUpFullScreenQuad } from '../full-screen-quad/full-screen-quad';
import random from '../random.wgsl';
import { smartCompile } from '../smart-compile';
import noise from './noise.wgsl';
const textureCache = new Map<string, GPUTexture>();
@ -10,20 +8,12 @@ export const generateNoise = ({
device,
width = 1024,
height = 1024,
octaves = 8,
lacunarity = 2,
amplitude = 0.5,
gain = 0.5,
}: {
device: GPUDevice;
width?: number;
height?: number;
octaves?: number;
lacunarity?: number;
amplitude?: number;
gain?: number;
}): GPUTextureView => {
const cacheKey = `${width}x${height}x${octaves}x${lacunarity}x${amplitude}x${gain}`;
const cacheKey = `${width}x${height}`;
if (!textureCache.has(cacheKey)) {
const { buffer, vertex } = setUpFullScreenQuad(device);
const quadVertexBuffer = buffer;
@ -32,18 +22,21 @@ export const generateNoise = ({
layout: 'auto',
vertex,
fragment: {
module: smartCompile(device, random, noise),
module: smartCompile(
device,
random,
/* wgsl */ `
@fragment
fn fragment(@location(0) uv: vec2<f32>) -> @location(0) vec4<f32> {
return vec4(
random_with_seed(uv, 1),
random_with_seed(uv, 2),
random_with_seed(uv, 3),
random_with_seed(uv, 4),
);
}`
),
entryPoint: 'fragment',
constants: {
octaves,
lacunarity,
amplitude,
gain,
seedR: Random.getRandom(),
seedG: Random.getRandom(),
seedB: Random.getRandom(),
seedA: Random.getRandom(),
},
targets: [
{
format: 'rgba16float',

View file

@ -1,6 +1,9 @@
import { ErrorHandler, Severity } from '../error-handler';
export const smartCompile = (device: GPUDevice, ...code: Array<string>) => {
export const smartCompile = (
device: GPUDevice,
...code: Array<string>
): GPUShaderModule => {
const concatenated = code.join('\n\n');
const module = device.createShaderModule({
@ -15,7 +18,9 @@ export const smartCompile = (device: GPUDevice, ...code: Array<string>) => {
warning: Severity.WARNING,
error: Severity.ERROR,
}[message.type],
`${message.message}\n${concatenated.split('\n')[message.lineNum - 1]}`
`${message.message}\n${
concatenated.split('\n')[message.lineNum - 1]
}\n\nCode:\n${concatenated}\n`
)
)
);