diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7bfe21baf6c1df64348b398bcffe157799ab0099..d90b88869732842120194b2064b76ec555727daa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ Note that since we don't clearly distinguish between a public and private interf
 
 - Fix parsing contour-level from emdb v3 header files
 - Fix invalid CSS (#376)
+- Fix "texture not renderable" & "texture not bound" warnings (#319)
 
 ## [v3.2.0] - 2022-02-17
 
diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts
index 265afff169d639fc10e5c4ecb7e68b0c4a2773c2..13fe3cfef25bb6ca3ab6c620b23ebcd51a4bac26 100644
--- a/src/mol-gl/renderer.ts
+++ b/src/mol-gl/renderer.ts
@@ -16,7 +16,7 @@ import { GlobalUniformValues } from './renderable/schema';
 import { GraphicsRenderVariant } from './webgl/render-item';
 import { ParamDefinition as PD } from '../mol-util/param-definition';
 import { degToRad } from '../mol-math/misc';
-import { createNullTexture, Texture, Textures } from './webgl/texture';
+import { Texture, Textures } from './webgl/texture';
 import { arrayMapUpsert } from '../mol-util/array';
 import { clamp } from '../mol-math/interpolate';
 
@@ -146,9 +146,9 @@ namespace Renderer {
 
         let transparentBackground = false;
 
-        const nullDepthTexture = createNullTexture(gl);
+        const emptyDepthTexture = ctx.resources.texture('image-depth', 'depth', 'ushort', 'nearest');
         const sharedTexturesList: Textures = [
-            ['tDepth', nullDepthTexture]
+            ['tDepth', emptyDepthTexture]
         ];
 
         const view = Mat4();
@@ -309,7 +309,7 @@ namespace Renderer {
         };
 
         const updateInternal = (group: Scene.Group, camera: ICamera, depthTexture: Texture | null, renderWboit: boolean, markingDepthTest: boolean) => {
-            arrayMapUpsert(sharedTexturesList, 'tDepth', depthTexture || nullDepthTexture);
+            arrayMapUpsert(sharedTexturesList, 'tDepth', depthTexture || emptyDepthTexture);
 
             ValueCell.update(globalUniforms.uModel, group.view);
             ValueCell.update(globalUniforms.uModelView, Mat4.mul(modelView, group.view, camera.view));
diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts
index 93f654581a728e1ca1438d219d7b4f43707feab1..7d58ef1da7dddb08823a42aa1e54d663f1186cf3 100644
--- a/src/mol-gl/webgl/texture.ts
+++ b/src/mol-gl/webgl/texture.ts
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -176,7 +176,7 @@ function isTexture2d(x: TextureImage<any> | TextureVolume<any>, target: number,
     return target === gl.TEXTURE_2D;
 }
 
-function isTexture3d(x: TextureImage<any> | TextureVolume<any>, target: number, gl: WebGL2RenderingContext): x is TextureImage<any> {
+function isTexture3d(x: TextureImage<any> | TextureVolume<any>, target: number, gl: WebGL2RenderingContext): x is TextureVolume<any> {
     return target === gl.TEXTURE_3D;
 }
 
@@ -260,6 +260,10 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension
     let destroyed = false;
 
     function define(_width: number, _height: number, _depth?: number) {
+        if (_width === 0 || _height === 0 || (isWebGL2(gl) && target === gl.TEXTURE_3D && _depth === 0)) {
+            throw new Error('empty textures are not allowed');
+        }
+
         if (width === _width && height === _height && depth === (_depth || 0)) return;
 
         width = _width, height = _height, depth = _depth || 0;
@@ -272,14 +276,20 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension
             throw new Error('unknown texture target');
         }
     }
+    define(1, 1, isWebGL2(gl) && target === gl.TEXTURE_3D ? 1 : 0);
 
     function load(data: TextureImage<any> | TextureVolume<any> | HTMLImageElement, sub = false) {
+        if (data.width === 0 || data.height === 0 || (!isImage(data) && isWebGL2(gl) && isTexture3d(data, target, gl) && data.depth === 0)) {
+            throw new Error('empty textures are not allowed');
+        }
+
         gl.bindTexture(target, texture);
         // unpack alignment of 1 since we use textures only for data
         gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
         gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE);
         gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0);
         if (isImage(data)) {
+            width = data.width, height = data.height;
             gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
             gl.bindTexture(gl.TEXTURE_2D, texture);
             gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, format, type, data);