Environment Mapping with Irrlicht

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Environment Mapping with Irrlicht

Post by Mel »

Here you are!, i hope you don't mind me posting the code directly here :) This works with the latest SVN (and hopefully, so on) and you can find everything needed in the media directory of irrlicht, thus, the example aims to it as if it was any other example of the engine.

Source...

Code: Select all

 
#include <irrlicht.h>
#include <iostream>
 
/*This example illustrates the usage of cubemaps. Given there are no predefined materials that use the cubemaps, we
have to provide our own, so this also illustrates the creation of shaders*/
 
/*This is our constants set callback for the cubemapped materials*/
class cubemapConstants : public irr::video::IShaderConstantSetCallBack
{
    int matWorldViewProjection;//Identifiers, much faster than string matching...
    int matViewInverse;
    int matWorld;
    int baseMap;
    int reflectionMap;
 
    bool firstRun;
    bool IsOpenGL;//Our constants set callback isn't limited to D3D9
 
    irr::video::IVideoDriver* driver; //Here so we can save a call during the execution
 
public:
    cubemapConstants(bool isGL)
    {
        IsOpenGL = isGL;
        firstRun = true;
    }
 
    void OnSetConstants(irr::video::IMaterialRendererServices* services, irr::s32 userData)
    {
        if(firstRun)
        {
            firstRun = false;
 
            driver = services->getVideoDriver();
            //Looking for our constants IDs...
            matViewInverse = services->getVertexShaderConstantID("matViewInverse");
 
            if(IsOpenGL)
            {
                baseMap = services->getPixelShaderConstantID("baseMap");
                reflectionMap = services->getPixelShaderConstantID("reflectionMap");
            }
            else
            {
                matWorldViewProjection=services->getVertexShaderConstantID("matWorldViewProjection");
                matWorld = services->getVertexShaderConstantID("matWorld");
            }
        }
 
        //Setting up our constants...
        irr::core::matrix4 mat;
 
        mat = driver->getTransform(irr::video::ETS_VIEW);
        mat.makeInverse();
        services->setVertexShaderConstant(matViewInverse,mat.pointer(),16);
 
        if(IsOpenGL)
        {
            int sampler=0;
            services->setPixelShaderConstant(baseMap,&sampler,1);
            sampler=1;
            services->setPixelShaderConstant(reflectionMap,&sampler,1);     
        }
        else
        {
            mat = driver->getTransform(irr::video::ETS_PROJECTION);
            mat *= driver->getTransform(irr::video::ETS_VIEW);
            mat *= driver->getTransform(irr::video::ETS_WORLD);
            services->setVertexShaderConstant(matWorldViewProjection,mat.pointer(),16);
 
            mat = driver->getTransform(irr::video::ETS_WORLD);
            services->setVertexShaderConstant(matWorld,mat.pointer(),16);
        }
    }
};
 
/*And our main*/
 
