SOLVED Trouble blending textured billboards with shader.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

SOLVED Trouble blending textured billboards with shader.

Post by pandoragami »

Hello,

Here's a picture of the problem,

Image


Basically I managed to get textures onto quads for billboards and then I managed to get the shader to rotate them to face the camera but now the blending is not quite normal as it should be. I'm just not sure how to go about making this work. I wondered how Irrlicht implemented their particle system, I noticed it doesn't use a shader so I assume it's all cpu but I figure a shader would be effective too. For the shaders, I've tried video::EMT_TRANSPARENT_ADD_COLOR and video::EMT_SOLID. Anyways here's the complete code

main.cpp

Code: Select all

 
#include "irrlicht.h"
#include <cstdlib>
#include <iostream>
#include <cmath>
 
using namespace irr;
 
class EventReceiver : public irr::IEventReceiver
{
    public:
 
    virtual bool OnEvent(const irr::SEvent& event);
    virtual bool IsKeyDown( irr::EKEY_CODE keyCode) const;
    EventReceiver();
 
private:
 
    bool KeyIsDown[ irr::KEY_KEY_CODES_COUNT];
};
bool EventReceiver::OnEvent(const irr::SEvent& event)
{
 
    if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
    return false;
}
bool EventReceiver::IsKeyDown( irr::EKEY_CODE keyCode) const
{
    return KeyIsDown[keyCode];
}
 
EventReceiver::EventReceiver()
{
    for ( irr::u32 i = 0; i < irr::KEY_KEY_CODES_COUNT; ++i)
        KeyIsDown[i] = false;
}
 
 
scene::SMeshBuffer Buffer;
video::IVideoDriver* driver;
 
video::E_DRIVER_TYPE driverType;
s32 shader_1_MaterialType1 = 0;
s32 shader_1_MaterialType2 = 0;
 
video::IGPUProgrammingServices* gpu;
 
class BILLBOARD : public video::IShaderConstantSetCallBack
{
public:
 
    io::path vsFileName;
    io::path psFileName;
 
    BILLBOARD()
    {
        vsFileName = "billboard.vert";
        psFileName = "billboard.frag";
    }
    virtual void OnSetConstants(video::IMaterialRendererServices* services,
            s32 userData)
    {
        video::IVideoDriver* driver = services->getVideoDriver();
 
        core::matrix4 worldViewProj;
        worldViewProj = driver->getTransform(video::ETS_PROJECTION);
        worldViewProj *= driver->getTransform(video::ETS_VIEW);
        worldViewProj *= driver->getTransform(video::ETS_WORLD);
 
        services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
 
        core::matrix4 viewMatrix = driver->getTransform(video::ETS_VIEW);
        services->setVertexShaderConstant("viewMatrix", viewMatrix.pointer(), 16);
 
        core::matrix4 projectionMatrix = driver->getTransform(video::ETS_PROJECTION);
        services->setVertexShaderConstant("projectionMatrix", projectionMatrix.pointer(), 16);
 
        core::matrix4 world = driver->getTransform(video::ETS_WORLD);
        world = world.getTransposed();
        services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
 
        core::matrix4 modelviewmatrix;
        modelviewmatrix = driver->getTransform(video::ETS_VIEW);
        modelviewmatrix *= driver->getTransform(video::ETS_WORLD);
        services->setVertexShaderConstant("modelviewmatrix", world.pointer(), 16);
 
        s32 TextureLayerID = 0;
            services->setPixelShaderConstant("inputTexture", &TextureLayerID, 1);
    }
};
 
unsigned int INDEX = 0;
unsigned int vertexCount;
unsigned int primCount = 0;
video::SMaterial material;
 
