表面着色器在增强现实中与平面裁剪存在问题。

huangapple go评论54阅读模式
英文:

Problem with surface shader for clipping with a plane in Augmented Reality

问题

我想在Unity中使用平面剪切一个3D模型,在这个很棒的教程中找到了方法,并且在通常的Unity环境中很容易让它工作。该教程使用一个表面着色器来剪切平面上方的所有部分,并只显示在平面下方的部分,这样你会得到打开3D模型的印象(请参考链接教程中的GIF图)。表面着色器的代码如下:

Shader "Clippingplane" {
	Properties {
		_Color ("Tint", Color) = (0, 0, 0, 1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Smoothness ("Smoothness", Range(0, 1)) = 0
		_Metallic ("Metalness", Range(0, 1)) = 0
		[HDR] _Emission ("Emission", color) = (0,0,0)

        [HDR]_CutoffColor("Cutoff Color", Color) = (1,0,0,0)
	}
	SubShader {
		Tags{ "RenderType"="Opaque" "Queue"="Geometry"}

        // render faces regardless if they point towards the camera or away from it
        Cull Off

		CGPROGRAM

		#pragma surface surf Standard fullforwardshadows
		#pragma target 3.0

		sampler2D _MainTex;
		fixed4 _Color;

		half _Smoothness;
		half _Metallic;
		half3 _Emission;

		float4 _Plane;

		float4 _CutoffColor;

		struct Input {
			float2 uv_MainTex;
            float3 worldPos;
            float facing : VFACE;
		};

		void surf (Input i, inout SurfaceOutputStandard o) {
			//calculate signed distance to plane
            float distance = dot(i.worldPos, _Plane.xyz);
            distance = distance + _Plane.w;
            //discard surface above plane
            clip(-distance);

			float facing = i.facing * 0.5 + 0.5; //convert facing from -1/1 to 0/1 for linear interpolation

            //normal color stuff
            fixed4 col = tex2D(_MainTex, i.uv_MainTex);
            col *= _Color;
            o.Albedo = col.rgb * facing;
            o.Metallic = _Metallic * facing;
            o.Smoothness = _Smoothness * facing;
            o.Emission = lerp(_CutoffColor, _Emission, facing); // lerp = linear interpolation

		}
		ENDCG
	}
	FallBack "Standard"
}

现在我想将整个移动剪切平面的交互转换到**增强现实(AR)**中,我使用ARFoundation和ARCore来实现这一点。

出于某种原因,着色器在AR中的表现不如预期。"内部颜色"(红色)覆盖了整个模型本身,而不仅仅是模型被切开的部分。似乎着色器不能再区分内外部了?剪切部分却可以正常工作。

显示整个3D模型为红色的截图

我尝试了一些方法,但只能使其显示正确的颜色,但剪切部分无法正常工作。特别是facing变量及其转换部分似乎是影响结果的原因之一。我对着色器了解不多,所以想知道有没有人能指导我正确的方向,看看法线等方面发生了什么?

教程中的表面着色器在AR中略有不同,在省略"显示内部部分"时仍然可以正常工作。非常奇怪,着色器在通常的Unity环境中可以正常工作,但在AR中不行。感谢任何帮助!

英文:

I want to clip a 3D model with a plane in Unity, found this great tutorial for it and got it to work easily in the usual Unity environment. The tutorial uses a surface shader to clip all parts above a plane and only show the parts underneath it, so that you get the impression of cutting open a 3D model (see the GIFs in the linked tutorial). Code of the surface shader is this:

Shader "Clippingplane" {
	Properties {
		_Color ("Tint", Color) = (0, 0, 0, 1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Smoothness ("Smoothness", Range(0, 1)) = 0
		_Metallic ("Metalness", Range(0, 1)) = 0
		[HDR] _Emission ("Emission", color) = (0,0,0)

        [HDR]_CutoffColor("Cutoff Color", Color) = (1,0,0,0)
	}
	SubShader {
		Tags{ "RenderType"="Opaque" "Queue"="Geometry"}

        // render faces regardless if they point towards the camera or away from it
        Cull Off

		CGPROGRAM

		#pragma surface surf Standard fullforwardshadows
		#pragma target 3.0

		sampler2D _MainTex;
		fixed4 _Color;

		half _Smoothness;
		half _Metallic;
		half3 _Emission;

		float4 _Plane;

		float4 _CutoffColor;

		struct Input {
			float2 uv_MainTex;
            float3 worldPos;
            float facing : VFACE;
		};

		void surf (Input i, inout SurfaceOutputStandard o) {
			//calculate signed distance to plane
            float distance = dot(i.worldPos, _Plane.xyz);
            distance = distance + _Plane.w;
            //discard surface above plane
            clip(-distance);

			float facing = i.facing * 0.5 + 0.5; //convert facing from -1/1 to 0/1 for linear interpolation

            //normal color stuff
            fixed4 col = tex2D(_MainTex, i.uv_MainTex);
            col *= _Color;
            o.Albedo = col.rgb * facing;
            o.Metallic = _Metallic * facing;
            o.Smoothness = _Smoothness * facing;
            o.Emission = lerp(_CutoffColor, _Emission, facing); // lerp = linear interpolation

		}
		ENDCG
	}
	FallBack "Standard"
}

Now I want to convert this whole interaction of moving a clipping plane through a 3D model to Augmented Reality, I use ARFoundation with ARCore for that.

For some reason, the shader doesn't work in AR as expected now anymore. The "inside color" (red) covers the whole model itself, and not only the part where the model is cut open. Seems like the shader can't differentiate between outside and inside anymore? The clipping part works, however.

Screenshot of the whole 3D model showing in red

I played around a bit, but only got it to work to show the correct colors WITHOUT the clipping part working. Especially the part with the facing variable and its conversion seems like the one messing with the result. I don't really know that much about shaders so I'm wondering if anyone could point me in the right direction what is happening with the normals and stuff?
The surface shader from the tutorial works fine in AR when leaving out the "Show the inside" part.
Super weird, that the shader works in the usual Unity environment and not in AR. Any help appreciated!

答案1

得分: 0

玩弄了一下,我找到了解决办法,可能之前测试的不够充分... 似乎AR已经提供了VFACE,范围从0到1,所以转换它会导致问题。
我简单地移除了转换部分,只留下了:

float facing = i.facing;

看起来这样就可以了!希望对任何尝试在AR中使用表面着色器裁剪物体的人有所帮助。

英文:

Playing around a bit more brought me to my solution, I might not have had tested enough... Seems like AR already provides VFACE in a range from 0 to 1, so converting it made things wrong.
I simply removed the conversion part which left me with only:

float facing = i.facing;

That seems to do the job! Hope this helps anyone trying to clip stuff in AR with a surface shader.

huangapple
  • 本文由 发表于 2023年2月18日 18:50:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75492809.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定