void main(void)
{
    irr::IrrlichtDevice* device;
    irr::video::IVideoDriver* driver;
    irr::scene::ISceneManager* manager;
    irr::video::ITexture* cubemap;
    irr::video::IImage* cubemapImages[6];
 
    //create the engine
    int value;
    std::cout<<"Pick driver 1:OpenGL 2:Direct3D9"<<std::endl;
    std::cin>>value;
 
    irr::SIrrlichtCreationParameters prm;
    prm.DriverType = value==1?irr::video::EDT_OPENGL:irr::video::EDT_DIRECT3D9;
    prm.WindowSize = irr::core::dimension2du(1024,768);
    device = createDeviceEx(prm);
 
    if( device != NULL )
    {
        cubemapConstants* cns = new cubemapConstants(prm.DriverType==irr::video::EDT_OPENGL);
        driver = device->getVideoDriver();
        manager = device->getSceneManager();
 
        //So far there are no materials ready to use a cubemap, so we provide our own.
        irr::s32 shader;
 
        if(prm.DriverType==irr::video::EDT_DIRECT3D9)
            shader = driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
                "../media/shader.hlsl",
                "vs_main",
                irr::video::EVST_VS_2_0,
                "../media/shader.hlsl",
                "ps_main",
                irr::video::EPST_PS_2_0,
                cns,
                irr::video::EMT_SOLID
                );
        else //OpenGL
            shader = driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
                "../media/shaderV.glsl",
                "main",
                irr::video::EVST_VS_2_0,
                "../media/shaderP.glsl",
                "main",
                irr::video::EPST_PS_2_0,
                cns,
                irr::video::EMT_SOLID
                );
 
        shader = shader==-1?0:shader; //Just in case something goes horribly wrong...
 
        //creating the cubemap... For now, Irrlicht's cubemaps need to be created on the fly out of images.
        //Loading the images
        cubemapImages[0] = driver->createImageFromFile("../media/irrlicht2_ft.jpg");
        cubemapImages[1] = driver->createImageFromFile("../media/irrlicht2_bk.jpg");
        cubemapImages[2] = driver->createImageFromFile("../media/irrlicht2_up.jpg");
        cubemapImages[3] = driver->createImageFromFile("../media/irrlicht2_dn.jpg");
        cubemapImages[4] = driver->createImageFromFile("../media/irrlicht2_lf.jpg");
        cubemapImages[5] = driver->createImageFromFile("../media/irrlicht2_rt.jpg");
 
        //creating the cubemap itself
        cubemap = driver->addTextureCubemap(
            "irrlicht2.cubemap",
            cubemapImages[0],
            cubemapImages[1],
            cubemapImages[2],
            cubemapImages[3],
            cubemapImages[4],
            cubemapImages[5]
        );
 
        //We're done with the images, so we're releasing them. Unlike the Textures, the Images can be dropped.
        for(int i=0;i<6;i++)
            cubemapImages[i]->drop();
 
        //creating the scene
        manager->addCameraSceneNodeFPS();
 
        //Adding a skybox...
        irr::scene::ISceneNode* node = manager->addSkyBoxSceneNode(
            driver->getTexture("../media/irrlicht2_up.jpg"),
            driver->getTexture("../media/irrlicht2_dn.jpg"),
            driver->getTexture("../media/irrlicht2_lf.jpg"),
            driver->getTexture("../media/irrlicht2_rt.jpg"),
            driver->getTexture("../media/irrlicht2_ft.jpg"),
            driver->getTexture("../media/irrlicht2_bk.jpg")
        );
 
        node->setRotation(irr::core::vector3df(0,-90.0f,0));//This way, the skybox matches the cubemap ;)
 
        //Add some rotating spheres and cubes...
        irr::scene::ISceneNode* root = manager->addEmptySceneNode();
        irr::scene::ISceneNodeAnimator* anim = manager->createRotationAnimator(irr::core::vector3df(0,0.1f,0));
        root->addAnimator(anim);
        anim->drop();
 
        for(int i=0;i<12;i++)
        {
            irr::scene::ISceneNode* sphere = manager->addSphereSceneNode(50.0f);
            sphere->setPosition(irr::core::vector3df(sin(2*i*irr::core::PI/12.0f)*350,0.0f,cos(2*i*irr::core::PI/12.0f)*350.0f));
            sphere->getMaterial(0).setTexture(0,driver->getTexture("../media/water.jpg"));
            sphere->getMaterial(0).setTexture(1,cubemap);
            sphere->getMaterial(0).MaterialType = (irr::video::E_MATERIAL_TYPE)shader;
            sphere->setParent(root);
        }
 
        irr::scene::ISceneNode* root2 = manager->addEmptySceneNode();
        irr::scene::ISceneNodeAnimator* anim2 = manager->createRotationAnimator(irr::core::vector3df(0.1f,0,0));
        root2->addAnimator(anim2);
        anim2->drop();
 
        for(int i=0;i<18;i++)
        {
            irr::scene::ISceneNode* sphere = manager->addCubeSceneNode(20.0f);
            sphere->setPosition(irr::core::vector3df(sin(2*i*irr::core::PI/12.0f)*260,0.0f,cos(2*i*irr::core::PI/12.0f)*260.0f));
            sphere->getMaterial(0).setTexture(0,driver->getTexture("../media/rockwall_height.bmp"));
            sphere->getMaterial(0).setTexture(1,cubemap);
            sphere->getMaterial(0).MaterialType = (irr::video::E_MATERIAL_TYPE)shader;
            sphere->setParent(root2);
        }
 
        irr::scene::ISceneNode* root3 = manager->addEmptySceneNode();
        irr::scene::ISceneNodeAnimator* anim3 = manager->createRotationAnimator(irr::core::vector3df(0,0,0.1f));
        root3->addAnimator(anim3);
        anim3->drop();
 
        for(int i=0;i<24;i++)
        {
            irr::scene::ISceneNode* sphere = manager->addSphereSceneNode(10.0f);
            sphere->setPosition(irr::core::vector3df(sin(2*i*irr::core::PI/12.0f)*80,0.0f,cos(2*i*irr::core::PI/12.0f)*80.0f));
            sphere->getMaterial(0).setTexture(0,driver->getTexture("../media/water.jpg"));
            sphere->getMaterial(0).setTexture(1,cubemap);
            sphere->getMaterial(0).MaterialType = (irr::video::E_MATERIAL_TYPE)shader;
            sphere->setParent(root3);
        }
 
        root2->setParent(root);
        root3->setParent(root2);
 
        //Add a dwarf...
        irr::scene::IAnimatedMesh* dwarf = manager->getMesh("../media/dwarf.x");
        irr::scene::ISceneNode* dwarfNode = manager->addAnimatedMeshSceneNode(dwarf);
        for(unsigned int i=0;i<dwarfNode->getMaterialCount();i++)
        {
            dwarfNode->getMaterial(i).setTexture(1,cubemap);
            dwarfNode->getMaterial(i).MaterialType = (irr::video::E_MATERIAL_TYPE)shader;
        }
        
        irr::s32 lastFPS = -1;
 
        while(device->run())
        {
            const irr::s32 fps = driver->getFPS();
            driver->beginScene();
            manager->drawAll();
            irr::core::stringw str = L"Irrlicht Engine - Cubemaps Example [";
            str += driver->getName();
            str += "] FPS:";
            str += fps;
 
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
            driver->endScene();
        }
 
    }
}
 
