3 ways to draw 3d lines in unity3d

本文介绍了在Unity3D中绘制3D线条的三种不同解决方案:使用LineRenderer组件,通过Graphics类创建网格,以及直接使用GL进行绘制。LineRenderer适合静态线,而GL方法在性能上更优但控制度较低。对于动态和大规模线的绘制,Graphics方案在Unity3D Pro中是更好的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Just as I was thinking about an interesting demo to play withdrawing functions in Unity3D,Mrdoob publishedhis Harmony drawingtool made with HTML5/Canvas. It looks really cool, so I though howabout doing this in 3D? I only had to figure out how to drawlines.

I did some research and below Ipresent 3 different solutions. Youcan grab the source of the examples discussedbelow here.

Drawing lines with LineRenderer [demo]

When it comes to lines, the first thing you'll bump into in theUnity3D API is the LineRenderercomponent. As the name suggests, it is used to drawlines so it seems the right tool for the job. Lines in this caseare defined by 2 or more points (segments), a material and awidth.

It has an important limitation: the line must be continuous.So if you need two lines, you need two renderers. The other problemis that the Line Renderer acts very strangely when new points areadded dynamically. The width of the line does not seem to rendercorrectly. It's either buggy or just wasn't designed for suchuse. Because of these limitations I had to create aseparate Line Renderer for each tiny bit of line I'm drawing.

It was easy to implement, but not very fast since I end up spawninglots of GameObjects each with a LineRenderer attached. It seems tobe the only option if you don't have Unity3DProthough.

Drawing lines as a meshusing Graphics [demo]

The Graphics classallows to draw a mesh directly without the overhead of creatinggame objects and components to hold it.It runsmuch faster than Line Renderer, but you need to create thelines yourself. This is a bit more difficult but also gives youtotal control of the lines - their color, material, width andorientation.

Since meshes are composed of surfaces rather than lines or points,in 3D space a line is best rendered as a very thin quad. A quad isdescribed with 4 vertices, and usually you'll only have the startand end points and a width. Based on this data you can compute aline like this:

C#:
  1. Vector3 normal = Vector3. Cross (start,end );
  2. Vector3 side = Vector3. Cross (normal,end-start );
  3. side. Normalize ( );
  4. Vector3 a = start + side *  (lineWidth/  2 );
  5. Vector3 b = start + side *  (lineWidth/ - 2 );
  6. Vector3 c = end + side *  (lineWidth/  2 );
  7. Vector3 d = end + side *  (lineWidth/ - 2 );

 

First, you get the normal of the plane on which both start and endvectors lie. This will be the plane on which the line-quad willlocated. The cross product of the normal and of the differencebetween end and start vectors gives you the side vector (the "thin"side of the quad). You need to normalize it to make it a unitvector. Finally calculate all 4 points of the rectangle by addingthe side vector multiplied by half width to both start and endpoints in both directions. In the sourcecode all this happensin MakeQuad and AddLine methods,so take a look in there.

It wasn't easy to implement, but once I was there it runs prettyfast.

Direct drawing withGL [demo]

No fast is fastenough! Instead of leaving this topic andlive happily with the Graphics solution, I kept searching forsomething even better. And I found the GLclass. GL is used to "issue rendering commands similar toOpenGL's immediate mode". This sounds like fast, doesn't it? Itis!

Being much easier to implement that the Graphics solution it isa clearwinner for me, the only drawback beingthat you don't have much control over theappearance of the lines. You can't set a width andperspective does not apply (i.e. lines that are far behind lookexactly the same as those that are close to the camera).

Conclusion

For massive & dynamic line drawing LineRenderer is not the bestsolution, but it is the only one available in Unity free version.It can surely be useful to draw limited amounts of static lines andthis is probably what it was made for. If you do have Unity3D Pro,the solution with Graphics is reasonable and very flexible but ifit is performance you're after choose GL.


注:

1、linerender:

 

  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class Script1 MonoBehaviour  
  5.     //LineRenderer  
  6.     private LineRenderer lineRenderer;  
  7.     //定义一个Vector3,用来存储鼠标点击的位置  
  8.     private Vector3 position;  
  9.     //用来索引端点  
  10.     private int index 0;  
  11.     //端点数  
  12.     private int LengthOfLineRenderer=0;  
  13.   
  14.     void Start()  
  15.      
  16.         //添加LineRenderer组件  
  17.         lineRenderer gameObject.AddComponent();  
  18.         //设置材质  
  19.         lineRenderer.material new Material(Shader.Find("Particles/Additive"));  
  20.         //设置颜色  
  21.         lineRenderer.SetColors(Color.red, Color.yellow);  
  22.         //设置宽度  
  23.         lineRenderer.SetWidth(0.02f, 0.02f);  
  24.           
  25.      
  26.   
  27.     void Update()  
  28.        
  29.         //获取LineRenderer组件  
  30.         lineRenderer GetComponent();  
  31.        //鼠标左击  
  32.         if (Input.GetMouseButtonDown(0))  
  33.          
  34.             //将鼠标点击的屏幕坐标转换为世界坐标,然后存储到position中  
  35.             position Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,1.0f));   
  36.             //端点数+1  
  37.             LengthOfLineRenderer++;  
  38.             //设置线段的端点数  
  39.             lineRenderer.SetVertexCount(LengthOfLineRenderer);  
  40.               
  41.          
  42.         //连续绘制线段  
  43.         while (index LengthOfLineRenderer)  
  44.             
  45.             //两点确定一条直线,所以我们依次绘制点就可以形成线段了  
  46.             lineRenderer.SetPosition(index, position);  
  47.             index++;  
  48.           
  49.          
  50.   
  51.      
  52.   
  53.     void OnGUI()  
  54.                
  55.         GUILayout.Label("当前鼠标X轴位置:" Input.mousePosition.x);  
  56.         GUILayout.Label("当前鼠标Y轴位置:" Input.mousePosition.y);          
  57.      
  58.       
  59.       
  60. }  


2、GL
There are two things:

1. GL immediate drawing functions use whatever is the "currentmaterial" set up right now. The material controls how the renderingis done (blending, textures, etc.) So unless you explicitly set itto something before using GL draw functions, the material canhappen to be anything. Also, if you call any other drawing commandsfrom inside GL drawing code, they can set material to somethingelse, so it's not good to mix them.

2. GL drawing commands execute immediately. That means if you callthem in Start(), they will be executed just once. If you call themin Update(), they will be executed before camera is rendered (andthe camera will most likely clear the screen, making the GL drawingnot visible). So the usual place to call GL drawing is most oftenin OnPostRender from a script that is attached to acamera.

Here's a small example, attach it to a camera:
Code:  
 
  
  1. static varlineMaterial : Material;
  2.  
  3. static functionCreateLineMaterial ( )
  4. {
  5.     if (!lineMaterial ) {
  6.         lineMaterial = new Material ( "Shader\"Lines/Colored Blended\"{" +
  7.             "SubShader{ Pass { " +
  8.              Blend SrcAlphaOneMinusSrcAlpha " +
  9.              ZWrite Off Cull Off Fog { ModeOff } " +
  10.              BindChannels {" +
  11.                Bind\"vertex\",vertex Bind \"color\",color }" +
  12.             "}} }" );
  13.         lineMaterial. hideFlags= HideFlags. HideAndDontSave;
  14.         lineMaterial. shader. hideFlags= HideFlags. HideAndDontSave;
  15.     }
  16. }
  17.  
  18. function OnPostRender ( )
  19. {
  20.     CreateLineMaterial ( );
  21.     lineMaterial. SetPass ( 0 );
  22.     GL. Begin ( GL. LINES );
  23.     GL. Color ( Color ( 1, 1, 1, 0.5 ) );
  24.     GL. Vertex3 ( 0, 0, 0 );
  25.     GL. Vertex3 ( 1, 0, 0 );
  26.     GL. Vertex3 ( 0, 1, 0 );
  27.     GL. Vertex3 ( 1, 1, 0 );
  28.     GL. Color ( Color ( 0, 0, 0, 0.5 ) );
  29.     GL. Vertex3 ( 0, 0, 0 );
  30.     GL. Vertex3 ( 0, 1, 0 );
  31.     GL. Vertex3 ( 1, 0, 0 );
  32.     GL. Vertex3 ( 1, 1, 0 );
  33.     GL. End ( );
  34. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值