diff --git a/src/apps/render-test/state.ts b/src/apps/render-test/state.ts
index 9fa66b0352c12dc84f0480a7ca8e6d1d16c03443..1e284a0a12b47738f2d32ca9dd550e07f9fbdbcd 100644
--- a/src/apps/render-test/state.ts
+++ b/src/apps/render-test/state.ts
@@ -40,7 +40,7 @@ export type ColorTheme = keyof typeof ColorTheme
 
 export default class State {
     viewer: Viewer
-    pdbId = ''
+    pdbId = '1crn'
     // pdbId = '5ire'
     emdId = '8116'
     // pdbId = '6G1K'
@@ -77,6 +77,7 @@ export default class State {
     getSpacefillProps (): SpacefillProps {
         const colorThemeName = this.colorTheme.getValue()
         return {
+            doubleSided: true,
             detail: this.sphereDetail.getValue(),
             colorTheme: colorThemeName === 'uniform' ?
                 { name: colorThemeName, value: this.colorValue.getValue() } :
@@ -161,7 +162,10 @@ export default class State {
         this.surfaceRepr = VolumeRepresentation(Surface)
         await Run(this.surfaceRepr.create(v.volume, {
             isoValue: VolumeIsoValue.relative(v.volume.dataStats, 3.0),
-            alpha: 1.0
+            alpha: 0.5,
+            flatShaded: false,
+            flipSided: true,
+            doubleSided: true
         }), log, 500)
         viewer.add(this.surfaceRepr)
 
diff --git a/src/mol-geo/representation/structure/point.ts b/src/mol-geo/representation/structure/point.ts
index 5b567b3690edc44332e491ef1cc7fe16942146fd..71f317e39c3a31e83cce6d0f63a3f25201406e29 100644
--- a/src/mol-geo/representation/structure/point.ts
+++ b/src/mol-geo/representation/structure/point.ts
@@ -20,7 +20,8 @@ import { deepEqual } from 'mol-util';
 export const DefaultPointProps = {
     colorTheme: { name: 'instance-index' } as ColorTheme,
     sizeTheme: { name: 'vdw' } as SizeTheme,
-    alpha: 1
+    alpha: 1,
+    visible: true
 }
 export type PointProps = Partial<typeof DefaultPointProps>
 
@@ -60,7 +61,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
                 _units = units
                 _elementGroup = elementGroup
 
-                const { colorTheme, sizeTheme, alpha } = curProps
+                const { colorTheme, sizeTheme, alpha, visible } = curProps
                 const elementCount = OrderedSet.size(elementGroup.elements)
                 const unitCount = units.length
 
@@ -86,6 +87,7 @@ export default function Point(): UnitsRepresentation<PointProps> {
                 points = createPointRenderObject({
                     objectId: 0,
                     alpha,
+                    visible,
 
                     position: ValueCell.create(vertices),
                     id: ValueCell.create(fillSerial(new Float32Array(elementCount))),
diff --git a/src/mol-geo/representation/structure/spacefill.ts b/src/mol-geo/representation/structure/spacefill.ts
index a4b2c485182b94c3697c1ea67d06efaaa969f457..689f2bfc9bfe0bfac81346a6294d5ae2330e2620 100644
--- a/src/mol-geo/representation/structure/spacefill.ts
+++ b/src/mol-geo/representation/structure/spacefill.ts
@@ -23,7 +23,9 @@ import { icosahedronVertexCount } from '../../primitive/icosahedron';
 export const DefaultSpacefillProps = {
     detail: 0,
     colorTheme: { name: 'instance-index' } as ColorTheme,
-    alpha: 1
+    alpha: 1,
+    visible: true,
+    doubleSided: false
 }
 export type SpacefillProps = Partial<typeof DefaultSpacefillProps>
 
@@ -79,7 +81,7 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
             return Task.create('Spacefill.create', async ctx => {
                 renderObjects.length = 0 // clear
 
-                const { detail, colorTheme, alpha } = { ...DefaultSpacefillProps, ...props }
+                const { detail, colorTheme, alpha, visible, doubleSided } = { ...DefaultSpacefillProps, ...props }
 
                 await ctx.update('Computing spacefill mesh');
                 const mesh = await ctx.runChild(createSpacefillMesh(units[0], elementGroup, detail))
@@ -96,6 +98,8 @@ export default function Spacefill(): UnitsRepresentation<SpacefillProps> {
                 spheres = createMeshRenderObject({
                     objectId: 0,
                     alpha,
+                    visible,
+                    doubleSided,
 
                     position: mesh.vertexBuffer,
                     normal: mesh.normalBuffer as ValueCell<Float32Array>,
diff --git a/src/mol-geo/representation/volume/surface.ts b/src/mol-geo/representation/volume/surface.ts
index 2961c611c0971cec31c839c8169240a7677c75b5..a2de1a61d10cef902ee848ee9efb6ddab6572ead 100644
--- a/src/mol-geo/representation/volume/surface.ts
+++ b/src/mol-geo/representation/volume/surface.ts
@@ -36,6 +36,7 @@ export function computeVolumeSurface(volume: VolumeData, isoValue: VolumeIsoValu
 export const DefaultSurfaceProps = {
     isoValue: VolumeIsoValue.relative({ min: 0, max: 0, mean: 0, sigma: 0 }, 0),
     alpha: 0.5,
+    visible: true,
     flatShaded: true,
     flipSided: true,
     doubleSided: true
@@ -53,13 +54,17 @@ export default function Surface(): VolumeElementRepresentation<SurfaceProps> {
             return Task.create('Point.create', async ctx => {
                 renderObjects.length = 0 // clear
                 curProps = { ...DefaultSurfaceProps, ...props }
-                const { alpha, flatShaded, flipSided, doubleSided } = curProps
+                const { alpha, visible, flatShaded, flipSided, doubleSided } = curProps
 
                 const mesh = await ctx.runChild(computeVolumeSurface(volume, curProps.isoValue))
+                if (!flatShaded) {
+                    Mesh.computeNormalsImmediate(mesh)
+                }
 
                 surface = createMeshRenderObject({
                     objectId: 0,
                     alpha,
+                    visible,
 
                     position: mesh.vertexBuffer,
                     normal: mesh.normalBuffer,
diff --git a/src/mol-geo/shape/mesh.ts b/src/mol-geo/shape/mesh.ts
index fcd4ac207f5e8dfb879c3ecacdb4ef33d4525bd8..fcbb9c0f9f4bdf91acde9c734236d77e670a3222 100644
--- a/src/mol-geo/shape/mesh.ts
+++ b/src/mol-geo/shape/mesh.ts
@@ -8,7 +8,7 @@ import { Task } from 'mol-task'
 import { ValueCell } from 'mol-util'
 import { Vec3, Mat4 } from 'mol-math/linear-algebra'
 import { Sphere3D } from 'mol-math/geometry'
-import { transformPositionArray } from '../util';
+import { transformPositionArray/* , transformDirectionArray, getNormalMatrix */ } from '../util';
 
 export interface Mesh {
     /** Number of vertices in the mesh */
@@ -86,7 +86,12 @@ export namespace Mesh {
 
     export function transformRangeImmediate(mesh: Mesh, t: Mat4, offset: number, count: number) {
         transformPositionArray(t, mesh.vertexBuffer.ref.value, offset, count)
-        // transformDirectionArray(n, mesh.normalBuffer.ref.value, offset, count)  // TODO
+        // TODO normals transformation does not work for an unknown reason, ASR
+        // if (mesh.normalBuffer.ref.value) {
+        //     const n = getNormalMatrix(Mat3.zero(), t)
+        //     transformDirectionArray(n, mesh.normalBuffer.ref.value, offset, count)
+        //     mesh.normalsComputed = true;
+        // }
         mesh.normalsComputed = false;
         // mesh.boundingSphere = void 0;
     }
diff --git a/src/mol-geo/util.ts b/src/mol-geo/util.ts
index 0f417021677d1341368c68c8359b31c70873fe4d..ad2156c06c38cccc9ec3ae6b5b87745276785738 100644
--- a/src/mol-geo/util.ts
+++ b/src/mol-geo/util.ts
@@ -19,21 +19,28 @@ export function normalizeVec3Array<T extends Helpers.NumberArray> (a: T) {
     }
 }
 
-const tmpV = Vec3.zero()
+export function getNormalMatrix(out: Mat3, t: Mat4) {
+    Mat3.fromMat4(out, t)
+    Mat3.invert(out, out)
+    Mat3.transpose(out, out)
+    return out
+}
+
+const tmpV3 = Vec3.zero()
 
 export function transformPositionArray (t: Mat4, array: Helpers.NumberArray, offset: number, count: number) {
     for (let i = 0, il = count * 3; i < il; i += 3) {
-        Vec3.fromArray(tmpV, array, offset + i)
-        Vec3.transformMat4(tmpV, tmpV, t)
-        Vec3.toArray(tmpV, array, offset + i)
+        Vec3.fromArray(tmpV3, array, offset + i)
+        Vec3.transformMat4(tmpV3, tmpV3, t)
+        Vec3.toArray(tmpV3, array, offset + i)
     }
 }
 
 export function transformDirectionArray (n: Mat3, array: Helpers.NumberArray, offset: number, count: number) {
     for (let i = 0, il = count * 3; i < il; i += 3) {
-        Vec3.fromArray(tmpV, array, offset + i)
-        Vec3.transformMat3(tmpV, tmpV, n)
-        Vec3.toArray(tmpV, array, offset + i)
+        Vec3.fromArray(tmpV3, array, offset + i)
+        Vec3.transformMat3(tmpV3, tmpV3, n)
+        Vec3.toArray(tmpV3, array, offset + i)
     }
 }
 
diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts
index ff80f1218f50efd3be9b7b0de4c3f63c9e87152a..fc669697aacf4f56b162b01040528908c06e5507 100644
--- a/src/mol-gl/_spec/renderer.spec.ts
+++ b/src/mol-gl/_spec/renderer.spec.ts
@@ -51,6 +51,7 @@ function createPoints() {
     return createPointRenderObject({
         objectId: 0,
         alpha: 1.0,
+        visible: true,
 
         position,
         id,
diff --git a/src/mol-gl/renderable.ts b/src/mol-gl/renderable.ts
index fc4228d4b288483e1ffda04a2ce12310c9f229a1..d889f89c64a18487b75f82524ed125813dfec47e 100644
--- a/src/mol-gl/renderable.ts
+++ b/src/mol-gl/renderable.ts
@@ -8,6 +8,16 @@ import PointRenderable from './renderable/point'
 import MeshRenderable from './renderable/mesh'
 import { Program } from './webgl/program';
 
+export type BaseProps = {
+    objectId: number
+    alpha: number
+    visible: boolean
+
+    flatShaded?: boolean
+    doubleSided?: boolean
+    flipSided?: boolean
+}
+
 export interface Renderable<T> {
     draw: () => void
     name: string
diff --git a/src/mol-gl/renderable/mesh.ts b/src/mol-gl/renderable/mesh.ts
index 91d3e432921ae39e5083be49cec733dac261beaa..71ddafacecf8bb7affb5f2eba98debb8d004a066 100644
--- a/src/mol-gl/renderable/mesh.ts
+++ b/src/mol-gl/renderable/mesh.ts
@@ -7,7 +7,7 @@
 import { ValueCell } from 'mol-util/value-cell'
 import { ColorData } from 'mol-geo/util/color-data';
 
-import { Renderable } from '../renderable'
+import { Renderable, BaseProps } from '../renderable'
 import { getBaseDefs, getBaseValues, getBaseDefines } from './util'
 import { MeshShaderCode, addShaderDefines } from '../shader-code'
 import { Context } from '../webgl/context';
@@ -17,9 +17,6 @@ type Mesh = 'mesh'
 
 namespace Mesh {
     export type Props = {
-        objectId: number
-        alpha: number
-
         position: ValueCell<Float32Array>
         normal: ValueCell<Float32Array | undefined>
         id: ValueCell<Float32Array>
@@ -32,11 +29,7 @@ namespace Mesh {
         instanceCount: number
         elementCount: number
         positionCount: number
-
-        flatShaded?: boolean
-        doubleSided?: boolean
-        flipSided?: boolean
-    }
+    } & BaseProps
 
     export function create(ctx: Context, props: Props): Renderable<Props> {
         const defines = getBaseDefines(props)
diff --git a/src/mol-gl/renderable/point.ts b/src/mol-gl/renderable/point.ts
index f0d4b78e0c605432bef6083095c2a251c4d4052f..83b206dde577e0aad08a15f3b735334bfd9e7b4a 100644
--- a/src/mol-gl/renderable/point.ts
+++ b/src/mol-gl/renderable/point.ts
@@ -6,7 +6,7 @@
 
 import { ValueCell } from 'mol-util/value-cell'
 
-import { Renderable } from '../renderable'
+import { Renderable, BaseProps } from '../renderable'
 import { getBaseValues, getBaseDefs, getBaseDefines } from './util'
 import { PointShaderCode, addShaderDefines } from '../shader-code'
 import { ColorData } from 'mol-geo/util/color-data';
@@ -18,9 +18,6 @@ type Point = 'point'
 
 namespace Point {
     export type Props = {
-        objectId: number
-        alpha: number
-
         position: ValueCell<Float32Array>
         id: ValueCell<Float32Array>
 
@@ -33,7 +30,7 @@ namespace Point {
         positionCount: number,
 
         usePointSizeAttenuation?: boolean
-    }
+    } & BaseProps
 
     export function create<T = Props>(ctx: Context, props: Props): Renderable<Props> {
         const defines = getBaseDefines(props)
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index aea1cc8386a8f994b9f69f2beec6e3c8c6fd4b5b..5aa260f1248e25744c7a3d32da4624bb3e20da4c 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -69,8 +69,22 @@ namespace Renderer {
 
         let currentProgramId = -1
         const drawObject = (r: Renderable<any>, o: RenderObject) => {
-            if (o.visible) {
+            if (o.props.visible) {
                 if (currentProgramId !== r.program.id) {
+                    if (o.props.doubleSided) {
+                        gl.disable(gl.CULL_FACE)
+                    } else {
+                        gl.enable(gl.CULL_FACE)
+                    }
+
+                    if (o.props.flipSided) {
+                        gl.frontFace(gl.CW)
+                        gl.cullFace(gl.FRONT)
+                    } else {
+                        gl.frontFace(gl.CCW)
+                        gl.cullFace(gl.BACK)
+                    }
+
                     r.program.use()
                     r.program.setUniforms({
                         model,
diff --git a/src/mol-gl/scene.ts b/src/mol-gl/scene.ts
index 28789540a70daf65c75a0b7e14bbc44561637c07..5e7c91763c4f73f327bb51f8b35da1442da72c23 100644
--- a/src/mol-gl/scene.ts
+++ b/src/mol-gl/scene.ts
@@ -16,16 +16,16 @@ function getNextId() {
 
 export type RenderData = { [k: string]: ValueCell<Helpers.TypedArray> }
 
-export interface BaseRenderObject { id: number, type: string, props: {}, visible: boolean, transparent: boolean }
+export interface BaseRenderObject { id: number, type: string, props: {} }
 export interface MeshRenderObject extends BaseRenderObject { type: 'mesh', props: MeshRenderable.Props }
 export interface PointRenderObject extends BaseRenderObject { type: 'point', props: PointRenderable.Props }
 export type RenderObject = MeshRenderObject | PointRenderObject
 
 export function createMeshRenderObject(props: MeshRenderable.Props): MeshRenderObject {
-    return { id: getNextId(), type: 'mesh', props, visible: true, transparent: props.alpha < 1 }
+    return { id: getNextId(), type: 'mesh', props }
 }
 export function createPointRenderObject(props: PointRenderable.Props): PointRenderObject {
-    return { id: getNextId(), type: 'point', props, visible: true, transparent: props.alpha < 1 }
+    return { id: getNextId(), type: 'point', props }
 }
 
 export function createRenderable(ctx: Context, o: RenderObject) {
@@ -73,12 +73,12 @@ namespace Scene {
             },
             eachOpaque: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
                 renderableMap.forEach((r, o) => {
-                    if (!o.transparent) callbackFn(r, o)
+                    if (o.props.alpha === 1) callbackFn(r, o)
                 })
             },
             eachTransparent: (callbackFn: (value: Renderable<any>, key: RenderObject) => void) => {
                 renderableMap.forEach((r, o) => {
-                    if (o.transparent) callbackFn(r, o)
+                    if (o.props.alpha < 1) callbackFn(r, o)
                 })
             },
             get count() {
diff --git a/src/mol-gl/shader/mesh.frag b/src/mol-gl/shader/mesh.frag
index 513593c2c0c9e2d40334e2247ca86cd393a50925..9b4fb18cfbb799bfd4a0a9c794c041bb8a5824b4 100644
--- a/src/mol-gl/shader/mesh.frag
+++ b/src/mol-gl/shader/mesh.frag
@@ -48,10 +48,7 @@ void main() {
     #ifdef FLAT_SHADED
         vec3 fdx = dFdx(vViewPosition);
         vec3 fdy = dFdy(vViewPosition);
-        vec3 N = normalize(cross(fdx, fdy));
-        #ifdef FLIP_SIDED
-            N = -N;
-        #endif
+        vec3 N = -normalize(cross(fdx, fdy));
     #else
         vec3 N = -normalize(vNormal);
         #ifdef DOUBLE_SIDED
diff --git a/src/mol-gl/shader/mesh.vert b/src/mol-gl/shader/mesh.vert
index 4a8a196ac5324ca0bd41a114549868bd01066ff6..27ac8270222f783511e8b4da379a839f59df1352 100644
--- a/src/mol-gl/shader/mesh.vert
+++ b/src/mol-gl/shader/mesh.vert
@@ -39,8 +39,8 @@ void main(){
 
     #ifndef FLAT_SHADED
         mat3 normalMatrix = transpose(inverse(mat3(modelView)));
-        vec3 transformedNormal = normalize(normalMatrix * normal);
-        #ifdef FLIP_SIDED
+        vec3 transformedNormal = normalize(normalMatrix * normalize(normal));
+        #if defined(FLIP_SIDED) && !defined(DOUBLE_SIDED) // TODO checking DOUBLE_SIDED should not be required, ASR
             transformedNormal = -transformedNormal;
         #endif
         vNormal = transformedNormal;
diff --git a/src/mol-math/linear-algebra/3d/mat3.ts b/src/mol-math/linear-algebra/3d/mat3.ts
index bb2d47c5efbd2925ad82157164ccf199c4f54465..cd577776b23b29e6abbd21049ae009ce42ce3a50 100644
--- a/src/mol-math/linear-algebra/3d/mat3.ts
+++ b/src/mol-math/linear-algebra/3d/mat3.ts
@@ -179,6 +179,19 @@ namespace Mat3 {
         out[8] = (a11 * a00 - a01 * a10) * det;
         return out;
     }
+
+    export function determinant(a: Mat3) {
+        const a00 = a[0], a01 = a[1], a02 = a[2];
+        const a10 = a[3], a11 = a[4], a12 = a[5];
+        const a20 = a[6], a21 = a[7], a22 = a[8];
+
+        const b01 = a22 * a11 - a12 * a21;
+        const b11 = -a22 * a10 + a12 * a20;
+        const b21 = a21 * a10 - a11 * a20;
+
+        // Calculate the determinant
+        return a00 * b01 + a01 * b11 + a02 * b21;
+    }
 }
 
 export default Mat3
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/vec4.ts b/src/mol-math/linear-algebra/3d/vec4.ts
index f481cf99d7224a0356b14eb827934f4b635dbb2f..54e2cda220efba0d36d0eaed13867cd9f820c55c 100644
--- a/src/mol-math/linear-algebra/3d/vec4.ts
+++ b/src/mol-math/linear-algebra/3d/vec4.ts
@@ -62,6 +62,20 @@ namespace Vec4 {
         return a
     }
 
+    export function toVec3Array(a: Vec4, out: Helpers.NumberArray, offset: number) {
+        out[offset + 0] = a[0];
+        out[offset + 1] = a[1];
+        out[offset + 2] = a[2];
+    }
+
+    export function fromVec3Array(a: Vec4, array: Helpers.NumberArray, offset: number) {
+        a[0] = array[offset + 0]
+        a[1] = array[offset + 1]
+        a[2] = array[offset + 2]
+        a[3] = 0
+        return a
+    }
+
     export function copy(out: Vec4, a: Vec4) {
         out[0] = a[0];
         out[1] = a[1];
diff --git a/src/mol-view/viewer.ts b/src/mol-view/viewer.ts
index 54a908c04b77f1c801dd93b806f6eccc0d56e0c9..4e8d9c26230f39a4407a14e79c137811f6bb9cb2 100644
--- a/src/mol-view/viewer.ts
+++ b/src/mol-view/viewer.ts
@@ -106,11 +106,11 @@ namespace Viewer {
         return {
             hide: (repr: Representation<any>) => {
                 const renderObjectSet = reprMap.get(repr)
-                if (renderObjectSet) renderObjectSet.forEach(o => o.visible = false)
+                if (renderObjectSet) renderObjectSet.forEach(o => o.props.visible = false)
             },
             show: (repr: Representation<any>) => {
                 const renderObjectSet = reprMap.get(repr)
-                if (renderObjectSet) renderObjectSet.forEach(o => o.visible = true)
+                if (renderObjectSet) renderObjectSet.forEach(o => o.props.visible = true)
             },
 
             add: (repr: Representation<any>) => {