Problem with alpha channel shader

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Problem with alpha channel shader

Post by jimy-byerley »

It is probably a stupid problem of beginners ...
I'm trying to make a cloud system with random placement of square faces, each face have a random cloud texture.
I heard the integrated billboard class in irrlicht was too slow with a big number of objects, so I written a small vertex shader.

I have to use EMT_TRANSPARENT_ALPHA_CHANNEL material to construct my HightLevelMaterial.
But instead of drawing a blended face It give me an opaque face. Only the absolutly transparent (alpha=0.000000) pixels are transparent.

I tried some other tricks, like using EMT_ONETEXTURE_BLEND instead, setting manually material.MaterialTypeParam:

Code: Select all

 
material.MaterialTypeParam = video::pack_textureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA,
                                                    video::EMFN_MODULATE_1X, video::EAS_TEXTURE | video::EAS_VERTEX_COLOR); 
I'm also using a custom SceneNode that draw itself a simple square.

Code: Select all

class FaceNode : public scene::ISceneNode
{
    core::aabbox3d<f32> Box;
    video::S3DVertex Vertices[4];
    video::SMaterial Material;
public:
 
    FaceNode(scene::ISceneNode* parent, scene::ISceneManager* mgr) 
    : scene::ISceneNode(parent, mgr)
    {
        //Material.Wireframe = false;
        // S3DVertex (f32 x, f32 y, f32 z, f32 nx, f32 ny, f32 nz, SColor c, f32 tu, f32 tv)
        Vertices[0] = video::S3DVertex( 0,0,0,  0,0,-1, video::SColor(0,0,0,0), 0, 0);
        Vertices[1] = video::S3DVertex( 0,1,0,  0,0,-1, video::SColor(0,0,0,0), 1, 0);
        Vertices[2] = video::S3DVertex( 1,0,0,  0,0,-1, video::SColor(0,0,0,0), 0, 1);
        Vertices[3] = video::S3DVertex( 1,1,0,  0,0,-1, video::SColor(0,0,0,0), 1, 1);
        Box.reset(Vertices[0].Pos);
        for (s32 i=1; i<4; ++i)
            Box.addInternalPoint(Vertices[i].Pos);
    }
    virtual void OnRegisterSceneNode()
    {
        if (IsVisible)
            SceneManager->registerNodeForRendering(this);
        ISceneNode::OnRegisterSceneNode();
    }
    virtual void render()
    {
        u16 indices[] = {0,1,3,   0,3,2}; // order of indices of points decide the normal of the plane
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
        driver->setMaterial(Material);
        driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
        driver->drawVertexPrimitiveList(&Vertices[0], 4, &indices[0], 4, video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
    }
    virtual const core::aabbox3d<f32>& getBoundingBox() const
    { return Box; }
 
    virtual u32 getMaterialCount() const
    { return 1; }
 
    virtual video::SMaterial& getMaterial(u32 i)
    { return Material; }   
};
I load my shader as it

Code: Select all

 
 
        s32 matnum;
        if (bCanDoGLSL_1_1)
        {
            matnum = gpu->addHighLevelShaderMaterialFromFiles(
                "cloud.vert", "main", video::EVST_VS_1_1,
                "cloud.frag", "main", video::EPST_PS_1_1,
                0, video::EMT_TRANSPARENT_ALPHA_CHANNEL);
            node->setMaterialType((video::E_MATERIAL_TYPE)matnum);
        }
        else
            printf("no opengl support\n");
        
        video::SMaterial material = node->getMaterial(0);
        material.Lighting = false;
        //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
        material.MaterialTypeParam = video::pack_textureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA,
                                                    video::EMFN_MODULATE_1X, video::EAS_TEXTURE | video::EAS_VERTEX_COLOR); 
        // this is not working
        // material.BackfaceCulling = false;
        node->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); 
        material.setTexture(0, driver->getTexture("cloud-2.png"));
 
I don't know if it can be usefull: I work on Debian Jessie (8) with an NVIDIA GT520, I got Irrlicht 1.8.1.

SOLUTION FOUND !
I just added the following line after the shader assignation. It now works as expected.

Code: Select all

node->setMaterialFlag(video::EMF_BLEND_OPERATION, true);
Last edited by jimy-byerley on Mon Nov 23, 2015 4:34 pm, edited 2 times in total.
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Problem with alpha channel shader

Post by mongoose7 »

EMT_TRANSPARENT_ALPHA_CHANNEL works. Maybe you have a problem in your pixel shader.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

I'm not sure but I don't know: when I force gl_FragColor alpha to 0.5, only one thing change: there is no more alpha even in texture transparent zones (100% transparence zones). It's logical because 0.5 is always > 0 (my name's captain obvious ?)

Anyway, this is my vertex shader

Code: Select all

 
varying vec4 vertex;
 
void main()
{
    // for the fragment
    gl_TexCoord[0].st = gl_MultiTexCoord0;
    vertex = gl_ModelViewMatrix * gl_Vertex;
    // the model view matrix (from world to screen) have a translation transform and a rotation transform.
    // the rotation transform is the mat3 of the center: columns 0, 1, 2 and lines 0, 1, 2
    // to abort rotation of the object in view, we set this matrix to identity matrix.
    mat4 ModelView = gl_ModelViewMatrix;
    // matrix[col][lin]
    ModelView[0][0] = 1;
    ModelView[0][1] = 0;
    ModelView[0][2] = 0;
    
    ModelView[1][0] = 0;
    ModelView[1][1] = 1;
    ModelView[1][2] = 0;
    
    ModelView[2][0] = 0;
    ModelView[2][1] = 0;
    ModelView[2][2] = 1;
    gl_Position = gl_ProjectionMatrix * ModelView * gl_Vertex;
 
And this is my fragment shader

Code: Select all

 
sampler2D texture;
varying vec4 vertex;
 
#define NUM_LIGHTS 3 //gl_MaxLights
 
void main()
{
    float color = texture2D(texture, gl_TexCoord[0].st).r;
    vec3 light = 0;
    vec4 lv;
    int i=0;
    for (i; i<NUM_LIGHTS; i++)
    {
        lv = gl_LightSource[i].position - vertex;
        light += gl_LightSource[i].diffuse / pow(length(lv), 2);
    }
    light = 0.05 + 0.2*light;
    gl_FragColor = vec4(light*color, color);
}
 
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Problem with alpha channel shader

Post by hendu »

You sure you want the red channel as alpha?
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Problem with alpha channel shader

Post by mongoose7 »

They are clouds so they should be mostly white. But I think he should disable the depth test.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

Exactly, my clouds are only white, the only value I need is the transparency stored on r channel (I use grayscale images).
I tried to disable the depth test by:

Code: Select all

node->setMaterialFlag(video::EMF_ZBUFFER, false); 
But it doesn't change anything. Anyway I need depth test for clouds.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

Someone have something for me ?
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Problem with alpha channel shader

Post by mongoose7 »

Post an image. Two clouds and background.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

Image
What I get with 2 cloud faces. The color gradient on the second is normal because it's near a light point.
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Problem with alpha channel shader

Post by hendu »

According to that image, your shader isn't applied? There are black areas with red = 0. Confirm by checking the source image's alpha channel.
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

My shader is applied : There is the billboard effect and the color gradient near lights.
In fact black zones we see is not absolutly black zones, The texture is at 100% black only in the transparent area.
let's see the image Image
mongoose7
Posts: 1227
Joined: Wed Apr 06, 2011 12:13 pm

Re: Problem with alpha channel shader

Post by mongoose7 »

And how do you account for the irregular shapes of the textures in the compound image you posted?
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Problem with alpha channel shader

Post by hendu »

If you run example 10, does it show ok?
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

mongoose7 wrote:And how do you account for the irregular shapes of the textures in the compound image you posted?
The irregular shape is due to non zero pixels in the image, maybe because of the jpeg compression (the image was in jpg before I converted it into png).
hendu wrote:If you run example 10, does it show ok?
It works fine, yes ... I'll try find the difference between this code and mine ...
jimy-byerley
Posts: 27
Joined: Thu Oct 22, 2015 10:42 am

Re: Problem with alpha channel shader

Post by jimy-byerley »

I FOUND !!!

In addition to build the shader on EMT_TRANSPARENT_ALPHA_CHANNEL, we have to declare the blend operation :

Code: Select all

node->setMaterialFlag(video::EMF_BLEND_OPERATION, true);
And I don't think it was often said in the documentation !
Thanks for all your answers, my result is now: Image
Post Reply