Merge remote-tracking branch 'glBitmap@DGL/master'
[LazOpenGLCore.git] / uglcArrayBuffer.pas
1 unit uglcArrayBuffer;
2
3 { Package:      OpenGLCore
4   Prefix:       glc - OpenGL Core
5   Beschreibung: diese Unit enthält eine Klassen-Kapselung für OpenGL Array Buffer
6   Beispiel:
7     type
8       TVertex = packed record
9         pos: TgluVector3f; // vertex position
10         tex: TgluVector2f; // texture coordinates
11         nor: TgluVector3f; // normal
12       end;
13       PVertex = ^TVertex;
14
15     var
16       vBuffer: TglcArrayBuffer;
17       iBuffer: TglcArrayBuffer;
18       p: Pointer;
19
20     vBuffer := TglcArrayBuffer.Create(TglcBufferTarget.btArrayBuffer);
21     iBuffer := TglcArrayBuffer.Create(TglcBufferTarget.btElementArrayBuffer);
22     try
23       // write vertex data to vertex buffer
24       vBuffer.Bind;
25       vBuffer.BufferData(4, SizeOf(TresMeshVertex), TglcBufferUsage.buStaticDraw, nil);
26       p := vBuffer.MapBuffer(TglcBufferAccess.baWriteOnly);
27       try
28         PVertex(p).pos := gluVertex3f(0.0, 0.0, 0.0);
29         PVertex(p).tex := gluVertex2f(0.0, 0.5);
30         PVertex(p).nor := gluVertex3f(0.0, 1.0, 0.0);
31         inc(p, SizeOf(TVertex));
32         // ... 
33       finally
34         vBuffer.UnmapBuffer;
35         vBuffer.Unbind;
36       end;
37
38       // write indices to index buffer 
39       iBuffer.Bind;
40       iBuffer.BufferData(4, SizeOf(GLuint), TglcBufferUsage.buStaticDraw, nil);
41       p := iBuffer.MapBuffer(TglcBufferAccess.baWriteOnly);
42       try
43         PGLuint(p) := 0;
44         //  ...
45       finally
46         iBuffer.UnmapBuffer;
47         iBuffer.Unbind;
48       end;
49
50       // use array buffers to draw primitive
51       vBuffer.Bind;
52       iBuffer.Bind;
53
54       glEnableClientState(GL_VERTEX_ARRAY);
55       glVertexPointer(3, GL_FLOAT, 8, Pointer(0));
56
57       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
58       glTexCoordPointer(2, GL_FLOAT, 8, Pointer(3));
59
60       glEnableClientState(GL_NORMAL_ARRAY);
61       glNormalPointer(GL_FLOAT, 8, Pointer(5));
62
63       glEnableClientState(GL_INDEX_ARRAY);
64       glIndexPointer(GL_INT, 0, nil);
65
66       glDrawElements(GL_QUADS, iBuffer.DataCount, GL_UNSIGNED_INT, nil);
67
68       glDisableClientState(GL_INDEX_ARRAY);
69       glDisableClientState(GL_VERTEX_ARRAY);
70       glDisableClientState(GL_TEXTURE_COORD_ARRAY);
71       glDisableClientState(GL_NORMAL_ARRAY);
72
73       fIndexBuffer.Unbind;
74       fVertexBuffer.Unbind;
75     finally
76       FreeAndNil(vBuffer);
77       FreeAndNil(iBuffer);
78     end; }
79
80 {$mode objfpc}{$H+}
81
82 interface
83
84 uses
85   {$IFNDEF OPENGL_ES}dglOpenGL{$ELSE}dglOpenGLES{$ENDIF}, sysutils, uglcTypes;
86
87 type
88   EglcArrayBuffer = class(Exception);
89   TglcArrayBuffer = class(TObject)
90   private
91     fID: GLuint;
92     fTarget: TglcBufferTarget;
93     fUsage: TglcBufferUsage;
94   protected
95     fDataCount: Integer;
96     fDataSize: Integer;
97   public
98     property ID:        gluInt           read fID;
99     property Target:    TglcBufferTarget read fTarget;
100     property Usage:     TglcBufferUsage  read fUsage;
101     property DataCount: Integer          read fDataCount;
102     property DataSize:  Integer          read fDataSize;
103
104     procedure BufferData(const aDataCount, aDataSize: Cardinal; const aUsage: TglcBufferUsage; const aData: Pointer);
105     function MapBuffer(const aAccess: TglcBufferAccess): Pointer;
106     function MapBufferRange(const aOffset: GLintptr; const aSize: GLsizeiptr; const aAccess: TglcBufferAccess): Pointer;
107     procedure UnmapBuffer;
108     procedure Bind;
109     procedure Unbind;
110     constructor Create(const aTarget: TglcBufferTarget);
111     destructor Destroy; override;
112   end;
113
114 implementation
115
116 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
117 //TglcArrayBuffer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
119 procedure TglcArrayBuffer.BufferData(const aDataCount, aDataSize: Cardinal; const aUsage: TglcBufferUsage; const aData: Pointer);
120 begin
121   glGetError(); //clear Errors
122   Bind;
123   fDataCount := aDataCount;
124   fDataSize  := aDataSize;
125   fUsage     := aUsage;
126   glBufferData(GLenum(fTarget), fDataCount * fDataSize, aData, GLenum(fUsage));
127   glcCheckAndRaiseError;
128 end;
129
130 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
131 function TglcArrayBuffer.MapBuffer(const aAccess: TglcBufferAccess): Pointer;
132 begin
133   glGetError();
134   result := nil;
135   if (fDataCount * fDataSize) <= 0 then
136     exit;
137 {$IFNDEF OPENGL_ES}
138   result := glMapBuffer(GLenum(fTarget), GLenum(aAccess));
139 {$ELSE}
140   if GL_OES_mapbuffer then
141     result := glMapBufferOES(GLenum(fTarget), GLenum(aAccess))
142   else
143     raise EglcArrayBuffer.Create('map buffer is not supported by video card');
144 {$ENDIF}
145   glcCheckAndRaiseError;
146 end;
147
148 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
149 function TglcArrayBuffer.MapBufferRange(const aOffset: GLintptr; const aSize: GLsizeiptr; const aAccess: TglcBufferAccess): Pointer;
150 begin
151   {$IFNDEF OPENGL_ES}
152   if not (GL_ARB_map_buffer_range or GL_VERSION_3_0) then
153     raise EglcArrayBuffer.Create('map buffer range is not supported by video card');
154   result := glMapBufferRange(GLenum(fTarget), aOffset, aSize, GLenum(aAccess));
155   {$ELSE}
156   if GL_VERSION_3_0 then
157     result := glMapBufferRange(GLenum(fTarget), aOffset, aSize, GLenum(aAccess))
158   else if GL_EXT_map_buffer_range then
159     result := glMapBufferRangeEXT(GLenum(fTarget), aOffset, aSize, GLenum(aAccess))
160   else
161     raise EglcArrayBuffer.Create('map buffer range is not supported by video card');
162   {$ENDIF}
163 end;
164
165 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
166 procedure TglcArrayBuffer.UnmapBuffer;
167 begin
168 {$IFNDEF OPENGL_ES}
169   glUnmapBuffer(GLenum(fTarget));
170 {$ELSE}
171   if GL_VERSION_3_0 then
172     glUnmapBuffer(GLenum(fTarget))
173   else if GL_OES_mapbuffer then
174     glUnmapBufferOES(GLenum(fTarget))
175   else
176     raise EglcArrayBuffer.Create('unmap buffer is not supported by video card');
177 {$ENDIF}
178 end;
179
180 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
181 procedure TglcArrayBuffer.Bind;
182 begin
183   glBindBuffer(GLenum(fTarget), fID);
184 end;
185
186 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
187 procedure TglcArrayBuffer.Unbind;
188 begin
189   glBindBuffer(GLenum(fTarget), 0);
190 end;
191
192 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
193 constructor TglcArrayBuffer.Create(const aTarget: TglcBufferTarget);
194 begin
195 {$IFNDEF OPENGL_ES}
196   if not (GL_ARB_Vertex_Buffer_Object or GL_VERSION_2_0) then
197     raise EglcArrayBuffer.Create('Create - VertexBuffer: not supported');
198 {$ELSE}
199   if not GL_VERSION_2_0 then
200     raise EglcArrayBuffer.Create('Create - VertexBuffer: not supported');
201 {$ENDIF}
202   glGetError();
203   inherited Create;
204   glGenBuffers(1, @fID);
205   fDataCount   := 0;
206   fDataSize    := 0;
207   fTarget      := aTarget;
208   glcCheckAndRaiseError;
209 end;
210
211 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
212 destructor TglcArrayBuffer.Destroy;
213 begin
214   glDeleteBuffers(1, @fID);
215   inherited Destroy;
216 end;
217
218 end.
219