Jump to content

  • Log In with Google      Sign In   
  • Create Account


More DX 16bit queries ... ;)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
18 replies to this topic

#1 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 24 December 1999 - 05:48 AM

Hi =)

After reading through a few articles on the problems of 16bit RGB formats on vid cards, I've finally (almost) got it licked.

What I'm not sure on is how to actually implement the different variations in my code. I can detect the format etc., that isn't the problem... Hmm, this is hard to explain.

What I mean is, say I have a 5-5-5 graphics card. Pure white will therefore me (31,31,31). But say I then use the code on a 5-6-5 format graphics card... It'll be a pinky colour. Basically what I'm asking is, do I pick say 5-6-5 as my primary format (65k colours) and then reduce (ie. divide by 2 the green componet) for a 5-5-5 card etc.?

Also, is it better to (at each point in my code where I want to draw a pixel say) have an if() or switch() kinda thing or should I use a macro which encompasses everything (but has a lot of shifts...)?

I'm sorry if I haven't made sense... basically I know how to detect the format, the shifts needed etc, just not how to implement them (in an optimized way).

Any help would be appreciated

Thanks,
James


Sponsor:

#2 CJ   Members   -  Reputation: 122

Like
Likes
Like

Posted 20 December 1999 - 10:39 AM

Take a look at my homepage......in the article

32,24,16 and 8 bit.....that should explain it all........at least,.....most of it.

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm


#3 Starfall   Members   -  Reputation: 122

Like
Likes
Like

Posted 20 December 1999 - 11:44 AM

Depending on application, one way you could do this is by creating an index of 0-255 values for Red, Green and Blue. I do this like so:

unsigned short rgb_index[256][3];

Then fill the structure with colour information. The first array index points to the colour amount, the second to the colour itself (R G or B, I use R = 0 G = 1 B = 2, but you could change that if you wanted to). Now, when you want to get a finished colour, you simply say:

color = rgb_index[r_color][0] | rgb_index[g_color][1] | rgb_index[b_color][2];

As I said, there will be situations where you won't want to use this because of the way it works. However, it is one way of doing things that you might want to take a look at.

Good luck

Starfall


#4 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 20 December 1999 - 12:07 PM

Thanks a lot to you both - You've been a lot of help.

Thanks again,

James


#5 CJ   Members   -  Reputation: 122

Like
Likes
Like

Posted 20 December 1999 - 10:51 PM

Starfall......You should've explained it further how to make the LUT.

Look at

code:
DWORD* Create16bppLUT(DWORD bitMask)
{

DWORD * p_lut = new DWORD[256];
if (p_lut == NULL) return NULL;
for (__int64 i = 0; i < 256; i++)
{

p_lut[i] = DWORD((( i * __int64(bitMask)) / 255) & bitMask);

}
return p_lut;

}


And call this function like:

DWORD *Red;
Red = Create16bppLUT(ddsd.ddpfPixelFormat.dwRBitMask);

after that you can use what you said

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm


#6 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 21 December 1999 - 12:07 AM

Hi Cj,

Thanks for the extra code... a couple of things I don't get however Could you explain why you use '__int64' variable type (not sure what this is exactly). Also, why do you malloc the memory at runtime, is this faster than using a play array of say:
WORD r_LUT[256];
?

Anyway, thanks for your help,

James


#7 CJ   Members   -  Reputation: 122

Like
Likes
Like

Posted 22 December 1999 - 06:09 AM

Okay......well.....i use an __int64 for 2 reasons, reason 1 is to have it working on different systems, since an int can be different on every computer. Reason 2 is because of the DWORD the function receives. A DWORD is a 32 bit unsigned integer. So...the values will range exactly the same as __int64. Makes sense? to me it does......I might've been wrong though. Haven't tried it different yet.

And about the memory allocation on run-time. I always do that. It's kinda my behavior. And I find it easier to use a pointer to something instead......

More questions?

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm


#8 Starfall   Members   -  Reputation: 122

Like
Likes
Like

Posted 22 December 1999 - 02:13 PM

And I find it easier to use a pointer to something instead......

Come again? How's an array like he suggested any different? It's still a pointer, just preallocated for you. In fact, for all intents and purposes exactly the same as using malloc, but with less hassle. I find it far easier to allocate fixed size memory like that, anyway.

Regards

Starfall


#9 Torval   Members   -  Reputation: 122

Like
Likes
Like

Posted 22 December 1999 - 02:40 PM

Above where CJ used a __int64 thats a no-no. The problem is that an int64 is a microsoft specific way to hold a 64 bit integer.... which is completely unnecessary when we deal with 16 bit colors (and probably slow too since intel machines are 32 bit.) Also, I'm not sure that the array produced would be what you desire, although I haven't looked into that very much.


#10 Coder++   Members   -  Reputation: 122

Like
Likes
Like

Posted 22 December 1999 - 06:08 PM

To clear some things up. First, your best bet is to use an int, not an __int64. Like someone previously noted, __int64's are a no-no. Definately not ANSI C++ standard. For large integers, an int/long is absolutely fine. However, in this case, if memory serves form looking at that code, our values are ranging from 0 to 255. Use a char.
Second thing...this:

int MyArray[256];

and this:

int *MyArray = (int *)malloc(256 * sizeof(int));
OR
int *MyArray = new int[256];

The last two do exactly the same thing. They are just different versions of each other. However, a pre-allocated array only uses the stack to store the array. Once it's out of scope, the array no longer exists. Using malloc() or new dynamically allocates it, and the memory is available until you call free() or delete[]. Therefore, they are not the same thing.


#11 CJ   Members   -  Reputation: 122

Like
Likes
Like

