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();
}
}
}
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;
}
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;
}
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;
}