Good luck with this, I am interested in the progress since eventually I want my engine project to move away from VCL and have some sort of OpenGL based GUI.
Good luck with this, I am interested in the progress since eventually I want my engine project to move away from VCL and have some sort of OpenGL based GUI.
DON'T.what will ultimately be a reusable piece of code.
I beg you, stop and rethink your strategy.
Any code that has glBegin/glVertex/etc. in it will be doomed to the compatibility ghetto, limited to 20k vertices while any semi-modern hardware is capable of millions.
I will write article about Pascal beginners being cursed with this glBegin trap and why is it so horrible... Some day.
The first consequence is saying bye-bye to GLES and, correspondingly, to Raspberry Pi 2/3 support.
Here is my horrible code I replaced the glBegin travesty in my project with. It now runs on Raspberry Pi 2 and 3 (I use ANGLE over Direct3d on Windows to develop it because compiling on RPi takes forever):
Code:TDumbUniMesh = class (TAbstractMesh) //for absolutely dynamic things that get uploaded to the videocard // every frame. public components: TRenderComponentSet; colors: array of TVector4f; normals: array of TVector3f; texcoords: array of TVector2f; vertices: array of TVector3f; indices: array of GLushort; //word aka uint16 matrix: TMatrix4f; constructor Create(_components: TRenderComponentSet = [renc_Vertex, renc_Texcoord, renc_Color]); //assumes origin in *upper* left corner (y axis downwards, z axis towards the viewer) procedure AddQuad2d(left, top, right, bottom: GLfloat; txleft: GLfloat = 0; txtop: GLfloat = 0; txright: GLfloat = 1; txbottom: GLfloat = 1); procedure Render; override; destructor Destroy; procedure Color3f(_r, _g, _b: float); procedure Color4f(_r, _g, _b, _a: float); procedure Color(c: TVector3f); overload; procedure Color(c: TVector4f); overload; procedure LineTexCoords(txleft, txtop, txright, txbottom: float); procedure AddLine(c: array of const; width: float); overload; procedure AddLineLoop(c: array of const; width: float); overload; procedure AddLine(points: array of TVector2f; width: float); overload; procedure AddLineLoop(points: array of TVector2f; width: float); overload; //specifies opposite corners of a rectangle procedure SetLineTexCoords(a, b: TVector2f; _repeat: boolean); overload; procedure SetLineGradientTo(c: TVector4f); // from current color to this procedure SetLineTexCoords; // default glyph from | character in the font protected currentColor: TVector4f; lineTC: array[0..3] of TVector2f; lineTCrepeat: boolean; lineGrad: TVector4f; currentNormal: TVector3f; maxVertex, maxIndex: integer; function ParseAOCToVector2f(var c: array of const): TVector2fArray; procedure GenerateLineMesh(points: array of TVector2f; width: float; loop: boolean); procedure EnlargeBuffersIfNecessary; // according to maxVertex, maxIndex public property GetCurrentColor: TVector4f read currentColor; end; procedure TDumbUniMesh.Render; var i: integer; myib: GLuint; mymat: TMatrix4f; using_shaders: boolean; x: TRenderComponentEnum; begin if Length(indices) <= 0 then Exit; if maxIndex < High(indices) then maxIndex:= High(indices); using_shaders:= Mother^.GAPI.currentProgram.prog > 0; case Mother^.GAPI.Mode of {$ifndef glesonly} gapi_GL21: begin end; {$endif glesonly} gapi_GLES2: begin if not using_shaders then Die(RuEn( 'Класс %0 не может рисовать, используя GLES2, когда в API матки не указана спецификация текущей программы.', 'Class %0 cannot render using GLES2 if no current program is specified in mother API.'), [AnsiString(Self.ClassName)]); end; else DieUnsupportedGLMode; end; if using_shaders then begin with Mother^.GAPI.currentProgram do begin for x in [renc_Matrix, renc_Vertex] do if location[x] < 0 then Die(RuEn( 'Класс %0 не может рисовать, так как в спецификация текущей программы в API матки не хватает компоненты %1.', 'Class %0 cannot render because the program specified in the mother API doesn''t have component %1.'), [AnsiString(Self.ClassName), GetEnumName(typeinfo(TRenderComponentEnum), ord(x))]); for x in TRenderComponentSet do begin if x = renc_Matrix then continue; // it then takes the matrix from the TGAPI singleton if (location[x] >= 0) and not (x in components) then Die(RuEn( 'Данный экземпляр %0 не может рисовать, так как текущая программа требует компоненты %1 которой у него нету.', 'This %0 instance cannot render because the current program requires the %1 component which it does not have.'), [AnsiString(Self.ClassName), GetEnumName(typeinfo(TRenderComponentEnum), ord(x))]); end; CheckGLError; glBindBuffer ( GL_ARRAY_BUFFER, 0 ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 ); CheckGLError; glEnableVertexAttribArray( location[renc_Vertex] ); CheckGLError; glVertexAttribPointer( location[renc_Vertex], 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), @vertices[0]); CheckGLError; if (renc_Texcoord in components) and (location[renc_Texcoord] >= 0) then begin glEnableVertexAttribArray( location[renc_Texcoord] ); CheckGLError; glVertexAttribPointer( location[renc_Texcoord], 2, GL_FLOAT, GL_FALSE, sizeof(texcoords[0]), @texcoords[0]); CheckGLError; end; if (renc_Color in components) and (location[renc_Color] >= 0) then begin glEnableVertexAttribArray( location[renc_Color] ); CheckGLError; glVertexAttribPointer( location[renc_Color], 4, GL_FLOAT, GL_FALSE, sizeof(colors[0]), @colors[0]); CheckGLError; end; if (renc_Normal in components) and (location[renc_Normal] >= 0) then begin glEnableVertexAttribArray( location[renc_Normal] ); CheckGLError; glVertexAttribPointer( location[renc_Normal], 3, GL_FLOAT, GL_FALSE, sizeof(normals[0]), @normals[0]); CheckGLError; end; if (renc_Matrix in components) then begin mymat:= matrix * TGAPI.matrix; glUniformMatrix4fv( location[renc_Matrix], 1, GL_FALSE, @mymat); end else glUniformMatrix4fv( location[renc_Matrix], 1, GL_FALSE, @TGAPI.matrix); CheckGLError; // http://openglbook.com/chapter-3-index-buffer-objects-and-primitive-types.html glDrawElements(GL_TRIANGLES, maxIndex + 1, GL_UNSIGNED_SHORT, @indices[0]); CheckGLError; glDisableVertexAttribArray(location[renc_Vertex]); if (renc_Texcoord in components) and (location[renc_Texcoord] >= 0) then glDisableVertexAttribArray(location[renc_Texcoord]); if (renc_Color in components) and (location[renc_Color] >= 0) then glDisableVertexAttribArray(location[renc_Color]); if (renc_Normal in components) and (location[renc_Normal] >= 0) then glDisableVertexAttribArray(location[renc_Normal]); end end {$ifndef glesonly} else begin // FFP compatible { glBegin(GL_TRIANGLES); for i:=0 to maxIndex do begin glColor4fv(@colors[indices[i]]); glNormal3fv(@normals[indices[i]]); glTexCoord3fv(@texcoords[indices[i]]); glVertex4fv(@vertices[indices[i]]); end; glEnd; } // https://www.opengl.org/wiki/Client-Side_Vertex_Arrays //glGetError(); //***TODO this is a hack for an error state provoked somewhere else. Note to self: find and eliminate CheckGLError; glEnableClientState(GL_VERTEX_ARRAY); CheckGLError; glVertexPointer(3, GL_FLOAT, 0, @vertices[0]); CheckGLError; if (renc_Color in components) then begin glEnableClientState(GL_COLOR_ARRAY); CheckGLError; glColorPointer(4, GL_FLOAT, 0, @colors[0]); end else glDisableClientState(GL_COLOR_ARRAY); CheckGLError; if (renc_Texcoord in components) then begin glClientActiveTexture(GL_TEXTURE0); CheckGLError; glEnableClientState(GL_TEXTURE_COORD_ARRAY); CheckGLError; glTexCoordPointer(2, GL_FLOAT, 0, @texcoords[0]); end else glDisableClientState(GL_TEXTURE_COORD_ARRAY); CheckGLError; if (renc_Normal in components) then begin glEnableClientState(GL_NORMAL_ARRAY); CheckGLError; glNormalPointer(GL_FLOAT, 0, @normals[0]); end else glDisableClientState(GL_NORMAL_ARRAY); CheckGLError; if (renc_Matrix in components) then begin glMatrixMode(GL_MODELVIEW); glLoadMatrixf(@matrix); CheckGLError; end; glDrawElements(GL_TRIANGLES, maxIndex + 1, GL_UNSIGNED_SHORT, @indices[0]); CheckGLError; end; {$endif} end; destructor TDumbUniMesh.Destroy; begin SetLength(colors, 0); // SetLength(normals, 0); SetLength(texcoords, 0); SetLength(vertices, 0); SetLength(indices, 0); inherited; end; constructor TDumbUniMesh.Create(_components: TRenderComponentSet); begin components:= _components; if not (renc_Vertex in components) then Die(RuEn( 'Класс %0 не приспособлен к отсутствию компоненты renc_Vertex', 'Class %0 cannot work without the renc_Vertex component'), [AnsiString(Self.ClassName)]); if renc_Color in components then begin currentColor[0]:= 1; currentColor[1]:= 1; currentColor[2]:= 1; currentColor[3]:= 1; end; if renc_Normal in components then begin currentNormal[0]:= 0; currentNormal[1]:= 0; currentNormal[2]:= 1; end; maxIndex:= -1; maxVertex:= -1; if renc_Matrix in components then begin FillChar(matrix, sizeof(matrix), 0); matrix[0,0]:= 1; matrix[1,1]:= 1; matrix[2,2]:= 1; matrix[3,3]:= 1; end; end; procedure TDumbUniMesh.Color3f(_r, _g, _b: float); begin if not (renc_Color in components) then Exit; currentColor[0]:= _r; currentColor[1]:= _g; currentColor[2]:= _b; currentColor[3]:= 1.0; end; procedure TDumbUniMesh.Color4f(_r, _g, _b, _a: float); begin if not (renc_Color in components) then Exit; currentColor[0]:= _r; currentColor[1]:= _g; currentColor[2]:= _b; currentColor[3]:= _a; end; procedure TDumbUniMesh.Color(c: TVector3f); begin PVector3f(@currentColor)^:= c; currentColor[3]:= 1.0; end; procedure TDumbUniMesh.Color(c: TVector4f); begin currentColor:= c; end; procedure TDumbUniMesh.LineTexCoords(txleft, txtop, txright, txbottom: float); begin if not (renc_Texcoord in components) then Exit; lineTC[0][0]:= txleft; lineTC[0][1]:= txtop; lineTC[1][0]:= txleft; lineTC[1][1]:= txbottom; lineTC[2][0]:= txright; lineTC[2][1]:= txtop; lineTC[3][0]:= txright; lineTC[3][1]:= txbottom; end; procedure TDumbUniMesh.EnlargeBuffersIfNecessary; var nv: integer; begin if Length(indices) <= maxIndex + 1 then Setlength(indices, max(16, max(maxIndex, Length(indices) * 2))); while Length(vertices) < maxVertex + 1 do begin nv:= max(16, max ( maxVertex, Length(vertices) * 2 )); if renc_Texcoord in components then SetLength(texcoords, nv); if renc_Color in components then SetLength(colors, nv); SetLength(vertices, nv); if renc_Normal in components then Setlength(normals, nv); end; end; //reminder: here "top" denotes smaller Y values as my GUI uses y axis downwards procedure TDumbUniMesh.AddQuad2d(left, top, right, bottom: GLfloat; txleft, txtop, txright, txbottom: GLfloat); var firstindex, firstvertex, newlength, i: GLint; begin firstindex:= maxIndex + 1; //because are initialized to 0, not -1 firstvertex:= maxVertex + 1; inc (maxIndex, 6); inc (maxVertex, 4); EnlargeBuffersIfNecessary; indices[firstindex + 0]:= firstvertex + 0; indices[firstindex + 1]:= firstvertex + 1; indices[firstindex + 2]:= firstvertex + 2; indices[firstindex + 3]:= firstvertex + 2; indices[firstindex + 4]:= firstvertex + 3; indices[firstindex + 5]:= firstvertex + 0; while Length(vertices) < maxVertex + 6 do begin newlength:= max(16, Length(vertices) * 2 ); if renc_Texcoord in components then SetLength(texcoords, newlength); if renc_Color in components then SetLength(colors, newlength); SetLength(vertices, newlength); if renc_Normal in components then Setlength(normals, newlength); end; if renc_Normal in components then for i:= firstvertex to firstvertex + 3 do normals[i]:= currentNormal; if renc_Color in components then for i:= firstvertex to firstvertex + 3 do colors[i]:= currentColor; if renc_Texcoord in components then begin texcoords[firstvertex + 0][0]:= txleft; texcoords[firstvertex + 0][1]:= txtop; // texcoords[firstvertex + 0][2]:= 0; texcoords[firstvertex + 1][0]:= txright; texcoords[firstvertex + 1][1]:= txtop; // texcoords[firstvertex + 1][2]:= 0; texcoords[firstvertex + 2][0]:= txright; texcoords[firstvertex + 2][1]:= txbottom; // texcoords[firstvertex + 2][2]:= 0; texcoords[firstvertex + 3][0]:= txleft; texcoords[firstvertex + 3][1]:= txbottom; // texcoords[firstvertex + 3][2]:= 0; end; //dat was awful idea, if funny for i:= firstvertex to firstvertex + 3 do vertices[i][3]:= 1.0; vertices[firstvertex + 0][0]:= left; vertices[firstvertex + 0][1]:= top; vertices[firstvertex + 0][2]:= 0; vertices[firstvertex + 1][0]:= right; vertices[firstvertex + 1][1]:= top; vertices[firstvertex + 1][2]:= 0; vertices[firstvertex + 2][0]:= right; vertices[firstvertex + 2][1]:= bottom; vertices[firstvertex + 2][2]:= 0; vertices[firstvertex + 3][0]:= left; vertices[firstvertex + 3][1]:= bottom; vertices[firstvertex + 3][2]:= 0; end;
I think it's way better to encourage people in what they are doing than to offer alternatives because there is some other/better/advanced/optimal/fancy/cross-platfrom/new ideology/etc... way, unless they ask.
At least I myself end up feeling demotivated if there are too many alternate approaches, to know which one is best would require learning about all of them, and that is too much new stuff in one go.
procedure TDumbUniMesh.Render; gives the rough idea of which (still sub-optimal but much better) approach could be used.so I don't have a clue where to start looking in that class.
Ideally, there should be a community library for beginners to use instead of the accursed glBegin -- I shall see if I could adapt my DumbUniMesh into a standalone library.
It would be hard it what is shown is your current level.any advice on the question regarding shaders?
First, you want to pass *two* colors to the shader. This is easily done *but* is, as far as I know, incompatible with the ancient "glColorXX" way of passing the data to the GPU.
So in addition to learning how to create shaders and bind input parameters to them (not that hard, but full of details rarely explained satisfactorily), you still *have* to learn a more modern method of passing parameters to the video card (I may be missing something here -- my knowledge was gained through much trial and error).
I'd give my examples, but my code is heavily diffused into abstraction classes and exception wrappers.
For now, have you tried simply doing it in two passes? One untextured quad for the background, then another glColor() and another, now textured, quad for the character. Yes, it's double overdraw. But it would work.
P.S. And "untextured" coluld be a single texel stretched wide -- I adapted this strategy for my GUI to avoid unnecessary state switches.
P.P.S. Annoyingly "GL_QUADS" is deprecated and GLES doesn't have it. I went total :rageface: when I tried drawing a textured trapezoid and found that there is no good way except tesselating the tar out of it. What a bummer!
I had to recreate GL_LINE_STRIP on my own because it does not exist either. There are only triangles. Indexed ones.
On the plus side I can now use Google's "GL over Direct3d" wrapper -- ain't that neat?
So my code does do a two pass at present and providing I use glColor4f(1.0,1.0,1.0,1.0); aka Opaque white, the blend works and the alpha is taken into account from the font texture. And everything is great, but when I change the color to say yellow, the blend changes the colour of the background quad. This is why I was looking at shaders.
Fundamentally I've been able to write a fragment shader to set the colour to a fixed value, but where I'm coming unstuck is if I use a vertex shader to extract the color (which I understand to be an interpolated value, along with the position information), I'm in a position where it breaks the 2D orthographic projection and nothing I've tried has worked. And I've tried quite a few variations of shader.
:: AthenaOfDelphi :: My Blog :: My Software ::
You should not use blend, you should use alpha test.
For shaders... I am beginner myself, but look at my FFP emulation for my GUI:Code:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.01);
(please note that I calculate matrix by hand for GLES compatibility where glRotate() and the like do not exist: these are deprecated)
Code:#version 120 uniform mat4 u_matrix; attribute vec3 a_position; attribute vec4 a_color; attribute vec2 a_texCoord; varying vec2 v_texCoord; varying vec4 v_color; void main() { gl_Position = u_matrix * vec4(a_position[0], a_position[1], a_position[2], 1.0); v_texCoord = a_texCoord; v_color = a_color; }Code:#version 120 uniform sampler2D u_texture; varying vec2 v_texCoord; varying vec4 v_color; void main() { vec4 mytexel = texture2D( u_texture, v_texCoord); if (mytexel[3] < 0.05) { discard; } else { gl_FragColor = v_color * mytexel; } }
(too long; didn't fit)
.. and usage (converted my old uber-crappy code to this less-crappy abstraction layer):Code://replacement for GL_LINE_STRIP used in GUI everywhere procedure TDumbUniMesh.AddLine(c: array of const; width: float); begin GenerateLineMesh(ParseAOCToVector2f(c), width, false); end; procedure TDumbUniMesh.AddLineLoop(c: array of const; width: float); begin GenerateLineMesh(ParseAOCToVector2f(c), width, true); end; procedure TDumbUniMesh.AddLine(points: array of TVector2f; width: float); begin GenerateLineMesh(points, width, false); end; procedure TDumbUniMesh.AddLineLoop(points: array of TVector2f; width: float); begin GenerateLineMesh(points, width, true); end; function TDumbUniMesh.ParseAOCToVector2f(var c: array of const): TVector2fArray; var i, k, n: integer; v: float; begin if (Length(c) mod 2) <> 0 then Die(MI_ERROR_PROGRAMMER_NO_BAKA, [ 'Odd number of parameters passed to TDumbLineMesh.AddLine']); SetLength(Result, Length(c) div 2); n:= 0; k:= 0; for i:= 0 to High(c) do begin case c[i].Vtype of vtInteger: v:= c[i].VInteger; vtExtended: v:= c[i].VExtended^; else Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['Wrong parameter type passed to TDumbUniMesh.AddLine, Vtype=' + IntToStr(c[i].Vtype)]); end; Result[n][k]:= v; k:= 1 - k; if k = 0 then Inc(n); end; end; procedure TDumbUniMesh.SetLineTexCoords(a, b: TVector2f; _repeat: boolean); overload; begin lineTC[0]:= a; lineTC[1]:= b - a; lineTCrepeat:= _repeat; end; procedure TDumbUniMesh.SetLineTexCoords; // default glyph from | character in the font var pv4: PVector4f; begin pv4:= @Mother^.Text.BuiltinFont[Mother^.Text.FixedFontQuality].GlyphTexCoords^[bifgglyph_Pipe]; lineTC[0][0]:= pv4^[0]; lineTC[0][1]:= pv4^[1]; lineTC[1][0]:= pv4^[2] - pv4^[0]; lineTC[1][1]:= pv4^[3] - pv4^[1]; lineTCrepeat:= true; end; procedure TDumbUniMesh.GenerateLineMesh(points: array of TVector2f; width: float; loop: boolean); var vectors, //vector goes from i to point i + 1 rightnormals, conormals, // normal goes clockwise in my GUI // coordinate system (X axis goes right, Y axis goes down from the top left // screen corner, which is NOT how GL usually is set up) v, //vertex buffer. Calculate in 2df before copying to real vertices field tc //texcoords. : array of TVector2f; idx: array of integer; //index buffer. To be copied to the real indices. connect, degenerate: array of boolean;//the segment i connects smoothly with segment i - 1 i, j, a, b, c, numConnections, startInd, startVert, curV, curI: integer; anglecosine, veclen, confrac, ffrac: float; begin if Length(points) < 2 then Die(MI_ERROR_PROGRAMMER_NO_BAKA, ['Not enough points passed to TDumbUniMesh.GenerateLineMesh']); if loop then j:= length(points) else j:= length(points) - 1; SetLength(vectors, j); SetLength(rightnormals, j); SetLength(conormals, j); SetLength(connect, j); SetLength(degenerate, j); for i:= 0 to length(points) - 2 do vectors[i]:= points[i + 1] - points[i]; if loop then vectors[j - 1]:= points[0] - points[High(points)]; for i:= 0 to High(vectors) do begin rightnormals[i][0]:= - vectors[i][1]; // points clockwise 90 deg from the vector rightnormals[i][1]:= vectors[i][0]; QuickNormalize(rightnormals[i]); ffrac:= FastInverseSquareRoot(sqr(vectors[i][0]) + sqr(vectors[i][1])); conormals[i]:= vectors[i] * ffrac; degenerate[i]:= ffrac > (1 / width); end; numConnections:= 0; if loop then a:= 0 else begin a:= 1; connect[0]:= false; end; for i:= a to j - 1 do begin if i = 0 then b:= j - 1 else b:= i - 1; //connect *only* if angle is less that 90 degrees ! //otherwise render as separate (overlapping) segments anglecosine:= DotProduct(rightnormals[b], rightnormals[i]); connect[i]:= (anglecosine >= 0) and not degenerate[i] and not degenerate[b]; if connect[i] then inc(numConnections); end; width*= 0.5; //finally generate the mesh startInd:= MaxIndex + 1; curI:= 0; SetLength(idx, (2 * 3 * j) + (4 * 3 * numConnections)); //addlog('i/i %0/%1 %2 %3 %4 ',[curI, length(idx), j, numConnections, connect[0]]); startVert:= MaxVertex + 1; curV:= 0; SetLength(v, (4 * j) + (1 * numConnections)); if renc_Texcoord in components then begin SetLength(tc, Length(v)); end; for i:= 0 to j - 1 do begin if i = (j - 1) then a:= 0 //next point index else a:= i + 1; if connect[i] or connect[a] then confrac:= 0.5 * ( 2 * width / QuickLength(vectors[i])); if connect[i] then begin //adding the 4 triangles of the connection if i > 0 then c:= curV //vertices added by the previous segment else c:= length(v); //vertices that *will* be added by the last segment // It's a good thing our algorithm is 100% predictable, isn't it? idx[curI + 0]:= (* CurV - 1; Так вот где таилась погибель моя! Мне смертию кость угрожала! Из мёртвой главы Access Violation in ig4icd32.dll, Шипя, между тем, выползало *) c - 1; idx[curI + 1]:= c - 3; idx[curI + 2]:= CurV + 0 ; idx[curI + 3]:= CurV + 1; idx[curI + 4]:= c - 2; idx[curI + 5]:= c - 1; idx[curI + 6]:= CurV + 0; idx[curI + 7]:= CurV + 1; idx[curI + 8]:= c - 1; idx[curI + 9]:= c - 1; idx[curI +10]:= c - 2; idx[curI +11]:= c - 3; inc(curI, 12); v[curV + 0]:= points[i] + ((conormals[i] - rightnormals[i]) * width); v[curV + 1]:= points[i] + ((conormals[i] + rightnormals[i]) * width); if renc_Texcoord in components then begin tc[curV + 0]:= lineTC[0] + lineTC[1] * ToVector2f(0, confrac); tc[curV + 1]:= lineTC[0] + lineTC[1] * ToVector2f(1, confrac); end; end else begin v[curV + 0]:= points[i] - (rightnormals[i] * width); v[curV + 1]:= points[i] + (rightnormals[i] * width); if renc_Texcoord in components then begin tc[curV + 0]:= lineTC[0]; tc[curV + 1]:= lineTC[0]+ lineTC[1] * ToVector2f(1, 0); end; end; idx[curI + 0]:= curV + 1; //1st body triangle idx[curI + 1]:= curV + 0; idx[curI + 2]:= curV + 2; idx[curI + 3]:= curV + 2; //2nd body triangle idx[curI + 4]:= curV + 3; idx[curI + 5]:= curV + 1; inc(curI, 6); if connect[a] then begin v[curV + 2]:= points[a] - ((conormals[i] + rightnormals[i]) * width); v[curV + 3]:= points[a] - ((conormals[i] - rightnormals[i]) * width); if renc_Texcoord in components then begin tc[curV + 2]:= lineTC[0] + lineTC[1] * ToVector2f(0, 1 - confrac); tc[curV + 3]:= lineTC[0] + lineTC[1] * ToVector2f(1, 1 - confrac); end; //middle vertex v[curV + 4]:= points[a] + (conormals[a] - conormals[i]) * width * 0.5; if renc_Texcoord in components then begin tc[curV + 4]:= lineTC[0] + lineTC[1] * ToVector2f(0.5, 1); end; inc(curV, 5); end else begin v[curV + 2]:= points[a] - (rightnormals[i] * width); v[curV + 3]:= points[a] + (rightnormals[i] * width); if renc_Texcoord in components then begin tc[curV + 2]:= lineTC[0] + lineTC[1] * ToVector2f(0, 1); tc[curV + 3]:= lineTC[0] + lineTC[1] * ToVector2f(1, 1); end; inc(curV, 4); end; end; inc (MaxIndex, Length(idx)); inc (MaxVertex, Length(v)); EnlargeBuffersIfNecessary; for i:= 0 to High(idx) do begin indices[startInd + i]:= startVert + idx[i]; end; ffrac:= 1 / High(v); for i:= 0 to High(v) do begin vertices[startVert + i]:= v[i]; if renc_Texcoord in components then texcoords[startVert + i]:= tc[i]; if renc_Normal in components then normals[startVert + i]:= currentNormal; if renc_Texcoord in components then colors[startVert + i]:= currentColor + lineGrad * (i * ffrac); end; end; procedure TDumbUniMesh.SetLineGradientTo(c: TVector4f); begin lineGrad:= c - currentColor; end;
Code:Mesh:= TDumbUniMesh.Create; Mesh.Color4f( f * Mother^.Display.FadeIn, f * Mother^.Display.FadeIn, f * Mother^.Display.FadeIn, 1); Mesh.AddQuad2d( 0, 0, Mother^.Display.ClientRect.Width, Mother^.Display.ClientRect.Height, 0, 0, 1, 1); TGAPI.SetGLStatesForGUI; case Mother^.GAPI.Mode of {$ifndef glesonly} gapi_GL21 : begin glDisable(GL_ALPHA_TEST); end; {$endif glesonly} gapi_GLES2: begin end; else DieUnsupportedGLMode; end; //f_current_bgtex //f_current_bgw //f_current_bgh glDisable(GL_BLEND); //glEnable(GL_TEXTURE_2D); if Mother^.Display.Background.custom = 0 then glBindTexture(GL_TEXTURE_2D, f_bgtex[Mother^.Display.Background._default]) else glBindTexture(GL_TEXTURE_2D, Mother^.Display.Background.custom); Mesh.Render; Mesh.Free; { glColor4f(f * Mother^.Display.FadeIn, f * Mother^.Display.FadeIn, f * Mother^.Display.FadeIn, 1); glBindTexture(GL_TEXTURE_2D, f_bgtex); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); //bottom left corner glTexCoord2f(0, 1); glVertex2f(0, Mother^.Display.WindowClientRect.Height); glTexCoord2f(1, 1); glVertex2f(Mother^.Display.WindowClientRect.Width, Mother^.Display.WindowClientRect.Height); glTexCoord2f(1, 0); glVertex2f(Mother^.Display.WindowClientRect.Width, 0); glEnd; glEnable(GL_ALPHA_TEST); glEnable(GL_BLEND); }
Whilst I appreciate the advice that I shouldn't use glBegin... unfortunately posting a class that apparently doesn't use it doesn't really help me as it's way to complicated for me right now. I have no idea what the other alternatives are so I don't have a clue where to start looking in that class.
glBegin is how I've done all my OpenGL stuff and it's fine for what I'm doing at the moment. I know much of what I'm doing is less than optimal, but that aside, any advice on the question regarding shaders?
:: AthenaOfDelphi :: My Blog :: My Software ::
Bookmarks