Ich habe einige Zeit damit verbracht einen Shader, der den Marching-Tetrahedra Algorithmus auf der GPU ausführt zu schreiben. Wem das ganze nichts sagt, Marching-Tetrahedra dient der Oberflächengenerirung aus einem Wertegitter(z.B ein Massengitter bei einer Flüssigkeitsimulation oder vll Hitze).
Derzeit gibt es jedoch einige probleme den so erzeugten Mesh zu texturieren, mir fehlt schlicht der Ansatz.
Code: #version 420 core // uniform buffer bindings #define TRANSFORM 0 // texture units #define DATAFIELD 1 layout (points, invocations = 1) in; layout (triangle_strip, max_vertices = 24) out; layout (binding = TRANSFORM) uniform transform { mat4 ModelViewMatrix; mat4 ProjectionMatrix; mat4 InfProjectionMatrix; mat4 MVPMatrix; vec4 Viewport; } Transform; //Volume data field texture layout (binding = DATAFIELD) uniform sampler3D dataFieldTex; out TexCoord { smooth vec2 decalTexCoord; } Out; uniform float isolevel = 0.39; uniform vec3 vertDecals[8]; const int[14] edgeTable = { 0x0d, 0x13, 0x1e, 0x26, 0x2b, 0x35, 0x38, 0x38, 0x35, 0x2b, 0x26, 0x1e, 0x13, 0x0d }; const int[14 * 4] triTable = { 0, 3, 2, -1, 0, 1, 4, -1, 1, 4, 2, 3, 1, 2, 5, -1, 3, 5, 0, 1, 2, 5, 0, 4, 5, 4, 3, -1, 3, 4, 5, -1, 4, 5, 0, 2, 1, 5, 0, 3, 5, 2, 1, -1, 3, 4, 2, 1, 4, 1, 0, -1, 2, 3, 0, -1, }; void marchTetra(vec3[4] pos, float[4] val){ //Determine the index into the edge table which //tells us which vertices are inside of the surface int tetraIndexFlag = 0; if (val[0] < isolevel) tetraIndexFlag |= 1; if (val[1] < isolevel) tetraIndexFlag |= 2; if (val[2] < isolevel) tetraIndexFlag |= 4; if (val[3] < isolevel) tetraIndexFlag |= 8; if (tetraIndexFlag == 0 || tetraIndexFlag == 15) return; tetraIndexFlag--; vec3 vertlist[6]; if ((edgeTable[tetraIndexFlag] & 1)!=0 ) vertlist[0] = mix(pos[0], pos[1], (isolevel-val[0])/(val[1]-val[0])); if ((edgeTable[tetraIndexFlag] & 2)!=0 ) vertlist[1] = mix(pos[1], pos[2], (isolevel-val[1])/(val[2]-val[1])); if ((edgeTable[tetraIndexFlag] & 4)!=0) vertlist[2] = mix(pos[2], pos[0], (isolevel-val[2])/(val[0]-val[2])); if ((edgeTable[tetraIndexFlag] & 8)!=0) vertlist[3] = mix(pos[0], pos[3], (isolevel-val[0])/(val[3]-val[0])); if ((edgeTable[tetraIndexFlag] & 16)!=0) vertlist[4] = mix(pos[1], pos[3], (isolevel-val[1])/(val[3]-val[1])); if ((edgeTable[tetraIndexFlag] & 32)!=0) vertlist[5] = mix(pos[2], pos[3], (isolevel-val[2])/(val[3]-val[2])); gl_Position = Transform.MVPMatrix * vec4(vertlist[triTable[tetraIndexFlag * 4 ]], 1); Out.decalTexCoord = vertlist[triTable[tetraIndexFlag * 4 + 0]].xy; EmitVertex(); gl_Position = Transform.MVPMatrix * vec4(vertlist[triTable[tetraIndexFlag * 4 + 1]], 1); Out.decalTexCoord = vertlist[triTable[tetraIndexFlag * 4 + 1]].xy; EmitVertex(); gl_Position = Transform.MVPMatrix * vec4(vertlist[triTable[tetraIndexFlag * 4 + 2]], 1); Out.decalTexCoord = vertlist[triTable[tetraIndexFlag * 4 + 2]].xy; EmitVertex(); if(triTable[tetraIndexFlag * 4 + 3] != -1){ gl_Position = Transform.MVPMatrix * vec4(vertlist[triTable[tetraIndexFlag * 4 + 3]], 1); Out.decalTexCoord = vertlist[triTable[tetraIndexFlag * 4 + 3]].xy; EmitVertex(); } EndPrimitive(); } const float texshift = 1.0; //Geometry Shader entry point void main(void) { vec3 pos5 = gl_in[0].gl_Position.xyz + vertDecals[5]; vec3 pos[4]; pos[0] = gl_in[0].gl_Position.xyz + vertDecals[0]; pos[1] = pos5; pos[2] = gl_in[0].gl_Position.xyz + vertDecals[1]; pos[3] = gl_in[0].gl_Position.xyz + vertDecals[6]; float val5 = texture(dataFieldTex, (pos5+texshift)/2).r; float val[4]; val[0] = texture(dataFieldTex, (pos[0]+texshift)/2).r; val[1] = val5; val[2] = texture(dataFieldTex, (pos[2]+texshift)/2).r; val[3] = texture(dataFieldTex, (pos[3]+texshift)/2).r; marchTetra(pos, val); pos[1] = pos[2]; pos[2] = gl_in[0].gl_Position.xyz + vertDecals[2]; val[1] = val[2]; val[2] = texture(dataFieldTex, (pos[2]+texshift)/2).r; marchTetra(pos, val); pos[1] = pos[2]; pos[2] = gl_in[0].gl_Position.xyz + vertDecals[3]; val[1] = val[2]; val[2] = texture(dataFieldTex, (pos[2]+texshift)/2).r; marchTetra(pos, val); pos[1] = pos[2]; pos[2] = gl_in[0].gl_Position.xyz + vertDecals[7]; val[1] = val[2]; val[2] = texture(dataFieldTex, (pos[2]+texshift)/2).r; marchTetra(pos, val); pos[1] = pos[2]; pos[2] = gl_in[0].gl_Position.xyz + vertDecals[4]; val[1] = val[2]; val[2] = texture(dataFieldTex, (pos[2]+texshift)/2).r; marchTetra(pos, val); pos[1] = pos[2]; pos[2] = pos5; val[1] = val[2]; val[2] = val5; marchTetra(pos, val); }
|