Index: include/irender.h
===================================================================
--- include/irender.h	(revision 6254)
+++ include/irender.h	(working copy)
@@ -337,6 +337,19 @@
 
 	/**
      * \brief
+     * Test if the the given shader is able to be captured.
+	 * Return true if the given shader is available.
+	 *
+	 * @param name
+	 * The name of the shader to test capture.
+	 *
+	 * @returns
+	 * bool, true if the shader is available.
+	 */
+	virtual bool canCapture(const std::string& name) = 0;
+
+	/**
+     * \brief
      * Capture the given shader, increasing its reference count and
 	 * returning a pointer to the Shader object.
      *
Index: plugins/model/RenderablePicoSurface.cpp
===================================================================
--- plugins/model/RenderablePicoSurface.cpp	(revision 6254)
+++ plugins/model/RenderablePicoSurface.cpp	(working copy)
@@ -22,47 +22,35 @@
 	// Get the shader from the picomodel struct. If this is a LWO model, use
 	// the material name to select the shader, while for an ASE model the
 	// bitmap path should be used.
-    picoShader_t* shader = PicoGetSurfaceShader(surf);
-    if (shader != 0) {
+	picoShader_t* shader = PicoGetSurfaceShader(surf);
+	std::string rawName = "";
+	if (shader != 0) {
 		if (fExt == "lwo")
-        {
-	    	_originalShaderName = PicoGetShaderName(shader);
+		{
+			_originalShaderName = PicoGetShaderName(shader);
 		}
 		else if (fExt == "ase")
-        {
+		{
+			rawName = PicoGetShaderName(shader);
 			std::string rawMapName = PicoGetShaderMapName(shader);
-			boost::algorithm::replace_all(rawMapName, "\\", "/");
+			_originalShaderName = cleanupShaderName(rawMapName);
+		}
+	}
 
-			// Take off the everything before "base/", and everything after
-			// the first period if it exists (i.e. strip off ".tga")
-			std::size_t basePos = rawMapName.find("base");
+	// If shader not found, fallback to alternative if available
+	// _originalShaderName is empty if the ase material has no BITMAP
+	// canCapture is false if _originalShaderName is not a valid shader
+	if((_originalShaderName.empty() ||
+		!GlobalRenderSystem().canCapture(_originalShaderName)) &&
+		!rawName.empty()) {
+		_originalShaderName = cleanupShaderName(rawName);
+	}
 
-			if (basePos != std::string::npos && basePos > 0)
-			{
-				std::size_t dotPos = rawMapName.find(".");
+	_mappedShaderName = _originalShaderName;
 
-				if (dotPos != std::string::npos)
-				{
-					_originalShaderName = rawMapName.substr(basePos + 5,
-															dotPos - basePos - 5);
-				}
-				else
-				{
-					_originalShaderName = rawMapName.substr(basePos + 5);
-				}
-			}
-			else {
-				// Unrecognised shader path
-				_originalShaderName = "";
-			}
-		}
-    }
+	// Capture the shader
+	_shader = GlobalRenderSystem().capture(_mappedShaderName);
 
-    _mappedShaderName = _originalShaderName; // no skin at this time
-
-    // Capture the shader
-    _shader = GlobalRenderSystem().capture(_originalShaderName);
-
     // Get the number of vertices and indices, and reserve capacity in our
     // vectors in advance by populating them with empty structs.
     int nVerts = PicoGetSurfaceNumVertexes(surf);
@@ -99,6 +87,47 @@
 	createDisplayLists();
 }
 
+std::string RenderablePicoSurface::cleanupShaderName(std::string mapName) {
+	const std::string baseFolder = "base";	//FIXME: should be from game.xml
+	std::size_t basePos;
+
+	boost::algorithm::replace_all(mapName, "\\", "/");
+
+	// for paths given relative, start from the beginning
+	if(mapName.substr(0,6) == "models" || mapName.substr(0,8) == "textures")
+	{
+		basePos = 0;
+	}
+	else
+	{
+		// Take off the everything before "base/", and everything after
+		// the first period if it exists (i.e. strip off ".tga")
+		basePos = mapName.find(baseFolder);
+		if (basePos == std::string::npos || basePos < 0)
+		{
+			// Unrecognised shader path, no base folder.
+			// Try the original incase it was already given relative.
+			basePos = 0;
+		}
+		else
+		{
+			// Increment for for the length of "base/", the / is the +1
+			basePos += (baseFolder.size() + 1);
+		}
+	}
+
+	std::size_t dotPos = mapName.find(".");
+
+	if (dotPos != std::string::npos)
+	{
+		return mapName.substr(basePos, dotPos - basePos);
+	}
+	else
+	{
+		return mapName.substr(basePos);
+	}
+}
+
 // Destructor. Release the GL display lists.
 RenderablePicoSurface::~RenderablePicoSurface()
 {
Index: plugins/model/RenderablePicoSurface.h
===================================================================
--- plugins/model/RenderablePicoSurface.h	(revision 6254)
+++ plugins/model/RenderablePicoSurface.h	(working copy)
@@ -71,6 +71,8 @@
     GLuint compileProgramList(ShaderLayer::VertexColourMode);
 	void createDisplayLists();
 
+	std::string RenderablePicoSurface::cleanupShaderName(std::string mapName);
+
 public:
 	/**
 	 * Constructor. Accepts a picoSurface_t struct and the file extension to determine
Index: radiant/render/OpenGLRenderSystem.cpp
===================================================================
--- radiant/render/OpenGLRenderSystem.cpp	(revision 6254)
+++ radiant/render/OpenGLRenderSystem.cpp	(working copy)
@@ -59,6 +59,12 @@
 	}
 }
 
+/* Test if the this can capture the given shader.
+ */
+bool OpenGLRenderSystem::canCapture(const std::string& name) {
+	return (_shaders.find(name) != _shaders.end());
+}
+
 /* Capture the given shader.
  */
 ShaderPtr OpenGLRenderSystem::capture(const std::string& name) {
Index: radiant/render/OpenGLRenderSystem.h
===================================================================
--- radiant/render/OpenGLRenderSystem.h	(revision 6254)
+++ radiant/render/OpenGLRenderSystem.h	(working copy)
@@ -50,6 +50,7 @@
 
     /* RenderSystem implementation */
 
+	bool canCapture(const std::string& name);
 	ShaderPtr capture(const std::string& name);
 	void render(RenderStateFlags globalstate,
 				const Matrix4& modelview,
