Skip to content

Commit

Permalink
feat: v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
mmmurray committed Feb 18, 2020
1 parent bcbcbd5 commit 6c04a8e
Show file tree
Hide file tree
Showing 14 changed files with 11,928 additions and 1 deletion.
33 changes: 33 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Push

on: [push]

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install
uses: docker://mmmurray/test:latest
with:
entrypoint: yarn
args: install
- name: Build
uses: docker://mmmurray/test:latest
with:
entrypoint: yarn
args: build
- name: Test
uses: docker://mmmurray/test:latest
with:
entrypoint: yarn
args: test
- name: Release
uses: docker://mmmurray/test:latest
with:
entrypoint: yarn
args: release
GH_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*.zip
.DS_Store
.eslintignore
.eslintrc.js
.huskyrc
.npmignore
.prettierrc
.terraform
.tfplan
commitlint.config.js
coverage
dist/example
lib
node_modules
tsconfig.json
tsconfig.lib.json
yarn-error.log
51 changes: 50 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,51 @@
# triangular
# Triangular ▲

Type safe API for WebGL

## Installation

```bash
yarn add triangular
```

## Usage

```ts
import { createGL } from 'triangular'

const canvas = document.createElement('canvas')
const context = canvas.getContext('webgl')

if (!context) {
throw new Error('Your device does not support WebGL')
}

document.body.appendChild(canvas)

const gl = createGL(context)

const positionBuffer = gl.createAttributeBuffer('vec2', [0, 1, 1, -1, -1, -1])

const program = gl.createProgram({
attributes: { position: 'vec2' },
uniforms: {},
varying: {},
vertexShaderSource: ({ attributes }) => `
void main() {
gl_Position = vec4(${attributes.position}.xy, 0, 1);
}
`,
fragmentShaderSource: () => `
void main() {
gl_FragColor = vec4(0, 1, 0, 1);
}
`,
})

gl.clear()

program.drawTriangles({
uniforms: {},
attributeBuffers: { position: positionBuffer },
})
```
20 changes: 20 additions & 0 deletions mmm.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
test: {
coverageIgnores: ['src/**'],
},
components: [
{
type: 'ts-web-app',
name: 'example',
entryPath: 'src/example',
outputPath: 'dist/example',
htmlTemplatePath: 'src/example/index.html',
},
{
type: 'ts-lib',
name: 'lib',
entryPath: 'src/index.ts',
outputPath: 'lib',
},
],
}
24 changes: 24 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "triangular",
"version": "0.0.0",
"description": "Type safe API for WebGL",
"author": "Mark Murray",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"scripts": {
"build": "mmm build",
"deploy": "./scripts/deploy.sh",
"dev": "mmm dev",
"format": "mmm format",
"jest": "mmm jest",
"release": "mmm release",
"test": "mmm test",
"test:compile": "mmm test:compile",
"test:coverage": "mmm test:coverage",
"test:lint": "mmm test:lint"
},
"dependencies": {},
"devDependencies": {
"mmm-scripts": "1.1.0"
}
}
179 changes: 179 additions & 0 deletions src/__tests__/gl.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { createGL } from '../gl/gl'

const createTrackedFn = (name: string, calls: string[], result?: any) => ({
[name]: (...args: any[]) => {
calls.push(`${name}(${args.map(x => JSON.stringify(x)).join(', ')})`)
return result
},
})

const createIncrementingStirng = (name: string) => {
let index = 1
return () => `${name}-${index++}`
}

const createMockContext = (
overrides: { [key: string]: any } = {},
): { context: WebGLRenderingContext; getCalls: () => string[] } => {
const calls: string[] = []

const context: WebGLRenderingContext = {
COLOR_BUFFER_BIT: 1,
DEPTH_BUFFER_BIT: 2,
ARRAY_BUFFER: 'array_buffer',
ELEMENT_ARRAY_BUFFER: 'element_array_buffer',
STATIC_DRAW: 'static_draw',
FLOAT: 'float',
UNSIGNED_INT: 'uint',
VERTEX_SHADER: 'vertex',
FRAGMENT_SHADER: 'fragment',
TRIANGLES: 'triangles',
createProgram: createIncrementingStirng('program'),
createBuffer: createIncrementingStirng('buffer'),
createShader: (type: any) => `shader-${type}`,
getShaderInfoLog: () => '',
getAttribLocation: (program: any, name: any) => `aloc:${program}:${name}`,
getUniformLocation: (program: any, name: any) => `uloc:${program}:${name}`,
...createTrackedFn('getExtension', calls, true),
...createTrackedFn('clear', calls),
...createTrackedFn('clearColor', calls),
...createTrackedFn('drawArrays', calls),
...createTrackedFn('drawElements', calls),
...createTrackedFn('attachShader', calls),
...createTrackedFn('linkProgram', calls),
...createTrackedFn('useProgram', calls),
...createTrackedFn('shaderSource', calls),
...createTrackedFn('compileShader', calls),
...createTrackedFn('bindBuffer', calls),
...createTrackedFn('bufferData', calls),
...createTrackedFn('enableVertexAttribArray', calls),
...createTrackedFn('vertexAttribPointer', calls),
...createTrackedFn('uniformMatrix2fv', calls),
...overrides,
} as any

const getCalls = () => calls

return { context, getCalls }
}

