2

Explanation

I'm generating textures for UI elements that have a single pixel outline on the edge of the texture.

The method of setting the color data in the texture is limited to passing a one dimensional array of color values.

These textures are 2D, so they are basically rectangles. I need to be able to identify when the current pixel is at an edge. This is how I currently do it:

Color[] colorData = new Color[width * height];
        for (int p = 0; p < colorData.Length; p++) {

            //Top
            if (p < width - 1) {

                colorData[p] = DefaultOutlineColor;
            }    
            //Left
            else if(p % width == 0) {
                colorData[p] = DefaultOutlineColor;
            }
            //Right
            else if(p % height == height - outlineWidth) {
                colorData[p] = DefaultOutlineColor;
            }
            //Bottom
            else if(p >= width * (height - outlineWidth)) {
                colorData[p] = DefaultOutlineColor;
            }
            //Fill
            else {
                colorData[p] = DefaultBaseColor;
            }
        }

The Problem

Some Modulo math and what not. The problem I am having is with the Right side of the Texture. More specifically calculating the right side edge. A picture is worth a thousand words:

UI Texture

I know it is just a miss calculation in the Right edge part. But I have no idea how to make it work. Any help would be highly appreciated.

EDIT: Figured it out. Here is the working code:

        //Fill
        for (int p = 0; p < colorData.Length; p++) {

            colorData[p] = DefaultBaseColor;
        }

        //Top
        for (int p = 0; width * outlineWidth > p; p++) {

            colorData[p] = DefaultOutlineColor;
        }

        //Left and Right
        for (int p = 1; height > p; p++) {

            for (int i = 0; i < outlineWidth; i++) {

                colorData[(p * width) + i] = DefaultOutlineColor; //Left
                colorData[((p * width) - i) - 1] = DefaultOutlineColor; //Right
            }

        }

        //Bottom
        for (int p = width * height - (width * outlineWidth); colorData.Length > p; p++) {

           colorData[p] = DefaultOutlineColor;
        }
Spool
  • 77
  • 7

3 Answers3

2

Why not do it in three loops? One for the top, one for the left and right and then one for the bottom? That way you can skip all the items that don't need to be touched at all.

for(int ndx = 0; Width > ndx; ++ndx)
{
  colorData[ndx] = DefaultOutlineColor;
}

for(int ndx = 1; Height > ndx; ++ndx)
{
  colorDatandx * Widthp] = DefaultOutlineColor;
  colorData[ndx*Width + Width] = DefaultOutlineColor;}
}

for(int ndx = Width * Height - Width; Length > ndx; ++ndx)
{
  colorDatandxp] = DefaultOutlineColor;
}
Dhaval Asodariya
  • 558
  • 5
  • 19
SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
1

Using SoronelHaetir's method I figured it out. Had to edit the math a little bit. Here is the working code if anyone is interested:

        for (int ndx = 0; width > ndx; ndx++) {
            colorData[ndx] = DefaultOutlineColor;
        }
        for (int ndx = 1; height > ndx ; ndx++) {
            colorData[ndx * width] = DefaultOutlineColor;
            colorData[(ndx * width) - 1] = DefaultOutlineColor;
        }
        for (int ndx = width * height - width; colorData.Length > ndx; ndx++) {
            colorData[ndx] = DefaultOutlineColor;
        }
Spool
  • 77
  • 7
0

In practice you're doing a one-pixel border - but you use outlineWidth in your original code, so here's an alternative method that works fine for arbitrary border sizes.

for (int p = 0; p < colorData.length; p++) {
    // retrieving the x/y coords isn't expensive if you do this only once
    int x = p % height;
    int y = p / height;

    if (x < outlineSize || y < outlineSize || x >= width - outlineSize || y >= height - outlineSize) {
        colorData[p] = DefaultOutlineColor;
    }
}
  • I literally just ran into this, I thought to myself I wonder how it would look with a wider outline? Than came back here to look at the post. Thank you. Going to try this out. – Spool Jan 17 '18 at 07:12
  • This doesn't work. I'm experimenting with it right now. – Spool Jan 17 '18 at 07:23
  • Oh, I think `colorData` might be row-major instead of column-major. I'll test that when I get home; I'm used to these things always being stored column-major, so I actually didn't even check – Matt Rollins Jan 30 '18 at 15:28