Alright. This is exactly the issue I'm running into, and it's driving me nuts, and I could really use an OpenGL solution since for my particular project (NDA, sorry) DirectX isn't going to be an option.
Obviously OpenGL can handle things correctly, as evidenced by Per Pixel Lighting example 11. But like HydroNom, I've tried dropping the exact same earth model with the exact same normal map into my own project, running the mesh through the tangent generator as suggested here and performed in the example, and it still lights as if the light is attached to and/or counter-rotating about the model. Parallax distortion may also be going a little screwy.
I've tried playing with all the differences I can find between my code and the example code (fixed vs FPS camera, point vs directional light, sphere mesh vs loaded model with and without creating tangent mesh, 1 light vs 2 lights, scale & distance, fog vs no, event receiver vs no, order of instantiating camera/lights/models, even enabling EMF_NORMALIZE_NORMALS on the material) to no avail. Can anyone think of any other important factors in getting the stock shaders working correctly?
Edit: I even dropped my for-real model into the working example and it lit just fine even without running it through the tangent generator (high-end high-poly Maya obj, it probably has the tangents already). There's
something I'm obviously not quite catching, but I could swear I've been through the example code, line by line, at least 5 times
I'll keep poking, and post the solution if I find it, but until then any help would be greatly appreciated.
Edit2: For the nonbelievers, here's a stripped down example demonstrating the problem. rainbow.png could really be anything, earthbump.bmp and earth.x are as provided in the examples, the whole thing is basically the Hello World example with parallax added. And the problem persists regardless of whether everything is parented to a root dummy node or to 0. If anyone bothers to run this on their own, thank you in advance, and if it actually works correctly on your machine under OpenGL, I'll be quite curious to know, since that means it does actually boil down to an OpenGL implementation issue that the stock parallax example somehow unintentionally circumvents...
Code: Select all
int main()
{
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 0;
}
IrrlichtDevice *device = createDevice( driverType, core::dimension2d<s32>(640, 480), 16,
false, false, false, 0);
device->setWindowCaption(L"Hello World! - Irrlicht Engine Demo");
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
guienv->addStaticText(L"Hello World! This is the Irrlicht Software renderer!",
core::rect<s32>(10,10,260,22), true);
driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
video::E_MATERIAL_TYPE type = video::EMT_PARALLAX_MAP_SOLID;
// set up for parallax, etc.
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(type);
if (renderer && renderer->getRenderCapability() != 0){
cout<<"Can't do parallax mapping on this hardware."<<endl;
type = video::EMT_NORMAL_MAP_SOLID;
renderer = driver->getMaterialRenderer(type);
}
if (renderer && renderer->getRenderCapability() != 0){
cout<<"Can't even do normal mapping."<<endl;
type = video::EMT_SOLID;
renderer = driver->getMaterialRenderer(type);
}
scene::ISceneNode *root = smgr->addEmptySceneNode();
scene::ILightSceneNode *light1 =
smgr->addLightSceneNode(root, core::vector3df(0,30,-40),
video::SColorf(0.8f,0.8f,0.8f,0.0f), 500.0f);
//scene::IAnimatedMesh *sphereMesh = smgr->addSphereMesh("",5,16,16);
scene::IAnimatedMesh *sphereMesh = smgr->getMesh("earth.x");
scene::IMeshManipulator *manipulator = smgr->getMeshManipulator();
scene::IMesh *tangentMesh = manipulator->createMeshWithTangents(sphereMesh->getMesh(0));
scene::IMeshSceneNode* node2 = smgr->addMeshSceneNode(
tangentMesh,
root,//parent
-1,//id
core::vector3df(0,25,-20),//position
core::vector3df(0,180,0),//rotation
core::vector3df(1,1,1),//scale
false); // still add if mesh pointer NULL
node2->setMaterialType(type); // set the type for all materials
node2->getMaterial(0).setTexture(0, driver->getTexture("rainbow.png"));
video::ITexture* normalMap = driver->getTexture("earthbump.bmp");
driver->makeNormalMapTexture(normalMap, 1.0f);
node2->getMaterial(0).setTexture(1, normalMap);
node2->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
scene::ISceneNodeAnimator* anim =
smgr->createRotationAnimator(core::vector3df(0,0.2f,0));
node2->addAnimator(anim);
anim->drop();
smgr->addCameraSceneNode(root, core::vector3df(0,30,-40), core::vector3df(0,5,0));
while(device->run())
{
driver->beginScene(true, true, video::SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
device->drop();
return 0;
}