Is XEffects compatible with Linux?

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.
Post Reply
Noiecity
Posts: 336
Joined: Wed Aug 23, 2023 7:22 pm
Contact:

Is XEffects compatible with Linux?

Post by Noiecity »

I was planning to use xeffects shaders with Irrlicht, but I'm worried that they won't work on Linux. Does anyone know if they are functional on Linux? Or will I have to write my own shaders? These shaders are very well designed, and they are perfect for low-resolution renders, such as reflections and shadows.
Irrlicht is love, Irrlicht is life, long live to Irrlicht
Noiecity
Posts: 336
Joined: Wed Aug 23, 2023 7:22 pm
Contact:

Re: Is XEffects compatible with Linux?

Post by Noiecity »

Image

It works correctly. You can open the sln file with CodeBlocks, then configure the project in the same way as the official Irrlicht projects that open with CodeBlocks (the .cbp project file) for Linux environments, GUI type. If you don't see anything when compiling (just an orange background), it's because you're missing the media and shader files. If you have them in the same folder as /bin, then open the executable from the folder instead of the compiler when compiling.

You have to modify the code a little bit and it works, at least in the first example.

Irrlicht 1.9.0 svn trunk.

Code: Select all

// main.cpp
#include <irrlicht.h>
#include <iostream>

// Include XEffects (add the .cpp files of XEffects to the build).
#include "XEffects.h"

using namespace irr;
using namespace scene;
using namespace video;
using namespace core;

