Batch rectangle renderer with regl
This commit is contained in:
@@ -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
|
||||
})
|
||||
}
|
||||
@@ -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'
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Generated
+5
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user