void init_indices()
{
     Buffer.Indices.push_back( 0+INDEX);
     Buffer.Indices.push_back( 1+INDEX);
     Buffer.Indices.push_back( 2+INDEX);
     Buffer.Indices.push_back( 2+INDEX);
     Buffer.Indices.push_back( 3+INDEX);
     Buffer.Indices.push_back( 0+INDEX);
}
void init_points( float x, float y, float z)
{
    init_indices();
 
    float a = 10.0;
    int r, g, b;
    r = g = b = 255;
 
    Buffer.Vertices.push_back(video::S3DVertex( x,y,z, 1,1,0,video::SColor(0,r,g,b), 0, 1));
    Buffer.Vertices.push_back(video::S3DVertex( x, a + y, z, 1,0,0,video::SColor(0,r,g,b), 1, 1));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, a+y, z, 0,1,1, video::SColor(0,r,g,b), 1, 0));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, y, z, 0,0,1,  video::SColor(0,r,g,b)  , 0, 0));
 
    INDEX+=4;
    primCount+=2;
}
void render()
{
    material.Wireframe = false;
    material.Lighting = false;//true
    material.setTexture( 0, driver->getTexture("../../../textures/particlewhite.bmp") );//Can also be found in the media folder with irrlicht
    material.MaterialType = irr::video::EMT_TRANSPARENT_ADD_COLOR;
    material.setFlag( irr::video::EMF_ZWRITE_ENABLE, false);
    material.MaterialType = (irr::video::E_MATERIAL_TYPE)shader_1_MaterialType1;
    driver->setMaterial( material);
    driver->drawVertexPrimitiveList(Buffer.getVertices(), INDEX, Buffer.getIndices(), primCount, irr::video::EVT_STANDARD, irr::scene::EPT_TRIANGLES, irr::video::EIT_16BIT);
}
 
int main()
{
    EventReceiver receiver;
    IrrlichtDevice *device = createDevice( irr::video::EDT_OPENGL,
                                       irr::core::dimension2d< irr::u32>( 1024, 768),
                                       16,
                                       false,
                                       false,
                                       false,
                                       &receiver);
 
    if (device == 0)
        return 1;
 
    device->setWindowCaption(L"IRRLICHT");
    driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    driver->setTextureCreationFlag( irr::video::ETCF_CREATE_MIP_MAPS, true);
 
    gpu = driver->getGPUProgrammingServices();
 
    if (gpu)
    {
        BILLBOARD* billboard = new BILLBOARD(); 
       
            const video::E_GPU_SHADING_LANGUAGE shadingLanguage =
            video::EGSL_DEFAULT;     
 
            shader_1_MaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
                billboard->vsFileName, "vertexMain", video::EVST_VS_1_1,
                billboard->psFileName, "pixelMain", video::EPST_PS_1_1,
                billboard, video::EMT_SOLID, 0, shadingLanguage);
 
            shader_1_MaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(
                billboard->vsFileName, "vertexMain", video::EVST_VS_1_1,
                billboard->psFileName, "pixelMain", video::EPST_PS_1_1,
                billboard, video::EMT_TRANSPARENT_ADD_COLOR, 0 , shadingLanguage);
 
            billboard->drop();
    }
 
    init_points(-5.0,-5.0, -2.0);
    init_points( 0.0, 0.0, -1.0);
    init_points( 5.0, 0.0,  0.0);
 
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setTarget( core::vector3df(0,0,0));
    cam->setPosition( core::vector3df(-15,0,-15));
    device->getCursorControl()->setVisible( true);
 
    u32 frames=0;
    while(device->run())
    {
        driver->beginScene( true, true, video::SColor( 0, 0, 0, 0));
        render();
        smgr->drawAll();
 
        driver->endScene();
        if (++frames==100)
        {
            core::stringw str = L"Irrlicht Engine [";
            str += driver->getName();
            str += L"] FPS: ";
            str += (s32)driver->getFPS();
 
            device->setWindowCaption(str.c_str());
            frames=0;
        } 
    }
 
    device->drop();
 
    return 0;
}
 
 

billboard.vert

