7 replies to this topic

#1TheJjokerR

New Member

• Members
• 12 posts

Posted 02 May 2011 - 05:52 PM

Hey guys,

Using the template here: http://www.devmaster...e-dev/part2.php

What would I have to do to make PNG's Alpha value effect in the actual game.

I need this because I want to have 2 actual layers, 1 with tiles for the terrain, and 1 on top that shows green tiles(with opacity) where you can build and red tiles(also with opacity) where you can not build.

Thanks in advance, any help is appreciated.

TJ

#2Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 02 May 2011 - 06:43 PM

Which lesson are you on? You linked to lesson 2, but I don't think PNG images show up until awhile later.

Anyway, assuming that you can already load the PNG including the alpha channel into a surface, in order to composite it onto an underlying image with alpha you'll need to write code that loops over the pixels of the tile and calculates the correct color for each individual pixel. That is, you won't be able to use the CopyTo method anymore. (Unless the IGAD framework includes a CopyTo method that does alpha compositing, which I don't think it does.)

Anyway, once you've got a loop that runs over the pixels, you'll need to extract the RGB color components of both the destination pixel (the pixel on the screen that you're writing to) and the pixel from the tile that is supposed to go over it. You'll also need the alpha component of the tile pixel. Convert the alpha to 0-1 range by converting it to a float, then dividing it by 255.0f. Then calculate:

dest_color = dest_color * (1.0f - alpha) + src_color * alpha

This calculation should be done separately for each RGB color channel. Convert back to integers, put the RGB back together into a 32-bit color value and store it in the screen buffer, and you're done.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3TheJjokerR

New Member

• Members
• 12 posts

Posted 02 May 2011 - 06:53 PM

I see what I should do, but I need a way to load the image and read it's pixels. I think it has something to do with Surface::LoadImage(), but I'm not sure..

Thanks

EDIT:

Ignore that, I can use surface->GetBuffer(), I'll be back later after trying some stuff

#4Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 02 May 2011 - 06:59 PM

I think the Surface::GetBuffer() method is what you want. Have a look at lesson 8 again; it seems to be doing similar stuff.
reedbeta.com - developer blog, OpenGL demos, and other projects

#5TheJjokerR

New Member

• Members
• 12 posts

Posted 02 May 2011 - 07:35 PM

Ok, I think I'm on the right track now, but I must've done something wrong here, because this doesn't really look right.

I've got this code so far.
tileSet[tile]->CopyTo( m_Screen, posX * 32, posY * 32 );

if(tile == 0){
}else{
}

{

}

As you can see I am using 50 as a fixed value for the alpha as I had no idea how to get the alpha value from the image.

As you can see the image looks fine like that, but after using your calculation it goes into "Trippin'-mode"(Might actually use it for some kind of power-up :P)

I figured out I'm writing to the wrong buffer. Seeing how I'm writing back to the "worldAddress" which is the buffer of the tile. Instead I should write to the screen buffer, yet I cant figure out how to get write it properly:
Pixel* screenAddress = m_Screen->GetBuffer();
{

screenAddress[((posX * 32) + readPixel / 32) + ((posY * 32) + readPixel / 32) * SCRWIDTH] = (Pixel) dest_color;
}

I did it before without any problems at all, but I lost the code and forgot how to get the positioning right.

#6Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 02 May 2011 - 08:03 PM

The alpha value should be between 0 and 1, so you should probably use 0.5 instead of 50. You didn't hear what I said about doing the math for all the RGB components independently. What you're trying to do, treating the whole Pixel struct as a single number, won't work. You need to extract the RGB components, do the math on each of them, and then put them back together into a Pixel again. See lesson 9 for more about this.

Your math for addressing the screen pixels is also wrong. Remember the destination image is not 32x32, so you need to calculate the correct address using the destination width, the posX and posY, and the x, y within the tile. You'll probably want to do separate y and x loops instead of doing one loop on readPixel.
reedbeta.com - developer blog, OpenGL demos, and other projects

#7TheJjokerR

New Member

• Members
• 12 posts

Posted 03 May 2011 - 11:05 AM

Reedbeta said:

The alpha value should be between 0 and 1, so you should probably use 0.5 instead of 50. You didn't hear what I said about doing the math for all the RGB components independently. What you're trying to do, treating the whole Pixel struct as a single number, won't work. You need to extract the RGB components, do the math on each of them, and then put them back together into a Pixel again. See lesson 9 for more about this.

Your math for addressing the screen pixels is also wrong. Remember the destination image is not 32x32, so you need to calculate the correct address using the destination width, the posX and posY, and the x, y within the tile. You'll probably want to do separate y and x loops instead of doing one loop on readPixel.

Aah man, you know I did read it, but in the excitement of getting it to work I totally forgot. Sorry!

Thanks!

_______________________________

Ok, I have tried almost everything but I can't get anything working now.. Here's the code with stuff commented out of what I tried earlier.

I first thought I could use the >> operator to get the colours out of the Pixel struct, but that didn't seem to work, then I tried using the Color struct, but that doesn't do anything with it's alpha value.

I can't even get the positioning right...

for (int readPixelX = 0; readPixelX < 32; readPixelX++)
{
{

Color extractedOriginal;
extractedOriginal.Set(float (original_color >> 16), float (original_color >> 8), (float) original_color);
Color extractedSource;
extractedSource.Set(float (src_color >> 16), float (src_color >> 8), (float) src_color);

/*
int dest_color_red = int (extractedOriginal.r * (1.0f - extractedSource.a) + extractedSource.r * extractedSource.a);
int dest_color_green = int (extractedOriginal.g * (1.0f - extractedSource.a) + extractedSource.g * extractedSource.a);
int dest_color_blue = int (extractedOriginal.b * (1.0f - extractedSource.a) + extractedSource.b * extractedSource.a);
*/
Color endColor = extractedOriginal + extractedSource;

screenAddress[((posX * 32) + readPixelX) + ((posY * 32) + readPixelY) * SCRWIDTH] = (Pixel) ((int (endColor.r) << 16) + (int (endColor.g) << 8) + endColor.b);//(dest_color_red << 16) + (dest_color_green << 8) + (dest_color_blue);
}
}

You must know that while I'm trying to make this work, I'm still reading a lot of tutorials on how to actually program in c++, so far I haven't learned anything related to stuff like this... -.-"

Thanks...

#8Reedbeta

DevMaster Staff

• 5309 posts
• LocationSanta Clara, CA

Posted 03 May 2011 - 04:45 PM

You're on the right track, but you need to mask as well as shifting when extracting colors, like:

red = (src_color & 0xff0000) >> 16;
green = (src_color & 0xff00) >> 8;
blue = src_color & 0xff;

The AND-ing zeroes out all the bits that aren't part of the color channel you want to extract, then the shifting repositions the bits so the color channel you want is at the least-significant end of the word.
reedbeta.com - developer blog, OpenGL demos, and other projects

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users