gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Single texture multiple times on a polygon

#108241 - Rajveer - Mon Nov 06, 2006 11:09 pm

Hi guys. I have a small 16x16 polygon which I want to put onto a polygon multiple times, is this possible?

[Images not permitted - Click here to view it]

#108246 - DiscoStew - Tue Nov 07, 2006 12:37 am

Yes, but to do this, you need to do 2 thing.

1) Set bits 16 and 17 of the texture image parameters. Those will have the texture repeat in both directions.
2) Coordinates. In order to make the texture repeat, you need to set the coordinates to be outside the range of 0.0 and 1.0. If you wanted your texture to repeat just twice in both directions, using 2.0 instead of 1.0 on the edges will do the trick. You can even change values of 0.0 to -2.0, and get the texture repeating 4 times in each direction. Remember, both values are 1bit sign + 11bit integer + 4bit fractional part.

I'm sure others will be a lot more explanation-friendly, as I am still getting the hang of this,
_________________
DS - It's all about DiscoStew

#108254 - Payk - Tue Nov 07, 2006 1:16 am

interesting...didnt knowed about that...

#108255 - Rajveer - Tue Nov 07, 2006 1:24 am

Sweet, cheers DiscoStew. Its the GFX_TEX_FORMAT register. One noob question, how do you switch bits of a register?

#108259 - HyperHacker - Tue Nov 07, 2006 3:04 am

Bit-manipulating operators such as AND (& in C), OR (|), and XOR (^). Look them up, you might find other useful info.
_________________
I'm a PSP hacker now, but I still <3 DS.

#108267 - Rajveer - Tue Nov 07, 2006 5:59 am

I'm reading up but finding it a bit complicated. I understand everything such as binary, hex, e.t.c, and understand alot of whats behind it. But I just dont know how to actually do it. If I wanted to switch GFX_TEX_FORMAT's 16th and 17th bit, I would switch those bits with

var |= GFX_TEX_FORMAT(16);
var |= GFX_TEX_FORMAT(17);

But I dont understand why you need a variable var?

#108269 - sajiimori - Tue Nov 07, 2006 7:16 am

Sometimes writing to an I/O register can be slow, so building up the value (in a temporary variable) and writing it once can be a good approach.

Other times, I/O registers are write-only, so you can't use bitwise operators on their current contents.

I don't know if either of these things apply in your situation, but the important thing is the final value that is written to the register.

#108270 - DiscoStew - Tue Nov 07, 2006 7:17 am

Rajveer wrote:
I'm reading up but finding it a bit complicated. I understand everything such as binary, hex, e.t.c, and understand alot of whats behind it. But I just dont know how to actually do it. If I wanted to switch GFX_TEX_FORMAT's 16th and 17th bit, I would switch those bits with

var |= GFX_TEX_FORMAT(16);
var |= GFX_TEX_FORMAT(17);

But I dont understand why you need a variable var?


Well, I think you've got them mixed up.

Because you can't read from the GFX_TEX_FORMAT register, you have to hold information in a temporary variable if you wish to change it. After you've made all the changes, you can then set the information in that variable into the register.

For your particular example, let me show you how it would be done...
Code:

//If var is the temporary variable...
var |= BIT16;
var |= BIT17;

//When everything is ready to be set into the register...
GFX_TEX_FORMAT = var;


This is assuming constants for BIT0 - BIT31.
However, you are doing an OR on the variable to set bits. To be able to unset the bits, do this (example BIT16)

var &= ~BIT16;

This takes BIT16, and flips all bits on it with ~, and then ANDs it to var. Pretty much it keeps everything in var except for bit 16. This method isn't just for single bits, but can be used for multiple bits at once. For instance...

var &= ~0x00000003;

...which is the same as doing...

var &= ~(BIT0 | BIT1);

...Pretty much bits 0 and 1 are unset in var.

Perhaps I've gone a little bit indepth in this.
_________________
DS - It's all about DiscoStew

#108277 - Rajveer - Tue Nov 07, 2006 11:38 am

Cheers guys for the help, I think I got all of that :). One more thing, if I'm to store my data as a variable which I "feed" into a register, how would I know which variable type to choose? I'm guessing it should be unsigned firstly, and since the register I want in particular has a width of 32 bits, I'd choose an unsigned variable of size 32 too (but which type?)

P.S. Do all registers have a width of size power of two?

#108284 - tepples - Tue Nov 07, 2006 2:08 pm

Rajveer wrote:
if I'm to store my data as a variable which I "feed" into a register, how would I know which variable type to choose?

libgba and libnds define the types u8, u16, and u32.

Quote:
P.S. Do all registers have a width of size power of two?

In 8-bit, 16-bit, 32-bit, and 64-bit systems, yes.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#108286 - Rajveer - Tue Nov 07, 2006 2:33 pm

Can somebody tell me if I'm thinking about this correctly?

Ok GFX_TEX_FORMAT is a 32 bit register, so to be able to switch its bits I need to define a u32 which I'll call repeatTexSwitch. I want to switch two bits together so I need 2 bits together: first I'll say
Code:
u32 repeatTexSwitch= 3;

so that I get two bits "switched on" in my variable together. Then I shift the variable left 16 places...or I could say
Code:
u32 repeatTexSwitch= 98304

which will give me the bits I need in the right place anyways.

Then to switch the 16th and 17th bits of the register on, I need to use the OR operation with the register and the switch variable, like so:

Code:
GFX_TEX_FORMAT = GFX_TEX_FORMAT | repeatTexSwitch<<16
(if I used repeatTexSwitch = 3)
or
Code:
GFX_TEX_FORMAT = GFX_TEX_FORMAT | repeatTexSwitch
(if I used repeatTexSwitch = 98304)

#108295 - DiscoStew - Tue Nov 07, 2006 4:12 pm

One thing you probably should learn not to do is not use what is called "magic numbers". What those are are values that mean something, yet have no type of description to go with them. They just magically work. I apologize that I used it a little in my last post, but only to get a point across. What you want to do to make sure what is going on with what you want, make your values #define, or if you are using something like libnds, use what they have provided. For the repeating texture, they have defines called GL_TEXTURE_WRAP_S (which is [1 << 16]) and GL_TEXTURE_WRAP_T (which is [1 << 17]). IMO, as far as setting bits in your temporary variable, set them as if that variable were the register itself. Your 2nd repeatTexSwitch is just about like that, except for the "magic number" part. Instead, do this using the defines I showed.

Code:
u32 texFormat = GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T

I changed the variable name to have it represent that it is the entire register, not just the bits you want it to set. Make sure that you set whatever else is needed in the variable for the register too, as this will be fed into it.

As was said before, that register can not be read from, so the code you provided won't work (at least on hardware)
_________________
DS - It's all about DiscoStew

#108297 - Rajveer - Tue Nov 07, 2006 4:24 pm

Cool, cheers for your time DiscoStew. So there are defines for all of the bits in all of the registers? And if not then programmers tend to make their own defines at the start of their code?

If I were to use the proper defines, from what you've told me and what I've learnt I would use

Code:
u32 texFormat = GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T;
GFX_TEX_FORMAT = texFormat;


I'm sure I'm still doing it wrong since it's not working. I'm putting it before I call glBindTexture to test wrapping on a quad but no luck.

#108380 - HyperHacker - Wed Nov 08, 2006 10:15 am

One thing you should note too is that any decent compiler will break down expressions to the simplest possible form before compiling them. So if for some silly reason you write
Code:
#define SOMETHING (2<<3)
#define SOMETHING_ELSE (2<<4)

Variable = (SOMETHING | SOMETHING_ELSE) + (((5*4) / 20) - 1);

the compiler will automatically break it down like so:
Code:
Variable = (SOMETHING | SOMETHING_ELSE) + (((5*4) / 20) - 1);
Variable = ((2<<3) | (2<<4)) + ((20 / 20) - 1);
Variable = (16 | 32) + (1 - 1);
Variable = 48 + (1 - 1);
Variable = 48 + 0;
Variable = 48;


What this means is you don't lose any speed by writing a big complicated expression with a bunch of constants (the first line) as opposed to a single number (the second), since the compiler will treat both the same way.
_________________
I'm a PSP hacker now, but I still <3 DS.