You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

132 lines
3.5 KiB

const vertexArray = new Float32Array(100 * 100 * 12)
const colorArray = new Float32Array(100 * 100 * 6)
const state = new Float32Array(100 * 100 * 2)
const [canvas] = document.getElementsByTagName('canvas')
const gl = canvas.getContext('webgl2', { antialias: false })
const S = 0.02
const applyState = (x, y, turn) => {
const index = x * 100 + y
const color = state[index * 2 + 0] > turn ? 0 : state[index * 2 + 1]
colorArray[index * 6 + 0] = color
colorArray[index * 6 + 1] = color
colorArray[index * 6 + 2] = color
colorArray[index * 6 + 3] = color
colorArray[index * 6 + 4] = color
colorArray[index * 6 + 5] = color
}
export const colorize = (x, y, color) => state[(x * 100 + y) * 2 + 1] = color
export const move = (x, y, color, turn) => {
const index = (x * 100 + y) * 2
if (state[index]) return state[index]
state[index] = turn
state[index + 1] = color
}
const loop = fn => {
let x = -1, y = -1
while (++x < 100) {
y = -1
while (++y < 100) fn(x, y)
}
}
const compileShader = (type, script) => {
const shader = gl.createShader(type)
gl.shaderSource(shader, script.trim())
gl.compileShader(shader)
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(shader)
}
return shader
}
// program
const program = gl.createProgram()
gl.attachShader(program, compileShader(gl.VERTEX_SHADER, `
#version 300 es
in vec2 a_position;
in float a_color;
out float v_color;
void main() {
gl_Position = vec4(a_position * vec2(1, -1), 0, 1);
v_color = a_color;
}`))
gl.attachShader(program, compileShader(gl.FRAGMENT_SHADER, `
#version 300 es
precision mediump float;
in float v_color;
out vec4 outColor;
vec4 unpackColor(float f) {
vec4 color;
color.r = floor(f / 65536.0);
color.g = floor((f - color.r * 65536.0) / 256.0);
color.b = floor(f - color.r * 65536.0 - color.g * 256.0);
color.a = 256.0;
return color / 256.0;
}
void main() {
outColor = unpackColor(v_color);
}`))
gl.linkProgram(program)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw gl.getProgramInfoLog(program)
}
gl.useProgram(program)
// initialize state
loop((x, y) => {
const x1 = ((x + 1) - 50) / 50 - S
const y1 = ((y + 1) - 50) / 50 - S
const x2 = x1 + S
const y2 = y1 + S
const index = (x * 100 + y) * 12
vertexArray[index + 0x0] = x1
vertexArray[index + 0x1] = y1
vertexArray[index + 0x2] = x2
vertexArray[index + 0x3] = y1
vertexArray[index + 0x4] = x1
vertexArray[index + 0x5] = y2
vertexArray[index + 0x6] = x1
vertexArray[index + 0x7] = y2
vertexArray[index + 0x8] = x2
vertexArray[index + 0x9] = y1
vertexArray[index + 0xa] = x2
vertexArray[index + 0xb] = y2
})
const vertexBuffer = gl.createBuffer()
const a_position = gl.getAttribLocation(program, 'a_position')
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer)
gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_position)
gl.bufferData(gl.ARRAY_BUFFER, vertexArray, gl.STATIC_DRAW)
gl.drawArrays(gl.TRIANGLES, 0, 60000)
// color buffer
const colorBuffer = gl.createBuffer()
const a_color = gl.getAttribLocation(program, 'a_color')
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
gl.vertexAttribPointer(a_color, 1, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(a_color)
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer)
export const update = (turn) => {
loop((x, y) => applyState(x, y, turn))
gl.bufferData(gl.ARRAY_BUFFER, colorArray, gl.STATIC_DRAW)
gl.drawArrays(gl.TRIANGLES, 0, 60000)
}
export const reset = () => {
state.fill(0)
update(0)
}