Code: Select all

 
uniform mat4 mWorldViewProj;//  ETS_PROJECTION*ETS_VIEW*ETS_WORLD
uniform mat4 mTransWorld;// ETS_WORLD.getTransposed()
uniform mat4 viewMatrix;
uniform mat4 modelviewmatrix;
uniform mat4 projectionMatrix;
 
void main() 
{
    gl_TexCoord[0] = gl_MultiTexCoord0;     
    gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 0.0)); 
}
 
billboard.frag

Code: Select all

 
uniform sampler2D inputTexture;
void main() 
{   
    vec4 tex_color = texture2D( inputTexture, gl_TexCoord [ 0].xy);     
    gl_FragColor = tex_color;
}
 
Here's the texture used

Image
Last edited by pandoragami on Wed Jan 17, 2018 12:33 am, edited 1 time in total.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Trouble blending textured billboards with shader.

Post by Mel »

When you compile a shader, the renderstate is picked up from the material type you set as reference, including the blending. The shader_1_MaterialType2 inherits the video::EMT_TRANSPARENT_ADD_COLOR renderstate, whereas the shader_1_MaterialType1 inherits the video::EMT_SOLID renderstate, thus, whenever you use the shader_1_MaterialType1 the rendering will be solid, and whenever you use shader_1_MaterialType2, the shader will be additive. Your code shows you're using only the shader_1_MaterialType1, thus the solid rendering.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Trouble blending textured billboards with shader.

Post by pandoragami »

Mel wrote:When you compile a shader, the renderstate is picked up from the material type you set as reference, including the blending. The shader_1_MaterialType2 inherits the video::EMT_TRANSPARENT_ADD_COLOR renderstate, whereas the shader_1_MaterialType1 inherits the video::EMT_SOLID renderstate, thus, whenever you use the shader_1_MaterialType1 the rendering will be solid, and whenever you use shader_1_MaterialType2, the shader will be additive. Your code shows you're using only the shader_1_MaterialType1, thus the solid rendering.

I've tried using both shader_1_MaterialType1 and shader_1_MaterialType2 with and without video::EMT_TRANSPARENT_ADD_COLOR and the results are the same though??? :?

What I really wanted to ask was, is there a way to blend the images in the shader instead. I'm guessing that would be the best option?
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Trouble blending textured billboards with shader.

Post by Mel »

The blending is a process independent from the shading, that is what shaders are for. If you were to do the blending in the shader, the final process would end being much much more complex than just allowing the API do the blending for you, for the same results, and no gain at all.

If the blending doesn't happen properly, it might be because you're writting the ZBuffer, try disabling the ZWrite.

And truth be said, irrlicht does the billboarding on its own and the blending, do you really need a shader for that? or is some requirement for your project? unless it is the later, really, use the standard billboard scene nodes (or the particle systems) and the standard materials, and leave the shaders for more complex stuff )
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Trouble blending textured billboards with shader.

Post by pandoragami »

Mel wrote:The blending is a process independent from the shading, that is what shaders are for. If you were to do the blending in the shader, the final process would end being much much more complex than just allowing the API do the blending for you, for the same results, and no gain at all.

If the blending doesn't happen properly, it might be because you're writting the ZBuffer, try disabling the ZWrite.

And truth be said, irrlicht does the billboarding on its own and the blending, do you really need a shader for that? or is some requirement for your project? unless it is the later, really, use the standard billboard scene nodes (or the particle systems) and the standard materials, and leave the shaders for more complex stuff )
Alright, that's fair, I still wonder how does irrlicht calculate the billboard normal vector to face the camera? I figured this math problem might be better on the gpu? Is there some way to rotate the quad in the code I posted (with the gpu vert file) but not use the fragment shader for blending and instead let the Irrlicht api do the blending?
I figure that since I've come this far with the code, I'd like to somewhat make it work with the drawvertexprimitive call and such; if not I'll just use the billboarding in the api.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Trouble blending textured billboards with shader.

Post by Mel »

Hmm... truth be said, i never did a vertex shader without a corresponding pixel shader, so no idea, sorry :/
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Trouble blending textured billboards with shader.

Post by pandoragami »

Mel wrote:Hmm... truth be said, i never did a vertex shader without a corresponding pixel shader, so no idea, sorry :/
Have you tried doing any blending in the pixel shader? Just wondering if maybe that would be the alternative to depth sorting and such, I've read here and there on other forums.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Trouble blending textured billboards with shader.

Post by Mel »

No, but you're mistaking what fragment shaders do with the whole blending process. you can't perform blending on a fragment shader, they are things completely diferent. For blending to work with fragment shaders, in the shader compilation, you have to provide a material type that uses any sort of blending. Try using a background of diferent color, because i think it is also a source of confusion, maybe you're actually blending, but you don't notice it because the background is black. If that was the case, then, the problem would probably be the shader updating the depth buffer.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: Trouble blending textured billboards with shader.

Post by pandoragami »

Mel wrote:No, but you're mistaking what fragment shaders do with the whole blending process. you can't perform blending on a fragment shader, they are things completely diferent. For blending to work with fragment shaders, in the shader compilation, you have to provide a material type that uses any sort of blending. Try using a background of diferent color, because i think it is also a source of confusion, maybe you're actually blending, but you don't notice it because the background is black. If that was the case, then, the problem would probably be the shader updating the depth buffer.
I think I got some kind of blending to work, in opengl I noticed that gl_blend was called before the shader so I wondered if Irrlicht had something similar; turns out it does in this thread http://irrlicht.sourceforge.net/forum/v ... =4&t=48998


So I added this line to the code where the material is set before drawvertexprimitivelist

Code: Select all

material.BlendOperation =  irr::video::EBO_ADD; 
and it works.

Image

Here's the complete code

main.cpp

Code: Select all

 
#include "irrlicht.h"
#include <cstdlib>
#include <iostream>
#include <cmath>
 
using namespace irr;
 
class EventReceiver : public irr::IEventReceiver
{
    public:
 
    virtual bool OnEvent(const irr::SEvent& event);
    virtual bool IsKeyDown( irr::EKEY_CODE keyCode) const;
    EventReceiver();
 
private:
 
    bool KeyIsDown[ irr::KEY_KEY_CODES_COUNT];
};
bool EventReceiver::OnEvent(const irr::SEvent& event)
{
 
    if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
 
    return false;
}
bool EventReceiver::IsKeyDown( irr::EKEY_CODE keyCode) const
{
    return KeyIsDown[keyCode];
}
 
EventReceiver::EventReceiver()
{
    for ( irr::u32 i = 0; i < irr::KEY_KEY_CODES_COUNT; ++i)
        KeyIsDown[i] = false;
}
 
 
scene::SMeshBuffer Buffer;
video::IVideoDriver* driver;
 
video::E_DRIVER_TYPE driverType;
s32 shader_1_MaterialType1 = 0;
s32 shader_1_MaterialType2 = 0;
 
video::IGPUProgrammingServices* gpu;
 
class BILLBOARD : public video::IShaderConstantSetCallBack
{
public:
 
    io::path vsFileName;
    io::path psFileName;
 
    BILLBOARD()
    {
        vsFileName = "billboard.vert";
        psFileName = "billboard.frag";
    }
    virtual void OnSetConstants(video::IMaterialRendererServices* services,
            s32 userData)
    {
        video::IVideoDriver* driver = services->getVideoDriver();
 
        core::matrix4 worldViewProj;
        worldViewProj = driver->getTransform(video::ETS_PROJECTION);
        worldViewProj *= driver->getTransform(video::ETS_VIEW);
        worldViewProj *= driver->getTransform(video::ETS_WORLD);
 
        services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);
 
        core::matrix4 viewMatrix = driver->getTransform(video::ETS_VIEW);
        services->setVertexShaderConstant("viewMatrix", viewMatrix.pointer(), 16);
 
        core::matrix4 projectionMatrix = driver->getTransform(video::ETS_PROJECTION);
        services->setVertexShaderConstant("projectionMatrix", projectionMatrix.pointer(), 16);
 
