@@ -153,152 +153,131 @@ out vec4 fragColor;
153153uniform vec3 cameraPosition;
154154uniform vec3 cameraDirection;
155155uniform sampler3D volumeTexture;
156- uniform ivec2 iResolution; // <-- aspect correction
156+ uniform ivec2 iResolution;
157157
158- const float stepSize = 0.005 ;
158+ const float stepSize = 0.001 ;
159159const int maxSteps = 1024;
160160const vec3 lightDir = normalize(vec3(1.0, 1.0, 0.0));
161161const float orthoScale = 0.5;
162162
163- // Gradient computation
164- vec3 computeGradient(vec3 uvw) {
165- float h = 0.005;
166- float fx1 = texture(volumeTexture, clamp(uvw + vec3(h,0,0), 0.0, 1.0)).r;
167- float fx2 = texture(volumeTexture, clamp(uvw - vec3(h,0,0), 0.0, 1.0)).r;
168- float fy1 = texture(volumeTexture, clamp(uvw + vec3(0,h,0), 0.0, 1.0)).r;
169- float fy2 = texture(volumeTexture, clamp(uvw - vec3(0,h,0), 0.0, 1.0)).r;
170- float fz1 = texture(volumeTexture, clamp(uvw + vec3(0,0,h), 0.0, 1.0)).r;
171- float fz2 = texture(volumeTexture, clamp(uvw - vec3(0,0,h), 0.0, 1.0)).r;
172- return -vec3(fx1 - fx2, fy1 - fy2, fz1 - fz2);
163+ vec3 ComputeGradient(vec3 UVW) {
164+ vec3 H = 1.0 / vec3(textureSize(volumeTexture, 0)); // Texelgröße
165+
166+ float Fx1 = texture(volumeTexture, clamp(UVW + vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r; // +x Probe
167+ float Fx2 = texture(volumeTexture, clamp(UVW - vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r; // -x Probe
168+
169+ float Fy1 = texture(volumeTexture, clamp(UVW + vec3(0.0, H.y, 0.0), 0.0, 1.0)).r; // +y Probe
170+ float Fy2 = texture(volumeTexture, clamp(UVW - vec3(0.0, H.y, 0.0), 0.0, 1.0)).r; // -y Probe
171+
172+ float Fz1 = texture(volumeTexture, clamp(UVW + vec3(0.0, 0.0, H.z), 0.0, 1.0)).r; // +z Probe
173+ float Fz2 = texture(volumeTexture, clamp(UVW - vec3(0.0, 0.0, H.z), 0.0, 1.0)).r; // -z Probe
174+
175+ return normalize(-vec3(Fx1 - Fx2, Fy1 - Fy2, Fz1 - Fz2)); // Zentraldiff, Negation
173176}
174177
175- // Transfer function
176- vec4 transferFunction(float f, float gradMag) {
177- // Representative CT numbers (HU)
178- const float f_air = -750.0;
179- const float f_tissue = 50.0;
180- const float f_bone = 700.0;
181-
182- // Assigned alpha values (Opacity)
183- const float a_air = 0.0; // Transparent
184- const float a_tissue = 0.2; // Medium opacity
185- const float a_bone = 1.0; // Strong opacity
186-
187- // Assigned colors
188- const vec3 c_air = vec3(0.0); // Air
189- const vec3 c_tissue = vec3(0.9, 0.7, 0.6); // Skin-tone
190- const vec3 c_bone = vec3(1.0, 1.0, 0.95); // White/Ivory
191-
192- // initial
178+ vec4 TransferFunction(float F, float gradientMagnitude) {
179+ const float huAir = -750.0;
180+ const float huTissue = 50.0;
181+ const float huBone = 700.0;
182+
183+ const float alphaAir = 0.0;
184+ const float alphaTissue = 0.02;
185+ const float alphaBone = 1.0;
186+
187+ const vec3 colorAir = vec3(0.0);
188+ const vec3 colorTissue = vec3(0.9, 0.7, 0.6);
189+ const vec3 colorBone = vec3(1.0, 1.0, 0.95);
190+
193191 float alpha = 0.0;
194- vec3 color = c_air;
195-
196- if (f >= f_air && f <= f_tissue) {
197- // Between air and soft tissue
198- float t = (f - f_air) / (f_tissue - f_air);
199- alpha = mix(a_air, a_tissue, t);
200- color = mix(c_air, c_tissue, t);
201- } else if (f >= f_tissue && f <= f_bone) {
202- // Between tissue and bone
203- float t = (f - f_tissue) / (f_bone - f_tissue);
204- alpha = mix(a_tissue, a_bone, t);
205- color = mix(c_tissue, c_bone, t);
206- } else if (f > f_bone) {
207- // Denser than bone
208- alpha = a_bone;
209- color = c_bone;
192+ vec3 Color = colorAir;
193+
194+ if (F >= huAir && F <= huTissue) {
195+ float T = (F - huAir) / (huTissue - huAir); // Air >Tissue Mix
196+ alpha = mix(alphaAir, alphaTissue, T);
197+ Color = mix(colorAir, colorTissue, T);
198+ } else if (F >= huTissue && F <= huBone) {
199+ float T = (F - huTissue) / (huBone - huTissue); // Tissue > Bone Mix
200+ alpha = mix(alphaTissue, alphaBone, T);
201+ Color = mix(colorTissue, colorBone, T);
202+ } else if (F > huBone) {
203+ alpha = alphaBone; // Bone+
204+ Color = colorBone;
210205 }
211206
212- // Multiply opacity by gradient magnitude
213- // alpha = clamp(alpha * gradMag * 2.0 , 0.0, 1.0);
207+ // hermit Interpolation zwischen 0 und 1, lower bound, upper bound, source Wert
208+ alpha *= smoothstep(0.05 , 0.2, gradientMagnitude); // Übergang mit Gradient verstärken
214209
215- return vec4(color , alpha);
210+ return vec4(Color , alpha);
216211}
217212
213+ vec3 PhongShade(vec3 N, vec3 BaseColor, vec3 ViewDir, vec3 lightDir) {
214+ const vec3 Ka = vec3(0.5); // Ambient
215+ const vec3 Kd = vec3(0.5); // Diffus
216+ const vec3 Ks = vec3(1.0); // Spekular
217+ const float NExp = 20.0; // Rauheit
218218
219- // Phong shading
220- vec3 phongShade(vec3 N, vec3 baseColor, vec3 viewDir, vec3 lightDir) {
221- const vec3 ka = vec3(0.5);
222- const vec3 kd = vec3(0.6);
223- const vec3 ks = vec3(0.3);
224- const float n = 20.0;
225-
226- vec3 H = normalize(viewDir + lightDir);
227- float diff = max(dot(N, lightDir), 0.0);
228- float spec = pow(max(dot(N, H), 0.0), n);
219+ vec3 H = normalize(ViewDir + lightDir); // Halfvector
220+ float Diff = max(dot(N, lightDir), 0.0); // Diffus
221+ float Spec = pow(max(dot(N, H), 0.0), NExp); // Spekular
229222
230- return baseColor * (ka + kd * diff ) + ks * spec ;
223+ return BaseColor * (Ka + Kd * Diff ) + Ks * Spec ;
231224}
232225
233- // Ray generation (aspect-corrected)
234- void generateRay(out vec3 rayOrigin, out vec3 rayDir) {
235- // compute aspect ratio from iResolution
236- float aspect = float(iResolution.x) / float(iResolution.y);
237-
238- // If vUv is already in -1..1, you may not want to remap; here we follow the existing use
239- // and simply scale the X component to correct for aspect.
240- vec2 uv = vUv;
241- uv.x *= aspect;
226+ void GenerateRay(out vec3 rayOrigin, out vec3 rayDir) {
227+ float Aspect = float(iResolution.x) / float(iResolution.y); // Seitenverhältnis aus Uniform
228+ vec2 UV = vUv;
229+ UV.x *= Aspect; // Korrigiert X-Skalierung
242230
231+ // Orthogonale Basis bilden
243232 vec3 forward = normalize(cameraDirection);
244- vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));
245- vec3 up = cross(right, forward);
233+ vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));
234+ vec3 up = cross(right, forward);
246235
247236 rayDir = forward;
248- // scale the right offset by the corrected uv.x
249- rayOrigin = cameraPosition + uv.x * right * orthoScale + uv.y * up * orthoScale;
237+ rayOrigin = cameraPosition + UV.x * right * orthoScale + UV.y * up * orthoScale; // Ortho Offset
250238}
251239
252- // Sample volume
253- vec4 sampleVolume(vec3 uvw, vec3 rayDir) {
254- float f = texture(volumeTexture, uvw).r - 1100.0; // texture is raised by 1100
255- vec3 grad = computeGradient(uvw);
256- float gradMag = length(grad);
240+ vec4 SampleVolume(vec3 UVW, vec3 rayDir) {
241+ float F = texture(volumeTexture, UVW).r - 1100.0; // HU-Korrektur weil Textur Werte um 1100 angehoben
242+ vec3 Grad = ComputeGradient(UVW); // Gradient berechnen für Phong Normale
243+ float gradientMagnitude = length(Grad);
257244
258- // Call transfer function to get material properties
259- vec4 material = transferFunction(f, gradMag);
260-
261- vec3 shaded = phongShade(normalize(grad), material.rgb, normalize(-rayDir), lightDir);
245+ vec4 Mat = TransferFunction(F, gradientMagnitude); // Materialdaten
246+ vec3 Shaded = PhongShade(normalize(Grad), Mat.rgb, normalize(-rayDir), lightDir); // Beleuchtung
262247
263- return vec4(shaded, material .a);
248+ return vec4(Shaded, Mat .a); // Farbe + alpha
264249}
265250
266251void main() {
267252 vec3 rayOrigin, rayDir;
268- generateRay (rayOrigin, rayDir);
253+ GenerateRay (rayOrigin, rayDir); // Strahl erzeugen
269254
270- float tNear = 0.01; // Start slightly away from the camera
271- float tFar = 2.0; // March a distance guaranteed to pass through the volume
255+ float TNear = 0.01; // Start
256+ float TFar = 2.0; // Ende
272257
273- vec3 colorAccum = vec3(0.0);
274- float alphaAccum = 0.0;
258+ vec3 ColorAccum = vec3(0.0); // Farbspeicher
259+ float alphaAccum = 0.0; // alphaakkumulation
275260
276- // Calculate number of steps based on the assumed marching length
277- float rayLength = tFar - tNear;
278- int steps = min(int(rayLength / stepSize), maxSteps);
261+ float RayLength = TFar - TNear;
262+ int Steps = min(int(RayLength / stepSize), maxSteps); // Schrittanzahl
279263
280- // Ray marching loop
281- // Back-to-front compositing
282- for (int i = steps - 1; i >= 0; --i) {
283- float t = tNear + float(i) * stepSize;
284- vec3 p = rayOrigin + rayDir * t;
285- vec3 uvw = p + 0.5;
264+ for (int I = Steps - 1; I >= 0; --I) { // Rückwärtslauf wegen Back to Front
265+ float T = TNear + float(I) * stepSize; // Distanz auf dem Strahl
266+ vec3 P = rayOrigin + rayDir * T; // Punkt im Raum
267+ vec3 UVW = P + 0.5; // Sample In Texturraum
286268
287- // Bounding box check (to ensure we only sample the texture)
288- // This acts as an implicit boundary for the volume.
289- if (any(lessThan(uvw, vec3(0.0))) || any(greaterThan(uvw, vec3(1.0))))
269+ if (any(lessThan(UVW, vec3(0.0))) || any(greaterThan(UVW, vec3(1.0)))) // Bounds check
290270 continue;
291271
292- vec4 s = sampleVolume(uvw , rayDir);
293- float a = s .a;
294- vec3 c = s .rgb;
272+ vec4 S = SampleVolume(UVW , rayDir); // Volume Abtasten
273+ float A = S .a;
274+ vec3 C = S .rgb;
295275
296- // 'Over' operator
297- colorAccum = c * a + colorAccum * (1.0 - a);
298- alphaAccum = a + alphaAccum * (1.0 - a);
276+ ColorAccum = C * A + ColorAccum * (1.0 - A); // Over Operator
277+ alphaAccum = A + alphaAccum * (1.0 - A); // alpha add
299278 }
300279
301- fragColor = vec4(colorAccum , 1.0);
280+ fragColor = vec4(ColorAccum , 1.0);
302281}
303282```
304283
0 commit comments