diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts
index 33a4f9faab2fffc3a19cdf3d8193eb741afb0862..95fbda73b318a8cce38131676a1abc244d56ea7f 100644
--- a/src/apps/canvas/structure-view.ts
+++ b/src/apps/canvas/structure-view.ts
@@ -197,7 +197,8 @@ export async function StructureView(app: App, canvas3d: Canvas3D, models: Readon
                     if (structureRepresentations[k]) {
                         repr = structureRepresentations[k]
                     } else {
-                        repr = app.structureRepresentationRegistry.create(k, app.reprCtx, structure)
+                        const provider = app.structureRepresentationRegistry.get(k)
+                        repr = provider.factory(provider.getParams)
                         structureRepresentations[k] = repr
                         canvas3d.add(repr)
                     }
diff --git a/src/mol-geo/geometry/direct-volume/direct-volume.ts b/src/mol-geo/geometry/direct-volume/direct-volume.ts
index 50dfc577d7e0cca54bd64994313d39bdc6d0d0af..9196992727d879ac5cb66b068762c3892a7102c2 100644
--- a/src/mol-geo/geometry/direct-volume/direct-volume.ts
+++ b/src/mol-geo/geometry/direct-volume/direct-volume.ts
@@ -75,10 +75,9 @@ export namespace DirectVolume {
         renderMode: PD.Select('Render Mode', '', 'isosurface', RenderModeOptions),
         controlPoints: PD.Text('Control Points', '', '0.19:0.1, 0.2:0.5, 0.21:0.1, 0.4:0.3'),
     }
-    export const DefaultProps = PD.getDefaultValues(Params)
-    export type Props = typeof DefaultProps
+    export type Params = typeof Params
 
-    export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<DirectVolumeValues> {
+    export async function createValues(ctx: RuntimeContext, directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): Promise<DirectVolumeValues> {
         const { gridTexture, gridTextureDim } = directVolume
         const { bboxSize, bboxMin, bboxMax, gridDimension, transform: gridTransform } = directVolume
 
@@ -126,7 +125,7 @@ export namespace DirectVolume {
         }
     }
 
-    export function updateValues(values: DirectVolumeValues, props: Props) {
+    export function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) {
         const vertices = new Float32Array(values.aPosition.ref.value)
         transformPositionArray(values.uTransform.ref.value, vertices, 0, vertices.length / 3)
         const boundingSphere = calculateBoundingSphere(
diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts
index 37cdf4b43955673e25acfdef657fcc058de5eebe..79d665d114c1c20ae252c670b44a4eb79abbf5d8 100644
--- a/src/mol-geo/geometry/geometry.ts
+++ b/src/mol-geo/geometry/geometry.ts
@@ -62,7 +62,6 @@ export namespace Geometry {
 
     export const Params = {
         alpha: PD.Range('Opacity', '', 1, 0, 1, 0.01),
-        visible: PD.Boolean('Visible', '', true),
         depthMask: PD.Boolean('Depth Mask', '', true),
         useFog: PD.Boolean('Use Fog', '', false),
         highlightColor: PD.Color('Highlight Color', '', Color.fromNormalizedRgb(1.0, 0.4, 0.6)),
@@ -73,12 +72,11 @@ export namespace Geometry {
         colorTheme: PD.Select<BuiltInColorThemeName>('Color Name', '', 'uniform', BuiltInColorThemeOptions),
         sizeTheme: PD.Select<BuiltInSizeThemeName>('Size Name', '', 'uniform', BuiltInSizeThemeOptions),
     }
-    export const DefaultProps = PD.getDefaultValues(Params)
-    export type Props = typeof DefaultProps
+    export type Params = typeof Params
 
     export type Counts = { drawCount: number, groupCount: number, instanceCount: number }
 
-    export function createValues(props: Props, counts: Counts) {
+    export function createValues(props: PD.Values<Params>, counts: Counts) {
         return {
             uAlpha: ValueCell.create(props.alpha),
             uHighlightColor: ValueCell.create(Color.toArrayNormalized(props.highlightColor, Vec3.zero(), 0)),
@@ -89,7 +87,7 @@ export namespace Geometry {
         }
     }
 
-    export function updateValues(values: BaseValues, props: Props) {
+    export function updateValues(values: BaseValues, props: PD.Values<Params>) {
         if (Color.fromNormalizedArray(values.uHighlightColor.ref.value, 0) !== props.highlightColor) {
             ValueCell.update(values.uHighlightColor, Color.toArrayNormalized(props.highlightColor, values.uHighlightColor.ref.value, 0))
         }
@@ -103,15 +101,14 @@ export namespace Geometry {
 
 //
 
-export function createRenderableState(props: Geometry.Props): RenderableState {
+export function createRenderableState(props: PD.Values<Geometry.Params>): RenderableState {
     return {
-        visible: props.visible,
+        visible: true,
         depthMask: props.depthMask
     }
 }
 
-export function updateRenderableState(state: RenderableState, props: Geometry.Props) {
-    state.visible = props.visible
+export function updateRenderableState(state: RenderableState, props: PD.Values<Geometry.Params>) {
     state.depthMask = props.depthMask
 }
 
diff --git a/src/mol-geo/geometry/lines/lines.ts b/src/mol-geo/geometry/lines/lines.ts
index 4c5a48a7313b0a431ba858066795b32a77a2d1e5..0cf5bfef2f08438d53b8d9ec5c7ffebdad0d7435 100644
--- a/src/mol-geo/geometry/lines/lines.ts
+++ b/src/mol-geo/geometry/lines/lines.ts
@@ -97,10 +97,9 @@ export namespace Lines {
         ...Geometry.Params,
         lineSizeAttenuation: PD.Boolean('Line Size Attenuation', '', false),
     }
-    export const DefaultProps = PD.getDefaultValues(Params)
-    export type Props = typeof DefaultProps
+    export type Params = typeof Params
 
-    export async function createValues(ctx: RuntimeContext, lines: Lines, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<LinesValues> {
+    export async function createValues(ctx: RuntimeContext, lines: Lines, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): Promise<LinesValues> {
         const { instanceCount, groupCount } = locationIt
         const color = await createColors(ctx, locationIt, theme.color)
         const size = await createSizes(ctx, locationIt, theme.size)
@@ -138,7 +137,7 @@ export namespace Lines {
         }
     }
 
-    export function updateValues(values: LinesValues, props: Props) {
+    export function updateValues(values: LinesValues, props: PD.Values<Params>) {
         const boundingSphere = Sphere3D.addSphere(
             calculateBoundingSphere(
                 values.aStart.ref.value, Math.floor(values.aStart.ref.value.length / 3),
diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts
index 0c1a8f5cf5556010e58731ced5275e18481845ed..0f79107459636a383fec52ecbe335c4c4e90dd2b 100644
--- a/src/mol-geo/geometry/mesh/mesh.ts
+++ b/src/mol-geo/geometry/mesh/mesh.ts
@@ -345,10 +345,9 @@ export namespace Mesh {
         flipSided: PD.Boolean('Flip Sided', '', false),
         flatShaded: PD.Boolean('Flat Shaded', '', false),
     }
-    export const DefaultProps = PD.getDefaultValues(Params)
-    export type Props = typeof DefaultProps
+    export type Params = typeof Params
 
-    export async function createValues(ctx: RuntimeContext, mesh: Mesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<MeshValues> {
+    export async function createValues(ctx: RuntimeContext, mesh: Mesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): Promise<MeshValues> {
         const { instanceCount, groupCount } = locationIt
         const color = await createColors(ctx, locationIt, theme.color)
         const marker = createMarkers(instanceCount * groupCount)
@@ -377,7 +376,7 @@ export namespace Mesh {
         }
     }
 
-    export function updateValues(values: MeshValues, props: Props) {
+    export function updateValues(values: MeshValues, props: PD.Values<Params>) {
         const boundingSphere = calculateBoundingSphere(
             values.aPosition.ref.value, Math.floor(values.aPosition.ref.value.length / 3),
             values.aTransform.ref.value, values.instanceCount.ref.value
diff --git a/src/mol-geo/geometry/points/points.ts b/src/mol-geo/geometry/points/points.ts
index 616e7e057ed2e98404bb6185d41e127ba2fc08c9..2b245338dfa71a2b02edfa155d69bbbb59742c39 100644
--- a/src/mol-geo/geometry/points/points.ts
+++ b/src/mol-geo/geometry/points/points.ts
@@ -61,10 +61,9 @@ export namespace Points {
         pointFilledCircle: PD.Boolean('Point Filled Circle', '', false),
         pointEdgeBleach: PD.Numeric('Point Edge Bleach', '', 0.2, 0, 1, 0.05),
     }
-    export const DefaultProps = PD.getDefaultValues(Params)
-    export type Props = typeof DefaultProps
+    export type Params = typeof Params
 
-    export async function createValues(ctx: RuntimeContext, points: Points, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: Props): Promise<PointsValues> {
+    export async function createValues(ctx: RuntimeContext, points: Points, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): Promise<PointsValues> {
         const { instanceCount, groupCount } = locationIt
         const color = await createColors(ctx, locationIt, theme.color)
         const size = await createSizes(ctx, locationIt, theme.size)
@@ -93,7 +92,7 @@ export namespace Points {
         }
     }
 
-    export function updateValues(values: PointsValues, props: Props) {
+    export function updateValues(values: PointsValues, props: PD.Values<Params>) {
         const boundingSphere = calculateBoundingSphere(
             values.aPosition.ref.value, Math.floor(values.aPosition.ref.value.length / 3),
             values.aTransform.ref.value, values.instanceCount.ref.value
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index f5ec7890e703c217ed8529e6b29d7bb353c7fe01..c7d4ce3a4fec1c3b17a1dd68cd02d8d020f80a49 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -44,7 +44,7 @@ interface Renderer {
 }
 
 export const DefaultRendererProps = {
-    clearColor: 0x000000 as Color,
+    clearColor: Color(0x000000),
     viewport: Viewport.create(0, 0, 0, 0)
 }
 export type RendererProps = typeof DefaultRendererProps
diff --git a/src/mol-plugin/behavior/static/representation.ts b/src/mol-plugin/behavior/static/representation.ts
index ee5c6a0e8343ee643070d580d1f3a282d54bffb4..0bd4ec276ddbf7f2be67231bdcfc86e6c4f51ac7 100644
--- a/src/mol-plugin/behavior/static/representation.ts
+++ b/src/mol-plugin/behavior/static/representation.ts
@@ -18,7 +18,7 @@ export function SyncRepresentationToCanvas(ctx: PluginContext) {
         ctx.canvas3d.add(e.obj.data);
         ctx.canvas3d.requestDraw(true);
 
-        // TODO: update visiblity
+        // TODO: update visiblity, e.obj.data.setVisibility()
     });
     events.object.updated.subscribe(e => {
         if (e.oldObj && SO.isRepresentation3D(e.oldObj)) {
@@ -29,7 +29,7 @@ export function SyncRepresentationToCanvas(ctx: PluginContext) {
 
         if (!SO.isRepresentation3D(e.obj)) return;
 
-        // TODO: update visiblity
+        // TODO: update visiblity, e.obj.data.setVisibility()
         ctx.canvas3d.add(e.obj.data);
         ctx.canvas3d.requestDraw(true);
     });
@@ -47,6 +47,6 @@ export function UpdateRepresentationVisibility(ctx: PluginContext) {
         const cell = e.state.cells.get(e.ref)!;
         if (!SO.isRepresentation3D(cell.obj)) return;
 
-        // TODO: update visiblity
+        // TODO: update visiblity, e.obj.data.setVisibility()
     })
 }
\ No newline at end of file
diff --git a/src/mol-plugin/state/transforms/visuals.ts b/src/mol-plugin/state/transforms/visuals.ts
index f5aab7a45bc5764627de9deb0804a31d0500aa8d..fb24bc2bc96e0e072e99c8c89d9bf08303f750b2 100644
--- a/src/mol-plugin/state/transforms/visuals.ts
+++ b/src/mol-plugin/state/transforms/visuals.ts
@@ -29,21 +29,22 @@ const CreateStructureRepresentation = PluginStateTransform.Create<SO.Molecule.St
         default: (a, ctx: PluginContext) => ({
             type: {
                 name: ctx.structureReprensentation.registry.default.name,
-                params: PD.getDefaultValues(ctx.structureReprensentation.registry.default.provider.getParams(ctx.structureReprensentation.themeCtx, a.data))
+                params: ctx.structureReprensentation.registry.default.provider.defaultValues
             }
         }),
         definition: (a, ctx: PluginContext) => ({
             type: PD.Mapped('Type', '',
                 ctx.structureReprensentation.registry.default.name,
                 ctx.structureReprensentation.registry.types,
-                name => PD.Group('Params', '', ctx.structureReprensentation.registry.get(name)!.getParams(ctx.structureReprensentation.themeCtx, a.data)))
+                name => PD.Group('Params', '', ctx.structureReprensentation.registry.get(name).getParams(ctx.structureReprensentation.themeCtx, a.data)))
         })
     },
     apply({ a, params }, plugin: PluginContext) {
         return Task.create('Structure Representation', async ctx => {
-            const repr = plugin.structureReprensentation.registry.create(params.type.name, plugin.structureReprensentation.themeCtx, a.data)
+            const provider = plugin.structureReprensentation.registry.get(params.type.name)
+            const repr = provider.factory(provider.getParams)
             await repr.createOrUpdate({ webgl: plugin.canvas3d.webgl, ...plugin.structureReprensentation.themeCtx }, params.type.params || {}, {}, a.data).runInContext(ctx);
-            return new SO.Molecule.Representation3D(repr, { label: params.type.name });
+            return new SO.Molecule.Representation3D(repr, { label: provider.label });
         });
     },
     update({ a, b, oldParams, newParams }, plugin: PluginContext) {
diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts
index 8f8efdefcc1561d4cb3e8a0c1d154dfeccf95451..c456ffcfce5fe78108c0d4b1519e563fe27c2f4e 100644
--- a/src/mol-repr/representation.ts
+++ b/src/mol-repr/representation.ts
@@ -27,10 +27,21 @@ export type RepresentationParamsGetter<D, P extends PD.Params> = (ctx: ThemeRegi
 //
 
 export interface RepresentationProvider<D, P extends PD.Params> {
+    readonly label: string
+    readonly description: string
     readonly factory: (getParams: RepresentationParamsGetter<D, P>) => Representation<D, P>
     readonly getParams: (ctx: ThemeRegistryContext, data: D) => P
-    // TODO
-    // readonly defaultParams: PD.Values<P>
+    readonly defaultValues: PD.Values<P>
+}
+
+export type AnyRepresentationProvider = RepresentationProvider<any, {}>
+
+export const EmptyRepresentationProvider = {
+    label: '',
+    description: '',
+    factory: () => Representation.Empty,
+    getParams: () => ({}),
+    defaultValues: {}
 }
 
 export class RepresentationRegistry<D> {
@@ -39,24 +50,18 @@ export class RepresentationRegistry<D> {
 
     get default() { return this._list[0]; }
     get types(): [string, string][] {
-        return this._list.map(e => [e.name, e.name] as [string, string]);
+        return this._list.map(e => [e.name, e.provider.label] as [string, string]);
     }
 
     constructor() {};
 
-    add<P extends PD.Params>(name: string, factory: RepresentationProvider<D, P>['factory'], getParams: RepresentationProvider<D, P>['getParams']) {
-        const provider = { factory, getParams } as RepresentationProvider<D, P>
+    add<P extends PD.Params>(name: string, provider: RepresentationProvider<D, P>) {
         this._list.push({ name, provider })
         this._map.set(name, provider)
     }
 
-    get(id: string) {
-        return this._map.get(id)
-    }
-
-    create(id: string, ctx: ThemeRegistryContext, data: D, props = {}): Representation<D, any> {
-        const provider = this.get(id)
-        return provider ? provider.factory(provider.getParams) : Representation.Empty
+    get<P extends PD.Params>(name: string): RepresentationProvider<D, P> {
+        return this._map.get(name) || EmptyRepresentationProvider as unknown as RepresentationProvider<D, P>
     }
 
     get list() {
@@ -82,15 +87,17 @@ interface Representation<D, P extends PD.Params = {}> {
     createOrUpdate: (ctx: RepresentationContext, props?: Partial<PD.Values<P>>, themeProps?: ThemeProps, data?: D) => Task<void>
     getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => boolean
+    setVisibility: (value: boolean) => void
     destroy: () => void
 }
 namespace Representation {
     export type Any = Representation<any>
-    export const Empty: Representation<any> = {
+    export const Empty: Any = {
         label: '', renderObjects: [], props: {}, params: {}, updated: new BehaviorSubject(0),
         createOrUpdate: () => Task.constant('', undefined),
         getLoci: () => EmptyLoci,
         mark: () => false,
+        setVisibility: () => {},
         destroy: () => {}
     }
 
@@ -163,6 +170,11 @@ namespace Representation {
                 }
                 return marked
             },
+            setVisibility: (value: boolean) => {
+                for (let i = 0, il = reprList.length; i < il; ++i) {
+                    reprList[i].setVisibility(value)
+                }
+            },
             destroy() {
                 for (let i = 0, il = reprList.length; i < il; ++i) {
                     reprList[i].destroy()
@@ -184,5 +196,6 @@ export interface Visual<D, P extends PD.Params> {
     createOrUpdate: (ctx: VisualContext, theme: Theme, props?: Partial<PD.Values<P>>, data?: D) => Promise<void>
     getLoci: (pickingId: PickingId) => Loci
     mark: (loci: Loci, action: MarkerAction) => boolean
+    setVisibility: (value: boolean) => void
     destroy: () => void
 }
\ No newline at end of file
diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts
index 9e283591f388d0c63167f22bbc9c4ce69e61dd5e..f9588891c092f2857753c552b4d297024feef2de 100644
--- a/src/mol-repr/shape/representation.ts
+++ b/src/mol-repr/shape/representation.ts
@@ -100,6 +100,9 @@ export function ShapeRepresentation<P extends ShapeParams>(): ShapeRepresentatio
             }
             return changed
         },
+        setVisibility(value: boolean) {
+            renderObjects.forEach(ro => ro.state.visible = value)
+        },
         destroy() {
             // TODO
             renderObjects.length = 0
diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts
index bf0350bcb4cd31af3d41620e441ae19716f2f4e8..c99f9c32b60a571797f5aa35db14002e0b1492ee 100644
--- a/src/mol-repr/structure/complex-representation.ts
+++ b/src/mol-repr/structure/complex-representation.ts
@@ -50,6 +50,10 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
         return visual ? visual.mark(loci, action) : false
     }
 
+    function setVisibility(value: boolean) {
+        if (visual) visual.setVisibility(value)
+    }
+
     function destroy() {
         if (visual) visual.destroy()
     }
@@ -65,6 +69,7 @@ export function ComplexRepresentation<P extends StructureParams>(label: string,
         createOrUpdate,
         getLoci,
         mark,
+        setVisibility,
         destroy
     }
 }
\ No newline at end of file
diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts
index 9d27d8bca1a1aadf810da95155f7e1a016c88d87..b24737ef35d6df0aa2b6f48b699cc65ae832e324 100644
--- a/src/mol-repr/structure/complex-visual.ts
+++ b/src/mol-repr/structure/complex-visual.ts
@@ -162,6 +162,9 @@ export function ComplexVisual<P extends ComplexParams>(builder: ComplexVisualGeo
             }
             return changed
         },
+        setVisibility(value: boolean) {
+            if (renderObject) renderObject.state.visible = value
+        },
         destroy() {
             // TODO
             renderObject = undefined
diff --git a/src/mol-repr/structure/registry.ts b/src/mol-repr/structure/registry.ts
index 5dcfe8aaff6045f9f2424a96b67d4e28cd517911..188c0d959249678a066241a5e1d864f88e31b45d 100644
--- a/src/mol-repr/structure/registry.ts
+++ b/src/mol-repr/structure/registry.ts
@@ -14,7 +14,7 @@ export class StructureRepresentationRegistry extends RepresentationRegistry<Stru
         super()
         Object.keys(BuiltInStructureRepresentations).forEach(name => {
             const p = (BuiltInStructureRepresentations as { [k: string]: RepresentationProvider<Structure, any> })[name]
-            this.add(name, p.factory, p.getParams)
+            this.add(name, p)
         })
     }
 }
diff --git a/src/mol-repr/structure/representation/ball-and-stick.ts b/src/mol-repr/structure/representation/ball-and-stick.ts
index 3cd9a158bdd22ec41c11bc7b5d7e87154aadc186..d411043d09835e2d78049330fda31e5bf06dace6 100644
--- a/src/mol-repr/structure/representation/ball-and-stick.ts
+++ b/src/mol-repr/structure/representation/ball-and-stick.ts
@@ -47,5 +47,9 @@ export function BallAndStickRepresentation(getParams: RepresentationParamsGetter
 }
 
 export const BallAndStickRepresentationProvider: StructureRepresentationProvider<typeof BallAndStickParams> = {
-    factory: BallAndStickRepresentation, getParams: getBallAndStickParams
+    label: 'Ball & Stick',
+    description: 'Displays atoms as spheres and bonds as cylinders.',
+    factory: BallAndStickRepresentation,
+    getParams: getBallAndStickParams,
+    defaultValues: PD.getDefaultValues(BallAndStickParams)
 }
\ No newline at end of file
diff --git a/src/mol-repr/structure/representation/cartoon.ts b/src/mol-repr/structure/representation/cartoon.ts
index 16beffdc93ccdd33a656b0c3b9794cce0a0e3057..8e5430564ad7195eb3e941c37153775c80e80e8c 100644
--- a/src/mol-repr/structure/representation/cartoon.ts
+++ b/src/mol-repr/structure/representation/cartoon.ts
@@ -47,5 +47,9 @@ export function CartoonRepresentation(getParams: RepresentationParamsGetter<Stru
 }
 
 export const CartoonRepresentationProvider: StructureRepresentationProvider<CartoonParams> = {
-    factory: CartoonRepresentation, getParams: getCartoonParams
+    label: 'Cartoon',
+    description: 'Displays a ribbon smoothly following the trace atom of polymers.',
+    factory: CartoonRepresentation,
+    getParams: getCartoonParams,
+    defaultValues: PD.getDefaultValues(CartoonParams)
 }
\ No newline at end of file
diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts
index c91a664a6a3529dea3b4b11df46ed38f33ef810c..f0d38b6699cb593a3ccbdd40cf8ab387029fcac5 100644
--- a/src/mol-repr/structure/units-representation.ts
+++ b/src/mol-repr/structure/units-representation.ts
@@ -141,6 +141,12 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, getPar
         return changed
     }
 
+    function setVisibility(value: boolean) {
+        visuals.forEach(({ visual }) => {
+            visual.setVisibility(value)
+        })
+    }
+
     function destroy() {
         visuals.forEach(({ visual }) => visual.destroy())
         visuals.clear()
@@ -161,6 +167,7 @@ export function UnitsRepresentation<P extends UnitsParams>(label: string, getPar
         createOrUpdate,
         getLoci,
         mark,
+        setVisibility,
         destroy
     }
 }
\ No newline at end of file
diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts
index ebfb6ab0461e97fd449b9c69dda6095ec83f18a4..f5cc5a4a58ce0ae94f8eb3bd551a47d0d49565f8 100644
--- a/src/mol-repr/structure/units-visual.ts
+++ b/src/mol-repr/structure/units-visual.ts
@@ -192,6 +192,9 @@ export function UnitsVisual<P extends UnitsParams>(builder: UnitsVisualGeometryB
             }
             return changed
         },
+        setVisibility(value: boolean) {
+            if (renderObject) renderObject.state.visible = value
+        },
         destroy() {
             // TODO
             renderObject = undefined
diff --git a/src/mol-repr/volume/registry.ts b/src/mol-repr/volume/registry.ts
index 30f5902bc10bd64d28b2a52a084c3614a9914e7c..e91833370ad02b2571af6a1da10d1c292047a347 100644
--- a/src/mol-repr/volume/registry.ts
+++ b/src/mol-repr/volume/registry.ts
@@ -12,7 +12,7 @@ export class VolumeRepresentationRegistry extends RepresentationRegistry<VolumeD
         super()
         Object.keys(BuiltInVolumeRepresentations).forEach(name => {
             const p = (BuiltInVolumeRepresentations as { [k: string]: RepresentationProvider<VolumeData, any> })[name]
-            this.add(name, p.factory, p.getParams)
+            this.add(name, p)
         })
     }
 }
diff --git a/src/mol-repr/volume/representation.ts b/src/mol-repr/volume/representation.ts
index 86eb9bb4912d75dce7a6e55a354e6805b53bfd72..d974b4e49bb964d45ffae23b7e639a7c4bc2fd9d 100644
--- a/src/mol-repr/volume/representation.ts
+++ b/src/mol-repr/volume/representation.ts
@@ -127,6 +127,9 @@ export function VolumeVisual<P extends VolumeParams>(builder: VolumeVisualGeomet
             }
             return changed
         },
+        setVisibility(value: boolean) {
+            if (renderObject) renderObject.state.visible = value
+        },
         destroy() {
             // TODO
             renderObject = undefined
@@ -198,6 +201,10 @@ export function VolumeRepresentation<P extends VolumeParams>(label: string, getP
         if (visual) visual.destroy()
     }
 
+    function setVisibility(value: boolean) {
+        if (visual) visual.setVisibility(value)
+    }
+
     return {
         label,
         get renderObjects() {
@@ -209,6 +216,7 @@ export function VolumeRepresentation<P extends VolumeParams>(label: string, getP
         createOrUpdate,
         getLoci,
         mark,
+        setVisibility,
         destroy
     }
 }
\ No newline at end of file