test('can draw triangles', () => {
const { context, getCalls } = createMockContext()
const gl = createGL(context)

gl.clear()

const program = gl.createProgram({
attributes: { at1: 'vec2' },
uniforms: { un1: 'mat2' },
varying: {},
fragmentShaderSource: () => 'mock fragment shader',
vertexShaderSource: () => 'mock vertex shader',
})

const at1Buffer = gl.createAttributeBuffer('vec2', [0, 1, 2, 3, 4, 5])

program.drawTriangles({
uniforms: { un1: [1, 0, 0, 1] },
attributeBuffers: { at1: at1Buffer },
})

expect(getCalls()).toEqual([
'getExtension("OES_element_index_uint")',
'clearColor(0, 0, 0, 1)',
'clear(3)',
'shaderSource("shader-vertex", "attribute vec2 a_at1;\\nuniform mat2 u_un1;\\n\\nmock vertex shader")',
'compileShader("shader-vertex")',
'attachShader("program-1", "shader-vertex")',
'shaderSource("shader-fragment", "precision mediump float;\\n\\nmock fragment shader")',
'compileShader("shader-fragment")',
'attachShader("program-1", "shader-fragment")',
'linkProgram("program-1")',
'useProgram("program-1")',
'bindBuffer("array_buffer", "buffer-1")',
'bufferData("array_buffer", {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5}, "static_draw")',
'bindBuffer("array_buffer", "buffer-1")',
'enableVertexAttribArray("aloc:program-1:a_at1")',
'vertexAttribPointer("aloc:program-1:a_at1", 2, "float", false, 0, 0)',
'uniformMatrix2fv("uloc:program-1:u_un1", false, {"0":1,"1":0,"2":0,"3":1})',
'useProgram("program-1")',
'drawArrays("triangles", 0, 6)',
])
})

test('can draw triangles with indices', () => {
const { context, getCalls } = createMockContext()
const gl = createGL(context)

gl.clear()

const program = gl.createProgram({
attributes: { at1: 'vec2' },
uniforms: { un1: 'mat2' },
varying: {},
fragmentShaderSource: () => 'mock fragment shader',
vertexShaderSource: () => 'mock vertex shader',
})

const at1Buffer = gl.createAttributeBuffer('vec2', [0, 1, 2, 3, 4, 5])
const inBuffer = gl.createIndicesBuffer([1, 2, 3])

program.drawTriangles({
uniforms: { un1: [1, 0, 0, 1] },
attributeBuffers: { at1: at1Buffer },
indicesBuffer: inBuffer,
})

expect(getCalls()).toEqual([
'getExtension("OES_element_index_uint")',
'clearColor(0, 0, 0, 1)',
'clear(3)',
'shaderSource("shader-vertex", "attribute vec2 a_at1;\\nuniform mat2 u_un1;\\n\\nmock vertex shader")',
'compileShader("shader-vertex")',
'attachShader("program-1", "shader-vertex")',
'shaderSource("shader-fragment", "precision mediump float;\\n\\nmock fragment shader")',
'compileShader("shader-fragment")',
'attachShader("program-1", "shader-fragment")',
'linkProgram("program-1")',
'useProgram("program-1")',
'bindBuffer("array_buffer", "buffer-1")',
'bufferData("array_buffer", {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5}, "static_draw")',
'bindBuffer("element_array_buffer", "buffer-2")',
'bufferData("element_array_buffer", {"0":1,"1":2,"2":3}, "static_draw")',
'bindBuffer("array_buffer", "buffer-1")',
'enableVertexAttribArray("aloc:program-1:a_at1")',
'vertexAttribPointer("aloc:program-1:a_at1", 2, "float", false, 0, 0)',
'uniformMatrix2fv("uloc:program-1:u_un1", false, {"0":1,"1":0,"2":0,"3":1})',
'useProgram("program-1")',
'bindBuffer("element_array_buffer", "buffer-2")',
'drawElements("triangles", 6, "uint", 0)',
])
})

test('throws an error if unsigned integers extension cannot be enabled', () => {
const { context } = createMockContext({
getExtension: (name: string) => name !== 'OES_element_index_uint',
})

expect(() => createGL(context)).toThrowError(
'Device does not support gl.UNSIGNED_INT indices',
)
})

test('throws an error if a program cannot be created', () => {
const { context } = createMockContext({
createProgram: () => null,
})

const gl = createGL(context)
const createProgram = () =>
gl.createProgram({
uniforms: {},
attributes: {},
varying: {},
fragmentShaderSource: () => '',
vertexShaderSource: () => '',
})

expect(createProgram).toThrowError('Failed to create program')
})
Loading

0 comments on commit 6c04a8e

Please sign in to comment.