From c9f864b0ab95c2dba4ce7d2f7c32f0980418a31f Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 11:47:56 -0700 Subject: [PATCH 01/14] added csc.rsp added csc.rsp to get compression and color working... idk why --- .../SimpleITK.meta => SampleScene.meta} | 2 +- Assets/csc.rsp | 2 + Assets/csc.rsp.meta | 7 +++ ProjectSettings/EditorSettings.asset | 56 ++++++++++++------- ProjectSettings/ProjectVersion.txt | 4 +- csc.rsp | 1 + 6 files changed, 48 insertions(+), 24 deletions(-) rename Assets/Scripts/{Importing/ImageFileImporter/Interface/SimpleITK.meta => SampleScene.meta} (77%) create mode 100644 Assets/csc.rsp create mode 100644 Assets/csc.rsp.meta create mode 100644 csc.rsp diff --git a/Assets/Scripts/Importing/ImageFileImporter/Interface/SimpleITK.meta b/Assets/Scripts/SampleScene.meta similarity index 77% rename from Assets/Scripts/Importing/ImageFileImporter/Interface/SimpleITK.meta rename to Assets/Scripts/SampleScene.meta index 78570c8c..85906d9c 100644 --- a/Assets/Scripts/Importing/ImageFileImporter/Interface/SimpleITK.meta +++ b/Assets/Scripts/SampleScene.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 2a823b11bfaf79741bf3312984c336fe +guid: b29785c43f69803468642c527b79dc58 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/csc.rsp b/Assets/csc.rsp new file mode 100644 index 00000000..fb1d8d08 --- /dev/null +++ b/Assets/csc.rsp @@ -0,0 +1,2 @@ +-r:System.Drawing.dll +-r:System.IO.Compression.dll \ No newline at end of file diff --git a/Assets/csc.rsp.meta b/Assets/csc.rsp.meta new file mode 100644 index 00000000..ad3806dd --- /dev/null +++ b/Assets/csc.rsp.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: cafdcbc396b144a48b7aa0b338842a11 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset index 78c18acc..5162e19f 100644 --- a/ProjectSettings/EditorSettings.asset +++ b/ProjectSettings/EditorSettings.asset @@ -1,21 +1,35 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!159 &1 -EditorSettings: - m_ObjectHideFlags: 0 - serializedVersion: 7 - m_ExternalVersionControlSupport: Visible Meta Files - m_SerializationMode: 2 - m_LineEndingsForNewScripts: 2 - m_DefaultBehaviorMode: 0 - m_SpritePackerMode: 0 - m_SpritePackerPaddingPower: 1 - m_EtcTextureCompressorBehavior: 1 - m_EtcTextureFastCompressor: 1 - m_EtcTextureNormalCompressor: 2 - m_EtcTextureBestCompressor: 4 - m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd - m_ProjectGenerationRootNamespace: - m_UserGeneratedProjectSuffix: - m_CollabEditorSettings: - inProgressEnabled: 1 +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 2 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmref + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 1 + m_AssetPipelineMode: 1 + m_CacheServerMode: 0 + m_CacheServerEndpoint: + m_CacheServerNamespacePrefix: default + m_CacheServerEnableDownload: 1 + m_CacheServerEnableUpload: 1 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt index d233b6dd..d53ff41f 100644 --- a/ProjectSettings/ProjectVersion.txt +++ b/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2019.4.23f1 -m_EditorVersionWithRevision: 2019.4.23f1 (3f4e01f1a5ec) +m_EditorVersion: 2019.4.11f1 +m_EditorVersionWithRevision: 2019.4.11f1 (2d9804dddde7) diff --git a/csc.rsp b/csc.rsp new file mode 100644 index 00000000..99afd1ef --- /dev/null +++ b/csc.rsp @@ -0,0 +1 @@ +-r:System.Drawing.dll \ No newline at end of file From 6cfca3645b2da87ee230e01f6c75372f4a970bf0 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:01:27 -0700 Subject: [PATCH 02/14] Added Clip Shader Added shader that will allow clipping from specific dimensions --- .../DirectVolumeRenderingClipShader.shader | 478 ++++++++++++++++++ ...irectVolumeRenderingClipShader.shader.meta | 9 + ProjectSettings/ProjectSettings.asset | 89 ++-- 3 files changed, 541 insertions(+), 35 deletions(-) create mode 100644 Assets/Shaders/DirectVolumeRenderingClipShader.shader create mode 100644 Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta diff --git a/Assets/Shaders/DirectVolumeRenderingClipShader.shader b/Assets/Shaders/DirectVolumeRenderingClipShader.shader new file mode 100644 index 00000000..72528a27 --- /dev/null +++ b/Assets/Shaders/DirectVolumeRenderingClipShader.shader @@ -0,0 +1,478 @@ +Shader "VolumeRendering/DirectVolumeRenderingClipShader" +{ + Properties + { + _DataTex ("Data Texture (Generated)", 3D) = "" {} + _GradientTex("Gradient Texture (Generated)", 3D) = "" {} + _NoiseTex("Noise Texture (Generated)", 2D) = "white" {} + _TFTex("Transfer Function Texture (Generated)", 2D) = "" {} + _MinVal("Min val", Range(0.0, 1.0)) = 0.0 + _MaxVal("Max val", Range(0.0, 1.0)) = 1.0 + _ClipDimMin("Clip Dim Min", Vector) = (0.0, 0.0, 0.0, 1.0) + _ClipDimMax("Clip Dim Max", Vector) = (1.0, 1.0, 1.0, 1.0) + } + SubShader + { + Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } + LOD 100 + Cull Front + ZTest LEqual + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + + Pass + { + CGPROGRAM + #pragma multi_compile MODE_DVR MODE_MIP MODE_SURF + #pragma multi_compile __ TF2D_ON + #pragma multi_compile __ CROSS_SECTION_ON + #pragma multi_compile __ LIGHTING_ON + #pragma multi_compile DEPTHWRITE_ON DEPTHWRITE_OFF + #pragma multi_compile __ DVR_BACKWARD_ON + #pragma multi_compile __ RAY_TERMINATE_ON + #pragma multi_compile __ USE_MAIN_LIGHT + #pragma multi_compile __ CUBIC_INTERPOLATION_ON + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + #include "TricubicSampling.cginc" + + #define AMBIENT_LIGHTING_FACTOR 0.5 + #define JITTER_FACTOR 5.0 + + struct vert_in + { + float4 vertex : POSITION; + float4 normal : NORMAL; + float2 uv : TEXCOORD0; + }; + + struct frag_in + { + float4 vertex : SV_POSITION; + float2 uv : TEXCOORD0; + float3 vertexLocal : TEXCOORD1; + float3 normal : NORMAL; + }; + + struct frag_out + { + float4 colour : SV_TARGET; +#if DEPTHWRITE_ON + float depth : SV_DEPTH; +#endif + }; + + sampler3D _DataTex; + sampler3D _GradientTex; + sampler2D _NoiseTex; + sampler2D _TFTex; + + float _MinVal; + float _MaxVal; + float3 _TextureSize; + +#if CROSS_SECTION_ON +#define CROSS_SECTION_TYPE_PLANE 1 +#define CROSS_SECTION_TYPE_BOX_INCL 2 +#define CROSS_SECTION_TYPE_BOX_EXCL 3 + float4x4 _CrossSectionMatrices[8]; + float _CrossSectionTypes[8]; + int _NumCrossSections; +#endif + + struct RayInfo + { + float3 startPos; + float3 endPos; + float3 direction; + float2 aabbInters; + }; + + struct RaymarchInfo + { + RayInfo ray; + int numSteps; + float numStepsRecip; + float stepSize; + }; + + float3 getViewRayDir(float3 vertexLocal) + { + if(unity_OrthoParams.w == 0) + { + // Perspective + return normalize(ObjSpaceViewDir(float4(vertexLocal, 0.0f))); + } + else + { + // Orthographic + float3 camfwd = mul((float3x3)unity_CameraToWorld, float3(0,0,-1)); + float4 camfwdobjspace = mul(unity_WorldToObject, camfwd); + return normalize(camfwdobjspace); + } + } + + // Find ray intersection points with axis aligned bounding box + float2 intersectAABB(float3 rayOrigin, float3 rayDir, float3 boxMin, float3 boxMax) + { + float3 tMin = (boxMin - rayOrigin) / rayDir; + float3 tMax = (boxMax - rayOrigin) / rayDir; + float3 t1 = min(tMin, tMax); + float3 t2 = max(tMin, tMax); + float tNear = max(max(t1.x, t1.y), t1.z); + float tFar = min(min(t2.x, t2.y), t2.z); + return float2(tNear, tFar); + }; + + // Get a ray for the specified fragment (back-to-front) + RayInfo getRayBack2Front(float3 vertexLocal) + { + RayInfo ray; + ray.direction = getViewRayDir(vertexLocal); + ray.startPos = vertexLocal + float3(0.5f, 0.5f, 0.5f); + // Find intersections with axis aligned boundinng box (the volume) + ray.aabbInters = intersectAABB(ray.startPos, ray.direction, float3(0.0, 0.0, 0.0), float3(1.0f, 1.0f, 1.0)); + + // Check if camera is inside AABB + const float3 farPos = ray.startPos + ray.direction * ray.aabbInters.y - float3(0.5f, 0.5f, 0.5f); + float4 clipPos = UnityObjectToClipPos(float4(farPos, 1.0f)); + ray.aabbInters += min(clipPos.w, 0.0); + + ray.endPos = ray.startPos + ray.direction * ray.aabbInters.y; + return ray; + } + + // Get a ray for the specified fragment (front-to-back) + RayInfo getRayFront2Back(float3 vertexLocal) + { + RayInfo ray = getRayBack2Front(vertexLocal); + ray.direction = -ray.direction; + float3 tmp = ray.startPos; + ray.startPos = ray.endPos; + ray.endPos = tmp; + return ray; + } + + RaymarchInfo initRaymarch(RayInfo ray, int maxNumSteps) + { + RaymarchInfo raymarchInfo; + raymarchInfo.stepSize = 1.732f/*greatest distance in box*/ / maxNumSteps; + raymarchInfo.numSteps = (int)clamp(abs(ray.aabbInters.x - ray.aabbInters.y) / raymarchInfo.stepSize, 1, maxNumSteps); + raymarchInfo.numStepsRecip = 1.0 / raymarchInfo.numSteps; + return raymarchInfo; + } + + // Gets the colour from a 1D Transfer Function (x = density) + float4 getTF1DColour(float density) + { + return tex2Dlod(_TFTex, float4(density, 0.0f, 0.0f, 0.0f)); + } + + // Gets the colour from a 2D Transfer Function (x = density, y = gradient magnitude) + float4 getTF2DColour(float density, float gradientMagnitude) + { + return tex2Dlod(_TFTex, float4(density, gradientMagnitude, 0.0f, 0.0f)); + } + + // Gets the density at the specified position + float getDensity(float3 pos) + { +#if CUBIC_INTERPOLATION_ON + return interpolateTricubicFast(_DataTex, float3(pos.x, pos.y, pos.z), _TextureSize); +#else + return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)); +#endif + } + + // Gets the gradient at the specified position + float3 getGradient(float3 pos) + { +#if CUBIC_INTERPOLATION_ON + return interpolateTricubicFast(_GradientTex, float3(pos.x, pos.y, pos.z), _TextureSize).rgb; +#else + return tex3Dlod(_GradientTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb; +#endif + } + + // Get the light direction (using main light or view direction, based on setting) + float3 getLightDirection(float3 viewDir) + { +#if defined(USE_MAIN_LIGHT) + return normalize(mul(unity_WorldToObject, _WorldSpaceLightPos0.xyz)); +#else + return viewDir; +#endif + } + + // Performs lighting calculations, and returns a modified colour. + float3 calculateLighting(float3 col, float3 normal, float3 lightDir, float3 eyeDir, float specularIntensity) + { + // Invert normal if facing opposite direction of view direction. + // Optimised version of: if(dot(normal, eyeDir) < 0.0) normal *= -1.0 + normal *= (step(0.0, dot(normal, eyeDir)) * 2.0 - 1.0); + + float ndotl = max(lerp(0.0f, 1.5f, dot(normal, lightDir)), AMBIENT_LIGHTING_FACTOR); + float3 diffuse = ndotl * col; + float3 v = eyeDir; + float3 r = normalize(reflect(-lightDir, normal)); + float rdotv = max( dot( r, v ), 0.0 ); + float3 specular = pow(rdotv, 32.0f) * float3(1.0f, 1.0f, 1.0f) * specularIntensity; + return diffuse + specular; + } + + // Converts local position to depth value + float localToDepth(float3 localPos) + { + float4 clipPos = UnityObjectToClipPos(float4(localPos, 1.0f)); + +#if defined(SHADER_API_GLCORE) || defined(SHADER_API_OPENGL) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) + return (clipPos.z / clipPos.w) * 0.5 + 0.5; +#else + return clipPos.z / clipPos.w; +#endif + } + + bool IsCutout(float3 currPos) + { +#if CROSS_SECTION_ON + // Move the reference in the middle of the mesh, like the pivot + float4 pos = float4(currPos - float3(0.5f, 0.5f, 0.5f), 1.0f); + + bool clipped = false; + for (int i = 0; i < _NumCrossSections && !clipped; ++i) + { + const int type = (int)_CrossSectionTypes[i]; + const float4x4 mat = _CrossSectionMatrices[i]; + + // Convert from model space to plane's vector space + float3 planeSpacePos = mul(mat, pos); + if (type == CROSS_SECTION_TYPE_PLANE) + clipped = planeSpacePos.z > 0.0f; + else if(type == CROSS_SECTION_TYPE_BOX_INCL) + clipped = !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); + else if(type == CROSS_SECTION_TYPE_BOX_EXCL) + clipped = planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; + } + return clipped; + /* + #if CUTOUT_PLANE + return planeSpacePos.z > 0.0f; + #elif CUTOUT_BOX_INCL + return !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); + #elif CUTOUT_BOX_EXCL + return planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; + #endif*/ +#else + return false; +#endif + } + + frag_in vert_main (vert_in v) + { + frag_in o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + o.vertexLocal = v.vertex; + o.normal = UnityObjectToWorldNormal(v.normal); + return o; + } + + // Direct Volume Rendering + frag_out frag_dvr(frag_in i) + { + #define MAX_NUM_STEPS 512 + #define OPACITY_THRESHOLD (1.0 - 1.0 / 255.0) + +#ifdef DVR_BACKWARD_ON + RayInfo ray = getRayBack2Front(i.vertexLocal); +#else + RayInfo ray = getRayFront2Back(i.vertexLocal); +#endif + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + float3 lightDir = normalize(ObjSpaceViewDir(float4(float3(0.0f, 0.0f, 0.0f), 0.0f))); + + // Create a small random offset in order to remove artifacts + ray.startPos += (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; + + float4 col = float4(0.0f, 0.0f, 0.0f, 0.0f); +#ifdef DVR_BACKWARD_ON + float tDepth = 0.0f; +#else + float tDepth = raymarchInfo.numStepsRecip * (raymarchInfo.numSteps - 1); +#endif + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + + // Perform slice culling (cross section plane) +#ifdef CROSS_SECTION_ON + if(IsCutout(currPos)) + continue; +#endif + + // Get the dansity/sample value of the current position + const float density = getDensity(currPos); + + // Apply visibility window + if (density < _MinVal || density > _MaxVal) continue; + + // Calculate gradient (needed for lighting and 2D transfer functions) +#if defined(TF2D_ON) || defined(LIGHTING_ON) + float3 gradient = getGradient(currPos); +#endif + + // Apply transfer function +#if TF2D_ON + float mag = length(gradient) / 1.75f; + float4 src = getTF2DColour(density, mag); +#else + float4 src = getTF1DColour(density); +#endif + + // Apply lighting +#if defined(LIGHTING_ON) && defined(DVR_BACKWARD_ON) + src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(ray.direction), ray.direction, 0.3f); +#elif defined(LIGHTING_ON) + src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(-ray.direction), -ray.direction, 0.3f); +#endif + +#ifdef DVR_BACKWARD_ON + col.rgb = src.a * src.rgb + (1.0f - src.a) * col.rgb; + col.a = src.a + (1.0f - src.a) * col.a; + + // Optimisation: A branchless version of: if (src.a > 0.15f) tDepth = t; + tDepth = max(tDepth, t * step(0.15, src.a)); +#else + src.rgb *= src.a; + col = (1.0f - col.a) * src + col; + + if (col.a > 0.15 && t < tDepth) { + tDepth = t; + } +#endif + + // Early ray termination +#if !defined(DVR_BACKWARD_ON) && defined(RAY_TERMINATE_ON) + if (col.a > OPACITY_THRESHOLD) { + break; + } +#endif + } + + // Write fragment output + frag_out output; + output.colour = col; +#if DEPTHWRITE_ON + tDepth += (step(col.a, 0.0) * 1000.0); // Write large depth if no hit + const float3 depthPos = lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f); + output.depth = localToDepth(depthPos); +#endif + return output; + } + + // Maximum Intensity Projection mode + frag_out frag_mip(frag_in i) + { + #define MAX_NUM_STEPS 512 + + RayInfo ray = getRayBack2Front(i.vertexLocal); + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + float maxDensity = 0.0f; + float3 maxDensityPos = ray.startPos; + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + +#ifdef CROSS_SECTION_ON + if (IsCutout(currPos)) + continue; +#endif + + const float density = getDensity(currPos); + if (density > maxDensity && density > _MinVal && density < _MaxVal) + { + maxDensity = density; + maxDensityPos = currPos; + } + } + + // Write fragment output + frag_out output; + output.colour = float4(1.0f, 1.0f, 1.0f, maxDensity); // maximum intensity +#if DEPTHWRITE_ON + output.depth = localToDepth(maxDensityPos - float3(0.5f, 0.5f, 0.5f)); +#endif + return output; + } + + // Surface rendering mode + // Draws the first point (closest to camera) with a density within the user-defined thresholds. + frag_out frag_surf(frag_in i) + { + #define MAX_NUM_STEPS 1024 + + RayInfo ray = getRayFront2Back(i.vertexLocal); + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + // Create a small random offset in order to remove artifacts + ray.startPos = ray.startPos + (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; + + float4 col = float4(0,0,0,0); + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + +#ifdef CROSS_SECTION_ON + if (IsCutout(currPos)) + continue; +#endif + + const float density = getDensity(currPos); + if (density > _MinVal && density < _MaxVal) + { + float3 normal = normalize(getGradient(currPos)); + col = getTF1DColour(density); + col.rgb = calculateLighting(col.rgb, normal, getLightDirection(-ray.direction), -ray.direction, 0.15); + col.a = 1.0f; + break; + } + } + + // Write fragment output + frag_out output; + output.colour = col; +#if DEPTHWRITE_ON + + const float tDepth = iStep * raymarchInfo.numStepsRecip + (step(col.a, 0.0) * 1000.0); // Write large depth if no hit + output.depth = localToDepth(lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f)); +#endif + return output; + } + + frag_in vert(vert_in v) + { + return vert_main(v); + } + + frag_out frag(frag_in i) + { +#if MODE_DVR + return frag_dvr(i); +#elif MODE_MIP + return frag_mip(i); +#elif MODE_SURF + return frag_surf(i); +#endif + } + + ENDCG + } + } +} diff --git a/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta b/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta new file mode 100644 index 00000000..cadaee2c --- /dev/null +++ b/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a8ce2343c9eb4ad42970cff15e48cd5f +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 691412eb..7cfebd19 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -3,7 +3,7 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 18 + serializedVersion: 20 productGUID: 7e7b03b4f05be5643a2618a6bd9b64d9 AndroidProfiler: 0 AndroidFilterTouchesWhenObscured: 0 @@ -52,7 +52,6 @@ PlayerSettings: m_StackTraceTypes: 010000000100000001000000010000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 - displayResolutionDialog: 1 iosUseCustomAppBackgroundBehavior: 0 iosAllowHTTPDownload: 1 allowedAutorotateToPortrait: 1 @@ -85,7 +84,6 @@ PlayerSettings: useMacAppStoreValidation: 0 macAppStoreCategory: public.app-category.games gpuSkinning: 1 - graphicsJobs: 0 xboxPIXTextureCapture: 0 xboxEnableAvatar: 0 xboxEnableKinect: 0 @@ -93,7 +91,6 @@ PlayerSettings: xboxEnableFitness: 0 visibleInBackground: 1 allowFullscreenSwitch: 1 - graphicsJobMode: 0 fullscreenMode: 1 xboxSpeechDB: 0 xboxEnableHeadOrientation: 0 @@ -106,6 +103,7 @@ PlayerSettings: xboxOneMonoLoggingLevel: 0 xboxOneLoggingLevel: 1 xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 xboxOnePresentImmediateThreshold: 0 switchQueueCommandMemory: 0 switchQueueControlMemory: 16384 @@ -113,7 +111,13 @@ PlayerSettings: switchNVNShaderPoolsGranularity: 33554432 switchNVNDefaultPoolsGranularity: 16777216 switchNVNOtherPoolsGranularity: 16777216 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 vulkanEnableSetSRGBWrite: 0 + vulkanEnableLateAcquireNextImage: 0 m_SupportedAspectRatios: 4:3: 1 5:4: 1 @@ -155,9 +159,9 @@ PlayerSettings: v2Signing: 0 enable360StereoCapture: 0 isWsaHolographicRemotingEnabled: 0 - protectGraphicsMemory: 0 enableFrameTimingStats: 0 useHDRDisplay: 0 + D3DHDRBitDepth: 0 m_ColorGamuts: 00000000 targetPixelDensity: 30 resolutionScalingMode: 0 @@ -166,7 +170,7 @@ PlayerSettings: applicationIdentifier: {} buildNumber: {} AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 16 + AndroidMinSdkVersion: 19 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: @@ -181,32 +185,16 @@ PlayerSettings: StripUnusedMeshComponents: 1 VertexChannelCompressionMask: 4054 iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 9.0 + iOSTargetOSVersionString: 10.0 tvOSSdkVersion: 0 tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 9.0 + tvOSTargetOSVersionString: 10.0 uIPrerenderedIcon: 0 uIRequiresPersistentWiFi: 0 uIRequiresFullScreen: 1 uIStatusBarHidden: 1 uIExitOnSuspend: 0 uIStatusBarStyle: 0 - iPhoneSplashScreen: {fileID: 0} - iPhoneHighResSplashScreen: {fileID: 0} - iPhoneTallHighResSplashScreen: {fileID: 0} - iPhone47inSplashScreen: {fileID: 0} - iPhone55inPortraitSplashScreen: {fileID: 0} - iPhone55inLandscapeSplashScreen: {fileID: 0} - iPhone58inPortraitSplashScreen: {fileID: 0} - iPhone58inLandscapeSplashScreen: {fileID: 0} - iPadPortraitSplashScreen: {fileID: 0} - iPadHighResPortraitSplashScreen: {fileID: 0} - iPadLandscapeSplashScreen: {fileID: 0} - iPadHighResLandscapeSplashScreen: {fileID: 0} - iPhone65inPortraitSplashScreen: {fileID: 0} - iPhone65inLandscapeSplashScreen: {fileID: 0} - iPhone61inPortraitSplashScreen: {fileID: 0} - iPhone61inLandscapeSplashScreen: {fileID: 0} appleTVSplashScreen: {fileID: 0} appleTVSplashScreen2x: {fileID: 0} tvOSSmallIconLayers: [] @@ -274,7 +262,6 @@ PlayerSettings: androidGamepadSupportLevel: 0 AndroidValidateAppBundleSize: 1 AndroidAppBundleSizeToValidate: 150 - resolutionDialogBanner: {fileID: 0} m_BuildTargetIcons: [] m_BuildTargetPlatformIcons: [] m_BuildTargetBatching: @@ -293,6 +280,40 @@ PlayerSettings: - m_BuildTarget: WebGL m_StaticBatching: 0 m_DynamicBatching: 0 + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 0 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 0 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 0 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 0 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: CloudRendering + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 m_BuildTargetGraphicsAPIs: - m_BuildTarget: AndroidPlayer m_APIs: 0b00000015000000 @@ -315,7 +336,6 @@ PlayerSettings: openGLRequireES31: 0 openGLRequireES31AEP: 0 openGLRequireES32: 0 - vuforiaEnabled: 0 m_TemplateCustomTags: {} mobileMTRendering: Android: 1 @@ -488,6 +508,7 @@ PlayerSettings: ps4ShareFilePath: ps4ShareOverlayImagePath: ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: ps4NPtitleDatPath: ps4RemotePlayKeyAssignment: -1 ps4RemotePlayKeyMappingDir: @@ -513,6 +534,7 @@ PlayerSettings: ps4UseResolutionFallback: 0 ps4ReprojectionSupport: 0 ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 ps4SocialScreenEnabled: 0 ps4ScriptOptimizationLevel: 0 ps4Audio3dVirtualSpeakerCount: 14 @@ -529,8 +551,11 @@ PlayerSettings: ps4disableAutoHideSplash: 0 ps4videoRecordingFeaturesUsed: 0 ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4GPU800MHz: 1 ps4attribEyeToEyeDistanceSettingVR: 0 ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 monoEnv: splashScreenBackgroundSourceLandscape: {fileID: 0} splashScreenBackgroundSourcePortrait: {fileID: 0} @@ -574,7 +599,8 @@ PlayerSettings: scriptingRuntimeVersion: 1 gcIncremental: 0 gcWBarrierValidation: 0 - apiCompatibilityLevelPerPlatform: {} + apiCompatibilityLevelPerPlatform: + Standalone: 3 m_RenderingPath: 1 m_MobileRenderingPath: 1 metroPackageName: Template_3D @@ -628,8 +654,8 @@ PlayerSettings: XboxOneAllowedProductIds: [] XboxOnePersistentLocalStorageSize: 0 XboxOneXTitleMemory: 8 - xboxOneScriptCompiler: 1 XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: vrEditorSettings: daydream: daydreamIconForeground: {fileID: 0} @@ -647,13 +673,6 @@ PlayerSettings: luminVersion: m_VersionCode: 1 m_VersionName: - facebookSdkVersion: 7.9.4 - facebookAppId: - facebookCookies: 1 - facebookLogging: 1 - facebookStatus: 1 - facebookXfbml: 0 - facebookFrictionlessRequests: 1 apiCompatibilityLevel: 6 cloudProjectId: framebufferDepthMemorylessMode: 0 From 2a4dc163c1c2c71bf49a8b344247dd7d7f593e75 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:05:04 -0700 Subject: [PATCH 03/14] updated DirectVolumeRenderingClipShader Added functionality to skip voxels if they lay outside the min/max clip dims --- Assets/Shaders/DirectVolumeRenderingClipShader.shader | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Assets/Shaders/DirectVolumeRenderingClipShader.shader b/Assets/Shaders/DirectVolumeRenderingClipShader.shader index 72528a27..7a812a65 100644 --- a/Assets/Shaders/DirectVolumeRenderingClipShader.shader +++ b/Assets/Shaders/DirectVolumeRenderingClipShader.shader @@ -73,6 +73,9 @@ float _MaxVal; float3 _TextureSize; + // For clipping in any direction + float4 _ClipDimMin, _ClipDimMax; + #if CROSS_SECTION_ON #define CROSS_SECTION_TYPE_PLANE 1 #define CROSS_SECTION_TYPE_BOX_INCL 2 @@ -320,6 +323,11 @@ // Apply visibility window if (density < _MinVal || density > _MaxVal) continue; + // cut with clip dims + if (currPos.x < _ClipDimMin.x || currPos.x > _ClipDimMax.x) continue; + if (currPos.y < _ClipDimMin.y || currPos.y > _ClipDimMax.y) continue; + if (currPos.z < _ClipDimMin.z || currPos.z > _ClipDimMax.z) continue; + // Calculate gradient (needed for lighting and 2D transfer functions) #if defined(TF2D_ON) || defined(LIGHTING_ON) float3 gradient = getGradient(currPos); From 749848ba048879598f89c7cfa2232860041833bd Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:15:22 -0700 Subject: [PATCH 04/14] Update VolumeRenderedObject.cs updated volumerenderedobject to account for clipping dimensions --- .../VolumeObject/VolumeRenderedObject.cs | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Assets/Scripts/VolumeObject/VolumeRenderedObject.cs b/Assets/Scripts/VolumeObject/VolumeRenderedObject.cs index c4232a04..5e3ea664 100644 --- a/Assets/Scripts/VolumeObject/VolumeRenderedObject.cs +++ b/Assets/Scripts/VolumeObject/VolumeRenderedObject.cs @@ -36,6 +36,13 @@ public class VolumeRenderedObject : MonoBehaviour private bool cubicInterpolationEnabled = false; private CrossSectionManager crossSectionManager; + + [SerializeField, HideInInspector] + private Vector2 ClipDim1 = new Vector2(0.0f, 1.0f); + [SerializeField, HideInInspector] + private Vector2 ClipDim2 = new Vector2(0.0f, 1.0f); + [SerializeField, HideInInspector] + private Vector2 ClipDim3 = new Vector2(0.0f, 1.0f); public SlicingPlane CreateSlicingPlane() { @@ -138,6 +145,47 @@ public Vector2 GetVisibilityWindow() return visibilityWindow; } + public void SetClipDims(Vector2 dim1, Vector2 dim2, Vector2 dim3) + { + bool different = false; + + if (dim1 != ClipDim1) + { + ClipDim1 = dim1; + different = true; + } + if (dim2 != ClipDim2) + { + ClipDim2 = dim2; + different = true; + } + if (dim3 != ClipDim3) + { + ClipDim3 = dim3; + different = true; + } + if (different) + { + UpdateMaterialProperties(); + } + } + + public Vector2 GetClipDim1() + { + return ClipDim1; + } + + public Vector2 GetClipDim2() + { + return ClipDim2; + } + + public Vector2 GetClipDim3() + { + return ClipDim3; + } + + public bool GetRayTerminationEnabled() { return rayTerminationEnabled; @@ -241,6 +289,9 @@ private void UpdateMaterialProperties() meshRenderer.sharedMaterial.SetFloat("_MaxVal", visibilityWindow.y); meshRenderer.sharedMaterial.SetVector("_TextureSize", new Vector3(dataset.dimX, dataset.dimY, dataset.dimZ)); + meshRenderer.sharedMaterial.SetVector("_ClipDimMin", new Vector4(ClipDim1.x, ClipDim2.x, ClipDim3.x, 1f)); + meshRenderer.sharedMaterial.SetVector("_ClipDimMax", new Vector4(ClipDim1.y, ClipDim2.y, ClipDim3.y, 1f)); + if (rayTerminationEnabled) meshRenderer.sharedMaterial.EnableKeyword("RAY_TERMINATE_ON"); else From 4111a57777acdac0565cd1ecb76b63d33023659f Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:15:38 -0700 Subject: [PATCH 05/14] Update VolumeRenderedObjectCustomInspector.cs added inspector to change the clipping dimensions min/max --- .../VolumeRenderedObjectCustomInspector.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Assets/Editor/VolumeRenderedObjectCustomInspector.cs b/Assets/Editor/VolumeRenderedObjectCustomInspector.cs index 300bebc7..be437972 100644 --- a/Assets/Editor/VolumeRenderedObjectCustomInspector.cs +++ b/Assets/Editor/VolumeRenderedObjectCustomInspector.cs @@ -6,6 +6,7 @@ namespace UnityVolumeRendering [CustomEditor(typeof(VolumeRenderedObject))] public class VolumeRenderedObjectCustomInspector : Editor { + private bool clipSettings = false; private bool tfSettings = true; private bool lightSettings = true; private bool otherSettings = true; @@ -20,6 +21,30 @@ public override void OnInspectorGUI() if (newRenderMode != oldRenderMode) volrendObj.SetRenderMode(newRenderMode); + #region ClippingData + EditorGUILayout.Space(); + clipSettings = EditorGUILayout.Foldout(clipSettings, "Clipping Settings"); + + if (clipSettings) + { + // Clip dim 1 + Vector2 ClipDim1 = volrendObj.GetClipDim1(); + EditorGUILayout.MinMaxSlider("Clipping Dimension x", ref ClipDim1.x, ref ClipDim1.y, 0.0f, 1.0f); + + // Clip dim 2 + Vector2 ClipDim2 = volrendObj.GetClipDim2(); + EditorGUILayout.MinMaxSlider("Clipping Dimension y", ref ClipDim2.x, ref ClipDim2.y, 0.0f, 1.0f); + + // Clip dim 3 + Vector2 ClipDim3 = volrendObj.GetClipDim3(); + EditorGUILayout.MinMaxSlider("Clipping Dimension y", ref ClipDim3.x, ref ClipDim3.y, 0.0f, 1.0f); + + // setting clip dims + volrendObj.SetClipDims(ClipDim1, ClipDim2, ClipDim3); + } + #endregion EndClippingData + + // Visibility window Vector2 visibilityWindow = volrendObj.GetVisibilityWindow(); EditorGUILayout.MinMaxSlider("Visible value range", ref visibilityWindow.x, ref visibilityWindow.y, 0.0f, 1.0f); From c6b3a45c8075864f72fce3f76d95b027a90d0358 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:17:19 -0700 Subject: [PATCH 06/14] added clip material --- .../DirectVolumeRenderingClipMaterial.mat | 98 +++++++++++++++++++ ...DirectVolumeRenderingClipMaterial.mat.meta | 8 ++ 2 files changed, 106 insertions(+) create mode 100644 Assets/Materials/DirectVolumeRenderingClipMaterial.mat create mode 100644 Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta diff --git a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat new file mode 100644 index 00000000..c50add0c --- /dev/null +++ b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat @@ -0,0 +1,98 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: DirectVolumeRenderingClipMaterial + m_Shader: {fileID: 4800000, guid: a8ce2343c9eb4ad42970cff15e48cd5f, type: 3} + m_ShaderKeywords: MODE_DVR TF2D_ON _MODE_DVR _MODE_MIP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: + - pass0 + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DataTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _GradientTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _NoiseTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _TFTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _MaxVal: 1 + - _Metallic: 0 + - _MinVal: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _ClipDimMax: {r: 1, g: 1, b: 1, a: 1} + - _ClipDimMin: {r: 0, g: 0, b: 0, a: 1} + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta new file mode 100644 index 00000000..47b5c243 --- /dev/null +++ b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c4954cbc3bdf4b54fb6fd0ea0c1e9d2b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: From 1206a4ee2f27ec86531ac67986743051a5cdd481 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:07:40 -0700 Subject: [PATCH 07/14] Changed material to use clip shader final step, changed shader to account for clip shader --- Assets/Materials/DirectVolumeRenderingMaterial.mat | 4 +++- Assets/Scripts/VolumeObject/MaterialFactory.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Assets/Materials/DirectVolumeRenderingMaterial.mat b/Assets/Materials/DirectVolumeRenderingMaterial.mat index 0686b26e..60319581 100644 --- a/Assets/Materials/DirectVolumeRenderingMaterial.mat +++ b/Assets/Materials/DirectVolumeRenderingMaterial.mat @@ -8,7 +8,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: DirectVolumeRenderingMaterial - m_Shader: {fileID: 4800000, guid: f9df7f8cb5dda3a48a945ab37d6b0d83, type: 3} + m_Shader: {fileID: 4800000, guid: a8ce2343c9eb4ad42970cff15e48cd5f, type: 3} m_ShaderKeywords: MODE_DVR TF2D_ON _MODE_DVR _MODE_MIP m_LightmapFlags: 4 m_EnableInstancingVariants: 0 @@ -92,5 +92,7 @@ Material: - _UVSec: 0 - _ZWrite: 1 m_Colors: + - _ClipDimMax: {r: 1, g: 1, b: 1, a: 1} + - _ClipDimMin: {r: 0, g: 0, b: 0, a: 1} - _Color: {r: 1, g: 1, b: 1, a: 1} - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Scripts/VolumeObject/MaterialFactory.cs b/Assets/Scripts/VolumeObject/MaterialFactory.cs index d1242e46..a4ae0953 100644 --- a/Assets/Scripts/VolumeObject/MaterialFactory.cs +++ b/Assets/Scripts/VolumeObject/MaterialFactory.cs @@ -6,7 +6,7 @@ public class MaterialFactory { public static Material CreateMaterialDVR(VolumeDataset dataset) { - Shader shader = Shader.Find("VolumeRendering/DirectVolumeRenderingShader"); + Shader shader = Shader.Find("VolumeRendering/DirectVolumeRenderingClipShader"); Material material = new Material(shader); const int noiseDimX = 512; From ec1671d7a18e4f4be354c0930da4060b83306f5a Mon Sep 17 00:00:00 2001 From: smallvalthoss <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:11:37 -0700 Subject: [PATCH 08/14] Update CREDITS.md --- CREDITS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CREDITS.md b/CREDITS.md index 1a7c3fb1..af322ea9 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -14,5 +14,7 @@ GUI for modifying slicing plane positiomn/orientation. Memory leak fix - [Vahid](https://github.com/vahpy) Texture downscaling, optimisation. +- [Walter](https://github.com/smallvalthoss) +Adding xyz Dimensional Clipping. Feel free to add yourself to this list when contributing to this project. From 4cbe279f88709d86c3caffab22366c3b9df55ae4 Mon Sep 17 00:00:00 2001 From: smallvalthoss <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:11:54 -0700 Subject: [PATCH 09/14] Update CREDITS.md --- CREDITS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CREDITS.md b/CREDITS.md index af322ea9..55ab5d7e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -15,6 +15,6 @@ Memory leak fix - [Vahid](https://github.com/vahpy) Texture downscaling, optimisation. - [Walter](https://github.com/smallvalthoss) -Adding xyz Dimensional Clipping. +Adding xyz Dimensional Clipping to DirectVolumeRendering. Feel free to add yourself to this list when contributing to this project. From e53dc0617f75388c309aefeee045e384cfc76c57 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:30:32 -0700 Subject: [PATCH 10/14] Deleted DirectVolumeRenderingClipShader --- Assets/Resources/ignore.meta | 8 + .../DirectVolumeRenderingClipShader.shader | 486 --------- ...irectVolumeRenderingClipShader.shader.meta | 9 - .../DirectVolumeRenderingShader.shader | 956 +++++++++--------- 4 files changed, 491 insertions(+), 968 deletions(-) create mode 100644 Assets/Resources/ignore.meta delete mode 100644 Assets/Shaders/DirectVolumeRenderingClipShader.shader delete mode 100644 Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta diff --git a/Assets/Resources/ignore.meta b/Assets/Resources/ignore.meta new file mode 100644 index 00000000..44b10945 --- /dev/null +++ b/Assets/Resources/ignore.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3510413e4161f6f49830a4acc5fcd5b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Shaders/DirectVolumeRenderingClipShader.shader b/Assets/Shaders/DirectVolumeRenderingClipShader.shader deleted file mode 100644 index 7a812a65..00000000 --- a/Assets/Shaders/DirectVolumeRenderingClipShader.shader +++ /dev/null @@ -1,486 +0,0 @@ -Shader "VolumeRendering/DirectVolumeRenderingClipShader" -{ - Properties - { - _DataTex ("Data Texture (Generated)", 3D) = "" {} - _GradientTex("Gradient Texture (Generated)", 3D) = "" {} - _NoiseTex("Noise Texture (Generated)", 2D) = "white" {} - _TFTex("Transfer Function Texture (Generated)", 2D) = "" {} - _MinVal("Min val", Range(0.0, 1.0)) = 0.0 - _MaxVal("Max val", Range(0.0, 1.0)) = 1.0 - _ClipDimMin("Clip Dim Min", Vector) = (0.0, 0.0, 0.0, 1.0) - _ClipDimMax("Clip Dim Max", Vector) = (1.0, 1.0, 1.0, 1.0) - } - SubShader - { - Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } - LOD 100 - Cull Front - ZTest LEqual - ZWrite On - Blend SrcAlpha OneMinusSrcAlpha - - Pass - { - CGPROGRAM - #pragma multi_compile MODE_DVR MODE_MIP MODE_SURF - #pragma multi_compile __ TF2D_ON - #pragma multi_compile __ CROSS_SECTION_ON - #pragma multi_compile __ LIGHTING_ON - #pragma multi_compile DEPTHWRITE_ON DEPTHWRITE_OFF - #pragma multi_compile __ DVR_BACKWARD_ON - #pragma multi_compile __ RAY_TERMINATE_ON - #pragma multi_compile __ USE_MAIN_LIGHT - #pragma multi_compile __ CUBIC_INTERPOLATION_ON - #pragma vertex vert - #pragma fragment frag - - #include "UnityCG.cginc" - #include "TricubicSampling.cginc" - - #define AMBIENT_LIGHTING_FACTOR 0.5 - #define JITTER_FACTOR 5.0 - - struct vert_in - { - float4 vertex : POSITION; - float4 normal : NORMAL; - float2 uv : TEXCOORD0; - }; - - struct frag_in - { - float4 vertex : SV_POSITION; - float2 uv : TEXCOORD0; - float3 vertexLocal : TEXCOORD1; - float3 normal : NORMAL; - }; - - struct frag_out - { - float4 colour : SV_TARGET; -#if DEPTHWRITE_ON - float depth : SV_DEPTH; -#endif - }; - - sampler3D _DataTex; - sampler3D _GradientTex; - sampler2D _NoiseTex; - sampler2D _TFTex; - - float _MinVal; - float _MaxVal; - float3 _TextureSize; - - // For clipping in any direction - float4 _ClipDimMin, _ClipDimMax; - -#if CROSS_SECTION_ON -#define CROSS_SECTION_TYPE_PLANE 1 -#define CROSS_SECTION_TYPE_BOX_INCL 2 -#define CROSS_SECTION_TYPE_BOX_EXCL 3 - float4x4 _CrossSectionMatrices[8]; - float _CrossSectionTypes[8]; - int _NumCrossSections; -#endif - - struct RayInfo - { - float3 startPos; - float3 endPos; - float3 direction; - float2 aabbInters; - }; - - struct RaymarchInfo - { - RayInfo ray; - int numSteps; - float numStepsRecip; - float stepSize; - }; - - float3 getViewRayDir(float3 vertexLocal) - { - if(unity_OrthoParams.w == 0) - { - // Perspective - return normalize(ObjSpaceViewDir(float4(vertexLocal, 0.0f))); - } - else - { - // Orthographic - float3 camfwd = mul((float3x3)unity_CameraToWorld, float3(0,0,-1)); - float4 camfwdobjspace = mul(unity_WorldToObject, camfwd); - return normalize(camfwdobjspace); - } - } - - // Find ray intersection points with axis aligned bounding box - float2 intersectAABB(float3 rayOrigin, float3 rayDir, float3 boxMin, float3 boxMax) - { - float3 tMin = (boxMin - rayOrigin) / rayDir; - float3 tMax = (boxMax - rayOrigin) / rayDir; - float3 t1 = min(tMin, tMax); - float3 t2 = max(tMin, tMax); - float tNear = max(max(t1.x, t1.y), t1.z); - float tFar = min(min(t2.x, t2.y), t2.z); - return float2(tNear, tFar); - }; - - // Get a ray for the specified fragment (back-to-front) - RayInfo getRayBack2Front(float3 vertexLocal) - { - RayInfo ray; - ray.direction = getViewRayDir(vertexLocal); - ray.startPos = vertexLocal + float3(0.5f, 0.5f, 0.5f); - // Find intersections with axis aligned boundinng box (the volume) - ray.aabbInters = intersectAABB(ray.startPos, ray.direction, float3(0.0, 0.0, 0.0), float3(1.0f, 1.0f, 1.0)); - - // Check if camera is inside AABB - const float3 farPos = ray.startPos + ray.direction * ray.aabbInters.y - float3(0.5f, 0.5f, 0.5f); - float4 clipPos = UnityObjectToClipPos(float4(farPos, 1.0f)); - ray.aabbInters += min(clipPos.w, 0.0); - - ray.endPos = ray.startPos + ray.direction * ray.aabbInters.y; - return ray; - } - - // Get a ray for the specified fragment (front-to-back) - RayInfo getRayFront2Back(float3 vertexLocal) - { - RayInfo ray = getRayBack2Front(vertexLocal); - ray.direction = -ray.direction; - float3 tmp = ray.startPos; - ray.startPos = ray.endPos; - ray.endPos = tmp; - return ray; - } - - RaymarchInfo initRaymarch(RayInfo ray, int maxNumSteps) - { - RaymarchInfo raymarchInfo; - raymarchInfo.stepSize = 1.732f/*greatest distance in box*/ / maxNumSteps; - raymarchInfo.numSteps = (int)clamp(abs(ray.aabbInters.x - ray.aabbInters.y) / raymarchInfo.stepSize, 1, maxNumSteps); - raymarchInfo.numStepsRecip = 1.0 / raymarchInfo.numSteps; - return raymarchInfo; - } - - // Gets the colour from a 1D Transfer Function (x = density) - float4 getTF1DColour(float density) - { - return tex2Dlod(_TFTex, float4(density, 0.0f, 0.0f, 0.0f)); - } - - // Gets the colour from a 2D Transfer Function (x = density, y = gradient magnitude) - float4 getTF2DColour(float density, float gradientMagnitude) - { - return tex2Dlod(_TFTex, float4(density, gradientMagnitude, 0.0f, 0.0f)); - } - - // Gets the density at the specified position - float getDensity(float3 pos) - { -#if CUBIC_INTERPOLATION_ON - return interpolateTricubicFast(_DataTex, float3(pos.x, pos.y, pos.z), _TextureSize); -#else - return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)); -#endif - } - - // Gets the gradient at the specified position - float3 getGradient(float3 pos) - { -#if CUBIC_INTERPOLATION_ON - return interpolateTricubicFast(_GradientTex, float3(pos.x, pos.y, pos.z), _TextureSize).rgb; -#else - return tex3Dlod(_GradientTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb; -#endif - } - - // Get the light direction (using main light or view direction, based on setting) - float3 getLightDirection(float3 viewDir) - { -#if defined(USE_MAIN_LIGHT) - return normalize(mul(unity_WorldToObject, _WorldSpaceLightPos0.xyz)); -#else - return viewDir; -#endif - } - - // Performs lighting calculations, and returns a modified colour. - float3 calculateLighting(float3 col, float3 normal, float3 lightDir, float3 eyeDir, float specularIntensity) - { - // Invert normal if facing opposite direction of view direction. - // Optimised version of: if(dot(normal, eyeDir) < 0.0) normal *= -1.0 - normal *= (step(0.0, dot(normal, eyeDir)) * 2.0 - 1.0); - - float ndotl = max(lerp(0.0f, 1.5f, dot(normal, lightDir)), AMBIENT_LIGHTING_FACTOR); - float3 diffuse = ndotl * col; - float3 v = eyeDir; - float3 r = normalize(reflect(-lightDir, normal)); - float rdotv = max( dot( r, v ), 0.0 ); - float3 specular = pow(rdotv, 32.0f) * float3(1.0f, 1.0f, 1.0f) * specularIntensity; - return diffuse + specular; - } - - // Converts local position to depth value - float localToDepth(float3 localPos) - { - float4 clipPos = UnityObjectToClipPos(float4(localPos, 1.0f)); - -#if defined(SHADER_API_GLCORE) || defined(SHADER_API_OPENGL) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) - return (clipPos.z / clipPos.w) * 0.5 + 0.5; -#else - return clipPos.z / clipPos.w; -#endif - } - - bool IsCutout(float3 currPos) - { -#if CROSS_SECTION_ON - // Move the reference in the middle of the mesh, like the pivot - float4 pos = float4(currPos - float3(0.5f, 0.5f, 0.5f), 1.0f); - - bool clipped = false; - for (int i = 0; i < _NumCrossSections && !clipped; ++i) - { - const int type = (int)_CrossSectionTypes[i]; - const float4x4 mat = _CrossSectionMatrices[i]; - - // Convert from model space to plane's vector space - float3 planeSpacePos = mul(mat, pos); - if (type == CROSS_SECTION_TYPE_PLANE) - clipped = planeSpacePos.z > 0.0f; - else if(type == CROSS_SECTION_TYPE_BOX_INCL) - clipped = !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); - else if(type == CROSS_SECTION_TYPE_BOX_EXCL) - clipped = planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; - } - return clipped; - /* - #if CUTOUT_PLANE - return planeSpacePos.z > 0.0f; - #elif CUTOUT_BOX_INCL - return !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); - #elif CUTOUT_BOX_EXCL - return planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; - #endif*/ -#else - return false; -#endif - } - - frag_in vert_main (vert_in v) - { - frag_in o; - o.vertex = UnityObjectToClipPos(v.vertex); - o.uv = v.uv; - o.vertexLocal = v.vertex; - o.normal = UnityObjectToWorldNormal(v.normal); - return o; - } - - // Direct Volume Rendering - frag_out frag_dvr(frag_in i) - { - #define MAX_NUM_STEPS 512 - #define OPACITY_THRESHOLD (1.0 - 1.0 / 255.0) - -#ifdef DVR_BACKWARD_ON - RayInfo ray = getRayBack2Front(i.vertexLocal); -#else - RayInfo ray = getRayFront2Back(i.vertexLocal); -#endif - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - float3 lightDir = normalize(ObjSpaceViewDir(float4(float3(0.0f, 0.0f, 0.0f), 0.0f))); - - // Create a small random offset in order to remove artifacts - ray.startPos += (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; - - float4 col = float4(0.0f, 0.0f, 0.0f, 0.0f); -#ifdef DVR_BACKWARD_ON - float tDepth = 0.0f; -#else - float tDepth = raymarchInfo.numStepsRecip * (raymarchInfo.numSteps - 1); -#endif - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - - // Perform slice culling (cross section plane) -#ifdef CROSS_SECTION_ON - if(IsCutout(currPos)) - continue; -#endif - - // Get the dansity/sample value of the current position - const float density = getDensity(currPos); - - // Apply visibility window - if (density < _MinVal || density > _MaxVal) continue; - - // cut with clip dims - if (currPos.x < _ClipDimMin.x || currPos.x > _ClipDimMax.x) continue; - if (currPos.y < _ClipDimMin.y || currPos.y > _ClipDimMax.y) continue; - if (currPos.z < _ClipDimMin.z || currPos.z > _ClipDimMax.z) continue; - - // Calculate gradient (needed for lighting and 2D transfer functions) -#if defined(TF2D_ON) || defined(LIGHTING_ON) - float3 gradient = getGradient(currPos); -#endif - - // Apply transfer function -#if TF2D_ON - float mag = length(gradient) / 1.75f; - float4 src = getTF2DColour(density, mag); -#else - float4 src = getTF1DColour(density); -#endif - - // Apply lighting -#if defined(LIGHTING_ON) && defined(DVR_BACKWARD_ON) - src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(ray.direction), ray.direction, 0.3f); -#elif defined(LIGHTING_ON) - src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(-ray.direction), -ray.direction, 0.3f); -#endif - -#ifdef DVR_BACKWARD_ON - col.rgb = src.a * src.rgb + (1.0f - src.a) * col.rgb; - col.a = src.a + (1.0f - src.a) * col.a; - - // Optimisation: A branchless version of: if (src.a > 0.15f) tDepth = t; - tDepth = max(tDepth, t * step(0.15, src.a)); -#else - src.rgb *= src.a; - col = (1.0f - col.a) * src + col; - - if (col.a > 0.15 && t < tDepth) { - tDepth = t; - } -#endif - - // Early ray termination -#if !defined(DVR_BACKWARD_ON) && defined(RAY_TERMINATE_ON) - if (col.a > OPACITY_THRESHOLD) { - break; - } -#endif - } - - // Write fragment output - frag_out output; - output.colour = col; -#if DEPTHWRITE_ON - tDepth += (step(col.a, 0.0) * 1000.0); // Write large depth if no hit - const float3 depthPos = lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f); - output.depth = localToDepth(depthPos); -#endif - return output; - } - - // Maximum Intensity Projection mode - frag_out frag_mip(frag_in i) - { - #define MAX_NUM_STEPS 512 - - RayInfo ray = getRayBack2Front(i.vertexLocal); - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - float maxDensity = 0.0f; - float3 maxDensityPos = ray.startPos; - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - -#ifdef CROSS_SECTION_ON - if (IsCutout(currPos)) - continue; -#endif - - const float density = getDensity(currPos); - if (density > maxDensity && density > _MinVal && density < _MaxVal) - { - maxDensity = density; - maxDensityPos = currPos; - } - } - - // Write fragment output - frag_out output; - output.colour = float4(1.0f, 1.0f, 1.0f, maxDensity); // maximum intensity -#if DEPTHWRITE_ON - output.depth = localToDepth(maxDensityPos - float3(0.5f, 0.5f, 0.5f)); -#endif - return output; - } - - // Surface rendering mode - // Draws the first point (closest to camera) with a density within the user-defined thresholds. - frag_out frag_surf(frag_in i) - { - #define MAX_NUM_STEPS 1024 - - RayInfo ray = getRayFront2Back(i.vertexLocal); - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - // Create a small random offset in order to remove artifacts - ray.startPos = ray.startPos + (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; - - float4 col = float4(0,0,0,0); - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - -#ifdef CROSS_SECTION_ON - if (IsCutout(currPos)) - continue; -#endif - - const float density = getDensity(currPos); - if (density > _MinVal && density < _MaxVal) - { - float3 normal = normalize(getGradient(currPos)); - col = getTF1DColour(density); - col.rgb = calculateLighting(col.rgb, normal, getLightDirection(-ray.direction), -ray.direction, 0.15); - col.a = 1.0f; - break; - } - } - - // Write fragment output - frag_out output; - output.colour = col; -#if DEPTHWRITE_ON - - const float tDepth = iStep * raymarchInfo.numStepsRecip + (step(col.a, 0.0) * 1000.0); // Write large depth if no hit - output.depth = localToDepth(lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f)); -#endif - return output; - } - - frag_in vert(vert_in v) - { - return vert_main(v); - } - - frag_out frag(frag_in i) - { -#if MODE_DVR - return frag_dvr(i); -#elif MODE_MIP - return frag_mip(i); -#elif MODE_SURF - return frag_surf(i); -#endif - } - - ENDCG - } - } -} diff --git a/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta b/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta deleted file mode 100644 index cadaee2c..00000000 --- a/Assets/Shaders/DirectVolumeRenderingClipShader.shader.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: a8ce2343c9eb4ad42970cff15e48cd5f -ShaderImporter: - externalObjects: {} - defaultTextures: [] - nonModifiableTextures: [] - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Shaders/DirectVolumeRenderingShader.shader b/Assets/Shaders/DirectVolumeRenderingShader.shader index 2d4e2727..1e4a32f7 100644 --- a/Assets/Shaders/DirectVolumeRenderingShader.shader +++ b/Assets/Shaders/DirectVolumeRenderingShader.shader @@ -1,476 +1,486 @@ Shader "VolumeRendering/DirectVolumeRenderingShader" { - Properties - { - _DataTex ("Data Texture (Generated)", 3D) = "" {} - _GradientTex("Gradient Texture (Generated)", 3D) = "" {} - _NoiseTex("Noise Texture (Generated)", 2D) = "white" {} - _TFTex("Transfer Function Texture (Generated)", 2D) = "" {} - _MinVal("Min val", Range(0.0, 1.0)) = 0.0 - _MaxVal("Max val", Range(0.0, 1.0)) = 1.0 - } - SubShader - { - Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } - LOD 100 - Cull Front - ZTest LEqual - ZWrite On - Blend SrcAlpha OneMinusSrcAlpha - - Pass - { - CGPROGRAM - #pragma multi_compile MODE_DVR MODE_MIP MODE_SURF - #pragma multi_compile __ TF2D_ON - #pragma multi_compile __ CROSS_SECTION_ON - #pragma multi_compile __ LIGHTING_ON - #pragma multi_compile DEPTHWRITE_ON DEPTHWRITE_OFF - #pragma multi_compile __ DVR_BACKWARD_ON - #pragma multi_compile __ RAY_TERMINATE_ON - #pragma multi_compile __ USE_MAIN_LIGHT - #pragma multi_compile __ CUBIC_INTERPOLATION_ON - #pragma vertex vert - #pragma fragment frag - - #include "UnityCG.cginc" - #include "TricubicSampling.cginc" - - #define AMBIENT_LIGHTING_FACTOR 0.5 - #define JITTER_FACTOR 5.0 - - struct vert_in - { - float4 vertex : POSITION; - float4 normal : NORMAL; - float2 uv : TEXCOORD0; - }; - - struct frag_in - { - float4 vertex : SV_POSITION; - float2 uv : TEXCOORD0; - float3 vertexLocal : TEXCOORD1; - float3 normal : NORMAL; - }; - - struct frag_out - { - float4 colour : SV_TARGET; -#if DEPTHWRITE_ON - float depth : SV_DEPTH; -#endif - }; - - sampler3D _DataTex; - sampler3D _GradientTex; - sampler2D _NoiseTex; - sampler2D _TFTex; - - float _MinVal; - float _MaxVal; - float3 _TextureSize; - -#if CROSS_SECTION_ON -#define CROSS_SECTION_TYPE_PLANE 1 -#define CROSS_SECTION_TYPE_BOX_INCL 2 -#define CROSS_SECTION_TYPE_BOX_EXCL 3 - float4x4 _CrossSectionMatrices[8]; - float _CrossSectionTypes[8]; - int _NumCrossSections; -#endif - - struct RayInfo - { - float3 startPos; - float3 endPos; - float3 direction; - float2 aabbInters; - }; - - struct RaymarchInfo - { - RayInfo ray; - int numSteps; - float numStepsRecip; - float stepSize; - }; - - float3 getViewRayDir(float3 vertexLocal) - { - if(unity_OrthoParams.w == 0) - { - // Perspective - return normalize(ObjSpaceViewDir(float4(vertexLocal, 0.0f))); - } - else - { - // Orthographic - float3 camfwd = mul((float3x3)unity_CameraToWorld, float3(0,0,-1)); - float4 camfwdobjspace = mul(unity_WorldToObject, camfwd); - return normalize(camfwdobjspace); - } - } - - // Find ray intersection points with axis aligned bounding box - float2 intersectAABB(float3 rayOrigin, float3 rayDir, float3 boxMin, float3 boxMax) - { - float3 tMin = (boxMin - rayOrigin) / rayDir; - float3 tMax = (boxMax - rayOrigin) / rayDir; - float3 t1 = min(tMin, tMax); - float3 t2 = max(tMin, tMax); - float tNear = max(max(t1.x, t1.y), t1.z); - float tFar = min(min(t2.x, t2.y), t2.z); - return float2(tNear, tFar); - }; - - // Get a ray for the specified fragment (back-to-front) - RayInfo getRayBack2Front(float3 vertexLocal) - { - RayInfo ray; - ray.direction = getViewRayDir(vertexLocal); - ray.startPos = vertexLocal + float3(0.5f, 0.5f, 0.5f); - // Find intersections with axis aligned boundinng box (the volume) - ray.aabbInters = intersectAABB(ray.startPos, ray.direction, float3(0.0, 0.0, 0.0), float3(1.0f, 1.0f, 1.0)); - - // Check if camera is inside AABB - const float3 farPos = ray.startPos + ray.direction * ray.aabbInters.y - float3(0.5f, 0.5f, 0.5f); - float4 clipPos = UnityObjectToClipPos(float4(farPos, 1.0f)); - ray.aabbInters += min(clipPos.w, 0.0); - - ray.endPos = ray.startPos + ray.direction * ray.aabbInters.y; - return ray; - } - - // Get a ray for the specified fragment (front-to-back) - RayInfo getRayFront2Back(float3 vertexLocal) - { - RayInfo ray = getRayBack2Front(vertexLocal); - ray.direction = -ray.direction; - float3 tmp = ray.startPos; - ray.startPos = ray.endPos; - ray.endPos = tmp; - return ray; - } - - RaymarchInfo initRaymarch(RayInfo ray, int maxNumSteps) - { - RaymarchInfo raymarchInfo; - raymarchInfo.stepSize = 1.732f/*greatest distance in box*/ / maxNumSteps; - raymarchInfo.numSteps = (int)clamp(abs(ray.aabbInters.x - ray.aabbInters.y) / raymarchInfo.stepSize, 1, maxNumSteps); - raymarchInfo.numStepsRecip = 1.0 / raymarchInfo.numSteps; - return raymarchInfo; - } - - // Gets the colour from a 1D Transfer Function (x = density) - float4 getTF1DColour(float density) - { - return tex2Dlod(_TFTex, float4(density, 0.0f, 0.0f, 0.0f)); - } - - // Gets the colour from a 2D Transfer Function (x = density, y = gradient magnitude) - float4 getTF2DColour(float density, float gradientMagnitude) - { - return tex2Dlod(_TFTex, float4(density, gradientMagnitude, 0.0f, 0.0f)); - } - - // Gets the density at the specified position - float getDensity(float3 pos) - { -#if CUBIC_INTERPOLATION_ON - return interpolateTricubicFast(_DataTex, float3(pos.x, pos.y, pos.z), _TextureSize); -#else - return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)); -#endif - } - - // Gets the gradient at the specified position - float3 getGradient(float3 pos) - { -#if CUBIC_INTERPOLATION_ON - return interpolateTricubicFast(_GradientTex, float3(pos.x, pos.y, pos.z), _TextureSize).rgb; -#else - return tex3Dlod(_GradientTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb; -#endif - } - - // Get the light direction (using main light or view direction, based on setting) - float3 getLightDirection(float3 viewDir) - { -#if defined(USE_MAIN_LIGHT) - return normalize(mul(unity_WorldToObject, _WorldSpaceLightPos0.xyz)); -#else - return viewDir; -#endif - } - - // Performs lighting calculations, and returns a modified colour. - float3 calculateLighting(float3 col, float3 normal, float3 lightDir, float3 eyeDir, float specularIntensity) - { - // Invert normal if facing opposite direction of view direction. - // Optimised version of: if(dot(normal, eyeDir) < 0.0) normal *= -1.0 - normal *= (step(0.0, dot(normal, eyeDir)) * 2.0 - 1.0); - - float ndotl = max(lerp(0.0f, 1.5f, dot(normal, lightDir)), AMBIENT_LIGHTING_FACTOR); - float3 diffuse = ndotl * col; - float3 v = eyeDir; - float3 r = normalize(reflect(-lightDir, normal)); - float rdotv = max( dot( r, v ), 0.0 ); - float3 specular = pow(rdotv, 32.0f) * float3(1.0f, 1.0f, 1.0f) * specularIntensity; - return diffuse + specular; - } - - // Converts local position to depth value - float localToDepth(float3 localPos) - { - float4 clipPos = UnityObjectToClipPos(float4(localPos, 1.0f)); - -#if defined(SHADER_API_GLCORE) || defined(SHADER_API_OPENGL) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) - return (clipPos.z / clipPos.w) * 0.5 + 0.5; -#else - return clipPos.z / clipPos.w; -#endif - } - - bool IsCutout(float3 currPos) - { -#if CROSS_SECTION_ON - // Move the reference in the middle of the mesh, like the pivot - float4 pos = float4(currPos - float3(0.5f, 0.5f, 0.5f), 1.0f); - - bool clipped = false; - for (int i = 0; i < _NumCrossSections && !clipped; ++i) - { - const int type = (int)_CrossSectionTypes[i]; - const float4x4 mat = _CrossSectionMatrices[i]; - - // Convert from model space to plane's vector space - float3 planeSpacePos = mul(mat, pos); - if (type == CROSS_SECTION_TYPE_PLANE) - clipped = planeSpacePos.z > 0.0f; - else if(type == CROSS_SECTION_TYPE_BOX_INCL) - clipped = !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); - else if(type == CROSS_SECTION_TYPE_BOX_EXCL) - clipped = planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; - } - return clipped; - /* - #if CUTOUT_PLANE - return planeSpacePos.z > 0.0f; - #elif CUTOUT_BOX_INCL - return !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); - #elif CUTOUT_BOX_EXCL - return planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; - #endif*/ -#else - return false; -#endif - } - - frag_in vert_main (vert_in v) - { - frag_in o; - o.vertex = UnityObjectToClipPos(v.vertex); - o.uv = v.uv; - o.vertexLocal = v.vertex; - o.normal = UnityObjectToWorldNormal(v.normal); - return o; - } - - // Direct Volume Rendering - frag_out frag_dvr(frag_in i) - { - #define MAX_NUM_STEPS 512 - #define OPACITY_THRESHOLD (1.0 - 1.0 / 255.0) - -#ifdef DVR_BACKWARD_ON - RayInfo ray = getRayBack2Front(i.vertexLocal); -#else - RayInfo ray = getRayFront2Back(i.vertexLocal); -#endif - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - float3 lightDir = normalize(ObjSpaceViewDir(float4(float3(0.0f, 0.0f, 0.0f), 0.0f))); - - // Create a small random offset in order to remove artifacts - ray.startPos += (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; - - float4 col = float4(0.0f, 0.0f, 0.0f, 0.0f); -#ifdef DVR_BACKWARD_ON - float tDepth = 0.0f; -#else - float tDepth = raymarchInfo.numStepsRecip * (raymarchInfo.numSteps - 1); -#endif - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - - // Perform slice culling (cross section plane) -#ifdef CROSS_SECTION_ON - if(IsCutout(currPos)) - continue; -#endif - - // Get the dansity/sample value of the current position - const float density = getDensity(currPos); - - // Apply visibility window - if (density < _MinVal || density > _MaxVal) continue; - - // Calculate gradient (needed for lighting and 2D transfer functions) -#if defined(TF2D_ON) || defined(LIGHTING_ON) - float3 gradient = getGradient(currPos); -#endif - - // Apply transfer function -#if TF2D_ON - float mag = length(gradient) / 1.75f; - float4 src = getTF2DColour(density, mag); -#else - float4 src = getTF1DColour(density); -#endif - - // Apply lighting -#if defined(LIGHTING_ON) && defined(DVR_BACKWARD_ON) - src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(ray.direction), ray.direction, 0.3f); -#elif defined(LIGHTING_ON) - src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(-ray.direction), -ray.direction, 0.3f); -#endif - -#ifdef DVR_BACKWARD_ON - col.rgb = src.a * src.rgb + (1.0f - src.a) * col.rgb; - col.a = src.a + (1.0f - src.a) * col.a; - - // Optimisation: A branchless version of: if (src.a > 0.15f) tDepth = t; - tDepth = max(tDepth, t * step(0.15, src.a)); -#else - src.rgb *= src.a; - col = (1.0f - col.a) * src + col; - - if (col.a > 0.15 && t < tDepth) { - tDepth = t; - } -#endif - - // Early ray termination -#if !defined(DVR_BACKWARD_ON) && defined(RAY_TERMINATE_ON) - if (col.a > OPACITY_THRESHOLD) { - break; - } -#endif - } - - // Write fragment output - frag_out output; - output.colour = col; -#if DEPTHWRITE_ON - tDepth += (step(col.a, 0.0) * 1000.0); // Write large depth if no hit - const float3 depthPos = lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f); - output.depth = localToDepth(depthPos); -#endif - return output; - } - - // Maximum Intensity Projection mode - frag_out frag_mip(frag_in i) - { - #define MAX_NUM_STEPS 512 - - RayInfo ray = getRayBack2Front(i.vertexLocal); - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - float maxDensity = 0.0f; - float3 maxDensityPos = ray.startPos; - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - -#ifdef CROSS_SECTION_ON - if (IsCutout(currPos)) - continue; -#endif - - const float density = getDensity(currPos); - if (density > maxDensity && density > _MinVal && density < _MaxVal) - { - maxDensity = density; - maxDensityPos = currPos; - } - } - - // Write fragment output - frag_out output; - output.colour = float4(1.0f, 1.0f, 1.0f, maxDensity); // maximum intensity -#if DEPTHWRITE_ON - output.depth = localToDepth(maxDensityPos - float3(0.5f, 0.5f, 0.5f)); -#endif - return output; - } - - // Surface rendering mode - // Draws the first point (closest to camera) with a density within the user-defined thresholds. - frag_out frag_surf(frag_in i) - { - #define MAX_NUM_STEPS 1024 - - RayInfo ray = getRayFront2Back(i.vertexLocal); - RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); - - // Create a small random offset in order to remove artifacts - ray.startPos = ray.startPos + (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; - - float4 col = float4(0,0,0,0); - for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) - { - const float t = iStep * raymarchInfo.numStepsRecip; - const float3 currPos = lerp(ray.startPos, ray.endPos, t); - -#ifdef CROSS_SECTION_ON - if (IsCutout(currPos)) - continue; -#endif - - const float density = getDensity(currPos); - if (density > _MinVal && density < _MaxVal) - { - float3 normal = normalize(getGradient(currPos)); - col = getTF1DColour(density); - col.rgb = calculateLighting(col.rgb, normal, getLightDirection(-ray.direction), -ray.direction, 0.15); - col.a = 1.0f; - break; - } - } - - // Write fragment output - frag_out output; - output.colour = col; -#if DEPTHWRITE_ON - - const float tDepth = iStep * raymarchInfo.numStepsRecip + (step(col.a, 0.0) * 1000.0); // Write large depth if no hit - output.depth = localToDepth(lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f)); -#endif - return output; - } - - frag_in vert(vert_in v) - { - return vert_main(v); - } - - frag_out frag(frag_in i) - { -#if MODE_DVR - return frag_dvr(i); -#elif MODE_MIP - return frag_mip(i); -#elif MODE_SURF - return frag_surf(i); -#endif - } - - ENDCG - } - } + Properties + { + _DataTex("Data Texture (Generated)", 3D) = "" {} + _GradientTex("Gradient Texture (Generated)", 3D) = "" {} + _NoiseTex("Noise Texture (Generated)", 2D) = "white" {} + _TFTex("Transfer Function Texture (Generated)", 2D) = "" {} + _MinVal("Min val", Range(0.0, 1.0)) = 0.0 + _MaxVal("Max val", Range(0.0, 1.0)) = 1.0 + _ClipDimMin("Clip Dim Min", Vector) = (0.0, 0.0, 0.0, 1.0) + _ClipDimMax("Clip Dim Max", Vector) = (1.0, 1.0, 1.0, 1.0) + } + SubShader + { + Tags { "Queue" = "Transparent" "RenderType" = "Transparent" } + LOD 100 + Cull Front + ZTest LEqual + ZWrite On + Blend SrcAlpha OneMinusSrcAlpha + + Pass + { + CGPROGRAM + #pragma multi_compile MODE_DVR MODE_MIP MODE_SURF + #pragma multi_compile __ TF2D_ON + #pragma multi_compile __ CROSS_SECTION_ON + #pragma multi_compile __ LIGHTING_ON + #pragma multi_compile DEPTHWRITE_ON DEPTHWRITE_OFF + #pragma multi_compile __ DVR_BACKWARD_ON + #pragma multi_compile __ RAY_TERMINATE_ON + #pragma multi_compile __ USE_MAIN_LIGHT + #pragma multi_compile __ CUBIC_INTERPOLATION_ON + #pragma vertex vert + #pragma fragment frag + + #include "UnityCG.cginc" + #include "TricubicSampling.cginc" + + #define AMBIENT_LIGHTING_FACTOR 0.5 + #define JITTER_FACTOR 5.0 + + struct vert_in + { + float4 vertex : POSITION; + float4 normal : NORMAL; + float2 uv : TEXCOORD0; + }; + + struct frag_in + { + float4 vertex : SV_POSITION; + float2 uv : TEXCOORD0; + float3 vertexLocal : TEXCOORD1; + float3 normal : NORMAL; + }; + + struct frag_out + { + float4 colour : SV_TARGET; + #if DEPTHWRITE_ON + float depth : SV_DEPTH; + #endif + }; + + sampler3D _DataTex; + sampler3D _GradientTex; + sampler2D _NoiseTex; + sampler2D _TFTex; + + float _MinVal; + float _MaxVal; + float3 _TextureSize; + + // For clipping in any direction + float4 _ClipDimMin, _ClipDimMax; + + #if CROSS_SECTION_ON + #define CROSS_SECTION_TYPE_PLANE 1 + #define CROSS_SECTION_TYPE_BOX_INCL 2 + #define CROSS_SECTION_TYPE_BOX_EXCL 3 + float4x4 _CrossSectionMatrices[8]; + float _CrossSectionTypes[8]; + int _NumCrossSections; + #endif + + struct RayInfo + { + float3 startPos; + float3 endPos; + float3 direction; + float2 aabbInters; + }; + + struct RaymarchInfo + { + RayInfo ray; + int numSteps; + float numStepsRecip; + float stepSize; + }; + + float3 getViewRayDir(float3 vertexLocal) + { + if (unity_OrthoParams.w == 0) + { + // Perspective + return normalize(ObjSpaceViewDir(float4(vertexLocal, 0.0f))); + } + else + { + // Orthographic + float3 camfwd = mul((float3x3)unity_CameraToWorld, float3(0,0,-1)); + float4 camfwdobjspace = mul(unity_WorldToObject, camfwd); + return normalize(camfwdobjspace); + } + } + + // Find ray intersection points with axis aligned bounding box + float2 intersectAABB(float3 rayOrigin, float3 rayDir, float3 boxMin, float3 boxMax) + { + float3 tMin = (boxMin - rayOrigin) / rayDir; + float3 tMax = (boxMax - rayOrigin) / rayDir; + float3 t1 = min(tMin, tMax); + float3 t2 = max(tMin, tMax); + float tNear = max(max(t1.x, t1.y), t1.z); + float tFar = min(min(t2.x, t2.y), t2.z); + return float2(tNear, tFar); + }; + + // Get a ray for the specified fragment (back-to-front) + RayInfo getRayBack2Front(float3 vertexLocal) + { + RayInfo ray; + ray.direction = getViewRayDir(vertexLocal); + ray.startPos = vertexLocal + float3(0.5f, 0.5f, 0.5f); + // Find intersections with axis aligned boundinng box (the volume) + ray.aabbInters = intersectAABB(ray.startPos, ray.direction, float3(0.0, 0.0, 0.0), float3(1.0f, 1.0f, 1.0)); + + // Check if camera is inside AABB + const float3 farPos = ray.startPos + ray.direction * ray.aabbInters.y - float3(0.5f, 0.5f, 0.5f); + float4 clipPos = UnityObjectToClipPos(float4(farPos, 1.0f)); + ray.aabbInters += min(clipPos.w, 0.0); + + ray.endPos = ray.startPos + ray.direction * ray.aabbInters.y; + return ray; + } + + // Get a ray for the specified fragment (front-to-back) + RayInfo getRayFront2Back(float3 vertexLocal) + { + RayInfo ray = getRayBack2Front(vertexLocal); + ray.direction = -ray.direction; + float3 tmp = ray.startPos; + ray.startPos = ray.endPos; + ray.endPos = tmp; + return ray; + } + + RaymarchInfo initRaymarch(RayInfo ray, int maxNumSteps) + { + RaymarchInfo raymarchInfo; + raymarchInfo.stepSize = 1.732f/*greatest distance in box*/ / maxNumSteps; + raymarchInfo.numSteps = (int)clamp(abs(ray.aabbInters.x - ray.aabbInters.y) / raymarchInfo.stepSize, 1, maxNumSteps); + raymarchInfo.numStepsRecip = 1.0 / raymarchInfo.numSteps; + return raymarchInfo; + } + + // Gets the colour from a 1D Transfer Function (x = density) + float4 getTF1DColour(float density) + { + return tex2Dlod(_TFTex, float4(density, 0.0f, 0.0f, 0.0f)); + } + + // Gets the colour from a 2D Transfer Function (x = density, y = gradient magnitude) + float4 getTF2DColour(float density, float gradientMagnitude) + { + return tex2Dlod(_TFTex, float4(density, gradientMagnitude, 0.0f, 0.0f)); + } + + // Gets the density at the specified position + float getDensity(float3 pos) + { + #if CUBIC_INTERPOLATION_ON + return interpolateTricubicFast(_DataTex, float3(pos.x, pos.y, pos.z), _TextureSize); + #else + return tex3Dlod(_DataTex, float4(pos.x, pos.y, pos.z, 0.0f)); + #endif + } + + // Gets the gradient at the specified position + float3 getGradient(float3 pos) + { + #if CUBIC_INTERPOLATION_ON + return interpolateTricubicFast(_GradientTex, float3(pos.x, pos.y, pos.z), _TextureSize).rgb; + #else + return tex3Dlod(_GradientTex, float4(pos.x, pos.y, pos.z, 0.0f)).rgb; + #endif + } + + // Get the light direction (using main light or view direction, based on setting) + float3 getLightDirection(float3 viewDir) + { + #if defined(USE_MAIN_LIGHT) + return normalize(mul(unity_WorldToObject, _WorldSpaceLightPos0.xyz)); + #else + return viewDir; + #endif + } + + // Performs lighting calculations, and returns a modified colour. + float3 calculateLighting(float3 col, float3 normal, float3 lightDir, float3 eyeDir, float specularIntensity) + { + // Invert normal if facing opposite direction of view direction. + // Optimised version of: if(dot(normal, eyeDir) < 0.0) normal *= -1.0 + normal *= (step(0.0, dot(normal, eyeDir)) * 2.0 - 1.0); + + float ndotl = max(lerp(0.0f, 1.5f, dot(normal, lightDir)), AMBIENT_LIGHTING_FACTOR); + float3 diffuse = ndotl * col; + float3 v = eyeDir; + float3 r = normalize(reflect(-lightDir, normal)); + float rdotv = max(dot(r, v), 0.0); + float3 specular = pow(rdotv, 32.0f) * float3(1.0f, 1.0f, 1.0f) * specularIntensity; + return diffuse + specular; + } + + // Converts local position to depth value + float localToDepth(float3 localPos) + { + float4 clipPos = UnityObjectToClipPos(float4(localPos, 1.0f)); + + #if defined(SHADER_API_GLCORE) || defined(SHADER_API_OPENGL) || defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) + return (clipPos.z / clipPos.w) * 0.5 + 0.5; + #else + return clipPos.z / clipPos.w; + #endif + } + + bool IsCutout(float3 currPos) + { + #if CROSS_SECTION_ON + // Move the reference in the middle of the mesh, like the pivot + float4 pos = float4(currPos - float3(0.5f, 0.5f, 0.5f), 1.0f); + + bool clipped = false; + for (int i = 0; i < _NumCrossSections && !clipped; ++i) + { + const int type = (int)_CrossSectionTypes[i]; + const float4x4 mat = _CrossSectionMatrices[i]; + + // Convert from model space to plane's vector space + float3 planeSpacePos = mul(mat, pos); + if (type == CROSS_SECTION_TYPE_PLANE) + clipped = planeSpacePos.z > 0.0f; + else if (type == CROSS_SECTION_TYPE_BOX_INCL) + clipped = !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); + else if (type == CROSS_SECTION_TYPE_BOX_EXCL) + clipped = planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; + } + return clipped; + /* + #if CUTOUT_PLANE + return planeSpacePos.z > 0.0f; + #elif CUTOUT_BOX_INCL + return !(planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f); + #elif CUTOUT_BOX_EXCL + return planeSpacePos.x >= -0.5f && planeSpacePos.x <= 0.5f && planeSpacePos.y >= -0.5f && planeSpacePos.y <= 0.5f && planeSpacePos.z >= -0.5f && planeSpacePos.z <= 0.5f; + #endif*/ + #else + return false; + #endif + } + + frag_in vert_main(vert_in v) + { + frag_in o; + o.vertex = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + o.vertexLocal = v.vertex; + o.normal = UnityObjectToWorldNormal(v.normal); + return o; + } + + // Direct Volume Rendering + frag_out frag_dvr(frag_in i) + { + #define MAX_NUM_STEPS 512 + #define OPACITY_THRESHOLD (1.0 - 1.0 / 255.0) + + #ifdef DVR_BACKWARD_ON + RayInfo ray = getRayBack2Front(i.vertexLocal); + #else + RayInfo ray = getRayFront2Back(i.vertexLocal); + #endif + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + float3 lightDir = normalize(ObjSpaceViewDir(float4(float3(0.0f, 0.0f, 0.0f), 0.0f))); + + // Create a small random offset in order to remove artifacts + ray.startPos += (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; + + float4 col = float4(0.0f, 0.0f, 0.0f, 0.0f); + #ifdef DVR_BACKWARD_ON + float tDepth = 0.0f; + #else + float tDepth = raymarchInfo.numStepsRecip * (raymarchInfo.numSteps - 1); + #endif + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + + // Perform slice culling (cross section plane) + #ifdef CROSS_SECTION_ON + if (IsCutout(currPos)) + continue; + #endif + + // Get the dansity/sample value of the current position + const float density = getDensity(currPos); + + // Apply visibility window + if (density < _MinVal || density > _MaxVal) continue; + + // cut with clip dims + if (currPos.x < _ClipDimMin.x || currPos.x > _ClipDimMax.x) continue; + if (currPos.y < _ClipDimMin.y || currPos.y > _ClipDimMax.y) continue; + if (currPos.z < _ClipDimMin.z || currPos.z > _ClipDimMax.z) continue; + + // Calculate gradient (needed for lighting and 2D transfer functions) + #if defined(TF2D_ON) || defined(LIGHTING_ON) + float3 gradient = getGradient(currPos); + #endif + + // Apply transfer function + #if TF2D_ON + float mag = length(gradient) / 1.75f; + float4 src = getTF2DColour(density, mag); + #else + float4 src = getTF1DColour(density); + #endif + + // Apply lighting + #if defined(LIGHTING_ON) && defined(DVR_BACKWARD_ON) + src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(ray.direction), ray.direction, 0.3f); + #elif defined(LIGHTING_ON) + src.rgb = calculateLighting(src.rgb, normalize(gradient), getLightDirection(-ray.direction), -ray.direction, 0.3f); + #endif + + #ifdef DVR_BACKWARD_ON + col.rgb = src.a * src.rgb + (1.0f - src.a) * col.rgb; + col.a = src.a + (1.0f - src.a) * col.a; + + // Optimisation: A branchless version of: if (src.a > 0.15f) tDepth = t; + tDepth = max(tDepth, t * step(0.15, src.a)); + #else + src.rgb *= src.a; + col = (1.0f - col.a) * src + col; + + if (col.a > 0.15 && t < tDepth) { + tDepth = t; + } + #endif + + // Early ray termination + #if !defined(DVR_BACKWARD_ON) && defined(RAY_TERMINATE_ON) + if (col.a > OPACITY_THRESHOLD) { + break; + } + #endif + } + + // Write fragment output + frag_out output; + output.colour = col; + #if DEPTHWRITE_ON + tDepth += (step(col.a, 0.0) * 1000.0); // Write large depth if no hit + const float3 depthPos = lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f); + output.depth = localToDepth(depthPos); + #endif + return output; + } + + // Maximum Intensity Projection mode + frag_out frag_mip(frag_in i) + { + #define MAX_NUM_STEPS 512 + + RayInfo ray = getRayBack2Front(i.vertexLocal); + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + float maxDensity = 0.0f; + float3 maxDensityPos = ray.startPos; + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + + #ifdef CROSS_SECTION_ON + if (IsCutout(currPos)) + continue; + #endif + + const float density = getDensity(currPos); + if (density > maxDensity && density > _MinVal && density < _MaxVal) + { + maxDensity = density; + maxDensityPos = currPos; + } + } + + // Write fragment output + frag_out output; + output.colour = float4(1.0f, 1.0f, 1.0f, maxDensity); // maximum intensity + #if DEPTHWRITE_ON + output.depth = localToDepth(maxDensityPos - float3(0.5f, 0.5f, 0.5f)); + #endif + return output; + } + + // Surface rendering mode + // Draws the first point (closest to camera) with a density within the user-defined thresholds. + frag_out frag_surf(frag_in i) + { + #define MAX_NUM_STEPS 1024 + + RayInfo ray = getRayFront2Back(i.vertexLocal); + RaymarchInfo raymarchInfo = initRaymarch(ray, MAX_NUM_STEPS); + + // Create a small random offset in order to remove artifacts + ray.startPos = ray.startPos + (JITTER_FACTOR * ray.direction * raymarchInfo.stepSize) * tex2D(_NoiseTex, float2(i.uv.x, i.uv.y)).r; + + float4 col = float4(0,0,0,0); + for (int iStep = 0; iStep < raymarchInfo.numSteps; iStep++) + { + const float t = iStep * raymarchInfo.numStepsRecip; + const float3 currPos = lerp(ray.startPos, ray.endPos, t); + + #ifdef CROSS_SECTION_ON + if (IsCutout(currPos)) + continue; + #endif + + const float density = getDensity(currPos); + if (density > _MinVal && density < _MaxVal) + { + float3 normal = normalize(getGradient(currPos)); + col = getTF1DColour(density); + col.rgb = calculateLighting(col.rgb, normal, getLightDirection(-ray.direction), -ray.direction, 0.15); + col.a = 1.0f; + break; + } + } + + // Write fragment output + frag_out output; + output.colour = col; + #if DEPTHWRITE_ON + + const float tDepth = iStep * raymarchInfo.numStepsRecip + (step(col.a, 0.0) * 1000.0); // Write large depth if no hit + output.depth = localToDepth(lerp(ray.startPos, ray.endPos, tDepth) - float3(0.5f, 0.5f, 0.5f)); + #endif + return output; + } + + frag_in vert(vert_in v) + { + return vert_main(v); + } + + frag_out frag(frag_in i) + { + #if MODE_DVR + return frag_dvr(i); + #elif MODE_MIP + return frag_mip(i); + #elif MODE_SURF + return frag_surf(i); + #endif + } + + ENDCG + } + } } From 3258f83804f326419a4e0d86dd6f7cea9e4af6fc Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:31:27 -0700 Subject: [PATCH 11/14] Update MaterialFactory.cs Removed shader.find for clip shader, since it's merged with DirectVolumeRenderingShader now --- Assets/Scripts/VolumeObject/MaterialFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Scripts/VolumeObject/MaterialFactory.cs b/Assets/Scripts/VolumeObject/MaterialFactory.cs index a4ae0953..d1242e46 100644 --- a/Assets/Scripts/VolumeObject/MaterialFactory.cs +++ b/Assets/Scripts/VolumeObject/MaterialFactory.cs @@ -6,7 +6,7 @@ public class MaterialFactory { public static Material CreateMaterialDVR(VolumeDataset dataset) { - Shader shader = Shader.Find("VolumeRendering/DirectVolumeRenderingClipShader"); + Shader shader = Shader.Find("VolumeRendering/DirectVolumeRenderingShader"); Material material = new Material(shader); const int noiseDimX = 512; From 90bc95026aab182c13fa9701c829f29a76c81f4b Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:31:56 -0700 Subject: [PATCH 12/14] Removed DirectVolumeRenderingClipMaterial --- .../DirectVolumeRenderingClipMaterial.mat | 98 ------------------- ...DirectVolumeRenderingClipMaterial.mat.meta | 8 -- 2 files changed, 106 deletions(-) delete mode 100644 Assets/Materials/DirectVolumeRenderingClipMaterial.mat delete mode 100644 Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta diff --git a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat deleted file mode 100644 index c50add0c..00000000 --- a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat +++ /dev/null @@ -1,98 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!21 &2100000 -Material: - serializedVersion: 6 - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: DirectVolumeRenderingClipMaterial - m_Shader: {fileID: 4800000, guid: a8ce2343c9eb4ad42970cff15e48cd5f, type: 3} - m_ShaderKeywords: MODE_DVR TF2D_ON _MODE_DVR _MODE_MIP - m_LightmapFlags: 4 - m_EnableInstancingVariants: 0 - m_DoubleSidedGI: 0 - m_CustomRenderQueue: -1 - stringTagMap: {} - disabledShaderPasses: - - pass0 - m_SavedProperties: - serializedVersion: 3 - m_TexEnvs: - - _BumpMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DataTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailAlbedoMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailMask: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _DetailNormalMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _EmissionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _GradientTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MainTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _MetallicGlossMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _NoiseTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _OcclusionMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _ParallaxMap: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - - _TFTex: - m_Texture: {fileID: 0} - m_Scale: {x: 1, y: 1} - m_Offset: {x: 0, y: 0} - m_Floats: - - _BumpScale: 1 - - _Cutoff: 0.5 - - _DetailNormalMapScale: 1 - - _DstBlend: 0 - - _GlossMapScale: 1 - - _Glossiness: 0.5 - - _GlossyReflections: 1 - - _MaxVal: 1 - - _Metallic: 0 - - _MinVal: 0 - - _Mode: 0 - - _OcclusionStrength: 1 - - _Parallax: 0.02 - - _SmoothnessTextureChannel: 0 - - _SpecularHighlights: 1 - - _SrcBlend: 1 - - _UVSec: 0 - - _ZWrite: 1 - m_Colors: - - _ClipDimMax: {r: 1, g: 1, b: 1, a: 1} - - _ClipDimMin: {r: 0, g: 0, b: 0, a: 1} - - _Color: {r: 1, g: 1, b: 1, a: 1} - - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta b/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta deleted file mode 100644 index 47b5c243..00000000 --- a/Assets/Materials/DirectVolumeRenderingClipMaterial.mat.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c4954cbc3bdf4b54fb6fd0ea0c1e9d2b -NativeFormatImporter: - externalObjects: {} - mainObjectFileID: 2100000 - userData: - assetBundleName: - assetBundleVariant: From 694b31117e39ca3b50d501db52374f214d3dd935 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:32:19 -0700 Subject: [PATCH 13/14] Update DirectVolumeRenderingMaterial.mat Changed shader back to DirectVolumeRenderingShader --- Assets/Materials/DirectVolumeRenderingMaterial.mat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Assets/Materials/DirectVolumeRenderingMaterial.mat b/Assets/Materials/DirectVolumeRenderingMaterial.mat index 60319581..85cc7773 100644 --- a/Assets/Materials/DirectVolumeRenderingMaterial.mat +++ b/Assets/Materials/DirectVolumeRenderingMaterial.mat @@ -8,7 +8,7 @@ Material: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_Name: DirectVolumeRenderingMaterial - m_Shader: {fileID: 4800000, guid: a8ce2343c9eb4ad42970cff15e48cd5f, type: 3} + m_Shader: {fileID: 4800000, guid: f9df7f8cb5dda3a48a945ab37d6b0d83, type: 3} m_ShaderKeywords: MODE_DVR TF2D_ON _MODE_DVR _MODE_MIP m_LightmapFlags: 4 m_EnableInstancingVariants: 0 From c784b5b10ac9cc3cae8c4a1b2ecc2eca33bd58f3 Mon Sep 17 00:00:00 2001 From: walterknowthyself <48263101+smallvalthoss@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:34:21 -0700 Subject: [PATCH 14/14] Delete ignore.meta --- Assets/Resources/ignore.meta | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 Assets/Resources/ignore.meta diff --git a/Assets/Resources/ignore.meta b/Assets/Resources/ignore.meta deleted file mode 100644 index 44b10945..00000000 --- a/Assets/Resources/ignore.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3510413e4161f6f49830a4acc5fcd5b3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: