Drawing a line in modern OpenGL - c++ - Stack Overflow
文章推薦指數: 80 %
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
延伸文章資訊
- 1OpenGL Tutorial 7 - Drawing A Line - YouTube
- 2Sample Modern OpenGL Programs - UCSD Math Department
SimpleDrawModern shows how to draw points, lines, line strips, line loops, and triangles. It incl...
- 3Hello Triangle - LearnOpenGL
In modern OpenGL we are required to define at least a vertex and fragment ... and back of all tri...
- 4OpenGL 101: Drawing primitives - points, lines and triangles
OpenGL 101: Drawing primitives - points, lines and triangles. Posted on May 13, 2013 by Paul. The...
- 5Drawing a line in modern OpenGL - c++ - Stack Overflow
Create an array with the corners points of the line strip. The first and the last point define th...