|
90 | 90 | "referenceVertexShader": "precision highp float;\n\nin vec3 position;\nin vec2 uv;\n\nout vec2 vUv;\n\nvoid main() {\n vUv = uv * 2.0 - 1.0;\n gl_Position = vec4(position, 1.0);\n}", |
91 | 91 | "referenceFragmentShader": "precision highp float;\nprecision highp sampler3D;\n\nin vec2 vUv;\nout vec4 fragColor;\n\nuniform vec3 cameraPosition;\nuniform vec3 cameraDirection;\nuniform sampler3D volumeTexture;\nuniform ivec2 iResolution;\n\n// Parameter aus der Vorlesung\nconst float stepSize = 0.00256;\nconst int maxSteps = 512;\nconst vec3 lightDir = normalize(vec3(1.0, 1.0, 0.0));\nconst float orthoScale = 0.5;\n\nvec3 ComputeGradient(vec3 samplePosition) {\n vec3 H = 1.0 / vec3(textureSize(volumeTexture, 0)); \n float Fx1 = texture(volumeTexture, clamp(samplePosition + vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fx2 = texture(volumeTexture, clamp(samplePosition - vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fy1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fy2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fz1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n float Fz2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n vec3 grad = vec3((Fx1 - Fx2), (Fy1 - Fy2), (Fz1 - Fz2)) / (2.0 * H);\n return grad;\n}\n\nvec4 TransferFunction(float density, float gradientMagnitude)\n{\n const float huAir = -800.0;\n const float huTissue = 50.0;\n const float huBone = 700.0;\n\n const float alphaAir = 0.0;\n const float alphaTissue = 0.03;\n const float alphaBone = 1.0;\n\n const vec3 colorAir = vec3(0.0);\n const vec3 colorTissue = vec3(0.929, 0.675, 0.522);\n const vec3 colorBone = vec3(0.949, 0.898, 0.643);\n\n float alpha;\n vec3 color;\n \n if (density <= huAir) {\n alpha = alphaAir;\n color = colorAir;\n } \n else if (density < huTissue) {\n float t = (density - huAir) / (huTissue - huAir);\n alpha = mix(alphaAir, alphaTissue, t);\n color = mix(colorAir, colorTissue, t);\n } \n else if (density < huBone) {\n float t = (density - huTissue) / (huBone - huTissue);\n alpha = mix(alphaTissue, alphaBone, t);\n color = mix(colorTissue, colorBone, t);\n } \n else {\n alpha = alphaBone;\n color = colorBone;\n }\n\n // Gradient Modulation (Levoy)\n alpha *= 1.0 - exp(-5.0 * clamp(gradientMagnitude / 8.0, 0.0, 1.0));\n\n return vec4(color, alpha);\n}\n\nvec3 PhongShade(vec3 N, vec3 BaseColor, vec3 ViewDir, vec3 lightDir) {\n const vec3 Ka = vec3(0.01); \n const vec3 Kd = vec3(1.0); \n const vec3 Ks = vec3(0.3); \n const float NExp = 120.0; \n\n vec3 H = normalize(ViewDir + lightDir); \n float Diff = max(dot(N, lightDir), 0.0); \n float Spec = pow(max(dot(N, H), 0.0), NExp); \n\n return BaseColor * (Ka + Kd * Diff) + Ks * Spec;\n}\n\nvoid GenerateRay(out vec3 rayOrigin, out vec3 rayDirection) {\n float Aspect = float(iResolution.x) / float(iResolution.y); \n vec2 pixelPos = vUv;\n pixelPos.x *= Aspect; \n\n vec3 forward = normalize(cameraDirection);\n vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));\n vec3 up = cross(right, forward);\n\n rayDirection = forward;\n rayOrigin = cameraPosition + pixelPos.x * right * orthoScale + pixelPos.y * up * orthoScale; \n}\n\nvec4 SampleVolume(vec3 textureCoord, vec3 rayDirection) {\n float rawValue = texture(volumeTexture, textureCoord).r;\n float density = rawValue - 1100.0; // HU Offset\n \n vec3 gradient = ComputeGradient(textureCoord); \n float gradMag = length(gradient);\n\n vec4 material = TransferFunction(density, gradMag); \n \n vec3 shadedColor = PhongShade(normalize(-gradient), material.rgb, normalize(-rayDirection), lightDir); \n\n return vec4(shadedColor, material.a); \n}\n\nvec3 Raymarch(vec3 rayOrigin, vec3 rayDirection) {\n vec3 accumulatedColor = vec3(0.0);\n int totalSteps = min(int(1.0 / stepSize), maxSteps);\n\n for (int i = totalSteps - 1; i >= 0; --i) { \n float t = float(i) * stepSize; \n vec3 currentPosition = rayOrigin + rayDirection * t;\n vec3 textureCoord = currentPosition + 0.5;\n\n if (textureCoord.x < 0.0 || textureCoord.y < 0.0 || textureCoord.z < 0.0 || \n textureCoord.x > 1.0 || textureCoord.y > 1.0 || textureCoord.z > 1.0)\n continue;\n\n vec4 src = SampleVolume(textureCoord, rayDirection);\n accumulatedColor = src.rgb * src.a + accumulatedColor * (1.0 - src.a);\n }\n return accumulatedColor;\n}\n\nvoid main() {\n vec3 rayOrigin, rayDirection;\n GenerateRay(rayOrigin, rayDirection);\n\n vec3 finalColor = Raymarch(rayOrigin, rayDirection);\n\n fragColor = vec4(finalColor, 1.0);\n}", |
92 | 92 | "starterVertexShader": "precision highp float;\n\nin vec3 position;\nin vec2 uv;\n\nout vec2 vUv;\n\nvoid main() {\n vUv = uv * 2.0 - 1.0;\n gl_Position = vec4(position, 1.0);\n}", |
93 | | - "starterFragmentShader": "precision highp float;\nprecision highp sampler3D;\n\nin vec2 vUv;\nout vec4 fragColor;\n\n// Uniforms\nuniform vec3 cameraPosition;\nuniform vec3 cameraDirection;\nuniform sampler3D volumeTexture;\nuniform ivec2 iResolution;\n\n// Konstanten\nconst float stepSize = 0.00256;\nconst int maxSteps = 512;\nconst vec3 lightDir = normalize(vec3(1.0, 1.0, 0.0));\nconst float orthoScale = 0.5;\n\n// Helper Functions (Bereits implementiert) \n\nvec3 ComputeGradient(vec3 samplePosition) {\n // Zentraler Differenzenquotient zur Bestimmung der Normale\n vec3 H = 1.0 / vec3(textureSize(volumeTexture, 0));\n float Fx1 = texture(volumeTexture, clamp(samplePosition + vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fx2 = texture(volumeTexture, clamp(samplePosition - vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fy1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fy2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fz1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n float Fz2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n return vec3((Fx1 - Fx2), (Fy1 - Fy2), (Fz1 - Fz2)) / (2.0 * H);\n}\n\nvec3 PhongShade(vec3 N, vec3 BaseColor, vec3 ViewDir) {\n // Blinn-Phong Beleuchtungsmodell\n const vec3 Ka = vec3(0.01); const vec3 Kd = vec3(1.0); const vec3 Ks = vec3(0.3); float NExp = 120.0;\n vec3 H = normalize(ViewDir + lightDir);\n return BaseColor * (Ka + Kd * max(dot(N, lightDir), 0.0)) + Ks * pow(max(dot(N, H), 0.0), NExp);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n// --------------------------------------------------\n// TASK 3: Transfer Function \n// --------------------------------------------------\nvec4 TransferFunction(float density, float gradientMagnitude) {\n // Referenzwerte HU (Hounsfield Units)\n const float huAir = -800.0;\n const float huTissue = 50.0;\n const float huBone = 700.0;\n\n // Zielwerte\n const float alphaTissue = 0.03;\n const float alphaBone = 1.0;\n const vec3 colorTissue = vec3(0.929, 0.675, 0.522);\n const vec3 colorBone = vec3(0.949, 0.898, 0.643);\n\n vec3 color = vec3(1.0); // Default Weiß\n float alpha = 0.0; // Default Transparent\n\n \n if (density <= huAir) {\n alpha = 0.0;\n color = vec3(0.0);\n }\n\n // TODO: Implementieren Sie die Klassifizierung für die Zielwerte oben\n\n /* SOLUTION TASK 3 START \n else if (density < huTissue) {\n float t = (density - huAir) / (huTissue - huAir);\n alpha = mix(0.0, alphaTissue, t);\n color = mix(vec3(0.0), colorTissue, t);\n } \n else if (density < huBone) {\n float t = (density - huTissue) / (huBone - huTissue);\n alpha = mix(alphaTissue, alphaBone, t);\n color = mix(colorTissue, colorBone, t);\n }\n SOLUTION TASK 3 END */\n \n else {\n alpha = alphaBone;\n color = colorBone;\n }\n\n // Fallback für Task 2 (Silhouetten-Modus):\n // Wenn die TransferFunction noch leer ist (alpha 0), aber Dichte da ist, mach es weiß.\n if (alpha == 0.0 && density > huAir) { alpha = 0.1; } \n\n return vec4(color, alpha);\n}\n\n\n\n\n\n\n// SampleVolume berechnet **an einer 3D-Koordinate im Volumen** die benötigten Werte.\n// samplePosition → Koordinate im Volumen\n// rayDirection → Richtungsvektor (für Gradienten / Beleuchtung berechnung)\n// return → vec4, rgb = Farbe, a = Opazität\nvec4 SampleVolume(vec3 samplePosition, vec3 rayDirection) {\n float rawValue = texture(volumeTexture, samplePosition).r;\n float density = rawValue - 1100.0; // Korrektur der Rohdaten\n \n vec3 gradient = ComputeGradient(samplePosition);\n \n vec4 material = TransferFunction(density, length(gradient));\n \n // Kantenverstärkung (Levoy)\n material.a *= (1.0 - exp(-5.0 * length(gradient))); \n\n vec3 shadedColor = PhongShade(normalize(-gradient), material.rgb, -rayDirection);\n return vec4(shadedColor, material.a);\n}\n\n\n\n\n// --------------------------------------------------\n// TASK 2: Raymarching Loop \n// --------------------------------------------------\nvec3 Raymarch(vec3 rayOrigin, vec3 rayDirection) {\n // SENTINEL: Wir initialisieren auf -1.0. \n // Sobald Sie Task 2 beginnen, ändern Sie dies auf vec3(0.0) (Schwarz).\n vec3 accumulatedColor = vec3(-1.0);\n \n int totalSteps = min(int(1.0 / stepSize), maxSteps);\n\n // TODO: Implementieren Sie die Schleife (Siehe Theory Abschnitt 2 & 3)\n \n /* SOLUTION TASK 2 START \n accumulatedColor = vec3(0.0); // Überschreibe Sentinel\n for (int i = totalSteps - 1; i >= 0; --i) {\n float t = float(i) * stepSize;\n\n vec3 currentPosition = rayOrigin + rayDirection * t;\n\n // Bounds Check\n if (any(lessThan(currentPosition, vec3(0.0))) || any(greaterThan(currentPosition, vec3(1.0))))\n continue;\n\n vec4 src = SampleVolume(currentPosition, rayDirection);\n accumulatedColor = src.rgb * src.a + accumulatedColor * (1.0 - src.a);\n }\n SOLUTION TASK 2 END */\n \n return accumulatedColor;\n}\n\n\n\n\n// --------------------------------------------------\n// TASK 1: Ray Generation \n// --------------------------------------------------\nvoid GenerateRay(out vec3 rayOrigin, out vec3 rayDirection) {\n float Aspect = float(iResolution.x) / float(iResolution.y);\n vec2 pixelPos = vUv;\n pixelPos.x *= Aspect;\n\n // Basisvektoren der Kamera\n vec3 forward = normalize(cameraDirection);\n vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));\n vec3 up = cross(right, forward);\n\n // TODO: Berechnen Sie Strahlstartpunkt und Richtung für Orthographische Projektion\n // Formel: Siehe Theory Abschnitt 1\n \n rayDirection = vec3(0.0); // Platzhalter\n rayOrigin = vec3(0.0); // Platzhalter\n\n /* SOLUTION TASK 1 START \n rayDirection = forward;\n rayOrigin = cameraPosition + (right * pixelPos.x + up * pixelPos.y) * orthoScale;\n SOLUTION TASK 1 END */\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid main() {\n vec3 rayOrigin, rayDirection;\n GenerateRay(rayOrigin, rayDirection);\n\n // Wir rufen den Loop immer auf.\n // Wenn er noch nicht implementiert ist, kommt der Sentinel (-1.0) zurück.\n vec3 resultColor = Raymarch(rayOrigin + 0.5, rayDirection); // +0.5 um den Kopf in den Ursprung zu verschieben\n\n // AUTOMATISCHE VORSCHAU \n \n // ZUSTAND 3: Sentinel (-1.0) wurde im Loop überschrieben -> Task 2 ist aktiv!\n // Wir zeigen das Ergebnis (Schwarz oder Bunt)\n if (resultColor.x >= 0.0) {\n fragColor = vec4(resultColor, 1.0);\n } \n // ZUSTAND 2: RayGen ist implementiert (Richtung != 0), aber Loop fehlt noch (Sentinel -1)\n // Wir zeigen die Ray-Origin als Debug-Farbe.\n else if (length(rayDirection) > 0.0) {\n fragColor = vec4(rayOrigin * 0.5 + 0.5, 1.0);\n } \n // ZUSTAND 1: Startzustand\n else {\n fragColor = vec4(vUv * 0.5 + 0.5, 0.0, 1.0); \n }\n}" |
| 93 | + "starterFragmentShader": "precision highp float;\nprecision highp sampler3D;\n\nin vec2 vUv;\nout vec4 fragColor;\n\n// Uniforms\nuniform vec3 cameraPosition;\nuniform vec3 cameraDirection;\nuniform sampler3D volumeTexture;\nuniform ivec2 iResolution;\n\n// Konstanten\nconst float stepSize = 0.00256;\nconst int maxSteps = 512;\nconst vec3 lightDir = normalize(vec3(1.0, 1.0, 0.0));\nconst float orthoScale = 0.5;\n\n// Helper Functions (Bereits implementiert) \n\nvec3 ComputeGradient(vec3 samplePosition) {\n // Zentraler Differenzenquotient zur Bestimmung der Normale\n vec3 H = 1.0 / vec3(textureSize(volumeTexture, 0));\n float Fx1 = texture(volumeTexture, clamp(samplePosition + vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fx2 = texture(volumeTexture, clamp(samplePosition - vec3(H.x, 0.0, 0.0), 0.0, 1.0)).r;\n float Fy1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fy2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, H.y, 0.0), 0.0, 1.0)).r;\n float Fz1 = texture(volumeTexture, clamp(samplePosition + vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n float Fz2 = texture(volumeTexture, clamp(samplePosition - vec3(0.0, 0.0, H.z), 0.0, 1.0)).r;\n return vec3((Fx1 - Fx2), (Fy1 - Fy2), (Fz1 - Fz2)) / (2.0 * H);\n}\n\nvec3 PhongShade(vec3 N, vec3 BaseColor, vec3 ViewDir) {\n // Blinn-Phong Beleuchtungsmodell\n const vec3 Ka = vec3(0.01); const vec3 Kd = vec3(1.0); const vec3 Ks = vec3(0.3); float NExp = 120.0;\n vec3 H = normalize(ViewDir + lightDir);\n return BaseColor * (Ka + Kd * max(dot(N, lightDir), 0.0)) + Ks * pow(max(dot(N, H), 0.0), NExp);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n// --------------------------------------------------\n// TASK 3: Transfer Function \n// --------------------------------------------------\nvec4 TransferFunction(float density, float gradientMagnitude) {\n // Referenzwerte HU (Hounsfield Units)\n const float huAir = -800.0;\n const float huTissue = 50.0;\n const float huBone = 700.0;\n\n // Zielwerte\n const float alphaTissue = 0.03;\n const float alphaBone = 1.0;\n const vec3 colorTissue = vec3(0.929, 0.675, 0.522);\n const vec3 colorBone = vec3(0.949, 0.898, 0.643);\n\n vec3 color = vec3(1.0); // Default Weiß\n float alpha = 0.0; // Default Transparent\n\n\n if (density <= huAir) {\n alpha = 0.0;\n color = vec3(0.0);\n }\n\n\n // TODO: Implementieren Sie die Klassifizierung für die Zielwerte oben\n\n\n else {\n alpha = alphaBone;\n color = colorBone;\n }\n\n\n\n // Fallback für Task 2 (Silhouetten-Modus):\n // Wenn die TransferFunction noch leer ist (alpha 0), aber Dichte da ist, mach es weiß.\n if (alpha == 0.0 && density > huAir) { alpha = 0.1; } \n\n return vec4(color, alpha);\n}\n\n\n\n\n\n\n// SampleVolume berechnet **an einer 3D-Koordinate im Volumen** die benötigten Werte.\n// samplePosition → Koordinate im Volumen\n// rayDirection → Richtungsvektor (für Gradienten / Beleuchtung berechnung)\n// return → vec4, rgb = Farbe, a = Opazität\nvec4 SampleVolume(vec3 samplePosition, vec3 rayDirection) {\n float rawValue = texture(volumeTexture, samplePosition).r;\n float density = rawValue - 1100.0; // Korrektur der Rohdaten\n \n vec3 gradient = ComputeGradient(samplePosition);\n \n vec4 material = TransferFunction(density, length(gradient));\n \n // Kantenverstärkung (Levoy)\n material.a *= (1.0 - exp(-5.0 * length(gradient))); \n\n vec3 shadedColor = PhongShade(normalize(-gradient), material.rgb, -rayDirection);\n return vec4(shadedColor, material.a);\n}\n\n\n\n\n// --------------------------------------------------\n// TASK 2: Raymarching Loop \n// --------------------------------------------------\nvec3 Raymarch(vec3 rayOrigin, vec3 rayDirection) {\n\n int totalSteps = min(int(1.0 / stepSize), maxSteps);\n\n // Sobald Sie Task 2 beginnen, ändern Sie dies auf vec3(0.0) (Schwarz).\n vec3 accumulatedColor = vec3(-1.0);\n\n // TODO: Implementieren Sie die Raymarching Schleife (Siehe Theory Abschnitt 2 & 3)\n \n return accumulatedColor;\n}\n\n\n\n\n// --------------------------------------------------\n// TASK 1: Ray Generation \n// --------------------------------------------------\nvoid GenerateRay(out vec3 rayOrigin, out vec3 rayDirection) {\n float Aspect = float(iResolution.x) / float(iResolution.y);\n vec2 pixelPos = vUv;\n pixelPos.x *= Aspect;\n\n // Basisvektoren der Kamera\n vec3 forward = normalize(cameraDirection);\n vec3 right = normalize(cross(forward, vec3(0.0, 1.0, 0.0)));\n vec3 up = cross(right, forward);\n\n // TODO: Berechnen Sie Strahlstartpunkt und Richtung für Orthographische Projektion (Siehe Theory Abschnitt 1)\n \n rayDirection = vec3(0.0); // Platzhalter\n rayOrigin = vec3(0.0); // Platzhalter\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nvoid main() {\n vec3 rayOrigin, rayDirection;\n GenerateRay(rayOrigin, rayDirection);\n\n // Wir rufen den Loop immer auf.\n // Wenn er noch nicht implementiert ist, kommt der Sentinel (-1.0) zurück.\n vec3 resultColor = Raymarch(rayOrigin + 0.5, rayDirection); // +0.5 um den Kopf in den Ursprung zu verschieben\n\n // AUTOMATISCHE VORSCHAU \n \n // ZUSTAND 3: Sentinel (-1.0) wurde im Loop überschrieben -> Task 2 ist aktiv!\n // Wir zeigen das Ergebnis (Schwarz oder Bunt)\n if (resultColor.x >= 0.0) {\n fragColor = vec4(resultColor, 1.0);\n } \n // ZUSTAND 2: RayGen ist implementiert (Richtung != 0), aber Loop fehlt noch (Sentinel -1)\n // Wir zeigen die Ray-Origin als Debug-Farbe.\n else if (length(rayDirection) > 0.0) {\n fragColor = vec4(rayOrigin * 0.5 + 0.5, 1.0);\n } \n // ZUSTAND 1: Startzustand\n else {\n fragColor = vec4(vUv * 0.5 + 0.5, 0.0, 1.0); \n }\n}" |
94 | 94 | }, |
95 | 95 | { |
96 | 96 | "category": "Grundlagen Computergrafik", |
|
0 commit comments