API

Creating A GreasedLine

GreasedLine

GreasedLine is a special type of line that uses a regular mesh with triangles to display a line of any width. It incorporates custom shaders designed to ensure that the mesh always faces the camera, resulting in consistent thickness from all perspectives. The shaders are provided through a plugin material. You can use StandardMaterial or PBRMaterial with GreasedLine, so you can use any property of the material to stylize your line. GreasedLine also features dashing, multicolored lines with sampling options, color blending options, variable width on both sides of the line (upper and lower parts), visibility (what percentage of the line is visible), point coordinate offsets, instance mode (you can add more lines to an instance and they will be drawn in one draw call), and lazy mode. The values for these features are animatable. You can also translate, rotate, and scale the line because it's a mesh.

Create a GreasedLine

The easiest, preferred and recommended way to create a GreasedLine is to use the CreateGreasedLine function:

function CreateGreasedLine(name: string, options: GreasedLineMeshBuilderOptions, materialOptions?: Nullable<GreasedLineMaterialBuilderOptions>, scene?: Nullable<Scene>)

The simplest usage is:

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const line = CreateGreasedLine("name", { points });
Basic usage Transforming a GreasedLine mesh

Dispose a GreasedLine

Please note that the dispose function doesn't dispose the material created for the line by default. You have to set the disposeMaterialAndTextures parameter to true in the dispose function if you want to dispose the associated material and textures as well.

GreasedLineMeshBuilderOptions

You will find an explanation of these options below this code snippet.

points: GreasedLinePoints;
pointsOptions?: GreasedLinePointsOptions;
widths?: number[];
widthDistribution?: GreasedLineMeshWidthDistribution;
instance?: GreasedLineMesh;
updatable?: boolean;
uvs?: number[];
lazy?: boolean;

points

Points of the line specified as x, y, z coordinates. All the points connected are called a line. The part of the line between two points is called a line segment in this documentation.

points can be of type number[], number[][], Vector3[], Vector3[][], Float32Array, or Float32Array[].

If you want to draw only one contiguous line you can use 1D arrays or Float32Array. If you want to draw multiple lines you have to use 2D arrays or Float32Array[].

To draw multiple disconnected lines using a flat Float32Array, you can specify the pointsOptions.stride property in the GreasedLineMeshBuilderOptions object. This value sets how many entries from the Float32Array will be used to create one line. One entry = 3 float values.

Float32Array stride
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
const points =
[
0, 0, 0,
1, 0, 0,
1, 1, 0
]
// x, y, z,
// x, y, z, ...
// is the same as
const points =
[
new Vector3(0,0,0)
new Vector3(1,0,0)
new Vector3(1,1,0)
]

It's a good habit to format your number coordinates for better readability.

We recommend using number or Float32Array objects when possible to avoid the unnecessary creation of temporary Vector3 objects holding the points, especially if you are creating the coordinates dynamically on the fly. The coordinates are converted to number[][] internally, so number[] or number[][] are the fastest options.

To draw two or more lines at once, you can define the points as:

const points = [
[0, 0, 0, 1, 0, 0],
[0, 1, 0, 1, 1, 0],
];

You can draw more lines at once by using the instance option. See the Instance mode example below.

You need to specify at least two points to draw a line, obviously.

Do not use sharp-angle connected long lines because they can be distorted by perspective. Use smaller line segments. There are helper functions available in BABYLON.GreasedLineTools for that. See the GreasedLineTools section for more info. Another option is to create two lines and add them to one instance, or add them as separate lines like this (this approach can cause small quirks where the lines 'connect' to each other when using dash mode, depending on your line width):

const points = [
[-10, 0, 0, 0, 10, 0],
[0, 10, 0, 10, 0, 0],
];

There is another option to avoid distortion when drawing thick, connected, long line segments: you need to duplicate each position, as demonstrated here:

Duplicating points

