EzWebGPU is a wrapper for WebGPU which handles setting up a read and write buffer pair to quickly write, deploy, and visually debug compute shaders very painlessly. You can quickly setup cellular automata simulations and get TRILLIONS of FLOPS all in the browser. See on: GitHub
Examples (Must have chrome):
Just include the EZWG.js file anyhwere in your browser to access these functions
- let computeWGSL =
- `
- // This value is used as an index to get the right attribute
- // in the cell (we're only going to define a size of 1 for
- // this CGOL example)
- let cellAttribute: u32 = 0u;
- var neighbourCount: u32 = 0u;
- // Explanation of the EX_CELL_VAL function call:
- // get the surroduning 8 neighbours (from the chunk that
- // EZX and EZY is in), get the offset by 1 or -1, and at
- // that cell's value stored at index "cellAttribute"
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
- var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
- if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
- }
- else if (myState == 0 && neighbourCount == 3u) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
- }
- else {
- EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- let cellAttIndex: u32 = 0u;
- var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
- // EZ_STATE_IN[ EZ_CELL_IND + (0u) * EZ_TOTAL_CELLS ];
- if( cellVal == 0 ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- rrr = 1;
- ggg = 1;
- bbb = 1;
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // Usage example
- let config = {
- CELL_SIZE: 8,
- CHUNK_SIZE: 50,
- CHUNKS_ACROSS: 1,
- BUFFER_TYPE: 'u32',
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- let cellAttribute: u32 = 0u;
- var neighbourCount: u32 = 0u;
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
- var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
- if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
- }
- else if (myState == 0 && neighbourCount == 3u) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
- }
- else {
- EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- let cellAttIndex: u32 = 0u;
- var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
- if( cellVal == 0 ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- if( EZ_CHUNK_X == 0 && EZ_CHUNK_Y == 0 ){
- rrr = 1;
- ggg = 1;
- bbb = 1;
- }
- else if( EZ_CHUNK_X == 0 && EZ_CHUNK_Y == 1 ){
- rrr = 1;
- ggg = 1;
- bbb = 0;
- }
- else if( EZ_CHUNK_X == 1 && EZ_CHUNK_Y == 0 ){
- rrr = 0;
- ggg = 1;
- bbb = 0;
- }
- else if( EZ_CHUNK_X == 1 && EZ_CHUNK_Y == 1 ){
- rrr = 1;
- ggg = 0;
- bbb = 0;
- }
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // Usage example
- let config = {
- CELL_SIZE: 6,
- CHUNK_SIZE: 30,
- CHUNKS_ACROSS: 2,
- BUFFER_TYPE: 'u32',
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- let cellAttribute: u32 = 0u;
- var neighbourCount: f32 = 0f;
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
- var myState: f32 = EZ_STATE_IN[ EZ_CELL_IND ];
- if (myState == 1f && (neighbourCount < 2f || neighbourCount > 3f)) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 0f;
- }
- else if (myState == 0 && neighbourCount == 3f) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 1f;
- }
- else {
- EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- let cellAttIndex: u32 = 0u;
- var cellVal: f32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
- if( cellVal == 0f ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- // Calc distance
- var distFromCenter: f32 = abs( EZ_PARTS_ACROSS_F/2f - f32(EZ_COMP_X) );
- distFromCenter = abs( distFromCenter + ((EZ_PARTS_ACROSS_F/2f)-f32(EZ_COMP_Y)) ) ;
- distFromCenter = distFromCenter / ( EZ_PARTS_ACROSS_F );
- let offR = 0.44 + (f32(EZ_CHUNK_X) * 0.913 + f32(EZ_CHUNK_Y) * 0.7121) % 1;
- let offG = 0.78 + (f32(EZ_CHUNK_X) * 0.513 + f32(EZ_CHUNK_Y) * 0.8121) % 1;
- let offB = 0.41 + (f32(EZ_CHUNK_X) * 0.693 + f32(EZ_CHUNK_Y) * 0.4121) % 1;
- rrr = offR * (1f - distFromCenter);
- ggg = offG * (1f - distFromCenter);
- bbb = offB * (1f - distFromCenter);
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // Usage example
- let config = {
- CELL_SIZE: 8,
- CHUNK_SIZE: 32,
- CHUNKS_ACROSS: 2,
- PARTS_ACROSS: 8,
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- let cellAttribute: u32 = 0u;
- // Only if the value is exactly 1 consider it alive, gredations of death
- var neighbs: f32 = 0f;
- var tmpVal: f32 = 0f;
- tmpVal = EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- tmpVal = EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
- if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
- var myState: f32 = EZ_STATE_IN[ EZ_CELL_IND ];
- if (myState == 1f && (neighbs < 2f || neighbs > 3f)) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 0.95f;
- }
- else if (myState < 1f && neighbs == 3f) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 1f;
- }
- else {
- // This is the decay
- if(myState < 1f){
- myState = myState * 0.96f;
- }
- EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0f;
- var ggg: f32 = 0f;
- var bbb: f32 = 0f;
- let cellAttIndex: u32 = 0u;
- var cellVal: f32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
- var drawingWeightsOffset: u32 = EZ_CHUNK_IND * 3u; // 3 storage values for r,g,b
- if( cellVal < 1f ){
- if( EZ_COMP_IND < u32( cellVal * f32( EZ_PARTS_ACROSS_F * EZ_PARTS_ACROSS_F )) ){
- rrr = EZ_STORAGE[ drawingWeightsOffset + 0u ];
- ggg = EZ_STORAGE[ drawingWeightsOffset + 1u ];
- bbb = EZ_STORAGE[ drawingWeightsOffset + 2u ];
- }
- else{
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- }
- else{
- rrr = EZ_STORAGE[ drawingWeightsOffset + 0u ];
- ggg = EZ_STORAGE[ drawingWeightsOffset + 1u ];
- bbb = EZ_STORAGE[ drawingWeightsOffset + 2u ];
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // An Extra buffer of random f32's 0-1 to get a variety of colours
- let randomConwayRGBs = new Float32Array( 256 );
- EZWG.SHA1.seed('test seed 1234' + Date.now());
- for(let b = 0;b < randomConwayRGBs.length;b++){
- randomConwayRGBs[b] = EZWG.SHA1.random()
- }
- console.log(randomConwayRGBs)
- // Usage example
- let config = {
- CELL_SIZE: 5,
- CHUNK_SIZE: 32,
- CHUNKS_ACROSS: 3,
- PARTS_ACROSS: 5,
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `,
- STORAGE: randomConwayRGBs
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- // This value is used as an index to get the right attribute
- // in the cell (we're only going to define a size of 1 for
- // this CGOL example)
- let cellAttribute: u32 = 0u;
- var neighbourCount: u32 = 0u;
- // Explanation of the EX_CELL_VAL function call:
- // get the surroduning 8 neighbours (from the chunk that
- // EZX and EZY is in), get the offset by 1 or -1, and at
- // that cell's value stored at index "cellAttribute"
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
- var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
- if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
- }
- else if (myState == 0 && neighbourCount == 3u) {
- EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
- }
- else {
- EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- let cellAttIndex: u32 = 0u;
- var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
- // EZ_STATE_IN[ EZ_CELL_IND + (0u) * EZ_TOTAL_CELLS ];
- if( cellVal == 0 ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- rrr = EZ_RAND( EZX + EZY + EZ_CHUNK_X*34 + EZ_CHUNK_Y*400 );
- ggg = EZ_RAND( EZX + EZY + EZ_CHUNK_X*13 + EZ_CHUNK_Y*213 );
- bbb = EZ_RAND( EZX + EZY + EZ_CHUNK_X*18 + EZ_CHUNK_Y*311 );
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // An Extra buffer of random f32's 0-1 to get a variety of colours
- let randomConwayRGBs = new Float32Array( 256 );
- EZWG.SHA1.seed('test seed 1234' + Date.now());
- for(let b = 0;b < randomConwayRGBs.length;b++){
- randomConwayRGBs[b] = EZWG.SHA1.random()
- }
- document.getElementById('extraTitle').innerHTML = '<span style="color: red;">*** </span> Check the console.log for the GPU buffer every 100 steps'
- // Usage example
- let config = {
- BUFFER_TYPE: 'u32',
- CELL_SIZE: 5,
- CHUNK_SIZE: 32,
- CHUNKS_ACROSS: 3,
- PARTS_ACROSS: 1,
- READ_BACK_FREQ: 15, // Every 15 time steps read back the gpu buffer
- READ_BACK_FUNC: ( currentStep, entireBuffer ) => { console.log('entireBuffer', entireBuffer.length); },
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `,
- STORAGE: randomConwayRGBs
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- // Helper variables for readability later on
- var attributeOffset: u32 = 0;
- var myState: f32 = 0;
- var totalNghbrCount: u32 = 0;
- // Loop through each value in the cell, and store their CGOL state value
- var neighbrs: array< f32, EZ_CELL_VALS >;
- var valIndex: u32 = 0;
- loop {
- if valIndex >= EZ_CELL_VALS { break; }
- var neighbourCount: u32 = 0u;
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, valIndex );
- var bufferInd: u32 = EZ_CELL_IND + valIndex * EZ_TOTAL_CELLS;
- var myState: u32 = EZ_STATE_IN[ bufferInd ];
- if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
- EZ_STATE_OUT[ bufferInd ] = 0u;
- }
- else if (myState == 0 && neighbourCount == 3u) {
- EZ_STATE_OUT[ bufferInd ] = 1u;
- }
- else {
- EZ_STATE_OUT[ bufferInd ] = myState;
- }
- valIndex++;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- // Helper variables for readiblity
- var drawingWeightsOffset: u32 = 0;
- var totalTypesLive: u32 = EZ_CELL_VALS;
- var valIndex: u32 = 0; //< - the attribute index in a cell
- loop {
- if valIndex >= EZ_CELL_VALS { break; }
- // shift read location in storage buffer: 3 storage values for r,g,b
- drawingWeightsOffset = EZ_CHUNK_IND * 3u;
- // and also shift down the location to accomodate the multiple values per cell
- drawingWeightsOffset = drawingWeightsOffset + (EZ_CELL_VALS * 3u) * valIndex;
- var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, valIndex );
- if( cellVal < 1 ){
- totalTypesLive = totalTypesLive - 1;
- }
- else{
- rrr += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 0 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- ggg += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 1 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- bbb += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 2 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- }
- valIndex++;
- }
- if( totalTypesLive < 1 ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- rrr = rrr / f32(totalTypesLive);
- ggg = ggg / f32(totalTypesLive);
- bbb = bbb / f32(totalTypesLive);
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // An Extra buffer of random f32's 0-1 to get a variety of colours
- let randomConwayRGBs = new Float32Array( 4096 );
- EZWG.SHA1.seed('test seed 1234' + Date.now());
- for(let b = 0;b < randomConwayRGBs.length;b++){
- randomConwayRGBs[b] = EZWG.SHA1.random()
- }
- // Usage example
- let config = {
- BUFFER_TYPE: 'u32',
- CELL_VALS: 5, // Now this means 17 f32 values per cell
- CELL_SIZE: 4,
- CHUNK_SIZE: 32,
- CHUNKS_ACROSS: 4,
- PARTS_ACROSS: 1,
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `,
- STORAGE: randomConwayRGBs
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);
- let computeWGSL =
- `
- // Helper variables for readability later on
- var attributeOffset: u32 = 0;
- var myState: f32 = 0;
- var totalNghbrCount: u32 = 0;
- // Loop through each value in the cell, and store their CGOL state value
- var neighbrs: array< u32, EZ_CELL_VALS >;
- var valIndex: u32 = 0;
- loop {
- if valIndex >= EZ_CELL_VALS { break; }
- var neighbourCount: u32 = 0u;
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, valIndex );
- neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, valIndex );
- var bufferInd: u32 = EZ_CELL_IND + valIndex * EZ_TOTAL_CELLS;
- var myState: u32 = EZ_STATE_IN[ bufferInd ];
- if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
- EZ_STATE_OUT[ bufferInd ] = 0u;
- neighbrs[valIndex] = 0u;
- }
- else if (myState == 0 && neighbourCount == 3u) {
- EZ_STATE_OUT[ bufferInd ] = 1u;
- neighbrs[valIndex] = 1u;
- }
- else {
- EZ_STATE_OUT[ bufferInd ] = myState;
- neighbrs[valIndex] = myState;
- }
- valIndex++;
- }
- // Here's the addition of mouse handling
- // 'incrementer' variable for each f32 or u32 value in memory
- var i_EZ_userInputCounter: u32 = 0u;
- loop {
- if i_EZ_userInputCounter >= EZ_CELL_VALS { break; }
- let EZ_lastInputToChange = EZ_TOTAL_CELLS * i_EZ_userInputCounter + EZ_CELL_IND;
- // Get the min max of the input coordinattres
- var minX: u32 = min( u32(EZ_USER_INPUT[0]), u32(EZ_USER_INPUT[2]));
- var maxX: u32 = max( u32(EZ_USER_INPUT[0]), u32(EZ_USER_INPUT[2]));
- var minY: u32 = min( u32(EZ_USER_INPUT[1]), u32(EZ_USER_INPUT[3]));
- var maxY: u32 = max( u32(EZ_USER_INPUT[1]), u32(EZ_USER_INPUT[3]));
- if( EZ_USER_INPUT[6] > 0 ){
- if( EZX >= minX && EZX <= maxX && EZY >= minY && EZY <= maxY ){
- // The case where the cell is in the bounding box of the user's click drag
- EZ_STATE_OUT[ EZ_lastInputToChange ] = 1;
- }
- else{
- EZ_STATE_OUT[ EZ_lastInputToChange ] = neighbrs[ i_EZ_userInputCounter ];
- }
- }
- else{
- EZ_STATE_OUT[ EZ_lastInputToChange ] = neighbrs[ i_EZ_userInputCounter ];
- }
- i_EZ_userInputCounter++;
- }
- `;
- let fragmentWGSL =
- `
- var rrr: f32 = 0;
- var ggg: f32 = 0;
- var bbb: f32 = 0;
- // Helper variables for readiblity
- var drawingWeightsOffset: u32 = 0;
- var totalTypesLive: u32 = EZ_CELL_VALS;
- var valIndex: u32 = 0; //< - the attribute index in a cell
- loop {
- if valIndex >= EZ_CELL_VALS { break; }
- // shift read location in storage buffer: 3 storage values for r,g,b
- drawingWeightsOffset = EZ_CHUNK_IND * 3u;
- // and also shift down the location to accomodate the multiple values per cell
- drawingWeightsOffset = drawingWeightsOffset + (EZ_CELL_VALS * 3u) * valIndex;
- var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, valIndex );
- if( cellVal < 1 ){
- totalTypesLive = totalTypesLive - 1;
- }
- else{
- rrr += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 0 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- ggg += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 1 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- bbb += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 2 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
- }
- valIndex++;
- }
- if( totalTypesLive < 1 ){
- rrr = 0;
- ggg = 0;
- bbb = 0;
- }
- else{
- rrr = rrr / f32(totalTypesLive);
- ggg = ggg / f32(totalTypesLive);
- bbb = bbb / f32(totalTypesLive);
- }
- EZ_OUTPUT.red = rrr;
- EZ_OUTPUT.grn = ggg;
- EZ_OUTPUT.blu = bbb;
- `;
- // An Extra buffer of random f32's 0-1 to get a variety of colours
- let randomConwayRGBs = new Float32Array( 4096 );
- EZWG.SHA1.seed('test seed 1234' + Date.now());
- for(let b = 0;b < randomConwayRGBs.length;b++){
- randomConwayRGBs[b] = EZWG.SHA1.random()
- }
- // Usage example
- let config = {
- BUFFER_TYPE: 'u32',
- CELL_VALS: 5, // Now this means 17 f32 values per cell
- CELL_SIZE: 4,
- CHUNK_SIZE: 32,
- CHUNKS_ACROSS: 4,
- PARTS_ACROSS: 1,
- CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
- RAND_SEED: 'randomseed12345678910',
- STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
- COMPUTE_WGSL: `
- // The custom WGSL code goes here
- ${computeWGSL}
- `,
- FRAGMENT_WGSL: `
- // The custom WGSL code goes here
- ${fragmentWGSL}
- `,
- STORAGE: randomConwayRGBs
- };
- // Intital set the default runner to this
- EZ_EXAMPLE = new EZWG( config);