Add optional Front-to-Back DVR + early ray termination
This commit is contained in:
Родитель
20b6a47f1a
Коммит
c5b94a0c01
|
@ -6,6 +6,7 @@ namespace UnityVolumeRendering
|
|||
[CustomEditor(typeof(VolumeRenderedObject))]
|
||||
public class VolumeRenderedObjectCustomInspector : Editor
|
||||
{
|
||||
bool otherSettings = false;
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
VolumeRenderedObject volrendObj = (VolumeRenderedObject)target;
|
||||
|
@ -36,11 +37,29 @@ namespace UnityVolumeRendering
|
|||
// Show TF button
|
||||
if (GUILayout.Button("Edit transfer function"))
|
||||
{
|
||||
if(tfMode == TFRenderMode.TF1D)
|
||||
if (tfMode == TFRenderMode.TF1D)
|
||||
TransferFunctionEditorWindow.ShowWindow();
|
||||
else
|
||||
TransferFunction2DEditorWindow.ShowWindow();
|
||||
}
|
||||
|
||||
// Other settings for direct volume rendering
|
||||
if (volrendObj.GetRenderMode() == RenderMode.DirectVolumeRendering)
|
||||
{
|
||||
GUILayout.Space(10);
|
||||
otherSettings = EditorGUILayout.Foldout(otherSettings, "Other Settings");
|
||||
if (otherSettings)
|
||||
{
|
||||
// Temporary back-to-front rendering option
|
||||
volrendObj.SetDVRBackwardEnabled(GUILayout.Toggle(volrendObj.GetDVRBackwardEnabled(), "Enable Back-to-Front Direct Volume Rendering"));
|
||||
|
||||
// Early ray termination for Front-to-back DVR
|
||||
if (!volrendObj.GetDVRBackwardEnabled())
|
||||
{
|
||||
volrendObj.SetRayTerminationEnabled(GUILayout.Toggle(volrendObj.GetRayTerminationEnabled(), "Enable early ray termination"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ namespace UnityVolumeRendering
|
|||
|
||||
private Vector2 visibilityWindow = new Vector2(0.0f, 1.0f);
|
||||
|
||||
private bool rayTerminationEnabled = true;
|
||||
private bool dvrBackward = true;
|
||||
|
||||
public SlicingPlane CreateSlicingPlane()
|
||||
{
|
||||
GameObject sliceRenderingPlane = GameObject.Instantiate(Resources.Load<GameObject>("SlicingPlane"));
|
||||
|
@ -43,12 +46,12 @@ namespace UnityVolumeRendering
|
|||
|
||||
public void SetRenderMode(RenderMode mode)
|
||||
{
|
||||
if(renderMode != mode)
|
||||
if (renderMode != mode)
|
||||
{
|
||||
renderMode = mode;
|
||||
SetVisibilityWindow(0.0f, 1.0f); // reset visibility window
|
||||
}
|
||||
UpdateMaaterialProperties();
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
|
||||
public void SetTransferFunctionMode(TFRenderMode mode)
|
||||
|
@ -56,9 +59,9 @@ namespace UnityVolumeRendering
|
|||
tfRenderMode = mode;
|
||||
if (tfRenderMode == TFRenderMode.TF1D && transferFunction != null)
|
||||
transferFunction.GenerateTexture();
|
||||
else if(transferFunction2D != null)
|
||||
else if (transferFunction2D != null)
|
||||
transferFunction2D.GenerateTexture();
|
||||
UpdateMaaterialProperties();
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
|
||||
public TFRenderMode GetTransferFunctionMode()
|
||||
|
@ -81,7 +84,7 @@ namespace UnityVolumeRendering
|
|||
if (enable != lightingEnabled)
|
||||
{
|
||||
lightingEnabled = enable;
|
||||
UpdateMaaterialProperties();
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +98,7 @@ namespace UnityVolumeRendering
|
|||
if (window != visibilityWindow)
|
||||
{
|
||||
visibilityWindow = window;
|
||||
UpdateMaaterialProperties();
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,12 +107,40 @@ namespace UnityVolumeRendering
|
|||
return visibilityWindow;
|
||||
}
|
||||
|
||||
private void UpdateMaaterialProperties()
|
||||
public bool GetRayTerminationEnabled()
|
||||
{
|
||||
return rayTerminationEnabled;
|
||||
}
|
||||
|
||||
public void SetRayTerminationEnabled(bool enable)
|
||||
{
|
||||
if (enable != rayTerminationEnabled)
|
||||
{
|
||||
rayTerminationEnabled = enable;
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetDVRBackwardEnabled()
|
||||
{
|
||||
return dvrBackward;
|
||||
}
|
||||
|
||||
public void SetDVRBackwardEnabled(bool enable)
|
||||
{
|
||||
if (enable != dvrBackward)
|
||||
{
|
||||
dvrBackward = enable;
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMaterialProperties()
|
||||
{
|
||||
bool useGradientTexture = tfRenderMode == TFRenderMode.TF2D || renderMode == RenderMode.IsosurfaceRendering || lightingEnabled;
|
||||
meshRenderer.sharedMaterial.SetTexture("_GradientTex", useGradientTexture ? dataset.GetGradientTexture() : null);
|
||||
|
||||
if(tfRenderMode == TFRenderMode.TF2D)
|
||||
if (tfRenderMode == TFRenderMode.TF2D)
|
||||
{
|
||||
meshRenderer.sharedMaterial.SetTexture("_TFTex", transferFunction2D.GetTexture());
|
||||
meshRenderer.sharedMaterial.EnableKeyword("TF2D_ON");
|
||||
|
@ -120,7 +151,7 @@ namespace UnityVolumeRendering
|
|||
meshRenderer.sharedMaterial.DisableKeyword("TF2D_ON");
|
||||
}
|
||||
|
||||
if(lightingEnabled)
|
||||
if (lightingEnabled)
|
||||
meshRenderer.sharedMaterial.EnableKeyword("LIGHTING_ON");
|
||||
else
|
||||
meshRenderer.sharedMaterial.DisableKeyword("LIGHTING_ON");
|
||||
|
@ -152,11 +183,29 @@ namespace UnityVolumeRendering
|
|||
|
||||
meshRenderer.sharedMaterial.SetFloat("_MinVal", visibilityWindow.x);
|
||||
meshRenderer.sharedMaterial.SetFloat("_MaxVal", visibilityWindow.y);
|
||||
|
||||
if (rayTerminationEnabled)
|
||||
{
|
||||
meshRenderer.sharedMaterial.EnableKeyword("RAY_TERMINATE_ON");
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.sharedMaterial.DisableKeyword("RAY_TERMINATE_ON");
|
||||
}
|
||||
|
||||
if (dvrBackward)
|
||||
{
|
||||
meshRenderer.sharedMaterial.EnableKeyword("DVR_BACKWARD_ON");
|
||||
}
|
||||
else
|
||||
{
|
||||
meshRenderer.sharedMaterial.DisableKeyword("DVR_BACKWARD_ON");
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
UpdateMaaterialProperties();
|
||||
UpdateMaterialProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#pragma multi_compile __ CUTOUT_PLANE CUTOUT_BOX_INCL CUTOUT_BOX_EXCL
|
||||
#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 vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
|
@ -233,8 +235,13 @@
|
|||
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)));
|
||||
|
@ -243,7 +250,11 @@
|
|||
ray.startPos += (2.0f * 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);
|
||||
float tDepth = 0.0;
|
||||
#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;
|
||||
|
@ -275,16 +286,33 @@
|
|||
#endif
|
||||
|
||||
// Apply lighting
|
||||
#ifdef LIGHTING_ON
|
||||
#if defined(LIGHTING_ON) && defined(DVR_BACKWARD_ON)
|
||||
src.rgb = calculateLighting(src.rgb, normalize(gradient), lightDir, ray.direction, 0.3f);
|
||||
#elif defined(LIGHTING_ON)
|
||||
src.rgb = calculateLighting(src.rgb, normalize(gradient), lightDir, -ray.direction, 0.3f);
|
||||
#endif
|
||||
|
||||
|
||||
col.rgb = src.a * src.rgb + (1.0f - src.a)*col.rgb;
|
||||
col.a = src.a + (1.0f - src.a)*col.a;
|
||||
#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 (src.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
|
||||
|
|
Загрузка…
Ссылка в новой задаче