Please note that the points property is not updatable, unlike when using a LineMesh. You have to use the offsets property on the line instance to update point positions without recreating the mesh. Updating the offsets doesn't involve any calculations and updates only one vertex buffer. See the Offsets section below and the PG example Offsetting line vertices.

However, there are two public methods available on the line instance for manipulating the points. Both of these functions will destroy the mesh and create a new one. This point-manipulation method is slower, but if you are not dealing with a lot of lines, it should not cause FPS issues.

addPoints(points: number[][]) // ads points to the existing ones and recreates the mesh
setPoints(points: number[][]) // sets the points and recreates the mesh - the number of points must be the same as in the original line

If you are using the right-handed coordinate system, please create the lines after you switch the scene to it.

If you modify the number of points in the line, you have to set the widths for the new lines or line segments before calling either of these two methods.

widths and widthDistribution

You can specify two width multiplier values for each point in your line. These values are multiplied with the width of the line to draw the resulting line. The first value specifies the width multiplier of the line below the line and the second above the line. These values are not normalized so if you use a value of 2, 2 the line will be twice the width at that point. There must be exactly the same count of width pair values as there are points.

The CreateGreasedLine function uses the function CompleteGreasedLineWidthTable to fill the missing values, if any. You can use the widthDistribution option to set the method used to automatically fill the widths table.

You can choose from these values:

enum GreasedLineMeshWidthDistribution {
WIDTH_DISTRIBUTION_NONE = 0,
WIDTH_DISTRIBUTION_REPEAT = 1,
WIDTH_DISTRIBUTION_EVEN = 2,
WIDTH_DISTRIBUTION_START = 3,
WIDTH_DISTRIBUTION_END = 4,
WIDTH_DISTRIBUTION_START_END = 5,
}

The default for this option is WIDTH_DISTRIBUTION_START.

Let's see an example:

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [0, 0, 0, 1, 0, 0];
const widths = [2, 2];
const line = CreateGreasedLine("line", { points, widths });

You can use the function CompleteGreasedLineWidthTable manually and set the widthDistribution to WIDTH_DISTRIBUTION_NONE. If you prepared the width table with the correct number of entries, set widthDistribution to WIDTH_DISTRIBUTION_NONE as well.

Please have a look at the API docs for more explanation about the width distribution modes.

You might wonder, as you continue reading, why you'll find the width option specified in materialOptions and widths here. It's because the options object contains all the mesh-related options, and width is used when creating the material, so it is material-related.

Widths

instance

You can add lines to an existing line whenever you want. All you need to do is specify the instance option and set a GreasedLineMesh instance on it. Every time you add a new line, all the data needed to render the line will be recalculated and the buffers will be updated. If you are adding many lines to an instance, use the lazy option. Lines added to an instance are joined with the existing mesh. See the examples for code.

Instance mode

updatable

If you want to update your line mesh after it was created, set this option to true when creating the line. This applies to offsets, segmentWidths, and colorPointers. This option doesn't affect the line materials, which can be updated at any time. Set this value to false if you don't intend to update the line mesh, for better performance. If you are adding lines to an existing line instance, you have to set this option on the line that was created first.

uvs

You can set your custom UVs when creating the line.

lazy

You can disable recalculating line data and updating the buffers when adding a new line to a line instance by setting this option to true. This option is always used with the instance option specified. If you're done adding new lines, you just need to call line.updateLazy() to recalculate the data and update the buffers. See the examples for code.

Lazy mode

GreasedLineMaterialBuilderOptions

createAndAssignMaterial?: boolean;
width?: number;
sizeAttenuation?: boolean;
materialType?: GreasedLineMeshMaterialType;
color?: Color3;
colorMode?: GreasedLineMeshColorMode;
colors?: Color3[];
colorDistribution?: GreasedLineMeshColorDistribution;
colorDistributionType?: GreasedLineMeshColorDistributionType;
useColors?: boolean;
colorsSampling?: number;
useDash?: boolean;
dashCount?: number;
dashOffset?: number;
dashRatio?: number;
visibility?: number;
resolution?: Vector2;
cameraFacing?: boolean;

createAndAssignMaterial

If set to true a new material will be created and a new material plugin will be attached to the material. The material will be set on the mesh. If the instance option is specified in the mesh options, no material will be created/assigned. If you omit GreasedLineMaterialBuilderOptions when calling CreateGreasedLine it behaves as if this option was set to true so it creates the material and the plugin. The default value is true. You can share the material between multiple lines so if you don't need a new material, set this to false to save resources and gain performance.

width

Line width in scene units unless sizeAttenuation is true. You can override the default value:

GreasedLineMaterialDefaults.DEFAULT_WIDTH_ATTENUATED = 10;
GreasedLineMaterialDefaults.DEFAULT_WIDTH = 0.5;

All lines created after setting this value and not providing a width option will use this value as the default one.

sizeAttenuation

If true, the line width will always be the same regardless of the distance from the camera. The upper line has constant width no matter how far it is from the camera. This PG also demonstrates how to use default values:

Size attenuation and GreasedLineMaterialDefaults

materialType

Type of the material to use to render the line. Default is StandardMaterial. Currently you can choose from:

enum GreasedLineMeshMaterialType {
MATERIAL_TYPE_STANDARD = 0,
MATERIAL_TYPE_PBR = 1,
MATERIAL_TYPE_SIMPLE = 2
}

The first two materials are implemented using material plugins. The simple material is based on a shader material. It is super fast but supports only plain colors without lighting.

color

Color of the line. Applies to all line segments. Defaults to White. You can change the default color to any other color.

import { GreasedLinePluginMaterial } from "@babylonjs/core/Materials/GreasedLine/greasedLinePluginMaterial";
import { Color3 } from "@babylonjs/core/Maths/math.color";
GreasedLinePluginMaterial.DEFAULT_COLOR = Color3.Green();

colorMode

Color mode of the line. Applies to all line segments. The pixel color from the material shader will be modified with the value of color using the colorMode. The default mode is GreasedLineMeshColorMode.SET. This means it will set the color regardless of the color from the material shader. To be more precise, it sets the color to the exact value and doesn't care about the color information from the material (textures, lighting, ...).

You can choose from and the names are self-explanatory:

enum GreasedLineMeshColorMode {
COLOR_MODE_SET = 0,
COLOR_MODE_ADD = 1,
COLOR_MODE_MULTIPLY = 2,
}

Please note a difference: MATERIAL_TYPE_SIMPLE mixes the color and colors of the greased line material. MATERIAL_TYPE_STANDARD and MATERIAL_TYPE_PBR mix the color from the base material with the color or the colors of the greased line material.

Simple material in multiply color mode

colors and colorDistribution

An array of colors for the line segments. The maximum number of colors supported for one line instance depends on the maximum texture width your GPU can support (we use 1D textures here for maximum performance). The minimum for all WebGL systems is 4k. On most modern desktop GPUs it is 16k. Each color in the array represents a line segment color. There must be exactly the same number of colors in the array as there are line segments in the line.

The CreateGreasedLine function uses the function CompleteGreasedLineColorTable to fill the missing values, if any. You can use the colorDistribution option to set the method used to automatically fill the colors table.

You can choose from these values:

enum GreasedLineMeshColorDistribution {
COLOR_DISTRIBUTION_NONE = 0,
COLOR_DISTRIBUTION_REPEAT = 1,
COLOR_DISTRIBUTION_EVEN = 2,
COLOR_DISTRIBUTION_START = 3,
COLOR_DISTRIBUTION_END = 4,
COLOR_DISTRIBUTION_START_END = 5,
}

The default for this option is COLOR_MODE_START.

Let's see an example (you will end up with a half-red, half-white line).

import { Color3 } from "@babylonjs/core/Maths/math.color";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [0, 0, 0, 1, 0, 0, 2, 0, 0];
const colors = [Color3.Red()];
const line = CreateGreasedLine("line", { points }, { colors });

The colors are used only when the option useColors is set to true and you do not set the color option. There is one exception; see the documentation for the useColors option below.

The color blending of the colors depends on colorMode option.

Line colors

colorDistributionType

The method used to distribute the colors along the line. You can use segment distribution, where each segment uses one color from the color table. Or you can use line distribution, where the colors are distributed evenly along the line while ignoring the segments.

Color distribution type Line colors using your own texture

When running on WebGPU/WGSL you must use RGBA textures:

Line colors using your own texture - WebGPU/WGSL Animating line colors using your own texture Setting color pointers manually

colorsSampling

Sampling type of the colors texture. Defaults to NEAREST_NEAREST. The line segment will be distinctly colored. If you use for example LINEAR_LINEAR you'll get a smooth color gradient.

Colors sampling

useColors

If true, colors are used, otherwise they're ignored.

There is a scenario when you need to set useColors to true and set the color option as well. Look at the PG:

Adding differently colored lines to an instance

useDash

If true, dashing is used.

Dashing

dashCount

Number of dashes in the line. If you add more lines, all of them will use this dash count and they are not treated as one line.

dashRatio

Length of the dash. 0 to 1. 0.5 means half empty, half drawn.

dashOffset

Offset of the dashes along the line. 0 to 1. Normalized value.

visibility

Sets the line length visibility. Normalized value. 0 - 0% of the line will be visible. 1 - 100% of the line will be visible.

Visibility

resolution

Rendering resolution. There may be special occasions when you want to change the resolution. In most cases do not set this value.

cameraFacing

Whether to use camera facing for the line. Defaults to true. If set to true, you have to use the GreasedLineMesh class to create the mesh. If set to false, you have to use the GreasedLineRibbonMesh class. The builder function automatically takes care of this decision and sets this value to false if ribbonOptions is present in the GreasedLineBuilderMeshOptions.

GreasedLine materials

GreasedLine uses StandardMaterial, PBRMaterial, or ShaderMaterial (MATERIAL_TYPE_SIMPLE) as the base material for rendering. It also uses a GreasedLinePluginMaterial, which plugs into the base material and provides the additional features of GreasedLine.

If you want to alter the properties of the material, you need to use line.material, but if you want to change the GreasedLine-specific material properties, you need to do it on the line.greasedMaterial object. All three materials implement the IGreasedLineMaterial interface:

/**
* Interface which defines the available methods for a GreasedLineMaterial
*/
export interface IGreasedLineMaterial {
/**
* Normalized value of how much of the line will be visible
* 0 - 0% of the line will be visible
* 1 - 100% of the line will be visible
*/
visibility: number;
/**
* Line base width. At each point the line width is calculated by widths[pointIndex] * width
*/
width: number;
/**
* Turns on/off dash mode
*/
useDash: boolean;
/**
* @see GreasedLinePluginMaterial.setDashCount
* Number of dashes in the line.
* Defaults to 1.
*/
dashCount: number;
/**
* Dash offset
*/
dashOffset: number;
/**
* Length of the dash. 0 to 1. 0.5 means half empty, half drawn.
*/
dashRatio: number;
/**
* Whether to use the colors option to colorize the line
*/
useColors: boolean;
/**
* The mixing mode of the color paramater. Default value is GreasedLineMeshColorMode.SET. MATERIAL_TYPE_SIMPLE supports only the default value/mode.
* @see GreasedLineMeshColorMode
*/
colorMode: GreasedLineMeshColorMode;
/**
* Colors of the line segments.
* Defaults to empty.
*/
colors: Nullable<Color3[]>;
/**
* If false then width units = scene units. If true then line will width be reduced.
* Defaults to false.
*/
sizeAttenuation: boolean;
/**
* Color of the line. Applies to all line segments.
* Defaults to White.
* MATERIAL_TYPE_STANDARD and MATERIAL_TYPE_PBR material's shaders will get recompiled if there was no color set and you set a color or when there was a color set and you set it to null.
*/
color: Nullable<Color3>;
/**
* The method used to distribute the colors along the line.
* You can use segment distribution when each segment will use on color from the color table.
* Or you can use line distribution when the colors are distributed evenly along the line ignoring the segments.
*/
colorsDistributionType: GreasedLineMeshColorDistributionType;
/**
* Defaults to engine.getRenderWidth() and engine.getRenderHeight()
* Rendering resolution
*/
resolution: Vector2;
/**
* Allows to change the color without marking the material dirty.
* MATERIAL_TYPE_STANDARD and MATERIAL_TYPE_PBR material's shaders will get recompiled if there was no color set and you set a color or when there was a color set and you set it to null. Use the flag to not to recompile immediately.
* @param value the color
* @param doNotMarkDirty the flag
*/
setColor(value: Nullable<Color3>, doNotMarkDirty?: boolean): void;
/**
*
* @param colors colors array
* @param lazy if true the colors texture will not be updated
* @param forceNewTexture forces to create a new colors texture
*/
setColors(colors: Nullable<Color3[]>, lazy: boolean, forceNewTexture?: boolean): void;
/**
* Creates and sets the colors texture from the colors array which was created in lazy mode
*/
updateLazy(): void;
}

All other properties must be defined when creating the line.

As you can see in the comment of the color public property, the shader gets recompiled if there are specific changes of this property. A real life scenario: You might want to draw textured lines. On a specific event you want to colorize the texture. In this case create the line with color set to Color3.White() and set the colorMode to GreasedLineColorMode.COLOR_MODE_MULTIPLY. The result will be the same as not setting a color. However now you can change the color to for example rgb(0.5, 0.5, 0.5) to dim the texture colors without shader recompilation. This doesn't apply to MATERIAL_TYPE_SIMPLE because this material supports only GreasedLineColorMode.COLOR_MODE_SET so there will be no shader recompilation upon changes of the color property at all.

Materials can be shared between line instances. If you create a line and the other should have the same material options, then create the other line(s) by setting the createAndAssignMaterial option to false and simply set the material:

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points1 = [-1, 0, 0, 1, 0, 0];
const line1 = CreateGreasedLine("line1", { points: points1 });
const points2 = [-1, 1, 0, 1, 1, 0];
const line2 = CreateGreasedLine("line2", { points: points2 }, { createAndAssignMaterial: false });
line2.material = line1.material;

Examples

The best way to show the possibilities of GreasedLine is to go through the following examples.

Basic code snippets with StandardMaterial

Line with no material settings, default width, default color

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points });

Lines with no material settings, default width, default color

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [
[-1, 0, 0, 1, 0, 0],
[-1, 1, 0, 1, 1, 0],
];
const lines = CreateGreasedLine("lines", { points });

Line with a color specified

import { Color3 } from "@babylonjs/core/Maths/math.color";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points }, { color: Color3.Red() });

You can set the default color:

import { Color3 } from "@babylonjs/core/Maths/math.color";
GreasedLineMaterialDefaults.DEFAULT_COLOR = Color3.Red();

Please note that the color will be cloned so changing this value will not affect the existing lines.

Line with a width specified

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points }, { width: 0.5 });

Line with multiple colors

import { Color3 } from "@babylonjs/core/Maths/math.color";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const colors = [Color3.Red(), Color3.Yellow()];
const line = CreateGreasedLine("line", { points }, { useColors: true, colors });

Line with multiple widths

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, -0.5, 0, 0, 0, 0, 0, 0.5, 0, 0, 1, 0, 0];
const widths = [1, 1, 2, 2, 3, 3, 2, 2];
const line = CreateGreasedLine("line", { points, widths });

Instance mode

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points });
const points2 = [-1, 1, 0, 1, 1, 0];
CreateGreasedLine("line", { instance: line, points: points2 });

Lazy mode

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { lazy: true, points });
const points2 = [-1, 1, 0, 1, 1, 0];
CreateGreasedLine("line", { instance: line, lazy: true, points: points2 });
const points3 = [-1, -1, 0, 1, -1, 0];
CreateGreasedLine("line", { instance: line, lazy: true, points: points3 });
line.updateLazy();

Dashed line

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points }, { useDash: true, dashCount: 4, dashRatio: 0.5 });

Line visibility

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points }, { visibility: 0.5 });

Offsets

You can offset the vertices of the line. Keep in mind that there are 2 vertices per point and the line must be updatable. If your line disappears after calling this function, it means you haven't provided enough offsets. There is a function BABYLON.GreasedLineTools.GetPointsCountInfo(points: number[][]): { total: number; counts: number[] } that will tell you the exact counts. Just pass your line's points option to this function.

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points, updatable: true });
const offsets = [-0.3, -0.3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
line.offsets = offsets;
Offsetting line vertices Offsetting line segments Modifying points positions

Adding/setting points to an existing GreasedLine instance

You can add points to an existing GreasedLine instance. The width table is extended automatically to match the vertex count, and the new widths are set to 1. You have to replace these values manually after the points are added, if needed. You can do this by setting the values on the line.widths array.

The color table, if useColors is true, must be extended manually. Please pay attention to the code in the PG and the comments on how to correctly extend the color table.

The line must be created with the updatable: true option.

Have a look at the PG called Adding and setting points on an existing instance at the end of the page.

Line transformations

import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points });
line.position.x = 2;
line.rotation.z = Math.PI / 2;
line.scaling = new Vector3(2, 2, 2);

Drawing arcs

import { Curve3 } from "@babylonjs/core/Maths/math.path";
import { Vector3 } from "@babylonjs/core/Maths/math.vector";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const f = new Vector3(-0.5 + Math.random(), -0.5 + Math.random(), -0.5 + Math.random()).scale(20);
const s = new Vector3(-0.5 + Math.random(), -0.5 + Math.random(), -0.5 + Math.random()).scale(20);
const t = new Vector3(-0.5 + Math.random(), -0.5 + Math.random(), -0.5 + Math.random()).scale(20);
const arc = Curve3.ArcThru3Points(f, s, t);
const arcLine = CreateGreasedLine("arc", { points: arc.getPoints() });

Line with texture

import { GreasedLineMeshColorMode } from "@babylonjs/core/Materials/GreasedLine/greasedLineMaterialInterfaces";
import { Texture } from "@babylonjs/core/Materials/Textures/texture";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points1 = [-6, 0, 0, 6, 0, 0];
const line1 = CreateGreasedLine("line1", { points: points1 }, { width: 1, colorMode: GreasedLineMeshColorMode.COLOR_MODE_MULTIPLY });
const texture = new Texture("/textures/amiga.jpg", scene);
texture.uScale = 10;
line1.material.emissiveTexture = texture;

The default color is white and the default colorMode is BABYLON.GreasedLineMeshColorMode.COLOR_MODE_SET so you need to set colorMode to BABYLON.GreasedLineMeshColorMode.COLOR_MODE_MULTIPLY to render the texture visible or you can remove the color by setting its value to null if you don't want to do color blending at all. Setting the color from null to a value or setting from a value to null will recompile the shader.

import { Texture } from "@babylonjs/core/Materials/Textures/texture";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points1 = [-6, 0, 0, 6, 0, 0];
const line1 = CreateGreasedLine("line1", { points: points1 }, { width: 1 });
line1.greasedLineMaterial.color = null;
const texture = new Texture("/textures/amiga.jpg", scene);
texture.uScale = 10;
line1.material.emissiveTexture = texture;

Setting line color using its material

You have to set a colorMode option or set the color to null. Setting the color from null to a value or setting from a value to null will recompile the shader.

import { Color3 } from "@babylonjs/core/Maths/math.color";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points1 = [-6, 0, 0, 6, 0, 0];
const line1 = CreateGreasedLine("line1", { points: points1 }, { width: 1 });
line1.greasedLineMaterial.color = null;
line1.material.emissiveColor = Color3.Red();

Glowing line

You have to set a colorMode option or set the color to null. Setting the color from null to a value or setting from a value to null will recompile the shader.

import { GlowLayer } from "@babylonjs/core/Layers/glowLayer";
import { Color3 } from "@babylonjs/core/Maths/math.color";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points1 = [-6, 0, 0, 6, 0, 0];
const line1 = CreateGreasedLine("line1", { points: points1 }, { width: 1 });
line1.greasedLineMaterial.color = null;
line1.material.emissiveColor = Color3.Red();
const gl = new GlowLayer("glow", scene, {
blurKernelSize: 32,
});
gl.intensity = 1.8;
gl.referenceMeshToUseItsOwnMaterial(line1);

Line using PBRMaterial

All you have to do is set the materialType to BABYLON.GreasedLineMeshMaterialType.MATERIAL_TYPE_PBR and set the colorMode to BABYLON.GreasedLineMeshColorMode.COLOR_MODE_MULTIPLY. Do not set the color to null as it was the case with StandardMaterial unless you set the base color of the line another way, for example by setting a texture on PBRMaterial.

import { GreasedLineMeshColorMode, GreasedLineMeshMaterialType } from "@babylonjs/core/Materials/GreasedLine/greasedLineMaterialInterfaces";
import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
const points = [-1, 0, 0, 1, 0, 0];
const line = CreateGreasedLine("line", { points }, {
materialType: GreasedLineMeshMaterialType.MATERIAL_TYPE_PBR,
colorMode: GreasedLineMeshColorMode.COLOR_MODE_MULTIPLY,
});
const pbrMaterial = line.material;

Text using GreasedLine

You can draw text with Greased Line as well.

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
const fontData = await(await fetch("https://assets.babylonjs.com/fonts/Droid Sans_Regular.json")).json();
const points = GreasedLineTools.GetPointsFromText("BabylonJS", 16, // size
16, // resolution
fontData);
const textLines = CreateGreasedLine("textLines", { points });

Read more about the GetPointsFromText function below and check out the example PG.

GreasedLineTools

GreasedLineTools contains useful helper functions that will help you easily handle common tasks when using GreasedLine. Refer to the API for details.

Meshes to lines

You can easily draw a wireframe of a mesh like this:

import { CreateGreasedLine } from "@babylonjs/core/Meshes/Builders/greasedLineBuilder";
import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder";
import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
const sphere = MeshBuilder.CreateSphere("sphere", { segments: 32, diameter: 2 }, scene);
const sphereLines = CreateGreasedLine("sphereLines", { points: GreasedLineTools.MeshesToLines([sphere]) });

You can use a predicate as the second parameter of this function to modify the line points returned from this function. The predicate is called once for a face (once for every third index).

MeshesToLines with OmitDuplicatesPredicate
import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
predicate?: (
p1: Vector3,
p2: Vector3,
p3: Vector3,
indiceIndex: number,
vertexIndex: number,
mesh: AbstractMesh,
meshIndex: number,
vertices: FloatArray,
indices: IndicesArray
) => Vector3[]
const predicate = (p1, p2, p3, ix, vx) => {
if (vx % 4 === 0) {
return [p1, p2, p3, p1]
}
return false
}
const points = GreasedLineTools.MeshesToLines([sphere], predicate)

Convert number[] to Vector3[] and vice versa

You will often face situations where you need to convert your point coordinates, mainly when using GreasedLineTools functions. There are two helper functions for that:

import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
GreasedLineTools.ToVector3Array(points: number[])
GreasedLineTools.ToNumberArray(array: Vector3[])

Getting the count of points in your line instance

You will face certain tasks, such as creating color textures or offset buffers, and you will need to know how many points the line instance was created from. This is especially true if you use the functions below, which divide and segmentize your lines, because you can easily lose track of the exact counts. You get the total number of points and the number of points in each line in the line instance.

import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
GreasedLineTools.GetPointsCountInfo(points: number[][]): { total: number; counts: number[] }

is here to help.

Dividing a line to smaller segments

You may want to divide your line to smaller pieces (to segments) for example for assigning different colors to the segments or setting different width on the segment or manipulating the offset of that smaller segment.

import { GreasedLineTools } from "@babylonjs/core/Misc/greasedLineTools";
const pointsOriginal = GreasedLineTools.ToVector3Array([0, 0, 0, 1, 0, 0]);
const points = GreasedLineTools.SegmentizeLineBySegmentLength(pointsOriginal, 0.25);
const points2 = GreasedLineTools.SegmentizeLineBySegmentCount(pointsOriginal, 4);

The line will be divided into 4 pieces because the line length is 1 and we asked for 0.25-long segments when using the first function, or you can provide the number of segments using the second function. Check the playgrounds for real-life examples.

Finding the last visible position on the line when using the visibility option

The visibility option allows you to render only part of the line. You can use this option to reveal your line by incrementing its value. Remember, the value of this option must be normalized so it must be between 0 and 1. For example you may want to display a marker where the line ends. You can use the BABYLON.GreasedLineTools.GetPositionOnLineByVisibility(lineSegments: { point1: Vector3; point2: Vector3; length: number }[], lineLength: number, visbility: number, localSpace = false) function for this. Examine the example Playground how to deal with this function.

Getting points from text and a typeface.js font - the GetPointsFromText function

You can draw texts using GreasedLine. See the example code snippet above and the PG below.

GreasedLineTools.GetPointsFromText(text: string, size: number, resolution: number, fontData: IFontData, z = 0, includeInner = true): number[][]

The size is the height of the text in BabylonJS units. Keep the resolution as low as possible without losing details. Start at low values such as 4 and go up to 32-64 (or you can use 1 to get a cool low-resolution vector font). fontData is the same object you would use with BABYLON.MeshBuilder.CreateText. You can generate your typeface.js font here.

Other functions

There are other useful functions like getting points for drawing a circle/oval, an arc, drawing arrows, getting line length, etc. Check the source code, the API and/or the playgrounds.

As an overall rule, always cache your parameters when calling functions. These functions located in GreasedLineTools may be CPU-intensive, so avoid using them in the render loop, or cache as much as possible. For example, convert your number coordinates to Vector3 coordinates once and store the result. Get the line length only once and buffer the value, etc.

Picking and intersections

You can use the findAllIntersections(ray) function on a GreasedLineMesh object to find the intersections of the ray and the line. You can fine-tune the intersection sensitivity by altering the value of the public property intersectionTreshold.

Example playgrounds

Vertex colors Picking & intersection Adding and setting points on an existing instance Glowing lines Arrows Curves Drawing text GetPositionOnLineByVisibility tool function example Cloning Serialization and parsing Thin instances Using PBR material Using PBR material with a texture PBR sphere demo PBR sphere demo with a mesh to line predicate Mesh to 'opaque' lines example with PBR

Coming next

GreasedLineRibbon - a non-camera-facing version of GreasedLine
GreasedLineRibbon - a non-camera-facing version of GreasedLine
GreasedLineRibbon - a non-camera-facing version of GreasedLine
GreasedLine advanced examples
Advanced scenarios/ideas using GreasedLine
GreasedLine advanced examples