diff --git a/src/mol-gl/compute/histogram-pyramid/reduction.ts b/src/mol-gl/compute/histogram-pyramid/reduction.ts
index 7e00a876a4fade1cf2e5ac3d3cde33d733531058..2705e28666ac875b94aeba1b4fa002428d2bea8c 100644
--- a/src/mol-gl/compute/histogram-pyramid/reduction.ts
+++ b/src/mol-gl/compute/histogram-pyramid/reduction.ts
@@ -11,7 +11,6 @@ import { Values, TextureSpec, UniformSpec } from '../../renderable/schema';
 import { Texture, createTexture } from 'mol-gl/webgl/texture';
 import { ShaderCode } from 'mol-gl/shader-code';
 import { ValueCell } from 'mol-util';
-import { GLRenderingContext } from 'mol-gl/webgl/compat';
 import { QuadSchema, QuadValues } from '../util';
 import { Vec2 } from 'mol-math/linear-algebra';
 import { getHistopyramidSum } from './sum';
@@ -62,11 +61,12 @@ function getLevelTexture(ctx: WebGLContext, level: number) {
     return tex
 }
 
-function setRenderingDefaults(gl: GLRenderingContext) {
-    gl.disable(gl.CULL_FACE)
-    gl.disable(gl.BLEND)
-    gl.disable(gl.DEPTH_TEST)
-    gl.depthMask(false)
+function setRenderingDefaults(ctx: WebGLContext) {
+    const { gl, state } = ctx
+    state.disable(gl.CULL_FACE)
+    state.disable(gl.BLEND)
+    state.disable(gl.DEPTH_TEST)
+    state.depthMask(false)
 }
 
 export interface HistogramPyramid {
@@ -102,7 +102,7 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture)
     for (let i = 0; i < levels; ++i) levelTextures.push(getLevelTexture(ctx, i))
 
     const renderable = getHistopyramidReductionRenderable(ctx, initialTexture)
-    setRenderingDefaults(gl)
+    setRenderingDefaults(ctx)
 
     let offset = 0;
     for (let i = 0; i < levels; i++) {
diff --git a/src/mol-gl/compute/marching-cubes/active-voxels.ts b/src/mol-gl/compute/marching-cubes/active-voxels.ts
index 0ede2cd48e727808c87237f6daa42e08f2d01f77..cf1367a8b867a03c1ea64eb318afc9fa16db9fcb 100644
--- a/src/mol-gl/compute/marching-cubes/active-voxels.ts
+++ b/src/mol-gl/compute/marching-cubes/active-voxels.ts
@@ -11,7 +11,6 @@ import { Values, TextureSpec, UniformSpec } from '../../renderable/schema';
 import { Texture, createTexture } from 'mol-gl/webgl/texture';
 import { ShaderCode } from 'mol-gl/shader-code';
 import { ValueCell } from 'mol-util';
-import { GLRenderingContext } from 'mol-gl/webgl/compat';
 import { Vec3 } from 'mol-math/linear-algebra';
 import { QuadSchema, QuadValues } from '../util';
 import { getTriCount } from './tables';
@@ -52,11 +51,12 @@ function getActiveVoxelsRenderable(ctx: WebGLContext, volumeData: Texture, gridD
     return createComputeRenderable(renderItem, values);
 }
 
-function setRenderingDefaults(gl: GLRenderingContext) {
-    gl.disable(gl.CULL_FACE)
-    gl.disable(gl.BLEND)
-    gl.disable(gl.DEPTH_TEST)
-    gl.depthMask(false)
+function setRenderingDefaults(ctx: WebGLContext) {
+    const { gl, state } = ctx
+    state.disable(gl.CULL_FACE)
+    state.disable(gl.BLEND)
+    state.disable(gl.DEPTH_TEST)
+    state.depthMask(false)
 }
 
 export function calcActiveVoxels(ctx: WebGLContext, cornerTex: Texture, gridDimensions: Vec3, isoValue: number) {
@@ -72,7 +72,7 @@ export function calcActiveVoxels(ctx: WebGLContext, cornerTex: Texture, gridDime
     const renderable = getActiveVoxelsRenderable(ctx, cornerTex, gridDimensions, isoValue)
 
     activeVoxelsTex.attachFramebuffer(framebuffer, 0)
-    setRenderingDefaults(gl)
+    setRenderingDefaults(ctx)
     gl.viewport(0, 0, width, height)
     renderable.render()
 
diff --git a/src/mol-gl/compute/marching-cubes/isosurface.ts b/src/mol-gl/compute/marching-cubes/isosurface.ts
index 7d69229971e3f7dfd555c98ec8c7cd1d311688a4..24a4cb508a6c7dc073d1cb0a526d7b9b66652383 100644
--- a/src/mol-gl/compute/marching-cubes/isosurface.ts
+++ b/src/mol-gl/compute/marching-cubes/isosurface.ts
@@ -11,7 +11,6 @@ import { Values, TextureSpec, UniformSpec } from '../../renderable/schema';
 import { Texture, createTexture } from 'mol-gl/webgl/texture';
 import { ShaderCode } from 'mol-gl/shader-code';
 import { ValueCell } from 'mol-util';
-import { GLRenderingContext } from 'mol-gl/webgl/compat';
 import { Vec3, Vec2, Mat4 } from 'mol-math/linear-algebra';
 import { QuadSchema, QuadValues } from '../util';
 import { HistogramPyramid } from '../histogram-pyramid/reduction';
@@ -73,16 +72,17 @@ function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture
     return createComputeRenderable(renderItem, values);
 }
 
-function setRenderingDefaults(gl: GLRenderingContext) {
-    gl.disable(gl.CULL_FACE)
-    gl.disable(gl.BLEND)
-    gl.disable(gl.DEPTH_TEST)
-    gl.depthMask(false)
-    gl.enable(gl.SCISSOR_TEST)
+function setRenderingDefaults(ctx: WebGLContext) {
+    const { gl, state } = ctx
+    state.disable(gl.CULL_FACE)
+    state.disable(gl.BLEND)
+    state.disable(gl.DEPTH_TEST)
+    state.depthMask(false)
+    state.enable(gl.SCISSOR_TEST)
 }
 
 export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Texture, volumeData: Texture, histogramPyramid: HistogramPyramid, gridDimensions: Vec3, transform: Mat4, isoValue: number, vertexGroupTexture?: Texture, normalTexture?: Texture) {
-    const { gl, framebufferCache } = ctx
+    const { gl, framebufferCache, state } = ctx
     const { pyramidTex, height, levels, scale, count } = histogramPyramid
 
     const framebuffer = framebufferCache.get(FramebufferName).value
@@ -130,11 +130,11 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex
         // drawBuffers.COLOR_ATTACHMENT5
     ])
 
-    setRenderingDefaults(gl)
+    setRenderingDefaults(ctx)
     gl.viewport(0, 0, pyramidTex.width, pyramidTex.height)
     gl.scissor(0, 0, pyramidTex.width, height)
     renderable.render()
-    gl.disable(gl.SCISSOR_TEST)
+    state.disable(gl.SCISSOR_TEST)
 
     // const vgt = readTexture(ctx, vertexGroupTexture, pyramidTex.width, height)
     // console.log('vertexGroupTexture', vgt.array.subarray(0, 4 * count))
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index ec9095bf11c03b5d8dc4483cebcbbfc672128740..d3d46423529fedd2138d3a69b4529efa6b346f9f 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -125,27 +125,27 @@ namespace Renderer {
 
                 if (r.values.dDoubleSided) {
                     if (r.values.dDoubleSided.ref.value) {
-                        gl.disable(gl.CULL_FACE)
+                        state.disable(gl.CULL_FACE)
                     } else {
-                        gl.enable(gl.CULL_FACE)
+                        state.enable(gl.CULL_FACE)
                     }
                 } else {
                     // webgl default
-                    gl.disable(gl.CULL_FACE)
+                    state.disable(gl.CULL_FACE)
                 }
 
                 if (r.values.dFlipSided) {
                     if (r.values.dFlipSided.ref.value) {
-                        gl.frontFace(gl.CW)
-                        gl.cullFace(gl.FRONT)
+                        state.frontFace(gl.CW)
+                        state.cullFace(gl.FRONT)
                     } else {
-                        gl.frontFace(gl.CCW)
-                        gl.cullFace(gl.BACK)
+                        state.frontFace(gl.CCW)
+                        state.cullFace(gl.BACK)
                     }
                 } else {
                     // webgl default
-                    gl.frontFace(gl.CCW)
-                    gl.cullFace(gl.BACK)
+                    state.frontFace(gl.CCW)
+                    state.cullFace(gl.BACK)
                 }
 
                 r.render(variant)
@@ -172,26 +172,26 @@ namespace Renderer {
             const { renderables } = scene
 
             if (variant === 'draw') {
-                gl.disable(gl.BLEND)
-                gl.enable(gl.DEPTH_TEST)
-                gl.depthMask(true)
+                state.disable(gl.BLEND)
+                state.enable(gl.DEPTH_TEST)
+                state.depthMask(true)
                 for (let i = 0, il = renderables.length; i < il; ++i) {
                     const r = renderables[i]
                     if (r.state.opaque) renderObject(r, variant)
                 }
 
-                gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
-                gl.enable(gl.BLEND)
+                state.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
+                state.enable(gl.BLEND)
                 for (let i = 0, il = renderables.length; i < il; ++i) {
                     const r = renderables[i]
-                    gl.depthMask(r.values.uAlpha.ref.value === 1.0)
+                    state.depthMask(r.values.uAlpha.ref.value === 1.0)
                     if (!r.state.opaque) renderObject(r, variant)
                 }
             } else {
                 // picking
-                gl.disable(gl.BLEND)
-                gl.enable(gl.DEPTH_TEST)
-                gl.depthMask(true)
+                state.disable(gl.BLEND)
+                state.enable(gl.DEPTH_TEST)
+                state.depthMask(true)
                 for (let i = 0, il = renderables.length; i < il; ++i) {
                     renderObject(renderables[i], variant)
                 }
@@ -202,7 +202,7 @@ namespace Renderer {
 
         return {
             clear: () => {
-                gl.depthMask(true)
+                state.depthMask(true)
                 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
             },
             render,
diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts
index fb59101169f71f72df25ad976ee3fe2f7933b523..09f567e2551d59c8e3f013f2f75de38680173928 100644
--- a/src/mol-gl/webgl/context.ts
+++ b/src/mol-gl/webgl/context.ts
@@ -160,49 +160,7 @@ export type WebGLExtensions = {
     drawBuffers: COMPAT_draw_buffers | null
 }
 
-export type WebGLStats = {
-    bufferCount: number
-    framebufferCount: number
-    renderbufferCount: number
-    textureCount: number
-    vaoCount: number
-
-    drawCount: number
-    instanceCount: number
-    instancedDrawCount: number
-}
-
-export type WebGLState = {
-    currentProgramId: number
-    currentMaterialId: number
-}
-
-/** A WebGL context object, including the rendering context, resource caches and counts */
-export interface WebGLContext {
-    readonly gl: GLRenderingContext
-    readonly isWebGL2: boolean
-    readonly pixelRatio: number
-
-    readonly extensions: WebGLExtensions
-    readonly state: WebGLState
-    readonly stats: WebGLStats
-
-    readonly shaderCache: ShaderCache
-    readonly programCache: ProgramCache
-    readonly framebufferCache: FramebufferCache
-
-    readonly maxTextureSize: number
-    readonly maxDrawBuffers: number
-
-    unbindFramebuffer: () => void
-    readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array | Float32Array) => void
-    readPixelsAsync: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => Promise<void>
-    waitForGpuCommandsComplete: () => Promise<void>
-    waitForGpuCommandsCompleteSync: () => void
-    destroy: () => void
-}
-
-export function createContext(gl: GLRenderingContext): WebGLContext {
+function createExtensions(gl: GLRenderingContext): WebGLExtensions {
     const instancedArrays = getInstancedArrays(gl)
     if (instancedArrays === null) {
         throw new Error('Could not find support for "instanced_arrays"')
@@ -244,12 +202,34 @@ export function createContext(gl: GLRenderingContext): WebGLContext {
         console.log('Could not find support for "draw_buffers"')
     }
 
-    const state: WebGLState = {
-        currentProgramId: -1,
-        currentMaterialId: -1,
+    return {
+        instancedArrays,
+        standardDerivatives,
+        blendMinMax,
+        textureFloat,
+        textureFloatLinear,
+        elementIndexUint,
+        vertexArrayObject,
+        fragDepth,
+        colorBufferFloat,
+        drawBuffers
     }
+}
+
+export type WebGLStats = {
+    bufferCount: number
+    framebufferCount: number
+    renderbufferCount: number
+    textureCount: number
+    vaoCount: number
+
+    drawCount: number
+    instanceCount: number
+    instancedDrawCount: number
+}
 
-    const stats: WebGLStats = {
+function createStats(): WebGLStats {
+    return {
         bufferCount: 0,
         framebufferCount: 0,
         renderbufferCount: 0,
@@ -260,19 +240,142 @@ export function createContext(gl: GLRenderingContext): WebGLContext {
         instanceCount: 0,
         instancedDrawCount: 0,
     }
+}
 
-    const extensions: WebGLExtensions = {
-        instancedArrays,
-        standardDerivatives,
-        blendMinMax,
-        textureFloat,
-        textureFloatLinear,
-        elementIndexUint,
-        vertexArrayObject,
-        fragDepth,
-        colorBufferFloat,
-        drawBuffers
+export type WebGLState = {
+    currentProgramId: number
+    currentMaterialId: number
+
+    enable: (cap: number) => void
+    disable: (cap: number) => void
+
+    frontFace: (mode: number) => void
+    cullFace: (mode: number) => void
+    depthMask: (flag: boolean) => void
+
+    blendFunc: (src: number, dst: number) => void
+    blendFuncSeparate: (srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => void
+
+    blendEquation: (mode: number) => void
+    blendEquationSeparate: (modeRGB: number, modeAlpha: number) => void
+}
+
+function createState(gl: GLRenderingContext): WebGLState {
+    const enabledCapabilities: { [k: number]: boolean } = {}
+
+    let currentFrontFace = gl.getParameter(gl.FRONT_FACE)
+    let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE)
+    let currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK)
+
+    let currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB)
+    let currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB)
+    let currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA)
+    let currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA)
+
+    let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB)
+    let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA)
+
+    return {
+        currentProgramId: -1,
+        currentMaterialId: -1,
+
+        enable: (cap: number) => {
+            if (enabledCapabilities[cap] !== true ) {
+                gl.enable(cap)
+                enabledCapabilities[cap] = true
+            }
+        },
+        disable: (cap: number) => {
+            if (enabledCapabilities[cap] !== false) {
+                gl.disable(cap)
+                enabledCapabilities[cap] = false
+            }
+        },
+
+        frontFace: (mode: number) => {
+            if (mode !== currentFrontFace) {
+                gl.frontFace(mode)
+                currentFrontFace = mode
+            }
+        },
+        cullFace: (mode: number) => {
+            if (mode !== currentCullFace) {
+                gl.cullFace(mode)
+                currentCullFace = mode
+            }
+        },
+        depthMask: (flag: boolean) => {
+            if (flag !== currentDepthMask) {
+                gl.depthMask(flag)
+                currentDepthMask = flag
+            }
+        },
+
+        blendFunc: (src: number, dst: number) => {
+            if (src !== currentBlendSrcRGB || dst !== currentBlendDstRGB || src !== currentBlendSrcAlpha || dst !== currentBlendDstAlpha) {
+                gl.blendFunc(src, dst)
+                currentBlendSrcRGB = src
+                currentBlendDstRGB = dst
+                currentBlendSrcAlpha = src
+                currentBlendDstAlpha = dst
+            }
+        },
+        blendFuncSeparate: (srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => {
+            if (srcRGB !== currentBlendSrcRGB || dstRGB !== currentBlendDstRGB || srcAlpha !== currentBlendSrcAlpha || dstAlpha !== currentBlendDstAlpha) {
+                gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha)
+                currentBlendSrcRGB = srcRGB
+                currentBlendDstRGB = dstRGB
+                currentBlendSrcAlpha = srcAlpha
+                currentBlendDstAlpha = dstAlpha
+            }
+        },
+
+        blendEquation: (mode: number) => {
+            if (mode !== currentBlendEqRGB || mode !== currentBlendEqAlpha) {
+                gl.blendEquation(mode)
+                currentBlendEqRGB = mode
+                currentBlendEqAlpha = mode
+            }
+        },
+        blendEquationSeparate: (modeRGB: number, modeAlpha: number) => {
+            if (modeRGB !== currentBlendEqRGB || modeAlpha !== currentBlendEqAlpha) {
+                gl.blendEquationSeparate(modeRGB, modeAlpha)
+                currentBlendEqRGB = modeRGB
+                currentBlendEqAlpha = modeAlpha
+            }
+        }
     }
+}
+
+/** A WebGL context object, including the rendering context, resource caches and counts */
+export interface WebGLContext {
+    readonly gl: GLRenderingContext
+    readonly isWebGL2: boolean
+    readonly pixelRatio: number
+
+    readonly extensions: WebGLExtensions
+    readonly state: WebGLState
+    readonly stats: WebGLStats
+
+    readonly shaderCache: ShaderCache
+    readonly programCache: ProgramCache
+    readonly framebufferCache: FramebufferCache
+
+    readonly maxTextureSize: number
+    readonly maxDrawBuffers: number
+
+    unbindFramebuffer: () => void
+    readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array | Float32Array) => void
+    readPixelsAsync: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => Promise<void>
+    waitForGpuCommandsComplete: () => Promise<void>
+    waitForGpuCommandsCompleteSync: () => void
+    destroy: () => void
+}
+
+export function createContext(gl: GLRenderingContext): WebGLContext {
+    const extensions = createExtensions(gl)
+    const state = createState(gl)
+    const stats = createStats()
 
     const shaderCache: ShaderCache = createShaderCache(gl)
     const programCache: ProgramCache = createProgramCache(gl, state, extensions, shaderCache)
diff --git a/src/mol-gl/webgl/program.ts b/src/mol-gl/webgl/program.ts
index 34bf101c9abe6c4bc1322ed9c1af5c77d8eb1837..5997cc71165cb322693132650ee8412add4fe475 100644
--- a/src/mol-gl/webgl/program.ts
+++ b/src/mol-gl/webgl/program.ts
@@ -163,7 +163,10 @@ export function createProgram(gl: GLRenderingContext, state: WebGLState, extensi
         setUniforms: (uniformValues: UniformsList) => {
             for (let i = 0, il = uniformValues.length; i < il; ++i) {
                 const [k, v] = uniformValues[i]
-                if (v) uniformSetters[k](gl, locations[k], v.ref.value)
+                if (v) {
+                    const l = locations[k]
+                    if (l !== null) uniformSetters[k](gl, l, v.ref.value)
+                }
             }
         },
         bindAttributes: (attribueBuffers: AttributeBuffers) => {
@@ -176,10 +179,13 @@ export function createProgram(gl: GLRenderingContext, state: WebGLState, extensi
         bindTextures: (textures: Textures) => {
             for (let i = 0, il = textures.length; i < il; ++i) {
                 const [k, texture] = textures[i]
-                texture.bind(i as TextureId)
-                // TODO if the order and count of textures in a material can be made invariant
-                //      this needs to be set only when the material changes
-                uniformSetters[k](gl, locations[k], i as TextureId)
+                const l = locations[k]
+                if (l !== null) {
+                    // TODO if the order and count of textures in a material can be made invariant
+                    //      bind needs to be called only when the material changes
+                    texture.bind(i as TextureId)
+                    uniformSetters[k](gl, l, i as TextureId)
+                }
             }
         },
 
diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts
index 5159ae4ff81a09e07f5a5c9500aeb07badfb88f9..8036d65c3ecf2df76bd4837711e96a30ad360554 100644
--- a/src/mol-math/geometry/gaussian-density/gpu.ts
+++ b/src/mol-math/geometry/gaussian-density/gpu.ts
@@ -14,7 +14,6 @@ import { ValueCell } from 'mol-util'
 import { createComputeRenderable, ComputeRenderable } from 'mol-gl/renderable'
 import { WebGLContext } from 'mol-gl/webgl/context';
 import { createTexture, Texture } from 'mol-gl/webgl/texture';
-import { GLRenderingContext } from 'mol-gl/webgl/compat';
 import { decodeFloatRGB } from 'mol-util/float-packing';
 import { ShaderCode } from 'mol-gl/shader-code';
 import { createComputeRenderItem } from 'mol-gl/webgl/render-item';
@@ -112,7 +111,7 @@ function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionDat
 
     const framebuffer = framebufferCache.get(FramebufferName).value
     framebuffer.bind()
-    setRenderingDefaults(gl)
+    setRenderingDefaults(webgl)
 
     if (!texture) texture = createTexture(webgl, 'image-float32', 'rgba', 'float', 'nearest')
     texture.define(texDimX, texDimY)
@@ -167,7 +166,7 @@ function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionDat
 
     const framebuffer = framebufferCache.get(FramebufferName).value
     framebuffer.bind()
-    setRenderingDefaults(gl)
+    setRenderingDefaults(webgl)
     gl.viewport(0, 0, dx, dy)
 
     if (!texture) texture = createTexture(webgl, 'volume-float32', 'rgba', 'float', 'nearest')
@@ -265,37 +264,38 @@ function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, po
     return createComputeRenderable(renderItem, values)
 }
 
-function setRenderingDefaults(gl: GLRenderingContext) {
-    gl.disable(gl.CULL_FACE)
-    gl.frontFace(gl.CCW)
-    gl.cullFace(gl.BACK)
-    gl.enable(gl.BLEND)
+function setRenderingDefaults(ctx: WebGLContext) {
+    const { gl, state } = ctx
+    state.disable(gl.CULL_FACE)
+    state.frontFace(gl.CCW)
+    state.cullFace(gl.BACK)
+    state.enable(gl.BLEND)
 }
 
 function setupMinDistanceRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
-    const { gl } = webgl
+    const { gl, state } = webgl
     ValueCell.update(renderable.values.dCalcType, 'minDistance')
     renderable.update()
-    gl.blendFunc(gl.ONE, gl.ONE)
+    state.blendFunc(gl.ONE, gl.ONE)
     // the shader writes 1 - dist so we set blending to MAX
-    gl.blendEquation(webgl.extensions.blendMinMax.MAX)
+    state.blendEquation(webgl.extensions.blendMinMax.MAX)
 }
 
 function setupDensityRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
-    const { gl } = webgl
+    const { gl, state } = webgl
     ValueCell.update(renderable.values.dCalcType, 'density')
     renderable.update()
-    gl.blendFunc(gl.ONE, gl.ONE)
-    gl.blendEquation(gl.FUNC_ADD)
+    state.blendFunc(gl.ONE, gl.ONE)
+    state.blendEquation(gl.FUNC_ADD)
 }
 
 function setupGroupIdRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) {
-    const { gl } = webgl
+    const { gl, state } = webgl
     ValueCell.update(renderable.values.dCalcType, 'groupId')
     renderable.update()
     // overwrite color, don't change alpha
-    gl.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ZERO, gl.ONE)
-    gl.blendEquation(gl.FUNC_ADD)
+    state.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ZERO, gl.ONE)
+    state.blendEquation(gl.FUNC_ADD)
 }
 
 function getTexture2dSize(gridDim: Vec3) {
diff --git a/src/tests/browser/render-structure.ts b/src/tests/browser/render-structure.ts
index 80ba14f4459aca89a8a958fe19e8ca4606ddcbab..290afa43d6b56c3b607aafcfdf98f8a7ac46724d 100644
--- a/src/tests/browser/render-structure.ts
+++ b/src/tests/browser/render-structure.ts
@@ -138,6 +138,7 @@ async function init() {
     if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr)
     if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr)
     canvas3d.resetCamera()
+    // canvas3d.setProps({ trackball: { ...canvas3d.props.trackball, spin: true } })
 }
 
 init()
\ No newline at end of file