Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
const vertex = `
attribute vec2 a_position;
attribute vec3 a_barycentric;
uniform mat3 u_matrix;
varying vec3 vbc;
void main() {
vbc = a_barycentric;
gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1);
}`
const fragment = `
#extension GL_OES_standard_derivatives : enable
precision mediump float;
varying vec3 vbc;
const float lineWidth = 1.0;
const vec3 color = vec3(0.7, 0.7, 0.7);
float edgeFactor() {
vec3 d = fwidth(vbc);
vec3 f = step(d * lineWidth, vbc);
return min(min(f.x, f.y), f.z);
}
void main() {
gl_FragColor = vec4(min(vec3(edgeFactor()), color), 1.0);
}`
const calculateBarycentric = length => {
const n = length / 6
const barycentric = []
for (let i = 0; i < n; i++) barycentric.push(1, 0, 0, 0, 1, 0, 0, 0, 1)
return new Float32Array(barycentric)
}
const setup = (gl, program, vertices, barycentric) => {
gl.clearColor(0, 0, 0, 0)
const positionLocation = gl.getAttribLocation(program, 'a_position')
const barycentricLocation = gl.getAttribLocation(program, 'a_barycentric')
const matrixLocation = gl.getUniformLocation(program, 'u_matrix')
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW)
const barycentricBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, barycentricBuffer)
gl.bufferData(gl.ARRAY_BUFFER, barycentric, gl.STATIC_DRAW)
return {
positionLocation,
positionBuffer,
barycentricLocation,
barycentricBuffer,
matrixLocation,
}
}
const draw = (gl, program, scene) => {
resize(gl)
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.useProgram(program)
gl.enableVertexAttribArray(scene.positionLocation)
gl.bindBuffer(gl.ARRAY_BUFFER, scene.positionBuffer)
gl.vertexAttribPointer(scene.positionLocation, 2, gl.FLOAT, false, 0, 0)
gl.enableVertexAttribArray(scene.barycentricLocation)
gl.bindBuffer(gl.ARRAY_BUFFER, scene.barycentricBuffer)
gl.vertexAttribPointer(scene.barycentricLocation, 3, gl.FLOAT, false, 0, 0)
const width = 345
const height = 210
const projection = [2 / width, 0, 0, 0, -2 / height, 0, -1, 1, 1]
gl.uniformMatrix3fv(scene.matrixLocation, false, projection)
gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 2)
}
const vertices = new Float32Array([45, 95, 50, 185, 0, 80, 45, 95, 0, 80, 100, 0, 190, 85, 270, 35, 345, 140, 190, 85, 345, 140, 255, 130, 190, 85, 255, 130, 215, 210, 190, 85, 215, 210, 140, 70, 140, 70, 45, 95, 100, 0, 140, 70, 100, 0, 190, 85])
const barycentric = calculateBarycentric(vertices.length)
const canvas = setUpCanvas()
const gl = canvas.getContext('webgl')
gl.getExtension('OES_standard_derivatives')
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertex)
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragment)
const program = createProgram(gl, vertexShader, fragmentShader)
const scene = setup(gl, program, vertices, barycentric)
const render = () => draw(gl, program, scene)
render()
window.addEventListener('resize', render)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment