how to use background image for texture in openGL - android

i want to use background image with texture but texture get images with power of 2 so i made image size (800x480 to 512x512).
but now it is showing image with some blank space.
how can i show image on entire screen. and also want to horizontally scrollable .

Well, if this is on Android, that means you don't have glDrawPixels, so the only way you could be "showing" an image would be to render a textured quad. So just make the quad whatever size you need.
You can also draw multiple textures, just by drawing one texture to one location, then drawing another texture to another location.

You need to use the right texture coordinates when rendering your background. You need to compute the texture coordinates so that you are having an offset for the axis perpendicular to the black borders.
I guess you resized your 800x480 image so that it fits in 512x512 pixels, making you end up with the actual background image (inside the 512x512 texture) being 512x307?
This would mean that your u texture coordinate offset would need to be (512.0 - 307.0) / 2.0 / 512.0 ~ 0.2, so your texture coordinates would need to be (0.0,0.0), (0.0,0.2), (1.0,0.2), (1.0,0.0).

Related

Draw quality of Single Bitmap vs Multiple Bitmaps on Canvas (Android)

I have a set of small images. If I draw these images individually on canvas, the draw quality is significantly low, compared to the case where I draw them on a screen size large bitmap and draw that bitmap on the canvas. Specially the lines get distorted. See the below (right side).
From the code below, the canvas also supports zooming (scaling). This issue occurs on small scale factors.
Question is how to improve the draw quantity of multiple small images to the standard of large image.
This is a code of multiple bitmaps drawn on canvas
canvas.scale(game.mScaleFactor, game.mScaleFactor);
canvas.translate(game.mPosX, game.mPosY);
for (int i = 0; i < game.clusters.size(); i++) {
Cluster cluster = game.clusters.get(i);
canvas.drawBitmap(cluster.Picture, cluster.left,
cluster.top, canvasPaint);
}
This is the code for single bitmap, game.board is a screen size image which has all the small bitmaps drawn on.
canvas.scale(game.mScaleFactor, game.mScaleFactor);
canvas.translate(game.mPosX, game.mPosY);
canvas.drawBitmap(game.board, matrix, canvasPaint)
The paint brush has following properties set.` All bitmaps are Bitmap.Config.ARGB_8888.
canvasPaint.setAntiAlias(true);
canvasPaint.setFilterBitmap(true);
canvasPaint.setDither(true);`
I can think of a couple, depending on you you are drawing the borders of the puzzle pieces.
The problem you are having is that when the single image is scaled, the lines are filtered with the rest of the image and it looks smooth (the blending is correct). When the puzzle is draw per-piece, the filtering reads adjacent pixels on the puzzle piece and blends them with the piece.
Approach 1
The first approach (one that is easy to do) is to render to FBO (RTT) at the logical size of the game and then scale the whole texture to the canvas with a fullscreen quad. This will get you the same result as single because the pixel blending involves neighboring pieces.
Approach B
Use bleeding to solve the issue. When you cut your puzzle piece, include the overlapping section of the adjacent pieces. Instead of setting the discarded pixels to zero, only set the alpha to zero. This will cause your blending function to pickup the same values as if it were placed on a single image. Also, double the lines for the border, but set the outside border alpha to zero.
Approach the Final
This last one is the most complicated, but will be smooth (AF) for any scaling.
Turn the alpha channel of your puzzle piece into a Signed Distance Field and render using a specialized shader that will smooth the output at any distance. Also, SDF allows you to draw the outline with a shader during rendering, and the outline will be smooth.
In fact, your SDF can be a separate texture and you can load it into the second texture stage. Bind the source image as tex unit 0, the sdf puzzle piece cutout(s) on tex unit 1 and use the SDF shader to determine the alpha from the SDF and the color from tex0, then mix in the outline as calculated from the SDF.
http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf
https://github.com/Chlumsky/msdfgen
http://catlikecoding.com/sdf-toolkit/docs/texture-generator/
SDF is generated from a Boolean map. Your puzzle piece cutouts will need to start as monochrome cutout and then turned into SDF (offline) using a tool or similar as listed above. Valve and LibGDX have example SDF shaders, as well as the tools listed above.

Android OpenGL2.0 intersection between two textures

I'm making game in OpenGL2.0 and I want to check are two sprites have intersection but i don't need to check intersection between two rectangles.I have two sprites with texture,some part of texture is transparent,some not. I need to check intersection between sprites only on not trasnparent part.
Example: http://i.stack.imgur.com/ywGN5.png
The easiest way to determine intersection between two sprites is by Bounding Box method.
Object 1 Bounding Box:
vec3 min1 = {Xmin, Ymin, Zmin}
vec3 max1 = {Xmax, Ymax, Zmax}
Object 2 Bounding Box:
vec3 min2 = {Xmin, Ymin, Zmin}
vec3 max2 = {Xmax, Ymax, Zmax}
You must precompute the bounding box by traversing through the vertex buffer array for your sprites.
http://en.wikibooks.org/wiki/OpenGL_Programming/Bounding_box
Then during each render frame check if the bounding boxes overlap (compute on CPU).
a) First convert the Mins & Maxs to world space.
min1WorldSpace = modelViewMatrix * min1
b) Then check their overlap.
I need to check intersection between sprites only on not trasnparent part.
Checking this test case maybe complicated depending on your scene. You may have to segment your transparent sprites into a separate sprite and compute their bounding box.
In your example it looks like the transparent object is encapsulate inside an opaque object so it's easy. Just compute two bounding boxes.
I don't think there's a very elegant way of doing this with ES 2.0. ES 2.0 is a very minimal version of OpenGL, and you're starting to push the boundaries of what it can do. For example in ES 3.0, you could use queries, which would be very helpful in solving this nicely and efficiently.
What can be done in ES 2.0 is draw the sprites in a way so that only pixels in the intersection of the two end up producing color. This can be achieved with either using a stencil buffer, or with blending (see details below). But then you need to find out if any pixels were rendered, and there's no good mechanism in ES 2.0 that I can think of to do this. I believe you're pretty much stuck with reading back the result, using glReadPixels(), and then checking for non-black pixels on the CPU.
One idea I had to avoid reading back the whole image was to repeatedly downsample it until it reaches a size of 1x1. It would originally render to a texture, and then in each step, sample the current texture with linear sampling, rendering to a texture of half the size. I believe this would work, but I'm not sure if it would be more efficient than just reading back the whole image.
I won't provide full code for the proposed solution, but the outline looks like this. This is using blending for drawing only the pixels in the intersection.
Set up an FBO with an RGBA texture attached as a color buffer. The size does not necessarily have to be the same as your screen resolution. It just needs to be big enough to give you enough precision for your intersection.
Clear FBO with black clear color.
Render first sprite with only alpha output, and no blending.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
// draw sprite 1
This leaves the alpha values of sprite 1 in the alpha of the framebuffer.
Render the second sprite with destination alpha blending. The transparent pixels will need to have black in their RGB components for this to work correctly. If that's not already the case, change the fragment shader to create pre-multiplied colors (multiply rgb of the output by a).
glColorMask(GL_TRUE GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc(GL_DST_ALPHA, GL_ZERO);
glEnable(GL_BLEND);
// draw sprite 2
This renders sprite 2 with color output only where the alpha of sprite 1 was non-zero.
Read back the result using glReadPixels(). The region being read needs to cover at least the bounding box of the two sprites.
Add up all the RGB values of the pixels that were read.
There was overlap between the two sprites if the resulting color is not black.

Moving image on OpenGl using px?

I am using OpenGl to draw an image. Now when i try to move the image, it moves by too much. So if i say the following:
gl.glTranslatef(0, 1, -5.0f);
squirrel.draw(gl);
If i out one as a parameter, the image is now located half way of screen. How do i make it so i can say things like:
gl.glTranslatef(screen_width - image_width , 0);
Is there an alternative method for drawing images in OpenGl?
I previously used canvas to draw images, and i had no problem positioning images on the screen. However with openGl i'm experiencing issues.
All you need to remember is, the screen space in OpenGL ranges from -1,-1 (top left), and 1,1 (bottom right). So you need to provide normalized values to OpenGL. To move a point along x direction from one end of the screen (-1.0) to another (1.0), left to right, you will have to Translate by 2.0 by using glTranslatef(2.0, 0, 0). This point is on the border, so you will have to adjust depending on the actual size of your object and its location.

Android Screen Ratios

I'm using OpenGL ES 2.0 on Android and I and I initialise my display like so:
float ratio = (float) width / height;
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); //Using Orthographic as developing 2d
What I'm having trouble understanding is this:
Let's say my app is a 'fixed screen' game (like Pac-Man ie, no scrolling, just the whole game visible on the screen).
Now at the moment, if I draw a quad at -1 to +1 on both x and y I get something like this:
Obviously, this is because I am setting -ratio, ratio as seen above. So this is correct.
But am I supposed to use this as my 'whole' screen? With rather massive letterboxing on the left and right?
I want a rectangular display that is the whole height of the physical display (and as much of the width as possible), but this would mean drawing at less that -1 and more than +1, is this a problem?
I realise the option may be to use clipping if this was a scrolling game, but for this particular scenario I want the whole 'game board' on the screen and to be static (And to use as much of the available screen real estate as possible without 'stretching' thus causing elongation of my sprites).
As I like to work with 0,0 as the top of the screen, basically what I do is pass my draw method something like so:
quad1.drawQuad (10,0);
When the drawQuad method get's this, it basically takes the range from left to right as expressed my openGL and divide the the screen width (so, in my case -1.7 through +1.7 so 3.4/2560 = 0.001328125). And say I specify 10 as my X (as above), it will say something like:
-1.7 + (10*0.001328125) = -1.68671875
It then plots the quad at -1.68671875.
Doing this I am able to work with normal co-ords (and I just subtract rather than add for y axis so I can have 0 at the top).
Is this a good way to do things?
Because with this method, at the moment, if I specify a 100,100 square, it isn't a square, it's rectangle. However, on the plus side, I can fill the whole physical screen by scaling the quad by width x height.
You are drawing a 1x1 quad, so that is why you see a 1x1 quad. Try translating the quad 0.25 to the right or left and you will see that you can draw in that space too.
In graphics, you create an object, like a quad, in your case you made it 1x1. Then you position it wherever you want. If you do not position it, then it will be at the origin, which is what you see.
If you draw a wider shape, you will also see you can draw outside this area on the screen.
By the way, with your ortho matrix function, you aren't just specifying the screen aspect ratio, you are also specifying the coordinate unit size you have to work with. This is why a 1x1 is filling the height the of the screen, because your upper and lower boundaries are set to 1 and -1. Your ratio is a little more than one, since your width is longer than your height, so your left and right boundaries are essentially something like -1.5 and 1.5 (whatever your ratio happens to be).
But you can also do something like this;
Matrix.orthoM(mProjMatrix, 0, -width/2, width/2, -height/2, height/2, 3, 7);
Here, your ratio is the same, but you are sending it to your ortho projection with screen coordinates. (Disclaimer: I don't use the same math library you do, but these appears to be a conventional ortho matrix function based on the arguments you are passing to it).
So lets say you have a 1000x500 pixel resolution. In OpenGL your origin of 0,0 is in the middle. So now your left edge is at (-500,y), right edge at (500,y) and your top is (x,250). So if you draw your 1x1 quad, it will be very tiny, but if you draw a 250x250 square, it will look like your 1x1 quad in your previous ortho projection.
So you can specify the coordinates you want, the ratio, the unit size, etc for how you want to work. Personally, I dont't like specifying coordinates as fractions between 0 and 1, I like to think about them in the same sense as the screen pixels.
But whether or not you choose to do this, hopefully you understand what you are actually passing to these matrix functions.
One of the best ways to learn is draw an object to the screen and just play around with different numbers you send to your modelview and projection matrices so you can see what it is they are actually doing.

Android - Set focus on a circle that I have drawn in my onDraw method

Android Question.
I have made a custom ImageView class and inside it I have an onDraw method which will draw a circle on particular pixels (using canvas). When I use this custom imageview and open up my image I would like to set the focus on the circle that I have drawn (e.g like google maps do with your current location. The focus is set to your current point)
What the map server does on google is deliver a customized set of tiles so that the center is displayed properly, the newer version is of course vector based so they simply draw the view so it's centered where they want it.
Without knowing the details of your application you probably need
Create your own container class, probably FrameLayout
public class myMapFrameLayout extends FrameLayout {
The override either onDraw or onDispatchDraw so that you can layout your tile appropriately
Figure out where to draw your bitmap so that the x,y you need will be in the center of the screen, then draw the other tiles that you need to fill in the blank space at the coordinates required dependent on which way the tile was moved to get centered
Think of a virtual screen that is larger than the actual screen with tiles all around it that are the same size
1 2 3
4 X 5
6 7 8
Assuming that X is the size of the display and represents the current tile you need to figure out which way to move the tile, and which other tiles 1,2,3,4,5,6,7 or 8 you need to fill in the empty space caused by move
If you had to draw the tile +x from 0,0 you need some of tile 4, drawing +y from 0,0 means some of 2 and both mean 1,2,4 are all needed and so on, so figure out the combinations and load the tiles you need, and figure out the drawing positions of each. That would give you your new virtual tile with the center displayed.
That's about as efficient as you can get I think with a bitmap drawing method on the client side.
UPDATE
Since your comment indicates you have only one very large image this is going to be a bit of a problem if the x,y you need as anything closer to the edges than the size of the display
None the less you can still draw the image where you need it, just measure the screen and draw the bitmap with the target x,y in the center
So if the screen was 500x500 and your image was 5000x5000 and the center was at position x=1000 y=1000 then
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
where source rectangle would be 1000-250,1000-250,500,500 and dst rectangle would be 0,0,500,500
The 250 is the center x and center y of the display, 1000 are the target x/y coordinates, and 500 is the size of display.
Again, with targets that are at the edges you are going to have a blank polygon in your screen since you dont have an infinite map tile
Alternatively you could oversize your framelayout using layoutparams and just translate the canvas in the x and y to get the canvas centered to the x,y you need using similar calcs which may be more performant, not really sure
Keep in mind you are going to be using a lot of memory if your image is really big

Categories

Resources