[fixed]Alpha Render Target Issue

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Post Reply
Puck6633
Posts: 27
Joined: Wed Aug 10, 2005 8:35 am

[fixed]Alpha Render Target Issue

Post by Puck6633 »

I've been playing with Irrlicht recently for a little game project of mine, but the strangest thing was happening when I tried to use a render target texture with an alpha channel: EMT_SOLID objects were rendering semi-transparent. I explored the issue a little on my own to (hopefully) verify that it's not my code, and created a minimal test case to demonstrate the problem.

The setup:
Irrlicht Engine version 1.7.3
Microsoft Windows 7 Ultimate Edition (Build 7600)
Using renderer: OpenGL 4.2.11631
ATI Radeon HD 5770
GLSL version: 4.2
  • Initialize Irrlicht with an OpenGL device in 32 bit color (I didn't compile D3D support into my DLL, so I didn't test that)
  • Create a scene using the scene manager with at least one solid object visible in the camera's frustrum
  • Create a render target texture with an alpha channel — I used ECF_A8R8G8B8
  • Clear the render target texture to an alpha value < 255 and render your scene
The result: objects with the EMT_SOLID material will be rendered with an alpha value. When I originally discovered the issue the value was 155, in my test case it seems to be 100.

Here you can see a render target texture of an unlit sphere over a red background:

Image

And here is the render target texture saved with the code in the following file:

Image

Here is the complete source:

Code: Select all

 
#include <irrlicht.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
class MyEventReceiver : public IEventReceiver {
    IrrlichtDevice* Device;
 
    public:
        MyEventReceiver(IrrlichtDevice* device) : Device(device) {
        }
 
        bool OnEvent(const SEvent& event) {
            if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) {
                switch (event.KeyInput.Key) {
                    case KEY_KEY_T:
                        //Save the render target texture from the last frame to a file
                        Device->getVideoDriver()->writeImageToFile(Device->getVideoDriver()->createImageFromData(
                            Device->getVideoDriver()->getTexture("problem")->getColorFormat(),
                            Device->getVideoDriver()->getTexture("problem")->getSize(),
                            Device->getVideoDriver()->getTexture("problem")->lock(),
                            false  //copy mem
                        ), "problem.png", 9);
                        return true;
                    default:
                    break;
                }
            }
 
            return false;
        }
};
 
int main(int argc, char** argv) {
    IrrlichtDevice* device = createDevice(EDT_OPENGL, dimension2d<u32>(1024, 768), 32, false, false, true);
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
 
    device->setWindowCaption(L"Alpha Issue");
 
    MyEventReceiver receiver(device);
    device->setEventReceiver(&receiver);
 
    //A basic sphere node, should have a solid white material
    ISceneNode* sphere = smgr->addSphereSceneNode(100, 100);
    sphere->setMaterialFlag(EMF_LIGHTING, false); //So we can see the diffuse color
 
    //Create a simple static camera to look at the object
    smgr->addCameraSceneNode(smgr->getRootSceneNode(), vector3df(0, 0, -200), vector3df(0), true);
 
    //Create our render target
    ITexture* rttTex = driver->addRenderTargetTexture(dimension2d<u32>(1024, 768), "problem", ECF_A8R8G8B8);
 
    while(device->run()) {
        driver->beginScene();
 
        //Render the scene
        driver->setRenderTarget(rttTex);
        smgr->drawAll();
 
        //Draw the image over a red background to visually illustrate the issue
        driver->setRenderTarget(0, true, true, SColor(255, 128, 0, 0));
        driver->draw2DImage(rttTex, position2di(0, 0), recti(0, 0, 1024, 768), &recti(0, 0, 1024, 768), SColor(255,255,255,255), true);
 
        driver->endScene();
    }
 
    device->drop();
    return 0;
}
 
Finally here is my test case with source and Win32-GCC binary:

http://www.mediafire.com/?y5519nplj5eq988

Press the T key at runtime to save the render target texture to file for examination.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Alpha Render Target Issue

Post by Granyte »

remove the last true at the end of your draw2dimage call.
the use alpha channel of image should read use alpha channel of image for transparency
Puck6633
Posts: 27
Joined: Wed Aug 10, 2005 8:35 am

Re: Alpha Render Target Issue

Post by Puck6633 »

