Batch rectangle renderer with regl

This commit is contained in:
Jamie Wong
2017-11-22 19:19:10 -08:00
parent facc492310
commit af9783c838
5 changed files with 185 additions and 1 deletions
+76
View File
@@ -1,4 +1,5 @@
import {Profile, Frame} from './profile'
import regl, {ReglCommandConstructor} from 'regl'
interface FlamechartFrame {
frame: Frame
@@ -49,4 +50,79 @@ export class Flamechart {
profile.forEachSample(this.appendSample.bind(this))
this.layers = this.layers.map(Flamechart.mergeAdjacentFrames)
}
}
interface Rect {
left: number
top: number
width: number
height: number
}
type vec2 = [number, number]
type vec3 = [number, number, number]
type mat3 = [number, number, number, number, number, number, number, number, number]
export const rectangleBatchRenderer = (ctx: WebGLRenderingContext, rects: Rect[], colors: vec3[]) => {
const gl = regl(ctx)
const positions: vec2[] = []
const vertexColors: vec3[] = []
const addRectangle = (r: Rect, color: [number, number, number]) => {
const NW: [number, number] = [r.left, r.top]
const NE: [number, number] = [r.left + r.width, r.top]
const SW: [number, number] = [r.left, r.top + r.height]
const SE: [number, number] = [r.left + r.width, r.top + r.height]
positions.push(NW)
positions.push(SW)
positions.push(NE)
positions.push(SW)
positions.push(NE)
positions.push(SE)
for (let i = 0; i < 6; i++) vertexColors.push(color)
}
for (let i = 0; i < rects.length; i++) addRectangle(rects[i], colors[i])
return gl<{
configSpaceToNDC: mat3
}>({
vert: `
uniform mat3 configSpaceToNDC;
attribute vec2 position;
attribute vec3 color;
varying vec3 vColor;
void main() {
vColor = color;
gl_Position = vec4((configSpaceToNDC * vec3(position, 1)).xy, 0, 1);
}
`,
frag: `
precision mediump float;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1);
}
`,
attributes: {
position: positions,
color: vertexColors
},
uniforms: {
configSpaceToNDC: (context, props) => {
return props.configSpaceToNDC
}
},
primitive: 'triangles',
count: colors.length
})
}
+50 -1
View File
@@ -2,6 +2,53 @@ import {h, render, Component} from 'preact'
import {StyleSheet, css} from 'aphrodite'
import {importFromStackprof} from './stackprof'
import {Flamechart, rectangleBatchRenderer} from './flamechart'
import { request } from 'https';
interface Rect {
left: number
top: number
width: number
height: number
}
class Canvas extends Component<{}, void> {
canvasRef = (element?: Element) => {
if (element) {
const rectangles: Rect[] = []
const colors: [number, number, number][] = []
for (let i = 0; i < 1000; i++) {
rectangles.push({
left: 2 * Math.random() - 1,
top: 2 * Math.random() - 1,
width: 2 * Math.random(),
height: 2 * Math.random(),
})
colors.push([Math.random(), Math.random(), Math.random()])
}
const renderer = rectangleBatchRenderer((element as HTMLCanvasElement).getContext('webgl')!, rectangles, colors)
;(function doit() {
renderer({
configSpaceToNDC: [
1, 0, 0,
0, 1, 0,
0, 0, 1,
]
})
requestAnimationFrame(doit)
})()
}
}
render() {
const width = window.innerWidth
const height = window.innerHeight
return <canvas width={width} height={height} ref={this.canvasRef} className={css(style.root)}></canvas>
}
}
class Application extends Component<{}, void> {
onDrop = (ev: DragEvent) => {
@@ -19,6 +66,7 @@ class Application extends Component<{}, void> {
render() {
return <div onDrop={this.onDrop} onDragOver={this.onDragOver} className={css(style.root)}>
<Canvas />
</div>
}
}
@@ -26,7 +74,8 @@ class Application extends Component<{}, void> {
const style = StyleSheet.create({
root: {
width: '100vw',
height: '100vw'
height: '100vh',
overflow: 'hidden'
}
})
+5
View File
@@ -628,6 +628,11 @@
"is-equal-shallow": "0.1.3"
}
},
"regl": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regl/-/regl-1.3.0.tgz",
"integrity": "sha1-zN6C7/iooGilWVgc6svvGv6njr0="
},
"remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+3
View File
@@ -23,5 +23,8 @@
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-typescript": "^0.8.1",
"typescript": "^2.6.1"
},
"dependencies": {
"regl": "^1.3.0"
}
}
Vendored
+51
View File
@@ -0,0 +1,51 @@
declare module "regl" {
interface ReglProp {}
type ReglPrimitiveValue =
boolean |
number |
number[] |
number[][] |
ReglProp
type ReglValue<P> = ReglPrimitiveValue | {(context: any, props: P, batchId: number): ReglPrimitiveValue}
interface ReglCommandParameters<P> {
/** Source code of vertex shader */
vert: string
/** Source code of fragment shader */
frag: string
attributes: {[attributeName: string]: ReglValue<P>}
uniforms: {[uniformName: string]: ReglValue<P>}
/** Number of vertices to draw */
count: number
/** */
primitive?: 'points' | 'lines' | 'line strip' | 'triangles' | 'triangle strip' | 'triangle fan'
/** Offset of primitives to draw */
offset?: number
}
interface ReglCommand<P> {
(p: P): void
}
export interface ReglCommandConstructor {
<P>(params: ReglCommandParameters<P>): ReglCommand<P>
}
function ReglConstructor(): ReglCommandConstructor
function ReglConstructor(ctx: WebGLRenderingContext): ReglCommandConstructor
function ReglConstructor(canvas: HTMLCanvasElement): ReglCommandConstructor
namespace ReglConstructor {
function prop(name: string): ReglProp
}
export default ReglConstructor
}