diff --git a/src/mol-gl/shader/chunks/common-vert-params.glsl b/src/mol-gl/shader/chunks/common-vert-params.glsl index 390f0f1c6b22288090a448f1512bf27e95f650c6..b20c57468507aeee7240689513961782a986bee6 100644 --- a/src/mol-gl/shader/chunks/common-vert-params.glsl +++ b/src/mol-gl/shader/chunks/common-vert-params.glsl @@ -1,6 +1,12 @@ uniform mat4 uProjection, uModel, uView; uniform vec3 uCameraPosition; +uniform Common { + mat4 uProjection; + int uObjectId; + int uInstanceCount; +} uboCommon; + uniform int uObjectId; uniform int uInstanceCount; uniform int uGroupCount; diff --git a/src/mol-gl/webgl/buffer.ts b/src/mol-gl/webgl/buffer.ts index 18aebb998a9014ccc32516dbe55801535f7c5393..183adacbda3e31eaeb122b440d82bd51f8d39bf9 100644 --- a/src/mol-gl/webgl/buffer.ts +++ b/src/mol-gl/webgl/buffer.ts @@ -76,6 +76,7 @@ export function getBufferType(ctx: WebGLContext, bufferType: BufferType) { switch (bufferType) { case 'attribute': return gl.ARRAY_BUFFER case 'elements': return gl.ELEMENT_ARRAY_BUFFER + case 'uniform': return (gl as WebGL2RenderingContext).UNIFORM_BUFFER } } @@ -214,4 +215,33 @@ export function createElementsBuffer(ctx: WebGLContext, array: ElementsType, usa gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, _buffer); } } -} \ No newline at end of file +} + +// + +export type UniformType = Float32Array +export type UniformKind = 'float32' + +// export type AttributeDefs = { +// [k: string]: { kind: ArrayKind, itemSize: BufferItemSize, divisor: number } +// } +// export type AttributeValues = { [k: string]: ValueCell<ArrayType> } +export type UniformBuffers = { [k: string]: UniformBuffer } + +export interface UniformBuffer extends Buffer { + bind: (location: number) => void +} + +export function createUniformBuffer(ctx: WebGLContext, array: UniformType, usageHint: UsageHint = 'dynamic'): UniformBuffer { + const gl = ctx.gl as WebGL2RenderingContext + const buffer = createBuffer(ctx, array, usageHint, 'uniform') + const { _buffer } = buffer + + return { + ...buffer, + bind: (location: number) => { + gl.bindBuffer(gl.UNIFORM_BUFFER, _buffer) + gl.bindBufferBase(gl.UNIFORM_BUFFER, location, _buffer) + } + } +} diff --git a/src/mol-gl/webgl/program.ts b/src/mol-gl/webgl/program.ts index 6cc476d5056cc0f0c76cd7de7c682cb362af0884..585ed8874a923ea2fdb25a7802b0b9f33a262010 100644 --- a/src/mol-gl/webgl/program.ts +++ b/src/mol-gl/webgl/program.ts @@ -7,7 +7,7 @@ import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code' import { WebGLContext } from './context'; import { UniformValues, getUniformSetters } from './uniform'; -import { AttributeBuffers } from './buffer'; +import { AttributeBuffers, UniformBuffers, createUniformBuffer } from './buffer'; import { Textures, TextureId } from './texture'; import { createReferenceCache, ReferenceCache } from 'mol-util/reference-cache'; import { idFactory } from 'mol-util/id-factory'; @@ -21,6 +21,8 @@ export interface Program { use: () => void setUniforms: (uniformValues: UniformValues) => void + setUniformBuffers: (uniformBuffers: UniformBuffers, uniformValues: UniformValues) => void + bindUniformBuffers: (/* uniformBuffers: UniformBuffers */) => void bindAttributes: (attribueBuffers: AttributeBuffers) => void bindTextures: (textures: Textures) => void @@ -77,6 +79,32 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program { const locations = getLocations(ctx, program, schema) const uniformSetters = getUniformSetters(schema) + interface UniformBufferInfo { + blockIndex: number, + blockSize: number, + uniformIndices: number[], + uniformOffsets: number[] + } + function getUniformBufferInfo(gl: WebGL2RenderingContext, program: WebGLProgram, name: string, uniformNames: string[]): UniformBufferInfo { + const blockIndex = gl.getUniformBlockIndex(program, name) + const blockSize = gl.getActiveUniformBlockParameter(program, blockIndex, gl.UNIFORM_BLOCK_DATA_SIZE) + const uniformIndices = gl.getUniformIndices(program, uniformNames) + if (uniformIndices === null) throw new Error(`Could not get uniform indices`) + const uniformOffsets = gl.getActiveUniforms(program, uniformIndices, gl.UNIFORM_OFFSET) + return { blockIndex, blockSize, uniformIndices, uniformOffsets } + } + + const uniformBufferInfos: { [k: string]: UniformBufferInfo } = { + 'Common': getUniformBufferInfo(gl as WebGL2RenderingContext, program, 'Common', [ + 'Common.uProjection', 'Common.uObjectId', 'Common.uInstanceCount' + ]) + } + console.log(uniformBufferInfos) + + const uniformBuffers: UniformBuffers = { + 'Common': createUniformBuffer(ctx, new Float32Array(uniformBufferInfos['Common'].blockSize)) + } + let destroyed = false return { @@ -96,6 +124,23 @@ export function createProgram(ctx: WebGLContext, props: ProgramProps): Program { if (v) uniformSetters[k](gl, l, v.ref.value) } }, + setUniformBuffers: (uniformBuffers: UniformBuffers, uniformValues: UniformValues) => { + const uniformBufferKeys = Object.keys(uniformBuffers) + for (let i = 0, il = uniformBufferKeys.length; i < il; ++i) { + // const k = uniformBufferKeys[i] + // const info = uniformBufferInfos[k] + // uniformBuffers[k].updateData() + } + }, + bindUniformBuffers: (/* uniformBuffers: UniformBuffers */) => { + const uniformBufferKeys = Object.keys(uniformBuffers) + for (let i = 0, il = uniformBufferKeys.length; i < il; ++i) { + const k = uniformBufferKeys[i] + const info = uniformBufferInfos[k] + uniformBuffers[k].bind(i) + ;(gl as WebGL2RenderingContext).uniformBlockBinding(program, info.blockIndex, i) + } + }, bindAttributes: (attribueBuffers: AttributeBuffers) => { const attributeKeys = Object.keys(attribueBuffers) for (let i = 0, il = attributeKeys.length; i < il; ++i) { diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index fad8f866e25789f402f9a8ef880d0d6fbeb0441a..6e522bd1b3f254b92ed5cdb361e9321989509a8d 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -139,6 +139,7 @@ export function createRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCo const program = programs[variant].value const vertexArray = vertexArrays[variant] program.setUniforms(uniformValues) + program.bindUniformBuffers() if (vertexArrayObject && vertexArray) { vertexArrayObject.bindVertexArray(vertexArray) // need to bind elements buffer explicitly since it is not always recorded in the VAO diff --git a/src/mol-gl/webgl/uniform.ts b/src/mol-gl/webgl/uniform.ts index a979a64fee9228f01f052d39aa94f067a2289807..2a416c57875fc947f9b66eb18d07c4ad52a7b44c 100644 --- a/src/mol-gl/webgl/uniform.ts +++ b/src/mol-gl/webgl/uniform.ts @@ -8,6 +8,7 @@ import { Mat3, Mat4, Vec2, Vec3, Vec4 } from 'mol-math/linear-algebra' import { ValueCell } from 'mol-util'; import { GLRenderingContext } from './compat'; import { RenderableSchema } from 'mol-gl/renderable/schema'; +import { WebGLContext } from './context'; export type UniformKindValue = { 'f': number @@ -72,4 +73,18 @@ export function getUniformSetters(schema: RenderableSchema) { } }) return setters +} + +// + +export interface UniformBlock { + update(): void + bind(): void +} + +export function createUniformBlock(ctx: WebGLContext, ) { + + return { + + } } \ No newline at end of file