// Both width and height must be multiple of 256, (one byte)
// but do not need to be the same,
// matching GPU capabilities is the aim
- static webglWidth = 256 * 8
- static webglHeight = 256 * 8
+ static webglWidth = 256 * 4
+ static webglHeight = 256 * 4
+ static gl = new OffscreenCanvas(this.webglWidth, this.webglHeight).getContext('webgl2')
static hexify (arr: number[] | Uint8Array): string {
let out = ''
reverseHex += hashHex.slice(i - 2, i)
}
- const canvas = new OffscreenCanvas(this.webglWidth, this.webglHeight)
- const gl = canvas.getContext('webgl2')
-
- if (!gl)
+ if (this.gl == null)
throw new Error('webgl2_required')
- gl.clearColor(0, 0, 0, 1)
-
- console.log(`color cleared: ${performance.now()}`)
+ this.gl.clearColor(0, 0, 0, 1)
// Vertext Shader
const vsSource = `#version 300 es
void main() {
int i;
- uint uv_x = uint(uv_pos.x * ${canvas.width - 1}.);
- uint uv_y = uint(uv_pos.y * ${canvas.height - 1}.);
+ uint uv_x = uint(uv_pos.x * ${this.webglWidth - 1}.);
+ uint uv_y = uint(uv_pos.y * ${this.webglHeight - 1}.);
uint x_pos = uv_x % 256u;
uint y_pos = uv_y % 256u;
uint x_index = (uv_x - x_pos) / 256u;
}
}`
- const vertexShader = gl.createShader(gl.VERTEX_SHADER)
+ console.log(`shaders start: ${performance.now()}`)
+ const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER)
if (vertexShader == null)
throw 'error creating vertex shader'
- gl.shaderSource(vertexShader, vsSource)
- gl.compileShader(vertexShader)
+ this.gl.shaderSource(vertexShader, vsSource)
+ this.gl.compileShader(vertexShader)
- if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
- throw gl.getShaderInfoLog(vertexShader)
+ if (!this.gl.getShaderParameter(vertexShader, this.gl.COMPILE_STATUS))
+ throw this.gl.getShaderInfoLog(vertexShader)
- const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
+ const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER)
if (fragmentShader == null)
throw 'error creating fragment shader'
- gl.shaderSource(fragmentShader, fsSource)
- gl.compileShader(fragmentShader)
+ this.gl.shaderSource(fragmentShader, fsSource)
+ this.gl.compileShader(fragmentShader)
- if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
- throw gl.getShaderInfoLog(fragmentShader)
+ if (!this.gl.getShaderParameter(fragmentShader, this.gl.COMPILE_STATUS))
+ throw this.gl.getShaderInfoLog(fragmentShader)
- const program = gl.createProgram()
+ const program = this.gl.createProgram()
if (program == null)
throw 'error creating program'
- gl.attachShader(program, vertexShader)
- gl.attachShader(program, fragmentShader)
- gl.linkProgram(program)
+ this.gl.attachShader(program, vertexShader)
+ this.gl.attachShader(program, fragmentShader)
+ this.gl.linkProgram(program)
- if (!gl.getProgramParameter(program, gl.LINK_STATUS))
- throw gl.getProgramInfoLog(program)
+ if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS))
+ throw this.gl.getProgramInfoLog(program)
- gl.useProgram(program)
+ this.gl.useProgram(program)
// Construct simple 2D geometry
- const triangleArray = gl.createVertexArray()
- gl.bindVertexArray(triangleArray)
+ const triangleArray = this.gl.createVertexArray()
+ this.gl.bindVertexArray(triangleArray)
// Vertex Positions, 2 triangles
const positions = new Float32Array([
-1, -1, 0, -1, 1, 0, 1, 1, 0,
1, -1, 0, 1, 1, 0, -1, -1, 0
])
- const positionBuffer = gl.createBuffer()
- gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
- gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW)
- gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0)
- gl.enableVertexAttribArray(0)
+ const positionBuffer = this.gl.createBuffer()
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, positionBuffer)
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW)
+ this.gl.vertexAttribPointer(0, 3, this.gl.FLOAT, false, 0, 0)
+ this.gl.enableVertexAttribArray(0)
// Texture Positions
const uvPosArray = new Float32Array([
1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1
])
- const uvBuffer = gl.createBuffer()
- gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer)
- gl.bufferData(gl.ARRAY_BUFFER, uvPosArray, gl.STATIC_DRAW)
- gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0)
- gl.enableVertexAttribArray(1)
+ const uvBuffer = this.gl.createBuffer()
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, uvBuffer)
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, uvPosArray, this.gl.STATIC_DRAW)
+ this.gl.vertexAttribPointer(1, 2, this.gl.FLOAT, false, 0, 0)
+ this.gl.enableVertexAttribArray(1)
- const work0Location = gl.getUniformLocation(program, 'u_work0')
- const work1Location = gl.getUniformLocation(program, 'u_work1')
+ const work0Location = this.gl.getUniformLocation(program, 'u_work0')
+ const work1Location = this.gl.getUniformLocation(program, 'u_work1')
// Draw output until success or progressCallback says to stop
const work0 = new Uint8Array(4)
const work1 = new Uint8Array(4)
+ console.log(`shaders end: ${performance.now()}`)
const draw = (): void => {
+ if (this.gl == null) throw new Error('webgl2_required')
+ const start = performance.now()
+ console.log(`crypto start: ${performance.now()}`)
crypto.getRandomValues(work0)
crypto.getRandomValues(work1)
+ console.log(`crypto end: ${performance.now()}`)
- gl.uniform4uiv(work0Location, work0)
- gl.uniform4uiv(work1Location, work1)
+ console.log(`uiv start: ${performance.now()}`)
+ this.gl.uniform4uiv(work0Location, work0)
+ this.gl.uniform4uiv(work1Location, work1)
+ console.log(`uiv end: ${performance.now()}`)
- gl.clear(gl.COLOR_BUFFER_BIT)
- gl.drawArrays(gl.TRIANGLES, 0, 6)
- const pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4)
+ console.log(`clear start: ${performance.now()}`)
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT)
+ console.log(`clear end: ${performance.now()}`)
+ console.log(`draw start: ${performance.now()}`)
+ this.gl.drawArrays(this.gl.TRIANGLES, 0, 6)
+ console.log(`draw end: ${performance.now()}`)
+ const pixels = new Uint8Array(this.gl.drawingBufferWidth * this.gl.drawingBufferHeight * 4)
console.log(`start readPixels: ${performance.now()}`)
- gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels)
+ this.gl.readPixels(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight, this.gl.RGBA, this.gl.UNSIGNED_BYTE, pixels)
console.log(`end readPixels: ${performance.now()}`)
// Check the pixels for any success
- for (let i = 0; i < pixels.length; i += 4) {
+ for (let i = pixels.length - 4; i >= 0; i -= 4) {
if (pixels[i] !== 0) {
console.log(`found: ${performance.now()}`)
+ console.log(`frame time: ${performance.now() - start}`)
// Return the work value with the custom bits
typeof callback === 'function' &&
callback(this.hexify(work1) + this.hexify([
return
}
}
+ console.log(`frame time: ${performance.now() - start}`)
// Nothing found yet, try again
self.requestAnimationFrame(draw)
}
- console.log(`starting first draw: ${performance.now()}`)
// Begin generation
self.requestAnimationFrame(draw)
}