Sprite quads & depth testing correctly in OpenGL ES 2 - opengl-es

I am trying to render 2D (flat) sprites in a 3D environment using OpenGL ES 2. The way I create each sprite is pretty standard: I create a quad consisting of two triangles, and I map the texture onto that. Everything works fine, except I noticed something strange: when depth testing is turned on (which it should be in 3D mode), the corners of my sprites are painted using the background color.
The easiest way to show this is by illustration:
When I turn off depth testing (on the left) it looks fine, but when I turn it on (on the right) you can see the green sprite's rectangle overlapping on top of the yellow sprite. They both use the same code, the same PNG file, the same shader. Everything is the same except depth testing.
I'm hoping someone might know a way to work around this.

What you can do is alpha testing. Basically your texture has to have an alpha value of 0 where it should be transparent (which it may already have). Then you configure alpha test like e.g.
glAlphaFunc(GL_GREATER, 0.5f);
glEnable(GL_ALPHA_TEST);
This way every pixel (or better fragment) with an alpha value <= 0.5 will not be written into the framebuffer (and therefore not into the depth buffer). You can also do the alpha test yourself in the fragment shader by just discarding the fragment:
...
if(color.a < 0.5)
discard;
...
Then you don't need the fixed-function alpha test (I think that is the reason why it is deprecated in modern desktop GL, don't know about ES).
EDIT: After looking into the ES 2.0 spec, it seems there is no fixed-function alpha test any more, so you will have to do it in the fragment shader like written above. This way you can also make it dependent on a specific color or any other computable property instead of the alpha channel.

Related

Alpha Blending and face sorting using OpenGL and GLSL

I'm writing a little 3D engine. I've just added the alpha blending functionality in my program and I wonder one thing: do I have to sort all the primitives compared with the camera?)
Let's take a simple example : I have a scene composed by 1 skybox and 1 tree with alpha blended leafs!
Here's a screenshot of a such scene:
Until here all seems to be correct concerning the alpha blending of the leafs relative to each others.
But if we get closer...
... we can see there is a little trouble on the top right of the image (the area around the leaf forms a quad).
I think this bug comes from the fact these two quads (primitives) should have been rendered later than the ones in back.
What do you think about my supposition ?
PS: I want to precise all the geometry concerning the leafs is rendered in just one draw call.
But if I'm right it would means when I need to render an alpha blended mesh like this tree I need update my VBO each time my camera is moving by sorting all the primitives (triangles or quads) from the camera's point of view. So the primitives in back should be rendered in first...
What do you think of my idea?

OpenGL ES 1.1 - texture and alpha and color key

Using OpenGL ES 1.1.
The picture I am generating is being color-keyed later on down the line. It replaces one color (magenta) with something else.
So I clean the background with that color, draw on top of it, and everything is good.
However, textures with an alpha channel cause some complications. I effectively want to use only maximum or minimum alpha, and show the background OR show the image blended with, say, black.
My mostly-working hack has the texture data manually adjusted force the alpha channel to either min or max, and do pre-multiplication for the actual color value, and this mostly works.
However, when the texture size changes, I get a little bit of filtering and some magenta goes through.
So:
1) Is there some combination of glBlendFunc and glTexEnv combiner functions that will let me stop manually editing the textures?
or, failing that....
2) What parameters should I use when drawing the texture to keep alpha at either 0 or 1 when it's scaling?
Use alpha testing instead of blending. Use glAlphaFunc to select a comparision function and reference value. Enable with glEnable(GL_ALPHA_TEST) (and disable once you no longer need it during rendering).

Drawing an outline around the non-transparent part of a texture

Tinkering with the feature set for a new game, i'm considering including a PVP gameplay mode. Nothing like NI after kicking the AI so smithereens :). iSomething only. Willing to restrict to modern devices.
One option I would consider to differentiate the characters for each player on the map would be to add 'on the fly' a 2-point outline of different colours to the characters of each player (others options exist, but have weight considerations for the resources).
I have not found on here (nor elsewhere for that matter) any very useful answers to this kind of requirement, nor am I an GL expert by a far cry. If any one of you could point me in the direction of some tutorials, I would greatly appreciate. TIA
I wasn't recommending that you necessarily put the outlines into separate textures. What I was imagining was that you have a sprite with a region that is all alpha = 1.0, surrounded by a transparent region of alpha = 0.0.
One idea could be to draw a couple pixel wide ring around the opaque region with something like alpha = 0.5.
If you then want to draw your sprites without a border, you can just alpha test for alpha > 0.75, and the border will not appear. If you want to draw a border, you can alpha test for alpha > 0.25, and use a fragment shader to replace all pixels with 0.4 < alpha < 0.6 with a colored border of your choice.
This becomes more difficult if your images use partial transparency, though in that case you could maybe block off the range from 0.0 to 0.1 for alpha metadata like the border.
This would not require any additional textures to be used or increase the size of any of the existing resources.

How to draw "glowing" line in OpenGL ES

Could you please share some code (any language) on how draw textured line (that would be smooth or have a glowing like effect, blue line, four points) consisting of many points like on attached image using OpenGL ES 1.0.
What I was trying was texturing a GL_LINE_STRIP with texture 16x16 or 1x16 pixels, but without any success.
In ES 1.0 you can use render-to-texture creatively to achieve the effect that you want, but it's likely to be costly in terms of fill rate. Gamasutra has an (old) article on how glow was achieved in the Tron 2.0 game — you'll want to pay particular attention to the DirectX 7.0 comments since that was, like ES 1.0, a fixed pipeline. In your case you probably want just to display the Gaussian image rather than mixing it with an original since the glow is all you're interested in.
My summary of the article is:
render all lines to a texture as normal, solid hairline lines. Call this texture the source texture.
apply a linear horizontal blur to that by taking the source texture you just rendered and drawing it, say, five times to another texture, which I'll call the horizontal blur texture. Draw one copy at an offset of x = 0 with opacity 1.0, draw two further copies — one at x = +1 and one at x = -1 — with opacity 0.63 and a final two copies — one at x = +2 and one at x = -2 with an opacity of 0.17. Use additive blending.
apply a linear vertical blur to that by taking the horizontal blur texture and doing essentially the same steps but with y offsets instead of x offsets.
Those opacity numbers were derived from the 2d Gaussian kernel on this page. Play around with them to affect the fall off towards the outside of your lines.
Note the extra costs involved here: you're ostensibly adding ten full-screen textured draws plus some framebuffer swapping. You can probably get away with fewer draws by using multitexturing. A shader approach would likely do the horizontal and vertical steps in a single pass.

How to create a shader to mask using a degree offset from a central point?

I'm a little bit lost, and this is somewhat related to another question I've asked about fragment shaders, but goes beyond it.
I have an orthographic scene (although that may not be relevant), with the scene drawn here as black, and I have one billboarded sprite that I draw using a shader, which I show in red. I have a point that I know and define myself, A, represented by the blue dot, at some x,y coordinate in the 2d coordinate space. (Lower-left of screen is origin). I need to mask the red billboard in a programmatic fashion where I specify 0% to 100%, with 0% being fully intact and 100% being fully masked. I can either pass 0-100% (0 to 1.0) in to the shader, or I could precompute an angle, either solution would be fine.
( Here you can see the scene drawn with '0%' masking )
So when I set "15%" I want the following to show up:
( Here you can see the scene drawn with '15%' masking )
And when I set "45%" I want the following to show up:
( Here you can see the scene drawn with '45%' masking )
And here's an example of "80%":
The general idea, I think, is to pass in a uniform 'A' vec2d, and within the fragment shader I determine if the fragment is within the area from 'A' to bottom of screen, to the a line that's the correct angle offset clockwise from there. If within that area, discard the fragment. (Discarding makes more sense than setting alpha to 0.0 or 1.0 if keeping, right?)
But how can I actually achieve this?? I don't understand how to implement that algorithm in terms of a shader. (I'm using OpenGL ES 2.0)
One solution to this would be to calculate the difference between gl_FragCoord (I hope that exists under ES 2.0!) and the point (must be sure the point is in screen coords) and using the atan function with two parameters, giving you an angle. If the angle is not some value that you like (greater than minimum and less than maximum), kill the fragment.
Of course, killing fragments is not precisely the most performant thing to do. A (somewhat more complicated) triangle solution may still be faster.
EDIT:
To better explain "not precisely the most performant thing", consider that killing fragments still causes the fragment shader to run (it only discards the result afterwards) and interferes with early depth/stencil fragment rejection.
Constructing a triangle fan like whoplisp suggested is more work, but will not process any fragments that are not visible, will not interfere with depth/stencil rejection, and may look better in some situations, too (MSAA for example).
Why don't you just draw some black triangles ontop of the red rectangle?

Resources