I am trying to develop an android drawing app.In this app I am using texture to draw.
I want to draw translucent texture one over another to get continuous translucent line but I am only able to get this:
As you can see in part B circular translucent textures appear one over other. I want line to appear as in part A.
I am adding information of texture drawing like width,height,x&y coordinate in ArrayList spriteArray.
The blending function used is- gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
To set opacity of texture-gl.glColor4f(1, 1, 1, opacityValue);
I have also used gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);it does not work either.
Any help to solve this problem will be appreciated.
If you need more information please tell me.
drawFrame code:enter code here
gl.glMatrixMode(GL10.GL_TEXTURE);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glColor4f(1, 1, 1, opacityValue);
for (int x = 0; x < GLSurfaceView.mSpriteArray.size(); x++) {
int
mTextureName=GLSurfaceView.mSpriteArray.get(x).textureName;
gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureName);
// Draw using the DrawTexture extension.
((GL11Ext) gl).glDrawTexfOES(x, y, 0, width, height);
}
Related
I am in a situation where I need to render to a texture using FBO, and I need to remove some pixels from the buffer. That is, draw (0,0,0,0) color in a RGBA colored framebuffer. This will later allow me to later render this texture on top of another one and the 'zero pixels' will not be rendered since I use blending.
The problem is that I cannot draw such color on the screen because GL_BLEND is enabled while I am doing that and the zero pixels aren't rendered to the texture.
So I have tried disabling GL_BLEND just before rendering to the texture, and 1. It continued blending like nothing happened, 2.At some point it renders of all the graphics without blending although it clearly receives the glEnable(GL_BLEND) call.
Here is most of the code:
gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
gl.glDisable(GL11.GL_BLEND);
gl.glBindTexture(GL11.GL_TEXTURE_2D, 0);
gl.glFrontFace(GL11.GL_CW);
gl.glVertexPointer(3, GL11.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, textureBuffer);
gl.glPushMatrix();
gl.glTranslatef(start_x+adv_x/2+adv_x*(float)col_idx, start_y+adv_y/2+adv_y*(float)j, -1.0f);
gl.glScalef(adv_x/2, adv_y/2, 1.0f);
gl.glColor4f(0,0,0,0);
gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, vertex.length / 3);
gl.glColor4f(1f, 1f, 1f, 1f);
gl.glPopMatrix();
gl.glEnable(GL11.GL_BLEND);
gl.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
This is code from an Android application, written in Java.
What can be the problem?
I'm trying to make a hexagon with 6 triangles using rotation and translation. Rather than making multiple translate calls, I instead want to translate the triangle downward once and rotate around the Z axis at 60 degrees six times (my sketch may help with that explanation: http://i.imgur.com/SrrXcA3.jpg). After repeating the drawTriangle() and rotate() methods six times, I should have a hexagon.
Currently my code looks like this:
public void onDrawFrame(GL10 unused)
{
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); //start by clearing the screen for each frame
GLES20.glUseProgram(mPerVertexProgramHandle); //tell OpenGL to use the shader program we've compiled
//Get pointers to the program's variables. Instance variables so we can break apart code
mMVPMatrixHandle = GLES20.glGetUniformLocation(mPerVertexProgramHandle, "uMVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "aPosition");
mColorHandle = GLES20.glGetAttribLocation(mPerVertexProgramHandle, "aColor");
//Prepare the model matrix!
Matrix.setIdentityM(mModelMatrix, 0); //start modelMatrix as identity (no transformations)
Matrix.translateM(mModelMatrix, 0, 0.0f, -0.577350269f, 0.0f); //shift the triangle down the y axis by -0.577350269f so that its top point is at 0,0,0
drawTriangle(mModelMatrix); //draw the triangle with the given model matrix
Matrix.rotateM(mModelMatrix, 0, 60f, 0.0f, 0.0f, 1.0f);
drawTriangle(mModelMatrix);
}
Here's my problem: it appears my triangle isn't rotating around (0,0,0), but instead it rotates around the triangle's center (as shown in this picture: http://i.imgur.com/oiLFSCE.png).
Is it possible for to rotate triangle around (0,0,0), where its vertex is located?
Are you really be sure that your constant -0.577350269f is the correct value for the triangle center?
Also your code looks unfinish (You use an mvp handle but never use it in the code), could you provide more information?
I have an app that I've been repeatedly playing with in android, it uses opengl-es.
Currently I load textures from a bitmap like so:
//Load up and flip the texture - then dispose the temp
Bitmap temp = BitmapFactory.decodeResource(Deflecticon.getContext().getResources(), resourceID);
Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), flip, true);
temp.recycle();
//Bind the texture in memory
gl.glBindTexture(GL10.GL_TEXTURE_2D, id);
//Set the parameters of the texture.
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
//On to the GPU
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
The obvious issue is that the texture I'm using has to be a power of 2. At the moment I'm pre-editing the textures in photoshop to be a power of 2 and simply have empty borders. However this is a little tedious and I want to be able to load them as they are .. recognise they aren't a power of 2 and load them into a texture that is.
I know I could scale the bitmap to become a power of 2 size and simply stretch the texture but I do not wish to stretch the texture and in some cases may want to put several textures into one "atlas".
I know I can use glTexSubImage2D() to paste into the texture the data I want at the origin I want. This is great!
However I do not know how in Android to initialise a texture with no data?
In this question previously asked the suggestion was to call glTexImage2D() with no data and to then fill it.
However in android when you call "GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);" you do not specify a width / height. It reads this from the bitmap I assume.
What is the best way to do this? Can I create a new bitmap of the right power of 2 size only blank and not filled with any data and use this to initialise the texture then paste into it using subImage? Or should I make a new bitmap somehow copy the pixels I want (not sure if you can do this easily) into this new bitmap (leaving borders) and then just use this?
Edit: clarified that I'm using opengl.
I think if you tried creating a bitmap with the power of 2 axis sizes and then add your bitmap it should work just fine. maybe something like
Bitmap.createBitmap(notPowerOf2Bitmap, offx, offy, xsize, ysize, bitmapFlag)
other than that, I would say suffer through the photoshop process. How many pictures you got?
Non-power-of-two (NPOT) bitmaps are supported on some GLES platforms, but you have to check to see if the appropriate extension exists. Note, however, that at least on PowerVR SGX, even though NPOT is supported, there are still some other fairly arbitrary restrictions; for example, your texture width must be a multiple of 2 (if not a power of 2). Also, NPOT rendering tends to be a bit slower on many GPUs.
One thing you can do is just create a wrapper texture which is a power-of-two size and then use glTexSubimage2D to upload the texture to cover only part of that, and then adjust your texture coordinates accordingly. The obvious drawback to this is that you can't use texture wrapping in that circumstance. If you absolutely must support wrapping, you could just scale your texture to the nearest power-of-two size before you call glTexImage2D, although this usually introduces sampling artifacts and makes things blurry, especially if you're trying to do pixel-precise 2D work.
Another thing you might consider, if you don't need to support wrapping, is to make a "texture atlas," in which you condense all of your textures into a few big textures, and have your polygons map to just some portions of the texture atlas(es). You have to be careful when generating MIPmaps, but other than that it usually provides a pretty nice performance benefit, as well as making more efficient use of texture memory since you're not wasting so much on padded or scaled images.
I have 2 solutions I have employed for this problem. I can be more specific if necessary, but conceptually you can: -
Make the image a power of 2, and the section to crop you fill with 100% alpha channel and load the images with alpha enabled.
Tweak your texture vector / buffer so it doesn't load that section. So instead of using the default
float texture[] = {
0.0f, 1.0f, //
1.0f, 1.0f, //
0.0f, 0.0f, //
1.0f, 0.0f, //
};
as the matrix (obviously this is for loading an image to a 2 triangled square), factor back by ratio the area to crop, eg.
float texture[] = {
0.0f, 0.75f, //
0.9f, 0.75f, //
0.0f, 0.0f, //
0.9f, 0.0f, //
};
of course, be precise with your math or the unwanted bit may bleed in, or you'll cut out some of the real image. Obviously this array is calculated on the fly and not hard-coded as I have demonstrated here.
Uh why don't you create two bitmaps. Load the first one as you're doing then use createBitmapScaled to turn that bitmap into a power of two. Performance-wise I don't know if it is the fastest method possible but it works.
YOu can use GLES20.glTexImage2D() to create a empty texture with specified width and height. The example code is
public static int genTexture(int texWidth, int texHeight) {
int[] textureIds = new int[1];
GLES20.glGenTextures(1, textureIds, 0);
assertNoError();
int textureId = textureIds[0];
texWidth = Utils.nextPowerOf2(texWidth);
texHeight = Utils.nextPowerOf2(texHeight);
GLES20.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
GLES20.glTexParameteri(
GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(
GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
texWidth, texHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
return textureId;
}
I've tried to follow all the information I could find, but I am not having any luck finding the source of my texture problems and could really use a hand.
The following is piece of code in which I'm trying to draw 3 pieces of my background using glDrawTexfOES. The 3 pieces should look like green grass.
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glFrontFace(GL10.GL_CW);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glBindTexture(GL10.GL_TEXTURE_2D, grass);
gl.glColor4x(0x10000, 0x00000, 0x10000, 0x10000);
((GL11Ext) gl).glDrawTexfOES(0.0f, 0.0f, -8.0f, 32, 32);
((GL11Ext) gl).glDrawTexfOES(32.0f, 0.0f, -8.0f, 32, 32);
((GL11Ext) gl).glDrawTexfOES(64.0f, 0.0f, -8.0f, 32, 32);
}
Instead of green grass however, I'm getting 3 brown squares:
http://img109.imageshack.us/img109/9670/84615249.jpg
Any help in figuring out why my textures won't display correctly would be most appreciated!
On a related note, for building a simple 2D tiled game is glDrawTexfOES the most efficient method for generating the tiled background?
Thanks in advance,
Harry
You need to define the mapping of the image to the rectangle
You are probably just getting the top left pixel of the image.
int[]crop={0,0,text_dimx,text_dimy};
((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D, GL11Ext.GL_TEXTURE_CROP_RECT_OES, crop,0);
If you google most OpenGL functions you get documentation for the function, followed by examples. For that function, the results are dominated by people having trouble.
That function might be slightly faster than using textures the usual way (I haven't used it so I don't know), but simply applying a texture to a quad needs no extensions and is extremely portable.
Why don't you try that and get back to us... it could be that the function is working perfectly, but something went wrong initializing the texture. Using the uncomplicated texture-a-quad method will help you find that out as well.
I am writing a small app that at the moment generates a random map of textures.
I am drawing this map as a 10 x 15 group of "quads" which are infact all triangle strips. I use the "map" to grab an int which I then take as the location of the texture for this square in the textureAtlas. so for example 0 is the bottom left "tile". The atlas is 128 x 128 and split into 32 pixel tiles.
However I seem to be getting some odd artifacts where the texture from the one tile is creeping in to the next tile. I wondered if it was the image itself but as far as I can tell the pixels are exactly where they should be. I then looked at the texture coords I was specifying but they all look exact (0.0, 0.25, 0.5, 0.75, 1.0 - splitting it into the 4 rows and columns I would expect).
The odd thing is if I run it on the emulator I do not get any artifacts.
Is there a setting I am missing which would cause bleeding of 1 pixel? It seemed to only be vertical too - this could be related to on the phone I am "stretching" the image in that direction as the phone's screen is larger than normal in that direction.
I load the texture like so:
//Get a new ID
int id = newTextureID(gl);
//We will need to flip the texture vertically
Matrix flip = new Matrix();
flip.postScale(1f, -1f);
//Load up and flip the texture
Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource);
//Store the widths for the texturemap
int width = temp.getWidth();
int height = temp.getHeight();
Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, width, height, flip, true);
temp.recycle();
//Bind
gl.glBindTexture(GL10.GL_TEXTURE_2D, id);
//Set params
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);
//Push onto the GPU
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
TextureAtlas atlas = new TextureAtlas(id, width, height, tileSize);
return atlas;
I then render it like so:
gl.glBindTexture(GL10.GL_TEXTURE_2D, currentAtlas.textureID);
//Enable the vertices buffer for writing and to be used during our rendering
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
//Specify the location and data format of an array of vertex coordinates to use
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
//Enable the texture buffer
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
I would take a picture, but I am unsure how to get a screen cap from the phone...
If anyone knows of how I can capture the current frame and perhaps put it out into a file I will do that if it helps explain what is going on!
Look forward to your response.
Edit: Here is a screencap - note I run the app in landscape but cap is in portrait. Also excuse the horrible textures :D they were merely a place holder / messing around.
ScreenCap
Well, after speaking to a friend I managed to solve this little problem.
It turns out that if you wish to have exact pixel perfect textures you have to specify the edge of the texture to be halfway into the pixel.
To do this I simply added half a pixel or subtracted half a pixel to the measurement for the texture coords.
Like so:
//Top Left
textureCoords[textPlace] = xAdjust*currentAtlas.texSpaceWidth + currentAtlas.halfPixelAdjust; textPlace++;
textureCoords[textPlace] = (yAdjust+1)*currentAtlas.texSpaceHeight - currentAtlas.halfPixelAdjust; textPlace++;
This was simply calculated when loading the texture atlas:
(float)(0.5 * ((1.0f / numberOfTilesInAtlasRow) / pixelsPerTile));
Although if the height was different to the width of each tile (which could happen) you would need to calculate them individually.
This has solved all the artifacts so I can continue on. Hope it helps someone else!