Select Git revision
render43.fs
-
Florent Berthaut authoredFlorent Berthaut authored
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;
}
};