        core::matrix4 world = driver->getTransform(video::ETS_WORLD);
        world = world.getTransposed();
        services->setVertexShaderConstant("mTransWorld", world.pointer(), 16);
 
        core::matrix4 modelviewmatrix;
        modelviewmatrix = driver->getTransform(video::ETS_VIEW);
        modelviewmatrix *= driver->getTransform(video::ETS_WORLD);
        services->setVertexShaderConstant("modelviewmatrix", world.pointer(), 16);
 
        s32 TextureLayerID = 0;
            services->setPixelShaderConstant("inputTexture", &TextureLayerID, 1);
    }
};
 
unsigned int INDEX = 0;
unsigned int vertexCount;
unsigned int primCount = 0;
video::SMaterial material;
 
void init_indices()
{
     Buffer.Indices.push_back( 0+INDEX);
     Buffer.Indices.push_back( 1+INDEX);
     Buffer.Indices.push_back( 2+INDEX);
     Buffer.Indices.push_back( 2+INDEX);
     Buffer.Indices.push_back( 3+INDEX);
     Buffer.Indices.push_back( 0+INDEX);
}
void init_points( float x, float y, float z)
{
    init_indices();
 
    float a = 10.0;
    int r, g, b;
    r = g = b = 255;
 
    Buffer.Vertices.push_back(video::S3DVertex( x,y,z, 1,1,0,video::SColor(0,r,g,b), 0, 1));
    Buffer.Vertices.push_back(video::S3DVertex( x, a + y, z, 1,0,0,video::SColor(0,r,g,b), 1, 1));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, a+y, z, 0,1,1, video::SColor(0,r,g,b), 1, 0));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, y, z, 0,0,1,  video::SColor(0,r,g,b)  , 0, 0));
 
    INDEX+=4;
    primCount+=2;
}
void render()
{
    material.Wireframe = false;
    material.Lighting = false;//true
    material.BackfaceCulling = false;//false
    material.setTexture( 0, driver->getTexture("../../../textures/particlewhite.bmp") );//Can be found in the media folder with irrlicht
    material.BlendOperation =  irr::video::EBO_ADD;
    material.MaterialType = (irr::video::E_MATERIAL_TYPE) shader_1_MaterialType2;
    driver->setMaterial( material);
    driver->drawVertexPrimitiveList(Buffer.getVertices(), INDEX, Buffer.getIndices(), primCount, irr::video::EVT_STANDARD, irr::scene::EPT_TRIANGLES, irr::video::EIT_16BIT);
}
 