Direct3D9 shader:

Code: Select all

 
/*Shader code for DirectX*/
float4x4 matWorldViewProjection;
float4x4 matViewInverse;
float4x4 matWorld;
sampler2D baseMap;
samplerCUBE reflectionMap;
 
struct vertexIN
{
   float4 Position : POSITION0;
   float2 Texcoord : TEXCOORD0;
   float3 Normal :   NORMAL0;
};
 
struct vertexOUT
{
    float4 position : POSITION0;
    float2 texcoord : TEXCOORD0;
    float3 normal : TEXCOORD1;
    float3 viewDirection: TEXCOORD2;
};
 
vertexOUT vs_main(vertexIN IN)
{
    vertexOUT OUT;
    OUT.position = mul(IN.Position,matWorldViewProjection);
    OUT.normal = mul(float4(IN.Normal,0),matWorld).xyz;
    OUT.viewDirection = mul(float4(OUT.position.xyz,0),matViewInverse).xyz;
    OUT.texcoord = IN.Texcoord;
    return OUT;
}
 
struct pixelIN
{
    float2 texcoord : TEXCOORD0;
    float3 normal : TEXCOORD1;
    float3 viewDirection: TEXCOORD2;
};
 
 
float4 ps_main(pixelIN IN):color0
{
    float4 color = tex2D(baseMap,IN.texcoord);
    float3 reflection = normalize(reflect(IN.viewDirection,IN.normal));
    float4 reflectedColor = texCUBE(reflectionMap,reflection);
    return reflectedColor*color;
}
 
OpenGL shaders:
vertex:

Code: Select all

 
/*Shader for Open GL*/
 
uniform mat4 matViewInverse; //We need to move the normal into world space so the reflections are accurate
 
varying vec2 Texcoord;
varying vec3 Normal;
varying vec3 ViewDirection;
 
void main()
{
   gl_Position = ftransform();
   Texcoord    = gl_MultiTexCoord0.xy;
   Normal      = gl_NormalMatrix * gl_Normal;
   ViewDirection = normalize(gl_Position.xyz);
   Normal      = (matViewInverse*vec4(Normal,0)).xyz;
   ViewDirection = (matViewInverse*vec4(ViewDirection,0)).xyz;
}
 
fragment:

Code: Select all

 
/*Shader for Open GL*/
uniform sampler2D baseMap;
uniform samplerCube reflectionMap;
 
varying vec2 Texcoord;
varying vec3 Normal;
varying vec3 ViewDirection;
 
void main()
{
    vec4 color = texture(baseMap,Texcoord);
    vec3 reflection = normalize(reflect(ViewDirection,Normal));
    vec4 refl = texture(reflectionMap,reflection);
    gl_FragColor = color*refl;
}
 
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Environment Mapping with Irrlicht

Post by kinkreet »

but the SVN version is not stable isn't it?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Environment Mapping with Irrlicht

Post by CuteAlien »

@kinkreet: I work with svn most of the time (doing jobs for companies). Once in a while I have to go back a few versions, but doesn't happen often and generally we fix it quickly when it happens.
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
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Environment Mapping with Irrlicht

Post by kinkreet »

Awesome, thanks. I'll try the SVN with this cool demo ;)
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Environment Mapping with Irrlicht

Post by Nadro »

Few revs ago I added support for load cubemaps directly from PVR textures. IMO PVR is the best file format for texture handling in Irrlicht at now (it supports standard and cubemaps textures, both compressed and uncompressed formats and custom mipmaps).
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Environment Mapping with Irrlicht

Post by kinkreet »

Is there any PVR editor/exporter that does not require a license?

EDIT: Thanks @Nadro :)
Last edited by kinkreet on Mon Mar 14, 2016 9:02 pm, edited 1 time in total.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Environment Mapping with Irrlicht

Post by Nadro »

You can use PVRTexTool from PowerVR SDK. It's free.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Environment Mapping with Irrlicht

Post by hendu »

...but is it open source and available for all common platforms?
kinkreet
Posts: 64
Joined: Thu Oct 31, 2013 7:53 pm
Location: Barcelona, Spain

Re: Environment Mapping with Irrlicht

Post by kinkreet »

"Our Tools and SDK can be used freely (i.e., no fees) for any commercial or non-commercial purpose. The code provided can be modified, cut and paste as well as integrated into other projects....."

https://community.imgtec.com/developers ... nstallers/
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Environment Mapping with Irrlicht

Post by Nadro »

hendu wrote:...but is it open source and available for all common platforms?
PVRTextTool is available for Windows, Linux and OSX (CLI + GUI). IIRC it isn't open source, but it shouldn't be a problem in this case.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Environment Mapping with Irrlicht

Post by hendu »

It is a problem: they may have embedded malfeatures, and users may be on non-x86 platforms. Like the recent Power8 workstation ;)
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Environment Mapping with Irrlicht

Post by Nadro »

PVR format is relative simple, so there shouldn't be a problem to write exporter yourself. Spec is available at here: http://cdn.imgtec.com/sdk-documentation ... cation.pdf

Anyway I don't think there is a lot of people without non-x86 platforms whose design textures for Irrlicht based games :P There is also an option to convert textures remotely on x86 server via PVRTexTool command-line in that cases.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: Environment Mapping with Irrlicht

Post by hendu »

There is also an option to convert textures remotely on x86 server via PVRTexTool command-line in that cases.
That is, if you're willing to run IMG's closed-source blob.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Re: Environment Mapping with Irrlicht

Post by Nadro »

Texture arrays and cubemap arrays are not supported yet. We'll add texture arrays support after v1.9 release and cubemaps arrays in further future.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Post Reply