Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by drhenry · Apr 12, 2010 at 02:58 PM · shaderproximity

How to detect in a shader, if two objects are close

Hi,

I'd like to write a shader effect, where a transparent wall "glows" locally when a ball comes near it. By "glow" I mean simply make the transparent wall locally opaque. In my current implementation that wall doesn't glow correctly. In a script attached to the wall I pass the ball position to the wall-shader:

renderer.material.SetVector("_BallPos", Vector4(pinball.transform.position.x, 
 pinball.transform.position.y, pinball.transform.position.z, 1));

So far I've written this shader code:

Shader "PinballShaders/BoundaryGlowShader" { Properties { _Color ("Main Color", Color) = (0.1, 0.3, 0.7, 0.25) _BallPos("Pinball position", Vector) = (0,0,0,1) //Max dist indicates the size of the effect when //pinball comes near the wall _MaxDist("Maximum distance", Float) = 2.0 _MainTex ("Base (RGBA)", 2D) = "white" {} } SubShader { //Blend One One Blend SrcAlpha OneMinusSrcAlpha

     Tags {Queue = Transparent}
     Cull Off

     Pass
     {

CGPROGRAM #pragma vertex vert #pragma fragment frag

include "UnityCG.cginc"

uniform float4 _Color; uniform float4 _BallPos; uniform float _MaxDist; uniform sampler2D _MainTex;

struct v2f { float4 pos : POSITION; float4 color : COLOR0; float4 fragPos : COLOR1; };

v2f vert (appdata_base v) { v2f o; 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; o.color = _Color; return o; }

half4 frag (v2f i) : COLOR { float4 outColor = i.color; float distance = length(_BallPos - i.fragPos.rgba); //the nearer the ball to pixel's 3d coordinate, the more opaque it should be outColor.a = max(1 - distance / _MaxDist, 0.0);

 return outColor;

} ENDCG

     }
 } 
 FallBack "VertexLit"

}

Any idea what's wrong with my code? Isn't fragPos interpolated across the triangle?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Horsman · Apr 12, 2010 at 10:18 PM

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;
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Daniel-Brauer · Apr 13, 2010 at 02:23 AM 1
Share

Of course, fragPos is no longer needed and should be removed from the v2f structure.

avatar image drhenry · Apr 13, 2010 at 07:20 AM 0
Share

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...?

avatar image drhenry · Apr 13, 2010 at 08:25 AM 0
Share

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.

avatar image
1

Answer by drhenry · Apr 13, 2010 at 07:58 AM

Thanks to Horsman. I changed a bit of his code, so that it works fine even for objects of arbitrary triangulation:

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;

}

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).

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image drhenry · May 05, 2010 at 07:29 AM 0
Share

See http://forum.unity3d.com/viewtopic.php?t=49037 for an even better solution. The $$anonymous$$odelView 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.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

1 Person is following this question.

avatar image

Related Questions

Proximity Based Shader? 1 Answer

How to force the compilation of a shader in Unity? 5 Answers

How to Get Nice Thick Toon-Like Outlines On Non-Smooth Geometry? 1 Answer

Creating a particle system that uses 1 draw call 0 Answers

FX/Flare is always on top 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges