Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Shader output is blocky

This thread is locked; no one can reply to it. rss feed Print
Shader output is blocky
The Master
Member #4,498
April 2004
avatar

Hi all,

Experimenting with shaders.

Just using a really simple pixel and vertex shader, based off the examples:

// The vertex shader.
attribute vec4 al_pos;
attribute vec4 al_color;
attribute vec2 al_texcoord;
uniform mat4 al_projview_matrix;
varying vec4 varying_color;
varying vec2 varying_texcoord;
void main()
{
   varying_color = al_color;
   varying_texcoord = al_texcoord;
   gl_Position = al_projview_matrix * al_pos;
}

// THE PIXEL SHADER
varying vec4 varying_color;

void main( void ) 
{
  gl_FragColor = varying_color;
}

I assume that "varying_color" is passed between these two programs. Here is the my program without shaders.

In the attachments, "snapshot2.png" is my program with the shader; "snapshot3.png" is my program without it.

Is there any reason why this is happening?

I have very minimal experience with shaders.

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

al_color is the vertex color. Most geometry is sent as two triangles forming a quad, where the vertex color is the tint value in the al_draw_tinted* arguments (among others).

You aren't reading the texture data. According to the manual, the current texture is automatically bound to al_tex.

So you need to change your pixel shader to:

uniform sampler2D al_tex;

varying vec4 varying_color;
varying vec2 varying_texcoord;

void main( void ) 
{
  vec4 tex_sample = texture(al_tex, varying_texcoord);
  gl_FragColor = tex_sample * varying_color;
}

The Master
Member #4,498
April 2004
avatar

Thanks for the reply.

However, it shows black now. When I touch certain widgets, it doesn't show the text as blocky anymore. Instead it shows a black screen until I find one of the list cells (snapshot5.png). If I touch the bottom-most cell in the list, I get the corresponding window appearing (snapshot4.png). All of these, except the text, are drawn with the primitive drawing functions with no textures.

Is it possible I have misused the primitive drawing functions?

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

Oh, you don't want to use al_tex if you aren't performing textured rendering. You'll get garbage values depending on the previous render commands.

If no texture is set, for example, tex_sample will be (0, 0, 0, 0), which will result in a black image. If, say, the font texture is set from previously drawing some text, you'd retrieve a pixel from the font atlas, which will cause a darkening effect if the font is stored in a greyscale or greyscale-alpha format.

You can use a different shader for textured and non-textured rendering, or use a small (e.g., 1x1) white texture when rendering non-textured primitives so the multiplication is essentially a no-op.

The Master
Member #4,498
April 2004
avatar

Hey, I did that and it worked perfectly... For a while. Seriously, shaders are a little bipolar.

I wanted to see the effects of the shader on a bitmap. Now, I'm not using al_draw_bitmap for this. Instead, I've used a textured quad.

Why is it that when I draw without the shader, I get 'snapshot6.png', but if I use the shader, I get 'snapshot7.png'?

I know what's happenning. See, when I use the textured quad, I specify the UV coords in bitmap space (i.e. number of pixels in the bitmap). And this works without the shader. When I use the shader, I have to normalise it down to 0-1 like I always thought I should (I also have to flip the vertical coordinate, because the texture comes out upside down). I just don't understand why it works one way but not the other. This is really inconsistent.

Also, my untextured quads that make up the UI are now not being drawn properly. For some reason, they're being shrunk to tiny size (look closely at the top-left of where the window should be. I do use an orthogonal transform as the projection transform for the UI and an identity transform as the main world transform. It seems the shader I've written is a little screwy.

Clearly I have completely missed something somewhere....

EDIT 1:
I use the textured quad instead of al_draw_bitmap because I needed to add a Z component. :)

EDIT 2:
Tried using the al_tex_matrix in the shader, but this caused stack-smashing at shader compile time... :-S

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

Are you using the built-in ALLEGRO_VERTEX? If not, can you provide the vertex structure, vertex declaration, vertex data, and parameters to al_draw_prim (or whichever low-level primitive drawing routine you are using)?

The Master
Member #4,498
April 2004
avatar

Yes I am. Here's my drawing code.

#SelectExpand
1/** 2 * Draw the bitmap. 3 * @param srcRect The sub-rect within the bitmap to draw. 4 * @param dstRect The screen rectangle in which to draw the bitmap. 5 * @param z The location of the rectangle within the scene. 6 * @param tint The colour to tint the bitmap. 7 */ 8void BitmapAsset::Draw( AppFramework2::Geometry::Rect srcRect, AppFramework2::Geometry::Rect dstRect, AppFramework2::Math::Real z, AppFramework2::Graphics::Colour tint ) const { 9 10 ALLEGRO_VERTEX vertices[] = { 11 { dstRect.location.x, dstRect.location.y, z, srcRect.location.x, srcRect.location.y, tint }, 12 { dstRect.size.x+dstRect.location.x, dstRect.location.y, z, srcRect.size.x + srcRect.location.x, srcRect.location.y, tint }, 13 { dstRect.location.x, dstRect.size.y+dstRect.location.y, z, srcRect.location.x, srcRect.size.y + srcRect.location.y, tint }, 14 { dstRect.size.x+dstRect.location.x, dstRect.size.y+dstRect.location.y, z, srcRect.size.x + srcRect.location.x, srcRect.size.y + srcRect.location.y, tint } 15 }; 16 17 al_draw_prim( &vertices, NULL, mBitmapData, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP ); 18 19}

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

The texture coordinates for ALLEGRO_VERTEX are ALLEGRO_PRIM_TEX_COORD_PIXEL, which are measured in pixels. You want to use ALLEGRO_PRIM_TEX_COORD, which are normalized. When using al_draw_prim, if you pass NULL as the const ALLEGRO_VERTEX_DECL* decl parameter, the default vertex declaration will be used.

Try creating a custom vertex declaration for ALLEGRO_VERTEX, where the texture coordinates are ALLEGRO_PRIM_TEX_COORD:

ALLEGRO_VERTEX_ELEMENT elements[] = {
   { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_3, offsetof(ALLEGRO_VERTEX, x) },
   { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ALLEGRO_VERTEX, u) },
   { ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ALLEGRO_VERTEX, color) },
   { 0, 0, 0 }
};

ALLEGRO_VERTEX_DECL* custom_decl = al_create_vertex_decl(elements, sizeof(ALLEGRO_VERTEX));

Do that in some single place, kind of like how you'd only create or load a bitmap once. Then provide custom_decl as an argument to al_draw_prim, as so:

al_draw_prim( &vertices, custom_decl, mBitmapData, 0, 4, ALLEGRO_PRIM_TRIANGLE_STRIP );

Everything else should be able to stay the same, assuming you're using normalized texture coordinates.

The Master
Member #4,498
April 2004
avatar

Ok, that fixed the issue with the scale of the texture coords. But not the fact that it vertically flips the texture when the shader is in use. This also doesn't fix the scaling issue of my untextured primitives.

EDIT:
I added this line to my fragment shader:

varying_texcoord.y = 1 - varying_texcoord.y;

which flips the y coordinate of the texture.

However, notice what happens to the UI quads? (See the attachment) The fill areas are flipped vertically as well. I was sure to draw them with the custom vertex declaration too.

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

(0, 0) is the bottom-left corner in OpenGL and GLSL, not top-left as with most everything else (Allegro, DirectX, etc). Since you're using GLSL, you'll have to adjust your coordinates accordingly.

I'm not sure about the untextured primitives. How do you use the shader? How do you render the untextured primitives?

The Master
Member #4,498
April 2004
avatar

Fair enough. Can't do much about that then. I'll just remember to add that line to all my shaders... Now if I can just get the untextured quads working...

We can only do what we feel is right each moment as we live it.

Aaron Bolyard
Member #7,537
July 2006
avatar

Are you using a blank, white texture, or a shader that doesn't use the texture, for the untextured quads?

The Master
Member #4,498
April 2004
avatar

Blank white texture 1x1.
It's all being run with a single shader.

We can only do what we feel is right each moment as we live it.

Go to: