87814e6b94a5de7a6f614a9d69f036cf0050c91a
[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 not GL_OES_mapbuffer then
141     raise EglcArrayBuffer.Create('map buffer is not supported by video card');
142   result := glMapBufferOES(GLenum(fTarget), GLenum(aAccess));
143 {$ENDIF}
144   glcCheckAndRaiseError;
145 end;
146
147 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
148 function TglcArrayBuffer.MapBufferRange(const aOffset: GLintptr; const aSize: GLsizeiptr; const aAccess: TglcBufferAccess): Pointer;
149 begin
150   {$IFNDEF OPENGL_ES}
151   if not (GL_ARB_map_buffer_range or GL_VERSION_3_0) then
152     raise EglcArrayBuffer.Create('map buffer range is not supported by video card');
153   result := glMapBufferRange(GLenum(fTarget), aOffset, aSize, GLenum(aAccess));
154   {$ELSE}
155   if not GL_VERSION_3_0 then
156     raise EglcArrayBuffer.Create('map buffer range is not supported by video card');
157   result := glMapBufferRange(GLenum(fTarget), aOffset, aSize, GLenum(aAccess));
158   {$ENDIF}
159 end;
160
161 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
162 procedure TglcArrayBuffer.UnmapBuffer;
163 begin
164 {$IFNDEF OPENGL_ES}
165   glUnmapBuffer(GLenum(fTarget));
166 {$ELSE}
167   if not (GL_OES_mapbuffer or GL_VERSION_3_0) then
168     raise EglcArrayBuffer.Create('unmap buffer is not supported by video card');
169   glUnmapBuffer(GLenum(fTarget));
170 {$ENDIF}
171 end;
172
173 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
174 procedure TglcArrayBuffer.Bind;
175 begin
176   glBindBuffer(GLenum(fTarget), fID);
177 end;
178
179 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
180 procedure TglcArrayBuffer.Unbind;
181 begin
182   glBindBuffer(GLenum(fTarget), 0);
183 end;
184
185 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
186 constructor TglcArrayBuffer.Create(const aTarget: TglcBufferTarget);
187 begin
188 {$IFNDEF OPENGL_ES}
189   if not (GL_ARB_Vertex_Buffer_Object or GL_VERSION_2_0) then
190     raise EglcArrayBuffer.Create('Create - VertexBuffer: not supported');
191 {$ELSE}
192   if not GL_VERSION_2_0 then
193     raise EglcArrayBuffer.Create('Create - VertexBuffer: not supported');
194 {$ENDIF}
195   inherited Create;
196   glGenBuffers(1, @fID);
197   fDataCount   := 0;
198   fDataSize    := 0;
199   fTarget      := aTarget;
200   glcCheckAndRaiseError;
201 end;
202
203 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////[c]
204 destructor TglcArrayBuffer.Destroy;
205 begin
206   glDeleteBuffers(1, @fID);
207   inherited Destroy;
208 end;
209
210 end.
211