I would like to render image in OpenGL ES, pixel by pixel. I want to do it this way because I plan to move those pixels over time to create various effect.
For performance and design reasons I decided to use only every other pixel in both directions (thus reducing their number to one quarter)
I have only very basic understanding of opengl, so I am probably missing some key knowledge to achieve this.
What is the best way to achieve this? Do I have to really render it pixel by pixel? Or can I somehow create texture out of array of pixels?
I would like to make this work on as much devices as possible (so OpenGL ES 1.1 solution is preffered, but if it is not possible or it would be really inconvenient or slow, 2.0 can be used)
I tried to do this using VBO with mixed results. I am not sure I have done it properly, because there are some problems (and it is very slow). Here is my code:
Initialization:
glGenBuffers(1, &pointsVBO);
glBindBuffer(GL_ARRAY_BUFFER, pointsVBO);
glBufferData(GL_ARRAY_BUFFER, 160*240*sizeof(Vertex), 0, GL_DYNAMIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
Rendering:
- (void)renderPoints:(ImagePixel**)imagePixels {
int count = 160 * 240;
for(int i = 0; i < count; ++i) {
vertices[i].v[0] = imagePixels[i]->positionX;
vertices[i].v[1] = imagePixels[i]->positionY;
vertices[i].color[0] = imagePixels[i]->red;
vertices[i].color[1] = imagePixels[i]->green;
vertices[i].color[2] = imagePixels[i]->blue;
vertices[i].color[3] = 1;
}
glVertexPointer(2, GL_FLOAT, sizeof(Vertex), vertices[0].v);
glColorPointer(4, GL_FLOAT, sizeof(Vertex), vertices[0].color);
// update vbo
GLvoid *vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
memcpy(vbo_buffer, vertices, count * sizeof(Vertex));
glUnmapBufferOES(GL_ARRAY_BUFFER);
// draw contents of vbo
glDrawArrays(GL_POINTS, 0, count);
}
Vertex struct:
typedef struct Vertex
{
float v[2];
float color[4];
} Vertex;
imagePixels array is filled with data from image.
When I do this, I get most of my image but I am missing few last rows and I can see some random pixels around the screen. Is it possible that I hit some limit in drawArrays that uses only portion of data?
Second problem is, that points in second half of columns aren't aligned properly. I guess this is caused by rounding errors in float math when computing position during rendering itself (supplied coordinates are all multiples of 2). Is there any way how to prevent this? I need all points to be aligned in proper grid.
I will provide you with screenshot as soon as I get my iphone back
If you really are wanting to manipulate every pixel, you should probably just use a single full-screen quad in OpenGL and update its texture each frame.
You can create a texture out of a bitmap array of pixels using glTexImage2D.
Related
I'm currently working on an iOS game where, long story short, I need to draw a lot of moving cubes - approximate maximum of 200 per frame. Emphasis on moving because yes, I have indeed Googled away for hours on this topic and have yet to find a suitable solution for fast, efficient drawing of multiple objects where their position updates every frame.
Through my endless amounts of research on this subject most seem to mention VBOs, however I'm not sure this would suit my case where the position of every object changes every frame.
I'm using OpenGL 1 at the moment - I have working code and on generation 3/4+ devices (the ones which support OpenGL 2, ha) it runs at a reasonable framerate - however when testing on my (old, yes) 2nd-gen iPod touch, it is very sluggish and essentially unplayable.
My code comprises of a static array of vertices for a 'cube' and an array containing the position and colour of every cube. My game logic loop updates the position of every cube in the array. At the moment I'm looping through the cube array, calling glTranslatef and glDrawArrays for every cube. From what I've read this is very inefficient, however I'm completely confused as to how you would optimise it. Any ideas?
(maybe I shouldn't be aiming for old, discontinued iOS devices but given my belief that my code is incredibly inefficient, I figure it'll help my future endeavours regardless if I find a way to address this)
For such simple objects I would make one big VBO say 200 Objects * NrVerticesPerCube, put all the data interleaved Vertex,Normal,UV,Vertex,Normal,UV, etc.
I do something similar in a keyframe animation of a beaver in my game, I start with something like this:
glGenBuffers(1, &vboObjects[vboGroupBeaver]);
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
glBufferData(GL_ARRAY_BUFFER, beaverVerts*8*sizeof(GLfloat), 0, GL_STATIC_DRAW);
vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
NSString *path;
path = [[NSBundle mainBundle] pathForResource:#"beaver01" ofType:#"bin"];
NSFileHandle *model = [NSFileHandle fileHandleForReadingAtPath:path];
float vertice[8];
int counter = 0;
while (read([model fileDescriptor], &vertice, 8*sizeof(float))) {
memcpy(vbo_buffer, vertice, 8*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
counter++;
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
This creates my VBO buffer with the correct size (in this case 8 * sizeof(GLfloat) wich is 3 Verts, 3 Normals and 2UV), and copies the first keyframe to the buffer, you could do the same with you initial object positions, or just leave that and compute latter...
Then in each frame I do interpolation between 2 keyframes for each vertex of my beaver, and just make one draw call, this is very fast for the 4029 vertices my beaver has, and works at 60FPS on my iPhone 3G.
For you doing only gltranslates it would be even simpler, just add the values of x,y,z to each vertice of each cube.
You would update it like this:
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[vboGroupBeaver]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
Bind the vbo buffer and mapit to a buffer var.
Calculate the stuff you want on a temp var.
memcpy(vbo_buffer, currentVert, 6*sizeof(GLfloat)); // 0
vbo_buffer += 8*sizeof(GLfloat);
Copy it and update buffer to next object, repeat until all objects updated...
You could also do all the updates in a seperate array and copy the whole array, but then you would be copying extra info that usually doesn't change (normals and UV). Or you could not use interleaved data and copy that...
glUnmapBufferOES(GL_ARRAY_BUFFER);
Unmap the VBO buffer
glVertexPointer(3, GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, 8*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,8*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLES, 0, beaverVerts);
Setup your draw call, and draw it all...
If you need to rotate objects and not just gltranslate them, you will need to add some matrix multiplications along the way...
EDIT **
ok, making a gltranste by hand is actually very easy (rotation, etc is a bit trickier).
I'm using a an interleaved plane drawed using TRIANGLE_STRIP instead of triangles, but the principle is the same.
float beltInter[] = {
0.0, 0.0, 0.0, // vertices[0]
0.0, 0.0, 1.0, // Normals [0]
6.0, 1.0, // UV [0]
0.0, 480, 0.0, // vertices[1]
0.0, 0.0, 1.0, // Normals [1]
0.0, 1.0, // UV [1]
320.0, 0.0, 0.0, // vertices[2]
0.0, 0.0, 1.0, // Normals [2]
6.0, 0.0, // UV [2]
320.0, 480, 0.0, // vertices[3]
0.0, 0.0, 1.0, // Normals [3]
0.0, 0.0 // UV [3]
};
So this is interleaved vertex, you got vertex then Normals then UV, if you're not using textures substitute UV for color.
The easiest way is to have an array with all the objects inside (made easy if all your objects are the same size) and make the position updates after draw (instead of in the middle of the opengl frame), better still make a seperate thread, create 2 VBOs update one of them while drawing from the other, something like this:
Thread 1 OpenGL DrawFrom VBO0
Thread 2 Game Updates, update positions on internal array and copy to VBO1, set Var saying VBO1 yes ready (so thread 1 only changes from drawing to VBO1 when all the updates are done).
Thread 1 OpenGL DrawFrom VBO1
Thread 2 Game update, same thing but update VBO0
continue with same logic
this is called double buffering and you use it to garanty stability, without this sometimes your game logic will be updating the VBO while the graphics card needs it and the graphics card will have to wait, resulting in lower FPS.
Anyway, back on topic
to make the equivalent to gltranslatef(10,20,30) just do:
int maxvertices = 4;
float x = 10;
float y = 20;
float z = 30;
int counter = 0;
int stride = 8; // stride is 8 = 3 x vertice + 3 x normal + 2 x UV change to 3 x color or 4 x color depending on your needs
glBindBuffer(GL_ARRAY_BUFFER, vboObjects[myObjects]);
GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES);
while (counter < (maxVertices*8)) {
beltInter[counter] += x; // just sum the corresponding values to each
beltInter[counter+1] += y;
beltInter[counter+2] += z;
memcpy(vbo_buffer, currentVert, 3*sizeof(GLfloat)); // again only copy what you need, in this case only copying the vertices, if your're updating all the data, you can just do a single memcpy at the end instead of these partial ones
vbo_buffer += stride*sizeof(GLfloat); // forward the buffer
counter += stride; // only update the vertex, but you could update everything
}
glUnmapBufferOES(GL_ARRAY_BUFFER);
glVertexPointer(3, GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL));
glNormalPointer(GL_FLOAT, stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+3*sizeof(GLfloat)));
glTexCoordPointer(2, GL_FLOAT,stride*sizeof(GLfloat), (GLvoid*)((char*)NULL+6*sizeof(GLfloat)));
glDrawArrays(GL_TRIANGLE_STRIP, 0, maxVertices);
Of course the update values doesn't have to be the same for all the objects, infact using a base array like this you can update all the info as you go along and just have the routine to copy it to VBO when needed.
All this was written from memory on the fly, so there maybe dragons :-)
Hope that helps.
You could optimise quite a bit by sticking all the coords for all your cubes in a single array, and drawing it with a single glDrawArrays call.
I'm not sure why you'd want to split up the cubes into separate arrays, except maybe because it makes your data structure more elegant/object oriented, but that's the first place I'd look at making an improvement.
Dump the cube coordinates in one big array, and give each cube object an index into that array so that you can still keep your update logic fairly compartmentalised (as in, cube n owns the coordinates in the range x to y and is responsible for updating them, but when you actually draw the coordinates you run glDrawArrays directly on the centralised coord array instead of looping through the cube objects and rendering them individually).
I would appreciate some help with the following. I'm trying to render a ring shape on top of another object in OpenGL ES 1.1 for an iPhone game. The ring is essentially the difference between two circles.
I have a graphic prepared for the ring itself, which is transparent in the centre.
I had hoped to just create a circle, and apply the texture to that. The texture is a picture of the ring that occupies the full size of the texture (i.e. the outside of the ring touches the four sides of the texture). The centre of the ring is transparent in the graphic being used.
It needs to be transparent in the centre to let the object underneath show through. The ring is rendering correctly, but is a solid black mass in the centre, not transparent. I'd appreciate any help to solve this.
Code that I'm using to render the circle is as follows (not optimised at all: I will move the coords in proper buffers etc for later code, but I have written it this way to just try and get it working...)
if (!m_circleEffects.empty())
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
int segments = 360;
for (int i = 0; i < m_circleEffects.size(); i++)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(m_circleEffects[i].position.x, m_circleEffects[i].position.y, 0);
glBindTexture(GL_TEXTURE_2D, m_Texture);
float radius = 1.764706;
GLfloat circlePoints[segments * 3];
GLfloat textureCoords[segments * 2];
int circCount = 3;
int texCount = 2;
for (GLfloat i = 0; i < 360.0f; i += (360.0f / segments))
{
GLfloat pos1 = cosf(i * M_PI / 180);
GLfloat pos2 = sinf(i * M_PI / 180);
circlePoints[circCount] = pos1 * radius;
circlePoints[circCount+1] = pos2 * radius;
circlePoints[circCount+2] = (float)z + 5.0f;
circCount += 3;
textureCoords[texCount] = pos1 * 0.5 + 0.5;
textureCoords[texCount+1] = pos2 * 0.5 + 0.5;
texCount += 2;
}
glVertexPointer(3, GL_FLOAT, 0, circlePoints);
glTexCoordPointer(2, GL_FLOAT, 0, textureCoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, segments);
}
m_circleEffects.clear();
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
I've been experimenting with trying to create a ring rather than a circle, but I haven't been able to get this right yet.
I guess that the best approach is actually to not create a circle, but a ring, and then get the equivalent texture coordinates as well. I'm still experimenting with the width of the ring, but, it is likely that the radius of the ring is 1/4 width of the total circle.
Still a noob at OpenGL and trying to wrap my head around it. Thanks in advance for any pointers / snippets that might help.
Thanks.
What you need to do is use alpha blending, which blends colors into each other based on their alpha values (which you say are zero in the texture center, meaning transparent). So you have to enable blending by:
glEnable(GL_BLEND);
and set the standard blending functions for using a color's alpha component as opacity:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
But always keep in mind in order to see the transparent object correctly blended over the object behind, you need to render your objects in back to front order.
But if you only use the alpha as a object/no-object indicator (only values of either 0 or 1) and don't need partially transparent colors (like glass, for example), you don't need to sort your objects. In this case you should use the alpha test to discard fragments based on their alpha values, so that they don't pollute the depth-buffer and prevent the behind lying object from being rendered. An alpha test set with
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
will only render fragments (~pixels) that have an alpha of more than 0.5 and will completely discard all other fragments. If you only have alpha values of 0 (no object) or 1 (object), this is exactly what you need and in this case you don't actually need to enable blending or even sort your objects back to front.
I have particles that I want to be able to change the color of in code, so any color can be used. So I have only one texture that basically has luminance.
I've been using glColor4f(1f, 0f, 0f, 1f); to apply the color.
Every blendfunc I've tried that has come close to working ends up like the last picture below. I still want to preserve luminance, like in the middle picture. (This is like the Overlay or Soft Light filters in Photoshop, if the color layer was on top of the texture layer.)
Any ideas for how to do this without programmable shaders? Also, since these are particles, I don't want a black box behind it, I want it to add onto the scene.
Here is a solution that might be close to what you're looking for:
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
glActiveTexture( GL_TEXTURE0 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glActiveTexture( GL_TEXTURE1 );
glEnable( GL_TEXTURE_2D );
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
What it does is multiply the original texture by the specified color and then adds the pixels values of the original texture on top:
final_color.rgba = original_color.rgba * color.rgba + original_color.rgba;
This will result in a brighter image than what you've asked for but might be good enough with some tweaking.
Should you want to preserve the alpha value of the texture, you'll need to use GL_COMBINE instead of GL_ADD (+ set GL_COMBINE_RGB and GL_COMBINE_ALPHA properly).
Here are some results using this technique on your texture.
NONSENSE! You don't have to use multi-texturing. Just premultiply your alpha.
If you premultiply alpha on the image after you load it in and before you create the GL texture for it then you only need one texture unit for the GL_ADD texture env mode.
If you're on iOS then Apple's libs can premultiply for you. See the example Texture2D class and look for the kCGImageAlphaPremultipliedLast flag.
If you're not using an image loader that supports premultiply then you have to do it manually after loading the image. Pseudo code:
uint8* LoadRGBAImage(const char* pImageFileName) {
Image* pImage = LoadImageData(pImageFileName);
if (pImage->eFormat != FORMAT_RGBA)
return NULL;
// allocate a buffer to store the pre-multiply result
// NOTE that in a real scenario you'll want to pad pDstData to a power-of-2
uint8* pDstData = (uint8*)malloc(pImage->rows * pImage->cols * 4);
uint8* pSrcData = pImage->pBitmapBytes;
uint32 bytesPerRow = pImage->cols * 4;
for (uint32 y = 0; y < pImage->rows; ++y) {
byte* pSrc = pSrcData + y * bytesPerRow;
byte* pDst = pDstData + y * bytesPerRow;
for (uint32 x = 0; x < pImage->cols; ++x) {
// modulate src rgb channels with alpha channel
// store result in dst rgb channels
uint8 srcAlpha = pSrc[3];
*pDst++ = Modulate(*pSrc++, srcAlpha);
*pDst++ = Modulate(*pSrc++, srcAlpha);
*pDst++ = Modulate(*pSrc++, srcAlpha);
// copy src alpha channel directly to dst alpha channel
*pDst++ = *pSrc++;
}
}
// don't forget to free() the pointer!
return pDstData;
}
uint8 Modulate(uint8 u, uint8 uControl) {
// fixed-point multiply the value u with uControl and return the result
return ((uint16)u * ((uint16)uControl + 1)) >> 8;
}
Personally, I'm using libpng and premultiplying manually.
Anyway, after you premultiply, just bind the byte data as an RGBA OpenGL texture. Using glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); with a single texture unit should be all you need after that. You should get exactly (or pretty damn close) to what you want. You might have to use glBlendFunc(GL_SRC_ALPHA, GL_ONE); as well if you really want to make the thing look shiny btw.
This is subtly different from the Ozirus method. He's never "reducing" the RGB values of the texture by premultiplying, so the RGB channels get added too much and look sort of washed out/overly bright.
I suppose the premultiply method is more akin to Overlay whereas the Ozirus method is Soft Light.
For more, see:
http://en.wikipedia.org/wiki/Alpha_compositing
Search for "premultiplied alpha"
I working on a spinning 3D cube (glFrustumf setup) and it multiplies the current matrix by the previous one so that the cube continues to spin. See below
/* save current rotation state */
GLfloat matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
/* re-center cube, apply new rotation */
glLoadIdentity();
glRotatef(self.angle, self.dy,self.dx,0);
glMultMatrixf(matrix);
The problem is I need to step back from this (as if I had a camera).
I tried to edit the matrix and that kind of works but picks up noise. The cube jumps around.
matrix[14] = -5.0;
matrix[13] = 0;
matrix[12] =0;
Is there a way to edit the current Modelview Matrix so that I can set the position of the cube with multiplying it by another matrix?
You should not mistreat OpenGL as a scene graph, nor a math library. That means: Don't read back the matrix, and multiply it arbitrarily back. Instead rebuild the whole matrix stack a new every time you do a render pass. I think I should point out, that in OpenGL-4 all the matrix functions have been removed. Instead you're expected to supply the matrices as uniforms.
EDIT due to comment by #Burf2000:
Your typical render handler will look something like this (pseudocode):
draw_object():
# bind VBO or plain VertexArrays (you might even use immediate mode, but that's deprecated)
# draw the stuff using glDrawArrays or better yet glDrawElements
render_subobject(object, parent_transform):
modelview = parent_tranform * object.transform
if OPENGL3_CORE:
glUniformMatrix4fv(object.shader.uniform_location[modelview], 1, 0, modelview)
else:
glLoadMatrixf(modelview)
draw_object(object)
for subobject in object.subobjects:
render_subobject(subobject, modelview)
render(deltaT, window, scene):
if use_physics:
PhysicsSimulateTimeStep(deltaT, scene.objects)
else:
for o in scene.objects:
o.animate(deltaT)
glClearColor(...)
glClearDepth(...)
glViewport(0, 0, window.width, window.height)
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)
# ...
# now _some_ objects' render pass - others may precede or follow, like for creating reflection cubemaps or water refractions.
glViewport(0, 0, window.width, window.height)
glEnable(GL_DEPTH_TEST)
glDepthMask(1)
glColorMask(1,1,1,1)
if not OPENGL3_CORE:
glMatrixMode(GL_PROJECTION)
glLoadMatrixf(scene.projection.matrix)
for object in scene.objects:
bind_shader(object.shader)
if OPENGL3_CORE:
glUniformMatrix4fv(scene.projection_uniform, 1, 0, scene.projection.matrix)
# other render passes
glViewport(window.HUD.x, window.HUD.y, window.HUD.width, window.HUD.height)
glStencil(window.HUD.x, window.HUD.y, window.HUD.width, window.HUD.height)
glEnable(GL_STENCIL_TEST)
glDisable(GL_DEPTH_TEST)
if not OPENGL3_CORE:
glMatrixMode(GL_PROJECTION)
glLoadMatrixf(scene.HUD.projection.matrix)
render_HUD(...)
and so on. I hope you get the general idea. OpenGL is neither a scene graph, nor a matrix manipulation library.
What I want to achieve:
Drawing png files with alpha exactly as it appears originally, without transforming any pixel. This is because the image is very detailed and I don't want to lose any bit of information.
Animating those images by rotating them and moving. No scaling.
Actually I don't want to use any 3rd party libraries like cocos2d. I have been reading blogs about OpenGL ES, also checked Texture2D.m so I have basic idea about drawing primitives in 3D space. As far as I understand if I need to draw and animate an image(sprite?) I can just make rectangle and map texture. But the problem is that I want my png file appear exactly as original, not scaled or rotated.
What is the best technique to achieve points mentioned above? Drawing textured rectangle in orthogonal viewport? How to preserve original size/color of image?
Sorry if question is a bit messed up, I can clarify.
By your description, I don't understand why you'd use OpenGL ES. Using Quartz and layers would enable 1) drawing PNGs 2) rotating and moving them (even scaling if you wished). It would be easier than setting up an orthogonal projection in OpenGL + handling loading of images.
Now, if you really want to go OpenGL, yes, you should setup an orthogonal projection, with view size strictly equal to the screen size, and draw a rectangle of the exact size, with texture mapped with exact 0/1 coordinates. For the color aspect, you can use 8888 format, which is exact, no compression, no color reduction and with full alpha.
I know you said you don't want to use a third party library, but Cocos2D implements 2D graphics with OpenGL, so you can reference CCSprite.m to see how they did it. That said, you may want to consider if this library is appropriate for your application. In order to do your own 3D rendering all you have to do is extend CCSprite and put in your own code, as you can see in the comment below the state is already setup for you and everything.
CCSprite.m:
-(void) draw
{
NSAssert(!usesBatchNode_, #"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
// Default GL states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Needed states: GL_TEXTURE_2D, GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_TEXTURE_COORD_ARRAY
// Unneeded states: -
BOOL newBlend = NO;
if( blendFunc_.src != CC_BLEND_SRC || blendFunc_.dst != CC_BLEND_DST ) {
newBlend = YES;
glBlendFunc( blendFunc_.src, blendFunc_.dst );
}
#define kQuadSize sizeof(quad_.bl)
glBindTexture(GL_TEXTURE_2D, [texture_ name]);
long offset = (long)&quad_;
// vertex
NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexPointer(3, GL_FLOAT, kQuadSize, (void*) (offset + diff) );
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glColorPointer(4, GL_UNSIGNED_BYTE, kQuadSize, (void*)(offset + diff));
// tex coords
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glTexCoordPointer(2, GL_FLOAT, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if( newBlend )
glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
#if CC_SPRITE_DEBUG_DRAW
CGSize s = [self contentSize];
CGPoint vertices[4]={
ccp(0,0),ccp(s.width,0),
ccp(s.width,s.height),ccp(0,s.height),
};
ccDrawPoly(vertices, 4, YES);
#endif // CC_TEXTURENODE_DEBUG_DRAW
}