Posted 22 December 1999 - 10:46 PM

Everybody has another style of coding, and after examining what you said. I agree......

I will always use new and delete functions. Everybody his liking. And......you are right about the __int64 thingy.....just an int works just fine too...........

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm


#12 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 23 December 1999 - 01:27 AM

Hey,

Thanks for all your replies guys, most useful

Have just been looking on directxfaq.com, and found this article; http://www.directxfaq.com/kbase/ddraw/16bitspixels.htm

The code in it looks pretty similar to CJs
Infact, I'd say identical heh.

Anyway, thanks a lot,

James


#13 Starfall   Members   -  Reputation: 122

Like
Likes
Like

Posted 23 December 1999 - 02:10 AM

I think you missed my point, Coder++. Using a global array is, in this case, much the same as using a pointer to memory allocated at startup and deallocated at shutdown. As CJ says, everyone has their style, and that is the style I find most simple to use for such things.

Also, using a char in this code would not be such a good idea. Even an unsigned char would still overflow when incremented at 255, and thus the for loop would not catch it.

My advice is to not bother to be frugal about counter variables and such. You're far more likely to cause more trouble than you save.

Regards

Starfall


#14 CJ   Members   -  Reputation: 122

Like
Likes
Like

Posted 23 December 1999 - 02:36 AM

jAMES,
hat's right, it's the place where I got it from a long time ago, I lost the url though. I've been using it for quite a while, but i changed to 24 bit these days. I got a good understanding about 16 bit, and will probably soon write a better thing.

I'm just wondering, what would be faster? To shift? or to use a LUT.....what's more important? speed or memory? I would say a LUT is still faster........

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm


#15 Jim Adams   Members   -  Reputation: 440

Like
Likes
Like

Posted 23 December 1999 - 07:22 AM

James -
An easy way is similar to using Starfalls-
just create an array that converts from 555 to the screen format and one that converts back:

unsigned short clr_555_to_fmt[32768];
unsigned short clr_fmt_to_555[65536];

All colors would pass through the first array before displaying them, and if you need to read information back, pass them through the 2nd.

The reason they are different sizes is the first only takes a 555 amount, and the second possibly uses 565.

If this doesn't make much sense, let me know and I'll type something better -- I'm at work right now.


Now, about using malloc and static arrays:
it doesn't really matter. It's just coding style. It some cases though, using a static array will bloat the .exe file.

As for using int and such, you have to remember that int is not a fixed size - it will vary from machine to machine and depending on the compiler.

Use short for 16 bit, and long for 32 bit
(on a x86 machine at least).

Jim


#16 Anonymous Poster_Anonymous Poster_*   Guests   -  Reputation:

Likes

Posted 23 December 1999 - 08:08 AM

Hi Jim,

Thanks for your reply, I *think* I get you, but could you kindly exemplify the creation of the LUT a little?

I'd appreciate it

Thanks,
James

btw, Lightbefallen is looking amazing!


#17 Jim Adams   Members   -  Reputation: 440

Like
Likes
Like

Posted 23 December 1999 - 05:24 PM

James-

Here's what I do: All my tiles are stored in a 555 format, just because I definately know that's what it is. All color calculations performed are 555 no matter what.

When it comes time, say to load a tile into the cache, it will pass through a conversion function to convert to the screen format.

So, let's say we have a 32x32 tile stored at 555 format and this is my loading function:

for(i=0;i<32;i++) {
fread(&buf, 1, 32*2, fp);
for(j=0;j<32;j++)
buf[j] = clr_555_to_fmt[buf[j]];
buf += page.lpitch;
}

I never have to worry what the screen format is. Let's assume I'm reading a pixel from a screen buffer or tile buffer or whatever to work on:

color = page.ptr[12];
color555 = clr_fmt_to_555[color];

Then I do color conversions based on 555 format to color555 variable, then I can write it back:

page.ptr[12] = clr_555_to_fmt[color555];


Now, to setup the conversion tables, just do this:

unsigned short clr_555_to_fmt[32768];
unsigned short clr_fmt_to_555[65536];

for(i=0;i<65536;i++) {
// convert 555 to format
if(i < 32768) {
red = (i >> 10) & 31;
green = (i >> 5) & 31;
blue = i & 31;
clr_555_to_fmt[i] = (red << 11) | (green << 5) | blue;
}

// convert format to 555 - assume 565
red = (i >> 11) & 31;
green = (i >> 5) & 31;
blue = i & 31;
clr_fmt_to_555[i] = (red << 10) | (green << 5) | blue;
}

Please excuse me if this is a little off - I'm trying to do this from memory, but it looks right. You should get the idea.

Just create a better one that shifts and arranges the colors based on the info you get from GetSurfDesc.


Thanks about TLB. It's being totally revamped - we have a new graphics and sound engine, plus some awesome stuff going in - we hope to have a new demo in the next couple of months.


Jim Adams



#18 DaJudge   Members   -  Reputation: 138

Like
Likes
Like

Posted 24 December 1999 - 02:14 AM

As already mentioned there is no reason to use an _int64 for creating portable apps, 'cause it's MS specific. And I don't think it's reasonable to talk about portability when writing apps for DirectX. I'd really like to see a port of DirectX to a system that does not use the same size for an int.

CU,
Alex

------------------
Alexander Stockinger
Programmer


#19 Jim Adams   Members   -  Reputation: 440

Like
Likes
Like

Posted 24 December 1999 - 05:48 AM

Regarding ints and DX - do you know what size an int is on the dreamcast? Is it use 32 or 64 bit registers?

As far as porting, you can alway generalize function calls and use DX in those. When you port, simply change a couple routines and it's done.


Jim





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS