Comments and answers for "How to detect in a shader, if two objects are close"
http://answers.unity.com/questions/14931/how-to-detect-in-a-shader-if-two-objects-are-close.html
The latest comments and answers for the question "How to detect in a shader, if two objects are close"Comment by drhenry on drhenry's answer
http://answers.unity.com/comments/71812/view.html
See http://forum.unity3d.com/viewtopic.php?t=49037 for an even better solution. The ModelView matrix multiplications in the vertex shader can be omitted, if _BallPos is in the local coordinate system of the wall. Then even ballPos in the v2f struct can be omitted.Wed, 05 May 2010 07:29:35 GMTdrhenryComment by drhenry on drhenry's answer
http://answers.unity.com/comments/70262/view.html
BTW: converting the ball position into the local coordinate system of the wall did the trick for me (see Horsman's code above).
I made mainly two mistakes in my code:
1) I thought I should pass global coordinates to the shader (thus I had the coordinates of the vertex and the ball in separate coordinates systems)
2) fragPos and ball position must be multiplied by the modelview matrix (not the model view PROJECTION matrix), if you do distance calculation in the fragment shader.Tue, 13 Apr 2010 08:25:32 GMTdrhenryAnswer by drhenry
http://answers.unity.com/answers/14992/view.html
<p>Thanks to Horsman. I changed a bit of his code, so that it works fine even for objects of arbitrary triangulation:</p>
<pre><code>struct v2f {
float4 pos : POSITION;
float4 color : COLOR0;
//position of the wall fragment in eye coordinates
float4 fragPos : TEXCOORD1;
//position of the pinball in eye coordinates
float4 ballPos : TEXCOORD2;
};
v2f vert (appdata_base v)
{
v2f o;
o.color = _Color;
o.pos = mul (glstate.matrix.mvp, v.vertex);
o.fragPos = mul (glstate.matrix.modelview[0], v.vertex);
o.ballPos = mul (glstate.matrix.modelview[0], _BallPos);
return o;
}
half4 frag (v2f i) : COLOR
{
float4 outColor = i.color;
// Check distance here.
float dist = distance(i.ballPos, i.fragPos);
float safety = step(0.001 , _MaxDist);
outColor.a = safety * (1 - clamp(dist, 0, _MaxDist)/_MaxDist);
return outColor;
}
</code></pre>
<p>Performance would be better, if the ball position in eye coordinates would not be computed in the vertex shader (=matrix multiplication for each vertex) but in a Unity script (=only one matrix multiplication).</p>Tue, 13 Apr 2010 07:58:01 GMTdrhenryComment by drhenry on drhenry's answer
http://answers.unity.com/comments/70258/view.html
Thanks a lot for your suggestion, which works pretty fine for well tesselated objects.
But in my case I have a quite big wall consisting of only two triangles.
If I calculate the distance in the vertex shader and the ball hits the wall in the middle, vertices are too far away so the wall doesn't get opaque at the hitpoint. That was the reason why I wanted to compute the distance in the fragment shader. I thought I had to get everything into eye coordinates...?Tue, 13 Apr 2010 07:20:02 GMTdrhenryComment by Daniel-Brauer on Daniel-Brauer's answer
http://answers.unity.com/comments/70253/view.html
Of course, fragPos is no longer needed and should be removed from the v2f structure.Tue, 13 Apr 2010 02:23:21 GMTDaniel-BrauerAnswer by Horsman
http://answers.unity.com/answers/14958/view.html
Looks like your checking the distance in the pixel shader, after coordinates have already been transformed into eye / screen space.
You need to convert the point into the wall's local co-ordinate system, and then do the distance calculation in the vertext shader instead.
Convert the position of the ball into local space before sending to the shader:
Vector4 localPoint = transform.InverseTransformPoint(pinball.transform.position);
localPoint.Scale(transform.localScale);
localPoint.w = 1;
renderer.material.SetVector("_BallPos", localPoint);
And the shader changes:
v2f vert (appdata_base v)
{
v2f o;
// Check distance here.
float dist = distance(_BallPos, v.vertex);
float safety = step(0.001 , maxDistance);
o.color = _Color;
o.color.a = safety * (1 - clamp(dist, 0, maxDistance)/maxDistance);
o.pos = mul (glstate.matrix.mvp, v.vertex);
//Store the fragment position relative to eye coordinate system.
//Is this interpolated between vertex and fragment shader?
o.fragPos = o.pos;
return o;
}
half4 frag (v2f i) : COLOR
{
float4 outColor = i.color;
return outColor;
}Mon, 12 Apr 2010 22:18:03 GMTHorsman