Refactor into a single CanvasContext
This commit is contained in:
+21
-28
@@ -1,12 +1,12 @@
|
||||
import {h} from 'preact'
|
||||
import * as regl from 'regl'
|
||||
import {StyleSheet, css} from 'aphrodite'
|
||||
import {ReloadableComponent} from './reloadable'
|
||||
|
||||
import {importFromBGFlameGraph} from './import/bg-flamegraph'
|
||||
import {importFromStackprof} from './import/stackprof'
|
||||
import {importFromChromeTimeline, importFromChromeCPUProfile} from './import/chrome'
|
||||
import { RectangleBatch, RectangleBatchRenderer } from './rectangle-batch-renderer'
|
||||
import { RectangleBatch } from './rectangle-batch-renderer'
|
||||
import { CanvasContext } from './canvas-context'
|
||||
|
||||
import {Profile, Frame} from './profile'
|
||||
import {Flamechart} from './flamechart'
|
||||
@@ -124,24 +124,25 @@ export class Toolbar extends ReloadableComponent<ToolbarProps, void> {
|
||||
}
|
||||
|
||||
interface GLCanvasProps {
|
||||
setGL(gl: regl.Instance | null): void
|
||||
setCanvasContext(canvasContext: CanvasContext | null): void
|
||||
}
|
||||
export class GLCanvas extends ReloadableComponent<GLCanvasProps, void> {
|
||||
private canvas: HTMLCanvasElement | null
|
||||
private gl: regl.Instance | null
|
||||
private canvas: HTMLCanvasElement | null = null
|
||||
private canvasContext: CanvasContext | null = null
|
||||
|
||||
private ref = (canvas?: Element) => {
|
||||
if (canvas instanceof HTMLCanvasElement) {
|
||||
this.canvas = canvas
|
||||
this.gl = regl(canvas)
|
||||
this.canvasContext = new CanvasContext(canvas)
|
||||
} else {
|
||||
this.gl = null
|
||||
this.canvas = null
|
||||
this.canvasContext = null
|
||||
}
|
||||
this.props.setGL(this.gl)
|
||||
this.props.setCanvasContext(this.canvasContext)
|
||||
}
|
||||
|
||||
private maybeResize() {
|
||||
if (!this.canvas || !this.gl) return
|
||||
if (!this.canvas) return
|
||||
let { width, height } = this.canvas.getBoundingClientRect()
|
||||
width = Math.floor(width) * window.devicePixelRatio
|
||||
height = Math.floor(height) * window.devicePixelRatio
|
||||
@@ -175,10 +176,10 @@ export class GLCanvas extends ReloadableComponent<GLCanvasProps, void> {
|
||||
}
|
||||
}
|
||||
|
||||
function rectangleBatchForFlamechart(gl: regl.Instance, flamechart: Flamechart) {
|
||||
function rectangleBatchForFlamechart(canvasContext: CanvasContext, flamechart: Flamechart) {
|
||||
console.time('rectangle batch generation')
|
||||
|
||||
const batch = new RectangleBatch(gl)
|
||||
const batch = canvasContext.createRectangleBatch()
|
||||
|
||||
const layers = flamechart.getLayers()
|
||||
for (let i = 0; i < layers.length; i++) {
|
||||
@@ -217,7 +218,7 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
}
|
||||
|
||||
loadFromString(fileName: string, contents: string) {
|
||||
if (!this.gl) return
|
||||
if (!this.canvasContext) return
|
||||
|
||||
console.time('import')
|
||||
const profile = importProfile(contents, fileName)
|
||||
@@ -241,7 +242,7 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
formatValue: profile.formatValue.bind(profile),
|
||||
getColorForFrame: colorGenerator.getColorForFrame.bind(colorGenerator)
|
||||
})
|
||||
const flamechartRectBatch = rectangleBatchForFlamechart(this.gl, flamechart)
|
||||
const flamechartRectBatch = rectangleBatchForFlamechart(this.canvasContext, flamechart)
|
||||
|
||||
const sortedFlamechart = new Flamechart({
|
||||
getTotalWeight: profile.getTotalNonIdleWeight.bind(profile),
|
||||
@@ -249,7 +250,7 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
formatValue: profile.formatValue.bind(profile),
|
||||
getColorForFrame: colorGenerator.getColorForFrame.bind(colorGenerator)
|
||||
})
|
||||
const sortedFlamechartRectBatch = rectangleBatchForFlamechart(this.gl, sortedFlamechart)
|
||||
const sortedFlamechartRectBatch = rectangleBatchForFlamechart(this.canvasContext, sortedFlamechart)
|
||||
|
||||
console.timeEnd('import')
|
||||
|
||||
@@ -361,16 +362,9 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
this.setState({ sortOrder })
|
||||
}
|
||||
|
||||
private gl: regl.Instance | null = null
|
||||
private rectangleBatchRenderer: RectangleBatchRenderer | null = null
|
||||
private setGL = (gl: regl.Instance | null) => {
|
||||
if (gl) {
|
||||
this.gl = gl
|
||||
this.rectangleBatchRenderer = new RectangleBatchRenderer(gl)
|
||||
} else {
|
||||
this.gl = null
|
||||
this.rectangleBatchRenderer = null
|
||||
}
|
||||
private canvasContext: CanvasContext | null = null
|
||||
private setCanvasContext = (canvasContext: CanvasContext | null) => {
|
||||
this.canvasContext = canvasContext
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -379,14 +373,13 @@ export class Application extends ReloadableComponent<{}, ApplicationState> {
|
||||
const rectangleBatch = sortOrder == SortOrder.CHRONO ? flamechartRectBatch : sortedFlamechartRectBatch
|
||||
|
||||
return <div onDrop={this.onDrop} onDragOver={this.onDragOver} className={css(style.root)}>
|
||||
<GLCanvas setGL={this.setGL} />
|
||||
<GLCanvas setCanvasContext={this.setCanvasContext} />
|
||||
<Toolbar setSortOrder={this.setSortOrder} {...this.state} />
|
||||
{loading ?
|
||||
this.renderLoadingBar() :
|
||||
this.gl && flamechartToView && this.rectangleBatchRenderer && rectangleBatch ?
|
||||
this.canvasContext && flamechartToView && rectangleBatch ?
|
||||
<FlamechartView
|
||||
gl={this.gl}
|
||||
renderer={this.rectangleBatchRenderer}
|
||||
canvasContext={this.canvasContext}
|
||||
rectangles={rectangleBatch}
|
||||
ref={this.flamechartRef}
|
||||
flamechart={flamechartToView} /> :
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import * as regl from 'regl'
|
||||
import { RectangleBatchRenderer, RectangleBatch, RectangleBatchRendererProps } from './rectangle-batch-renderer';
|
||||
import { ViewportRectangleRenderer, ViewportRectangleRendererProps } from './overlay-rectangle-renderer';
|
||||
import { Vec2, Rect } from './math';
|
||||
|
||||
|
||||
export class CanvasContext {
|
||||
private gl: regl.Instance
|
||||
private rectangleBatchRenderer: RectangleBatchRenderer
|
||||
private viewportRectangleRenderer: ViewportRectangleRenderer
|
||||
private setViewportScope: regl.Command<{ physicalBounds: Rect }>
|
||||
|
||||
constructor(canvas: HTMLCanvasElement) {
|
||||
this.gl = regl(canvas)
|
||||
this.rectangleBatchRenderer = new RectangleBatchRenderer(this.gl)
|
||||
this.viewportRectangleRenderer = new ViewportRectangleRenderer(this.gl)
|
||||
|
||||
this.setViewportScope = this.gl({
|
||||
viewport: (context, props) => {
|
||||
const { physicalBounds } = props
|
||||
return {
|
||||
x: physicalBounds.left(),
|
||||
y: window.devicePixelRatio * window.innerHeight - physicalBounds.top() - physicalBounds.height(),
|
||||
width: physicalBounds.width(),
|
||||
height: physicalBounds.height()
|
||||
}
|
||||
},
|
||||
scissor: (context, props) => {
|
||||
const { physicalBounds } = props
|
||||
return {
|
||||
enable: true,
|
||||
box: {
|
||||
x: physicalBounds.left(),
|
||||
y: window.devicePixelRatio * window.innerHeight - physicalBounds.top() - physicalBounds.height(),
|
||||
width: physicalBounds.width(),
|
||||
height: physicalBounds.height()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
drawRectangleBatch(props: RectangleBatchRendererProps) {
|
||||
this.rectangleBatchRenderer.render(props)
|
||||
}
|
||||
|
||||
createRectangleBatch(): RectangleBatch {
|
||||
return new RectangleBatch(this.gl)
|
||||
}
|
||||
|
||||
drawViewportRectangle(props: ViewportRectangleRendererProps){
|
||||
this.viewportRectangleRenderer.render(props)
|
||||
}
|
||||
|
||||
renderInto(el: HTMLElement, cb: () => void) {
|
||||
const bounds = el.getBoundingClientRect()
|
||||
const physicalBounds = new Rect(
|
||||
new Vec2(bounds.left * window.devicePixelRatio, bounds.top * window.devicePixelRatio),
|
||||
new Vec2(bounds.width * window.devicePixelRatio, bounds.height * window.devicePixelRatio)
|
||||
)
|
||||
this.setViewportScope({ physicalBounds }, cb)
|
||||
}
|
||||
}
|
||||
+10
-139
@@ -1,13 +1,12 @@
|
||||
import * as regl from 'regl'
|
||||
import { Command } from 'regl'
|
||||
import { h, Component } from 'preact'
|
||||
import { css } from 'aphrodite'
|
||||
import { Flamechart } from './flamechart'
|
||||
import { Rect, Vec2, AffineTransform, clamp } from './math'
|
||||
import { RectangleBatchRenderer, RectangleBatch } from "./rectangle-batch-renderer"
|
||||
import { RectangleBatch } from "./rectangle-batch-renderer"
|
||||
import { atMostOnceAFrame, cachedMeasureTextWidth } from "./utils";
|
||||
import { style, Sizes } from "./flamechart-style";
|
||||
import { FontFamily, FontSize, Colors } from "./style"
|
||||
import { CanvasContext } from './canvas-context'
|
||||
|
||||
const DEVICE_PIXEL_RATIO = window.devicePixelRatio
|
||||
|
||||
@@ -15,10 +14,7 @@ interface FlamechartMinimapViewProps {
|
||||
flamechart: Flamechart
|
||||
configSpaceViewportRect: Rect
|
||||
|
||||
// TODO(jlfwong): Encapsulate the regl.Instance and the batch renderer
|
||||
// in a CanvasContext object or something along those lines
|
||||
gl: regl.Instance
|
||||
renderer: RectangleBatchRenderer
|
||||
canvasContext: CanvasContext
|
||||
rectangles: RectangleBatch
|
||||
|
||||
transformViewport: (transform: AffineTransform) => void
|
||||
@@ -31,8 +27,6 @@ enum DraggingMode {
|
||||
}
|
||||
|
||||
export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps, {}> {
|
||||
viewportRectRenderer: Command<OverlayRectangleRendererProps> | null = null
|
||||
|
||||
canvas: HTMLCanvasElement | null = null
|
||||
|
||||
overlayCanvas: HTMLCanvasElement | null = null
|
||||
@@ -85,35 +79,19 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
this.resizeCanvasIfNeeded()
|
||||
const configSpaceToNDC = this.physicalViewSpaceToNDC().times(this.configSpaceToPhysicalViewSpace())
|
||||
|
||||
const bounds = this.canvas.getBoundingClientRect()
|
||||
const physicalBounds = this.logicalToPhysicalViewSpace().transformRect(new Rect(
|
||||
new Vec2(bounds.left, bounds.top),
|
||||
new Vec2(bounds.width, bounds.height)
|
||||
))
|
||||
|
||||
this.props.gl({
|
||||
viewport: {
|
||||
x: physicalBounds.left(),
|
||||
y: window.devicePixelRatio * window.innerHeight - physicalBounds.top() - physicalBounds.height(),
|
||||
width: physicalBounds.width(),
|
||||
height: physicalBounds.height()
|
||||
}
|
||||
})(() => {
|
||||
this.props.renderer.render({
|
||||
this.props.canvasContext.renderInto(this.canvas, () => {
|
||||
this.props.canvasContext.drawRectangleBatch({
|
||||
configSpaceToNDC: configSpaceToNDC,
|
||||
physicalSize: this.physicalViewSize(),
|
||||
strokeSize: 0,
|
||||
batch: this.props.rectangles
|
||||
})
|
||||
this.props.canvasContext.drawViewportRectangle({
|
||||
configSpaceViewportRect: this.props.configSpaceViewportRect,
|
||||
configSpaceToPhysicalViewSpace: this.configSpaceToPhysicalViewSpace(),
|
||||
physicalSize: this.physicalViewSize()
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
this.viewportRectRenderer({
|
||||
configSpaceViewportRect: this.props.configSpaceViewportRect,
|
||||
configSpaceToPhysicalViewSpace: this.configSpaceToPhysicalViewSpace(),
|
||||
physicalSize: this.physicalViewSize()
|
||||
})
|
||||
*/
|
||||
}
|
||||
|
||||
private renderOverlays() {
|
||||
@@ -451,110 +429,3 @@ export class FlamechartMinimapView extends Component<FlamechartMinimapViewProps,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export interface OverlayRectangleRendererProps {
|
||||
configSpaceToPhysicalViewSpace: AffineTransform
|
||||
configSpaceViewportRect: Rect
|
||||
physicalSize: Vec2
|
||||
}
|
||||
|
||||
export const viewportRectangleRenderer = (regl: regl.Instance) => {
|
||||
return regl<OverlayRectangleRendererProps>({
|
||||
vert: `
|
||||
attribute vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0, 1);
|
||||
}
|
||||
`,
|
||||
|
||||
frag: `
|
||||
precision mediump float;
|
||||
|
||||
uniform mat3 configSpaceToPhysicalViewSpace;
|
||||
uniform vec2 physicalSize;
|
||||
uniform vec2 configSpaceViewportOrigin;
|
||||
uniform vec2 configSpaceViewportSize;
|
||||
|
||||
void main() {
|
||||
vec2 origin = (configSpaceToPhysicalViewSpace * vec3(configSpaceViewportOrigin, 1.0)).xy;
|
||||
vec2 size = (configSpaceToPhysicalViewSpace * vec3(configSpaceViewportSize, 0.0)).xy;
|
||||
|
||||
vec2 halfSize = physicalSize / 2.0;
|
||||
|
||||
float borderWidth = 2.0;
|
||||
|
||||
origin = floor(origin * halfSize) / halfSize + borderWidth * vec2(1.0, 1.0);
|
||||
size = floor(size * halfSize) / halfSize - 2.0 * borderWidth * vec2(1.0, 1.0);
|
||||
|
||||
vec2 coord = gl_FragCoord.xy;
|
||||
coord.y = physicalSize.y - coord.y;
|
||||
vec2 clamped = clamp(coord, origin, origin + size);
|
||||
vec2 gap = clamped - coord;
|
||||
float maxdist = max(abs(gap.x), abs(gap.y));
|
||||
|
||||
// TOOD(jlfwong): Could probably optimize this to use mix somehow.
|
||||
if (maxdist == 0.0) {
|
||||
// Inside viewport rectangle
|
||||
gl_FragColor = vec4(0, 0, 0, 0);
|
||||
} else if (maxdist < borderWidth) {
|
||||
// Inside viewport rectangle at border
|
||||
gl_FragColor = vec4(0.7, 0.7, 0.7, 0.8);
|
||||
} else {
|
||||
// Outside viewport rectangle
|
||||
gl_FragColor = vec4(0.7, 0.7, 0.7, 0.5);
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: 'src alpha',
|
||||
srcAlpha: 'one',
|
||||
dstRGB: 'one minus src alpha',
|
||||
dstAlpha: 'one'
|
||||
}
|
||||
},
|
||||
|
||||
depth: {
|
||||
enable: false
|
||||
},
|
||||
|
||||
attributes: {
|
||||
// Cover full canvas with a rectangle
|
||||
// with 2 triangles using a triangle
|
||||
// strip.
|
||||
//
|
||||
// 0 +--+ 1
|
||||
// | /|
|
||||
// |/ |
|
||||
// 2 +--+ 3
|
||||
position: [
|
||||
[-1, 1],
|
||||
[1, 1],
|
||||
[-1, -1],
|
||||
[1, -1]
|
||||
]
|
||||
},
|
||||
|
||||
uniforms: {
|
||||
configSpaceToPhysicalViewSpace: (context, props) => {
|
||||
return props.configSpaceToPhysicalViewSpace.flatten()
|
||||
},
|
||||
configSpaceViewportOrigin: (context, props) => {
|
||||
return props.configSpaceViewportRect.origin.flatten()
|
||||
},
|
||||
configSpaceViewportSize: (context, props) => {
|
||||
return props.configSpaceViewportRect.size.flatten()
|
||||
},
|
||||
physicalSize: (context, props) => {
|
||||
return props.physicalSize.flatten()
|
||||
}
|
||||
},
|
||||
|
||||
primitive: 'triangle strip',
|
||||
|
||||
count: 4
|
||||
})
|
||||
}
|
||||
+8
-25
@@ -1,4 +1,3 @@
|
||||
import * as regl from 'regl'
|
||||
import {h} from 'preact'
|
||||
import {css} from 'aphrodite'
|
||||
import {ReloadableComponent} from './reloadable'
|
||||
@@ -8,11 +7,12 @@ import { Flamechart, FlamechartFrame } from './flamechart'
|
||||
|
||||
import { Rect, Vec2, AffineTransform, clamp } from './math'
|
||||
import { atMostOnceAFrame, cachedMeasureTextWidth } from "./utils";
|
||||
import { RectangleBatchRenderer, RectangleBatch } from "./rectangle-batch-renderer"
|
||||
import { RectangleBatch } from "./rectangle-batch-renderer"
|
||||
import { FlamechartMinimapView } from "./flamechart-minimap-view"
|
||||
|
||||
import { style, Sizes } from './flamechart-style'
|
||||
import { FontSize, FontFamily, Colors } from './style'
|
||||
import { CanvasContext } from './canvas-context'
|
||||
|
||||
interface FlamechartFrameLabel {
|
||||
configSpaceBounds: Rect
|
||||
@@ -73,8 +73,7 @@ const DEVICE_PIXEL_RATIO = window.devicePixelRatio
|
||||
interface FlamechartPanZoomViewProps {
|
||||
flamechart: Flamechart
|
||||
|
||||
gl: regl.Instance
|
||||
renderer: RectangleBatchRenderer
|
||||
canvasContext: CanvasContext
|
||||
rectangles: RectangleBatch
|
||||
|
||||
setNodeHover: (node: CallTreeNode | null, logicalViewSpaceMouse: Vec2) => void
|
||||
@@ -336,21 +335,8 @@ export class FlamechartPanZoomView extends ReloadableComponent<FlamechartPanZoom
|
||||
|
||||
const configSpaceToNDC = this.physicalViewSpaceToNDC().times(this.configSpaceToPhysicalViewSpace())
|
||||
|
||||
const bounds = this.canvas.getBoundingClientRect()
|
||||
const physicalBounds = this.logicalToPhysicalViewSpace().transformRect(new Rect(
|
||||
new Vec2(bounds.left, bounds.top),
|
||||
new Vec2(bounds.width, bounds.height)
|
||||
))
|
||||
|
||||
this.props.gl({
|
||||
viewport: {
|
||||
x: physicalBounds.left(),
|
||||
y: window.devicePixelRatio * window.innerHeight - physicalBounds.top() - physicalBounds.height(),
|
||||
width: physicalBounds.width(),
|
||||
height: physicalBounds.height()
|
||||
}
|
||||
})(() => {
|
||||
this.props.renderer.render({
|
||||
this.props.canvasContext.renderInto(this.canvas, () => {
|
||||
this.props.canvasContext.drawRectangleBatch({
|
||||
configSpaceToNDC: configSpaceToNDC,
|
||||
physicalSize: this.physicalViewSize(),
|
||||
strokeSize: 1,
|
||||
@@ -604,8 +590,7 @@ export class FlamechartPanZoomView extends ReloadableComponent<FlamechartPanZoom
|
||||
|
||||
interface FlamechartViewProps {
|
||||
flamechart: Flamechart
|
||||
gl: regl.Instance
|
||||
renderer: RectangleBatchRenderer
|
||||
canvasContext: CanvasContext
|
||||
rectangles: RectangleBatch
|
||||
}
|
||||
|
||||
@@ -736,15 +721,13 @@ export class FlamechartView extends ReloadableComponent<FlamechartViewProps, Fla
|
||||
<FlamechartMinimapView
|
||||
configSpaceViewportRect={this.state.configSpaceViewportRect}
|
||||
transformViewport={this.transformViewport}
|
||||
gl={this.props.gl}
|
||||
renderer={this.props.renderer}
|
||||
canvasContext={this.props.canvasContext}
|
||||
rectangles={this.props.rectangles}
|
||||
setConfigSpaceViewportRect={this.setConfigSpaceViewportRect}
|
||||
flamechart={this.props.flamechart} />
|
||||
<FlamechartPanZoomView
|
||||
ref={this.panZoomRef}
|
||||
gl={this.props.gl}
|
||||
renderer={this.props.renderer}
|
||||
canvasContext={this.props.canvasContext}
|
||||
rectangles={this.props.rectangles}
|
||||
flamechart={this.props.flamechart}
|
||||
setNodeHover={this.onNodeHover}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import * as regl from 'regl'
|
||||
import { AffineTransform, Rect, Vec2 } from './math'
|
||||
|
||||
export interface ViewportRectangleRendererProps {
|
||||
configSpaceToPhysicalViewSpace: AffineTransform
|
||||
configSpaceViewportRect: Rect
|
||||
physicalSize: Vec2
|
||||
}
|
||||
|
||||
export class ViewportRectangleRenderer {
|
||||
private command: regl.Command<ViewportRectangleRendererProps>
|
||||
constructor(regl: regl.Instance) {
|
||||
this.command = regl<ViewportRectangleRendererProps>({
|
||||
vert: `
|
||||
attribute vec2 position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(position, 0, 1);
|
||||
}
|
||||
`,
|
||||
|
||||
frag: `
|
||||
precision mediump float;
|
||||
|
||||
uniform mat3 configSpaceToPhysicalViewSpace;
|
||||
uniform vec2 physicalSize;
|
||||
uniform vec2 configSpaceViewportOrigin;
|
||||
uniform vec2 configSpaceViewportSize;
|
||||
|
||||
void main() {
|
||||
vec2 origin = (configSpaceToPhysicalViewSpace * vec3(configSpaceViewportOrigin, 1.0)).xy;
|
||||
vec2 size = (configSpaceToPhysicalViewSpace * vec3(configSpaceViewportSize, 0.0)).xy;
|
||||
|
||||
vec2 halfSize = physicalSize / 2.0;
|
||||
|
||||
float borderWidth = 2.0;
|
||||
|
||||
origin = floor(origin * halfSize) / halfSize + borderWidth * vec2(1.0, 1.0);
|
||||
size = floor(size * halfSize) / halfSize - 2.0 * borderWidth * vec2(1.0, 1.0);
|
||||
|
||||
vec2 coord = gl_FragCoord.xy;
|
||||
coord.y = physicalSize.y - coord.y;
|
||||
vec2 clamped = clamp(coord, origin, origin + size);
|
||||
vec2 gap = clamped - coord;
|
||||
float maxdist = max(abs(gap.x), abs(gap.y));
|
||||
|
||||
// TOOD(jlfwong): Could probably optimize this to use mix somehow.
|
||||
if (maxdist == 0.0) {
|
||||
// Inside viewport rectangle
|
||||
gl_FragColor = vec4(0, 0, 0, 0);
|
||||
} else if (maxdist < borderWidth) {
|
||||
// Inside viewport rectangle at border
|
||||
gl_FragColor = vec4(0.7, 0.7, 0.7, 0.8);
|
||||
} else {
|
||||
// Outside viewport rectangle
|
||||
gl_FragColor = vec4(0.7, 0.7, 0.7, 0.5);
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
blend: {
|
||||
enable: true,
|
||||
func: {
|
||||
srcRGB: 'src alpha',
|
||||
srcAlpha: 'one',
|
||||
dstRGB: 'one minus src alpha',
|
||||
dstAlpha: 'one'
|
||||
}
|
||||
},
|
||||
|
||||
depth: {
|
||||
enable: false
|
||||
},
|
||||
|
||||
attributes: {
|
||||
// Cover full canvas with a rectangle
|
||||
// with 2 triangles using a triangle
|
||||
// strip.
|
||||
//
|
||||
// 0 +--+ 1
|
||||
// | /|
|
||||
// |/ |
|
||||
// 2 +--+ 3
|
||||
position: [
|
||||
[-1, 1],
|
||||
[1, 1],
|
||||
[-1, -1],
|
||||
[1, -1]
|
||||
]
|
||||
},
|
||||
|
||||
uniforms: {
|
||||
configSpaceToPhysicalViewSpace: (context, props) => {
|
||||
return props.configSpaceToPhysicalViewSpace.flatten()
|
||||
},
|
||||
configSpaceViewportOrigin: (context, props) => {
|
||||
return props.configSpaceViewportRect.origin.flatten()
|
||||
},
|
||||
configSpaceViewportSize: (context, props) => {
|
||||
return props.configSpaceViewportRect.size.flatten()
|
||||
},
|
||||
physicalSize: (context, props) => {
|
||||
return props.physicalSize.flatten()
|
||||
}
|
||||
},
|
||||
|
||||
primitive: 'triangle strip',
|
||||
|
||||
count: 4
|
||||
})
|
||||
}
|
||||
|
||||
render(props: ViewportRectangleRendererProps) {
|
||||
this.command(props)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user