wore321

Unity3D 에서 스파인 오브젝트가 스파인 모션에 의해 모든 파츠들의 opacity 가 255 -> 0 으로 감소할 때

파츠끼리 겹치는 부분이 덧그려지는걸 방지하기위해

Spine-Skeleton.shader 에서 Cull Back, ZWrite On 으로 모두 수정했지만 별 효과가 없는것 같습니다

예시.png


기본 Spine-Skeleton.shader 에서 코드를 수정하여 덧그려지는 문제를 방지할 방법이 있을까요?

--- 아래는 수정한 Spine-Skeleton.shader 코드 전체 입니다 ---

Shader "Spine/Skeleton" {
Properties {
_Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
[NoScaleOffset] _MainTex ("Main Texture", 2D) = "black" {}
}

SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane"}

Fog { Mode Off }
Cull Back
ZWrite On
Blend One OneMinusSrcAlpha
Lighting Off

Pass {
Fog { Mode Off }
ColorMaterial AmbientAndDiffuse
SetTexture [_MainTex] {
Combine texture * primary
}
}

Pass {
Name "Caster"
Tags { "LightMode"="ShadowCaster" }
Offset 1, 1
ZWrite On
ZTest LEqual

Fog { Mode Off }
Cull Back
Lighting Off

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed _Cutoff;

struct v2f {
V2F_SHADOW_CASTER;
float2 uv : TEXCOORD1;
};

v2f vert (appdata_base v) {
v2f o;
TRANSFER_SHADOW_CASTER(o)
o.uv = v.texcoord;
return o;
}

float4 frag (v2f i) : COLOR {
fixed4 texcol = tex2D(_MainTex, i.uv);
clip(texcol.a - _Cutoff);
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}

SubShader {
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

Cull Back
ZWrite On
Blend One OneMinusSrcAlpha
Lighting Off

Pass {
ColorMaterial AmbientAndDiffuse
SetTexture [_MainTex] {
Combine texture * primary DOUBLE, texture * primary
}
}
}
}
이 게시글에 첨부된 파일을 보기위한 권한을 요청할 수 없습니다.
사용자 아바타
wore321
  • 전체글: 6

Harald

이 작업을 원할 경우 다음을 확인해야합니다.
If you want to make this work, you have to ensure the following:

1) 메시 내부의 순서 정렬 그리기가 앞뒤로 변경되어야합니다 (Spine은 투명도를 올바르게 처리하기 위해 앞뒤 순서를 사용합니다)
2) ZWrite를 활성화해야합니다.
3) ZTest를 활성화해야합니다.
4) 알파 테스트는 매우 적극적으로 폐기해야하며 1.0 이하의 모든 불투명도는 잘립니다. 그렇지 않으면 이상한 테두리 윤곽 효과가 나타납니다.

1) Draw order sorting inside the mesh needs to be changed to front-to-back (Spine uses back-to-front order to handle transparency correctly)
2) ZWrite needs to be enabled
3) ZTest needs to be enabled
4) Alpha Test needs to discard very agressively, everything below 1.0 opacity should be clipped. Otherwise you would receive strange border outline effects.

