Page 1 of 1

Coloring units

Posted: Sun Nov 27, 2011 12:19 pm
by badday
Hi guys,

I´m currently trying to colorize my units the following way:

Taking the original texture/material:

Code: Select all

video::SMaterial text = node->getMaterial(0);
text.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
text.setFlag(video::EMF_LIGHTING, false);
As a background I create a solid color texture like the following:

Code: Select all

video::SMaterial solid;
solid.MaterialType = video::EMT_SOLID;
video::IImage *img = Device->getVideoDriver()->createImage(video::ECF_A8R8G8B8, core::dimension2du(1,1));
img->setPixel(0,0, video::SColor(0, 0, 0, 255));        
solid.setTexture(0, Device->getVideoDriver()->addTexture("bla", img));
solid.setFlag(video::EMF_LIGHTING, false);
Finally I use those two materials at the node:

Code: Select all

node->setMaterialTexture(0, solid.getTexture(0));
node->setMaterialTexture(1, text.getTexture(0));
But as a result, not only the transparent part of my .png texture (currently I only use values 0 and 255 and nothing in between) seems to be transparent, but all parts. Therefore the hole model seems to be dip-painted in blue in this example.

What am I doing wrong? I further information is required, please give a shout.


Best wishes,

badday

Re: Coloring units

Posted: Sun Nov 27, 2011 12:38 pm
by Klunk
scolor is alpha red green blue not red green blue alpha

Re: Coloring units

Posted: Sun Nov 27, 2011 12:49 pm
by badday
You´re right, the solid color should therefore be video::SColor(255, 0, 0, 255) meaning not transparent at all. Anyway, this doesn´t solve the problem (it doesn´t even have any obvious effect at all)

Re: Coloring units

Posted: Sun Nov 27, 2011 2:19 pm
by hybrid
The proper material would be EMT_TRANSPARENT_ALPHA_CHANNEL. Otherwise you get transparency on black (0,0,0) colors.

Re: Coloring units

Posted: Mon Nov 28, 2011 2:47 pm
by badday
Hm... I made the MaterialType of text video::EMT_TRANSPARENT_ALPHA_CHANNEL. However, the problem remains.

Re: Coloring units

Posted: Mon Nov 28, 2011 3:26 pm
by hybrid
Well, looking over the code in more detail: Why do you need two textures? All the materials you mentioned don't even support two textures. From what I see you probably want to change the background color independently of the text. I'd probably change the vertex color to solid blue and use the transparent text on top. But you can also use two meshes overlaid, or the two texture materials. However, the two texture solid material seems to use vertex alpha only, lightmap and detailmap might have disturbing visual effects, and reflection materials distort the reflected texture (although this would be invisible on the plain blue texture). So don't know if any of these options really helps. Guess you have to try them all

Re: Coloring units

Posted: Mon Nov 28, 2011 3:58 pm
by badday
Hm... It all results in almost the same unfortunately, even with video::EMT_TRANSPARENT_REFLECTION_2_LAYER or video::EMT_LIGHTMAP like this:
Image
What I do not understand is why this can´t be easily made as by default it does colorize the background with white:
Image

So isn´t it just possible to change this "default" color or is this a totally different mechanism?

Thanks.

Re: Coloring units

Posted: Mon Nov 28, 2011 4:32 pm
by hybrid
I still don't really get what you want to achieve. But the white color comes from the vertex color, which you can change on a per-mesh base (not per scene node). You might need to enable lighting for the meshes, though. Also note that you seem to mix texture and material in your code example. You talk about text material and solid material, but use only textures in the end.

Re: Coloring units

Posted: Mon Nov 28, 2011 4:49 pm
by badday
I still don't really get what you want to achieve
I would like to have some background in the color I choose and to put the texture on top of it. According to the alpha-value of this texture, you should see the background or not.
But the white color comes from the vertex color, which you can change on a per-mesh base (not per scene node). You might need to enable lighting for the meshes, though.
Alright, so you thought about

Code: Select all

Device->getSceneManager()->getMeshManipulator()->setVertexColors(mesh, SColor(255,0,0,255));
mesh->setMaterialFlag(video::EMF_LIGHTING, true);
This results in the first image above. Do I need to set the MaterialType of the scene node to some other value maybe? Does it mix the vertex color and the texture color? What exactly does vertex color mean? I this just the default color of all vertices?
Also note that you seem to mix texture and material in your code example. You talk about text material and solid material, but use only textures in the end.
OK, you´re right, this it doesn´t make sense to play around with the materials which are not used at all (as only textures are used from those materials).


Thanks again for spending ur time on helping me :)

Re: Coloring units

Posted: Mon Nov 28, 2011 6:35 pm
by badday
Alright, I finally made it by hand. This way should be driver-independent, therefore it might be useful for others as well:

Code: Select all

core::dimension2du size = node->getMaterial(0).getTexture(0)->getSize();
 
video::ITexture *texture = node->getMaterial(0).getTexture(0);
char* pixels = (char*)texture->lock();
        
unsigned long offset = 0;
unsigned long fractionColor = 0x000000FF;
unsigned short r2, g2, b2;
unsigned short r1,g1,b1;
r1 = (unsigned short)((fractionColor & 0x00FF0000) >> 16);
g1 = (unsigned short)((fractionColor & 0x0000FF00) >> 8);
b1 = (unsigned short)(fractionColor & 0x000000FF);
unsigned long PointColor;
unsigned int size1D = size.Width * size.Height;
 
size_t sizeOf_ul = sizeof(unsigned long);
 
for(s32 counter = 0; counter < size1D; ++counter)
{
        memcpy(&PointColor, pixels + offset, sizeOf_ul);
 
        if((PointColor & 0xFF000000) != 0xFF000000)
        {
                        unsigned short r2,g2,b2;
                        float a2, a1;
                        a2 = (unsigned short)((PointColor & 0xFF000000) >> 32);
                        a2 = a2/255.0;
                        a1 = 255 - (unsigned short)((PointColor & 0xFF000000) >> 32);
                        a1 = a1/255.0;
                        r2 = (unsigned short)((PointColor & 0x00FF0000) >> 16);
                        g2 = (unsigned short)((PointColor & 0x0000FF00) >> 8);
                        b2 = (unsigned short)(PointColor & 0x000000FF);
 
                        r2 = (r2*a2) + r1*a1;
                        g2 = (g2*a2) + g1*a1;
                        b2 = (b2*a2) + b1*a1;
 
                        
                        if(r2 > 0xFF) r2 = 0xFF;
                        if(g2 > 0xFF) g2 = 0xFF;
                        if(b2 > 0xFF) b2 = 0xFF;
 
                        PointColor = 0xFF000000 | (r2 << 16) | (g2 << 8) | b2;
 
                        
                        memcpy(pixels + offset, &PointColor, sizeOf_ul);
        }
 
        offset += sizeOf_ul;
}
texture->unlock();
texture->regenerateMipMapLevels();
Which results in:
Image

I didn´t test the algo for other alpha-values than 0 and 255, therefore it might be possible that there is some mistake somewhere ;)

Re: Coloring units

Posted: Tue Nov 29, 2011 9:32 am
by hendu
Why not use a shader? Certainly should be faster and less code than generating textures on the cpu.