Drawing Lines is Hard - Matt DesLauriers - Svbtle
文章推薦指數: 80 %
Line Primitives #. touch to rotate rendering with gl.LINES. WebGL includes support for lines with ... Svbtle MattDesLauriers Menu MattDesLauriersiswritingontheSvbtlenetwork. mattdesl.com @mattdesl rssfeed aboutsvbtle signup March9,2015 DrawingLinesisHard Twitter:@mattdesl Drawinglinesmightnotsoundlikerocketscience,butit’sdamndifficulttodowellinOpenGL,particularlyWebGL.HereIexploreafewdifferenttechniquesfor2Dand3Dlinerendering,andaccompanyeachwithasmallcanvasdemo. Sourcefordemoscanbefoundhere: https://github.com/mattdesl/webgl-lines LinePrimitives# (demo) WebGLincludessupportforlineswithgl.LINES,gl.LINE_STRIP,andgl.LINE_LOOP.Soundsgreat,right?Notreally.Herearejustafewissueswiththat: Driversmayimplementtherendering/filteringslightlydifferently,andyoumaynotgetaconsistentrenderacrossdevicesorbrowsers Themaximumlinewidthisdriver-dependent.UsersrunningANGLE,forexample,willgetamaximumof1.0,whichisprettyuseless.OnmynewYosemitemachine,linewidthmaxesoutatabout10. Nocontroloverlinejoinorendcapstyles MSAAisnotsupportedinalldevices,andmostbrowsersdonotsupportitforoff-screenbuffers.Youmayendupwithjaggedlines Fordashed/dottedlines,glLineStipplehasbeendeprecatedanddoesn’texistinWebGL Insomedemos,liketheoneabove,gl.LINESmightbeacceptable,butinmostcasesit’sinadequateforproductionqualitylinerendering. TriangulatedLines# (demo) Acommonalternativeistobreakalineintotrianglesortrianglestrips,andthenrenderthemasregulargeometry.Thisgivesyouthemostcontrolovertheline,allowingforendcaps,specificjoins,unions(foroverlappingtransparentareas),andsoforth.Thiscanalsoleadtosomemorecreativeandinterestinglinerendering,asintheabovedemo. Atypicalwayofachievingthisistogetthenormalsforeachpointalongapath,andexpandoutwardsbyhalfthethicknessoneitherside.Foranimplementation,seepolyline-normals.Themathbehindthemiterjoinisdiscussedhere. Moreadvancedmeshesmayneedtoemitnewgeometriesforendcaps,beveljoins,feathering,andsoforth.Handlingtheseedgecasescangetfairlycomplex,asyoucanseeinVaserC/C++source. Foranti-aliasing,youhaveafewoptions: hopethatMSAAissupportedandthatyouwillneverneedthelinesrenderedtoanoff-screenbuffer addmoretrianglesforthefeatherededgesofastroke(asinthisimage) useatexturelookuptogradatethealpha;veryeasybutdoesnotscalewell inthefragmentshader,computetheanti-aliasingbasedontheprojectedscaleofthestrokeinscreenspace renderprefilteredgl.LINESasasecondpass,aroundtheedgeofyourstroke Note:adrawbackthatcomeswithmiter-joinedlinesissharpedges.Whentheangleconnectingtwosegmentsisverysharp,themiterlengthgrowsexponentiallytowardinfinity,andcauseshugeartifactsinrendering.Insomeapplicationsthismaynotbeaproblem,inothersyoumightwanttolimitthemiterorfallbacktoanotherjoin(i.e.bevel)whentheangleistoosharp. TheaboveTrianglesdemousesextrude-polyline,asmallwork-in-progressmoduleforbuildingatriangulatedmeshoutofa2Dpolyline.Eventuallyitaimstosupportroundjoins/capsandpropermiterlimiting. ExpandinginaVertexShader# (demo) Triangulationcanaddafairamountofcomplexitytoyourcode,andthemeshneedstobere-constructedwhenthestrokeandjoinstylechanges.IfyoujustwantsimplethicklinesinWebGL,itcanbeabitoverkill. Thisdemoaboveexpandsthestrokeinthevertexshader,wherethethicknessisauniform.Wesubmittwoverticesforeachpointinourpath,andpassthelinenormalsandmiterlengthsasvertexattributes.Eachpairhasonenormal(ormiter)flipped,sothatthetwopointsarepushedawayfromthecentretoformathickline. attributevec2position; attributevec2normal; attributefloatmiter; uniformmat4projection; voidmain(){ //pushthepointalongitsnormalbyhalfthickness vec2p=position.xy+vec2(normal*thickness/2.0*miter); gl_Position=projection*vec4(p,0.0,1.0); } Theinnerstrokeeffectontheleft(clickthecanvastoanimateit)iscreatedinthefragmentshaderusingthesigneddistancefromcentre.Wecanalsoachievelinedashes,gradients,glows,andothereffectsbypassingdistanceAlongPathasanothervertexattribute. ?ForaThreeJSimplementationofthisapproach,includinglinedashes,seethree-line-2d. Screen-SpaceProjectedLines# Thepreviousdemoworkswellfor2D(orthographic)lines,butmaynotfityourdesignneedsin3Dspace.Togivethelineaconstantthicknessregardlessofthe3Dview,weneedtoexpandthelineafterprojectingitintoscreenspace. (demo) Likethelastdemo,weneedtosubmiteachpointtwice,withmirroredorientationssotheyarepushedawayfromeachother.However,insteadofcomputingthenormalandmiterlengthCPU-side,wedoitinthevertexshader.Todothis,weneedtosendalongvertexattributesforthenextandpreviouspositionsalongthepath. Inthevertexshader,wecomputeourjoinandextrusioninscreenspacetoensuretheconstantthickness.Toworkinscreenspace,weneedtousetheillusivehomogeneouscomponent,W.Alsoknownas“perspectivedivide.”ThisgivesusNormalizedDeviceCoordinates(NDC),whichlieintherange[-1,1].Wethencorrectforaspectratiobeforeexpandingourlines.Wealsodothesameforpreviousandnextpositionsalongthepath: mat4projViewModel=projection*view*model; //intoclipspace vec4currentProjected=projViewModel*vec4(position,1.0); //intoNDCspace[-1..1] vec2currentScreen=currentProjected.xy/currentProjected.w; //correctforaspectratio(screenWidth/screenHeight) currentScreen.x*=aspect; Therearesomeedgecasesthatneedtobehandledforthefirstandlastpointsinapath,butotherwiseasimplesegmentmightlooklikethis: //normalofline(B-A) vec2dir=normalize(nextScreen-currentScreen); vec2normal=vec2(-dir.y,dir.x); //extrudefromcenter&correctaspectratio normal*=thickness/2.0; normal.x/=aspect; //offsetbythedirectionofthispointinthepair(-1or1) vec4offset=vec4(normal*direction,0.0,0.0); gl_Position=currentProjected+offset; Noticethereisnoattempttojointwosegmentshere.Thisapproachissometimespreferabletomitersinceitdoesn’tdealwiththeproblemsofsharpedges.Thetwistingcircleintheabovedemoisnotusinganymiterjoins. Ontheotherhand,thehourglassshapeinthedemowouldlookpinchedanddeformedwithoutamiterjoin.Forthis,thevertexshaderimplementsabasicmiterjoinwithoutanylimiting. Wecouldmakesomeslightvariationstothemathtoachieveadifferentdesign.Forexample,usingtheZcomponentoftheNDCtoscalethethicknessofthelinesastheyfalldeeperintothescene.Thiswouldhelpgiveagreatersenseofdepth. ?ForaThreeJSimplementationofthisapproach,seeTHREE.MeshLineby@thespite. OtherApproaches# AswithmostthingsinWebGL,thereareadozenwaystoskinacat.Theabovedemoswereimplementedwithratherlow-levelabstractionssoyoucangetasenseofwhatisgoingon,anddecideforyourselfthemostsuitableapproachforyournextapplication.Someotherapproachesthatmightbeviable: StencilGeometry Acooltrickusingthestencilbuffertocreatecomplexpolygonswithouttriangulation.However,itdoesnotreceiveanyMSAAatall.[1][2][3] Loop-BlinnCurveRendering Resolution-independentcubicsplinerendering,idealforfontglyphs. Rasterizedstrokes CanbeusedtobuildfeatureslikePhotoshopbrushes SinglePassWireframeRendering Similartotheprojectedlinesdemo,butbettersuitedfor3Dwireframes[1] GeometryShaders Thiswouldallowprojectedlinestoemitavarietyofcaps/joins.However,geometryshadersarenotsupportedinWebGL. AnalyticDistanceFields Usingasinglequadanddistancefieldsinthefragmentshadercouldalsoachievethickanti-aliasedlinesin2Dand3D.Thisisnotverypractical,andmayperformpoorly,butitcanalsoenablesomeinterestingeffects(likemotionblur). ModulesUsed# Thedemoswerecomposedofdozensofopensourcemodulesonnpmjs.org.Someofthepath-relatedmodules: adaptive-bezier-curve arc-to extrude-polyline polyline-normals quad-indices gl-vec3,gl-mat4 FurtherReading# CesiumJS-RobustPolylineRendering MapboxGL-DrawingAntialiasedLinesinWebGL NVIDIA-GPUPathRendering PrefilteredLines THREE.MeshLine 5,053 Kudos 5,053 Kudos Nowreadthis DebuggingNode.jsinChromeDevTools Thispostintroducesanovelapproachtodeveloping,debugging,andprofilingNode.jsapplicationswithinChromeDevTools.devtool#RecentlyI’vebeenworkingonacommand-linetool,devtool,whichrunsNode.jsprogramsinsideChrome...Continue →
延伸文章資訊
- 1Instanced Line Rendering in WebGL - wwwtyro.net
In order to render our instanced lines, we're going to need two things - a WebGL context that sup...
- 2WebGL Points, Lines, and Triangles
As mentioned in the first article WebGL draws points, lines, and triangles. It does this when we ...
- 3Instanced Line Rendering Using WebGL - Hacker News
If like me you're also rendering lines with perspective, you want to also look at ... When we wro...
- 4Drawing A Line Using gl.LINES - WebGL Programming
- 5Robust Polyline Rendering with WebGL - Cesium
Rendering with Line Primitives. We ran into a few problems when using line primitives (LINES, LIN...