Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
96aeda6
feat(core): add GPU instancing auto-batching with UBO-based per-insta…
GuoLei1990 Apr 7, 2026
3279bb6
fix: static init order for _gpuInstanceMacro and prettier formatting
GuoLei1990 Apr 7, 2026
2318007
style: remove extra blank lines
GuoLei1990 Apr 7, 2026
94ef055
revert: restore original shader files, instancing UBO injection handl…
GuoLei1990 Apr 7, 2026
128b16e
fix: restore non-Layer shader improvements that were over-reverted
GuoLei1990 Apr 7, 2026
4d8f2b7
refactor: revert _getMacroCachePool rename back to _getShaderProgramPool
GuoLei1990 Apr 7, 2026
75a1ba2
feat(instancing): fix batch reuse bug and optimize ModelMat to affine…
GuoLei1990 Apr 7, 2026
9d015d6
feat(gpu-instancing): load ambient light and clone ducks for instancing
GuoLei1990 Apr 8, 2026
7b49335
fix(instancing): keep renderer_NormalMat as mat4 for shader compatibi…
GuoLei1990 Apr 8, 2026
73c19fa
refactor: rename batch to packer for consistency with InstanceDataPacker
GuoLei1990 Apr 8, 2026
4a55540
refactor: clarify _canBatch/_batch parameter semantics
GuoLei1990 Apr 8, 2026
9002cb4
refactor: move gpuInstanceMacro to InstanceDataPacker and cleanup
GuoLei1990 Apr 8, 2026
fdc380a
refactor: defer instancing layout computation to render phase
GuoLei1990 Apr 8, 2026
c40a679
refactor: replace InstanceDataPackerPool with single shared packer
GuoLei1990 Apr 8, 2026
b8935e3
refactor: move batcherManager declaration to first usage
GuoLei1990 Apr 8, 2026
002d7ab
refactor: rename InstanceDataPacker to InstanceBatch
GuoLei1990 Apr 8, 2026
f984867
refactor: rename MacroCachePool to MacroMap
GuoLei1990 Apr 8, 2026
1fc3f4f
refactor: rename shaderProgramPool(s) variables to shaderProgramMap(s)
GuoLei1990 Apr 8, 2026
53a9a9f
refactor: simplify bindUniformBufferBase - remove unnecessary null check
GuoLei1990 Apr 8, 2026
c63b83b
refactor: simplify InstanceBatch - store layout directly, rename fields
GuoLei1990 Apr 11, 2026
b9f4168
refactor: clean up InstanceBatch upload method
GuoLei1990 Apr 11, 2026
8c704a7
refactor: clean up RenderQueue instancing render loop
GuoLei1990 Apr 11, 2026
d75acb7
style: fix prettier formatting in RenderQueue
GuoLei1990 Apr 11, 2026
82c0d60
chore: upgrade lint-staged to v16 and fix glob pattern
GuoLei1990 Apr 11, 2026
baeaa3d
chore: upgrade eslint and @typescript-eslint to support TS 5.6
GuoLei1990 Apr 11, 2026
99ec5d1
refactor: null out instancedRenderers in dispose
GuoLei1990 Apr 11, 2026
fd747eb
refactor: store InstanceLayout on ShaderProgram during compilation
GuoLei1990 Apr 11, 2026
910b8cc
refactor: inline _buildMacroMap into _compileShaderLabSource
GuoLei1990 Apr 11, 2026
891d2c2
refactor: rename isGpuInstance to isGPUInstance
GuoLei1990 Apr 11, 2026
5d02bbe
refactor: inline _compilePlatformSource into _getCanonicalShaderProgram
GuoLei1990 Apr 11, 2026
6a01018
refactor: rename _getCanonicalShaderProgram to _compileShaderProgram
GuoLei1990 Apr 11, 2026
967fc6b
refactor: move bindUniformBlocks next to other public methods
GuoLei1990 Apr 11, 2026
b420f61
refactor: remove empty SubShader._destroy
GuoLei1990 Apr 11, 2026
1d84610
refactor: inline single-use subShader variable
GuoLei1990 Apr 11, 2026
a850200
refactor: remove unused GLSLIfdefResolver
GuoLei1990 Apr 11, 2026
34d5570
refactor: move InstanceFieldInfo and InstanceLayout after ShaderFacto…
GuoLei1990 Apr 11, 2026
a629292
refactor: remove default value from isGPUInstance parameter
GuoLei1990 Apr 11, 2026
f7ad877
refactor: reorder ShaderFactory - group static fields before methods
GuoLei1990 Apr 11, 2026
76b23a0
refactor: clean up ShaderFactory naming and visibility
GuoLei1990 Apr 11, 2026
9a82af5
refactor: optimize ShaderFactory - merge pack functions, extract cons…
GuoLei1990 Apr 11, 2026
4f76b6b
refactor: replace mat4_affine with mat3x4, clean up ShaderFactory det…
GuoLei1990 Apr 11, 2026
1052411
refactor: simplify UBO injection and skip UBO members in uniform refl…
GuoLei1990 Apr 11, 2026
7ba4137
refactor: extract InstancePackFunc type alias
GuoLei1990 Apr 11, 2026
f06aa39
fix: update test references from _getCanonicalShaderProgram to _compi…
GuoLei1990 Apr 11, 2026
c1195f8
Merge remote-tracking branch 'origin/dev/2.0' into feat/gpu-instancing
GuoLei1990 Apr 11, 2026
3c58dd8
fix: resolve shader compile errors and add missing matrix uniform types
GuoLei1990 Apr 11, 2026
74cbb0e
feat: add GPU instancing e2e tests and complete matrix uniform support
GuoLei1990 Apr 11, 2026
6ab1b9c
feat: convert GPU instancing examples to animated benchmarks with Stats
GuoLei1990 Apr 11, 2026
86f3e5b
refactor: sort opaque objects by material/primitive instead of distance
GuoLei1990 Apr 11, 2026
ec70753
refactor: unroll mat3x4 pack loop and precompute field offset
GuoLei1990 Apr 11, 2026
38239ed
test: update e2e baseline images for opaque sorting change
GuoLei1990 Apr 11, 2026
1566c69
test: adjust e2e diff threshold for gpu-instancing-auto-batch
GuoLei1990 Apr 11, 2026
0c0373d
refactor: update auto-batch example with Avocado model and 5000 insta…
GuoLei1990 Apr 12, 2026
9533e2e
refactor: rename MacroMap to ShaderProgramMap and remove generic abst…
GuoLei1990 Apr 12, 2026
d58aaa3
feat: add macro collection equality check to _canBatch
GuoLei1990 Apr 12, 2026
761bec4
refactor: remove unused renderer_LocalMat and renderer_MVInvMat
GuoLei1990 Apr 12, 2026
91e2ce2
refactor: make ShaderProgramMap constructor engine param required
GuoLei1990 Apr 12, 2026
ee3aa61
refactor: detect array uniforms in instancing and use Record for buil…
GuoLei1990 Apr 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ gl_FragColor = vec4(lighting, 1.0);

The engine provides a rich set of built-in variables that can be used directly, such as transformation matrix variables:
```glsl
mat4 renderer_LocalMat; // Local transformation matrix
mat4 renderer_ModelMat; // Model matrix
mat4 renderer_MVMat; // Model-view matrix
mat4 renderer_MVPMat; // MVP matrix
Expand Down
1 change: 0 additions & 1 deletion docs/en/graphics/material/shaderAPI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ vec4 fog(vec4 color, vec3 positionVS);
Provides system variables for model space, view space, world space, and camera coordinates:

```glsl
mat4 renderer_LocalMat;
mat4 renderer_ModelMat;
mat4 camera_ViewMat;
mat4 camera_ProjMat;
Expand Down
1 change: 0 additions & 1 deletion docs/en/graphics/material/variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ Below are the engine's built-in variables for reference when writing Shaders:

| Name | Type | Description |
| :---------------- | :--- | :--------------------------- |
| renderer_LocalMat | mat4 | Model local coordinate matrix |
| renderer_ModelMat | mat4 | Model world coordinate matrix |
| renderer_MVMat | mat4 | Model view matrix |
| renderer_MVPMat | mat4 | Model view projection matrix |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ void frag() {

引擎提供了丰富的内置变量,直接声明使用即可,比如变换矩阵相关变量:
```glsl
mat4 renderer_LocalMat; // 本地变换矩阵
mat4 renderer_ModelMat; // 模型矩阵
mat4 renderer_MVMat; // 模型视图矩阵
mat4 renderer_MVPMat; // MVP矩阵
Expand Down
1 change: 0 additions & 1 deletion docs/zh/graphics/material/shaderAPI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ vec4 fog(vec4 color, vec3 positionVS);
提供了模型空间、视图空间、世界空间、相机坐标等[系统变量](/docs/graphics/material/variables/):

```glsl
mat4 renderer_LocalMat;
mat4 renderer_ModelMat;
mat4 camera_ViewMat;
mat4 camera_ProjMat;
Expand Down
1 change: 0 additions & 1 deletion docs/zh/graphics/material/variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ Shader 代码中会经常用到内置变量,一种是**逐顶点**的 `attribu

| 名字 | 类型 | 解释 |
| :----------------- | :--- | ------------------ |
| renderer_LocalMat | mat4 | 模型本地坐标系矩阵 |
| renderer_ModelMat | mat4 | 模型世界坐标系矩阵 |
| renderer_MVMat | mat4 | 模型视口矩阵 |
| renderer_MVPMat | mat4 | 模型视口投影矩阵 |
Expand Down
68 changes: 68 additions & 0 deletions e2e/case/gpu-instancing-auto-batch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @title GPU Instancing Auto Batch
* @category Mesh
*/
import {
AmbientLight,
AssetType,
Camera,
Color,
DirectLight,
GLTFResource,
Logger,
Vector3,
WebGLEngine
} from "@galacean/engine";
import { initScreenshot, updateForE2E } from "./.mockForE2E";

Logger.enable();
WebGLEngine.create({ canvas: "canvas" }).then(async (engine) => {
engine.canvas.resizeByClientSize(2);

const scene = engine.sceneManager.activeScene;
const rootEntity = scene.createRootEntity("Root");

// Camera
const cameraEntity = rootEntity.createChild("Camera");
cameraEntity.transform.setPosition(0, 10, 80);
cameraEntity.transform.lookAt(new Vector3(0, 0, 0));
const camera = cameraEntity.addComponent(Camera);
camera.farClipPlane = 300;

// Light
const lightEntity = rootEntity.createChild("Light");
lightEntity.transform.setRotation(-45, -45, 0);
lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1);

// Load Duck model and ambient light
const [glTF, ambientLight] = await Promise.all([
engine.resourceManager.load<GLTFResource>({
url: "https://gw.alipayobjects.com/os/bmw-prod/6cb8f543-285c-491a-8cfd-57a1160dc9ab.glb",
type: AssetType.GLTF
}),
engine.resourceManager.load<AmbientLight>({
url: "https://mdn.alipayobjects.com/oasis_be/afts/file/A*eRJ8QKzf5zAAAAAAgBAAAAgAekp5AQ/ambient.ambLight",
type: AssetType.AmbientLight
})
]);
scene.ambientLight = ambientLight;

// Clone ducks with fixed seed positions for deterministic output
const count = 500;
const spread = 50;
for (let i = 0; i < count; i++) {
const duck = glTF.instantiateSceneRoot();
// Use deterministic positions based on index
const t = i / count;
duck.transform.setPosition(
Math.sin(t * 137.5) * spread * 0.5,
Math.cos(t * 97.3) * spread * 0.5,
Math.sin(t * 59.1) * spread * 0.5
);
duck.transform.setRotation(t * 360, t * 720, t * 1080);
rootEntity.addChild(duck);
}

updateForE2E(engine);
initScreenshot(engine, camera);
});
100 changes: 100 additions & 0 deletions e2e/case/gpu-instancing-custom-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/**
* @title GPU Instancing Custom Data
* @category Mesh
*/
import {
Camera,
Color,
DirectLight,
Logger,
Material,
MeshRenderer,
PrimitiveMesh,
Shader,
ShaderProperty,
Vector3,
Vector4,
WebGLEngine
} from "@galacean/engine";
import { initScreenshot, updateForE2E } from "./.mockForE2E";

Logger.enable();

// Custom shader: uses renderer_CustomColor (per-instance) for fragment output
Shader.create(
"CustomInstanceShader",
`
#include <transform_declare>
attribute vec3 POSITION;
attribute vec3 NORMAL;

varying vec3 v_normal;

void main() {
gl_Position = renderer_MVPMat * vec4(POSITION, 1.0);
v_normal = normalize((renderer_NormalMat * vec4(NORMAL, 0.0)).xyz);
}
`,
`
uniform vec4 renderer_CustomColor;

varying vec3 v_normal;

void main() {
vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0));
float NdotL = max(dot(v_normal, lightDir), 0.2);
gl_FragColor = vec4(renderer_CustomColor.rgb * NdotL, 1.0);
}
`
);

WebGLEngine.create({ canvas: "canvas" }).then((engine) => {
engine.canvas.resizeByClientSize(2);

const scene = engine.sceneManager.activeScene;
const rootEntity = scene.createRootEntity("Root");

// Camera
const cameraEntity = rootEntity.createChild("Camera");
cameraEntity.transform.setPosition(0, 10, 80);
cameraEntity.transform.lookAt(new Vector3(0, 0, 0));
const camera = cameraEntity.addComponent(Camera);
camera.farClipPlane = 300;

// Light
const lightEntity = rootEntity.createChild("Light");
lightEntity.transform.setRotation(-45, -45, 0);
lightEntity.addComponent(DirectLight).color = new Color(1, 1, 1, 1);

// Shared mesh and material
const mesh = PrimitiveMesh.createCuboid(engine, 1, 1, 1);
const material = new Material(engine, Shader.find("CustomInstanceShader"));
const customColorProperty = ShaderProperty.getByName("renderer_CustomColor");

// Create cubes with deterministic positions and colors
const count = 500;
const spread = 50;
for (let i = 0; i < count; i++) {
const entity = rootEntity.createChild("Cube" + i);
const t = i / count;
entity.transform.setPosition(
Math.sin(t * 137.5) * spread * 0.5,
Math.cos(t * 97.3) * spread * 0.5,
Math.sin(t * 59.1) * spread * 0.5
);
entity.transform.setRotation(t * 360, t * 720, t * 1080);

const renderer = entity.addComponent(MeshRenderer);
renderer.mesh = mesh;
renderer.setMaterial(material);

// Deterministic colors based on index
renderer.shaderData.setVector4(
customColorProperty,
new Vector4(Math.sin(t * 6.28) * 0.5 + 0.5, Math.cos(t * 4.71) * 0.5 + 0.5, Math.sin(t * 3.14) * 0.5 + 0.5, 1.0)
);
}

updateForE2E(engine);
initScreenshot(engine, camera);
});
16 changes: 15 additions & 1 deletion e2e/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export const E2E_CONFIG = {
category: "Material",
caseFileName: "material-pbr",
threshold: 0,
diffPercentage: 0.0080
diffPercentage: 0.008
},
shaderLab: {
category: "Material",
Expand Down Expand Up @@ -464,6 +464,20 @@ export const E2E_CONFIG = {
diffPercentage: 0.03
}
},
GPUInstancing: {
autoBatch: {
category: "GPUInstancing",
caseFileName: "gpu-instancing-auto-batch",
threshold: 0,
diffPercentage: 0.00126
},
customData: {
category: "GPUInstancing",
caseFileName: "gpu-instancing-custom-data",
threshold: 0,
diffPercentage: 0
}
},
SpriteMask: {
CustomStencil: {
category: "SpriteMask",
Expand Down
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Animator_animator-crossfade.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Animator_animator-play.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Camera_camera-opaque-texture.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Physics_physx-collision.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Physics_physx-customUrl.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions e2e/fixtures/originImage/Physics_physx-mesh-collider-data.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@galacean/engine-shader": "workspace:*",
"@galacean/engine-shaderlab": "workspace:*",
"@galacean/engine-toolkit": "latest",
"@galacean/engine-toolkit-stats": "latest",
"@galacean/engine-ui": "workspace:*"
},
"devDependencies": {
Expand Down
Loading
Loading