Skip to content

Commit

Permalink
<GLText> Disable depth testing when scale invariance is enabled (crui…
Browse files Browse the repository at this point in the history
…se-automation#384)

* Disable depth testing when scale invariance is enabled for GLText

* Update docs/src/4.15.GLText.mdx

Co-Authored-By: Troy Gibb <[email protected]>

Co-authored-by: Troy Gibb <[email protected]>
  • Loading branch information
hhsaez and troygibb authored Mar 27, 2020
1 parent e8295cc commit 09c5631
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 7 deletions.
12 changes: 8 additions & 4 deletions docs/src/4.15.GLText.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,29 @@ The prop types are identical to `<Text />`, except that additionally each Text o

## Scale Invariance

`<GLText />` also supports rendering text at a constant scale regardless of the zoom level by using the optional `scaleInvariantFontSize?: number` property. If set (default is `undefined`), the text will be rendered always at the same size, resembling the behavior of the `<Text />` command.
`<GLText />` also supports rendering text at a constant scale regardless of the zoom level by using the optional `scaleInvariantFontSize?: number` property. If set (default is `undefined`), the text will be rendered always at the same size, resembling the behavior of the `<Text />` command.

Please note that `scaleInvariantFontSize` only works if the `billboard` property is set to true.

<GLTextScaleInvariant />

### Rendering text on top of other objects

If scale invariance is enabled, you should make sure `<GLText />` is the last command being rendered in your world representation. That will draw these text markers on top of other visible objects.

## Resolution

By default, `<GLText />` uses a high resolution font texture atlas for rendering text, which may have an impact on the performance of your application.
By default, `<GLText />` uses a high resolution font texture atlas for rendering text, which may have an impact on the performance of your application.

The optional `resolution?: number` property allows you to override the default high resolution. If your application does not need to render text that is too close the camera, it is recommended to reduce the font resolution to ensure a better performance.

**Default value is `resolution={160}`. Minimum value is `resolution={40}`.**

## Alphabet

`<GLText />` generates a new texture atlas on the fly whenever a marker's text contains at least one character that was not rendered before. This is a complex operation and may impact on the performance of your application.
`<GLText />` generates a new texture atlas on the fly whenever a marker's text contains at least one character that was not rendered before. This is a complex operation and may impact on the performance of your application.

In order to avoid texture generation when you have an expected subset of characters, you can use the optional `alphabet?: string[]`.
In order to avoid texture generation when you have an expected subset of characters, you can use the optional `alphabet?: string[]`.

For example, if markers are known to have only digits, you can use the `alphabet` property as follows to reduce the number of times the texture atlas needs to be re-generated from a worst case scenario of 10 times to only once.

Expand Down
8 changes: 6 additions & 2 deletions packages/regl-worldview/src/commands/GLText.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import memoizeOne from "memoize-one";
import React, { useState } from "react";

import type { Color } from "../types";
import { defaultBlend, defaultDepth, toColor } from "../utils/commandUtils";
import { defaultBlend, defaultDepth, disabledDepth, toColor } from "../utils/commandUtils";
import { createInstancedGetChildrenForHitmap } from "../utils/getChildrenForHitmapDefaults";
import Command, { type CommonCommandProps } from "./Command";
import { isColorDark, type TextMarker } from "./Text";
Expand Down Expand Up @@ -311,7 +311,11 @@ function makeTextCommand(alphabet?: string[]) {
const atlasTexture = regl.texture();
const makeDrawText = (isHitmap: boolean) => {
return regl({
depth: defaultDepth,
// When using scale invariance, we want the text to be drawn on top
// of other elements. This is achieved by disabling depth testing
// In addition, make sure the <GLText /> command is the last one
// being rendered.
depth: command.scaleInvariant ? disabledDepth : defaultDepth,
blend: defaultBlend,
primitive: "triangle strip",
vert,
Expand Down
83 changes: 82 additions & 1 deletion packages/regl-worldview/src/stories/GLText.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import React, { useState, useLayoutEffect, useCallback } from "react";
import { withScreenshot } from "storybook-chrome-screenshot";
import tinyColor from "tinycolor2";

import { Axes } from "../commands";
import { Axes, Cubes } from "../commands";
import type { Color } from "../types";
import { vec4ToOrientation } from "../utils/commandUtils";
import Container from "./Container";
Expand Down Expand Up @@ -400,4 +400,85 @@ storiesOf("Worldview/GLText", module)
};

return <Example />;
})
.add("Depth testing enabled for text in the 3D world", () => {
const text = {
text: "Hello\nWorld!",
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 1, y: 1, z: 1 },
color: { r: 1, g: 1, b: 1, a: 1 },
billboard: true,
};
const cube = {
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 2, y: 2, z: 2 },
color: { r: 1, g: 0, b: 1, a: 1 },
};
return (
<Container cameraState={{ perspective: false, distance: 25 }}>
<Cubes>{[cube]}</Cubes>
<GLText>{[text]}</GLText>
<Axes />
</Container>
);
})
.add("Depth testing disabled when using scale invariance. Draw order issues.", () => {
const text = {
text: "Hello\nWorld!",
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 1, y: 1, z: 1 },
color: { r: 1, g: 1, b: 1, a: 1 },
billboard: true,
};
const cube = {
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 2, y: 2, z: 2 },
color: { r: 1, g: 0, b: 1, a: 1 },
};
return (
<Container cameraState={{ perspective: false, distance: 25 }}>
<Axes />
<GLText scaleInvariantFontSize={30}>{[text]}</GLText>
<Cubes>{[cube]}</Cubes>
</Container>
);
})
.add("Depth testing disabled when using scale invariance. GLText render last", () => {
const text = {
text: "Hello\nWorld!",
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 1, y: 1, z: 1 },
color: { r: 1, g: 1, b: 1, a: 1 },
billboard: true,
};
const cube = {
pose: {
position: { x: 0, y: 0, z: 0 },
orientation: { x: 0, y: 0, z: 0, w: 1 },
},
scale: { x: 2, y: 2, z: 2 },
color: { r: 1, g: 0, b: 1, a: 1 },
};
return (
<Container cameraState={{ perspective: false, distance: 25 }}>
<Cubes>{[cube]}</Cubes>
<Axes />
<GLText scaleInvariantFontSize={30}>{[text]}</GLText>
</Container>
);
});
5 changes: 5 additions & 0 deletions packages/regl-worldview/src/utils/commandUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ export const defaultDepth = {
mask: (context: any, props: any) => (props.depth && props.depth.mask) || defaultReglDepth.mask,
};

export const disabledDepth = {
enable: (context: any, props: any) => false,
mask: (context: any, props: any) => false,
};

export const defaultBlend = {
...defaultReglBlend,
enable: (context: any, props: any) => (props.blend && props.blend.enable) || defaultReglBlend.enable,
Expand Down

0 comments on commit 09c5631

Please sign in to comment.