简体   繁体   中英

glsl fragment shader calculate texture position

I'm writing a fragment shader for rendering a 1D texture containing an arbitrary byte array into a kind of barcode. my idea is to encode each byte into a square divided diagonally (so each of the 4 triangles represents 2 bit), like so:

 _____
|\ A /|  each byte encoded as binary is DDCCBBAA,
| \ / |  the colors are: Red   if 11
|D X B|                  Green if 10
| / \ |                  Blue  if 01
|/ C \|                  Black if 00
 ¯¯¯¯¯   so color can be calculated as: [(H & L), (H & !L), (!H & L)]

so for example: 198 == 11 00 01 10 would be:
 _____                 DD CC BB AA
|\ G /| 
| \ / | A=10=Green
|R X B| B=01=Blue
| / \ | C=00=Black
|/ b \| D=11=Red
 ¯¯¯¯¯  (B=Blue, b=Black)

what I got so far are a function for encoding 2 bools (H,L in the example notation) into a vec3 color and a function for encoding a byte and "corner index" (A/B/C/D in the example) into the color:

#version 400
out vec4 gl_FragColor; // the output fragment
in vec2 vf_texcoord; // normalized texture coords, 0/0=top/left
uniform isampler1D uf_texture; // the input data
uniform int uf_texLen; // the input data's byte count
vec3 encodeColor(bool H, bool L){
  return vec3(H&&L,H&&!L,!H&&L);
}
vec3 encodeByte(int data,int corner){
  int maskL = 1 << corner;
  int maskH = maskL << 1;
  int shiftL = corner/2;
  int shiftH = shiftL+1;
  bool H=bool((data&maskH)>>shiftH);
  bool L=bool((data&maskL)>>shiftL);
  return encodeColor(H,L);
}
void main(void) {

  // the part I can't figure out

  gl_FragColor.rgb=encodeByte(/* some stuff calculated by the part above*/);
  gl_FragColor.a=1;
}

the problem is I can't figure out how to calculate which byte to encode and in what "corner" the current fragment is.

(Note, the code here is is off the top of my head and untested, and I haven't written a lot of GLSL. The variable names are sloppy and I've probably made some stupid syntax mistakes, but it should be enough to convey the idea.)

The first thing you need to do is translate the texture coordinates into a data index (which square to display colors for) and a modified set of texture coordinates that represent the position within that square.

For a horizontal arrangement, you could do something like:

float temp = vf_texcoord.x * uf_texLen;
float temp2 = floor(temp);
int dataIndex = temp2;
vec2 squareTexcoord = { temp2 - temp, vf_texcoord.y };

Then you'd use squareTexcoord to decide which quadrant of the square you're in:

int corner;
vec2 squareTexcoord2 = squareTexcoord - { 0.5, 0.5 }
if (abs(squareTexcoord2.x) > abs(squareTexcoord2.y)) {  // Left or right triangle
    if (squareTexcoord2.x > 0) {  // Right triangle
        corner = 0;
    }
    else {  // Left triangle
        corner = 1;
    }
}
else {  // Top or bottom triangle
    if (squareTexcoord2.y > 0) {  // Bottom triangle
        corner = 2;
    }
    else {  // Top triangle
        corner = 3;
    }
}

And now you have all you need for shading:

gl_FragColor = { encodeByte(int(texelFetch(uf_texture,dataIndex,0).r), corner), 1.0 };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM