VB:Tutorials:Generic information about RGB

From GPWiki

Files:GUITutorial_warn.gif The Game Programming Wiki has moved! Files:GUITutorial_warn.gif

The wiki is now hosted by GameDev.NET at wiki.gamedev.net. All gpwiki.org content has been moved to the new server.

However, the GPWiki forums are still active! Come say hello.

Contents

Function: RGB

Hi there,

Most of you allready know about RGB and what its all about. No? Shame on you... ;)

RGB (Red Green Blue) is the color combination computers use, hence also us computer programmers. Most of you also know that VB offers very poor functions for handling colors.

The best example for this is the RGB function:

dim cRed as long
 cRed = RGB(255, 0, 0) 'eek! 

Anybody see anything wrong with this picture? Well, the code is solid, but the result is way off. Instead of getting the color "vbRed" we actualy get blue. The VB RGB function reverses the RGB input for some unknown reason, so to get red we have to turn everything upside-down:

dim cRed as long
 cred = RGB(0, 0, 255) 'right! 

So, my advice to you who deal with RGB values (i know i do), here is an extremely simple function to avoid confusion:

Function cRGB(R as Integer, G as Integer, B as Integer) as Long
   cRGB = RGB(B, G, R)
 End Function

And so we get:

dim cRed as long
 cRed = cRGB(255, 0, 0) 'right! 

Converting long colors to RGB values

Now on to the next problem. VB dont have any built-in function to convert the RGB values back from a long value to 3 integers.

Why? We dont know. But neverthenless its simple. The long colors are no unexplainable "voodoo mumbo-jumbo" and even if the value looks alien and unknown, it wont look that fancy when you know the math behind it.

cRed = 200
 cGreen = 120
 cBlue = 35
 cColor = cRGB(cRed, cGreen, cBlue)
 MsgBox cColor '13137955 

Here is a typical RGB in a long value. Now, how to retrive the individual values?

Well, we'll start by counting how many times "65536" fits in cColor (cRed = int(cColor / 65536)). That should give us the red segment.

Now we take cColor - red segment multiplied by 65536 divided by 256 (cGreen = int(cRed * 65536) / 256)

Then the rest is the blue segment. Hard nut to chew? Well, it also has its advantages. A single long value is smaller then 3 ints, so it cuts down size alot - specialy when dealing with larger images - then again it requires more speed if you need to retrive the individual values.

Enough chatting, lets bring on a snippet to demonstrate - perhaps it will look clearer:

shiftRed = 65536 'shiftGreen * shiftGreen (256*256)
 shiftGreen = 256 'max colors times max colors (256)
 cRed = 200
 cGreen = 120
 cBlue = 35
 cColor = cRGB(cRed, cGreen, cBlue)
 msgbox ccolor 'the long color
 cRed = cint(cColor / shiftRed)
 cGreen = cint((cColor - cRed * shiftRed) / shiftGreen)
 cBlue = cColor - int(cRed * shiftRed) - int(cGreen * shiftGreen)
 msgbox "Red: " & cRed & vbcrlf & "Green: " & cGreen & vbcrlf & "Blue: " & cBlue

Fine, so what do we do with this?

Just like turning radians to degrees, we convert long colors to RGB when we need a human readable conversion for manipulating the result. (phew)

An example is when you need to blend 2 colors in DirectDraw. Some say it cant be done (bah), others say that the answer is to make a DD/D3D hybrid engine.

Well, you can belive what you want to belive - but myself i need to create "shadows" in my C&C clone, so we'l use this as an example.

const shadow = 0.65 'lets darken the src by 35%
 srcColor = point(x, y)
 srcRed = cint(srcColor / shiftRed)
 srcGreen = cint((srcColor - srcRed * shiftRed) / shiftGreen)
 srcBlue = srcColor - int(srcRed * shiftRed) - int(srcGreen * shiftGreen)
 destColor = cRGB(int(srcRed * shadow), int(srcGreen * shadow), int(srcBlue * shadow))
 pset(x, y), destColor

What about alpha blending?

image:alpha_blending.jpg

I know for a fact that people have problems with alpha blending.

Using OpenGL in C its easy enough by just 2-3 lines of code to enable just about any kind of blending - since the blending functions are integrated - but in VB we have to come up with the formula on our own...

image:alpha_equation.gif

As we see;

finalrgb = a*rgb1 + (1-a)rgb2

Another way to describe the formula is: (taken from wikipedia)

Value = Value0(1.0 - Alpha) + Value1(Alpha)

This will be slower to do pixel per pixel compared to doing it with alpha quads in a hybrid engine - but the advantage is in detail. We can now very precisely per pixel alpha small segments of images.

Optimize

Our main problem (as always) is speed. The more calculations the lesser speed we have left.

I heard some discussion about wether the FPS matters or not, well - if you have a amd64x2 4600+ system and run your game at a "floating" 35 fps - how well do you think it will be running on lesser systems?

The first thing id like to point out is not to use VB's builtin point/pset as used in the sample above - but to use DXDD or some similar graphical acceleration.

Another tip is to use the byte type for defining individual RGB colors, since they cant go over the value 255 anyway.

As a rule - dont pixel-per-pixel plot more than is needed, dxdd7 blt's way faster.

Also you should find some more optimized way to retrive the RGB values of long colors, prefferably as a function for reuseability. The above sources are not optimized, but just to basicly show the works.

Sample project

I prepared a demonstration source of alpha blending - i know a few people will thank me for it :-)

Credits

Hope this were interesting :-)

Written by: Darksnow 15:06, 22 April 2006 (EDT)