|
|
|
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)
|
|
|
|
}
|