Suppose I have made five strokes with different texture in opengl.Now I want to clear all only four texture I want to keep as it is remaining one texture.How can I do that.
When I use glClear() it removes all.I can not use glScissor as texture location can be same.
How can I do this.
You create exact texture with:
GLuint index=x;
glGenTextures(1, &index);
glBindTexture(GL_TEXTURE_2D, index);
glTexImage2D...
And delete the same texture with:
glDeleteTextures(1, &index);
Now, you don't need to delete texture during the rendering process, just use the proper texture index for desired stroke. Use the same mesh, just change the texture index when rendering vertices.
Related
I am making a unity 2D RTS game and I thought of using a big texture for the tiled map (instead of a lot of textures - for the memory reasons...).
The tiled map is supposed to generate randomly at runtime so I don't want to save a texture and upload it. I want the map to be generated and then build it from a set of textures resources.
so, I have a little tiles textures of grass/forest/hills etc. and after I generate the map randomly, I need to draw those little textures on my big map texture so I will use it as my map.
How can I draw a texture from my resources on other texture? I saw there is only a Get/SetPixel functions... so I can use it to copy all the pixels one by one to the big texture, but there is something easier?
Is my solution for the map is OK? (is it better from just create a lot of texture tiles side by side? There is other better solution?)
The correct way to create a large tiled map would be to compose it from smaller, approximately-screen-sized chunks. Unity will correctly not draw the chunks that are off the screen.
As for your question about copying to a texture: I have not done this before in Unity, but this process is called Blitting, and there just happens to be a method in Unity called Graphics.Blit(). It takes a source texture and copies it into a destination texture, which sounds like exactly what you're looking for. However, it requires Unity Pro :(
There is also SetPixels(), but it sounds like this function does the processing on the CPU rather than the GPU, so it's going to be extremely slow/resource-intensive.
Well, after more searching I discovered the Get/SetPixel s
Texture2D sourceTex = //get it from somewere
var pix = sourceTex.GetPixels(x, y, width, height); // get the block of pixels
var destTex = new Texture2D(width, height); // create new texture to copy the pixels to it
destTex.SetPixels(pix);
destTex.Apply(); // important to save changes
http://smotr.im/9KwB
There are some pictures:
1)a texture I have
2)a line I have already drawed with triangle strip
3)the result I need to achieve
The question is how to draw a texture inside these segments which are usually not regular quads?
What do you mean, "usually not regular quads"? Are they quads or not?
If they are quads, just assign texture coordinates normally. The hardware will interpolate correctly.
If they are not quads, why don't you make them quads?
I have managed to get a CVPixelBufferRef from an AVPlayer to feed pixel data that I can use to texture a 2D object. When my pixelbuffer has data in it I do:
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage('
kCFAllocatorDefault,
videoTextureCache_,
pixelBuffer, //this is a CVPixelBufferRef
NULL,
GL_TEXTURE_2D,
GL_RGBA,
frameWidth,
frameHeight,
GL_BGRA,
GL_UNSIGNED_BYTE,
0,
&texture);
I would like to use this buffer to create a GL_TEXTURE_CUBE_MAP. My video frame data is actually 6 sections in one image (e.g. a cubestrip) that in total makes the sides of a cube. Any thoughts on a way to do this?
I had thought to just pretend my GL_TEXTURE_2D was a GL_TEXTURE_CUBE_MAP and replace the texture on my skybox with the texture generated by the code above, but this creates a distorted mess (as I suppose should be expected when trying to force a skybox to be textured with a GL_TEXTURE_2D.
The other idea was to setup unpacking using glPixelStorei and then read from the pixelbuffur:
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, X);
glPixelStorei(GL_UNPACK_SKIP_ROWS, Y);
glTexImage2D(...,&pixelbuffer);
But unbelievably GL_UNPACK_ROW_LENGTH is not supported in OpenGl ES2.0 for iOS.
So, is there:
-Any way to split us the pixel data in my CVPixelBufferRef through indexing the buffer to some pixel subset before using it to make a texture?
-Any way to make a 6 new GL_TEXTURE_2D as indexed subsets of my GL_TEXTURE_2D that is created by the code above
-any way to convert a GL_TEXTURE_2D to a valid GL_TEXTURE_CUBE_MAP (e.g. GLKit has a Skybox effect that loads a GL_TEXTURE_CUBE_MAP from a single cubestrip file. It doesnt have a method to load a texture from memory though or I would be sorted)
-any other ideas?
If it were impossible any other way (which is unlikely, there probably is an alternate way -- so this is probably not the best answer & involves more work than necessary) here is a hack I'd try:
How a cube map works is it projects the texture for each face from a point in the center of the geometry out toward each of the cube faces. So you could reproduce that behavior yourself; you could use Projective Texturing to make six draw calls, one for each face of your cube. Each time, you'd first draw the face you're interested in to the stencil buffer, then calculate the projection matrix for your texture (this technique is used a lot for 'spotlight' effects in games), then figure out the transform matrix required to augment the fragment shader's texture read so that for each face, only the portion of the texture that corresponds to that face winds up within the (0..1) texture lookup range. If everything has gone right, anything outside the 0..1 range should be discarded by the stencil buffer, and you'd be left with a DIY cube map out of a TEXTURE_2D.
The above method is actually really similar to what I'm doing for an app right now, except I'm only using projective texturing to mask off & replace a small portion of the cube map. I need to pixel-match the edges of the small square I'm projecting so that it's seamlessly applied to the skybox, so that's why I feel confident that this method will actually reproduce the cube map behavior -- otherwise, pixel-matching wouldn't be possible.
Anyway, I hope you find a way to simply transition your 2D to CUBEMAP, because that would probably be much easier and cleaner.
I want to make a 2D tiled background system on the iPhone. Something that takes a tilemap and tileset image(s) and converts it into the full map on the screen.
Just doing some messing around, my first approach was to create a polygon for each tile. This worked fine until I started testing it for 400 polygons or so, then it started running very slowly. I'm just wondering - is this method of several polygons just not the way to go? Or am I doing something wrong with it? I'll post code later if needed but my main question is "Would 400 small polygons run slowly on the iPhone or am I just doing something wrong?"
I also considered another way which was to, during initialization, create the map texture by code out of the tilemap/tilesets, and then stick that on ONE large polygon. So yeah...any feedback on how I should go about something like this?
I know someone will mention this - I gave consideration to trying cocos2d, but I've got my reasons for not going that route.
Your problem is almost certainly that you're binding textures 400 times, and not anything else. You should have all your tiles in one big texture atlas / sprite sheet and instead of rebinding your textures you should just bind your atlas once and then draw small parts of it. If you do this, you should be able to draw thousands of tiles with no real slowdown.
You can draw your sprite like this:
//Push the matrix so we can keep it as it was previously.
glPushMatrix();
//Store the coordinates/dimensions from a rectangle.
float x = CGRectGetMinX(rect);
float y = CGRectGetMinY(rect);
float w = CGRectGetWidth(rect);
float h = CGRectGetHeight(rect);
float xOffset = x;
float yOffset = y;
if (rotation != 0.0f)
{
//Translate the OpenGL context to the center of the sprite for rotation.
glTranslatef(x+w/2, y+h/2, 0.0f);
//Apply the rotation over the Z axis.
glRotatef(rotation, 0.0f, 0.0f, 1.0f);
//Have an offset for the top left corner.
xOffset = -w/2;
yOffset = -h/2;
}
// Set up an array of values to use as the sprite vertices.
GLfloat vertices[] =
{
xOffset, yOffset,
xOffset, yOffset+h,
xOffset+w, yOffset+h,
xOffset+w, yOffset,
};
// Set up an array of values for the texture coordinates.
GLfloat texcoords[] =
{
CGRectGetMinX(clippingRect), CGRectGetMinY(clippingRect),
CGRectGetMinX(clippingRect), CGRectGetHeight(clippingRect),
CGRectGetWidth(clippingRect), CGRectGetHeight(clippingRect),
CGRectGetWidth(clippingRect), CGRectGetMinY(clippingRect),
};
//If the image is flipped, flip the texture coordinates.
if (flipped)
{
texcoords[0] = CGRectGetWidth(clippingRect);
texcoords[2] = CGRectGetWidth(clippingRect);
texcoords[4] = CGRectGetMinX(clippingRect);
texcoords[6] = CGRectGetMinX(clippingRect);
}
//Render the vertices by pointing to the arrays.
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
// Set the texture parameters to use a linear filter when minifying.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Allow transparency and blending.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Enable 2D textures.
glEnable(GL_TEXTURE_2D);
//Bind this texture.
if ([Globals getLastTextureBound] != texture)
{
glBindTexture(GL_TEXTURE_2D, texture);
}
//Finally draw the arrays.
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
//Restore the model view matrix to prevent contamination.
glPopMatrix();
The two CGRect's I used are just for ease's sake. You can specify the X, Y, width, and height to draw the image, and you can specify where in the image you want to draw using the clippingRect. With the clipping rect, (0, 0, 1, 1) is the entire image, whereas (0, 0, 0.25, 0.25) would only draw the top left corner. By changing the clipping rect, you can put all sorts of different tiles in the same texture, then you only need to bind once. Way cheaper.
Scott, the TexParameter setup only needs to be done once per texture. However, that is not the source of your slowdown.
You'll be much better off building up a list of indexes, and calling glDrawArrays once for the entire set of tiles. The goal of vertex arrays are to allow you to draw as much as possible in one step.
glDrawTex should be avoided, because it forces you into the very inefficient one-at-a-time mindset.
Using the glDrawTex extension may also be a possibility.
Stanford iTune University has a podcast on Optimizing OpenGL for iPhone.
But the basic idea are these:
Batch Geometry, combining various vertex array into a single big vertice array. This should reduce x number of glPointer calls into a single glPointer call.
Texture Atlases, using a single texture for all the different tiles, differences being the regions to use for each tile. Just bind once to the texture for all tile drawing.
Interleaved Arrays, combining various parts of a point (eg. vertex, texture coordinates, color) into a single array. This should reduce gl*Pointer calls to a single call.
Indexed triangles, allowing you to reuse geometry information
Using Short instead of Float if possible for geometery information, as it is smaller.
That's just a general opengl optimization guidelines. As for tile engine, well..
Do your own culling before sending the data to opengl. What you don't draw, you save.
I think that's what I can think of so far.
What i did to speed my app up. Was after i load my level. I created an atlas out of the tiles on the map. Then every frame i check to see if the camera did move. If it did then i just pass an glTranslatef and move the entire map at once. If only dynamic objects move on the map then i just update that object in the vertex array atlas. This system is very effiecient as i am able to draw tons of tiles with no framerate drop.
Client states should be enabled only at initialization, also the glTexParameteri functions should be called when creating the texture object.
All glEnable functions are not cached, meaning it will set the state even if it is already set to that value.
All these small things can add up and slow you down.
BR
This is hopefully a simple question: I have an OpenGL texture and would like to be able to change its opacity, how do I do that? The texture already has an alpha channel and blending works fine, but I want to be able to decrease the opacity of the whole texture, to fade it into the background. I have fiddled with glBlendFunc, but with no luck – it seems that I would need something like GL_SRC_ALPHA_MINUS_CONSTANT, which is not available. I am working on iPhone, with OpenGL ES.
I have no idea about OpenGL ES, but in standard OpenGL you would set the opacity by declaring a colour for the texture before you use it:
// R, G, B, A
glColor4f(1.0, 1.0, 1.0, 0.5);
The example would give you 50% alpha without affecting the colour of your texture. By adjusting the other values you can shift the texture colour too.
Use a texture combiner. Set the texture stage to do a GL_MODULATE operation between a texture and constant color. Then change the constant color from your code (glTexEnv, GL_TEXTURE_ENV_COLOR).
This should come as "free" in terms of performance. On most (if not all) graphics chips combiner operations take the same number of GPU cycles (usually 1), so just using a texture versus doing a modulate operation (or any other operation) is exactly the same cost.
Basically you have two options: use glTexEnv for your texture with GL_MODULATE and specify the color using glColor4* and use a non-opaque level for the alpha channel. Note that glTexEnv should be issued only once, when you first load your texture. This scenario will not work if you specify colors in your vertex-attributes though. Those will namely override any glColor4* color you may set. In that case, you may want to resort to either of 2 options: use texture combiners (advanced topic, not nice to use in fixed-pipeline), or "manually" change the vertex color attribute of each individual vertex (can be undesirable for larger meshes).
If you are using modern OpenGL..
You can do this in the fragment shader :
void main()
{
color = vec4(1.0f, 1.0f, 1.0f, OPACITY) * texture(u_Texture, TexCoord);
}
This allows you to apply a opacity value to a texture without disrupting the blending.
Thank You all for the ideas. I’ve played both with glColor4f and glTexEnv and at last forced myself to read the glTexEnv manpage carefully. The manpage says that in the GL_MODULATE texturing mode, the resulting color is computed by multiplying the incoming fragment by the texturing color (C=Cf×Ct), same goes for the alpha. I tried glColor4f(1, 1, 1, opacity) and that did not work, but passing the desired opacity into all four arguments of the call did the trick. (Still not sure why though.)
The most straightforward way is to change the texture's alpha value on the fly. Since you tell OpenGL about the texture at some point, you will have the bitmap in memory. So just rebind the texture to the same texture id. In case you don't have it in memory, (due to space constraints, since you are on ES), you can retrieve the texture to a buffer again, using glGetTexImage(). That's the clean solution.
Saving/retrieving operations are a bit costly, though, so you might want another solution. Thinking about it, you might be able to work with geometry behind your the geometry displaying your texture or simply work on the material/colour of the geometry that holds the texture. You will probably want to have some additive blending of the back-geometry. Using a glBlendFunc of
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA),
you might be able to "easily" and - more important, cheaply - achieve the desired effect.
Most likely you are using cg to get your image into a texture. When you use cg, the alpha is premultiplied, thus why you have to use the alpha for rgba of the color4f func.
I suspect that you had a black background, and thus by decreasing the amount of every color, you were effectively fading the color to black.