The draw2DImage call is working as intended. Setting the last parameter to false ignores the alpha channel of the render target texture, which hides the issue at hand. The real problem is with the texture itself, as you can see in the second image I posted, which is a direct dump of the render target texture (the result of everything before driver->setRenderTarget(0<...>) to file.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Alpha Render Target Issue

Post by Granyte »

if you dump the image to a png it will be transparent when ever there is alpha iplied because tha't how the "PNG" standar behave if you save to "bmp" you will seee pink ish dots all over the image because that's how the standar behave

if you wanna avoiid this issue you need to write something to that alpha channel that prevent transparency
Puck6633
Posts: 27
Joined: Wed Aug 10, 2005 8:35 am

Re: Alpha Render Target Issue

Post by Puck6633 »

A quick update that will hopefully be helpful in debugging this issue: If the lighting flag on the node is on and the material's ColorMaterial flag is set to ECM_NONE, the behavior is as expected, but the ability to set any material colors on the node is lost. Here is my new source and an example shot:

Code: Select all

 
#include <irrlicht.h>
 
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
class MyEventReceiver : public IEventReceiver {
    IrrlichtDevice* Device;
 
    public:
        MyEventReceiver(IrrlichtDevice* device) : Device(device) {
        }
 
        bool OnEvent(const SEvent& event) {
            if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown) {
                switch (event.KeyInput.Key) {
                    case KEY_KEY_T:
                        //Save the render target texture from the last frame to a file
                        Device->getVideoDriver()->writeImageToFile(Device->getVideoDriver()->createImageFromData(
                            Device->getVideoDriver()->getTexture("problem")->getColorFormat(),
                            Device->getVideoDriver()->getTexture("problem")->getSize(),
                            Device->getVideoDriver()->getTexture("problem")->lock(),
                            false  //copy mem
                        ), "problem.png", 9);
                        return true;
                    default:
                    break;
                }
            }
 
            return false;
        }
};
 
int main(int argc, char** argv) {
    IrrlichtDevice* device = createDevice(EDT_OPENGL, dimension2d<u32>(1024, 768), 32, false, false, true);
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
 
    device->setWindowCaption(L"Alpha Issue");
 
    MyEventReceiver receiver(device);
    device->setEventReceiver(&receiver);
 
    //A basic sphere node, should have a solid white material
    ISceneNode* sphere = smgr->addSphereSceneNode(100, 100);
    //sphere->setMaterialFlag(EMF_LIGHTING, true); //So we can see the diffuse color
    sphere->getMaterial(0).ColorMaterial = ECM_NONE;
 
    //Create a simple static camera to look at the object
    smgr->addCameraSceneNode(smgr->getRootSceneNode(), vector3df(0, 0, -200), vector3df(0), true);
 
    //Create our render target
    ITexture* rttTex = driver->addRenderTargetTexture(dimension2d<u32>(1024, 768), "problem", ECF_A8R8G8B8);
 
    while(device->run()) {
        driver->beginScene();
 
        //Render the scene
        driver->setRenderTarget(rttTex);
        smgr->drawAll();
 
        //Draw the image over a red background to visually illustrate the issue
        driver->setRenderTarget(0, true, true, SColor(255, 128, 0, 0));
        driver->draw2DImage(rttTex, position2di(0, 0), recti(0, 0, 1024, 768), &recti(0, 0, 1024, 768), SColor(255,255,255,255), true);
 
        driver->endScene();
    }
 
    device->drop();
    return 0;
}
 
Image
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Alpha Render Target Issue

Post by hendu »

I confirm your first test app shows what you say, this is on linux. I get 100 as the image alpha too.
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Alpha Render Target Issue

Post by hendu »

..and it's no bug, check CGeometryCreator.cpp - the vertex color of the created sphere has 100 alpha ;)

(certainly curious why it's 100 when all other default colors are full white, but eh)
Puck6633
Posts: 27
Joined: Wed Aug 10, 2005 8:35 am

Re: Alpha Render Target Issue

Post by Puck6633 »

Ah, I see. Not exactly a bug per se, but I would still consider it something to change in the next official release as being unintuitive at best. Thanks for the explanation though!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Alpha Render Target Issue

Post by hybrid »

Yeah, that's definitely some kind of typo or so. It's changed in SVN for upcoming 1.8
Post Reply