00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Mark Alexander 00008 * Side Effects 00009 * 123 Front Street West, Suite 1401 00010 * Toronto, Ontario 00011 * Canada M5J 2M2 00012 * 416-504-9876 00013 * 00014 * NAME: RE_OGLBufferObject.h ( RE Library, C++) 00015 * 00016 * COMMENTS: 00017 * Buffer objects are merely registered chunks of memory that is 00018 * managed by the graphics driver. Although the come in different 00019 * flavours, they are all created and accessed in the same way. 00020 * 00021 * One buffer object represents one type of data - texture coords, 00022 * point positions, pixels or colors. There are two main types in terms 00023 * of usage, vertex and pixel buffers. 00024 * 00025 * 1. Vertex-oriented buffers are used in lieu of glVertex, glNormal, 00026 * glColor, etc.. They are much more efficient in that you can send 00027 * a lot of data with one call, and you can update parts of the 00028 * list instead of rewriting the entire list. They are used in 00029 * conjunction with glDrawArrays() to create geometry. As an example: 00030 * 00031 * RE_OGLVertexBuffer vBuf(nVertices); 00032 * RE_OGLVertexBuffer texBuf(nVertices, 0); // 0 = gl_TexCoord[0] 00033 * 00034 * vBuf.setData(vertex_list); 00035 * texBuf.setData(tex_coord_list); // you can free the lists after this 00036 * 00037 * vBuf.enable(); 00038 * texBuf.enable(); 00039 * 00040 * r->getExt()->glDrawArraysEXT(GL_TRIANGLES, 0, nVertices); 00041 * 00042 * vBuf.disable(); 00043 * texBuf.disable(); 00044 * 00045 * The data is always assumed to be interleaved (xyzxyz...) 00046 * 00047 * 2. Pixel buffers are used to write and rewrite pixel data to a GL structure 00048 * (normally a texture). In this case, there use is slighly different. 00049 * Instead of passing the image data directly to glTexImage...(), you 00050 * pass NULL and instead enable the pixel buffer first. Ex: 00051 * 00052 * RE_OGLPixelWriteBuffer pBuf(xres, yres); 00053 * 00054 * pBuf.setFormat(RE_GPU_UINT8, 4); 00055 * pBuf.setData( image_data ); 00056 * pBuf.enable(); 00057 * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xres, yres, 0, 00058 * GL_UNSIGNED_BYTE, GL_RGBA, NULL); 00059 * pBuf.disable(); 00060 * 00061 * After that, you can change the texture (or a portion of the texture) 00062 * by calling setData() again. 00063 * 00064 * You can also use a pixel buffer as a target for reading data back from 00065 * the GPU (via glReadPixels(), glGetTexImage(), etc). 00066 * 00067 * RE_OGLPixelReadBuffer pBuf(xres, yres); 00068 * 00069 * pBuf.enable(); 00070 * glReadPixels(0,0, xres, yres, GL_RGB, GL_UNSIGNED_BYTE, NULL); 00071 * pBuf.disable(); 00072 * 00073 * ptr = pBug.getData(); 00074 * 00075 * This allows you to do asynchronous reads. The glReadPixels() starts the 00076 * DMA transfer, but does not wait - the getData() does. 00077 * 00078 * Finally, the various types of buffer objects, and their default settings, 00079 * are: 00080 * 00081 * Vertex: 00082 * RE_OGLVertexBuffer vertex position 3 fp32 00083 * RE_OGLColorBuffer vertex color 3 fp32 00084 * RE_OGLNormalBuffer vertex normal 3 fp32 00085 * RE_OGLTexCoordBuffer vertex texture coords 2 fp32 00086 * 00087 * Pixel: 00088 * RE_OGLPixelReadBuffer read pixels from GPU 3 uint8 00089 * RE_OGLPixelWriteBuffer vertex position 3 uint8 00090 */ 00091 #ifndef RE_OGLBufferObject_H 00092 #define RE_OGLBufferObject_H 00093 00094 #include "RE_API.h" 00095 #include "RE_Types.h" 00096 00097 class RE_Render; 00098 00099 class RE_API RE_OGLBufferObject 00100 { 00101 public: 00102 // Alternatively, you can use the convenience classes listed below. 00103 enum RE_BufferObjectType 00104 { 00105 VERTEX, 00106 NORMAL, 00107 COLOR, 00108 TEXTURE_COORD, 00109 ELEMENT, 00110 00111 PIXEL_WRITE, 00112 PIXEL_READ 00113 }; 00114 00115 RE_OGLBufferObject(RE_BufferObjectType type, int num_elements); 00116 virtual ~RE_OGLBufferObject(); 00117 00118 enum RE_UsageHint 00119 { 00120 // passing data to GPU only. 00121 WRITE_ONCE, 00122 WRITE_FREQUENT, 00123 WRITE_STREAM, // once per redraw. 00124 00125 // reading data from GPU only. 00126 READ_ONCE, 00127 READ_FREQUENT, 00128 READ_STREAM, 00129 00130 // read and write (ex: rendering to a vertex list to use as geo) 00131 READ_WRITE_ONCE, 00132 READ_WRITE_FREQUENT, 00133 READ_WRITE_STREAM 00134 }; 00135 00136 // 1. Set up the buffer data type and number of elements in the buffer. 00137 // Matrix types are not supported. 00138 // 'elements' is the number of data types in the buffer, not bytes (so 00139 // for a list of 20 fp32 vec3's, pass 20, not 60 or 240). 00140 00141 void setFormat(RE_GPUType type, int vectorsize); 00142 void setNumElements(int numelems); 00143 00144 // You can optionally give GL a hint how you'll be using the data. 00145 // Hints are set reasonably for the convenience classes below. This also 00146 // affects the read/write status of mapData(). 00147 void setUsage(RE_UsageHint hint); 00148 00149 // 2. Fill in the data 00150 // if sublen == 0, the full size is used. Otherwise, you can update 00151 // portions of the array. Passing NULL frees the buffer. 00152 void setData(RE_Render *r, const void *data, 00153 int offset = 0, int sublen = 0); 00154 00155 // 3. Enable the buffer for use 00156 // (all NULL data pointers for the appropriate type refer to this buffer) 00157 virtual void enable(RE_Render *r); 00158 00159 // 4. Disable the buffer once you're done drawing. 00160 virtual void disable(RE_Render *r); 00161 00162 00163 // If you want to write or read directly from the memory chunk, 00164 // this returns a pointer to the data. You must upmap it when you're done. 00165 // Do NOT delete this pointer - it is owned by the graphics driver. 00166 void *mapData(RE_Render *r); 00167 void unmapData(RE_Render *r); 00168 00169 // This is a convenience method that will draw the object with all 00170 // currently enabled buffer objects (you only need to call this on one of 00171 // the buffers, if multiple buffers are enabled). 'gltype' is the GL 00172 // primitive you want to draw (GL_LINES, GL_TRIANGLE_STRIP, GL_QUADS, etc) 00173 void drawObject(RE_Render *r, int gltype); 00174 00175 // This is a convenience method that will draw objects using randomly 00176 // selected elements from the array. 00177 void drawElements(RE_Render *r, int gltype, 00178 int num, const unsigned int *elements); 00179 00180 static bool hasVertexBufferSupport(RE_Render *r); 00181 static bool hasPixelBufferSupport(RE_Render *r); 00182 00183 private: 00184 RE_BufferObjectType myObjectType; 00185 GLenum myDataType; 00186 int myVectorSize; 00187 int myNumElements; 00188 GLenum myStreamType; 00189 GLuint myBufferID; 00190 GLenum myBufferType; 00191 bool myBoundFlag; 00192 bool myEnableFlag; 00193 }; 00194 00195 00196 // A vertex buffer stores the positions for a vertex list. 00197 // Data type defaults to 3 32bit floats. 00198 class RE_API RE_OGLVertexBuffer : public RE_OGLBufferObject 00199 { 00200 public: 00201 RE_OGLVertexBuffer(int num_vertex = 0) 00202 : RE_OGLBufferObject(VERTEX, num_vertex) 00203 {} 00204 }; 00205 00206 // A color buffer stores the vertex colors for a vertex list. 00207 // Data type defaults to 3 32bit floats. 00208 class RE_API RE_OGLColorBuffer : public RE_OGLBufferObject 00209 { 00210 public: 00211 RE_OGLColorBuffer(int num_vertex = 0) 00212 : RE_OGLBufferObject(COLOR, num_vertex) 00213 {} 00214 }; 00215 00216 // A normal buffer stores the vertex normals for a vertex list. 00217 // Data type defaults to 3 32bit floats. 00218 class RE_API RE_OGLNormalBuffer : public RE_OGLBufferObject 00219 { 00220 public: 00221 RE_OGLNormalBuffer(int num_vertex = 0) 00222 : RE_OGLBufferObject(NORMAL, num_vertex) 00223 {} 00224 }; 00225 00226 // A normal buffer stores the vertex normals for a vertex list. 00227 // Data type defaults to 2 32bit floats. 00228 class RE_API RE_OGLTexCoordBuffer : public RE_OGLBufferObject 00229 { 00230 public: 00231 RE_OGLTexCoordBuffer(int num_vertex = 0, int multitexture_level = 0) 00232 : RE_OGLBufferObject(TEXTURE_COORD, num_vertex), 00233 myMultiTextureLevel(multitexture_level) 00234 { 00235 setFormat(RE_GPU_FLOAT32, 2); 00236 } 00237 00238 virtual void enable(RE_Render *r); 00239 virtual void disable(RE_Render *r); 00240 00241 private: 00242 int myMultiTextureLevel; 00243 }; 00244 00245 00246 class RE_API RE_OGLElementBuffer : public RE_OGLBufferObject 00247 { 00248 public: 00249 RE_OGLElementBuffer(int num = 0) 00250 : RE_OGLBufferObject(ELEMENT, num) 00251 { 00252 setFormat(RE_GPU_UINT32, 1); 00253 } 00254 }; 00255 00256 00257 00258 // A pixel read buffer is used to read data back from the GPU. 00259 // Data type defaults to 3 8bit ints. 00260 class RE_API RE_OGLPixelReadBuffer : public RE_OGLBufferObject 00261 { 00262 public: 00263 RE_OGLPixelReadBuffer(int xres = 0, int yres = 1) 00264 : RE_OGLBufferObject(PIXEL_READ, xres * yres) 00265 { 00266 setFormat(RE_GPU_UINT8, 4); 00267 setUsage(READ_ONCE); 00268 } 00269 }; 00270 00271 // A pixel write buffer is used to write data to the GPU. 00272 // Data type defaults to 3 8bit ints. 00273 class RE_API RE_OGLPixelWriteBuffer : public RE_OGLBufferObject 00274 { 00275 public: 00276 RE_OGLPixelWriteBuffer(int xres = 0, int yres = 1) 00277 : RE_OGLBufferObject(PIXEL_WRITE, xres * yres) 00278 { 00279 setFormat(RE_GPU_UINT8, 4); 00280 } 00281 }; 00282 00283 #endif
1.5.9