diff --git a/examples/DecodeOnGPU/CMakeLists.txt b/examples/DecodeOnGPU/CMakeLists.txt
index fb298715..07f87101 100644
--- a/examples/DecodeOnGPU/CMakeLists.txt
+++ b/examples/DecodeOnGPU/CMakeLists.txt
@@ -44,12 +44,13 @@ LINK_DIRECTORIES(${PolyVoxCore_BINARY_DIR})
#This will include the shader files inside the compiled binary
QT4_ADD_RESOURCES(COMMON_RESOURCES_RCC ../common/example.qrc)
+QT4_ADD_RESOURCES(DECODE_RESOURCES_RCC decode.qrc)
# Put the resources in a seperate folder in Visual Studio
-SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC})
+SOURCE_GROUP("Resource Files" FILES ../common/example.qrc ${COMMON_RESOURCES_RCC} decode.qrc ${DECODE_RESOURCES_RCC})
#Build
-ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC})
+ADD_EXECUTABLE(DecodeOnGPUExample ${SRC_FILES} ${COMMON_RESOURCES_RCC} ${DECODE_RESOURCES_RCC})
IF(MSVC)
SET_TARGET_PROPERTIES(DecodeOnGPUExample PROPERTIES COMPILE_FLAGS "/W4 /wd4127")
ENDIF(MSVC)
diff --git a/examples/DecodeOnGPU/decode.frag b/examples/DecodeOnGPU/decode.frag
new file mode 100644
index 00000000..c9cbf215
--- /dev/null
+++ b/examples/DecodeOnGPU/decode.frag
@@ -0,0 +1,19 @@
+#version 130
+
+// Passed in from the vertex shader
+in vec4 worldPosition;
+in vec4 worldNormal;
+
+// the color that gets written to the display
+out vec4 outputColor;
+
+void main()
+{
+ // Again, for the purposes of these examples we cannot be sure that per-vertex normals are provided. A sensible fallback
+ // is to use this little trick to compute per-fragment flat-shaded normals from the world positions using derivative operations.
+ vec3 normal = normalize(cross(dFdy(worldPosition.xyz), dFdx(worldPosition.xyz)));
+
+ // We are just using the normal as the output color, and making it lighter so it looks a bit nicer.
+ // Obviously a real shader would also do texuring, lighting, or whatever is required for the application.
+ outputColor = vec4(abs(normal) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
+}
diff --git a/examples/DecodeOnGPU/decode.qrc b/examples/DecodeOnGPU/decode.qrc
new file mode 100644
index 00000000..f29bc1ad
--- /dev/null
+++ b/examples/DecodeOnGPU/decode.qrc
@@ -0,0 +1,6 @@
+
+
+ decode.vert
+ decode.frag
+
+
diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert
new file mode 100644
index 00000000..94d35f44
--- /dev/null
+++ b/examples/DecodeOnGPU/decode.vert
@@ -0,0 +1,20 @@
+#version 140
+
+in vec4 position; // This will be the position of the vertex in model-space
+
+// The usual matrices are provided
+uniform mat4 cameraToClipMatrix;
+uniform mat4 worldToCameraMatrix;
+uniform mat4 modelToWorldMatrix;
+
+// This will be used by the fragment shader to calculate flat-shaded normals. This is an unconventional approach
+// but we use it in this example framework because not all surface extractor generate surface normals.
+out vec4 worldPosition;
+
+void main()
+{
+ // Standard sequence of OpenGL transformations.
+ worldPosition = modelToWorldMatrix * position;
+ vec4 cameraPosition = worldToCameraMatrix * worldPosition;
+ gl_Position = cameraToClipMatrix * cameraPosition;
+}
diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp
index 83950b1b..3a36fd48 100644
--- a/examples/DecodeOnGPU/main.cpp
+++ b/examples/DecodeOnGPU/main.cpp
@@ -125,6 +125,22 @@ int main(int argc, char *argv[])
OpenGLWidget openGLWidget(0);
openGLWidget.show();
+ QSharedPointer shader(new QGLShaderProgram);
+
+ if (!shader->addShaderFromSourceFile(QGLShader::Vertex, ":/decode.vert"))
+ {
+ std::cerr << shader->log().toStdString() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag"))
+ {
+ std::cerr << shader->log().toStdString() << std::endl;
+ exit(EXIT_FAILURE);
+ }
+
+ openGLWidget.setShader(shader);
+
//Create an empty volume and then place a sphere in it
SimpleVolume volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
createSphereInVolume(volData, 30);