diff --git a/README.md b/README.md
index 8e735931b28917791b68f64eb0f369de7953d403..4b8c16abd2308f65f6f3503cbe9ee4d1ac87fb94 100644
--- a/README.md
+++ b/README.md
@@ -85,10 +85,11 @@ used in the following projects :
 
 ## Authors:
 * Florent Berthaut, Assistant Professor, Université de Lille, CRIStAL/MINT
-        florent_DOT_berthaut_AT_univ-lille_DOT_fr
-* Alan Menit alanmenit_AT_gmail_DOT_com
+	(https://pro.univ-lille.fr/florent-berthaut)
+* Alan Menit
 * Boris Legal
 * Anthony Beuchey
 * Cagan Arslan
+* Luka Claeys
 
 
diff --git a/src/Reveal.cpp b/src/Reveal.cpp
index 44c7273a730e1dd7a933c19bcb5f3be356da81d4..9e8e981fb7783c09404e0acaeaac295fa9ca7b08 100644
--- a/src/Reveal.cpp
+++ b/src/Reveal.cpp
@@ -60,6 +60,7 @@
 #include "osc/OscManager.hpp"
 #include "osc/OscListener.hpp"
 
+
 using namespace std;
 
 Reveal* Reveal::getInstance() {
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..16c294169c63ae5bff9f3e96e678f944a4ce9ee6
--- /dev/null
+++ b/src/audio/AudioManager.cpp
@@ -0,0 +1,146 @@
+/***************************************************************************
+ *	AudioManager.cpp
+ *	Part of Rivill
+ *	2015-  Florent Berthaut / Luka Claeys
+ *	https://gitlab.univ-lille.fr/mint/rivill
+ ****************************************************************************/
+/*
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "AudioManager.hpp"
+
+void* audioThreadFunction(void* pvParam) {
+    AudioManager *pThis=(AudioManager*)pvParam;
+    RtAudio *audio = pThis->audio;
+    audio->startStream();
+    return 0;
+}
+
+AudioManager* AudioManager::getInstance() {
+    static AudioManager rev;
+    return &rev;
+}
+
+AudioManager::~AudioManager() {}
+
+int AudioManager::getRate(){
+    return data.nRate;
+}
+
+int AudioManager::getBufferSize(){
+    return buf;
+}
+
+int AudioManager::getMixSize(){
+    return data.mixSize;
+}
+
+static int rtaudio_callback(void *outbuf, void *inbuf, unsigned int nFrames, double streamtime, RtAudioStreamStatus	status, void *userdata){
+    (void)inbuf;
+	float *buf = (float*)outbuf;
+    CallbackData *data = (CallbackData*) userdata;
+    unsigned int i = 0;
+    int j = 0;
+    int audioIndex = 0;
+
+    //check if there is audio value to play
+    if(ringbuffer_read_space(data->audioBuf) > 2*(nFrames + data->mixSize)){//!=0){
+		
+        //read the audio values
+        ringbuffer_read(data->audioBuf, data->audio, nFrames + data->mixSize);
+
+        //put the values to play in the audio buffer
+		while(i < nFrames * data->nChannel) {
+			if(j < data->mixSize){
+				buf[i] = data->audio[j] + data->mix[j];
+				buf[i+1] = data->audio[j] + data->mix[j];
+				
+			}
+			else{
+				buf[i] = data->audio[j];
+				buf[i+1] = data->audio[j];
+			}
+			audioIndex += 1;
+			j += 1;
+			i += 2;
+		}
+		//save the value for the next crossfading
+		memcpy(&data->mix[0], data->audio + nFrames, data->mixSize*sizeof(float));
+    }
+	return 0;
+}
+
+AudioManager::AudioManager(){
+    buf = 4096;
+    audio = new RtAudio(RtAudio::LINUX_PULSE);
+    param = new RtAudio::StreamParameters();
+    param->deviceId = audio->getDefaultOutputDevice();
+    param->nChannels = 2;
+
+    audio->openStream(param, NULL, RTAUDIO_FLOAT32, 44100, &buf, rtaudio_callback, &data);
+
+	data.mixSize = 100;
+    data.nRate = audio->getDeviceInfo(param->deviceId).preferredSampleRate;
+    data.nChannel = param->nChannels;
+    data.ratioSampleFreq = data.nRate/440.0;
+    data.ratioFreqSample = 1.0/data.ratioSampleFreq;
+    size_t size = 10 * buf;
+    data.audioBuf = ringbuffer_create(size);
+
+    data.audio = new float[buf + data.mixSize];
+    data.mix = new float[data.mixSize];
+    memset(&data.mix[0], 0, data.mixSize*4);
+    audioValue = new float[buf + data.mixSize];
+    m_thread = new std::thread(audioThreadFunction, this);
+
+
+}
+
+
+void AudioManager::changeBuf(float* outputBuf, float maxSinValue){      
+          
+	//check if there is space to write the new values
+    //if not, move write_ptr of both ringbuffer size index back
+    size_t write_space = ringbuffer_write_space(data.audioBuf);
+    if(write_space >= (buf+data.mixSize)){//!= 0){
+		float phase = 0;
+		float pas = 1.0/float(data.mixSize);
+						
+		//fill the audioValue array with the audio value
+		for(int i=0; i < int(buf); i++){
+			if(i < data.mixSize){
+				audioValue[i] = outputBuf[i]*phase;
+				phase += pas;
+			}
+			else{
+				audioValue[i] = outputBuf[i];
+			}
+			
+		}
+
+		//pas = 1/data.mixSize;	
+		//fill the audioValue array with the values for the next crossfading
+		for(int i=0; i < data.mixSize; i++){
+			audioValue[buf + i] = outputBuf[buf + i]*phase;
+			phase -= pas;
+		}
+		constAudioValue = const_cast<const float *>(audioValue);
+				
+		ringbuffer_write(data.audioBuf, constAudioValue, buf + data.mixSize);	
+	}
+}
+
+
diff --git a/src/audio/AudioManager.hpp b/src/audio/AudioManager.hpp
index ead8896e254322cd5d57d0f00d5f351516e347c0..f67d62a5c41b7ea10ec74dc470a6e0dc7e7c5e58 100644
--- a/src/audio/AudioManager.hpp
+++ b/src/audio/AudioManager.hpp
@@ -1,8 +1,8 @@
 /***************************************************************************
  *	AudioManager.hpp
- *	Part of Revil
- *	2015-  Florent Berthaut
- *	hitmuri.net
+ *	Part of Rivill
+ *	2015-  Florent Berthaut / Luka Claeys
+ *	https://gitlab.univ-lille.fr/mint/rivill
  ****************************************************************************/
 /*
  *	This program is free software; you can redistribute it and/or modify
@@ -20,22 +20,69 @@
  *	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
 
-#include <portaudio.h>
+#include <rtaudio/RtAudio.h>
+#include <cstring>
+#include <math.h>
+#include <unistd.h>
+#include <mutex>
+#include <thread>
+#include <queue>
 
+#include <iostream>
+#include <fstream>
+using namespace std;
 
-#ifndef OscManager_h
-#define OscManager_h
+#include <sys/time.h>
+#include "Ringbuffer.hpp"
+
+
+#ifndef AudioManager_h
+#define AudioManager_h
+
+//#define POWER32 pow(2,31)
+
+static std::mutex mtx_audio;
+
+typedef struct {
+    unsigned int	nRate;		/* Sampling Rate (sample/sec) */
+    unsigned int	nChannel;	/* Channel Number */
+	float ratioSampleFreq;		/* Ratio between the sample frequence and the signal frequency  */
+	float ratioFreqSample;		/* Ratio between the signal frequency and the sample frequence */
+	int mixSize;				/* the number of values to crossfade */
+	ringbuffer *mixBuf;			/* ringbuffer with the value for the crossfading */
+	ringbuffer *audioBuf;		/* ringbuffer with the value for audio render */
+	float *audio; 				/* buffer to save the current audio value */
+	float *mix;					/* buffer to save the mix value */
+} CallbackData;
+
+static int rtaudio_callback(void *outbuf, void *inbuf, unsigned int nFrames, double streamtime, RtAudioStreamStatus	status, void *userdata);
 
 class AudioManager {
+	public:
+		RtAudio *audio;
+		RtAudio::StreamParameters *param;
+		unsigned int buf;  //the size of the audio buffer
+		CallbackData data; //the audio data structure
+		pthread_t t;
+		
+
 	public:
 		static AudioManager* getInstance();
 		~AudioManager();
+		void changeBuf(float* outputBuf, float maxSinValue);
+		int getRate();
+		int getBufferSize();
+		int getMixSize();
 
 
 	private:
-		AudioManager(){}
+		std::thread* m_thread;
+		AudioManager();
+		float * audioValue;			  //array to save the audio value before writing
+		const float *constAudioValue; //array to write the audio value in the ringbuffer
+		
 
-}
+};
 
 #endif
 
diff --git a/src/audio/Ringbuffer.cpp b/src/audio/Ringbuffer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a0103fbc3ff63f3a64b0892218413f86c4d2908
--- /dev/null
+++ b/src/audio/Ringbuffer.cpp
@@ -0,0 +1,264 @@
+#include "Ringbuffer.hpp"
+#include <iostream>
+ringbuffer* ringbuffer_create(size_t sz){
+    int power_of_two;
+    ringbuffer* rb;
+    rb = (ringbuffer*) malloc(sizeof(ringbuffer));
+
+    if(rb == NULL){
+        return NULL;
+    }
+
+    //for(power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
+    rb->size = sz;//1 << power_of_two;
+    rb->size_mask = rb->size;
+    rb->write_ptr = 0;
+    rb->read_ptr = 0;
+    rb->buf = (float *) malloc (rb->size * sizeof(float));
+	if(rb->buf == NULL) {
+	    free (rb);
+	    return NULL;
+    }
+    memset(rb->buf, 0, rb->size * sizeof(float));
+
+	rb->mlocked = 0;
+	rb->writed = 0;
+	
+	return rb;
+}
+
+void ringbuffer_free(ringbuffer *rb){
+    free(rb->buf);
+    free(rb);
+}
+
+int ringbuffer_mlock(ringbuffer *rb){
+    rb->mlocked = 1;
+    return 0;
+}
+
+void ringbuffer_reset(ringbuffer *rb){
+    rb->read_ptr = 0;
+    rb->write_ptr = 0;
+    memset(rb->buf, 0, rb->size);
+}
+
+void ringbuffer_reset_size(ringbuffer *rb, size_t sz){
+    rb->size = sz;
+    rb->size_mask = rb->size;
+    //rb->size_mask -= 1;
+    rb->read_ptr = 0;
+    rb->write_ptr = 0;
+}
+
+size_t ringbuffer_read_space(const ringbuffer *rb){
+    size_t w,r;
+
+    w = rb->write_ptr;
+    r = rb->read_ptr;
+
+    if(w>r){
+        return w - r;
+    }
+    else if(w==r){
+		if(rb->writed){
+			return rb->size;
+		}
+		else{
+			return 0;
+		}
+        //return (w - r + rb->size) & rb->size_mask;
+    }
+    else{
+		return rb->size - (r - w);
+	}
+}
+
+size_t ringbuffer_get_write_vector(const ringbuffer *rb){
+    size_t w, r;
+
+	w = rb->write_ptr;
+	r = rb->read_ptr;
+
+	if (w > r) {
+		return ((r - w + rb->size) & rb->size_mask) - 1;
+	} else if (w < r) {
+		return (r - w) - 1;
+	} else {
+		return rb->size - 1;
+	}
+}
+
+size_t ringbuffer_read(ringbuffer *rb, float *dest, size_t cnt){
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_read;
+    size_t n1,n2;
+
+    free_cnt = ringbuffer_read_space(rb);
+    //std::cout<<free_cnt<<std::endl;
+    if(free_cnt == 0){
+        return 0;
+    }
+    
+    if(free_cnt < cnt){
+		to_read = free_cnt;
+	}
+	else{
+		to_read = cnt;
+	}
+	
+    //to_read = cnt > free_cnt ? free_cnt : cnt;
+    cnt2 = rb->read_ptr + to_read;
+
+    if(cnt2 > rb->size){
+        n1 = rb->size - rb->read_ptr;
+        n2 = to_read - n1;//cnt2 & rb->size_mask;
+    }
+    else{
+        n1 = to_read;
+        n2 = 0;
+    }
+    
+    memcpy(dest, &(rb->buf[rb->read_ptr]), n1*sizeof(float));
+
+    //rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
+    rb->read_ptr = rb->read_ptr + n1;
+    if(rb->read_ptr >= rb->size){
+		rb->read_ptr = rb->read_ptr - rb->size;
+	} 
+
+    if(n2){
+        memcpy(dest + n1, &(rb->buf[rb->read_ptr]), n2*sizeof(float));
+        //rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
+        rb->read_ptr = rb->read_ptr + n2;
+		if(rb->read_ptr >= rb->size){
+			rb->read_ptr = rb->read_ptr - rb->size;
+		}
+    }
+    
+    if(rb->read_ptr == rb->write_ptr){
+		rb->writed = 0;
+	}
+
+    return to_read;
+}
+
+size_t ringbuffer_write_space (const ringbuffer * rb)
+{
+	size_t w, r;
+
+	w = rb->write_ptr;
+	r = rb->read_ptr;
+
+	if (w > r) {
+		return rb->size -(w - r);
+		//return ((r - w + rb->size) & rb->size_mask) - 1;
+	} else if (w < r) {
+		return (r - w);// - 1;
+	} else {
+		if(!(rb->writed)){
+			return rb->size;
+		}
+		else{
+			return 0;//rb->size - 1;
+		}
+	}
+}
+
+size_t ringbuffer_peek(ringbuffer *rb, float *dest, size_t cnt){
+    size_t free_cnt;
+	size_t cnt2;
+	size_t to_read;
+	size_t n1, n2;
+	size_t tmp_read_ptr;
+
+	tmp_read_ptr = rb->read_ptr;
+    free_cnt = ringbuffer_read_space(rb);
+	if (free_cnt == 0) {
+		return 0;
+	}
+
+	to_read = cnt > free_cnt ? free_cnt : cnt;
+
+	cnt2 = tmp_read_ptr + to_read;
+
+	if (cnt2 > rb->size) {
+		n1 = rb->size - tmp_read_ptr;
+		n2 = cnt2 & rb->size_mask;
+	} else {
+		n1 = to_read;
+		n2 = 0;
+	}
+
+	memcpy(dest, &(rb->buf[tmp_read_ptr]), n1);
+	tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
+
+	if (n2) {
+		memcpy(dest + n1, &(rb->buf[tmp_read_ptr]), n2);
+	}
+
+	return to_read;
+}
+
+size_t ringbuffer_write(ringbuffer *rb, const float *src, size_t cnt){
+    size_t free_cnt;
+	size_t cnt2;
+	size_t to_write;
+	size_t n1, n2;
+
+    free_cnt = ringbuffer_write_space(rb);
+	if (free_cnt == 0) {
+		return 0;
+	}
+	
+	if(free_cnt < cnt){
+		to_write = free_cnt;
+	}
+	else{
+		to_write = cnt;
+	}
+	//to_write = cnt > free_cnt ? free_cnt : cnt;
+
+	cnt2 = rb->write_ptr + to_write;
+
+	if (cnt2 > rb->size) {
+		n1 = rb->size - rb->write_ptr;
+		n2 = to_write - n1;//cnt2 & rb->size_mask;
+	} else {
+		n1 = to_write;
+		n2 = 0;
+	}
+
+	memcpy(&(rb->buf[rb->write_ptr]), src, n1*sizeof(float));
+	//rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
+	rb->write_ptr = rb->write_ptr + n1;
+
+    if(rb->write_ptr >= rb->size){
+		rb->write_ptr = rb->write_ptr - rb->size;
+	}
+
+
+	if(n2){
+		memcpy(&(rb->buf[rb->write_ptr]), src + n1, n2*sizeof(float));
+		//rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
+		rb->write_ptr = rb->write_ptr + n2;
+		if(rb->write_ptr >= rb->size){
+			rb->write_ptr = rb->write_ptr - rb->size;
+		}
+	}
+
+	rb->writed = 1;
+	return to_write;
+}
+
+void ringbuffer_read_advance(ringbuffer *rb, size_t cnt){
+    size_t temp = (rb->read_ptr + cnt) & rb->size_mask;
+    rb->read_ptr = temp;
+}
+
+void ringbuffer_write_advance(ringbuffer *rb, size_t cnt){
+    size_t temp = (rb->write_ptr + cnt) & rb->size_mask;
+    rb->write_ptr = temp;
+}
+
diff --git a/src/audio/Ringbuffer.hpp b/src/audio/Ringbuffer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f4a298c9b93097897f7727c9ae4aa603b48f5ec
--- /dev/null
+++ b/src/audio/Ringbuffer.hpp
@@ -0,0 +1,35 @@
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+typedef struct
+{
+    float *buf;
+    size_t len;
+} ringbuffer_data;
+
+typedef struct
+{
+    float* buf;
+    volatile size_t write_ptr;
+    volatile size_t read_ptr;
+    size_t size;
+    size_t size_mask;
+    int mlocked;
+    int writed;
+}ringbuffer;
+
+ringbuffer *ringbuffer_create(size_t size);
+void ringbuffer_free(ringbuffer *rb);
+size_t ringbuffer_read(ringbuffer *rb, float *dest, size_t cnt);
+size_t ringbuffer_peek(ringbuffer *rb, float *dest, size_t cnt);
+void ringbuffer_read_advance(ringbuffer *rb, size_t cnt);
+size_t ringbuffer_read_space(const ringbuffer *rb);
+int ringbuffer_mlock(ringbuffer *rb);
+void ringbuffer_reset(ringbuffer *rb);
+void ringbuffer_reset_size (ringbuffer * rb, size_t sz);
+size_t ringbuffer_write(ringbuffer *rb, const float *src, size_t cnt);
+void ringbuffer_write_advance(ringbuffer *rb, size_t cnt);
+size_t ringbuffer_write_space(const ringbuffer *rb);
+
diff --git a/src/modules/DepthCamModule.hpp b/src/modules/DepthCamModule.hpp
index ac9ee78a97cf1b0a947fd87a3483d0943f00f44f..9fcae7e5d2e51e307acb169dc925f13a27e2aa45 100644
--- a/src/modules/DepthCamModule.hpp
+++ b/src/modules/DepthCamModule.hpp
@@ -33,7 +33,7 @@
 #include <mutex>
 
 #include <OpenNI.h>
-#include <opencv2/core/core.hpp>
+#include <opencv2/core.hpp>
 #include <opencv2/highgui/highgui.hpp>
 #include <opencv2/imgproc/imgproc.hpp>
 #include <opencv2/calib3d/calib3d.hpp>
diff --git a/src/modules/ProjectorModule.cpp b/src/modules/ProjectorModule.cpp
index d59f86867e0ee50e0208eacec0a19d11010b94d5..3b0bbecc041accbe9c51f555b651e576542ac260 100644
--- a/src/modules/ProjectorModule.cpp
+++ b/src/modules/ProjectorModule.cpp
@@ -39,6 +39,7 @@ https://github.com/kylemcdonald/ofxCv
 #include "SpaceModule.hpp"
 #include "RevealedModule.hpp"
 
+#include "shaders.h.in"
 
 using namespace std;
 using namespace glm;
@@ -310,7 +311,7 @@ void ProjectorModule::draw() {
     glActiveTexture(GL_TEXTURE1);
     glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::SELECTTEX], 1);
     glBindTexture(GL_TEXTURE_2D, m_selectTex);
-#ifdef GL42
+#ifdef GL43
     glActiveTexture(GL_TEXTURE7);
     glUniform1i(m_uniforms[Reveal::RENDERPROG][Reveal::OUTPUTTEX], 7);
     glBindImageTexture(7, m_outputTex, 0, GL_FALSE, 0,
@@ -356,7 +357,7 @@ void ProjectorModule::draw() {
     glfwSwapBuffers(m_projWindow);
 
     //PROCESS OUTPUT
-#ifdef GL42
+#ifdef GL43
     if(m_processOutput) {
         processOutput();
     }
@@ -372,59 +373,16 @@ void ProjectorModule::initGL() {
 
     //POSTPROCESSING
     {
-    const char * vertSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "in vec3 vertex; \n"
-    " \n"
-    "void main(void) {\n"
-    "   gl_Position = vec4(vertex, 1.0);\n"
-    "}\n"};
-
-    const char * fragSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "uniform float viewportWidth;\n"
-    "uniform float viewportHeight;\n"
-    "uniform float postFilter;\n"
-#ifdef GL42
-    "layout(binding=0) uniform sampler2D renderTex;\n"
+
+#ifdef GL43
+    m_programs[Reveal::POSTPROG]
+        = Reveal::getInstance()->createProgram(post43VS.c_str(), 
+				post43FS.c_str());
 #else
-    "uniform sampler2D renderTex;\n"
-#endif
-    " \n"
-    "out vec4 color;\n"
-    " \n"
-    "void main(void) {\n"
-    "   float coordX = gl_FragCoord.x;\n"
-    "   float coordY = gl_FragCoord.y;\n"
-    "   ivec2 patSize = textureSize(renderTex, 0);\n"
-    "   vec3 sumCol = vec3(0,0,0);\n"
-    "   float cnt=0;\n"
-    "   for(float dX = coordX-postFilter; dX <= coordX+postFilter; ++dX) {\n"
-    "       for(float dY = coordY-postFilter; dY <= coordY+postFilter; ++dY) {\n"
-    "           if(dX>=0 && dX<viewportWidth \n"
-    "                   && dY>=0 && dY<viewportHeight) {\n"
-    "               sumCol+=texelFetch(renderTex, \n"
-    "                                  ivec2((dX-0.5)/viewportWidth*patSize.x,\n"
-    "                                     (dY-0.5)/viewportHeight*patSize.y),\n"
-    "                                  0).xyz; \n"
-    "               cnt+=1;\n"
-    "           }\n"
-    "       }\n"
-    "   }\n"
-    "   color=vec4(sumCol.xyz/cnt, 1.0);\n"
-    "}\n"};
     m_programs[Reveal::POSTPROG]
-        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+        = Reveal::getInstance()->createProgram(post30VS.c_str(), 
+				post30FS.c_str());
+#endif
     m_uniforms[Reveal::POSTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
     m_uniforms[Reveal::POSTPROG][Reveal::VIEWPORTWIDTH]
         = glGetUniformLocation(m_programs[Reveal::POSTPROG],"viewportWidth");
@@ -436,653 +394,18 @@ void ProjectorModule::initGL() {
         = glGetUniformLocation(m_programs[Reveal::POSTPROG],"renderTex");
     }
 
-
-
     //RENDER
     {
-    const char * vertSource = {
-    #ifdef GL42
-    "#version 430 \n"
-    #else
-    "#version 410 \n"
-    #endif
-    " \n"
-    "in vec3 vertex; \n"
-    "in vec2 texCoords;\n"
-    " \n"
-    "uniform mat4 modelMat;\n"
-    "uniform mat4 viewMat;\n"
-    "uniform mat4 viewProjMat;\n"
-    "uniform float mirrored;\n"
-    " \n"
-    "out vec3 viewRay;\n"
-    "out vec2 uvCoords;\n"
-    " \n"
-    "void main(void) {\n"
-    "   vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
-    "   if(mirrored<1) {\n"
-    "       posWS.x = -posWS.x;\n"
-    "   }\n"
-    "   gl_Position = viewProjMat * posWS;\n"
-    "   viewRay = posWS.xyz - vec3(viewMat[3][0],\n"
-    "                              viewMat[3][1],\n"
-    "                              viewMat[3][2]);\n"
-    "   uvCoords=texCoords;\n"
-    "}\n"};
-
-    const char * fragSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    "\n"//defined in Reveal.hpp
-	"const int BOX=0;\n"
-	"const int SPHERE=1;\n"
-	"const int TUBE=2;\n"
-	"const int CONE=3;\n"
-	"const int FRAME=4;\n"
-	"const int PATH=5;\n"
-	"const int MODEL=10;\n"
-	"\n"
-    "in vec3 viewRay;\n"
-    "in vec2 uvCoords;\n"
-    " \n"
-#ifdef GL42
-    "layout(binding=0) uniform sampler2D sliceTex;\n"
-    "layout(binding=1) uniform sampler2D selectTex;\n"
-    "layout(binding=2) uniform sampler3D insideTex;\n"
-    "layout(binding=3) uniform sampler2D surfaceTex;\n"
-    "layout(binding=4) uniform sampler3D reactTex;\n"
-    "layout(binding=5) uniform sampler3D surfDistTex;\n"
-    "layout(binding=6) uniform sampler2D gradientTex;\n"
-    "layout(r32ui, binding=7) uniform coherent uimage2D outputTex;\n"
+#ifdef GL43
+    m_programs[Reveal::RENDERPROG]
+        = Reveal::getInstance()->createProgram(render43VS.c_str(), 
+				render43FS.c_str());
 #else
-    "uniform sampler2D sliceTex;\n"
-    "uniform sampler2D selectTex;\n"
-    "uniform sampler3D insideTex;\n"
-    "uniform sampler2D surfaceTex;\n"
-    "uniform sampler3D reactTex;\n"
-    "uniform sampler3D surfDistTex;\n"
-    "uniform sampler2D gradientTex;\n"
-#endif
-    "uniform float viewportWidth;\n"
-    "uniform float viewportHeight;\n"
-    "uniform float mirrored;\n"
-    "uniform float shapeID;\n"
-    "uniform float shapeIDBit;\n"
-	"uniform int shapeGeom;\n"
-    "uniform float subShapeID;\n"
-    "uniform float subShapesNb;\n"
-    "uniform mat4 subShapeInvMat;\n"
-    "uniform mat4 viewMat;\n"
-    "uniform mat4 modelMat;\n"
-    "uniform mat4 invModelMat;\n"
-    "uniform vec3 modelScale;\n"
-    "uniform int revealedBy;\n"
-	"\n"
-    "uniform vec3 shapeColor;\n"
-    //0: none, 1:color, 2:texture
-    "uniform int surface;\n"
-    "uniform vec3 surfaceColor;\n"
-	"uniform int insideOutputOnly;\n"
-	"uniform int reactivity;\n"
-    "uniform float thickness;\n"
-	"\n"
-    "uniform int insideVisible;\n"
-    //0:from center, 1:along x, 2: along y, 3:along z, 4 :from surface
-    "uniform int insideStructure;\n"
-    "uniform float structureRatio;\n"
-	"\n"
-    "uniform float gradientAlpha;\n"
-    //0:greyscale, 1:texture
-    "uniform int gradientType;\n"
-    "uniform int gradientSteps;\n"
-    "uniform float gradientCurveRatio;\n"
-	"\n"
-    "uniform float densityAlpha;\n"
-    //0:layers, 1:grid, 2:pointcloud
-    "uniform int densityType;\n"
-    "uniform float densityRatio;\n"
-    "uniform float densitySize;\n"
-    "uniform float densityCurveRatio;\n"
-	"\n"
-    "uniform float texAlpha;\n"
-    "uniform vec3 texOffset;\n"
-    "uniform vec3 texScale;\n"
-    "uniform int texGray;\n"
-#ifdef GL42
-    "uniform int revSize;\n"
-    "uniform int revSurface;\n"
-    "uniform int revInside;\n"
-    "uniform int revCenter;\n"
-    "uniform int revCursor;\n"
-    "uniform int revColor;\n"
-    "uniform int revHisto;\n"
-    "uniform int revVoxels;\n"
-    "uniform float revSubShapeID;\n"
-    "uniform int shapeOutSize;\n"
-    "uniform int histoOutSize;\n"
-    "uniform int voxelOutSize;\n"
-    "uniform int depthOutSize;\n"
-    "uniform int depthOutNb;\n"
-	"uniform vec4 boundingRect;\n"
-#endif
-    " \n"
-    "vec3 rgb2hsv(vec3 c) {\n"
-    "	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"
-    "	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"
-    "	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"
-	"	float d = q.x - min(q.w, q.y);\n"
-    "	float e = 1.0e-10;\n"
-    "	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d/(q.x + e), q.x);\n"
-	"}\n"
-
-	"float random (vec3 st) {\n"
-    "	return fract(sin(dot(st.xyz,\n"
-    "                     vec3(12.9898,78.233, 102.234)))*\n"
-    "    43758.5453123);\n"
-	"}\n"
-
-	"out vec4 color;\n"
-    " \n"
-    "void main(void) {\n"
-		//get fragment coordinates
-    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
-    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
-    "   ivec2 sliSize = textureSize(sliceTex, 0);\n"
-		//retrieve pixel in slicing texture
-    "   vec4 sli = texelFetch(sliceTex,\n"
-    "                         ivec2(coordX*float(sliSize.x), \n"
-    "                               coordY*float(sliSize.y)), \n"
-    "                         0);\n"
-    "   float pixZ=abs(gl_FragCoord.z);\n"
-    "   float cutZ=abs(sli.z);\n"
-    "   int depthID=int(sli.y)-1;\n"
-#ifdef GL42
-    "   int outCols=imageSize(outputTex).x;\n"
-	"   int outOffset=(int(shapeID-1)*depthOutNb+(depthID-1))*revSize;\n"
-#endif
-    "   int rendered=0;\n"
-    "   vec3 finalColor = shapeColor;\n"
-    "   float alpha=0;\n"
-	"	vec3 pixelPosW;\n"
-	"	vec3 pixelPos = vec3(0.0, 0.0, 1.0);\n"
-	"	vec3 ratioWithinBox = vec3(0.0, 0.0, 0.0);\n"
-	"	vec3 outRatioWithinBox = vec3(0.0, 0.0, 0.0);\n"
-		//if there is a slicing pixel aligned with our coordinate
-		//and we are revealed by this depth module
-	"	if(cutZ>0 && (revealedBy & (1<<(1+depthID)))>0 ) { \n"
-			//compute the slicing pixel world position
-    "   	pixelPosW = vec3(viewMat[3][0], \n"
-	"                       viewMat[3][1], \n"
-    "                       viewMat[3][2])\n"
-    "                  + vec3(normalize(viewRay) * sli.w);\n"
-    "       pixelPosW.x = pixelPosW.x*(-2.0*(1-mirrored)+1.0);\n"
-			//compute the slicing pixel position in model coords
-	"		pixelPos = (invModelMat * vec4(pixelPosW,1.0)).xyz;\n"
-	"\n"
-			//depending on type, test if slicing pixel inside 
-			//and retrieve distance to the surface on each axis
-	"		vec3 diffMin = vec3(1.0);\n" 
-	"		vec3 diffMax = vec3(1.0);\n"
-	"		switch(shapeGeom) {\n"
-	"			case PATH : {\n"//use min/max/size of current segment
-	"				pixelPos = (subShapeInvMat*vec4(pixelPos,1.0)).xyz;\n"
-	"				if(length(vec2(pixelPos.x, pixelPos.y))<=0.5\n"
-	"						&& (pixelPos.z>-0.5 && pixelPos.z<0.5)) { \n"
-	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
-	"					float yy = (pixelPos.y)*(pixelPos.y);\n"
-	"					float ax = sqrt(0.25-yy);\n"
-	"					diffMin.x = pixelPos.x+ax;\n"
-	"					diffMax.x = ax-pixelPos.x;\n"
-	"					float ay = sqrt(0.25-xx);\n"
-	"					diffMin.y = pixelPos.y+ay;\n"
-	"					diffMax.y = ay-pixelPos.y;\n"
-	"					diffMin.z = pixelPos.z+0.5;\n"
-	"					diffMax.z = 0.5-pixelPos.z;\n"
-    "          			rendered=1;\n"
-	"				}\n"
-	"			}break;\n"
-	"			case CONE : {\n"
-	"				if(pixelPos.y<0.5 && pixelPos.y>-0.5) {\n"
-	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
-	"					float yy = (pixelPos.y-0.5)*(pixelPos.y-0.5);\n"
-	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
-	"					if((xx+zz)/yy<0.25){ \n"
-	"						float ax = sqrt(0.25*yy-zz);\n"
-	"						diffMin.x = pixelPos.x+ax;\n"
-	"						diffMax.x = ax-pixelPos.x;\n"
-	"						float ay = sqrt((yy+xx)/0.25);\n"
-	"						diffMin.y = pixelPos.y+0.5;\n"
-	"						diffMax.y = 0.5-pixelPos.y;\n"
-	"						float az = sqrt(0.25*yy-xx);\n"
-	"						diffMin.z = pixelPos.z+az;\n"
-	"						diffMax.z = az-pixelPos.z;\n"
-    "          				rendered=1;\n"
-	"					}\n"
-	"				}\n"
-	"			} break;\n"
-	"			case TUBE : {\n"
-	"				if(length(vec2(pixelPos.x, pixelPos.z))<=0.5\n"
-	"						&& (pixelPos.y>-0.5 && pixelPos.y<0.5)) { \n"
-	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
-	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
-	"					float ax = sqrt(0.25-zz);\n"
-	"					diffMin.x = pixelPos.x+ax;\n"
-	"					diffMax.x = ax-pixelPos.x;\n"
-	"					float az = sqrt(0.25-xx);\n"
-	"					diffMin.z = pixelPos.z+az;\n"
-	"					diffMax.z = az-pixelPos.z;\n"
-	"					diffMin.y = pixelPos.y+0.5;\n"
-	"					diffMax.y = 0.5-pixelPos.y;\n"
-    "          			rendered=1;\n"
-	"				}\n"
-	"			} break;\n"
-	"			case SPHERE : {\n"
-	"				if(length(pixelPos)<=0.5) { \n"
-	"					float xx = (pixelPos.x)*(pixelPos.x);\n"
-	"					float yy = (pixelPos.y)*(pixelPos.y);\n"
-	"					float zz = (pixelPos.z)*(pixelPos.z);\n"
-	"					float ax = sqrt(0.25-yy-zz);\n"
-	"					diffMin.x = pixelPos.x+ax;\n"
-	"					diffMax.x = ax-pixelPos.x;\n"
-	"					float ay = sqrt(0.25-xx-zz);\n"
-	"					diffMin.y = pixelPos.y+ay;\n"
-	"					diffMax.y = ay-pixelPos.y;\n"
-	"					float az = sqrt(0.25-xx-yy);\n"
-	"					diffMin.z = pixelPos.z+az;\n"
-	"					diffMax.z = az-pixelPos.z;\n"
-    "          			rendered=1;\n"
-	"				}\n"
-	"			} break;\n"
-	"			case BOX : {\n"
-	"				diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
-	"				diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
-    "       		if(diffMin.x>0 && diffMax.x>0\n"
-	"						&& diffMin.y>0 && diffMax.y>0\n"
-    "          				&& diffMin.z>0 && diffMax.z>0){\n"
-	"					rendered=1;\n" 
-	"				} \n"
-	"			} break;\n"
-	"			case FRAME : {\n"
-	"				diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
-	"				diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
-    "       		if(diffMin.x>0 && diffMax.x>0\n"
-	"						&& diffMin.y>0 && diffMax.y>0\n"
-    "          				&& diffMin.z>0 && diffMax.z>0){\n"
-	"					rendered=1;\n" 
-	"				} \n"
-	"			} break;\n"
-	"			case MODEL : {\n"
-    "   			ivec2 selSize = textureSize(selectTex, 0);\n"
-    "   			vec4 sel = texelFetch(selectTex,\n"
-    "                         ivec2(coordX*float(selSize.x), \n"
-    "                               coordY*float(selSize.y)), \n"
-    "                         0);\n"
-        			//get front surfaces before depth map
-    "   			if(pixZ<=cutZ+thickness/1000.0) { \n"
-	"					if(sel.z==0) {\n"
-	"						if(sel.x==shapeID) {\n"
-	"							rendered=1;\n" 
-	"						}\n"
-	"						else if((int(shapeIDBit)&int(sel.w))>0) {\n"
-	"							diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);\n"
-	"							diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;\n"
-    "       					if(diffMin.x>0 && diffMax.x>0\n"
-	"									&& diffMin.y>0 && diffMax.y>0\n"
-    "          							&& diffMin.z>0 && diffMax.z>0){\n"
-	"								rendered=1;\n" 
-	"							}\n"
-	"						}\n"
-	"					}\n"
-    "       			if(surface>0 \n"
-    "               		&& (pixZ>cutZ \n"
-    "                      || (sel.z>0 && (int(shapeIDBit)&int(sel.w))>0))) {\n"
-	"							rendered=2;\n"
-	"					}\n"
-	"				}\n"
-	"			} break;\n"
-	"		}\n"
-	"		if(rendered>0) {\n"
-	"			ratioWithinBox = (pixelPos)+0.5;\n"
-				//test if on the surface
-	"			if(diffMin.x*modelScale.x<thickness || \n"
-	"							diffMax.x*modelScale.x<thickness || \n"
-	"							diffMin.y*modelScale.y<thickness || \n"
-	"							diffMax.y*modelScale.y<thickness || \n"
-	"							diffMin.z*modelScale.z<thickness || \n"
-	"							diffMax.z*modelScale.z<thickness) { \n"
-	"					rendered=2;\n" 
-	"			} \n"
-                    //extend ratiowithinbox to multiplesubshapes
-                    //and get gradient ratio according to type
-    "               float gradRatio = 0;\n"
-    "               vec3 subAdd;\n"
-    "               vec3 subDiv;\n"
-    "               if(insideStructure==0) {\n"//from center
-    "                   subAdd = vec3(subShapeID, subShapeID, subShapeID);\n"
-    "                   subDiv = vec3(subShapesNb, subShapesNb, subShapesNb);\n"
-    "                  ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
-    "                  	outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
-    "                   gradRatio = length(ratioWithinBox.xyz\n"
-    "                                     - vec3(0.5,0.5,0.5))/0.5;\n"
-    "               }\n"
-    "               else {\n"//from surface or along axes
-    "                   subAdd = vec3(0,0, subShapeID);\n"
-    "                   subDiv = vec3(1,1, subShapesNb);\n"
-    "                  	ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;\n"
-    "                  	outRatioWithinBox.xyz=ratioWithinBox.xyz;\n"
-	"					if(insideStructure==1) {\n"
-	"						ratioWithinBox.x=0.5;\n"
-	"					}\n"
-	"					else if(insideStructure==2) {\n"
-	"						ratioWithinBox.y=0.5;\n"
-	"					}\n"
-	"					else if(insideStructure==3 && shapeGeom!=PATH) {\n"
-	"						ratioWithinBox.z=0.5;\n"
-	"					}\n"
-	"					switch(shapeGeom) {\n"
-	"						case BOX : {\n"
-	"							vec3 q = abs(ratioWithinBox.xyz\n"
-	"										-vec3(0.5,0.5,0.5))*2.0\n" 
-	"									- vec3(1.0,1.0,1.0);\n"
-  	"							gradRatio = 1.0-abs(length(max(q,0.0)) \n"
-	"									+ min(max(q.x,max(q.y,q.z)),0.0));\n"
-	"						} break;\n"
-	"						case SPHERE : {\n"
-    "                   		gradRatio = length(ratioWithinBox.xyz\n"
-    "                       	              - vec3(0.5,0.5,0.5))/0.5;\n"
-	"						} break;\n"
-	"						case PATH  : {\n"
-	"							vec2 d = abs(vec2(length((ratioWithinBox.xy-vec2(0.5, 0.5))*2.0), \n"
-	"												  (ratioWithinBox.z-0.5)*2.0)) \n"
-	"											- vec2(1.0,1.0);\n"
-	"						 	gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
-	"										+ length(max(d,0.0)));\n"
-	"						} break;\n"
-	"						case TUBE  : {\n"
-	"							vec2 d = abs(vec2(length((ratioWithinBox.xz-vec2(0.5, 0.5))*2.0), \n"
-	"												  (ratioWithinBox.y-0.5)*2.0)) \n"
-	"											- vec2(1.0,1.0);\n"
-	"						 	gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)\n"
-	"										+ length(max(d,0.0)));\n"
-	"						} break;\n"
-	"						case CONE : {\n" 
-	"							float q = length((ratioWithinBox.xz\n"
-	"											- vec2(0.5,0.5))*2.0);\n"
-  	"							gradRatio = 1.0-abs(max(dot(vec2(0.5,0.5),\n"
-	"										vec2(q,(ratioWithinBox.y-1.0))),\n"
-	"										-1.0-(ratioWithinBox.y-1.0)));\n"
-	"						} break;\n"
-	"						case FRAME : {\n" //FIXME compute frame SDF
-	"							vec3 q = abs(ratioWithinBox.xyz\n"
-	"										-vec3(0.5,0.5,0.5))*2.0\n" 
-	"									- vec3(1.0,1.0,1.0);\n"
-  	"							gradRatio = 1.0-abs(length(max(q,0.0)) \n"
-	"									+ min(max(q.x,max(q.y,q.z)),0.0));\n"
-	"						} break;\n"
-	"						case MODEL : {\n" 
-    "                   		gradRatio = texture(surfDistTex, \n"
-	"                             					ratioWithinBox).r\n"
-	"										* structureRatio;\n"
-	"						} break;\n"
-	"						default :{\n"//defaults to sphere
-    "                   		gradRatio = length(ratioWithinBox.xyz\n"
-    "                       	              - vec3(0.5,0.5,0.5))/0.5;\n"
-	"						} break;\n"
-    "               	}\n"
-    "               }\n"
-                    //texture coordinates
-    "               vec3 texCoords = vec3(1-ratioWithinBox.x,\n"
-    "                                     1-ratioWithinBox.y,\n"
-    "                                     ratioWithinBox.z);\n"
-	"\n"
-					//start with shapeColor
-	"				finalColor = shapeColor;\n"
-					//test gradient
-	"				if(gradientAlpha>0) {\n"
-	"					float gradColor = \n"
-	"						pow(gradientCurveRatio<0?1.0-gradRatio:gradRatio,\n" 
-	"							abs(gradientCurveRatio));\n"
-	"					if(gradientSteps>1) {\n"
-	"						gradColor = floor(gradColor*gradientSteps)\n"
-	"										/ gradientSteps;\n"
-	"					}\n"
-	"					gradColor*=(gradRatio<=1.0)?1.0:0.0;\n"
-	"					if(gradientType>0) {\n"//gradient texture
-	"						finalColor=finalColor*(1.0-gradientAlpha) \n"
-	"								+ finalColor*gradientAlpha\n"
-    "									* texture(gradientTex, \n"
-    "										vec2(gradRatio, 0.0)).xyz;\n"
-	"					}\n"
-	"					else {\n"
-	"						finalColor=finalColor*(1.0-gradientAlpha) \n"
-	"								+ finalColor*gradColor*gradientAlpha;\n"
-	"					}\n"
-	"				}\n"
-					//test density
-	"				if(densityAlpha>0) {\n"
-	"					float densColor = \n"
-	"						pow(densityCurveRatio<0?1.0-gradRatio:gradRatio,\n" 
-	"							abs(densityCurveRatio));\n"
-    "                   if(densityType==0 && \n" //layers
-	"							length(mod(densColor*100.0, \n"
-	"									   densitySize*100.0))\n"
-	"								< densityRatio*densitySize*100.0) {\n"
-	"						densColor = 1.0;\n"
-	"						densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
-    "					}\n" 
-    "                   else if(densityType==1\n" //grid
-	"							&& (length(mod(ratioWithinBox.x*100,\n"
-    "										densitySize*100.0))\n"
-	"								<densitySize*densityRatio*100.0 \n"
-    "                   		|| length(mod(ratioWithinBox.y*100,\n"
-    "										densitySize*100.0))\n"
-	"								<densitySize*densityRatio*100.0 \n"
-    "                   		|| length(mod(ratioWithinBox.z*100,\n"
-    "										densitySize*100.0))\n"
-	"								<densitySize*densityRatio*100.0)) { \n"
-	"							densColor = 1.0;\n"
-    "                   }\n" 
-	"					else if(densityType==2  \n" //pointcloud
-	"						   && floor(random(ratioWithinBox.xyz)\n"
-	"										*floor(100.0))>100.0*densColor) {\n"
-	"							densColor = 1.0; \n"
-	"						densColor*=(gradRatio<=1.0)?1.0:0.0;\n"
-	"					}\n"
-	"					else {\n"
-	"						densColor = 0.0;\n"
-	"					}\n"
-	"					finalColor=finalColor*(1.0-densityAlpha) \n"
-	"								+ finalColor*densColor*densityAlpha;\n"
-	"				}\n"
-					//test texture
-	"				if(texAlpha>0) {\n"
-    "                   vec3 texColor = texture(insideTex, \n"
-    "                             texOffset+texScale*texCoords).xyz;\n"
-	"					if(texGray>0) {\n"
-	"						texColor=vec3((texColor.r+texColor.g+texColor.b)\n"
-	"									/ 3.0);\n"
-	"					}\n"
-	"					finalColor=finalColor*(1.0-texAlpha) \n"
-	"								+ finalColor*texColor*texAlpha;\n"
-	"				}\n"
-#ifdef GL42
-					//if revealing something, output values
-    "               if(sli.x>=1.0 && depthID<=depthOutNb) {\n"
-                        //inside output
-    "                   if(revInside>0 && rendered==1) {\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                               ivec2(mod(outOffset+revInside,outCols), \n"
-    "                                 floor((outOffset+revInside))/outCols),\n"
-    "                               1);\n"
-    "                   }\n"
-    "                   outRatioWithinBox.x=clamp(outRatioWithinBox.x, 0, 1);\n"
-    "                   outRatioWithinBox.y=clamp(outRatioWithinBox.y, 0, 1);\n"
-    "                   outRatioWithinBox.z=clamp(outRatioWithinBox.z, 0, 1);\n"
-                        //compute min,max on the three axes
-    "                   int xk=int(outRatioWithinBox.x*1000.0);\n"
-    "                   int yk=int(outRatioWithinBox.y*1000.0);\n"
-    "                   int zk=int(outRatioWithinBox.z*1000.0);\n"
-                        //output min/max ratios
-    "                   if(revCenter>0) {\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+0,outCols), \n"
-    "                                floor((outOffset+revCenter+0)/outCols)),\n"
-    "                           1000-xk);\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+1,outCols), \n"
-    "                                floor((outOffset+revCenter+1)/outCols)),\n"
-    "                          xk);\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+2,outCols), \n"
-    "                                floor((outOffset+revCenter+2)/outCols)),\n"
-    "                         1000-yk);\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+3,outCols), \n"
-    "                                floor((outOffset+revCenter+3)/outCols)),\n"
-    "                          yk);\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+4,outCols), \n"
-    "                                floor((outOffset+revCenter+4)/outCols)),\n"
-    "                          1000-zk);\n"
-    "                       imageAtomicMax(outputTex, \n"
-    "                          ivec2(mod(outOffset+revCenter+5,outCols), \n"
-    "                                floor((outOffset+revCenter+5)/outCols)),\n"
-    "                          zk);\n"
-    "                   }\n"
-						//convert from rgb to hsv
-	"					vec3 hsv = rgb2hsv(finalColor);\n"
-                        //Sum color channels
-    "                   if(revColor>0) {\n"
-                            //count nb revealed points
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revColor+0,outCols), \n"
-    "                                floor((outOffset+revColor+0)/outCols)),\n"
-    "                          1);\n"
-                            //sum point h
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revColor+1,outCols), \n"
-    "                                floor((outOffset+revColor+1)/outCols)),\n"
-    "                          clamp(int(hsv.x*1000.0),0,1000));\n"
-                            //sum s
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revColor+2,outCols), \n"
-    "                                floor((outOffset+revColor+2)/outCols)),\n"
-    "                          clamp(int(hsv.y*1000.0),0,1000));\n"
-                            //sum v
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revColor+3,outCols), \n"
-    "                                floor((outOffset+revColor+3)/outCols)),\n"
-    "                          clamp(int(hsv.z*1000.0),0,1000));\n"
-    "                   }\n"
-						//histo : accumulate on luminance bins
-    "                   if(revHisto>0) {\n"
-                            //count nb revealed points
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revHisto,outCols), \n"
-    "                                floor((outOffset+revHisto)/outCols)),\n"
-    "                          1);\n"
-	"						int bin = int(hsv.z*float(histoOutSize-1));\n"
-    "                       imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(outOffset+revHisto+1+bin,outCols), \n"
-    "                                floor((outOffset+revHisto+1+bin)/outCols)),\n"
-    "                          1);\n"
-	"					}\n"
-
-                        //2D grid of projected voxels (nbvox, 3D coords, lum)
-    "                   if(revVoxels>0) {\n"
-							//compute pixel ratio within 2D bounding rect
-	"						vec2 pixRatio = (vec2(coordX, coordY)\n"
-	"											- boundingRect.xy) / \n"
-	"									   (boundingRect.zw-boundingRect.xy);\n"
-	"						pixRatio.x = clamp(pixRatio.x, 0.0, 1.0);\n"
-	"						pixRatio.y = clamp(pixRatio.y, 0.0, 1.0);\n"
-							//compute offset in voxel output
-	"						int voxOff = outOffset+revVoxels;\n"
-	"						voxOff+=5*(int(pixRatio.x*voxelOutSize)\n"
-	"							+ int((1.0-pixRatio.y)*voxelOutSize)\n"
-	"									*voxelOutSize);\n"
-							//accumulate points
-	"						imageAtomicAdd(outputTex,\n"
-    "                          ivec2(mod(voxOff,outCols), \n"
-    "                                floor((voxOff)/outCols)),\n"
-	"							1);\n"
-							//accumulate coords
-	"						imageAtomicAdd(outputTex, \n"
-    "                          ivec2(mod(voxOff+1,outCols), \n"
-    "                                floor((voxOff+1)/outCols)),\n"
-    "                          clamp(int(outRatioWithinBox.x*1000.0),0,1000));\n"
-	"						imageAtomicAdd(outputTex, \n"
-    "                          ivec2(mod(voxOff+2,outCols), \n"
-    "                                floor((voxOff+2)/outCols)),\n"
-    "                          clamp(int(outRatioWithinBox.y*1000.0),0,1000));\n"
-	"						imageAtomicAdd(outputTex, \n"
-    "                          ivec2(mod(voxOff+3,outCols), \n"
-    "                                floor((voxOff+3)/outCols)),\n"
-    "                          clamp(int(outRatioWithinBox.z*1000.0),0,1000));\n"
-							//accumulate lum
-	"						imageAtomicAdd(outputTex, \n"
-    "                          ivec2(mod(voxOff+4,outCols), \n"
-    "                                floor((voxOff+4)/outCols)),\n"
-    "                          clamp(int(hsv.z*1000.0),0,1000));\n"
-    "                   }\n"
-    "               }\n"
-#endif
-    "       }\n"
-			//SURFACE test
-    "       if(rendered>1) { \n"
-	"			finalColor = surfaceColor;\n"
-#ifdef GL42
-    "           if(revSurface>0 && sli.x>=1.0 && depthID<=depthOutNb) {\n"
-    "               imageAtomicMax(outputTex,\n"
-    "                         ivec2(mod(outOffset+revSurface,outCols), \n"
-    "                               floor((outOffset+revSurface)/outCols)),\n"
-    "                         1);\n"
-    "           }\n"
-#endif
-    "       }\n"
-    "   }\n"
-		//final test, output if rendered or not, output final color
-    "   if(rendered>0 && length(finalColor)>0) { \n"
-#ifdef GL42
-	"		if(revSize>0) {\n"
-    "   		imageAtomicOr(outputTex, \n"
-    "           				ivec2(mod(outOffset,outCols), \n"
-    "             					floor((outOffset))/outCols),\n"
-    "           				rendered);\n"
-	"		}\n"
-#endif
-    "       if((insideVisible>0 && rendered==1) \n"
-	"				|| (surface>0 && rendered==2)) {\n"
-	"			color = vec4(finalColor, 1.0);\n"//display
-	//"			color = vec4(finalColor, sli.x);\n"//display
-	/*
-	"			if(sli.x>0.5) {\n"
-	"				color = vec4(1.0, 0.0, 0.0, 1.0);\n"//display
-	"			}\n"
-	"			else {\n"
-	"				color = vec4(0.0, 1.0, 0.0, 1.0);\n"//display
-	"			}\n"
-	*/
-	"		}\n"
-	"		else {\n"
-	"			color = vec4(0.0, 0.0, 0.0, 1.0);\n"
-	"		}\n"
-    //"       color = vec4((pixelPos+0.5)/2.0, 1.0);\n"//debug pix coords
-    //"       color = vec4(cutZ*10.0, pixZ*10.0, 0.0, 1.0);\n"//debug slice texture
-	//"		  color = vec4(texture(surfDistTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
-	//"		  color = vec4(texture(insideTex, ratioWithinBox).r*10.0, 1.0,1.0,1.0);\n"
-	//"		  color = vec4(ratioWithinBox.xyz, 1.0);\n"
-    "   }\n"
-    "   else {\n" //DISCARD
-	//"		color = vec4(1.0,0.0,0.0,1.0);\n"
-    "       discard;\n"
-    "   }\n"
-    "}\n"};
     m_programs[Reveal::RENDERPROG]
-        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+        = Reveal::getInstance()->createProgram(render30VS.c_str(), 
+				render30FS.c_str());
+#endif
+
     m_uniforms[Reveal::RENDERPROG] = map<Reveal::REVIL_UNIFORM, GLint>();
     m_uniforms[Reveal::RENDERPROG][Reveal::MIRRORED]
         = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "mirrored");
@@ -1188,7 +511,7 @@ void ProjectorModule::initGL() {
         = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxLocalSize");
     m_uniforms[Reveal::RENDERPROG][Reveal::BBOXROT]
         = glGetUniformLocation(m_programs[Reveal::RENDERPROG], "bboxRot");
-#ifdef GL42
+#ifdef GL43
     //output texture
     m_outputImg = new unsigned int[m_outputImgSize*m_outputImgSize];
     m_outputImgInit = new unsigned int[m_outputImgSize*m_outputImgSize];
@@ -1236,78 +559,15 @@ void ProjectorModule::initGL() {
 
    {
     //select prog
-    const char * vertSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "in vec3 vertex;\n"
-    " \n"
-    "uniform mat4 modelMat;\n"
-    "uniform mat4 viewMat;\n"
-    "uniform mat4 viewProjMat;\n"
-    "uniform float mirrored;\n"
-    " \n"
-    "void main(void) {\n"
-    "   vec4 posWS = modelMat * vec4(vertex, 1.0);\n"
-    "   if(mirrored<1) {\n"
-    "       posWS.x = -posWS.x;\n"
-    "   }\n"
-    "   gl_Position = viewProjMat * posWS;\n"
-    "}\n"};
-
-    const char * fragSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-#ifdef GL42
-    "layout(binding=0) uniform sampler2D sliceTex;\n"
+#ifdef GL43
+    m_programs[Reveal::SELECTPROG]
+        = Reveal::getInstance()->createProgram(select43VS.c_str(), 
+				select43FS.c_str());
 #else
-    "uniform sampler2D sliceTex;\n"
-#endif
-    "uniform float viewportWidth;\n"
-    "uniform float viewportHeight;\n"
-    "uniform float shapeID;\n"
-    "uniform float shapeIDBit;\n"
-    "uniform float mirrored;\n"
-    "uniform float thickness;\n"
-    "uniform int surface;\n"
-    " \n"
-    "out vec4 color;\n"
-    " \n"
-    "void main(void) {\n"
-    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
-    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
-    "   ivec2 sliSize = textureSize(sliceTex, 0);\n"
-    "   vec4 sli = texelFetch(sliceTex,\n"
-    "                         ivec2(coordX*float(sliSize.x),\n"
-    "                               coordY*float(sliSize.y)),\n"
-    "                         0);\n"
-    "   float pixZ=abs(gl_FragCoord.z);\n"
-    "   float cutZ=abs(sli.z);\n"
-    //  keep all ids of back surfaces after depth map
-    "   if(pixZ>cutZ && cutZ>0) {\n"
-    "       if((mirrored<1 && !gl_FrontFacing)\n"
-    "               || (mirrored>0 && gl_FrontFacing)) {\n"
-    "           color = vec4(shapeID, 0, \n"
-    "                        (abs(pixZ-cutZ)<thickness/1000.0 && surface>0)?1:0, \n"
-    "                        shapeIDBit);\n"
-    "       }\n"
-    "       else {\n" //occlude back when front face also behind
-    "           color = vec4(-shapeID, 0, 0, -shapeIDBit);\n"
-    "       }\n"
-    "   }\n"
-    "   else {\n"
-    "       discard;\n"
-    "   }\n"
-    "}\n"};
     m_programs[Reveal::SELECTPROG]
-        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+        = Reveal::getInstance()->createProgram(select30VS.c_str(), 
+				select30FS.c_str());
+#endif
     m_uniforms[Reveal::SELECTPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
     m_uniforms[Reveal::SELECTPROG][Reveal::MIRRORED]
         = glGetUniformLocation(m_programs[Reveal::SELECTPROG], "mirrored");
@@ -1336,193 +596,16 @@ void ProjectorModule::initGL() {
 
     //SLICE
     {
-    const char * vertSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);\n"
-    "#define mn3(a, b, c)  s2(a, b); s2(a, c);\n"
-    "#define mx3(a, b, c)  s2(b, c); s2(a, c);\n"
-    "#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b);\n"
-    "#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d);\n"
-    "#define mnmx5(a, b, c, d, e) s2(a,b); s2(c,d);mn3(a,c,e);mx3(b,d,e);\n"
-   "#define mnmx6(a,b,c,d,e,f) s2(a,d);s2(b,e);s2(c,f);mn3(a,b,c);mx3(d,e,f);\n"
-    "in vec3 vertex; \n"
-    " \n"
-#ifdef GL42
-    "layout(binding=0) uniform sampler2D depthCamTex;\n"
-    "layout(binding=1) uniform sampler2D depthCamTexFil;\n"
-    "layout(binding=2) uniform sampler2D markersTex;\n"
-    //"layout(r32ui, binding=2) uniform coherent uimage2D outputTex;\n"
-#else
-    "uniform sampler2D depthCamTex;\n"
-    "uniform sampler2D depthCamTexFil;\n"
-    "uniform sampler2D markersTex;\n"
-#endif
-    "uniform mat4 modelMat;\n"
-    "uniform mat4 viewMat;\n"
-    "uniform mat4 viewProjMat;\n"
-    "uniform float camXReso;\n"
-    "uniform float camYReso;\n"
-    "uniform float camXZFactor;\n"
-    "uniform float camYZFactor;\n"
-    "uniform int camFilter;\n"
-    "uniform int background;\n"
-    "uniform float camContThresh;\n"
-    "uniform float camMarkers;\n"
-    "uniform int depthType;\n"
-    "uniform int depthID;\n"
-    "uniform float outputCurs;\n"
-    "uniform float mirrored;\n"
-    " \n"
-    "out vec3 viewRay;\n"
-    "out float kept;\n"
-    "flat out int outDepthID;\n"
-    " \n"
-    "void main(void) {\n"
-    "   vec4 depthPos = vec4(0, 0, 0, 1);\n"
-    "   vec4 posWS = vec4(0, 0, 0, 1);\n"
-        //depth camera
-    "   if(depthType==0) {\n"
-    "	    vec2 coords = vertex.xy;\n"
-            //get marker if any
-    "       if(camMarkers>0) {\n"
-    "           outDepthID = int(float(texture(markersTex,\n"
-    "                                  vec2(coords.x/camXReso,\n"
-    "                                       coords.y/camYReso)).r)\n"
-    "                           * 255.0);\n"
-    "       }\n"
-    "       else {\n"
-    "           outDepthID=depthID+1;\n"
-    "       }\n"
-            //get depth pixel in camera texture
-    "       float depth = \n"
-    "                     float(texture(depthCamTex,\n"
-    "                                   vec2(coords.x/camXReso,\n"
-    "                                        coords.y/camYReso)).r)\n"
-    "                     * 65535.0;\n"
-    "       kept=1.0;\n"
-    "       float backgroundDepth=0;\n"
-    "       if(background>0) {\n"
-    "           float backDepth = float(texture(depthCamTex,\n"
-    "                                   vec2(coords.x/camXReso,\n"
-    "                                        coords.y/camYReso)).r)\n"
-    "                                   * 65535.0;\n"
-    "           if(backDepth<depth) {\n"
-    "               depth=backDepth;\n"
-    "               backgroundDepth=1;\n"
-    "           }\n"
-    "       }\n"
-    "       if(depth<=500.0 || depth>8000.0) {\n"
-    "           kept=0.0;\n"
-    "       }\n"
-    "       else if(backgroundDepth==0) {\n"
-                //filter out contours
-    "           float maxD=camContThresh;\n" 
-    "           bool contour=false;\n"
-    "           for(int dX = -1; dX <= 1; ++dX) {\n"
-    "               for(int dY = -1; dY <= 1; ++dY) {\n"
-    "                   if(abs(float(texture(depthCamTex,\n"
-    "                                   vec2((coords.x+dX)/camXReso,\n"
-    "                                        (coords.y+dY)/camYReso)).r)\n"
-    "                               * 65535.0\n"
-    "                           - depth) > maxD) {\n"
-    "                       contour=true;\n"
-    "                   }\n"
-    "               }\n"
-    "           }\n"
-    "           if(contour) {\n"
-    "               kept=0.0;\n"
-    "           }\n"
-                //see if needs filtering
-    "           if(camFilter>0) {\n"
-    "               float filtDepth = float(texture(depthCamTexFil,\n"
-    "                                       vec2(coords.x/camXReso,\n"
-    "                                        	 coords.y/camYReso)).r)\n"
-    "                                   * 65535.0;\n"
-                    //select either filtered version or current one
-                    //depending on movement 
-    "               if(abs(filtDepth-depth)<camContThresh) {\n"
-    "                   float filRatio = abs(filtDepth-depth)/camContThresh;\n"
-    "                   depth=(1-filRatio)*filtDepth+(filRatio)*depth;\n"
-    "               }\n"
-    "           }\n"
-    "       }\n"
-            //test distance again
-    "       if(depth<=500.0 || depth>8000.0) {\n"
-    "           kept=0.0;\n"
-    "       }\n"
-            //compute position in world units
-    "       depthPos = vec4((vertex.x/camXReso-0.5)\n"
-    "                           *depth*camXZFactor,\n"
-    "                        (0.5-(vertex.y/camYReso))\n"
-    "                           *depth*camYZFactor,\n"
-    "                        depth,\n"
-    "                        1.0);\n"
-            //get world pos
-    "       posWS = modelMat * depthPos;\n"
-    "   }\n"
-        //other slicing shapes
-    "   else {\n"
-    "       outDepthID=depthID+1;\n"
-    "       kept=1.0;\n"
-    "       depthPos=vec4(vertex, 1.0);\n"
-    "       posWS = modelMat * depthPos;\n"
-    "       if(mirrored<1) {\n"
-    "           posWS.x = -posWS.x;\n"
-    "       }\n"
-    "   }\n"
-#ifdef GL42
-/*
-        //output minimum point on z axis if output is active
-    "   if(outputCurs>0 && kept>0.0) {\n"
-    "       imageAtomicMin(outputTex,ivec2(0,int(depthID)+500),\n"
-    "                                  int(floor(1000.0+posWS.z/10.0)*1000000\n"
-    "                                      +floor(posWS.y/10.0+500.0)*1000\n"
-    "                                      +floor(posWS.x/10.0+500.0)));\n"
-    //"       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),4400600);\n"
-    //"       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),6400600);\n"
-    "   }\n"
-*/
-#endif
-        //keep/interpolate ray from view to each vertex
-    "   viewRay = (posWS.xyz - vec3(viewMat[3][0],\n"
-    "                               viewMat[3][1],\n"
-    "                               viewMat[3][2]));\n"
-    "   gl_Position = viewProjMat * posWS;\n"
-    "}\n"};
-    const char * fragSource = {
-#ifdef GL42
-    "#version 430 \n"
+#ifdef GL43
+    m_programs[Reveal::SLICEPROG]
+        = Reveal::getInstance()->createProgram(slice43VS.c_str(), 
+				slice43FS.c_str());
 #else
-    "#version 410 \n"
+    m_programs[Reveal::SLICEPROG]
+        = Reveal::getInstance()->createProgram(slice30VS.c_str(), 
+				slice30FS.c_str());
 #endif
-    " \n"
-    "in float kept;\n"
-    "in vec3 viewRay;\n"
-    "flat in int outDepthID;\n"
-    " \n"
-    "out vec4 color;\n"
-    " \n"
-    "void main(void) {\n"
-    "   float thresh=0.8;\n"
-    "   if(kept>=thresh) {\n"
-    "       color = vec4((kept-thresh)/(1.0-thresh),\n"
-    "                     float(outDepthID),\n"
-    "                     gl_FragCoord.z,\n"
-    "                     length(viewRay));\n"
-    "   }\n"
-    "   else {\n"
-    "       discard;\n"
-    "   }\n"
-//    "   color = vec4(1.0, 1.0, 0.0, 1.0);\n"
-    "}\n"};
 
-    m_programs[Reveal::SLICEPROG]
-        = Reveal::getInstance()->createProgram(vertSource, fragSource);
     m_uniforms[Reveal::SLICEPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
     m_uniforms[Reveal::SLICEPROG][Reveal::BACKGROUND]
         = glGetUniformLocation(m_programs[Reveal::SLICEPROG], "background");
@@ -1563,84 +646,15 @@ void ProjectorModule::initGL() {
 
     //Calibration
     {
-    const char * vertSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "in vec3 vertex; \n"
-    " \n"
-    "void main(void) {\n"
-    "   gl_Position = vec4(vertex, 1.0);\n"
-    "}\n"};
-
-    const char * fragSource = {
-#ifdef GL42
-    "#version 430 \n"
-#else
-    "#version 410 \n"
-#endif
-    " \n"
-    "uniform float viewportWidth;\n"
-    "uniform float viewportHeight;\n"
-    "uniform float patW;\n"
-    "uniform float patPosX;\n"
-    "uniform float patPosY;\n"
-    "uniform float patNbX;\n"
-    "uniform float patNbY;\n"
-    "uniform float patBright;\n"
-    "uniform vec2 patOffset;\n"
-    "uniform vec2 patRange;\n"
-#ifdef GL42
-    "layout(binding=0) uniform sampler2D patternTex;\n"
+#ifdef GL43
+    m_programs[Reveal::CALIBPROG]
+        = Reveal::getInstance()->createProgram(calib43VS.c_str(), 
+				calib43FS.c_str());
 #else
-    "uniform sampler2D patternTex;\n"
-#endif
-    " \n"
-    "out vec4 color;\n"
-    " \n"
-    "void main(void) {\n"
-    /*
-    "   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;\n"
-    "   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;\n"
-    "   ivec2 patSize = textureSize(patternTex, 0);\n"
-    "   float pat = texelFetch(patternTex,\n"
-    "                          ivec2(coordX*float(patSize.x),\n"
-    "                                (1.0-coordY)*float(patSize.y)),\n"
-    "                          0).r;\n"
-    "   color=vec4(pat, pat, pat, 1.0);\n"
-    //"   color=vec4(1.0,1.0,1.0,1.0);\n"
-    */
-    //pixel is white by default
-    "   color = vec4(patBright);\n"
-    "   float offX = gl_FragCoord.x - patPosX;\n"
-    "   float offY = (viewportHeight-gl_FragCoord.y) - patPosY;\n"
-    //black squares
-    "   if(offX>=0 && offX<patW*(patNbX+1)\n"
-    "           && offY>=0 && offY<patW*(patNbY+1)) {\n"
-    "       if((mod(offX,patW*2)<patW && mod(offY,patW*2)<patW) \n"
-    "          || (mod(offX,patW*2)>patW && mod(offY,patW*2)>patW)) {\n"
-    "           color = vec4(0, 0, 0, 1);\n"
-    "       }\n"
-    "   }\n"
-    //color in red the pattern range border
-    "   float thick=2;\n"
-    "   float coordY = viewportHeight-gl_FragCoord.y;\n"
-    "   if(((abs(gl_FragCoord.x-patOffset.x)<thick\n"
-    "               || abs(gl_FragCoord.x-(patOffset.x+patRange.x))<thick)\n"
-    "           && coordY>patOffset.y\n" 
-    "           && coordY<(patOffset.y+patRange.y))\n"
-    "       ||((abs(coordY-patOffset.y)<thick\n"
-    "               || abs(coordY-(patOffset.y+patRange.y))<thick)\n"
-    "           && gl_FragCoord.x>patOffset.x\n" 
-    "           && gl_FragCoord.x<(patOffset.x+patRange.x))) {\n"
-    "       color=vec4(1,0,0,1);\n"
-    "   }\n"
-    "}\n"};
     m_programs[Reveal::CALIBPROG]
-        = Reveal::getInstance()->createProgram(vertSource, fragSource);
+        = Reveal::getInstance()->createProgram(calib30VS.c_str(), 
+				calib30FS.c_str());
+#endif
     m_uniforms[Reveal::CALIBPROG]=map<Reveal::REVIL_UNIFORM, GLint>();
     m_uniforms[Reveal::CALIBPROG][Reveal::VIEWPORTWIDTH]
         = glGetUniformLocation(m_programs[Reveal::CALIBPROG],"viewportWidth");
diff --git a/src/shaders/calib30.fs b/src/shaders/calib30.fs
new file mode 100644
index 0000000000000000000000000000000000000000..fe27b5678be2aecb2c4339367ff9a57a99246d40
--- /dev/null
+++ b/src/shaders/calib30.fs
@@ -0,0 +1,55 @@
+#version 130 
+
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float patW;
+uniform float patPosX;
+uniform float patPosY;
+uniform float patNbX;
+uniform float patNbY;
+uniform float patBright;
+uniform vec2 patOffset;
+uniform vec2 patRange;
+uniform sampler2D patternTex;
+
+out vec4 color;
+
+void main(void) {
+	/*
+	   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	   ivec2 patSize = textureSize(patternTex, 0);
+	   float pat = texelFetch(patternTex,
+	   ivec2(coordX*float(patSize.x),
+	   (1.0-coordY)*float(patSize.y)),
+	   0).r;
+	   color=vec4(pat, pat, pat, 1.0);
+	//   color=vec4(1.0,1.0,1.0,1.0);
+	 */
+	//pixel is white by default
+	color = vec4(patBright);
+	float offX = gl_FragCoord.x - patPosX;
+	float offY = (viewportHeight-gl_FragCoord.y) - patPosY;
+	//black squares
+	if(offX>=0 && offX<patW*(patNbX+1)
+			&& offY>=0 && offY<patW*(patNbY+1)) {
+		if((mod(offX,patW*2)<patW && mod(offY,patW*2)<patW) 
+				|| (mod(offX,patW*2)>patW && mod(offY,patW*2)>patW)) {
+			color = vec4(0, 0, 0, 1);
+		}
+	}
+	//color in red the pattern range border
+	float thick=2;
+	float coordY = viewportHeight-gl_FragCoord.y;
+	if(((abs(gl_FragCoord.x-patOffset.x)<thick
+					|| abs(gl_FragCoord.x-(patOffset.x+patRange.x))<thick)
+				&& coordY>patOffset.y 
+				&& coordY<(patOffset.y+patRange.y))
+			||((abs(coordY-patOffset.y)<thick
+					|| abs(coordY-(patOffset.y+patRange.y))<thick)
+				&& gl_FragCoord.x>patOffset.x 
+				&& gl_FragCoord.x<(patOffset.x+patRange.x))) {
+		color=vec4(1,0,0,1);
+	}
+};
+
diff --git a/src/shaders/calib30.vs b/src/shaders/calib30.vs
new file mode 100644
index 0000000000000000000000000000000000000000..3248ef02dd8c745b0406ba6d16692549ad60772b
--- /dev/null
+++ b/src/shaders/calib30.vs
@@ -0,0 +1,7 @@
+#version 130
+
+in vec3 vertex; 
+
+void main(void) {
+	gl_Position = vec4(vertex, 1.0);
+};
diff --git a/src/shaders/calib43.fs b/src/shaders/calib43.fs
new file mode 100644
index 0000000000000000000000000000000000000000..bc3b96dde957ca9845387f005ff9a9543cd81685
--- /dev/null
+++ b/src/shaders/calib43.fs
@@ -0,0 +1,56 @@
+#version 430 
+
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float patW;
+uniform float patPosX;
+uniform float patPosY;
+uniform float patNbX;
+uniform float patNbY;
+uniform float patBright;
+uniform vec2 patOffset;
+uniform vec2 patRange;
+
+layout(binding=0) uniform sampler2D patternTex;
+
+out vec4 color;
+
+void main(void) {
+	/*
+	   float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	   float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	   ivec2 patSize = textureSize(patternTex, 0);
+	   float pat = texelFetch(patternTex,
+	   ivec2(coordX*float(patSize.x),
+	   (1.0-coordY)*float(patSize.y)),
+	   0).r;
+	   color=vec4(pat, pat, pat, 1.0);
+	//   color=vec4(1.0,1.0,1.0,1.0);
+	 */
+	//pixel is white by default
+	color = vec4(patBright);
+	float offX = gl_FragCoord.x - patPosX;
+	float offY = (viewportHeight-gl_FragCoord.y) - patPosY;
+	//black squares
+	if(offX>=0 && offX<patW*(patNbX+1)
+			&& offY>=0 && offY<patW*(patNbY+1)) {
+		if((mod(offX,patW*2)<patW && mod(offY,patW*2)<patW) 
+				|| (mod(offX,patW*2)>patW && mod(offY,patW*2)>patW)) {
+			color = vec4(0, 0, 0, 1);
+		}
+	}
+	//color in red the pattern range border
+	float thick=2;
+	float coordY = viewportHeight-gl_FragCoord.y;
+	if(((abs(gl_FragCoord.x-patOffset.x)<thick
+					|| abs(gl_FragCoord.x-(patOffset.x+patRange.x))<thick)
+				&& coordY>patOffset.y 
+				&& coordY<(patOffset.y+patRange.y))
+			||((abs(coordY-patOffset.y)<thick
+					|| abs(coordY-(patOffset.y+patRange.y))<thick)
+				&& gl_FragCoord.x>patOffset.x 
+				&& gl_FragCoord.x<(patOffset.x+patRange.x))) {
+		color=vec4(1,0,0,1);
+	}
+};
+
diff --git a/src/shaders/calib43.vs b/src/shaders/calib43.vs
new file mode 100644
index 0000000000000000000000000000000000000000..6c127fdd330f1eeab1cba29de2da1da6c962aee9
--- /dev/null
+++ b/src/shaders/calib43.vs
@@ -0,0 +1,7 @@
+#version 430 
+
+in vec3 vertex; 
+
+void main(void) {
+	gl_Position = vec4(vertex, 1.0);
+};
diff --git a/src/shaders/post30.fs b/src/shaders/post30.fs
new file mode 100644
index 0000000000000000000000000000000000000000..bb679be38fec94d58f62eaf6090d3f581b14a68f
--- /dev/null
+++ b/src/shaders/post30.fs
@@ -0,0 +1,29 @@
+#version 130
+
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float postFilter;
+uniform sampler2D renderTex;
+
+out vec4 color;
+
+void main(void) {
+	float coordX = gl_FragCoord.x;
+	float coordY = gl_FragCoord.y;
+	ivec2 patSize = textureSize(renderTex, 0);
+	vec3 sumCol = vec3(0,0,0);
+	float cnt=0;
+	for(float dX = coordX-postFilter; dX <= coordX+postFilter; ++dX) {
+		for(float dY = coordY-postFilter; dY <= coordY+postFilter; ++dY) {
+			if(dX>=0 && dX<viewportWidth 
+					&& dY>=0 && dY<viewportHeight) {
+				sumCol+=texelFetch(renderTex, 
+						ivec2((dX-0.5)/viewportWidth*patSize.x,
+							(dY-0.5)/viewportHeight*patSize.y),
+						0).xyz; 
+				cnt+=1;
+			}
+		}
+	}
+	color=vec4(sumCol.xyz/cnt, 1.0);
+}
diff --git a/src/shaders/post30.vs b/src/shaders/post30.vs
new file mode 100644
index 0000000000000000000000000000000000000000..ee33b5fbe14b555ad3431f47c0a8411e02e3cf75
--- /dev/null
+++ b/src/shaders/post30.vs
@@ -0,0 +1,8 @@
+#version 130 
+
+in vec3 vertex; 
+
+void main(void) {
+	gl_Position = vec4(vertex, 1.0);
+};
+
diff --git a/src/shaders/post43.fs b/src/shaders/post43.fs
new file mode 100644
index 0000000000000000000000000000000000000000..d09abf4e48b2cbbb980f7250514f6226e5173d5e
--- /dev/null
+++ b/src/shaders/post43.fs
@@ -0,0 +1,30 @@
+#version 430 
+
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float postFilter;
+layout(binding=0) uniform sampler2D renderTex;
+
+out vec4 color;
+
+void main(void) {
+	float coordX = gl_FragCoord.x;
+	float coordY = gl_FragCoord.y;
+	ivec2 patSize = textureSize(renderTex, 0);
+	vec3 sumCol = vec3(0,0,0);
+	float cnt=0;
+	for(float dX = coordX-postFilter; dX <= coordX+postFilter; ++dX) {
+		for(float dY = coordY-postFilter; dY <= coordY+postFilter; ++dY) {
+			if(dX>=0 && dX<viewportWidth 
+					&& dY>=0 && dY<viewportHeight) {
+				sumCol+=texelFetch(renderTex, 
+						ivec2((dX-0.5)/viewportWidth*patSize.x,
+							(dY-0.5)/viewportHeight*patSize.y),
+						0).xyz; 
+				cnt+=1;
+			}
+		}
+	}
+	color=vec4(sumCol.xyz/cnt, 1.0);
+};
+
diff --git a/src/shaders/post43.vs b/src/shaders/post43.vs
new file mode 100644
index 0000000000000000000000000000000000000000..d7116e788ca3b1011dd4df79b9abfd45a9307c2a
--- /dev/null
+++ b/src/shaders/post43.vs
@@ -0,0 +1,8 @@
+#version 430 
+
+in vec3 vertex; 
+
+void main(void) {
+	gl_Position = vec4(vertex, 1.0);
+};
+
diff --git a/src/shaders/render30.fs b/src/shaders/render30.fs
new file mode 100644
index 0000000000000000000000000000000000000000..a65ee8a3624383475fa91c6a01f94941ae8b5acf
--- /dev/null
+++ b/src/shaders/render30.fs
@@ -0,0 +1,25 @@
+#version 130
+
+in vec3 vertex; 
+in vec2 texCoords;
+
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float mirrored;
+
+out vec3 viewRay;
+out vec2 uvCoords;
+
+void main(void) {
+	vec4 posWS = modelMat * vec4(vertex, 1.0);
+	if(mirrored<1) {
+		posWS.x = -posWS.x;
+	}
+	gl_Position = viewProjMat * posWS;
+	viewRay = posWS.xyz - vec3(viewMat[3][0],
+			viewMat[3][1],
+			viewMat[3][2]);
+	uvCoords=texCoords;
+};
+
diff --git a/src/shaders/render30.vs b/src/shaders/render30.vs
new file mode 100644
index 0000000000000000000000000000000000000000..5aeef20973ff7947076498cf3e9fe499ab73f7fa
--- /dev/null
+++ b/src/shaders/render30.vs
@@ -0,0 +1,420 @@
+#version 130
+const int BOX=0;
+const int SPHERE=1;
+const int TUBE=2;
+const int CONE=3;
+const int FRAME=4;
+const int PATH=5;
+const int MODEL=10;
+
+in vec3 viewRay;
+in vec2 uvCoords;
+
+uniform sampler2D sliceTex;
+uniform sampler2D selectTex;
+uniform sampler3D insideTex;
+uniform sampler2D surfaceTex;
+uniform sampler3D reactTex;
+uniform sampler3D surfDistTex;
+uniform sampler2D gradientTex;
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float mirrored;
+uniform float shapeID;
+uniform float shapeIDBit;
+uniform int shapeGeom;
+uniform float subShapeID;
+uniform float subShapesNb;
+uniform mat4 subShapeInvMat;
+uniform mat4 viewMat;
+uniform mat4 modelMat;
+uniform mat4 invModelMat;
+uniform vec3 modelScale;
+uniform int revealedBy;
+
+uniform vec3 shapeColor;
+//0: none, 1:color, 2:texture
+uniform int surface;
+uniform vec3 surfaceColor;
+uniform int insideOutputOnly;
+uniform int reactivity;
+uniform float thickness;
+
+uniform int insideVisible;
+//0:from center, 1:along x, 2: along y, 3:along z, 4 :from surface
+uniform int insideStructure;
+uniform float structureRatio;
+
+uniform float gradientAlpha;
+//0:greyscale, 1:texture
+uniform int gradientType;
+uniform int gradientSteps;
+uniform float gradientCurveRatio;
+
+uniform float densityAlpha;
+//0:layers, 1:grid, 2:pointcloud
+uniform int densityType;
+uniform float densityRatio;
+uniform float densitySize;
+uniform float densityCurveRatio;
+
+uniform float texAlpha;
+uniform vec3 texOffset;
+uniform vec3 texScale;
+uniform int texGray;
+
+vec3 rgb2hsv(vec3 c) {
+	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+	float d = q.x - min(q.w, q.y);
+	float e = 1.0e-10;
+	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d/(q.x + e), q.x);
+}
+
+float random (vec3 st) {
+	return fract(sin(dot(st.xyz,
+					vec3(12.9898,78.233, 102.234)))*
+			43758.5453123);
+}
+
+out vec4 color;
+
+void main(void) {
+	//get fragment coordinates
+	float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	ivec2 sliSize = textureSize(sliceTex, 0);
+	//retrieve pixel in slicing texture
+	vec4 sli = texelFetch(sliceTex,
+			ivec2(coordX*float(sliSize.x), 
+				coordY*float(sliSize.y)), 
+			0);
+	float pixZ=abs(gl_FragCoord.z);
+	float cutZ=abs(sli.z);
+	int depthID=int(sli.y)-1;
+	int rendered=0;
+	vec3 finalColor = shapeColor;
+	float alpha=0;
+	vec3 pixelPosW;
+	vec3 pixelPos = vec3(0.0, 0.0, 1.0);
+	vec3 ratioWithinBox = vec3(0.0, 0.0, 0.0);
+	vec3 outRatioWithinBox = vec3(0.0, 0.0, 0.0);
+	//if there is a slicing pixel aligned with our coordinate
+	//and we are revealed by this depth module
+	if(cutZ>0 && (revealedBy & (1<<(1+depthID)))>0 ) { 
+		//compute the slicing pixel world position
+		pixelPosW = vec3(viewMat[3][0], 
+				viewMat[3][1], 
+				viewMat[3][2])
+			+ vec3(normalize(viewRay) * sli.w);
+		pixelPosW.x = pixelPosW.x*(-2.0*(1-mirrored)+1.0);
+		//compute the slicing pixel position in model coords
+		pixelPos = (invModelMat * vec4(pixelPosW,1.0)).xyz;
+
+		//depending on type, test if slicing pixel inside 
+		//and retrieve distance to the surface on each axis
+		vec3 diffMin = vec3(1.0); 
+		vec3 diffMax = vec3(1.0);
+		switch(shapeGeom) {
+			case PATH : {//use min/max/size of current segment
+							pixelPos = (subShapeInvMat*vec4(pixelPos,1.0)).xyz;
+							if(length(vec2(pixelPos.x, pixelPos.y))<=0.5
+									&& (pixelPos.z>-0.5 && pixelPos.z<0.5)) { 
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float yy = (pixelPos.y)*(pixelPos.y);
+								float ax = sqrt(0.25-yy);
+								diffMin.x = pixelPos.x+ax;
+								diffMax.x = ax-pixelPos.x;
+								float ay = sqrt(0.25-xx);
+								diffMin.y = pixelPos.y+ay;
+								diffMax.y = ay-pixelPos.y;
+								diffMin.z = pixelPos.z+0.5;
+								diffMax.z = 0.5-pixelPos.z;
+								rendered=1;
+							}
+						}break;
+			case CONE : {
+							if(pixelPos.y<0.5 && pixelPos.y>-0.5) {
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float yy = (pixelPos.y-0.5)*(pixelPos.y-0.5);
+								float zz = (pixelPos.z)*(pixelPos.z);
+								if((xx+zz)/yy<0.25){ 
+									float ax = sqrt(0.25*yy-zz);
+									diffMin.x = pixelPos.x+ax;
+									diffMax.x = ax-pixelPos.x;
+									float ay = sqrt((yy+xx)/0.25);
+									diffMin.y = pixelPos.y+0.5;
+									diffMax.y = 0.5-pixelPos.y;
+									float az = sqrt(0.25*yy-xx);
+									diffMin.z = pixelPos.z+az;
+									diffMax.z = az-pixelPos.z;
+									rendered=1;
+								}
+							}
+						} break;
+			case TUBE : {
+							if(length(vec2(pixelPos.x, pixelPos.z))<=0.5
+									&& (pixelPos.y>-0.5 && pixelPos.y<0.5)) { 
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float zz = (pixelPos.z)*(pixelPos.z);
+								float ax = sqrt(0.25-zz);
+								diffMin.x = pixelPos.x+ax;
+								diffMax.x = ax-pixelPos.x;
+								float az = sqrt(0.25-xx);
+								diffMin.z = pixelPos.z+az;
+								diffMax.z = az-pixelPos.z;
+								diffMin.y = pixelPos.y+0.5;
+								diffMax.y = 0.5-pixelPos.y;
+								rendered=1;
+							}
+						} break;
+			case SPHERE : {
+							  if(length(pixelPos)<=0.5) { 
+								  float xx = (pixelPos.x)*(pixelPos.x);
+								  float yy = (pixelPos.y)*(pixelPos.y);
+								  float zz = (pixelPos.z)*(pixelPos.z);
+								  float ax = sqrt(0.25-yy-zz);
+								  diffMin.x = pixelPos.x+ax;
+								  diffMax.x = ax-pixelPos.x;
+								  float ay = sqrt(0.25-xx-zz);
+								  diffMin.y = pixelPos.y+ay;
+								  diffMax.y = ay-pixelPos.y;
+								  float az = sqrt(0.25-xx-yy);
+								  diffMin.z = pixelPos.z+az;
+								  diffMax.z = az-pixelPos.z;
+								  rendered=1;
+							  }
+						  } break;
+			case BOX : {
+						   diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+						   diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+						   if(diffMin.x>0 && diffMax.x>0
+								   && diffMin.y>0 && diffMax.y>0
+								   && diffMin.z>0 && diffMax.z>0){
+							   rendered=1; 
+						   } 
+					   } break;
+			case FRAME : {
+							 diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+							 diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+							 if(diffMin.x>0 && diffMax.x>0
+									 && diffMin.y>0 && diffMax.y>0
+									 && diffMin.z>0 && diffMax.z>0){
+								 rendered=1; 
+							 } 
+						 } break;
+			case MODEL : {
+							 ivec2 selSize = textureSize(selectTex, 0);
+							 vec4 sel = texelFetch(selectTex,
+									 ivec2(coordX*float(selSize.x), 
+										 coordY*float(selSize.y)), 
+									 0);
+							 //get front surfaces before depth map
+							 if(pixZ<=cutZ+thickness/1000.0) { 
+								 if(sel.z==0) {
+									 if(sel.x==shapeID) {
+										 rendered=1; 
+									 }
+									 else if((int(shapeIDBit)&int(sel.w))>0) {
+										 diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+										 diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+										 if(diffMin.x>0 && diffMax.x>0
+												 && diffMin.y>0 && diffMax.y>0
+												 && diffMin.z>0 && diffMax.z>0){
+											 rendered=1; 
+										 }
+									 }
+								 }
+								 if(surface>0 
+										 && (pixZ>cutZ 
+											 || (sel.z>0 && (int(shapeIDBit)&int(sel.w))>0))) {
+									 rendered=2;
+								 }
+							 }
+						 } break;
+		}
+		if(rendered>0) {
+			ratioWithinBox = (pixelPos)+0.5;
+			//test if on the surface
+			if(diffMin.x*modelScale.x<thickness || 
+					diffMax.x*modelScale.x<thickness || 
+					diffMin.y*modelScale.y<thickness || 
+					diffMax.y*modelScale.y<thickness || 
+					diffMin.z*modelScale.z<thickness || 
+					diffMax.z*modelScale.z<thickness) { 
+				rendered=2; 
+			} 
+			//extend ratiowithinbox to multiplesubshapes
+			//and get gradient ratio according to type
+			float gradRatio = 0;
+			vec3 subAdd;
+			vec3 subDiv;
+			if(insideStructure==0) {//from center
+				subAdd = vec3(subShapeID, subShapeID, subShapeID);
+				subDiv = vec3(subShapesNb, subShapesNb, subShapesNb);
+				ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;
+				outRatioWithinBox.xyz=ratioWithinBox.xyz;
+				gradRatio = length(ratioWithinBox.xyz
+						- vec3(0.5,0.5,0.5))/0.5;
+			}
+			else {//from surface or along axes
+				subAdd = vec3(0,0, subShapeID);
+				subDiv = vec3(1,1, subShapesNb);
+				ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;
+				outRatioWithinBox.xyz=ratioWithinBox.xyz;
+				if(insideStructure==1) {
+					ratioWithinBox.x=0.5;
+				}
+				else if(insideStructure==2) {
+					ratioWithinBox.y=0.5;
+				}
+				else if(insideStructure==3 && shapeGeom!=PATH) {
+					ratioWithinBox.z=0.5;
+				}
+				switch(shapeGeom) {
+					case BOX : {
+								   vec3 q = abs(ratioWithinBox.xyz
+										   -vec3(0.5,0.5,0.5))*2.0 
+									   - vec3(1.0,1.0,1.0);
+								   gradRatio = 1.0-abs(length(max(q,0.0)) 
+										   + min(max(q.x,max(q.y,q.z)),0.0));
+							   } break;
+					case SPHERE : {
+									  gradRatio = length(ratioWithinBox.xyz
+											  - vec3(0.5,0.5,0.5))/0.5;
+								  } break;
+					case PATH  : {
+									 vec2 d = abs(vec2(length((ratioWithinBox.xy-vec2(0.5, 0.5))*2.0), 
+												 (ratioWithinBox.z-0.5)*2.0)) 
+										 - vec2(1.0,1.0);
+									 gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)
+											 + length(max(d,0.0)));
+								 } break;
+					case TUBE  : {
+									 vec2 d = abs(vec2(length((ratioWithinBox.xz-vec2(0.5, 0.5))*2.0), 
+												 (ratioWithinBox.y-0.5)*2.0)) 
+										 - vec2(1.0,1.0);
+									 gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0)
+											 + length(max(d,0.0)));
+								 } break;
+					case CONE : { 
+									float q = length((ratioWithinBox.xz
+												- vec2(0.5,0.5))*2.0);
+									gradRatio = 1.0-abs(max(dot(vec2(0.5,0.5),
+													vec2(q,(ratioWithinBox.y-1.0))),
+												-1.0-(ratioWithinBox.y-1.0)));
+								} break;
+					case FRAME : { //FIXME compute frame SDF
+									 vec3 q = abs(ratioWithinBox.xyz
+											 -vec3(0.5,0.5,0.5))*2.0 
+										 - vec3(1.0,1.0,1.0);
+									 gradRatio = 1.0-abs(length(max(q,0.0)) 
+											 + min(max(q.x,max(q.y,q.z)),0.0));
+								 } break;
+					case MODEL : { 
+									 gradRatio = texture(surfDistTex, 
+											 ratioWithinBox).r
+										 * structureRatio;
+								 } break;
+					default :{//defaults to sphere
+								 gradRatio = length(ratioWithinBox.xyz
+										 - vec3(0.5,0.5,0.5))/0.5;
+							 } break;
+				}
+			}
+			//texture coordinates
+			vec3 texCoords = vec3(1-ratioWithinBox.x,
+					1-ratioWithinBox.y,
+					ratioWithinBox.z);
+
+			//start with shapeColor
+			finalColor = shapeColor;
+			//test gradient
+			if(gradientAlpha>0) {
+				float gradColor = 
+					pow(gradientCurveRatio<0?1.0-gradRatio:gradRatio, 
+							abs(gradientCurveRatio));
+				if(gradientSteps>1) {
+					gradColor = floor(gradColor*gradientSteps)
+						/ gradientSteps;
+				}
+				gradColor*=(gradRatio<=1.0)?1.0:0.0;
+				if(gradientType>0) {//gradient texture
+					finalColor=finalColor*(1.0-gradientAlpha) 
+						+ finalColor*gradientAlpha
+						* texture(gradientTex, 
+								vec2(gradRatio, 0.0)).xyz;
+				}
+				else {
+					finalColor=finalColor*(1.0-gradientAlpha) 
+						+ finalColor*gradColor*gradientAlpha;
+				}
+			}
+			//test density
+			if(densityAlpha>0) {
+				float densColor = 
+					pow(densityCurveRatio<0?1.0-gradRatio:gradRatio, 
+							abs(densityCurveRatio));
+				if(densityType==0 &&  //layers
+						length(mod(densColor*100.0, 
+								densitySize*100.0))
+						< densityRatio*densitySize*100.0) {
+					densColor = 1.0;
+					densColor*=(gradRatio<=1.0)?1.0:0.0;
+				} 
+				else if(densityType==1 //grid
+						&& (length(mod(ratioWithinBox.x*100,
+									densitySize*100.0))
+							<densitySize*densityRatio*100.0 
+							|| length(mod(ratioWithinBox.y*100,
+									densitySize*100.0))
+							<densitySize*densityRatio*100.0 
+							|| length(mod(ratioWithinBox.z*100,
+									densitySize*100.0))
+							<densitySize*densityRatio*100.0)) { 
+					densColor = 1.0;
+				} 
+				else if(densityType==2   //pointcloud
+						&& floor(random(ratioWithinBox.xyz)
+							*floor(100.0))>100.0*densColor) {
+					densColor = 1.0; 
+					densColor*=(gradRatio<=1.0)?1.0:0.0;
+				}
+				else {
+					densColor = 0.0;
+				}
+				finalColor=finalColor*(1.0-densityAlpha) 
+					+ finalColor*densColor*densityAlpha;
+			}
+			//test texture
+			if(texAlpha>0) {
+				vec3 texColor = texture(insideTex, 
+						texOffset+texScale*texCoords).xyz;
+				if(texGray>0) {
+					texColor=vec3((texColor.r+texColor.g+texColor.b)
+							/ 3.0);
+				}
+				finalColor=finalColor*(1.0-texAlpha) 
+					+ finalColor*texColor*texAlpha;
+			}
+		}
+		//SURFACE test
+		if(rendered>1) { 
+			finalColor = surfaceColor;
+		}
+	}
+	//final test, output if rendered or not, output final color
+	if(rendered>0 && length(finalColor)>0) { 
+		if((insideVisible>0 && rendered==1) 
+				|| (surface>0 && rendered==2)) {
+			color = vec4(finalColor, 1.0);//display
+		}
+		else {
+			color = vec4(0.0, 0.0, 0.0, 1.0);
+		}
+	}
+	else { //DISCARD
+		discard;
+	}
+};
diff --git a/src/shaders/render43.fs b/src/shaders/render43.fs
new file mode 100644
index 0000000000000000000000000000000000000000..f1eb72e53b6e2032b39685ac2b1af2dc2c4b1645
--- /dev/null
+++ b/src/shaders/render43.fs
@@ -0,0 +1,557 @@
+#version 430
+
+const int BOX=0;
+const int SPHERE=1;
+const int TUBE=2;
+const int CONE=3;
+const int FRAME=4;
+const int PATH=5;
+const int MODEL=10;
+
+in vec3 viewRay;
+in vec2 uvCoords;
+
+layout(binding=0) uniform sampler2D sliceTex;
+layout(binding=1) uniform sampler2D selectTex;
+layout(binding=2) uniform sampler3D insideTex;
+layout(binding=3) uniform sampler2D surfaceTex;
+layout(binding=4) uniform sampler3D reactTex;
+layout(binding=5) uniform sampler3D surfDistTex;
+layout(binding=6) uniform sampler2D gradientTex;
+layout(r32ui, binding=0) uniform coherent uimage2D outputTex;
+layout(r32i, binding=1) uniform coherent iimage2D outputAudioTex;
+layout(r32i, binding=2) uniform coherent iimage2D phases;
+
+uniform int mixSize;
+uniform float maxSinValue;
+uniform int nRate;
+uniform float phase;
+uniform int bufSize;
+
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float mirrored;
+uniform float shapeID;
+uniform float shapeIDBit;
+uniform int shapeGeom;
+uniform float subShapeID;
+uniform float subShapesNb;
+uniform mat4 subShapeInvMat;
+uniform mat4 viewMat;
+uniform mat4 modelMat;
+uniform mat4 invModelMat;
+uniform vec3 modelScale;
+uniform int revealedBy;
+
+uniform vec3 shapeColor;
+//0: none, 1:color, 2:texture
+uniform int surface;
+uniform vec3 surfaceColor;
+uniform int insideOutputOnly;
+uniform int reactivity;
+uniform float thickness;
+
+uniform int insideVisible;
+//0:from center, 1:along x, 2: along y, 3:along z, 4 :from surface
+uniform int insideStructure;
+uniform float structureRatio;
+
+uniform float gradientAlpha;
+//0:greyscale, 1:texture
+uniform int gradientType;
+uniform int gradientSteps;
+uniform float gradientCurveRatio;
+
+uniform float densityAlpha;
+//0:layers, 1:grid, 2:pointcloud
+uniform int densityType;
+uniform float densityRatio;
+uniform float densitySize;
+uniform float densityCurveRatio;
+
+uniform float texAlpha;
+uniform vec3 texOffset;
+uniform vec3 texScale;
+uniform int texGray;
+
+uniform int revSize;
+uniform int revSurface;
+uniform int revInside;
+uniform int revCenter;
+uniform int revCursor;
+uniform int revColor;
+uniform int revHisto;
+uniform int revVoxels;
+uniform float revSubShapeID;
+uniform int shapeOutSize;
+uniform int histoOutSize;
+uniform int voxelOutSize;
+uniform int depthOutSize;
+uniform int depthOutNb;
+uniform vec4 boundingRect;
+
+vec3 rgb2hsv(vec3 c){
+	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+	vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+	vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+	float d = q.x - min(q.w, q.y);
+	float e = 1.0e-10;
+	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)),d/(q.x + e), q.x);
+}
+
+float random (vec3 st){
+	return fract(sin(dot(st.xyz,
+					vec3(12.9898,78.233, 102.234)))*
+			43758.5453123);
+}
+
+out vec4 color;
+
+void additiveSynth(vec4 color){
+	int freq;
+	int i = 2;
+	float note = 20 + color.x * 50;//color.x * 127;
+	int octave = int(note/12);
+	float modNote = int(note) % 12;
+	int ratioSampleFreq;
+	float ratioFreqSample;
+	int initPhase;
+	int fragPhase;
+	int ind;
+
+	if(modNote >= 8.5){
+		note = octave * 12 + 10;
+		ind = 4 * octave + 3;
+	}
+	else if(modNote >= 5.5){
+		note = octave * 12 + 7;
+		ind = 4 * octave + 2;
+	}
+	else if(modNote >= 2.0){
+		note = octave * 12 + 4;
+		ind = 4 * octave + 1;
+	}
+	else{
+		note = octave * 12;
+		ind = 4 * octave;
+	}
+
+	/*int n = int(color.x * 3);
+	  int note = 0;
+	  if(n == 0){
+	  note = 40;
+	  }
+	  else if(n == 1){
+	  note = 44;
+	  }
+	  else if(n == 2){
+	  note = 47;
+	  }
+	  else{
+	  note = 50;
+	  }
+	  ind = n;*/
+
+	freq = int(440 * pow(2, (note-69)/12));
+
+	ratioSampleFreq = nRate/freq;
+	ratioFreqSample = 1.0/ratioSampleFreq;
+
+	fragPhase = imageLoad(phases, ivec2(ind, 0)).x;
+
+	float a = sin(fragPhase *(3.14f) * freq/nRate);
+
+	float s[2];
+
+	s[0] = 1.0f;
+	s[1] = 0.0f;
+	imageStore(outputAudioTex, ivec2(0, ind), ivec4(42));
+
+	while (i < bufSize) {
+		imageStore(outputAudioTex, ivec2(i, ind), ivec4(int(s[1]*maxSinValue)));
+
+		s[0] = s[0] - a*s[1];
+		s[1] = s[1] + a*s[0];
+
+		i += 1;
+	}
+
+	imageStore(outputAudioTex, ivec2(1, ind), ivec4(ratioSampleFreq));
+}
+
+void main(void) {
+	//get fragment coordinates
+	float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	ivec2 sliSize = textureSize(sliceTex, 0);
+
+	//retrieve pixel in slicing texture
+	vec4 sli = texelFetch(sliceTex, ivec2(coordX*float(sliSize.x), coordY*float(sliSize.y)), 0);
+	float pixZ=abs(gl_FragCoord.z);
+	float cutZ=abs(sli.z);
+	int depthID=int(sli.y)-1;
+
+	int outCols=imageSize(outputTex).x;
+	int outOffset=(int(shapeID-1)*depthOutNb+(depthID-1))*revSize;
+
+	int rendered=0;
+	vec3 finalColor = shapeColor;
+	float alpha=0;
+	vec3 pixelPosW;
+	vec3 pixelPos = vec3(0.0, 0.0, 1.0);
+	vec3 ratioWithinBox = vec3(0.0, 0.0, 0.0);
+	vec3 outRatioWithinBox = vec3(0.0, 0.0, 0.0);
+
+	//if there is a slicing pixel aligned with our coordinate
+	//and we are revealed by this depth module
+	if(cutZ>0 && (revealedBy & (1<<(1+depthID)))>0 ) {
+		//compute the slicing pixel world position
+		pixelPosW = vec3(viewMat[3][0], viewMat[3][1], viewMat[3][2]) + vec3(normalize(viewRay) * sli.w);
+		pixelPosW.x = pixelPosW.x*(-2.0*(1-mirrored)+1.0);
+		//compute the slicing pixel position in model coords
+		pixelPos = (invModelMat * vec4(pixelPosW,1.0)).xyz;
+
+		//depending on type, test if slicing pixel inside 
+		//and retrieve distance to the surface on each axis
+		vec3 diffMin = vec3(1.0);
+		vec3 diffMax = vec3(1.0);
+
+		switch(shapeGeom) {
+			case PATH : {
+							//use min/max/size of current segment
+							pixelPos = (subShapeInvMat*vec4(pixelPos,1.0)).xyz;
+							if(length(vec2(pixelPos.x, pixelPos.y))<=0.5 && (pixelPos.z>-0.5 && pixelPos.z<0.5)) {
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float yy = (pixelPos.y)*(pixelPos.y);
+								float ax = sqrt(0.25-yy);
+								diffMin.x = pixelPos.x+ax;
+								diffMax.x = ax-pixelPos.x;
+								float ay = sqrt(0.25-xx);
+								diffMin.y = pixelPos.y+ay;
+								diffMax.y = ay-pixelPos.y;
+								diffMin.z = pixelPos.z+0.5;
+								diffMax.z = 0.5-pixelPos.z;
+								rendered=1;
+							}
+						} break;
+			case CONE : {
+							if(pixelPos.y<0.5 && pixelPos.y>-0.5) {
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float yy = (pixelPos.y-0.5)*(pixelPos.y-0.5);
+								float zz = (pixelPos.z)*(pixelPos.z);
+								if((xx+zz)/yy<0.25){
+									float ax = sqrt(0.25*yy-zz);
+									diffMin.x = pixelPos.x+ax;
+									diffMax.x = ax-pixelPos.x;
+									float ay = sqrt((yy+xx)/0.25);
+									diffMin.y = pixelPos.y+0.5;
+									diffMax.y = 0.5-pixelPos.y;
+									float az = sqrt(0.25*yy-xx);
+									diffMin.z = pixelPos.z+az;
+									diffMax.z = az-pixelPos.z;
+									rendered=1;
+								}
+							}
+						} break;
+			case TUBE : {
+							if(length(vec2(pixelPos.x, pixelPos.z))<=0.5 && (pixelPos.y>-0.5 && pixelPos.y<0.5)) {
+								float xx = (pixelPos.x)*(pixelPos.x);
+								float zz = (pixelPos.z)*(pixelPos.z);
+								float ax = sqrt(0.25-zz);
+								diffMin.x = pixelPos.x+ax;
+								diffMax.x = ax-pixelPos.x;
+								float az = sqrt(0.25-xx);
+								diffMin.z = pixelPos.z+az;
+								diffMax.z = az-pixelPos.z;
+								diffMin.y = pixelPos.y+0.5;
+								diffMax.y = 0.5-pixelPos.y;
+								rendered=1;
+							}
+						} break;
+			case SPHERE : {
+							  if(length(pixelPos)<=0.5) {
+								  float xx = (pixelPos.x)*(pixelPos.x);
+								  float yy = (pixelPos.y)*(pixelPos.y);
+								  float zz = (pixelPos.z)*(pixelPos.z);
+								  float ax = sqrt(0.25-yy-zz);
+								  diffMin.x = pixelPos.x+ax;
+								  diffMax.x = ax-pixelPos.x;
+								  float ay = sqrt(0.25-xx-zz);
+								  diffMin.y = pixelPos.y+ay;
+								  diffMax.y = ay-pixelPos.y;
+								  float az = sqrt(0.25-xx-yy);
+								  diffMin.z = pixelPos.z+az;
+								  diffMax.z = az-pixelPos.z;
+								  rendered=1;
+							  }
+						  } break;
+			case BOX : {
+						   diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+						   diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+						   if(diffMin.x>0 && diffMax.x>0 && diffMin.y>0 && diffMax.y>0 && diffMin.z>0 && diffMax.z>0){
+							   rendered=1;
+						   }
+					   } break;
+			case FRAME : {
+							 diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+							 diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+							 if(diffMin.x>0 && diffMax.x>0 && diffMin.y>0 && diffMax.y>0 && diffMin.z>0 && diffMax.z>0){
+								 rendered=1;
+							 }
+						 } break;
+			case MODEL : {
+							 ivec2 selSize = textureSize(selectTex, 0);
+							 vec4 sel = texelFetch(selectTex,
+									 ivec2(coordX*float(selSize.x), coordY*float(selSize.y)), 0);
+							 //get front surfaces before depth map
+							 if(pixZ<=cutZ+thickness/1000.0) {
+								 if(sel.z==0) {
+									 if(sel.x==shapeID) {
+										 rendered=1;
+									 }
+									 else if((int(shapeIDBit)&int(sel.w))>0) {
+										 diffMin = pixelPos - vec3(-0.5, -0.5, -0.5);
+										 diffMax = vec3(0.5, 0.5, 0.5) - pixelPos;
+										 if(diffMin.x>0 && diffMax.x>0 && diffMin.y>0 && diffMax.y>0 && diffMin.z>0 && diffMax.z>0){
+											 rendered=1;
+										 }
+									 }
+								 }
+								 if(surface>0 && (pixZ>cutZ || (sel.z>0 && (int(shapeIDBit)&int(sel.w))>0))) {
+									 rendered=2;
+								 }
+							 }
+						 } break;
+		}
+		if(rendered>0) {
+			ratioWithinBox = (pixelPos)+0.5;
+			//test if on the surface
+			if(diffMin.x*modelScale.x<thickness || diffMax.x*modelScale.x<thickness || diffMin.y*modelScale.y<thickness ||
+					diffMax.y*modelScale.y<thickness || diffMin.z*modelScale.z<thickness || diffMax.z*modelScale.z<thickness) {
+				rendered=2;
+			}
+			//extend ratiowithinbox to multiplesubshapes
+			//and get gradient ratio according to type
+			float gradRatio = 0;
+			vec3 subAdd;
+			vec3 subDiv;
+			if(insideStructure==0) {
+				//from center
+				subAdd = vec3(subShapeID, subShapeID, subShapeID);
+				subDiv = vec3(subShapesNb, subShapesNb, subShapesNb);
+				ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;
+				outRatioWithinBox.xyz=ratioWithinBox.xyz;
+				gradRatio = length(ratioWithinBox.xyz - vec3(0.5,0.5,0.5))/0.5;
+			}
+			else {
+				//from surface or along axes
+				subAdd = vec3(0,0, subShapeID);
+				subDiv = vec3(1,1, subShapesNb);
+				ratioWithinBox.xyz=(ratioWithinBox.xyz+subAdd)/subDiv;
+				outRatioWithinBox.xyz=ratioWithinBox.xyz;
+				if(insideStructure==1) {
+					ratioWithinBox.x=0.5;
+				}
+				else if(insideStructure==2) {
+					ratioWithinBox.y=0.5;
+				}
+				else if(insideStructure==3 && shapeGeom!=PATH) {
+					ratioWithinBox.z=0.5;
+				}
+				switch(shapeGeom) {
+					case BOX : {
+								   vec3 q = abs(ratioWithinBox.xyz - vec3(0.5,0.5,0.5))*2.0 - vec3(1.0,1.0,1.0);
+								   gradRatio = 1.0-abs(length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0));
+							   } break;
+					case SPHERE : {
+									  gradRatio = length(ratioWithinBox.xyz - vec3(0.5,0.5,0.5))/0.5;
+								  } break;
+					case PATH  : {
+									 vec2 d = abs(vec2(length((ratioWithinBox.xy-vec2(0.5, 0.5))*2.0), (ratioWithinBox.z-0.5)*2.0)) - vec2(1.0,1.0);
+									 gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0) + length(max(d,0.0)));
+								 } break;
+					case TUBE  : {
+									 vec2 d = abs(vec2(length((ratioWithinBox.xz-vec2(0.5, 0.5))*2.0), (ratioWithinBox.y-0.5)*2.0)) - vec2(1.0,1.0);
+									 gradRatio = 1.0 - abs(min(max(d.x,d.y),0.0) + length(max(d,0.0)));
+								 } break;
+					case CONE : {
+									float q = length((ratioWithinBox.xz - vec2(0.5,0.5))*2.0);
+									gradRatio = 1.0-abs(max(dot(vec2(0.5,0.5), vec2(q,(ratioWithinBox.y-1.0))), -1.0-(ratioWithinBox.y-1.0)));
+								} break;
+					case FRAME : {
+									 //FIXME compute frame SDF
+									 vec3 q = abs(ratioWithinBox.xyz - vec3(0.5,0.5,0.5))*2.0 - vec3(1.0,1.0,1.0);
+									 gradRatio = 1.0-abs(length(max(q,0.0)) + min(max(q.x,max(q.y,q.z)),0.0));
+								 } break;
+					case MODEL : {
+									 gradRatio = texture(surfDistTex, ratioWithinBox).r * structureRatio;
+								 } break;
+					default :{
+								 //defaults to sphere
+								 gradRatio = length(ratioWithinBox.xyz - vec3(0.5,0.5,0.5))/0.5;
+							 } break;
+				}
+			}
+			/*imageAtomicAdd(outputAudioTex, ivec2(0,0), 1);
+			  int i = 1;
+			  float ratioSampleFreq = nRate/700.0;
+			  float ratioFreqSample = 1.0/ratioSampleFreq;
+			  int fragPhase = int(phase);
+			  while (i < bufSize) {
+			  int val = int(cos(fragPhase * ratioFreqSample * (2 * 3.14))*maxSinValue);
+			  imageAtomicAdd(outputAudioTex, ivec2(i,0), val);
+			//imageAtomicAdd(outputAudioTex, ivec2(i+1,0),val);
+			fragPhase += 1;
+			fragPhase = fragPhase % int(ratioSampleFreq);
+			i += 1;
+			}*/
+
+			//texture coordinates
+			vec3 texCoords = vec3(1-ratioWithinBox.x, 1-ratioWithinBox.y, ratioWithinBox.z);
+
+			//start with shapeColor
+			finalColor = shapeColor;
+			//test gradient
+			if(gradientAlpha>0) {
+				float gradColor = pow(gradientCurveRatio<0?1.0-gradRatio:gradRatio, abs(gradientCurveRatio));
+				if(gradientSteps>1) {
+					gradColor = floor(gradColor*gradientSteps) / gradientSteps;
+				}
+				gradColor*=(gradRatio<=1.0)?1.0:0.0;
+				if(gradientType>0) {
+					//gradient texture
+					finalColor=finalColor*(1.0-gradientAlpha) + finalColor*gradientAlpha * texture(gradientTex, vec2(gradRatio, 0.0)).xyz;
+				}
+				else {
+					finalColor=finalColor*(1.0-gradientAlpha) + finalColor*gradColor*gradientAlpha;
+				}
+			}
+			//test density
+			if(densityAlpha>0) {
+				float densColor = pow(densityCurveRatio<0?1.0-gradRatio:gradRatio, abs(densityCurveRatio));
+				if(densityType==0 && //layers
+						length(mod(densColor*100.0, densitySize*100.0)) < densityRatio*densitySize*100.0) {
+					densColor = 1.0;
+					densColor*=(gradRatio<=1.0)?1.0:0.0;
+				}
+				else if(densityType==1 //grid
+						&& (length(mod(ratioWithinBox.x*100, densitySize*100.0)) < densitySize*densityRatio*100.0
+							|| length(mod(ratioWithinBox.y*100, densitySize*100.0)) < densitySize*densityRatio*100.0
+							|| length(mod(ratioWithinBox.z*100, densitySize*100.0)) < densitySize*densityRatio*100.0)) {
+					densColor = 1.0;
+				}
+				else if(densityType==2 //pointcloud
+						&& floor(random(ratioWithinBox.xyz)*floor(100.0))>100.0*densColor) {
+					densColor = 1.0;
+					densColor*=(gradRatio<=1.0)?1.0:0.0;
+				}
+				else {
+					densColor = 0.0;
+				}
+				finalColor=finalColor*(1.0-densityAlpha) + finalColor*densColor*densityAlpha;
+			}
+			//test texture
+			if(texAlpha>0) {
+				vec3 texColor = texture(insideTex, texOffset+texScale*texCoords).xyz;
+				if(texGray>0) {
+					texColor=vec3((texColor.r+texColor.g+texColor.b) / 3.0);
+				}
+				finalColor=finalColor*(1.0-texAlpha) + finalColor*texColor*texAlpha;
+			}
+
+			//if revealing something, output values
+			if(sli.x>=1.0 && depthID<=depthOutNb) {
+				//inside output
+				if(revInside>0 && rendered==1) {
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revInside,outCols), floor((outOffset+revInside))/outCols), 1);					
+				}
+				outRatioWithinBox.x=clamp(outRatioWithinBox.x, 0, 1);
+				outRatioWithinBox.y=clamp(outRatioWithinBox.y, 0, 1);
+				outRatioWithinBox.z=clamp(outRatioWithinBox.z, 0, 1);
+				//compute min,max on the three axes
+				int xk=int(outRatioWithinBox.x*1000.0);
+				int yk=int(outRatioWithinBox.y*1000.0);
+				int zk=int(outRatioWithinBox.z*1000.0);
+				//output min/max ratios
+				if(revCenter>0) {
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+0,outCols), floor((outOffset+revCenter+0)/outCols)), 1000-xk);
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+1,outCols), floor((outOffset+revCenter+1)/outCols)), xk);
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+2,outCols), floor((outOffset+revCenter+2)/outCols)), 1000-yk);
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+3,outCols), floor((outOffset+revCenter+3)/outCols)), yk);
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+4,outCols), floor((outOffset+revCenter+4)/outCols)), 1000-zk);
+					imageAtomicMax(outputTex, ivec2(mod(outOffset+revCenter+5,outCols), floor((outOffset+revCenter+5)/outCols)), zk);
+				}
+				//convert from rgb to hsv
+				vec3 hsv = rgb2hsv(finalColor);
+				//Sum color channels
+				if(revColor>0) {
+					//count nb revealed points
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revColor+0,outCols), floor((outOffset+revColor+0)/outCols)), 1);
+					//sum point h
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revColor+1,outCols), floor((outOffset+revColor+1)/outCols)), clamp(int(hsv.x*1000.0),0,1000));
+					//sum s
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revColor+2,outCols), floor((outOffset+revColor+2)/outCols)), clamp(int(hsv.y*1000.0),0,1000));
+					//sum v
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revColor+3,outCols), floor((outOffset+revColor+3)/outCols)), clamp(int(hsv.z*1000.0),0,1000));
+				}
+				//histo : accumulate on luminance bins
+				if(revHisto>0) {
+					//count nb revealed points
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revHisto,outCols), 
+								floor((outOffset+revHisto)/outCols)), 1);
+					int bin = int(hsv.z*float(histoOutSize-1));
+					imageAtomicAdd(outputTex, ivec2(mod(outOffset+revHisto+1+bin,outCols), floor((outOffset+revHisto+1+bin)/outCols)), 1);
+				}
+
+				//2D grid of projected voxels (nbvox, 3D coords, lum)
+				if(revVoxels>0) {
+					//compute pixel ratio within 2D bounding rect
+					vec2 pixRatio = (vec2(coordX, coordY) - boundingRect.xy) / (boundingRect.zw-boundingRect.xy);
+					pixRatio.x = clamp(pixRatio.x, 0.0, 1.0);
+					pixRatio.y = clamp(pixRatio.y, 0.0, 1.0);
+					//compute offset in voxel output
+					int voxOff = outOffset+revVoxels;
+					voxOff+=5*(int(pixRatio.x*voxelOutSize) + int((1.0-pixRatio.y)*voxelOutSize)*voxelOutSize);
+					//accumulate points
+					imageAtomicAdd(outputTex, ivec2(mod(voxOff,outCols), floor((voxOff)/outCols)), 1);
+					//accumulate coords
+					imageAtomicAdd(outputTex, ivec2(mod(voxOff+1,outCols), floor((voxOff+1)/outCols)), clamp(int(outRatioWithinBox.x*1000.0),0,1000));
+					imageAtomicAdd(outputTex, ivec2(mod(voxOff+2,outCols),floor((voxOff+2)/outCols)), clamp(int(outRatioWithinBox.y*1000.0),0,1000));
+					imageAtomicAdd(outputTex, ivec2(mod(voxOff+3,outCols), floor((voxOff+3)/outCols)), clamp(int(outRatioWithinBox.z*1000.0),0,1000));
+					//accumulate lum
+					imageAtomicAdd(outputTex, ivec2(mod(voxOff+4,outCols), floor((voxOff+4)/outCols)),
+							clamp(int(hsv.z*1000.0),0,1000));
+				}
+			}
+		}
+
+		//SURFACE test
+		if(rendered>1) {
+			finalColor = surfaceColor;
+
+			if(revSurface>0 && sli.x>=1.0 && depthID<=depthOutNb) {
+				imageAtomicMax(outputTex, ivec2(mod(outOffset+revSurface,outCols), floor((outOffset+revSurface)/outCols)), 1);
+			}
+		}
+	}
+	//final test, output if rendered or not, output final color
+	if(rendered>0 && length(finalColor)>0) { 
+
+		if(revSize>0) {
+			imageAtomicOr(outputTex, ivec2(mod(outOffset,outCols), floor((outOffset))/outCols), rendered);
+		}
+
+		if((insideVisible>0 && rendered==1) || (surface>0 && rendered==2)) {
+			color = vec4(finalColor, 1.0);
+
+			additiveSynth(color);
+		}
+		else {
+			color = vec4(0.0, 0.0, 0.0, 1.0);
+		}
+	}
+	else { //DISCARD
+		discard;
+	}
+};
+
diff --git a/src/shaders/render43.vs b/src/shaders/render43.vs
new file mode 100644
index 0000000000000000000000000000000000000000..277dfc1029c7492d3d890ff1cb811dcd50916791
--- /dev/null
+++ b/src/shaders/render43.vs
@@ -0,0 +1,25 @@
+#version 430 
+
+in vec3 vertex; 
+in vec2 texCoords;
+
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float mirrored;
+
+out vec3 viewRay;
+out vec2 uvCoords;
+
+void main(void) {
+	vec4 posWS = modelMat * vec4(vertex, 1.0);
+	if(mirrored<1) {
+		posWS.x = -posWS.x;
+	}
+	gl_Position = viewProjMat * posWS;
+	viewRay = posWS.xyz - vec3(viewMat[3][0],
+			viewMat[3][1],
+			viewMat[3][2]);
+	uvCoords=texCoords;
+};
+
diff --git a/src/shaders/select30.fs b/src/shaders/select30.fs
new file mode 100644
index 0000000000000000000000000000000000000000..874a0b1508f25cb52618252799124d4cb25145f5
--- /dev/null
+++ b/src/shaders/select30.fs
@@ -0,0 +1,40 @@
+#version 130
+
+uniform sampler2D sliceTex;
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float shapeID;
+uniform float shapeIDBit;
+uniform float mirrored;
+uniform float thickness;
+uniform int surface;
+
+out vec4 color;
+
+void main(void) {
+	float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	ivec2 sliSize = textureSize(sliceTex, 0);
+	vec4 sli = texelFetch(sliceTex,
+			ivec2(coordX*float(sliSize.x),
+				coordY*float(sliSize.y)),
+			0);
+	float pixZ=abs(gl_FragCoord.z);
+	float cutZ=abs(sli.z);
+	//  keep all ids of back surfaces after depth map
+	if(pixZ>cutZ && cutZ>0) {
+		if((mirrored<1 && !gl_FrontFacing)
+				|| (mirrored>0 && gl_FrontFacing)) {
+			color = vec4(shapeID, 0, 
+					(abs(pixZ-cutZ)<thickness/1000.0 && surface>0)?1:0, 
+					shapeIDBit);
+		}
+		else { //occlude back when front face also behind
+			color = vec4(-shapeID, 0, 0, -shapeIDBit);
+		}
+	}
+	else {
+		discard;
+	}
+};
+
diff --git a/src/shaders/select30.vs b/src/shaders/select30.vs
new file mode 100644
index 0000000000000000000000000000000000000000..2d99e129a72851fbf1c062f59c25542f18ec86bd
--- /dev/null
+++ b/src/shaders/select30.vs
@@ -0,0 +1,16 @@
+#version 130
+
+in vec3 vertex;
+
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float mirrored;
+
+void main(void) {
+	vec4 posWS = modelMat * vec4(vertex, 1.0);
+	if(mirrored<1) {
+		posWS.x = -posWS.x;
+	}
+	gl_Position = viewProjMat * posWS;
+}
diff --git a/src/shaders/select43.fs b/src/shaders/select43.fs
new file mode 100644
index 0000000000000000000000000000000000000000..6a4473c41806f651829ce9ef8715967ddeb785de
--- /dev/null
+++ b/src/shaders/select43.fs
@@ -0,0 +1,40 @@
+#version 430 
+
+layout(binding=0) uniform sampler2D sliceTex;
+uniform float viewportWidth;
+uniform float viewportHeight;
+uniform float shapeID;
+uniform float shapeIDBit;
+uniform float mirrored;
+uniform float thickness;
+uniform int surface;
+
+out vec4 color;
+
+void main(void) {
+	float coordX = (gl_FragCoord.x-0.5)/viewportWidth;
+	float coordY = (gl_FragCoord.y-0.5)/viewportHeight;
+	ivec2 sliSize = textureSize(sliceTex, 0);
+	vec4 sli = texelFetch(sliceTex,
+			ivec2(coordX*float(sliSize.x),
+				coordY*float(sliSize.y)),
+			0);
+	float pixZ=abs(gl_FragCoord.z);
+	float cutZ=abs(sli.z);
+	//  keep all ids of back surfaces after depth map
+	if(pixZ>cutZ && cutZ>0) {
+		if((mirrored<1 && !gl_FrontFacing)
+				|| (mirrored>0 && gl_FrontFacing)) {
+			color = vec4(shapeID, 0, 
+					(abs(pixZ-cutZ)<thickness/1000.0 && surface>0)?1:0, 
+					shapeIDBit);
+		}
+		else { //occlude back when front face also behind
+			color = vec4(-shapeID, 0, 0, -shapeIDBit);
+		}
+	}
+	else {
+		discard;
+	}
+};
+
diff --git a/src/shaders/select43.vs b/src/shaders/select43.vs
new file mode 100644
index 0000000000000000000000000000000000000000..c9eb457bfaea1922a5527ded223e6ead65eec56e
--- /dev/null
+++ b/src/shaders/select43.vs
@@ -0,0 +1,16 @@
+#version 430
+
+in vec3 vertex;
+
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float mirrored;
+
+void main(void) {
+	vec4 posWS = modelMat * vec4(vertex, 1.0);
+	if(mirrored<1) {
+		posWS.x = -posWS.x;
+	}
+	gl_Position = viewProjMat * posWS;
+}
diff --git a/src/shaders/slice30.fs b/src/shaders/slice30.fs
new file mode 100644
index 0000000000000000000000000000000000000000..43069830abd4581f35f0531486d1dac56f1f1440
--- /dev/null
+++ b/src/shaders/slice30.fs
@@ -0,0 +1,21 @@
+#version 130 
+ 
+in float kept;
+in vec3 viewRay;
+flat in int outDepthID;
+ 
+out vec4 color;
+ 
+void main(void) {
+   float thresh=0.8;
+   if(kept>=thresh) {
+       color = vec4((kept-thresh)/(1.0-thresh),
+                     float(outDepthID),
+                     gl_FragCoord.z,
+                     length(viewRay));
+   }
+   else {
+       discard;
+   }
+//       color = vec4(1.0, 1.0, 0.0, 1.0);
+};
diff --git a/src/shaders/slice30.vs b/src/shaders/slice30.vs
new file mode 100644
index 0000000000000000000000000000000000000000..9ad4c20387e49546ab0533941de73c22e6fbe949
--- /dev/null
+++ b/src/shaders/slice30.vs
@@ -0,0 +1,134 @@
+#version 130 
+
+#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);
+#define mn3(a, b, c)  s2(a, b); s2(a, c);
+#define mx3(a, b, c)  s2(b, c); s2(a, c);
+#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b);
+#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d);
+#define mnmx5(a, b, c, d, e) s2(a,b); s2(c,d);mn3(a,c,e);mx3(b,d,e);
+#define mnmx6(a,b,c,d,e,f) s2(a,d);s2(b,e);s2(c,f);mn3(a,b,c);mx3(d,e,f);
+in vec3 vertex; 
+
+uniform sampler2D depthCamTex;
+uniform sampler2D depthCamTexFil;
+uniform sampler2D markersTex;
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float camXReso;
+uniform float camYReso;
+uniform float camXZFactor;
+uniform float camYZFactor;
+uniform int camFilter;
+uniform int background;
+uniform float camContThresh;
+uniform float camMarkers;
+uniform int depthType;
+uniform int depthID;
+uniform float outputCurs;
+uniform float mirrored;
+
+out vec3 viewRay;
+out float kept;
+flat out int outDepthID;
+
+void main(void) {
+	vec4 depthPos = vec4(0, 0, 0, 1);
+	vec4 posWS = vec4(0, 0, 0, 1);
+	//depth camera
+	if(depthType==0) {
+		vec2 coords = vertex.xy;
+		//get marker if any
+		if(camMarkers>0) {
+			outDepthID = int(float(texture(markersTex,
+							vec2(coords.x/camXReso,
+								coords.y/camYReso)).r)
+					* 255.0);
+		}
+		else {
+			outDepthID=depthID+1;
+		}
+		//get depth pixel in camera texture
+		float depth = 
+			float(texture(depthCamTex,
+						vec2(coords.x/camXReso,
+							coords.y/camYReso)).r)
+			* 65535.0;
+		kept=1.0;
+		float backgroundDepth=0;
+		if(background>0) {
+			float backDepth = float(texture(depthCamTex,
+						vec2(coords.x/camXReso,
+							coords.y/camYReso)).r)
+				* 65535.0;
+			if(backDepth<depth) {
+				depth=backDepth;
+				backgroundDepth=1;
+			}
+		}
+		if(depth<=500.0 || depth>8000.0) {
+			kept=0.0;
+		}
+		else if(backgroundDepth==0) {
+			//filter out contours
+			float maxD=camContThresh; 
+			bool contour=false;
+			for(int dX = -1; dX <= 1; ++dX) {
+				for(int dY = -1; dY <= 1; ++dY) {
+					if(abs(float(texture(depthCamTex,
+										vec2((coords.x+dX)/camXReso,
+											(coords.y+dY)/camYReso)).r)
+								* 65535.0
+								- depth) > maxD) {
+						contour=true;
+					}
+				}
+			}
+			if(contour) {
+				kept=0.0;
+			}
+			//see if needs filtering
+			if(camFilter>0) {
+				float filtDepth = float(texture(depthCamTexFil,
+							vec2(coords.x/camXReso,
+								coords.y/camYReso)).r)
+					* 65535.0;
+				//select either filtered version or current one
+				//depending on movement 
+				if(abs(filtDepth-depth)<camContThresh) {
+					float filRatio = abs(filtDepth-depth)/camContThresh;
+					depth=(1-filRatio)*filtDepth+(filRatio)*depth;
+				}
+			}
+		}
+		//test distance again
+		if(depth<=500.0 || depth>8000.0) {
+			kept=0.0;
+		}
+		//compute position in world units
+		depthPos = vec4((vertex.x/camXReso-0.5)
+				*depth*camXZFactor,
+				(0.5-(vertex.y/camYReso))
+				*depth*camYZFactor,
+				depth,
+				1.0);
+		//get world pos
+		posWS = modelMat * depthPos;
+	}
+	//other slicing shapes
+	else {
+		outDepthID=depthID+1;
+		kept=1.0;
+		depthPos=vec4(vertex, 1.0);
+		posWS = modelMat * depthPos;
+		if(mirrored<1) {
+			posWS.x = -posWS.x;
+		}
+	}
+	//keep/interpolate ray from view to each vertex
+	viewRay = (posWS.xyz - vec3(viewMat[3][0],
+				viewMat[3][1],
+				viewMat[3][2]));
+	gl_Position = viewProjMat * posWS;
+};
+
diff --git a/src/shaders/slice43.fs b/src/shaders/slice43.fs
new file mode 100644
index 0000000000000000000000000000000000000000..f1201a390610e1f9be9eb5cebe80f82772c711fe
--- /dev/null
+++ b/src/shaders/slice43.fs
@@ -0,0 +1,22 @@
+#version 430 
+ 
+in float kept;
+in vec3 viewRay;
+flat in int outDepthID;
+ 
+out vec4 color;
+ 
+void main(void) {
+   float thresh=0.8;
+   if(kept>=thresh) {
+	   color = vec4((kept-thresh)/(1.0-thresh),
+					 float(outDepthID),
+					 gl_FragCoord.z,
+					 length(viewRay));
+   }
+   else {
+	   discard;
+   }
+//       color = vec4(1.0, 1.0, 0.0, 1.0);
+};
+
diff --git a/src/shaders/slice43.vs b/src/shaders/slice43.vs
new file mode 100644
index 0000000000000000000000000000000000000000..660d649311496c5ed0eb23e06c8b02a808dc60f6
--- /dev/null
+++ b/src/shaders/slice43.vs
@@ -0,0 +1,145 @@
+#version 430 
+
+#define s2(a, b) temp = a; a = min(a, b); b = max(temp, b);
+#define mn3(a, b, c)  s2(a, b); s2(a, c);
+#define mx3(a, b, c)  s2(b, c); s2(a, c);
+#define mnmx3(a, b, c) mx3(a, b, c); s2(a, b);
+#define mnmx4(a, b, c, d) s2(a, b); s2(c, d); s2(a, c); s2(b, d);
+#define mnmx5(a, b, c, d, e) s2(a,b); s2(c,d);mn3(a,c,e);mx3(b,d,e);
+#define mnmx6(a,b,c,d,e,f) s2(a,d);s2(b,e);s2(c,f);mn3(a,b,c);mx3(d,e,f);
+in vec3 vertex; 
+
+layout(binding=0) uniform sampler2D depthCamTex;
+layout(binding=1) uniform sampler2D depthCamTexFil;
+layout(binding=2) uniform sampler2D markersTex;
+//layout(r32ui, binding=2) uniform coherent uimage2D outputTex;
+uniform mat4 modelMat;
+uniform mat4 viewMat;
+uniform mat4 viewProjMat;
+uniform float camXReso;
+uniform float camYReso;
+uniform float camXZFactor;
+uniform float camYZFactor;
+uniform int camFilter;
+uniform int background;
+uniform float camContThresh;
+uniform float camMarkers;
+uniform int depthType;
+uniform int depthID;
+uniform float outputCurs;
+uniform float mirrored;
+
+out vec3 viewRay;
+out float kept;
+flat out int outDepthID;
+
+void main(void) {
+	vec4 depthPos = vec4(0, 0, 0, 1);
+	vec4 posWS = vec4(0, 0, 0, 1);
+	//depth camera
+	if(depthType==0) {
+		vec2 coords = vertex.xy;
+		//get marker if any
+		if(camMarkers>0) {
+			outDepthID = int(float(texture(markersTex,
+							vec2(coords.x/camXReso,
+								coords.y/camYReso)).r)
+					* 255.0);
+		}
+		else {
+			outDepthID=depthID+1;
+		}
+		//get depth pixel in camera texture
+		float depth = 
+			float(texture(depthCamTex,
+						vec2(coords.x/camXReso,
+							coords.y/camYReso)).r)
+			* 65535.0;
+		kept=1.0;
+		float backgroundDepth=0;
+		if(background>0) {
+			float backDepth = float(texture(depthCamTex,
+						vec2(coords.x/camXReso,
+							coords.y/camYReso)).r)
+				* 65535.0;
+			if(backDepth<depth) {
+				depth=backDepth;
+				backgroundDepth=1;
+			}
+		}
+		if(depth<=500.0 || depth>8000.0) {
+			kept=0.0;
+		}
+		else if(backgroundDepth==0) {
+			//filter out contours
+			float maxD=camContThresh; 
+			bool contour=false;
+			for(int dX = -1; dX <= 1; ++dX) {
+				for(int dY = -1; dY <= 1; ++dY) {
+					if(abs(float(texture(depthCamTex,
+										vec2((coords.x+dX)/camXReso,
+											(coords.y+dY)/camYReso)).r)
+								* 65535.0
+								- depth) > maxD) {
+						contour=true;
+					}
+				}
+			}
+			if(contour) {
+				kept=0.0;
+			}
+			//see if needs filtering
+			if(camFilter>0) {
+				float filtDepth = float(texture(depthCamTexFil,
+							vec2(coords.x/camXReso,
+								coords.y/camYReso)).r)
+					* 65535.0;
+				//select either filtered version or current one
+				//depending on movement 
+				if(abs(filtDepth-depth)<camContThresh) {
+					float filRatio = abs(filtDepth-depth)/camContThresh;
+					depth=(1-filRatio)*filtDepth+(filRatio)*depth;
+				}
+			}
+		}
+		//test distance again
+		if(depth<=500.0 || depth>8000.0) {
+			kept=0.0;
+		}
+		//compute position in world units
+		depthPos = vec4((vertex.x/camXReso-0.5)
+				*depth*camXZFactor,
+				(0.5-(vertex.y/camYReso))
+				*depth*camYZFactor,
+				depth,
+				1.0);
+		//get world pos
+		posWS = modelMat * depthPos;
+	}
+	//other slicing shapes
+	else {
+		outDepthID=depthID+1;
+		kept=1.0;
+		depthPos=vec4(vertex, 1.0);
+		posWS = modelMat * depthPos;
+		if(mirrored<1) {
+			posWS.x = -posWS.x;
+		}
+	}
+	/*
+	//output minimum point on z axis if output is active
+	if(outputCurs>0 && kept>0.0) {
+	imageAtomicMin(outputTex,ivec2(0,int(depthID)+500),
+	int(floor(1000.0+posWS.z/10.0)*1000000
+	+floor(posWS.y/10.0+500.0)*1000
+	+floor(posWS.x/10.0+500.0)));
+	//       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),4400600);
+	//       imageAtomicMin(outputTex,ivec2(0, int(depthID)+500),6400600);
+	}
+	 */
+	//keep/interpolate ray from view to each vertex
+	viewRay = (posWS.xyz - vec3(viewMat[3][0],
+				viewMat[3][1],
+				viewMat[3][2]));
+	gl_Position = viewProjMat * posWS;
+};
diff --git a/wscript b/wscript
index 2cdda6d4844fe425ecd9c6a9f614ce639436efa6..7363cc04c74d2c1aef365a98bdb6cc7139c2b4e7 100755
--- a/wscript
+++ b/wscript
@@ -1,138 +1,155 @@
 #!/usr/bin/env python
 
 import sys, os 
+from waflib import Utils
 
 def options(opt):
-    opt.load('compiler_cxx')
-    opt.load('compiler_c')
+	opt.load('compiler_cxx')
+	opt.load('compiler_c')
 
 def configure(conf):
-    conf.load('compiler_cxx')
-    conf.load('compiler_c')
-
-    #conf.check_cxx(lib="glfw",
-    #            errmsg="Please install the glfw library",
-    #            mandatory=True)
-    #conf.check_cxx(lib="glm",
-    #            errmsg="Please install the glm library",
-    #            mandatory=True)
-    #conf.check_cxx(lib="openni",
-    #            errmsg="Please install the openni2 library",
-    #            mandatory=True)
-    #conf.check_cxx(lib="fltk",
-    #            errmsg="Please install the fltk library",
-    #            mandatory=True)
-    #conf.check_cxx(lib="opencv2",
-    #            errmsg="Please install the opencv library",
-    #            mandatory=True)
-    
-
-    #platform specific
-    if sys.platform == 'darwin': 
-        conf.env.INCLUDES_OS = ['/opt/local/include',
-                                '/opt/local/include/libxml2',
-                                '/opt/local/include/opencv4',
-                                '/opt/local/include/opencv3',
-                                '/opt/local/include/openni']
-        conf.env.LIBPATH_OS = ['/opt/local/lib','/opt/local/lib/opencv3']
-        conf.env.LIB_OS = ['m', 'xml2', 'fltk', 'fltk_images',
-                           'glfw', 'glew','OpenNI2',
-                           'opencv_core', 'opencv_highgui', 
-                           'opencv_calib3d', 'opencv_imgproc', 
-                           'opencv_imgcodecs', 'opencv_videoio', 
-                           'opencv_aruco', 'opencv_features2d',
-                           'assimp']
-        conf.env.FRAMEWORK_OS = ['Cocoa','OpenGL', 'AGL', 'Carbon', 
-                                 'Accelerate', 'IOKit','System', 'AppKit',
-                                 'CoreFoundation']
-        conf.env.DEFINES_OS  = ['OSX=1', 'POSIX=1']
-    elif sys.platform == 'win32' or sys.platform == 'cygwin':
-        conf.env.INCLUDES_OS = ['os/win/include/', 'C:\MinGW\include']
-        conf.env.LIBPATH_OS = [os.path.join(os.getcwd(), 'os/win/lib/')]
-        conf.env.LIB_OS = ['m', 'pthreadGC1',
-                           'ws2_32', 'xml2', 'GLU', 'GL',
-                           'OpenNI2', 'fltk', 'fltk_gl', 
-                           'opencv_core', 'opencv_highgui', 
-                           'opencv_calib3d', 'opencv_imgproc']
-    else : #linux
-        conf.env.INCLUDES_OS = ['/usr/include', '/usr/local/include',
-                                '/usr/include/libxml2', 
-                                '/usr/include/opencv4',
-                                '/usr/local/include/opencv4',
-                                '/usr/include/opencv4',
-                                '/usr/local/include/openni2',
-                                '/usr/include/openni2']
-        conf.env.LIB_OS = ['jpeg', 'X11', 'm',
-                           'xml2', 'GLU', 'GL', 'pthread',
-                           'glfw', 'GLEW', 
-                           'OpenNI2', 'fltk', 'fltk_images',
-                           'opencv_core', 'opencv_highgui', 
-                           'opencv_calib3d', 'opencv_imgproc', 
-                           'opencv_imgcodecs', 'opencv_videoio', 
-                           'opencv_aruco', 'opencv_features2d',
-                           'assimp', 'portaudio']
-        conf.env.LIBPATH_OS = ['/usr/local/lib/']
-        conf.env.DEFINES_OS  = ['POSIX=1','GL42=1', 'LINUX=1']
-   
-    #release specific
-    conf.env.CXXFLAGS = ['-O3', '-Wall', '-std=c++2a'] 
-    conf.env.DEFINES  = ['DEBUG(x)=//x']
-
-    #debug specific
-    conf.setenv('debug', env=conf.env.derive())
-    conf.env.CXXFLAGS = ['-g', '-Wall', '-std=c++2a']
-    conf.env.DEFINES  = ['DEBUG(x)=std::cout<< x <<std::endl;']
+	conf.load('compiler_cxx')
+	conf.load('compiler_c')
+
+	#conf.check_cxx(lib="glfw",
+	#            errmsg="Please install the glfw library",
+	#            mandatory=True)
+	#conf.check_cxx(lib="glm",
+	#            errmsg="Please install the glm library",
+	#            mandatory=True)
+	#conf.check_cxx(lib="openni",
+	#            errmsg="Please install the openni2 library",
+	#            mandatory=True)
+	#conf.check_cxx(lib="fltk",
+	#            errmsg="Please install the fltk library",
+	#            mandatory=True)
+	#conf.check_cxx(lib="opencv2",
+	#            errmsg="Please install the opencv library",
+	#            mandatory=True)
+
+
+	#platform specific
+	if sys.platform == 'darwin': 
+		conf.env.INCLUDES_OS = ['/opt/local/include',
+				'/opt/local/include/libxml2',
+				'/opt/local/include/opencv4',
+				'/opt/local/include/opencv3',
+				'/opt/local/include/openni']
+		conf.env.LIBPATH_OS = ['/opt/local/lib','/opt/local/lib/opencv3']
+		conf.env.LIB_OS = ['m', 'xml2', 'fltk', 'fltk_images',
+				'glfw', 'glew','OpenNI2',
+				'opencv_core', 'opencv_highgui', 
+				'opencv_calib3d', 'opencv_imgproc', 
+				'opencv_imgcodecs', 'opencv_videoio', 
+				'opencv_aruco', 'opencv_features2d',
+				'assimp']
+		conf.env.FRAMEWORK_OS = ['Cocoa','OpenGL', 'AGL', 'Carbon', 
+				'Accelerate', 'IOKit','System', 'AppKit',
+				'CoreFoundation']
+		conf.env.DEFINES_OS  = ['OSX=1', 'POSIX=1']
+	elif sys.platform == 'win32' or sys.platform == 'cygwin':
+		conf.env.INCLUDES_OS = ['os/win/include/', 'C:\MinGW\include']
+		conf.env.LIBPATH_OS = [os.path.join(os.getcwd(), 'os/win/lib/')]
+		conf.env.LIB_OS = ['m', 'pthreadGC1',
+				'ws2_32', 'xml2', 'GLU', 'GL',
+				'OpenNI2', 'fltk', 'fltk_gl', 
+				'opencv_core', 'opencv_highgui', 
+				'opencv_calib3d', 'opencv_imgproc']
+	else : #linux
+		conf.env.INCLUDES_OS = ['/usr/include', '/usr/local/include',
+				'/usr/include/libxml2', 
+				'/usr/include/opencv4',
+				'/usr/local/include/opencv4',
+				'/usr/local/include/openni2',
+				'/usr/include/openni2',
+				'build/']
+		conf.env.LIB_OS = ['jpeg', 'X11', 'm',
+				'xml2', 'GLU', 'GL', 'pthread',
+				'glfw', 'GLEW', 
+				'OpenNI2', 'fltk', 'fltk_images',
+				'opencv_core', 'opencv_highgui', 
+				'opencv_calib3d', 'opencv_imgproc', 
+				'opencv_imgcodecs', 'opencv_videoio', 
+				'opencv_aruco', 'opencv_features2d',
+				'assimp', 'rtaudio']
+		conf.env.LIBPATH_OS = ['/usr/local/lib/']
+		conf.env.DEFINES_OS  = ['POSIX=1','GL43=1', 'LINUX=1']
+
+	#release specific
+	conf.env.CXXFLAGS = ['-O3', '-w', '-std=c++2a'] 
+	conf.env.DEFINES  = ['DEBUG(x)=//x']
+
+	#debug specific
+	conf.setenv('debug', env=conf.env.derive())
+	conf.env.CXXFLAGS = ['-g', '-Wall', '-std=c++2a']
+	conf.env.DEFINES  = ['DEBUG(x)=std::cout<< x <<std::endl;']
 
 def build(bld):
-    macApp = False
-    if sys.platform == 'win32' or sys.platform == 'msys' :
-        bld.objects(
-            source  = bld.path.ant_glob('src/osc/oscPack/ip/win32/*.cpp')
-                      +bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
-                      +bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
-            use     = ['OS'],
-            target  = 'oscpack')
-    else : 
-        bld.objects(
-            source  = bld.path.ant_glob('src/osc/oscPack/ip/posix/*.cpp')
-                      +bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
-                      +bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
-            use     = ['OS'],
-            target  = 'oscpack')
-
-    if sys.platform == 'darwin': 
-        installPath = '/opt/bin/'
-        macApp = 'True'
-
-    bld.program(
-        source       = bld.path.ant_glob('src/gui/*.cpp')
-                       + bld.path.ant_glob('src/modules/*.cpp')
-                       + bld.path.ant_glob('src/geoms/*.cpp')
-                       + bld.path.ant_glob('src/osc/*.cpp')
-                       + bld.path.ant_glob('src/audio/*.cpp')
-                       + bld.path.ant_glob('src/*.cpp'),
-        use          = ['OS','ringbuf','oscpack'],
-        target       = 'rivill'+bld.variant,
-        vnum         = '0.0.1',
-        mac_app      = macApp,
-        mac_plist     = 'data/Info.plist',
-        mac_resources = 'data/rivill.icns',
-    )
-
-    bld.program(
-        source="src/utils/create_marker.cpp",
-        use="OS",
-        target="rivill_create_marker")
-
-    bld.install_files('${PREFIX}/share/applications', 
-                       ['data/rivill.desktop'])
-    bld.install_files('${PREFIX}/share/mime/packages', 
-                       ['data/rivill.xml'])
-    bld.install_files('${PREFIX}/share/icons', 
-                   ['data/rivill.png'])
+	macApp = False
+	if sys.platform == 'win32' or sys.platform == 'msys' :
+		bld.objects(
+				source  = bld.path.ant_glob('src/osc/oscPack/ip/win32/*.cpp')
+				+bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
+				+bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
+				use     = ['OS'],
+				target  = 'oscpack')
+	else : 
+		bld.objects(
+				source  = bld.path.ant_glob('src/osc/oscPack/ip/posix/*.cpp')
+				+bld.path.ant_glob('src/osc/oscPack/ip/*.cpp')
+				+bld.path.ant_glob('src/osc/oscPack/osc/*.cpp'),
+				use     = ['OS'],
+				target  = 'oscpack')
+
+	if sys.platform == 'darwin': 
+		installPath = '/opt/bin/'
+		macApp = 'True'
+
+	#Create shaders.h.in file to integrate shaders in binary
+	shaders = ""
+	for s in ["render", "post", "select", "slice", "calib"] :
+		for v in ["43", "30"] :
+			shaders += 'std::string '+s+v+'FS = R"('\
+				+ Utils.readf('src/shaders/'+s+v+'.fs')\
+				+ ')";\n\n'
+			shaders += 'std::string '+s+v+'VS = R"('\
+				+ Utils.readf('src/shaders/'+s+v+'.vs')\
+				+ ')";\n\n'
+
+	Utils.writef('build/shaders.h.in', shaders)
+	bld(rule='touch shaders.h.in', 
+			source=bld.path.ant_glob('src/shaders/*'),
+			target="shaders.h.in")
+
+	bld.program(
+			source       = bld.path.ant_glob('src/gui/*.cpp')
+			+ bld.path.ant_glob('src/modules/*.cpp')
+			+ bld.path.ant_glob('src/geoms/*.cpp')
+			+ bld.path.ant_glob('src/osc/*.cpp')
+			+ bld.path.ant_glob('src/audio/*.cpp')
+			+ bld.path.ant_glob('src/*.cpp'),
+			use          = ['OS','ringbuf','oscpack', 'shaders.h.in'],
+			target       = 'rivill'+bld.variant,
+			vnum         = '0.0.1',
+			mac_app      = macApp,
+			mac_plist     = 'data/Info.plist',
+			mac_resources = 'data/rivill.icns',
+			)
+
+	bld.program(
+			source="src/utils/create_marker.cpp",
+			use="OS",
+			target="rivill_create_marker")
+
+	bld.install_files('${PREFIX}/share/applications', 
+			['data/rivill.desktop'])
+	bld.install_files('${PREFIX}/share/mime/packages', 
+			['data/rivill.xml'])
+	bld.install_files('${PREFIX}/share/icons', 
+			['data/rivill.png'])
 
 from waflib.Build import BuildContext, CleanContext
 class debug(BuildContext): 
-    cmd = 'debug'
-    variant = 'debug' 
+	cmd = 'debug'
+	variant = 'debug'