Robust Polyline Rendering with WebGL - Cesium
文章推薦指數: 80 %
Rendering with Line Primitives. We ran into a few problems when using line primitives (LINES, LINE_STRIP, or LINE_LOOP) to render lines.
SkiptomaincontentRenderingwithLinePrimitivesWeranintoafewproblemswhenusinglineprimitives(LINES, LINE_STRIP,or LINE_LOOP)torenderlines.First,themaximumlinewidthwhenusing ANGLE is 1.0.Second,drawinglineprimitiveswith lineWidth (withoutANGLE)doesnotjoinlinesegmentsatasharedvertex:Theimagebelowshowslineswiththetwojoinsmitered:Finally,ourmethodtodrawoutlinedlineswithoutz-fightingwastousethreepasseswiththestencilbuffer.OurMethodOurnewmethodfordrawingpolylinesistodrawascreen-alignedquadsforeachsegmentoftheline.InWebGL,wedonothavegeometryshaders,soweduplicateeachpositionofthelineandextrudetheminscreenspaceinthevertexshader.Toextrudethepositions,weneedtoknowthepositionsofadjacentvertices.Again,wedonothavegeometryshaderssoweneedtocreateadditionalvertexattributesfortheadjacentpositioninformation.Oncewehavetheadjacentvertexpositionsandtwoverticesatthesameposition,wecanextrudethepositionsinthedirectionsnormaltotheline.Ifthisisdonetoallofthevertexpositions,wewouldendupwithsomethingsimilartodrawinglineprimitiveswith lineWidth withoutANGLEimageabove.Thatisfinefortheendpointsofthepolyline,butwewanttojointhepointswherethesegmentsofthepolylineareconnected.Tofindthedirectiontoextrudetheposition,transformallofthepositionstowindowcoordinatesandfindhalfthesumofthetwovectorspointingfromtheadjacentpositionstothevertexposition.Theamounttomovethevertexpositioninthatdirectionwillinvolvesometrigonometryandwillbediscussedlaterinthepost.Atfirst,wetriedtokeepthenumberofvertexattributesunder8becausethatistheminimumneededtosupportWebGL.Foreachposition,weneedfour vec3s.Twoareusedforthepositionin3Dandtwoareusedforthepositionin2D.TheneedforthepositionintwodifferentmodesisuniquetoCesium.Thereasonweneedtwo vec3sforasingle3Dpositionisemulateddoubleprecisioninthevertexshader.Formoreonthattopicsee, Precisions,Precisions.Toincludeeachvertexpositionplusbothadjacentvertexpositions,wewouldneedatleast12vertexattributes.Onewaytokeepthenumberofvertexattributesto8,wastouseonlythedirectionsfromthecurrentvertextotheadjacentvertices.Wewouldneeddirectionsforboth3Dand2D.Thatstillleavesuswithfour vec3sforthedirectionsandatotalof8vertexattributes.Wewouldliketoincludemoreinformationinothervertexattributessuchastexturecoordinates,width,etc.Wecouldfurtherreducethenumberofattributesbycompressingtheunitvectordirections.Thiswilltakeustotwo vec4sforthedirection.Themethodforcompressingthemwillbedescribedlaterinthepost.Wecameacrossaprecisionproblemwhenusingthecompressednormals.Whenzoomedinclosetoapolylineendpointthathasanotherendpointatmorethanabout90thousandmetersaway,theextrudedpositionswilljitterlikeintheimagebelow:Onesolutionistosubdividetheline;however,fortheaccesslinebetweentheGeoeye1andtheISSshownbelow,thenumberofpositionsgoesfrom2toabout50.Insteadofaddingthatmanyadditionalpointsforasimpleaccessline,wedecidedtousethe12vertexattributesforthecurrentvertexpositionandtheadjacentpositions.Afterweextrudethepositionsinscreenspace,weneedtotransformthepositiontoclipcoordinatesfortheoutputofthevertexshader.Thefinalpositioninscreenspaceisavec4ofthemodifiedxandycoordinates,thenegativezcoordinateandawcoordinateof1.0.Weusethenegativezcoordinatebecausetheviewdirectionisalongthenegativezaxisineveryspaceafterandincludingeyespace.Thewcoordinateisusedfortheperspectivedividewhichmakeobjectsfartherfromtheeyeseemsmaller.Wesetthewcoordinateto1.0becausewewantthewidthtobeconstantregardlessofperspective.Thiscausesanissuewhenthelineintersectsthenearplane.Wethenreversetheoperationsoftheviewporttransformationtohaveourfinalvertexshaderoutputpositioninclipspace.Belowshowsalinebeforeitintersectsthenearplane:andthisnextimageshowsthesamelineafterzoominginthatnowintersectsthenearplane:Formoreinformationaboutwhythishappens,seeClippingusinghomogeneouscoordinates.Tofixthis,weneedtoclipthelinetothenearplanebeforetransformingtoscreenspace.Whatifthereisasituationsuchasintheimagebelow:Ontheleft,twolinesegmentsshouldbeclippedbythenearplaneandtheysharethesamevertexposition.Thelinesegmentsintersectthenearplaneatthepointsinthegreencircles.Thepositionthatneedstobeclippediscircledinblue.Whichgreenpositionshouldweclipthebluepositionto?Eachvertexthatissharedbytwolinesegmentsneedstobeduplicatedagain.Foreachconnectedline,eachpositionisduplicatedtwiceattheendpointsandfourtimesatthesharedpositions.Wealsoneedtoknowwhichlinesegmentthepositionbelongstoandclipitintherightdirection.Thesituationontherightiseasiertohandleoncewehavehandledthesituationontheleft.Ifavertexpositionbelongstoalinethatisculled,simplyoutputclipcoordinatesthatarebehindthenearplaneensuringthatthelineisnotdrawn.VertexShaderDetailsExtrudeVertexinScreenSpaceThediagrambelowshowsalinedrawninblackandthesamelineextrudedtoagreaterwidthinscreenspaceoutlinedinred.Toextrudethelineattheendpoints,simplymovetheverticesthedesirednumberofpixelsinthedirectionofthenormalstothelinesegment.Thediagrambelowshowsacloseupoftheareasurroundedbyadashedorangelineintheimageabove.Letthegreenvectorbe u andtheblackvectorbe v.Wewanttofindthevector u.Weknowthedirectionof v becauseitiseitherthedirectiontothenextpointorthepreviouspointontheline.Wecanfindthedirectionof u becauseithalf-waybetweenthedirectiontothenextandpreviouspointsontheline.Now,wejustneedtofindthemagnitudeof u which,fromthetrigonometryidentity,weknowis ||u||=width/sin(a).Weknowthatforanyvectors p and q that ||pxq||=||p||||q|||sin(a)|.Ifwetreat û and v̂ asthreedimensionalvectorsinthexy-plane,wecansubstitute û and v̂ intotheexpression.Because û and v̂ areunitvectorsandthezcoordinateis 0.0,thelastexpressioncanbesimplifiedto sin(a)=|û.x*v̂.y-û.y*v̂.x|.TheGLSLcodeisgivenbelow:
floatsinAngle=abs(u.x*v.y-u.y*v.x);
width/=sinAngle;
vec2offset=direction*directionSign*width*czm_highResolutionSnapScale;
gl_Position=czm_viewportOrthographic*vec4(positionWC.xy+offset,-positionWC.z,1.0);
Caremustbegiventomakesurethat sinAngle isnotclosetozeroandthatwemovethevertexintherightdirection(either u or -u inourexample).
ClippingtotheNearPlane
Asexplainedabove,weneedtocliptheendpointsofthelinesegmentstothenearplane.HereistheGLSLfunctionusedtoclipapointtothenearplaneineyecoordinates:
voidclipLineSegmentToNearPlane(
vec3p0,
vec3p1,
outvec4positionWC,
outboolculledByNearPlane)
{
culledByNearPlane=false;
vec3p1ToP0=p1-p0;
floatmagnitude=length(p1ToP0);
vec3direction=normalize(p1ToP0);
floatendPoint0Distance=-(czm_currentFrustum.x+p0.z);
floatdenominator=-direction.z;
if(endPoint0Distance<0.0&&abs(denominator)
延伸文章資訊
- 1WebGL Points, Lines, and Triangles
As mentioned in the first article WebGL draws points, lines, and triangles. It does this when we ...
- 2How 2 draw lines in
How to draw line in WebGL ... 2013 april, Robust polyline rendering with WebGL by Dan Bagnell. ○ ...
- 3Instanced 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...
- 4Instanced 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...
- 5Robust Polyline Rendering with WebGL - Cesium
Rendering with Line Primitives. We ran into a few problems when using line primitives (LINES, LIN...