컬 모드를`컬백 (Cull Back) '으로 설정하여 달성하고자하는 것을 이해하지 못합니다.
I do not quite understand what you wanted to achieve by setting cull mode to Cull Back.

---

하나의 대안은 RenderTexture를 사용하는 것입니다 : https://docs.unity3d.com/Manual/class-RenderTexture.html.
One alternative would be to use a RenderTexture: https://docs.unity3d.com/Manual/class-RenderTexture.html.

RenderTexture를 100 % 불투명도로 렌더링하고 투명도를 적용하지 않고 RenderTexture를 원하는 불투명도로 오버레이하여 RenderTexture를 간단한 투명한 재질로 적용한 간단한 쿼드를 통해 렌더링 할 수 있습니다 (50 % 투명한). 이것은 귀하의 경우에 가장 빠르고 쉬운 해결책이 될 것입니다.

You could render the character to the RenderTexture at 100% opacity (so without the transparency applied yet) and then overlay the RenderTexture to your scene at the desired opacity via a simple quad with the RenderTexture applied at a simple transparent material (lets say 50% transparent). This would be the quickest and easiest solution in your case.

앞으로는 일반적인 페이드 아웃 시나리오를 보여주기 위해 예제 장면을 제공 할 계획입니다.

We are planning to provide an example scene in the future to show common fade-out scenarios.
사용자 아바타
Harald

Harri
  • 전체글: 1727

wore321

정성스러운 답변에 감사합니다!

지속적으로 위 현상을 해결하기 위해 노력하고있고 연구중입니다.
(RenderTexture 사용은 unity camera 를 1개만 사용해야하는 제약조건이 있기에 그 방법은 사용이 불가능 할 것 같습니다..)

다시한번 도움을 주셔서 감사합니다!.
사용자 아바타
wore321
  • 전체글: 6

Harald

친절한 단어를 가져 주셔서 대단히 감사합니다!
Thank you very much for the kind words!

문제에 대한 다른 해결책을 제공하는대로 알려 드리겠습니다.
We will let you know as soon as we can provide another solution for the problem.
사용자 아바타
Harald

Harri
  • 전체글: 1727

titidatiti

Harald 작성:이 작업을 원할 경우 다음을 확인해야합니다.
If you want to make this work, you have to ensure the following:

1) 메시 내부의 순서 정렬 그리기가 앞뒤로 변경되어야합니다 (Spine은 투명도를 올바르게 처리하기 위해 앞뒤 순서를 사용합니다)
2) ZWrite를 활성화해야합니다.
3) ZTest를 활성화해야합니다.
4) 알파 테스트는 매우 적극적으로 폐기해야하며 1.0 이하의 모든 불투명도는 잘립니다. 그렇지 않으면 이상한 테두리 윤곽 효과가 나타납니다.

1) Draw order sorting inside the mesh needs to be changed to front-to-back (Spine uses back-to-front order to handle transparency correctly)
2) ZWrite needs to be enabled
3) ZTest needs to be enabled
4) Alpha Test needs to discard very agressively, everything below 1.0 opacity should be clipped. Otherwise you would receive strange border outline effects.

컬 모드를`컬백 (Cull Back) '으로 설정하여 달성하고자하는 것을 이해하지 못합니다.
I do not quite understand what you wanted to achieve by setting cull mode to Cull Back.

---

하나의 대안은 RenderTexture를 사용하는 것입니다 : https://docs.unity3d.com/Manual/class-RenderTexture.html.
One alternative would be to use a RenderTexture: https://docs.unity3d.com/Manual/class-RenderTexture.html.

RenderTexture를 100 % 불투명도로 렌더링하고 투명도를 적용하지 않고 RenderTexture를 원하는 불투명도로 오버레이하여 RenderTexture를 간단한 투명한 재질로 적용한 간단한 쿼드를 통해 렌더링 할 수 있습니다 (50 % 투명한). 이것은 귀하의 경우에 가장 빠르고 쉬운 해결책이 될 것입니다.

You could render the character to the RenderTexture at 100% opacity (so without the transparency applied yet) and then overlay the RenderTexture to your scene at the desired opacity via a simple quad with the RenderTexture applied at a simple transparent material (lets say 50% transparent). This would be the quickest and easiest solution in your case.

앞으로는 일반적인 페이드 아웃 시나리오를 보여주기 위해 예제 장면을 제공 할 계획입니다.

We are planning to provide an example scene in the future to show common fade-out scenarios.
Is there any updates on the subject now?
I meet the same problem when creating a fake shadow for the spine character. I used a camera to render the shadow to a render texture, but found it difficult to place the render texture to the position of the spine character. :tear:
사용자 아바타
titidatiti
  • 전체글: 24

Harald

I'm sorry to say that unfortunately we did not get to this task yet.

Do you have any special requirements that you need your shadow to look like? Please note that there are more efficient ways to create shadows than using the render texture based approach above. You could use any shader with zwrite (depth write) enabled and have the alpha threshold set accordingly.
사용자 아바타
Harald

Harri
  • 전체글: 1727

titidatiti

Harald 작성:I'm sorry to say that unfortunately we did not get to this task yet.

Do you have any special requirements that you need your shadow to look like? Please note that there are more efficient ways to create shadows than using the render texture based approach above. You could use any shader with zwrite (depth write) enabled and have the alpha threshold set accordingly.
Thank you for your reply!
I'm new to shader, and I'm creating fake shadow in a platform game which actually does not have real ground.
Now I'm trying something like this:
1. Set the original spine character's z-spacing to -0.0001
2. Copy the mesh filter to the shader in LateUpdate
3. Use a z-write and z-test shader on shadow
4. Clip transparency and set color to black where the pixel is not transparent

Then I get something like this:
shadow2.jpg

The texture has outer glow so they are are treated as bigger pieces with transparent border.With the Z-Test on, the transparent part is preventing the pieces behind it to get rendered.
If I set the transparent cutoff to 0, I get something like this:
shadow1.jpg


Is there any solution to achieve something like:
1. Get the whole spine result
2. Then use transparent cutoff to the whole texture

Many thanks!
이 게시글에 첨부된 파일을 보기위한 권한을 요청할 수 없습니다.
사용자 아바타
titidatiti
  • 전체글: 24

Harald

Sorry, I forgot to mention a few things: you should set:
ZWrite On
ZTest Less
And also enable alpha cutoff by adding the following line (which discards pixels when alpha test fails), this seems to be missing in your shader above:
clip(yourTexture.a - _Cutoff);
With this combination, you should set Z-Spacing to 0 to make sure that everything is rendered at the same depth.

I have just written a shader that does all this for you (and anyone who is interested), please find it attached below.
Using this shader you can set the Color to a transparent black color and set Color Overlay to 1 to get the desired transparent shadow effect. Note that when Color Overlay is less than 1, it will be visible that draw order is actually inverted for this ZTest setup.

After some testing, this shader will most likely be added to the official spine-unity packages. Then later, we could potentially add a Reverse Draw Order parameter at SkeletonRenderer to also draw everything in the correct order without any color overlay.
이 게시글에 첨부된 파일을 보기위한 권한을 요청할 수 없습니다.
사용자 아바타
Harald

Harri
  • 전체글: 1727

titidatiti

Harald 작성:Sorry, I forgot to mention a few things: you should set:
ZWrite On
ZTest Less
And also enable alpha cutoff by adding the following line (which discards pixels when alpha test fails), this seems to be missing in your shader above:
clip(yourTexture.a - _Cutoff);
With this combination, you should set Z-Spacing to 0 to make sure that everything is rendered at the same depth.

I have just written a shader that does all this for you (and anyone who is interested), please find it attached below.
Using this shader you can set the Color to a transparent black color and set Color Overlay to 1 to get the desired transparent shadow effect. Note that when Color Overlay is less than 1, it will be visible that draw order is actually inverted for this ZTest setup.

After some testing, this shader will most likely be added to the official spine-unity packages. Then later, we could potentially add a Reverse Draw Order parameter at SkeletonRenderer to also draw everything in the correct order without any color overlay.
Thank you so much! I love Spine not only for it's a wonderful software, but also for such a responsible team!
After comparing you shader code with mine, I found out I've made a mistake of using
c.a = step(_CutOff, c.a);
instead of
clip(baseColor.a - _Cutoff);
which causes the alpha pixels are not really being clipped! :lol:
Now it's working perfectly after setting the _Cutoff value to almost 1! :nerd:

I still have a question about the 'Z-Spacing'. In my understanding, the 'Z-Spacing' makes the pieces of the spine to separate from each other in Z-Axis to get a correct render order.

However, when I set the 'Z-Spacing' to zero, the render order of shadow seems to get messed up:
shadow_of_z_9.gif

If I set the value to -0.00001, the problem still occurs with a small probability:
shaodow_ofz.gif

The problem is gone when I set the 'Z-Spacing' to very small value like -0.001.

Is this problem occurs because I'm using a perspective main camera? I've set the camera transparency sort axis to z-axis in my project, but the problem still occurs:
QQ截图20200214172326.jpg


I just want to get an expert reply from you! It's not a big problem for setting the 'Z-Spacing' to -0.001 does not mess up anything. :D

Many thanks!
이 게시글에 첨부된 파일을 보기위한 권한을 요청할 수 없습니다.
사용자 아바타
titidatiti
  • 전체글: 24

Harald

Thanks so much for your kind words! :)

I would assume that you are using ZTest LEqual instead of ZTest Less, right?

When it is set to LEqual, you will receive undesired overdraw (double-shadowing) at equal depth, so when there is no Z-Spacing, it will all be at the same depth (= all overlapping shadow areas are incorrectly accepted). When set to a very small value like -0.00001, you have a chance that numerical rounding errors will put two elements on the same depth. Finding a value that is causing no visual problems like -0.001 will always be in the precision range where there is enough numerical precision available so that no two different elements will end up at the same depth.

Note that precision will depend on Z distance between the camera near plane and the rendered element (the vertex position), and also on the distance between near and far plane. So the same Z-Spacing value may be sufficient when the element is very close, but could lead to precision problems when far away. Just keep this in mind so you don't wonder why things suddenly look wrong when placed further back in a scene.

The precise solutions would be the Reverse Draw Order option with Z-Spacing < 0 which is yet to be implemented, or using ZTest Less and Z-Spacing = 0.
사용자 아바타
Harald

Harri
  • 전체글: 1727

titidatiti

Harald 작성:Thanks so much for your kind words! :)

I would assume that you are using ZTest LEqual instead of ZTest Less, right?

When it is set to LEqual, you will receive undesired overdraw (double-shadowing) at equal depth, so when there is no Z-Spacing, it will all be at the same depth (= all overlapping shadow areas are incorrectly accepted). When set to a very small value like -0.00001, you have a chance that numerical rounding errors will put two elements on the same depth. Finding a value that is causing no visual problems like -0.001 will always be in the precision range where there is enough numerical precision available so that no two different elements will end up at the same depth.

Note that precision will depend on Z distance between the camera near plane and the rendered element (the vertex position), and also on the distance between near and far plane. So the same Z-Spacing value may be sufficient when the element is very close, but could lead to precision problems when far away. Just keep this in mind so you don't wonder why things suddenly look wrong when placed further back in a scene.

The precise solutions would be the Reverse Draw Order option with Z-Spacing < 0 which is yet to be implemented, or using ZTest Less and Z-Spacing = 0.
Thank you for reply! I'm sorry for replying late.
The ZTest is set to less actually.
When I rotate the fake shadow to (0,0,0), the overdraw does not occur:
QQ截图20200226141026.jpg

When the rotationX is not zero, the overdraw occurs:
QQ截图20200226142312.png

According to your explanation, the overdraw should appear because the pieces are not at the same depth when rotated. Maybe I should use scaleY instead rotationX to achieve a similar result when the Z-Spacing is set to 0.
Thank you! :D
이 게시글에 첨부된 파일을 보기위한 권한을 요청할 수 없습니다.
사용자 아바타
titidatiti
  • 전체글: 24

Harald

Hm, rotation by 180 degrees is indeed problematic, didn't think of that.
And yes, your solution of using scaleX would be the proper solution, just be sure to set scale to scaleX = cos(angle), this should do the trick. :)
사용자 아바타
Harald

Harri
  • 전체글: 1727


다시 돌아감: 한국어 Spine 사용자