1
\$\begingroup\$

I am currently writing a UV texture mapper.

But i don't know how to convert UV coordinates to texel coordinates.

And i also have no idea how i should convert texel coordinates to "array coordinates".

By "array coordinates", i mean number that represents a part of an array (in this case a bitmap).

Here is my code:

 su =  (u0)  * (tx-1) ;
 sv =  (v0)  * (ty-1) ;


 texloc = ((sv >>16)* bytes_per_row) +((su>>16)* bytes_per_pixel);

Also i use fixedpoint math to interpolate between the uv coordinates.

tx and ty are the dimensions of the texturemap.

\$\endgroup\$
1
\$\begingroup\$

WARNING: pointer math ahead.

texloc is the "array coordinate" or rather it's the byte offset:

uint32_t the_rgba8888_pixel = *((const uint32_t *) (((const uint8_t *)my_texture_data) + texloc));

Make sure you wrap u0 and v0 to (0 ... (1-epsilon)) first:

unsigned int su =  (u0 & 0xFFFF) * tx;
unsigned int sv =  (v0 & 0xFFFF) * ty;

texloc = ((sv >>16)* bytes_per_row) +((su>>16)* bytes_per_pixel);

uint8_t  pixel_8  = *((const uint8_t  *) (((const uint8_t *)my_texture_data) + texloc)); // 8bits
uint16_t pixel_16 = *((const uint16_t *) (((const uint8_t *)my_texture_data) + texloc)); // 16bits
uint32_t pixel_32 = *((const uint32_t *) (((const uint8_t *)my_texture_data) + texloc)); // 32bits

You can make this faster by pre-multiplying the UV coordinates by the texture size pre-interpolation, changing the mask to ((size-1) << 16), the shift amount and removing the multiplication of bytes_per_pixels and bytes_per_row.

For example 256x512 pixels, 32bpp:

((u0 & 0xFF0000u) >> 14) + ((v0 & 0x1FF0000u) >> 6).

That's

14 = (16 - bytes_per_pixel_as_shift_amount(4 = 1 << 2) ) 

and

6 = (16 - bytes_per_row_as_shift_amount(1024 = (256 x 4 bytes) = 1 << 10) )

This way you don't need to mask u0 and v0 first.

\$\endgroup\$
  • \$\begingroup\$ I there a non pointer math aproach? While, i do like this aproach. I am not good at pointer math. \$\endgroup\$ – user2875871 Dec 26 '14 at 22:40
  • \$\begingroup\$ Not for variable-sized arrays in C++ which you would need for different texture sizes, you will have to use linear arrays and calculate the offset yourself (pointer math) which is what texloc is. Any other solution will be slower as the compiler cannot fold the x4 or x2 (for 32bits and 16 bits) into the variable right-shifts and will need to do it in the read instruction. Although many CPUs support x4 and x2 right in the address calculation this prevents folding the variable shift right into the memory-read instruction (ARM), or may adds uOPs (x86) Practice makes perfect. \$\endgroup\$ – Stephane Hockenhull Dec 26 '14 at 23:01
  • \$\begingroup\$ And thanks to user glampert for the formatting improvements. \$\endgroup\$ – Stephane Hockenhull Dec 26 '14 at 23:01
  • \$\begingroup\$ I am using linear arrays for textures. \$\endgroup\$ – user2875871 Dec 27 '14 at 20:06
  • \$\begingroup\$ Doing array_pointer[x + y * width] is a form of pointer math. In C and C++ you can rewrite this as (array_pointer + y * width)[x] and (array_pointer + x + y * width)[0] and *(array_pointer + x + y * width) which all come down to the same result. \$\endgroup\$ – Stephane Hockenhull Dec 27 '14 at 23:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.