Skip to content
Snippets Groups Projects
Select Git revision
  • 3d765f8c8238834a4a342e384917bc32a3b629a6
  • main default protected
2 results

render43.fs

Blame
  • render43.fs 18.48 KiB
    #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;
    	}
    };