int main()
{
    EventReceiver receiver;
    IrrlichtDevice *device = createDevice( irr::video::EDT_OPENGL,
                                       irr::core::dimension2d< irr::u32>( 1024, 768),
                                       16,
                                       false,
                                       false,
                                       false,
                                       &receiver);
 
    if (device == 0)
        return 1;
 
    device->setWindowCaption(L"IRRLICHT");
    driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    driver->setTextureCreationFlag( irr::video::ETCF_CREATE_MIP_MAPS, true);
 
    gpu = driver->getGPUProgrammingServices();
 
    if (gpu)
    {
        BILLBOARD* billboard = new BILLBOARD();
 
        // create the shaders depending on if the user wanted high level
        // or low level shaders:
 
                // Choose the desired shader type. Default is the native
            // shader type for the driver, for Cg pass the special
            // enum value EGSL_CG
            const video::E_GPU_SHADING_LANGUAGE shadingLanguage =
            video::EGSL_DEFAULT;
 
            // create material from high level shaders (hlsl, glsl or cg)
 
            shader_1_MaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
                                                                                                                    billboard->vsFileName,
                                                                                                                    "vertexMain",
                                                                                                                    video::EVST_VS_1_1,
                                                                                                                    billboard->psFileName,
                                                                                                                    "pixelMain",
                                                                                                                    video::EPST_PS_1_1,
                                                                                                                    billboard,
                                                                                                                    video::EMT_SOLID,
                                                                                                                    0,
                                                                                                                    shadingLanguage);
 
            shader_1_MaterialType2 = gpu->addHighLevelShaderMaterialFromFiles(
                billboard->vsFileName, "vertexMain", video::EVST_VS_1_1,
                billboard->psFileName, "pixelMain", video::EPST_PS_1_1,
                billboard, video::EMT_TRANSPARENT_ADD_COLOR , 0 , shadingLanguage);
 
            billboard->drop();
    }
 
    init_points( 5.0, 0.0,  0.0);
    init_points( 0.0, 0.0, -1.0);
    init_points(-5.0,-5.0, -2.0);
 
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setTarget( core::vector3df(0,0,0));
    cam->setPosition( core::vector3df(-15,0,-15));
    device->getCursorControl()->setVisible( true);
 
    u32 frames=0;
    while(device->run())
    {
        driver->beginScene( true, true, video::SColor( 0, 0, 0, 0));
        render();
        smgr->drawAll();
 
        driver->endScene();
        if (++frames==100)
        {
            core::stringw str = L"Irrlicht Engine [";
            str += driver->getName();
            str += L"] FPS: ";
            str += (s32)driver->getFPS();
 
 
 
            device->setWindowCaption(str.c_str());
            frames=0;
        }
 
 
    }
 
    device->drop();
 
    return 0;
}
 
 
billboard.vert

Code: Select all

 
uniform mat4 mWorldViewProj;//  ETS_PROJECTION*ETS_VIEW*ETS_WORLD
uniform mat4 mTransWorld;// ETS_WORLD.getTransposed()
uniform mat4 viewMatrix;
uniform mat4 modelviewmatrix;
uniform mat4 projectionMatrix;
 
void main() 
{
    gl_TexCoord[0] = gl_MultiTexCoord0;     
    gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 0.0)); 
}
 

billboard.frag

Code: Select all

 
uniform sampler2D inputTexture;
void main() 
{ 
    vec4 tex_color = texture2D( inputTexture, gl_TexCoord [ 0].xy);     
    gl_FragColor = vec4(tex_color.xyz, 0.1);    
}
 
MartinVee
Posts: 139
Joined: Tue Aug 02, 2016 3:38 pm
Location: Québec, Canada

Re: SOLVED Trouble blending textured billboards with shader.

Post by MartinVee »

Did you benchmark your solution versus the regular Irrlicht Billboard?
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: SOLVED Trouble blending textured billboards with shader.

Post by pandoragami »

MartinVee wrote:Did you benchmark your solution versus the regular Irrlicht Billboard?
Nope, did this mostly for concept, would you know if Irrlicht runs its billboard on cpu or gpu?
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: SOLVED Trouble blending textured billboards with shader.

Post by CuteAlien »

CPU, but unless you have lots of them it doesn't matter anyway (just 2 polygons and some calculation for rotation).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: SOLVED Trouble blending textured billboards with shader.

Post by Mel »

I'd say on the contrary, you better have thousands or else it is wasted bandwidth,The largest overhead in Irrlicht billboards is transmiting them to the GPU, on the paper, it costs almost the same transmiting one than transmiting 6000 together. You can calculate billboards on the CPU and have that amount and almost not notice it.

https://www.youtube.com/watch?v=7ZS2amg8So0

This was a proof of concept for a particle system i created some time ago, just using Irrlicht and API agnostic (ran on DX9). The particles used no shader, only the default EMT_TRANSPARENT_ALPHA_BLEND, vertex colors and standard vertices, Each particle was a billboard, facing always the camera, with its own position and size. I then animated their length with regard to the particle system emiter, so they became shorter, but they were always facing to the camera, and everything on the CPU, no GPU involved save the rendering. If i remember correctly, each explosion spawned 1000 particles, and at times there are 5 or 6 of these explosions going on without slowdown. The largest slowdowns were when the particles appeared big enough on screen to cover a reasonable area, but none the less, all of them, visible or not, were calculated. People tend to underestimate the CPU a lot these days.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: SOLVED Trouble blending textured billboards with shader.

Post by pandoragami »

Mel wrote:I'd say on the contrary, you better have thousands or else it is wasted bandwidth,The largest overhead in Irrlicht billboards is transmiting them to the GPU, on the paper, it costs almost the same transmiting one than transmiting 6000 together. You can calculate billboards on the CPU and have that amount and almost not notice it.

https://www.youtube.com/watch?v=7ZS2amg8So0

This was a proof of concept for a particle system i created some time ago, just using Irrlicht and API agnostic (ran on DX9). The particles used no shader, only the default EMT_TRANSPARENT_ALPHA_BLEND, vertex colors and standard vertices, Each particle was a billboard, facing always the camera, with its own position and size. I then animated their length with regard to the particle system emiter, so they became shorter, but they were always facing to the camera, and everything on the CPU, no GPU involved save the rendering. If i remember correctly, each explosion spawned 1000 particles, and at times there are 5 or 6 of these explosions going on without slowdown. The largest slowdowns were when the particles appeared big enough on screen to cover a reasonable area, but none the less, all of them, visible or not, were calculated. People tend to underestimate the CPU a lot these days.
Beautiful demo Mel... anyways just wondered if anyone had a clue as to how I could change the color of the texture. For some reason the blending turns off the coloring. I tried the function,

Code: Select all

 
 material.MaterialTypeParam
       = video::pack_textureBlendFunc( irr::video::EBF_ONE ,
                                     irr::video::EBF_ONE_MINUS_SRC_ALPHA,
                                     irr::video::EMFN_MODULATE_1X,
                                     irr::video::EAS_TEXTURE  | irr::video::EAS_TEXTURE );
 
but no luck so far, here are the other options http://irrlicht.sourceforge.net/docu/na ... 8ed87c6e63
pandoragami
Posts: 226
Joined: Wed Jan 26, 2011 5:37 pm
Contact:

Re: SOLVED Trouble blending textured billboards with shader.

Post by pandoragami »

Nevermind, the blending isn't turning off the vertex colors, it's the shader itself that doesn't seem to change the color of the polygon as passed in this part

Code: Select all

 
 Buffer.Vertices.push_back(video::S3DVertex( x,y,z, 1,1,0,video::SColor(0,r,g,b), 0, 1));
    Buffer.Vertices.push_back(video::S3DVertex( x, a + y, z, 1,0,0,video::SColor(0,r,g,b), 1, 1));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, a+y, z, 0,1,1, video::SColor(0,r,g,b), 1, 0));
    Buffer.Vertices.push_back(video::S3DVertex(  a+x, y, z, 0,0,1,  video::SColor(0,r,g,b)  , 0, 0));
 
I assume the gl_Color in the shader is this

Code: Select all

video::SColor(0,r,g,b)
right ?

Solved it! Had to take the gl_Color in the vertex shader and send it to the pixel shader

Code: Select all

 
uniform mat4 mWorldViewProj;//  ETS_PROJECTION*ETS_VIEW*ETS_WORLD
uniform mat4 mTransWorld;// ETS_WORLD.getTransposed()
uniform mat4 viewMatrix;
uniform mat4 modelviewmatrix;
uniform mat4 projectionMatrix;
varying vec4 vertexColor;
 
void main() 
{
    gl_TexCoord[0] = gl_MultiTexCoord0;     
    gl_Position = gl_ProjectionMatrix * (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0) + vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 0.0)); 
    vertexColor = gl_Color;
}
 

Code: Select all

 
uniform sampler2D inputTexture;
varying vec4 vertexColor;
 
void main() 
{ 
    vec4 tex_color = texture2D( inputTexture, gl_TexCoord [ 0].xy);     
    gl_FragColor = vertexColor*vec4( tex_color.xyz, 0.1);   
}
 
Post Reply