Border around texture, OpenGL
Asked Answered
N

2

8

This is a code I use to draw rectangle in my program:

glBegin(GL_QUADS);
    glTexCoord2f(0.0f, maxTexCoordHeight);              glVertex2i(pos.x, pos.y + height);
    glTexCoord2f(0.0f, 0.0f);                           glVertex2i(pos.x, pos.y);
    glTexCoord2f(maxTexCoordWidth, 0.0f);               glVertex2i(pos.x + width, pos.y);
    glTexCoord2f(maxTexCoordWidth, maxTexCoordHeight);  glVertex2i(pos.x + width, pos.y + height);
glEnd();

It draws just a simple rectangle with specified texture, e.g. like this: enter image description here

I'd like to ask if it's possible in OpenGL to achieve border effect like this:

As you see inside this tile there's just a plain blue background which could be handled separately - just automatically resized texture. This can be achieved easily with a code snippet I gave, but the problem is with border.

If the border was supposed to be one color, I could try drawing empty, not-filled rectangle by using GL_LINES around my texture, but it's not.

Also if tiles were always with a fixed size, I could prepare a texure that would match it, but they HAVE TO be easily resizable without changing a bitmap file I use as texture.

So if it's not possible with basic OpenGL functions, what are the approaches to achieve this effect that would be most efficient and/or easy?

EDIT: It has to be 2D.

Nancinancie answered 12/12, 2012 at 13:34 Comment(4)
Unless you need it to be 2d, why not actually create the bevelled effect by making that trapezoid-y shape in 3D and use the lighting to get the shaded effects you need?Verbenaceous
@Verbenaceous Thank you for the answer, but yes, it has to be 2D. I'll edit my question to add this information.Nancinancie
You could write a fragment shader to add the border. However, if you're still using immediate mode (obsolete functions like glVertex), it will probably take you a while to catch up to the wonderful world of OpenGL 2.0 and beyond.Holbrook
@Mosquito: You could still use OpenGL lighting and just modify the edges normal vectors. The actual spatial geometry doesn't matter for illumination calculations, it only happens on the user supplied normal vectors, which can be anything.Exstipulate
A
5

This is a classical problem of GUIs with OpenGL and is often solved using the 9-cell-pattern. In this, you add the effect to the original image (or define it by other opengl-parameters) and split the rendered quad in nine quads: three rows and three columns.

You then make the height of the upper and bottom row fixed, as you make the width of the left and the right column fixed. The center quad is scaled so that your object fits the rectangle you want to fit. You then map only the border parts of the texture to the quads forming the outer cells, while you map the center of the texture to the center quad.


Related to what was said in the comments, you could also use actual 3D effects by making the quad 3D. Noone forces you to use perspectivic projection in that case, you can stay with Orthogonal projection (2D-Mode). OpenGL will always do 3D-calculations anyways.

Aunt answered 12/12, 2012 at 14:10 Comment(0)
C
1

Aside from Jonas's answer, which is excellent, I want to add two more options.
The first one is to just make the texture look like your desired square. No fancy code necessary if you can do it in photoshop ;).
The second one is to complicate your drawing code a bit. If you look at your image you can see that every "side-slope" of your square can be drawn with two triangles. You can make your code draw 10 triangles instead of one square and use a different color for each group of two triangles:

draw() {
    GLFloat i = <your_inset_here>;

    //top border part, top left triangle
    glColor3f(<color_0>);
    glVertex2f(pos.x, pos.y);
    glVertex2f(pos.x + w, pos.y);
    glVertex2f(pos.x + i, pos.y + i);
    //top border part, bottom right triangle
    glVertex2f(pos.x + w, pos.y);
    glVertex2f(pos.x + w - i, pos.y + i);
    glVertex2f(pos.x + i, pos.y + i);

    //repeat this process with the other coordinates for the other three borders

    // draw the middle square using {(pos.x+i,pos.y+i),(pos.x+w-i,pos.y+i),(pos.x+w-i,pos.y+h-i),(pos.x+i,pos.y+h-i)} as coordinates
}

You can further improve this by creating a function to draw an irregularly shaped quad with the give coordinates and a color and call that function 5 times.

Countless answered 4/12, 2015 at 15:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.