EZWebGPU.js

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

WHAT:

Examples (Must have chrome):

Just include the EZWG.js file anyhwere in your browser to access these functions




  1. let computeWGSL =
  2. `
  3. // This value is used as an index to get the right attribute
  4. // in the cell (we're only going to define a size of 1 for
  5. // this CGOL example)
  6. let cellAttribute: u32 = 0u;
  7. var neighbourCount: u32 = 0u;
  8. // Explanation of the EX_CELL_VAL function call:
  9. // get the surroduning 8 neighbours (from the chunk that
  10. // EZX and EZY is in), get the offset by 1 or -1, and at
  11. // that cell's value stored at index "cellAttribute"
  12. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
  13. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
  14. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
  15. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
  16. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
  17. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
  18. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
  19. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
  20. var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
  21. if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
  22. EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
  23. }
  24. else if (myState == 0 && neighbourCount == 3u) {
  25. EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
  26. }
  27. else {
  28. EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
  29. }
  30. `;
  31. let fragmentWGSL =
  32. `
  33. var rrr: f32 = 0;
  34. var ggg: f32 = 0;
  35. var bbb: f32 = 0;
  36. let cellAttIndex: u32 = 0u;
  37. var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
  38. // EZ_STATE_IN[ EZ_CELL_IND + (0u) * EZ_TOTAL_CELLS ];
  39. if( cellVal == 0 ){
  40. rrr = 0;
  41. ggg = 0;
  42. bbb = 0;
  43. }
  44. else{
  45. rrr = 1;
  46. ggg = 1;
  47. bbb = 1;
  48. }
  49. EZ_OUTPUT.red = rrr;
  50. EZ_OUTPUT.grn = ggg;
  51. EZ_OUTPUT.blu = bbb;
  52. `;
  53. // Usage example
  54. let config = {
  55. CELL_SIZE: 8,
  56. CHUNK_SIZE: 50,
  57. CHUNKS_ACROSS: 1,
  58. BUFFER_TYPE: 'u32',
  59. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  60. RAND_SEED: 'randomseed12345678910',
  61. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  62. COMPUTE_WGSL: `
  63. // The custom WGSL code goes here
  64. ${computeWGSL}
  65. `,
  66. FRAGMENT_WGSL: `
  67. // The custom WGSL code goes here
  68. ${fragmentWGSL}
  69. `
  70. };
  71. // Intital set the default runner to this
  72. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. let cellAttribute: u32 = 0u;
  4. var neighbourCount: u32 = 0u;
  5. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
  6. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
  7. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
  8. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
  9. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
  10. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
  11. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
  12. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
  13. var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
  14. if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
  15. EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
  16. }
  17. else if (myState == 0 && neighbourCount == 3u) {
  18. EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
  19. }
  20. else {
  21. EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
  22. }
  23. `;
  24. let fragmentWGSL =
  25. `
  26. var rrr: f32 = 0;
  27. var ggg: f32 = 0;
  28. var bbb: f32 = 0;
  29. let cellAttIndex: u32 = 0u;
  30. var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
  31. if( cellVal == 0 ){
  32. rrr = 0;
  33. ggg = 0;
  34. bbb = 0;
  35. }
  36. else{
  37. if( EZ_CHUNK_X == 0 && EZ_CHUNK_Y == 0 ){
  38. rrr = 1;
  39. ggg = 1;
  40. bbb = 1;
  41. }
  42. else if( EZ_CHUNK_X == 0 && EZ_CHUNK_Y == 1 ){
  43. rrr = 1;
  44. ggg = 1;
  45. bbb = 0;
  46. }
  47. else if( EZ_CHUNK_X == 1 && EZ_CHUNK_Y == 0 ){
  48. rrr = 0;
  49. ggg = 1;
  50. bbb = 0;
  51. }
  52. else if( EZ_CHUNK_X == 1 && EZ_CHUNK_Y == 1 ){
  53. rrr = 1;
  54. ggg = 0;
  55. bbb = 0;
  56. }
  57. }
  58. EZ_OUTPUT.red = rrr;
  59. EZ_OUTPUT.grn = ggg;
  60. EZ_OUTPUT.blu = bbb;
  61. `;
  62. // Usage example
  63. let config = {
  64. CELL_SIZE: 6,
  65. CHUNK_SIZE: 30,
  66. CHUNKS_ACROSS: 2,
  67. BUFFER_TYPE: 'u32',
  68. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  69. RAND_SEED: 'randomseed12345678910',
  70. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  71. COMPUTE_WGSL: `
  72. // The custom WGSL code goes here
  73. ${computeWGSL}
  74. `,
  75. FRAGMENT_WGSL: `
  76. // The custom WGSL code goes here
  77. ${fragmentWGSL}
  78. `
  79. };
  80. // Intital set the default runner to this
  81. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. let cellAttribute: u32 = 0u;
  4. var neighbourCount: f32 = 0f;
  5. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
  6. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
  7. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
  8. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
  9. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
  10. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
  11. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
  12. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
  13. var myState: f32 = EZ_STATE_IN[ EZ_CELL_IND ];
  14. if (myState == 1f && (neighbourCount < 2f || neighbourCount > 3f)) {
  15. EZ_STATE_OUT[ EZ_CELL_IND ] = 0f;
  16. }
  17. else if (myState == 0 && neighbourCount == 3f) {
  18. EZ_STATE_OUT[ EZ_CELL_IND ] = 1f;
  19. }
  20. else {
  21. EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
  22. }
  23. `;
  24. let fragmentWGSL =
  25. `
  26. var rrr: f32 = 0;
  27. var ggg: f32 = 0;
  28. var bbb: f32 = 0;
  29. let cellAttIndex: u32 = 0u;
  30. var cellVal: f32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
  31. if( cellVal == 0f ){
  32. rrr = 0;
  33. ggg = 0;
  34. bbb = 0;
  35. }
  36. else{
  37. // Calc distance
  38. var distFromCenter: f32 = abs( EZ_PARTS_ACROSS_F/2f - f32(EZ_COMP_X) );
  39. distFromCenter = abs( distFromCenter + ((EZ_PARTS_ACROSS_F/2f)-f32(EZ_COMP_Y)) ) ;
  40. distFromCenter = distFromCenter / ( EZ_PARTS_ACROSS_F );
  41. let offR = 0.44 + (f32(EZ_CHUNK_X) * 0.913 + f32(EZ_CHUNK_Y) * 0.7121) % 1;
  42. let offG = 0.78 + (f32(EZ_CHUNK_X) * 0.513 + f32(EZ_CHUNK_Y) * 0.8121) % 1;
  43. let offB = 0.41 + (f32(EZ_CHUNK_X) * 0.693 + f32(EZ_CHUNK_Y) * 0.4121) % 1;
  44. rrr = offR * (1f - distFromCenter);
  45. ggg = offG * (1f - distFromCenter);
  46. bbb = offB * (1f - distFromCenter);
  47. }
  48. EZ_OUTPUT.red = rrr;
  49. EZ_OUTPUT.grn = ggg;
  50. EZ_OUTPUT.blu = bbb;
  51. `;
  52. // Usage example
  53. let config = {
  54. CELL_SIZE: 8,
  55. CHUNK_SIZE: 32,
  56. CHUNKS_ACROSS: 2,
  57. PARTS_ACROSS: 8,
  58. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  59. RAND_SEED: 'randomseed12345678910',
  60. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  61. COMPUTE_WGSL: `
  62. // The custom WGSL code goes here
  63. ${computeWGSL}
  64. `,
  65. FRAGMENT_WGSL: `
  66. // The custom WGSL code goes here
  67. ${fragmentWGSL}
  68. `
  69. };
  70. // Intital set the default runner to this
  71. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. let cellAttribute: u32 = 0u;
  4. // Only if the value is exactly 1 consider it alive, gredations of death
  5. var neighbs: f32 = 0f;
  6. var tmpVal: f32 = 0f;
  7. tmpVal = EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
  8. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  9. tmpVal = EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
  10. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  11. tmpVal = EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
  12. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  13. tmpVal = EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
  14. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  15. tmpVal = EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
  16. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  17. tmpVal = EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
  18. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  19. tmpVal = EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
  20. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  21. tmpVal = EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
  22. if( tmpVal == 1f ){ neighbs = neighbs + 1f; }
  23. var myState: f32 = EZ_STATE_IN[ EZ_CELL_IND ];
  24. if (myState == 1f && (neighbs < 2f || neighbs > 3f)) {
  25. EZ_STATE_OUT[ EZ_CELL_IND ] = 0.95f;
  26. }
  27. else if (myState < 1f && neighbs == 3f) {
  28. EZ_STATE_OUT[ EZ_CELL_IND ] = 1f;
  29. }
  30. else {
  31. // This is the decay
  32. if(myState < 1f){
  33. myState = myState * 0.96f;
  34. }
  35. EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
  36. }
  37. `;
  38. let fragmentWGSL =
  39. `
  40. var rrr: f32 = 0f;
  41. var ggg: f32 = 0f;
  42. var bbb: f32 = 0f;
  43. let cellAttIndex: u32 = 0u;
  44. var cellVal: f32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
  45. var drawingWeightsOffset: u32 = EZ_CHUNK_IND * 3u; // 3 storage values for r,g,b
  46. if( cellVal < 1f ){
  47. if( EZ_COMP_IND < u32( cellVal * f32( EZ_PARTS_ACROSS_F * EZ_PARTS_ACROSS_F )) ){
  48. rrr = EZ_STORAGE[ drawingWeightsOffset + 0u ];
  49. ggg = EZ_STORAGE[ drawingWeightsOffset + 1u ];
  50. bbb = EZ_STORAGE[ drawingWeightsOffset + 2u ];
  51. }
  52. else{
  53. rrr = 0;
  54. ggg = 0;
  55. bbb = 0;
  56. }
  57. }
  58. else{
  59. rrr = EZ_STORAGE[ drawingWeightsOffset + 0u ];
  60. ggg = EZ_STORAGE[ drawingWeightsOffset + 1u ];
  61. bbb = EZ_STORAGE[ drawingWeightsOffset + 2u ];
  62. }
  63. EZ_OUTPUT.red = rrr;
  64. EZ_OUTPUT.grn = ggg;
  65. EZ_OUTPUT.blu = bbb;
  66. `;
  67. // An Extra buffer of random f32's 0-1 to get a variety of colours
  68. let randomConwayRGBs = new Float32Array( 256 );
  69. EZWG.SHA1.seed('test seed 1234' + Date.now());
  70. for(let b = 0;b < randomConwayRGBs.length;b++){
  71. randomConwayRGBs[b] = EZWG.SHA1.random()
  72. }
  73. console.log(randomConwayRGBs)
  74. // Usage example
  75. let config = {
  76. CELL_SIZE: 5,
  77. CHUNK_SIZE: 32,
  78. CHUNKS_ACROSS: 3,
  79. PARTS_ACROSS: 5,
  80. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  81. RAND_SEED: 'randomseed12345678910',
  82. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  83. COMPUTE_WGSL: `
  84. // The custom WGSL code goes here
  85. ${computeWGSL}
  86. `,
  87. FRAGMENT_WGSL: `
  88. // The custom WGSL code goes here
  89. ${fragmentWGSL}
  90. `,
  91. STORAGE: randomConwayRGBs
  92. };
  93. // Intital set the default runner to this
  94. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. // This value is used as an index to get the right attribute
  4. // in the cell (we're only going to define a size of 1 for
  5. // this CGOL example)
  6. let cellAttribute: u32 = 0u;
  7. var neighbourCount: u32 = 0u;
  8. // Explanation of the EX_CELL_VAL function call:
  9. // get the surroduning 8 neighbours (from the chunk that
  10. // EZX and EZY is in), get the offset by 1 or -1, and at
  11. // that cell's value stored at index "cellAttribute"
  12. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, cellAttribute );
  13. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, cellAttribute );
  14. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, cellAttribute );
  15. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, cellAttribute );
  16. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, cellAttribute );
  17. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, cellAttribute );
  18. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, cellAttribute );
  19. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, cellAttribute );
  20. var myState: u32 = EZ_STATE_IN[ EZ_CELL_IND ];
  21. if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
  22. EZ_STATE_OUT[ EZ_CELL_IND ] = 0u;
  23. }
  24. else if (myState == 0 && neighbourCount == 3u) {
  25. EZ_STATE_OUT[ EZ_CELL_IND ] = 1u;
  26. }
  27. else {
  28. EZ_STATE_OUT[ EZ_CELL_IND ] = myState;
  29. }
  30. `;
  31. let fragmentWGSL =
  32. `
  33. var rrr: f32 = 0;
  34. var ggg: f32 = 0;
  35. var bbb: f32 = 0;
  36. let cellAttIndex: u32 = 0u;
  37. var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, cellAttIndex );
  38. // EZ_STATE_IN[ EZ_CELL_IND + (0u) * EZ_TOTAL_CELLS ];
  39. if( cellVal == 0 ){
  40. rrr = 0;
  41. ggg = 0;
  42. bbb = 0;
  43. }
  44. else{
  45. rrr = EZ_RAND( EZX + EZY + EZ_CHUNK_X*34 + EZ_CHUNK_Y*400 );
  46. ggg = EZ_RAND( EZX + EZY + EZ_CHUNK_X*13 + EZ_CHUNK_Y*213 );
  47. bbb = EZ_RAND( EZX + EZY + EZ_CHUNK_X*18 + EZ_CHUNK_Y*311 );
  48. }
  49. EZ_OUTPUT.red = rrr;
  50. EZ_OUTPUT.grn = ggg;
  51. EZ_OUTPUT.blu = bbb;
  52. `;
  53. // An Extra buffer of random f32's 0-1 to get a variety of colours
  54. let randomConwayRGBs = new Float32Array( 256 );
  55. EZWG.SHA1.seed('test seed 1234' + Date.now());
  56. for(let b = 0;b < randomConwayRGBs.length;b++){
  57. randomConwayRGBs[b] = EZWG.SHA1.random()
  58. }
  59. document.getElementById('extraTitle').innerHTML = '<span style="color: red;">*** </span> Check the console.log for the GPU buffer every 100 steps'
  60. // Usage example
  61. let config = {
  62. BUFFER_TYPE: 'u32',
  63. CELL_SIZE: 5,
  64. CHUNK_SIZE: 32,
  65. CHUNKS_ACROSS: 3,
  66. PARTS_ACROSS: 1,
  67. READ_BACK_FREQ: 15, // Every 15 time steps read back the gpu buffer
  68. READ_BACK_FUNC: ( currentStep, entireBuffer ) => { console.log('entireBuffer', entireBuffer.length); },
  69. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  70. RAND_SEED: 'randomseed12345678910',
  71. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  72. COMPUTE_WGSL: `
  73. // The custom WGSL code goes here
  74. ${computeWGSL}
  75. `,
  76. FRAGMENT_WGSL: `
  77. // The custom WGSL code goes here
  78. ${fragmentWGSL}
  79. `,
  80. STORAGE: randomConwayRGBs
  81. };
  82. // Intital set the default runner to this
  83. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. // Helper variables for readability later on
  4. var attributeOffset: u32 = 0;
  5. var myState: f32 = 0;
  6. var totalNghbrCount: u32 = 0;
  7. // Loop through each value in the cell, and store their CGOL state value
  8. var neighbrs: array< f32, EZ_CELL_VALS >;
  9. var valIndex: u32 = 0;
  10. loop {
  11. if valIndex >= EZ_CELL_VALS { break; }
  12. var neighbourCount: u32 = 0u;
  13. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, valIndex );
  14. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, valIndex );
  15. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, valIndex );
  16. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, valIndex );
  17. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, valIndex );
  18. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, valIndex );
  19. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, valIndex );
  20. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, valIndex );
  21. var bufferInd: u32 = EZ_CELL_IND + valIndex * EZ_TOTAL_CELLS;
  22. var myState: u32 = EZ_STATE_IN[ bufferInd ];
  23. if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
  24. EZ_STATE_OUT[ bufferInd ] = 0u;
  25. }
  26. else if (myState == 0 && neighbourCount == 3u) {
  27. EZ_STATE_OUT[ bufferInd ] = 1u;
  28. }
  29. else {
  30. EZ_STATE_OUT[ bufferInd ] = myState;
  31. }
  32. valIndex++;
  33. }
  34. `;
  35. let fragmentWGSL =
  36. `
  37. var rrr: f32 = 0;
  38. var ggg: f32 = 0;
  39. var bbb: f32 = 0;
  40. // Helper variables for readiblity
  41. var drawingWeightsOffset: u32 = 0;
  42. var totalTypesLive: u32 = EZ_CELL_VALS;
  43. var valIndex: u32 = 0; //< - the attribute index in a cell
  44. loop {
  45. if valIndex >= EZ_CELL_VALS { break; }
  46. // shift read location in storage buffer: 3 storage values for r,g,b
  47. drawingWeightsOffset = EZ_CHUNK_IND * 3u;
  48. // and also shift down the location to accomodate the multiple values per cell
  49. drawingWeightsOffset = drawingWeightsOffset + (EZ_CELL_VALS * 3u) * valIndex;
  50. var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, valIndex );
  51. if( cellVal < 1 ){
  52. totalTypesLive = totalTypesLive - 1;
  53. }
  54. else{
  55. rrr += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 0 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  56. ggg += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 1 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  57. bbb += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 2 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  58. }
  59. valIndex++;
  60. }
  61. if( totalTypesLive < 1 ){
  62. rrr = 0;
  63. ggg = 0;
  64. bbb = 0;
  65. }
  66. else{
  67. rrr = rrr / f32(totalTypesLive);
  68. ggg = ggg / f32(totalTypesLive);
  69. bbb = bbb / f32(totalTypesLive);
  70. }
  71. EZ_OUTPUT.red = rrr;
  72. EZ_OUTPUT.grn = ggg;
  73. EZ_OUTPUT.blu = bbb;
  74. `;
  75. // An Extra buffer of random f32's 0-1 to get a variety of colours
  76. let randomConwayRGBs = new Float32Array( 4096 );
  77. EZWG.SHA1.seed('test seed 1234' + Date.now());
  78. for(let b = 0;b < randomConwayRGBs.length;b++){
  79. randomConwayRGBs[b] = EZWG.SHA1.random()
  80. }
  81. // Usage example
  82. let config = {
  83. BUFFER_TYPE: 'u32',
  84. CELL_VALS: 5, // Now this means 17 f32 values per cell
  85. CELL_SIZE: 4,
  86. CHUNK_SIZE: 32,
  87. CHUNKS_ACROSS: 4,
  88. PARTS_ACROSS: 1,
  89. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  90. RAND_SEED: 'randomseed12345678910',
  91. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  92. COMPUTE_WGSL: `
  93. // The custom WGSL code goes here
  94. ${computeWGSL}
  95. `,
  96. FRAGMENT_WGSL: `
  97. // The custom WGSL code goes here
  98. ${fragmentWGSL}
  99. `,
  100. STORAGE: randomConwayRGBs
  101. };
  102. // Intital set the default runner to this
  103. EZ_EXAMPLE = new EZWG( config);
  1. let computeWGSL =
  2. `
  3. // Helper variables for readability later on
  4. var attributeOffset: u32 = 0;
  5. var myState: f32 = 0;
  6. var totalNghbrCount: u32 = 0;
  7. // Loop through each value in the cell, and store their CGOL state value
  8. var neighbrs: array< u32, EZ_CELL_VALS >;
  9. var valIndex: u32 = 0;
  10. loop {
  11. if valIndex >= EZ_CELL_VALS { break; }
  12. var neighbourCount: u32 = 0u;
  13. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 1, valIndex );
  14. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, 0, valIndex );
  15. neighbourCount += EZ_CELL_VAL( EZX, 1, EZY, -1, valIndex );
  16. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, -1, valIndex );
  17. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, -1, valIndex );
  18. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 0, valIndex );
  19. neighbourCount += EZ_CELL_VAL( EZX, -1, EZY, 1, valIndex );
  20. neighbourCount += EZ_CELL_VAL( EZX, 0, EZY, 1, valIndex );
  21. var bufferInd: u32 = EZ_CELL_IND + valIndex * EZ_TOTAL_CELLS;
  22. var myState: u32 = EZ_STATE_IN[ bufferInd ];
  23. if (myState == 1u && (neighbourCount < 2u || neighbourCount > 3u)) {
  24. EZ_STATE_OUT[ bufferInd ] = 0u;
  25. neighbrs[valIndex] = 0u;
  26. }
  27. else if (myState == 0 && neighbourCount == 3u) {
  28. EZ_STATE_OUT[ bufferInd ] = 1u;
  29. neighbrs[valIndex] = 1u;
  30. }
  31. else {
  32. EZ_STATE_OUT[ bufferInd ] = myState;
  33. neighbrs[valIndex] = myState;
  34. }
  35. valIndex++;
  36. }
  37. // Here's the addition of mouse handling
  38. // 'incrementer' variable for each f32 or u32 value in memory
  39. var i_EZ_userInputCounter: u32 = 0u;
  40. loop {
  41. if i_EZ_userInputCounter >= EZ_CELL_VALS { break; }
  42. let EZ_lastInputToChange = EZ_TOTAL_CELLS * i_EZ_userInputCounter + EZ_CELL_IND;
  43. // Get the min max of the input coordinattres
  44. var minX: u32 = min( u32(EZ_USER_INPUT[0]), u32(EZ_USER_INPUT[2]));
  45. var maxX: u32 = max( u32(EZ_USER_INPUT[0]), u32(EZ_USER_INPUT[2]));
  46. var minY: u32 = min( u32(EZ_USER_INPUT[1]), u32(EZ_USER_INPUT[3]));
  47. var maxY: u32 = max( u32(EZ_USER_INPUT[1]), u32(EZ_USER_INPUT[3]));
  48. if( EZ_USER_INPUT[6] > 0 ){
  49. if( EZX >= minX && EZX <= maxX && EZY >= minY && EZY <= maxY ){
  50. // The case where the cell is in the bounding box of the user's click drag
  51. EZ_STATE_OUT[ EZ_lastInputToChange ] = 1;
  52. }
  53. else{
  54. EZ_STATE_OUT[ EZ_lastInputToChange ] = neighbrs[ i_EZ_userInputCounter ];
  55. }
  56. }
  57. else{
  58. EZ_STATE_OUT[ EZ_lastInputToChange ] = neighbrs[ i_EZ_userInputCounter ];
  59. }
  60. i_EZ_userInputCounter++;
  61. }
  62. `;
  63. let fragmentWGSL =
  64. `
  65. var rrr: f32 = 0;
  66. var ggg: f32 = 0;
  67. var bbb: f32 = 0;
  68. // Helper variables for readiblity
  69. var drawingWeightsOffset: u32 = 0;
  70. var totalTypesLive: u32 = EZ_CELL_VALS;
  71. var valIndex: u32 = 0; //< - the attribute index in a cell
  72. loop {
  73. if valIndex >= EZ_CELL_VALS { break; }
  74. // shift read location in storage buffer: 3 storage values for r,g,b
  75. drawingWeightsOffset = EZ_CHUNK_IND * 3u;
  76. // and also shift down the location to accomodate the multiple values per cell
  77. drawingWeightsOffset = drawingWeightsOffset + (EZ_CELL_VALS * 3u) * valIndex;
  78. var cellVal: u32 = EZ_CELL_VAL( EZX, 0, EZY, 0, valIndex );
  79. if( cellVal < 1 ){
  80. totalTypesLive = totalTypesLive - 1;
  81. }
  82. else{
  83. rrr += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 0 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  84. ggg += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 1 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  85. bbb += EZ_RAND(EZ_STORAGE[ drawingWeightsOffset + 2 ]);//+ EZ_CHUNK_X + EZ_CHUNK_Y + cellVal);
  86. }
  87. valIndex++;
  88. }
  89. if( totalTypesLive < 1 ){
  90. rrr = 0;
  91. ggg = 0;
  92. bbb = 0;
  93. }
  94. else{
  95. rrr = rrr / f32(totalTypesLive);
  96. ggg = ggg / f32(totalTypesLive);
  97. bbb = bbb / f32(totalTypesLive);
  98. }
  99. EZ_OUTPUT.red = rrr;
  100. EZ_OUTPUT.grn = ggg;
  101. EZ_OUTPUT.blu = bbb;
  102. `;
  103. // An Extra buffer of random f32's 0-1 to get a variety of colours
  104. let randomConwayRGBs = new Float32Array( 4096 );
  105. EZWG.SHA1.seed('test seed 1234' + Date.now());
  106. for(let b = 0;b < randomConwayRGBs.length;b++){
  107. randomConwayRGBs[b] = EZWG.SHA1.random()
  108. }
  109. // Usage example
  110. let config = {
  111. BUFFER_TYPE: 'u32',
  112. CELL_VALS: 5, // Now this means 17 f32 values per cell
  113. CELL_SIZE: 4,
  114. CHUNK_SIZE: 32,
  115. CHUNKS_ACROSS: 4,
  116. PARTS_ACROSS: 1,
  117. CONTAINER_ID: 'demoCanvasContainer', // DOM id to insdert canvas to
  118. RAND_SEED: 'randomseed12345678910',
  119. STARTING_CONFIG: EZWG.ALL_BINS, // couldve been EZWG.ALL_ZERO
  120. COMPUTE_WGSL: `
  121. // The custom WGSL code goes here
  122. ${computeWGSL}
  123. `,
  124. FRAGMENT_WGSL: `
  125. // The custom WGSL code goes here
  126. ${fragmentWGSL}
  127. `,
  128. STORAGE: randomConwayRGBs
  129. };
  130. // Intital set the default runner to this
  131. EZ_EXAMPLE = new EZWG( config);

TODO: