diff --git a/docs/api-reference/engine/model.md b/docs/api-reference/engine/model.md index b242381075..c101df9993 100644 --- a/docs/api-reference/engine/model.md +++ b/docs/api-reference/engine/model.md @@ -1,7 +1,8 @@ # Model -The `Model` class is the centerpiece of the luma.gl API. It brings together all the different functionality needed to run shaders and perform draw calls in a single, easy-to-use interface. +The `Model` class is the centerpiece of the luma.gl API. It brings together all GPU functionality needed to run shaders and perform draw calls, in a single, easy-to-use interface. +`Model` manages the following responsibilities: - **render pipeline creation** - - **attributes** - **bindings** these can reference textures and uniform buffers @@ -10,9 +11,9 @@ The `Model` class is the centerpiece of the luma.gl API. It brings together all - **shader transpilation**** - **debugging** - Detailed debug logging of draw calls -The `Model` class integrates with the `@luma.gl/shadertools` shader module system: [see `Shader Assembly`]( /docs/api-reference/shadertools/shader-assembler). - - (Accepts a [`Mesh`] or a [`Geometry`](/docs/- - api-reference/engine/geometry) instance, plus any additional attributes for instanced rendering) +The `Model` class integrates with +- The `@luma.gl/shadertools` shader module system: [see `Shader Assembly`]( /docs/api-reference/shadertools/shader-assembler). +- The `Geometry` classes - accepts a [`Mesh`] or a [`Geometry`](/docs/modules/engine/api-reference/geometry) instance, plus any additional attributes for instanced rendering) ## Usage @@ -36,6 +37,7 @@ const model = new Model(device, { }, }) ``` + ### Provide attribute data using Buffer When using `Buffer` objects, data remains on GPU and same `Buffer` object can be shared between multiple models. @@ -77,19 +79,21 @@ const model = new Model(device, { ## Types -### ModelProps +### `ModelProps` -| Property | Type | Description | -| ------------------ | ---------------------------------------------- | ----------------------------------------------------------------------------------- | -| `vs` | `Shader` \| _string_ | A vertex shader object, or source as a string. | -| `fs` | `Shader` \| _string_ | A fragment shader object, or source as a string. | -| `modules` | | shader modules to be applied (shadertools). | -| `pipelineFactory?` | | `PipelineFactory` to use for program creation and caching. | -| `varyings?` | `string[]` | WebGL 2: Array of vertex shader output variables (used in TransformFeedback flow). | -| `bufferMode` | | WebGL 2: Mode for recording vertex shader outputs (used in TransformFeedback flow). | -| `debugShaders?` | `'error' \| 'never' \| 'warnings' \| 'always'` | Specify in what triggers the display shader compilation log (default: `'error'`). | +| Property | Type | Description | +| ------------------ | ---------------------------------------------- | --------------------------------------------------------------------------------- | +| `vs` | `Shader` \| _string_ | A vertex shader object, or source as a string. | +| `fs` | `Shader` \| _string_ | A fragment shader object, or source as a string. | +| `modules` | | shader modules to be applied (shadertools). | +| `pipelineFactory?` | | `PipelineFactory` to use for program creation and caching. | +| `debugShaders?` | `'error' \| 'never' \| 'warnings' \| 'always'` | Specify in what triggers the display shader compilation log (default: `'error'`). | +| `onBeforeRender?` | `Function` | function to be called before every time this model is drawn. | +| `onAfterRender?` | `Function` | function to be called after every time this model is drawn. | +| `varyings?` | `string[]` | WebGL: Array of vertex shader output variables (used in TransformFeedback flow). | +| `bufferMode?` | | WebGL: Mode for recording vertex shader outputs (used in TransformFeedback flow). | -`ModelProps` passes through `RenderPipelineProps` +`ModelProps` also include `RenderPipelineProps`, which are passed through to the `RenderPipeline` constructor, e.g: | Property | Type | Description | | ----------------- | -------------------------- | --------------------------------------------------------------------------------------- | @@ -103,19 +107,12 @@ const model = new Model(device, { | `bindings?` | `Record` | | | `buffers?` | `Record` | | -## Properties - -### renderPipeline: RenderPipeline - -Get model's `RenderPipeline` instance - -### onBeforeRender -function to be called before every time this model is drawn. +## Fields -### onAfterRender +### `renderPipeline: RenderPipeline` -function to be called after every time this model is drawn. +The model's `RenderPipeline` instance ### instanceCount: number @@ -127,15 +124,15 @@ when not provided will be deduced from `geometry` object. ## Methods -### constructor(device: Device, props: ModelProps) +### `constructor(device: Device, props: ModelProps)` The constructor for the Model class. Use this to create a new Model. -### destroy(): void +### `destroy(): void` Free GPU resources associated with this model immediately, instead of waiting for garbage collection. -### draw(options: DrawOptions): boolean +### `draw(options: DrawOptions): boolean` Renders the model with provided uniforms, attributes and samplers @@ -169,31 +166,27 @@ The remaining draw options are passed directly to `Program.draw()`: - `transformFeedback` - an instance `TranformFeedback` object, that gets activated for this rendering. - `vertexArray` - an instance of `VertexArray` object, that holds required buffer bindings for vertex shader inputs. - -### setVertexCount(); this +### `setVertexCount(): void` Sets the number of vertices -### setInstanceCount(); this +### `setInstanceCount(); void` How many instances will be rendered -### setGeometry(); this +### `setGeometry(); void` Use a `Geometry` instance to define attribute buffers -### setAttributes(attributes: object); this - -Sets map of attributes (passes through to [VertexArray.setAttributes](/docs/api-reference/core/resources/vertex-array)) - -### setUniforms(uniforms: object): void - -Stores named uniforms key, value +### `setAttributes(attributes: object, options?): void` +Sets map of attributes (via [VertexArray.setAttributes](/docs/api-reference/core/resources/vertex-array)) -### updateModuleSettings(moduleSettings: object): void +- `attributes` (Object) - map of attribute names to values. +- `options.ignoreMissingAttributes` (boolean) - if `true`, allows the function to silently ignore missing attributes. +### `setUniforms(uniforms: object): void` (Deprecated) -## Remarks +Global uniforms key, value. Only works on WebGL, for portable code, use uniform buffers and `model.setBindings()` instead. -- The `Model` class is arguably the most useful class for typical applications. It manages the WebGL resources needed to perform draw calls and provide additional functionality as described below. +### `updateModuleSettings(moduleSettings: object): void` (Deprecated) diff --git a/modules/engine/src/model/model.ts b/modules/engine/src/model/model.ts index 52056e3865..56f1de6946 100644 --- a/modules/engine/src/model/model.ts +++ b/modules/engine/src/model/model.ts @@ -57,6 +57,8 @@ export type ModelProps = Omit & { attributes?: Record; /** */ constantAttributes?: Record; + /** Some applications intentionally supply unused attributes */ + ignoreUnknownAttributes?: boolean; /** @internal For use with {@link TransformFeedback}, WebGL only. */ varyings?: string[]; @@ -102,7 +104,8 @@ export class Model { transformFeedback: undefined, shaderAssembler: ShaderAssembler.getDefaultShaderAssembler(), - debugShaders: undefined + debugShaders: undefined, + ignoreUnknownAttributes: undefined }; readonly device: Device; @@ -256,7 +259,7 @@ export class Model { this.setIndexBuffer(props.indexBuffer); } if (props.attributes) { - this.setAttributes(props.attributes); + this.setAttributes(props.attributes, {ignoreUnknownAttributes: props.ignoreUnknownAttributes}); } if (props.constantAttributes) { this.setConstantAttributes(props.constantAttributes); @@ -364,8 +367,8 @@ export class Model { // TODO - delete previous geometry? this.vertexCount = gpuGeometry.vertexCount; this.setIndexBuffer(gpuGeometry.indices); - this.setAttributes(gpuGeometry.attributes, 'ignore-unknown'); - this.setAttributes(attributes); + this.setAttributes(gpuGeometry.attributes, {ignoreUnknownAttributes: true}); + this.setAttributes(attributes, {ignoreUnknownAttributes: this.props.ignoreUnknownAttributes}); } /** @@ -514,7 +517,7 @@ export class Model { * Sets attributes (buffers) * @note Overrides any attributes previously set with the same name */ - setAttributes(buffers: Record, _option?: 'ignore-unknown'): void { + setAttributes(buffers: Record, options?: {ignoreUnknownAttributes?: boolean}): void { if (buffers.indices) { log.warn( `Model:${this.id} setAttributes() - indexBuffer should be set using setIndexBuffer()` @@ -539,7 +542,7 @@ export class Model { set = true; } } - if (!set && _option !== 'ignore-unknown') { + if (!set && (options?.ignoreUnknownAttributes || this.props.ignoreUnknownAttributes)) { log.warn( `Model(${this.id}): Ignoring buffer "${buffer.id}" for unknown attribute "${bufferName}"` )(); diff --git a/modules/webgl/test/context/state-tracker/data/sample-enum-settings.ts b/modules/webgl/test/context/state-tracker/data/sample-enum-settings.ts index 26ea94ab17..fc0b4a0830 100644 --- a/modules/webgl/test/context/state-tracker/data/sample-enum-settings.ts +++ b/modules/webgl/test/context/state-tracker/data/sample-enum-settings.ts @@ -133,7 +133,7 @@ export const ENUM_STYLE_SETTINGS_SET2: GLParameters = { // [GL.FRAGMENT_SHADER_DERIVATIVE_HINT]: GL.NICEST, // [GL.RASTERIZER_DISCARD]: false, - // WEBGL1 PIXEL PACK/UNPACK MODES + // PIXEL PACK/UNPACK MODES [GL.PACK_ALIGNMENT]: 2, [GL.UNPACK_ALIGNMENT]: 2, [GL.UNPACK_FLIP_Y_WEBGL]: false, diff --git a/modules/webgpu/src/adapter/resources/webgpu-render-pipeline.ts b/modules/webgpu/src/adapter/resources/webgpu-render-pipeline.ts index 34906b5615..ead30db806 100644 --- a/modules/webgpu/src/adapter/resources/webgpu-render-pipeline.ts +++ b/modules/webgpu/src/adapter/resources/webgpu-render-pipeline.ts @@ -62,26 +62,24 @@ export class WebGPURenderPipeline extends RenderPipeline { // this._indexBuffer = cast(indexBuffer); // } - /* - setAttributes(attributes: Record): void { - for (const [name, buffer] of Object.entries(attributes)) { - const bufferIndex = this._bufferSlots[name]; - if (bufferIndex >= 0) { - this._buffers[bufferIndex] = buffer; - } else { - throw new Error( - `Setting attribute '${name}' not listed in shader layout for program ${this.id}` - ); - } - } - // for (let i = 0; i < this._bufferSlots.length; ++i) { - // const bufferName = this._bufferSlots[i]; - // if (attributes[bufferName]) { - // this.handle - // } - // } - } - */ + // setAttributes(attributes: Record): void { + // for (const [name, buffer] of Object.entries(attributes)) { + // const bufferIndex = this._bufferSlots[name]; + // if (bufferIndex >= 0) { + // this._buffers[bufferIndex] = buffer; + // } else { + // throw new Error( + // `Setting attribute '${name}' not listed in shader layout for program ${this.id}` + // ); + // } + // } + // // for (let i = 0; i < this._bufferSlots.length; ++i) { + // // const bufferName = this._bufferSlots[i]; + // // if (attributes[bufferName]) { + // // this.handle + // // } + // // } + // } setBindings(bindings: Record): void { // if (isObjectEmpty(bindings)) {