Drawing a line in modern OpenGL - c++ - Stack Overflow

文章推薦指數: 80 %
投票人數:10人

Create an array with the corners points of the line strip. The first and the last point define the start and end tangents of the line strip. So ... Home Public Questions Tags Users Companies Collectives ExploreCollectives Teams StackOverflowforTeams –Startcollaboratingandsharingorganizationalknowledge. CreateafreeTeam WhyTeams? Teams CreatefreeTeam Collectives™onStackOverflow Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost. LearnmoreaboutCollectives Teams Q&Aforwork Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch. LearnmoreaboutTeams DrawingalineinmodernOpenGL AskQuestion Asked 2years,6monthsago Modified 3monthsago Viewed 12ktimes 5 7 Isimplywanttodrawalinetothescreen.I'musingOpenGl4.6.AlltutorialsIfoundusedaglVertexPointer,whichisdeprecatedasfarasIcantell. Iknowhowyoucandrawtrianglesusingbuffers,soItriedthatwithaline.Itdidn'twork,merelydisplayingablackscreen.(I'musingGLFWandGLEW,andIamusingavertex+fragmentshaderIalreadytestedonthetriangle) //Makeline floatline[]={ 0.0,0.0, 1.0,1.0 }; unsignedintbuffer;//TheID,kindofapointerforVRAM glGenBuffers(1,&buffer);//Allocatememoryforthetriangle glBindBuffer(GL_ARRAY_BUFFER,buffer);//Setthebufferastheactivearray glBufferData(GL_ARRAY_BUFFER,2*sizeof(float),line,GL_STATIC_DRAW);//Fillthebufferwithdata glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,2*sizeof(float),0);//Specifyhowthebufferisconvertedtovertices glEnableVertexAttribArray(0);//Enablethevertexarray //Loopuntiltheuserclosesthewindow while(!glfwWindowShouldClose(window)) { //Clearprevious glClear(GL_COLOR_BUFFER_BIT); //Drawtheline glDrawArrays(GL_LINES,0,2); //Swapfrontandbackbuffers glfwSwapBuffers(window); //Pollforandprocessevents glfwPollEvents(); } AmIgoingintherightdirection,orisacompletelydifferentapproachthecurrentbestpractice? IfIam,howdoIfixmycode? c++openglglfw Share Follow editedMar7at20:45 genpfault 49.8k1010goldbadges8181silverbadges130130bronzebadges askedFeb27,2020at19:43 CheeseCrusteryCheeseCrustery 76111goldbadge77silverbadges1717bronzebadges 7 IfyouuseacompatibilityprofileOpenGLContext,thenyoucanstilluseglVertexAttribPointer.IfyouhavetouseacoreprofilecontextthanyouhavetouseaShaderprogramandaVertexArrayObjectandyou'llneedagoodtutorial(e.g.LearnOpenGL) – Rabbid76 Feb27,2020at19:47 @Rabbidthanks,butIwanttolearnmodernOpenGLstraightaway,notrelyingoncodethatisalreadyoutdated.ButIamatotalbeginner,somaybeusingthisfunctionistheintendedwayafterall? – CheeseCrustery Feb27,2020at19:51 AsImentioned,readatutorial.Toexplainshadersandvertexarrayobjectsistobroadforasinglestackoverflowquestion. – Rabbid76 Feb27,2020at19:52 @RabbidIt'snotthatIhavenoideawhatthiscodedoes.Ijustaskedforhelpinfindingtheerror. – CheeseCrustery Feb27,2020at19:59 YoucanusethelatestOpenGLtodowhatyouwant,butifyou'reconcernedaboutbeingveryup-to-date,whichyouseemtobe,VulkanisthemostmodernofferingfromtheKhronosGroup,whichisalsoresponsibleforOpenGL.Forinstance,Vulkanisreadyformultithreadedrendering,whereasthisishardinOpenGL.(OpenGLisstillwidelysupported,butApplehasdeprecatedsupportforit,forinstance.) – metal Feb27,2020at20:09  |  Show2morecomments 1Answer 1 Sortedby: Resettodefault Highestscore(default) Trending(recentvotescountmore) Datemodified(newestfirst) Datecreated(oldestfirst) 21 TheissueisthecalltoglBufferData.The2ndargumentisthesizeofthebufferinbytes.Sincethevertexarrayconsistsof2coordinateswith2components,thesizeofthebufferis4*sizeof(float)ratherthan2*sizeof(float): glBufferData(GL_ARRAY_BUFFER,2*sizeof(float),line,GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER,4*sizeof(float),line,GL_STATIC_DRAW); Butnotethatisstillnot"modern"OpenGL.IfyouwanttousecoreprofileOpenGLContext,thenyouhavetouseaShaderprogramandaVertexArrayObject However,ifyouareusingacoreOpenGLcontextandtheforwardcompatibilitybitisset,thewidthofaline(glLineWidth),cannotbegraterthan1.0. SeeOpenGL4.6APICoreProfileSpecification-E.2DeprecatedandRemovedFeatures Widelines-LineWidthvaluesgreaterthan1.0willgenerateanINVALID_VALUEerror. Youhavetofindadifferentapproach. IrecommendtouseaShader,whichgeneratestriangleprimitivesalongalinestrip(orevenalineloop). Thetaskistogeneratethicklinestrip,withaslessCPUandGPUoverheadaspossible.ThatmeanstoavoidcomputationofpolygonsontheCPUaswellasgeometryshaders(ortessellationshaders). Eachsegmentofthelineconsistofaquadrepresentedby2triangleprimitivesrespectively6vertices. 025 +-------++ |//| |//| |//| ++-------+ 134 Betweenthelinesegmentsthemiterhasttobefoundandthequadshavetobecuttothemiter. +----------------+ |/| |segment1/| |/| +--------+| |segment2 || || +-------+ Createanarraywiththecornerspointsofthelinestrip.Thefirstandthelastpointdefinethestartandendtangentsofthelinestrip.Soyouneedtoadd1pointbeforethelineandonepointaftertheline.Ofcourseitwouldbeeasy,toidentifythefirstandlastelementofthearraybycomparingtheindexto0andthelengthofthearray,butwedon'twanttodoanyextrachecksintheshader. Ifalineloophastobedraw,thenthelastpointhastobeaddtothearrayheadandthefirstpointtoitstail. ThearrayofpointsisstoredtoaShaderStorageBufferObject.Weusethebenefit,thatthelastvariableoftheSSBOcanbeanarrayofvariablesize.InolderversionsofOpenGL(orOpenGLES)aUniformBufferObjectorevenaTexturecanbeused. Theshaderdoesn'tneedanyvertexcoordinatesorattributes.Allwehavetoknowistheindexofthelinesegment.Thecoordinatesarestoredinthebuffer.Tofindtheindexwemakeuseofthetheindexofthevertexcurrentlybeingprocessed(gl_VertexID). TodrawalinestripwithNsegments,6*(N-1)verticeshavetpobeprocessed. Wehavetocreatean"empty"VertexArrayObject(withoutanyvertexattributespecification): glGenVertexArrays(1,&vao); glBindVertexArray(vao); Andtodraw2*(N-1)triangle(6*(N-1)vertices): glDrawArrays(GL_TRIANGLES,0,6*(N-1)); ForthecoordinatearrayintheSSBO,thedatatypevec4isused(Pleasbelieveme,youdon'twanttousevec3): layout(std430,binding=0)bufferTVertex { vec4vertex[]; }; Computetheindexofthelinesegment,wherethevertexcoordinatebelongstooandtheindexofthepointinthe2triangles: intline_i=gl_VertexID/6; inttri_i=gl_VertexID%6; SincewearedrawingN-1linesegments,butthenumberofelementsinthearrayisN+2,theelementsformvertex[line_t]tovertex[line_t+3]canbeaccessedforeachvertexwhichisprocessedinthevertexshader. vertex[line_t+1]andvertex[line_t+2]arethestartrespectivelyendcoordinateofthelinesegment.vertex[line_t]andvertex[line_t+3]arerequiredtocomputethemiter. Thethicknessofthelineshouldbesetinpixelunit(uniformfloatu_thickness).Thecoordinateshavetobetransformedfrommodelspacetowindowspace.Forthattheresolutionoftheviewporthastobeknown(uniformvec2u_resolution).Don'tforgettheperspectivedivide.Thedrawingofthelinewillevenworkatperspectiveprojection. vec4va[4]; for(inti=0;i<4;++i) { va[i]=u_mvp*vertex[line_i+i]; va[i].xyz/=va[i].w; va[i].xy=(va[i].xy+1.0)*0.5*u_resolution; } Themitercalculationevenworksifthepredecessororsuccessorpointisequaltothestartrespectivelyendpointofthelinesegment.Inthiscasetheendofthelineiscutnormaltoitstangent: vec2v_line=normalize(va[2].xy-va[1].xy); vec2nv_line=vec2(-v_line.y,v_line.x); vec2v_pred=normalize(va[1].xy-va[0].xy); vec2v_succ=normalize(va[3].xy-va[2].xy); vec2v_miter1=normalize(nv_line+vec2(-v_pred.y,v_pred.x)); vec2v_miter2=normalize(nv_line+vec2(-v_succ.y,v_succ.x)); Inthefinalvertexshaderwejustneedtocalculateeitherv_miter1orv_miter2dependentonthetri_i.Withthemiter,thenormalvectortothelinesegmentandthelinethickness(u_thickness),thevertexcoordinatecanbecomputed: vec4pos; if(tri_i==0||tri_i==1||tri_i==3) { vec2v_pred=normalize(va[1].xy-va[0].xy); vec2v_miter=normalize(nv_line+vec2(-v_pred.y,v_pred.x)); pos=va[1]; pos.xy+=v_miter*u_thickness*(tri_i==1?-0.5:0.5)/dot(v_miter,nv_line); } else { vec2v_succ=normalize(va[3].xy-va[2].xy); vec2v_miter=normalize(nv_line+vec2(-v_succ.y,v_succ.x)); pos=va[2]; pos.xy+=v_miter*u_thickness*(tri_i==5?0.5:-0.5)/dot(v_miter,nv_line); } Finallythewindowcoordinateshavetobetransformedbacktoclipspacecoordinates.Transformfromwindowspacetonormalizeddevicespace.Theperspectivedividehastobereversed: pos.xy=pos.xy/u_resolution*2.0-1.0; pos.xyz*=pos.w; PolygonscreatedwithglPolygonMode(GL_FRONT_AND_BACK,GL_FILL)andglPolygonMode(GL_FRONT_AND_BACK,GL_LINE): DemoprogramusingGLFWAPIforcreatingawindow,GLEWforloadingOpenGLandGLM-OpenGLMathematicsforthemath.(Idon'tprovidethecodeforthefunctionCreateProgram,whichjustcreatesaprogramobject,fromthevertexshaderandfragmentshadersourcecode): #include #include #include #include #include #include #include std::stringvertShader=R"( #version460 layout(std430,binding=0)bufferTVertex { vec4vertex[]; }; uniformmat4u_mvp; uniformvec2u_resolution; uniformfloatu_thickness; voidmain() { intline_i=gl_VertexID/6; inttri_i=gl_VertexID%6; vec4va[4]; for(inti=0;i<4;++i) { va[i]=u_mvp*vertex[line_i+i]; va[i].xyz/=va[i].w; va[i].xy=(va[i].xy+1.0)*0.5*u_resolution; } vec2v_line=normalize(va[2].xy-va[1].xy); vec2nv_line=vec2(-v_line.y,v_line.x); vec4pos; if(tri_i==0||tri_i==1||tri_i==3) { vec2v_pred=normalize(va[1].xy-va[0].xy); vec2v_miter=normalize(nv_line+vec2(-v_pred.y,v_pred.x)); pos=va[1]; pos.xy+=v_miter*u_thickness*(tri_i==1?-0.5:0.5)/dot(v_miter,nv_line); } else { vec2v_succ=normalize(va[3].xy-va[2].xy); vec2v_miter=normalize(nv_line+vec2(-v_succ.y,v_succ.x)); pos=va[2]; pos.xy+=v_miter*u_thickness*(tri_i==5?0.5:-0.5)/dot(v_miter,nv_line); } pos.xy=pos.xy/u_resolution*2.0-1.0; pos.xyz*=pos.w; gl_Position=pos; } )"; std::stringfragShader=R"( #version460 outvec4fragColor; voidmain() { fragColor=vec4(1.0); } )"; //main GLuintCreateSSBO(std::vector<:vec4>&varray) { GLuintssbo; glGenBuffers(1,&ssbo); glBindBuffer(GL_SHADER_STORAGE_BUFFER,ssbo); glBufferData(GL_SHADER_STORAGE_BUFFER,varray.size()*sizeof(*varray.data()),varray.data(),GL_STATIC_DRAW); returnssbo; } intmain(void) { if(glfwInit()==0) throwstd::runtime_error("errorinitializingglfw"); GLFWwindow*window=glfwCreateWindow(800,600,"GLFWOGLwindow",nullptr,nullptr); if(window==nullptr) { glfwTerminate(); throwstd::runtime_error("errorinitializingwindow"); } glfwMakeContextCurrent(window); if(glewInit()!=GLEW_OK) throwstd::runtime_error("errorinitializingglew"); OpenGL::CContext::TDebugLeveldebug_level=OpenGL::CContext::TDebugLevel::all; OpenGL::CContextcontext; context.Init(debug_level); GLuintprogram=OpenGL::CreateProgram(vertShader,fragShader); GLintloc_mvp=glGetUniformLocation(program,"u_mvp"); GLintloc_res=glGetUniformLocation(program,"u_resolution"); GLintloc_thi=glGetUniformLocation(program,"u_thickness"); glUseProgram(program); glUniform1f(loc_thi,20.0); GLushortpattern=0x18ff; GLfloatfactor=2.0f; std::vector<:vec4>varray; varray.emplace_back(glm::vec4(0.0f,-1.0f,0.0f,1.0f)); varray.emplace_back(glm::vec4(1.0f,-1.0f,0.0f,1.0f)); for(intu=0;u<=90;u+=10) { doublea=u*M_PI/180.0; doublec=cos(a),s=sin(a); varray.emplace_back(glm::vec4((float)c,(float)s,0.0f,1.0f)); } varray.emplace_back(glm::vec4(-1.0f,1.0f,0.0f,1.0f)); for(intu=90;u>=0;u-=10) { doublea=u*M_PI/180.0; doublec=cos(a),s=sin(a); varray.emplace_back(glm::vec4((float)c-1.0f,(float)s-1.0f,0.0f,1.0f)); } varray.emplace_back(glm::vec4(1.0f,-1.0f,0.0f,1.0f)); varray.emplace_back(glm::vec4(1.0f,0.0f,0.0f,1.0f)); GLuintssbo=CreateSSBO(varray); GLuintvao; glGenVertexArrays(1,&vao); glBindVertexArray(vao); glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,ssbo); GLsizeiN=(GLsizei)varray.size()-2; glClearColor(0.0f,0.0f,0.0f,0.0f); glm::mat4(project); intvpSize[2]{0,0}; while(!glfwWindowShouldClose(window)) { intw,h; glfwGetFramebufferSize(window,&w,&h); if(w!=vpSize[0]||h!=vpSize[1]) { vpSize[0]=w;vpSize[1]=h; glViewport(0,0,vpSize[0],vpSize[1]); floataspect=(float)w/(float)h; project=glm::ortho(-aspect,aspect,-1.0f,1.0f,-10.0f,10.0f); glUniform2f(loc_res,(float)w,(float)h); } glClear(GL_COLOR_BUFFER_BIT); glm::mat4modelview1(1.0f); modelview1=glm::translate(modelview1,glm::vec3(-0.6f,0.0f,0.0f)); modelview1=glm::scale(modelview1,glm::vec3(0.5f,0.5f,1.0f)); glm::mat4mvp1=project*modelview1; glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); glUniformMatrix4fv(loc_mvp,1,GL_FALSE,glm::value_ptr(mvp1)); glDrawArrays(GL_TRIANGLES,0,6*(N-1)); glm::mat4modelview2(1.0f); modelview2=glm::translate(modelview2,glm::vec3(0.6f,0.0f,0.0f)); modelview2=glm::scale(modelview2,glm::vec3(0.5f,0.5f,1.0f)); glm::mat4mvp2=project*modelview2; glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); glUniformMatrix4fv(loc_mvp,1,GL_FALSE,glm::value_ptr(mvp2)); glDrawArrays(GL_TRIANGLES,0,6*(N-1)); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return0; } Share Follow editedMay23at19:23 answeredFeb27,2020at20:03 Rabbid76Rabbid76 185k2525goldbadges105105silverbadges154154bronzebadges 3 2 ThecodecanbetranslatedtoApple'sMetalgraphicsframeworknearly1:1,ifyoudothiswatchouttousetheprecise::normalizefunctionoftheMetalshadinglanguagewithfastarithmeticsincethelengthcanbezerointhemitercalculation. – Dr.F. Mar28,2021at8:04 2 @Rabbid76Fantasticexample!Couldyouexplaintheorderofpointstodrawanopenline?Thispart:"Createanarraywiththecornerspointsofthelinestrip.Thearrayhastocontainthefirstandthelastpointtwice..."ItriedthatbuttheresultwasnotwhatIexpected.eg.Whatshouldthearraylookliketogetlinep0:{-100,-100},p1:{100,100},p2:{200,100},p3:{300,-50}?Itried[p0,p1,p2,p3,p0,p1]butnotallsegmentsweredrawn. – SinisaDrpa Nov27,2021at12:47 2 @SinisaDrpaThefirstandthelastpointdefinethestartandendtangentsoftheline.Soyouneedtoadd1pointbeforethelineandonepointaftertheline.Ichangedthatpartintheanswer.e.g.[(-200,-200),(-100,-100),(100,100),(200,100),(350,-50),(400,0)].Inthiscase(-200,-200)isforthestarttangentand(400,0)fortheendtangent. – Rabbid76 Nov27,2021at12:59 Addacomment  |  YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy Nottheansweryou'relookingfor?Browseotherquestionstaggedc++openglglfworaskyourownquestion. TheOverflowBlog Functionalprogrammingisanidealfitfordevelopingblockchains Environmentson-demand(Ep.479) FeaturedonMeta AnnouncingtheStackOverflowStudentAmbassadorProgram GoogleAnalytics4(GA4)upgrade StagingGroundWorkflow:QuestionLifecycle The[option]tagisbeingburninated CollectivesUpdate:WSO2launches,andGoogleGosunsets Linked 45 ShouldIeverusea`vec3`insideofauniformbufferorshaderstoragebufferobject? 9 DrawingavariablewidthlineinopenGL(NoglLineWidth) 1 OpenGLlinewidthgeometryshader Related 6 TroubleportingOpenGLapptoWindows 1 OpenglesmixingVBOandnonVBOrendersgivesEXC_BAD_ACCESS 0 VBOdoesn'tuseUVcoordinates 1 IncorrectlightingwhenbatchingtrianglestripsinOpenGL 29 OpenGL,VAOsandmultiplebuffers 9 VertexArrayObjects-Confusionregardingexactlywhatstateinformationissavedaboutthecurrentlyboundvertexbuffer 2 RedundantVertexBuffercausingOpenGLtonotdrawcorrectly 1 IsVertexArrayObjectapartofContext? 3 PyOpenGL-MinimalglDrawArraysExample HotNetworkQuestions IsthereevidencewhetherSpaceXismakingaprofitlaunchingrockets? WhydidthepilotsinTopGun:Maverickinvertatthecrestofthemountainbeforedescending? Ifalldemonsarebelievers,thenwhyaresomehumansatheists? CouldCongress"bribe"thePresidenttosignabillbyincludingapresidentialpayraise? IsURLrewritingine-mailasoundsecuritypractice? Iwantthemostfunformyplayersbuttheygotangrysecondsessionbecauseofcombat.Anytips? Bookaboutspacefaringhumansthatcapturesomeformofalien/spirit(possiblynamed"angels")foundinspace ReactionofxenonwithO₂F₂? Whywerehiraganaandkatakananevermergedintoonesystem? Whyisablackribbonhungoveraperson'sportraitwhentheydie? CountingadjacentpolygonsusingQGIS HowcanIrecycleabrokentitaniumframe? Whatisthepointofthelineonacheck? Identification:StarTrekVoyager-realcivilizationtreatedlikeAgeofEmpires(i.e.areal-timestrategygame) Meaningof"shade"in"ashabbygreenshadeshovedupfromoneofhiseyes" WhyisthehotpartofWebb'sMIRIcryocoolerinthe300Karea? Wouldalifetimegymmembershipbesubjecttobankruptcyproceedings? WhatisthepoliticaljustificationbyChinaandIndiafornotparticipatinginthesanctionsagainstRussia? Deletionoflistelementsbyrule Intheelectrondoubleslitexperiment,whatisinterfering? Doweneedtocitearticlestothepaperfromthejournaltowherewearesendingto? Whydoesthisalgorithmgenerateastandardnormaldistribution? TwinParadox(SR):Howcanweexpressthecomparativelengthofarbitraryworld-linesmathematically? Howdoonlinegameshandlefrequentupdates? morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-cpp Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?