Is it possible to .setColor(x,x,x,1) for a border of a circle like this:
else I have to use 2 sprites, and I already have 500 sprites referenced. Do not want to use a 1000.
To do it in one pass with a custom shader, encode your source sprite in a certain way. Like this:
Now you can blend between white and your border color using the R channel as the interpolation factor. You can copy the vertex shader from the SpriteBatch source code and modify the fragment shader main function to look like this:
vec4 texColor = texture2D(u_texture, v_texCoords);
gl_FragColor = vec4(mix(vec3(1.0), v_color.rgb, texColor.rrr), v_color.a * texColor.a);
Just simply use two different textures, one with a filled-in circle and one with only a stroke. Set the texture of whichever sprite needs a stroked or a filled circle using the setTexture method in the libGDX Sprite class.
This is still efficient since the textures only need to be loaded once and by setting the texture of a sprite it only keeps a pointer in memory not the whole texture.
I would go with the TextureRegion idea above and when you've finished your game, IF your having performance issues THEN and only then would i really worry about this, but im somewhat scared of shaders.
Most people never finish their games because they get caught up in the details way before they really need to.
Related
So Im trying to figure out how to draw a single textured quad many times. My issue is that since these are create and deleted and every one of them has a unique position and rotation. Im not sure a vbo is the best solution as I've heard modifying buffers is extremely slow on android and it seems I would need to create a new one each frame since different quads might disappear randomly (collide with an enemy). If I simply do a draw call for each one I get 20fps around 100, which is unusable. any advice?
Edit: I'm trying to create a bullethell, but figuring out how to draw 500+ things is hurting my head.
I think you're after a particle system. A similar question is here: Drawing many textured particles quickly in OpenGL ES 1.1.
Using point sprites is quite cheap, but you have to do extra work in the fragment shader and I'm not sure if GLES2 supports gl_PointSize if you need different sized particles. gl_PointSize Corresponding to World Space Size
My go-to particle system is storing positions in a double buffered texture, then draw using a single draw call and a static array of quads. This is related but I'll describe it a bit more here...
Create a texture (floating point if you can, but this may limit the supported devices). Each pixel holds the particle position and maybe rotation information.
[EDITED] If you need to animate the particles you want to change the values in the texture each frame. To make it fast, get the GPU to do it in a shader. Using an FBO, draw a fullscreen polygon and update the values in the fragment shader. The problem is you can't read and write to the same texture (or shouldn't). The common approach is to double buffer the texture by creating a second one to render to while you read from the first, then ping-pong between them.
Create a VBO for drawing triangles. The positions are all the same, filling a -1 to 1 quad. However make texture coordinates for each quad address the correct pixel in the above texture.
Draw the VBO, binding your positions texture. In the vertex shader, read the position given the vertex texture coordinate. Scale the -1 to 1 vertex positions to the right size, apply the position and any rotation. Use the original -1 to 1 position as the texture coordinate to pass to the fragment shader to add any regular colour textures.
If you ever have a GLSL version with gl_Vertex, I quite like generating these coordinates in the vertex shader, saving storing unnecessarily trivial data just to draw simple objects. This for example.
To spawn particles, use glTexSubImage2D and write a block of particles into the position texture. You may need a few textures if you start storing more particle attributes.
I'm trying to get my point sprites to display with the correct opacity.
Originally, I was getting my sprite texture on a black square.
So, I added the following to my fragment shader:
"if(color.a < 0.5) "+
"discard;"+
Now, this does seem to work, in that my sprite displays without the black background, however, my texture itself is 'partially transparent' - and it isn't showing this partial transparency, it is appearing solid. It's a bit difficult to explain, but I hope you understand what I mean. If I draw the same texture using canvas/surfaceview, it displays correctly.
Basically I'm trying to get my textures to display in their original format (ie as they do in the software in which they were created - ie, the Gimp / photoshop etc).
Would appreciate any help - thanks
First make sure your textures are loaded from transparent pngs through a Bitmap with either RGBA_8888 or RGBA_4444 configuration, so you don't lose the alpha channel.
Second you need to enable GL_BLEND with the glEnable() command. On Android you will write it like this: GLES20.glEnable(GLES20.GL_BLEND);. This allows you to blend the already drawn color with the new color, achieving a transparent look.
The blending function should be set to GL_ONE, GL_ONE_MINUS_ALPHA for regular transparency: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GL_SRC_ALPHA, GL_ONE_MINUS_ALPHA for regular transparency: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Finally, you do not need to use discard, just set the gl_FragColor to a 4-component vector with the alpha in the fourth channel (which is what you get when reading a texture from a sampler), e.g. you could just do gl_FragColor = texture2D(sampler, texCoord); if you wanted to.
You will most likely have to turn off depth-testing with glDisable(GL_DEPTH_TEST) to avoid problems with unsorted triangles.
You can read a little bit more about transparency here.
I am using OpenGL ES 2.0 (on Android) to draw simple 2D scene has few images. I have background image and some others which have alpha channel.
I would like to draw outline around non-transparent pixels in texture using only shader programs. After somewhat extensive search I failed to find example code. It looks like GLES 2.0 is still not that popular.
Can you provide some sample code or point me in right direction where I can find more information on how to do this?
There are a couple of ways of doing this depending on the a) Qaulity, and b) Speed you need. The common search terms are:
"glow outline"
"bloom"
"toon shader" or "toon shading"
"edge detection"
"silhouette extraction"
"mask"
1) The traditional approach is to use the stencil buffer and render to texture
Clear the stencil buffer (usually done once per frame)
glClear( GL_COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT )
Render to Texture
Disable Depth Writes
glDepthMask( 1 );
Disable Color Buffer Writes
glColorMask( 0, 0, 0, 0 );
Enable the Stencil buffer Set stencil to always pass and replace
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
glStencilFunc( GL_ALWAYS, 1, 1 );
Draw object into texture
Disable stencil
Enable Color Buffer Writes
Enable Depth Writes
Do a N-pass "tap", such as 5 or 7 pass tap where you blur the texture via rendering to itself in both the vertical and horizontal direction (another option is to scale drawing the texture image up)
Switch to orthographic projection
Draw & Blend the texture image back into the framebuffer
Restore perspective projection
2) Pass along extra vertex, namely which vertices are adjacent in the proper winding order, and dynamically generate extra outline triangles.
See: http://www.gamasutra.com/view/feature/1644/sponsored_feature_inking_the_.php?print=1
3) Use cheap edge detection. In the vertex shader check the dot product of the normal with the view. If it is between:
-epsilon < 0 < epsilon
Then you have an edge.
4) Use cheap-o-rama object scaling. It doesn't work for concave objects of course but depending on your quality needs may be "good enough"
Switch to a "flat" shader
Enable Alpha Testing
Draw the model scaled up slightly
Disable Alpha Testing
Draw the model but at the normal size
References:
https://developer.valvesoftware.com/wiki/L4D_Glow_Effect
http://prideout.net/blog/?p=54
http://en.wikibooks.org/wiki/GLSL_Programming/Unity/Toon_Shading#Outlines
http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter09.html
Related SO questions:
Outline effects in OpenGL
To get the pixel shader drawing something, there needs to be geometry.
As far as I understand, you want to draw a border around these images,
but the outermost fragments generated would be image pixels in a basic implementation,
so you'd overdraw them with any border.
If you want a 'line border', you cannot do anything else than drawing the image triangles/quads (GL_TRIANGLES,GL_QUADS), and in an additional call the outline (using GL_LINES), where you may share the vertices of a single quad.
Consider, that lines can't be drawn efficiently by many GPU's)
Otherwise, see below solutions:
Solution 1:
Draw the rectangle as big as the image + border will be and adjust texture coords for the image, so that it will be placed within the rectangle appropriately.
This way, no extra geometry or draw calls are required.
Set the texture border property (single 4 component color), there will be no need to do extra fragment shader calculations, the texture unit/sampler does all the work.
Texture properties:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER)
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,borderColor4f)
I've never used a color border for a single channel texture, so this approach needs to be verified.
Solution 2:
Similar to 1, but with calculations in the fragment shader to check, whether the texture coords are within the border area, instead of the texture border. Without modification, the scalars of a texture coord range from 0.0 to 1.0.
Texture properties may be:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)
The fragment color could be determined by any of these methods:
an additional border color attribute for the rectangle, where either the texel or that border color is selected then (could be a vertex attribute, but more likely an uniform or constant).
combination of the alpha texture with a second texture as background for the whole rectangle (like a picture frame) and here too, either texel is choosen.
some other math function
Of course, the color values could be mixed for image/border gradients.
EDIT:
As the number, length and position of such outline segments will vary and can even form concave shapes, you'd need to do this with a geometry shader, which is not available in ES 2.0 core. The best thing you can do is to precompute a line loop for each image on the CPU. Doing such tests in a shader is rather inefficient and even overkill, depending on image size, the hardware you actually run it on etc. If you'd draw a fixed amount of line segments and transform them using the vertex shader, you can not properly cover all cases, at least not without immense effort and GPU workload.
Should you intend to change the color values of corresponding texels, your fragment shader would need to fetch a massive and varying amount of texels for each neighbour pixel towards the texture edges as in all other implementations. Such brute force techniques are usually a replacement for recursive and iterative algos, for which the CPU is a better choice. So I suggest that you do it there by either modifying the texture or generate a second one for combination in the fragment shader.
Basically, you need to implement a path finding algo, which tries to 'get around' opaque pixels towards any edge.
Your alpha channel can be seen as a grey scale image. Look for any edge detection/drawing algorithm. For example Canny edge detector (http://en.wikipedia.org/wiki/Canny_edge_detector). Alternatively and probably much better idea if your images are not procedural is to pre-compute the edges.
If your goal is to blend various images and then apply the contour from the result of that blending, try rendering to a texture and then render again that texture over the screen and perform the edge detection algorithm.
I'm implementing some native 2D-draw functions in my graphics engine for android, but now there's another question coming up, when I observe the performance of my program.
At the moment I'm implementing a drawLine/drawImage function. In summary, there are following different values for drawing each different line / image:
the color
the alpha value
the width of the line
rotation (only for images)
size/scale (also for images)
blending method (subrtract, add, normal-alpha)
Now, when an imageLine is drawn,
I put the CPU-calculated vertex-positions and uv-values for 6 vertices (2 triangles), into a Floatbuffer and draw it immediately with drawArrays, after passing information for drawing (color,alpha, etc.) via uniforms to the shader. When I draw an image, the pre-set VBO is directly drawn after passing information.
The first fact I recognized, is: of course drawing Images is much faster, than imagelines (beacuse of VBOs), but also: I cannot pre-put vertex-data into a VBO for imageLines, because imageLines have no static shape like normal images (varying linelength, varying linewidth and the vertex positions of x1,y1 and x2,y2 change too often)
That's why I use a normal Floatbuffer, instead of a VBO.
So my question is: What's the best way for managing images, and other 2D-graphics functions. For me it's some kind of important, that the user of the engine is able to draw as many images/2D graphics as possible, without loosing to much performance.
You can find the functions for drawing images, imagelines, rects, quads, etc. here:
https://github.com/Chrise55/LLama3D/blob/master/Llama3DLibrary/src/com/llama3d/object/graphics/image/ImageBase.java
Here an example how it looks with many images (testing artificial neural networks), it works fine, but already little bit slow with that many images... :(
I'm trying to learn OpenGL, and it's a bit daunting. To get started I am trying to use it to create some effects on a 2D image. Basically, I want to take an image (say 1000px by 1000px) and divide it into a grid of equally sized squares (say a 10 by 10 grid) and then manipulate the squares individually (like turn one square black, flip another over, make another "fall" off the screen, etc). I've followed some basic online instructions (http://blog.jayway.com/2010/12/30/opengl-es-tutorial-for-android-%E2%80%93-part-vi-textures/) on how to map a texture to a simple square, but I'm having problems with mapping the texture to a more complex arrangement of multiple squares.
1) Given a 2x2 (and larger size) grid of squares, how can I map a single texture/image over the entire grid? That is, what are the texture coordinates that OpenGL expects (and in what order) to make this work? I can't seem to wrap my head around how to figure out the order of the "UV" coordinates on a larger polygon structure.
2) Since I will ultimately be transforming, rotating, etc. each individual square of the grid, would it be better to create each square of the grid and individually divide the texture/bitmap and apply each piece of the image to each square separately? If so, do you have any recommendations on how to do efficiently divide the bitmap into pieces?
Any and all help, links, suggestions, etc. will be greatly appreciated. I'm doing this in an Android app with assumed support for OpenGL ES 2, but I assume most of the OpenGL discussion/concepts are platform agnostic. I don't want to include some large framework or toolkit to do this if possible since I want a lot of speed and minimum size.
Starting with the more important reply, #2, you really don't want to do more texture switches than you absolutely need. They're an insane performance loss.
Back to #1, the way you do this is actually quite straight forward. Your texture resides in a unit square of coordinates (0,0) to (1,1). This is called texture-space coordinates, and the axes are called U and V respectively. So each go between 0 and 1 and cover your whole image.
Now when you create your objects, vertex by vertex (through a vertex buffer or immediately), you can send a second set of coordinates, the UV texture coordinates, for each vertex. You use this to "slice up" your image into parts.
The easiest way to do your specific application is to take the vertex coordinate, divide it by the length of length of the image and multiply it by the length of the small square you're building. This will obviously not work once you start rotating your squares, but maybe it will help you visualize the process better.
Note how this is completely platform independent, you can use the same reasoning for DirectX applications or whatever!
1)I think the keyword you search for is "Texture atlas".
Some hints, but you may find better explanations on the Internet as im still learning too: (i use OpenGl 2.1, and GLSL 1.2 so ymmv)
The vertex shader has something like this:
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
attribute vec3 position;
attribute vec2 texcoord;
varying vec2 vertTexCoord;
void main()
{
vertTexCoord = texcoord;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0f);
}
in your fragment shader you do something like this:
uniform sampler2D texture;
varying vec2 vertTexCoord;
void main()
{
gl_FragColor = texture2D(texture, vertTexCoord);
}
and then, for example, if you want a 2x2 grid of squares (texture divided in 4 parts) you would have vertices like this; (assuming the squares are 1 unit wide and tall)
(uv = texcoord, vertex = position)
square1
and the next square to the right would look like this:
square2
It's kinda important to remember that while vertex coordinates can go over 1 and below 0, texture coordinates can not( always between 0 and 1).
2) I wouldn't divide the bitmap, since using texture atlases(plural?) is already quite fast, and i doubt you would gain a significant speed gain (if at all).
I hope i could help! (also sorry but i couldn't embed the images directly, please give me rep. so i can do in the future! :))