int main()
{
    // --- CONFIGURATION (modify if desired) ---
    const E_DRIVER_TYPE driverType = EDT_OPENGL;
    const u32 shadowDimen = 1024u;
    const E_FILTER_TYPE filterType = static_cast<E_FILTER_TYPE>(2); // 2 => 8 PCF (adjust if necessary)
    const core::stringc shaderExt = ".glsl";
    // ------------------------------------------------

    IrrlichtDevice* device = createDevice(
        driverType,
        dimension2du(800, 600),
        32,         // bits
        false,      // fullscreen
        false,      // stencil buffer
        false,      // vsync
        0           // event receiver
    );

    if (!device)
        return 1;

    device->setWindowCaption(L"Shadow Map Demo - Linux (OpenGL)");

    ISceneManager* smgr = device->getSceneManager();
    IVideoDriver* driver = device->getVideoDriver();

    // Basic FPS camera
    ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0, 100.0f, 0.05f);
    cam->setPosition(vector3df(0.0f, 10.0f, 0.0f));
    cam->setFarValue(50.0f);
    cam->setNearValue(0.1f);

    // Initialize EffectHandler (XEffects)
    EffectHandler* effect = new EffectHandler(device, driver->getScreenSize(), false, true);

    // --- ROOM MESH: use IAnimatedMesh (correction) ---
    IAnimatedMesh* roomAnim = smgr->getMesh("media/ShadRoom.b3d");
    if (!roomAnim) {
        // fallback: cube if mesh doesn't exist
        ISceneNode* fallback = smgr->addCubeSceneNode(5.0f);
        fallback->setPosition(vector3df(2.5f, 0.5f, 2.5f));
        fallback->getMaterial(0).Lighting = false;
        effect->addShadowToNode(fallback, filterType);
    } else {
        // get IMesh* from IAnimatedMesh (LOD 0)
        IMesh* roomMesh = roomAnim->getMesh(0);
        IMeshSceneNode* room = smgr->addMeshSceneNode(roomMesh);
        if (room) {
            room->setScale(vector3df(3.0f, 2.0f, 3.0f));
            room->setPosition(vector3df(4.5f, 0.5f, 4.0f));
            if (driver->getTexture("media/wall.jpg"))
                room->setMaterialTexture(0, driver->getTexture("media/wall.jpg"));
            room->getMaterial(0).Lighting = false;
            effect->addShadowToNode(room, filterType); // ESM_BOTH by default
        }
    }

    // Global ambient color
    effect->setAmbientColor(SColor(255, 32, 32, 32));

    // Load dwarf mesh (fallback if not present)
    IAnimatedMesh* dwarfmesh = smgr->getMesh("media/dwarf.x");
    if (dwarfmesh) {
        for (int g = 0; g < 2; ++g) {
            for (int v = 0; v < 2; ++v) {
                IAnimatedMeshSceneNode* dwarf = smgr->addAnimatedMeshSceneNode(dwarfmesh);
                if (!dwarf) continue;
                dwarf->setScale(vector3df(0.05f, 0.05f, 0.05f));
                dwarf->setPosition(vector3df(g * 4.5f + 1.0f, 0.5f, v * 3.5f + 2.0f));
                for (u32 i = 0; i < dwarf->getMaterialCount(); ++i)
                    dwarf->getMaterial(i).Lighting = false;
                dwarf->setAnimationSpeed(20.0f);
                effect->addShadowToNode(dwarf, filterType);
            }
        }
    }

    // Transparent cube
    ISceneNode* cube = smgr->addCubeSceneNode(3.0f);
    cube->setPosition(vector3df(5, 6, 5));
    if (driver->getTexture("media/xeffects.png"))
        cube->getMaterial(0).setTexture(0, driver->getTexture("media/xeffects.png"));
    cube->getMaterial(0).MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
    effect->addShadowToNode(cube, filterType, ESM_CAST);

    // Orange background
    effect->setClearColour(SColor(255, 250, 100, 0));

    // Add two lights and animators
    ILightSceneNode* light = smgr->addLightSceneNode();
    ISceneNodeAnimator* ani = smgr->createFlyCircleAnimator(vector3df(5, 20, 5), 38);
    light->addAnimator(ani);
    ani->drop();

    ILightSceneNode* light2 = smgr->addLightSceneNode();
    ani = smgr->createFlyCircleAnimator(vector3df(5, 20, 5), 38, -0.001f);
    light2->addAnimator(ani);
    ani->drop();

    // Post-processing: load GLSL effects
    effect->addPostProcessingEffectFromFile(core::stringc("shaders/BrightPass") + shaderExt);
    effect->addPostProcessingEffectFromFile(core::stringc("shaders/BlurHP") + shaderExt);
    effect->addPostProcessingEffectFromFile(core::stringc("shaders/BlurVP") + shaderExt);
    effect->addPostProcessingEffectFromFile(core::stringc("shaders/BloomP") + shaderExt);

    // Add two shadow lights (use shadowDimen defined above)
    effect->addShadowLight(SShadowLight(shadowDimen, vector3df(0, 0, 0), vector3df(5, 0, 5),
        SColor(0, 255, 0, 0), 20.0f, 60.0f, 30.0f * DEGTORAD));
    effect->addShadowLight(SShadowLight(shadowDimen, vector3df(0, 0, 0), vector3df(5, 0, 5),
        SColor(0, 0, 255, 0), 20.0f, 60.0f, 30.0f * DEGTORAD));

    // Particle system (fire)
    scene::IParticleSystemSceneNode* ps = smgr->addParticleSystemSceneNode(false);
    if (ps) {
        scene::IParticleEmitter* em = ps->createBoxEmitter(
            core::aabbox3d<f32>(-1,0,-1,1,1,1),
            core::vector3df(0.0f,0.005f,0.0f),
            80, 100,
            video::SColor(0,255,255,255),
            video::SColor(0,255,255,255),
            800, 1500, 0,
            core::dimension2df(1.f,1.f),
            core::dimension2df(2.f,2.f));

        ps->setEmitter(em);
        em->drop();

        scene::IParticleAffector* paf = ps->createFadeOutParticleAffector();
        ps->addAffector(paf);
        paf->drop();

        ps->setPosition(core::vector3df(-2.5f, 2.5f, -3.0f));
        ps->setMaterialFlag(video::EMF_LIGHTING, false);
        ps->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
        if (driver->getTexture("media/fireball.bmp"))
            ps->setMaterialTexture(0, driver->getTexture("media/fireball.bmp"));
        ps->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);

        effect->excludeNodeFromLightingCalculations(ps);
    }

    s32 oldFps = 0;

    // Main loop
    while (device->run())
    {
        if (oldFps != driver->getFPS())
        {
            core::stringw windowCaption = L"Shadow Map Demo FPS: ";
            windowCaption += driver->getFPS();
            device->setWindowCaption(windowCaption.c_str());
            oldFps = driver->getFPS();
        }

        // Update shadow light positions from the animated lights
        effect->getShadowLight(0).setPosition(light->getPosition());
        effect->getShadowLight(1).setPosition(light2->getPosition());

        effect->getShadowLight(0).setTarget(vector3df(5, 0, 5));
        effect->getShadowLight(1).setTarget(vector3df(5, 0, 5));

        driver->beginScene(true, true, SColor(0x0));

        // update() handles rendering the entire scene and effects
        effect->update();

        driver->endScene();
    }

    // Cleanup: EffectHandler is a custom class, use delete if created with new.
    delete effect;
    device->drop();

    return 0;
}
https://github.com/mzeilfelder/xeffects
Irrlicht is love, Irrlicht is life, long live to Irrlicht
Post Reply