textureRenderStates.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // Copyright (C) 2008-2012 Christian Stehno, Colin MacDonald
  2. // No rights reserved: this software is in the public domain.
  3. #include "testUtils.h"
  4. using namespace irr;
  5. using namespace core;
  6. static bool manyTextures(video::E_DRIVER_TYPE driverType)
  7. {
  8. IrrlichtDevice *device = createDevice(driverType, dimension2d<u32>(160, 120), 32);
  9. if (!device)
  10. return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
  11. video::IVideoDriver* driver = device->getVideoDriver();
  12. scene::ISceneManager * smgr = device->getSceneManager();
  13. stabilizeScreenBackground(driver);
  14. logTestString("Testing driver %ls\n", driver->getName());
  15. (void)smgr->addCameraSceneNode();
  16. scene::SMeshBufferLightMap* mesh = new scene::SMeshBufferLightMap;
  17. mesh->Vertices.reallocate(4);
  18. mesh->Indices.reallocate(6);
  19. mesh->Vertices.push_back(video::S3DVertex2TCoords(-50,50,80,irr::video::SColor(255,100,100,100),0,1,0,1));
  20. mesh->Vertices.push_back(video::S3DVertex2TCoords(50,50,80,irr::video::SColor(255,100,100,100),1,1,1,1));
  21. mesh->Vertices.push_back(video::S3DVertex2TCoords(50,-50,80,irr::video::SColor(255,100,100,100),1,0,1,0));
  22. mesh->Vertices.push_back(video::S3DVertex2TCoords(-50,-50,80,irr::video::SColor(255,100,100,100),0,0,0,0));
  23. mesh->Indices.push_back(0);
  24. mesh->Indices.push_back(1);
  25. mesh->Indices.push_back(2);
  26. mesh->Indices.push_back(2);
  27. mesh->Indices.push_back(3);
  28. mesh->Indices.push_back(0);
  29. video::SMaterial& mat = mesh->getMaterial();
  30. mat.Lighting = false;
  31. mat.setTexture(0,driver->getTexture("../media/fire.bmp"));
  32. mat.setTexture(1,driver->getTexture("../media/fire.bmp"));
  33. mat.setTexture(2,driver->getTexture("../media/fire.bmp"));
  34. mat.setTexture(3,driver->getTexture("../media/fire.bmp"));
  35. mesh->setDirty();
  36. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  37. // set camera
  38. smgr->drawAll();
  39. // draw meshbuffer
  40. driver->setMaterial(mat);
  41. driver->drawMeshBuffer(mesh);
  42. driver->endScene();
  43. mesh->drop();
  44. bool result = takeScreenshotAndCompareAgainstReference(driver, "-multiTexture.png", 99.31f);
  45. device->closeDevice();
  46. device->run();
  47. device->drop();
  48. return result;
  49. }
  50. //! Tests interleaved loading and rendering of textures
  51. /** The test loads a texture, renders it using draw2dimage, loads another
  52. texture and renders the first one again. Due to the texture cache this
  53. can lead to rendering of the second texture in second place. */
  54. static bool renderAndLoad(video::E_DRIVER_TYPE driverType)
  55. {
  56. IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
  57. if (!device)
  58. return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
  59. video::IVideoDriver* driver = device->getVideoDriver();
  60. scene::ISceneManager * smgr = device->getSceneManager();
  61. stabilizeScreenBackground(driver);
  62. logTestString("Testing driver %ls\n", driver->getName());
  63. video::ITexture* tex1 = driver->getTexture("../media/wall.bmp");
  64. (void)smgr->addCameraSceneNode();
  65. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  66. driver->draw2DImage(tex1, position2di(0,0));
  67. driver->endScene();
  68. driver->getTexture("../media/tools.png");
  69. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  70. driver->draw2DImage(tex1, position2di(0,0));
  71. driver->endScene();
  72. bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureRenderStates.png", 99.85f);
  73. device->closeDevice();
  74. device->run();
  75. device->drop();
  76. return result;
  77. }
  78. // This test would cause a crash if it does not work
  79. // in 1.5.1 and 1.6 an illegal access in the OpenGL driver caused this
  80. static bool renderAndRemove(video::E_DRIVER_TYPE driverType)
  81. {
  82. IrrlichtDevice *device = createDevice( driverType, dimension2d<u32>(160, 120), 32);
  83. if (!device)
  84. return true; // Treat a failure to create a driver as benign; this saves a lot of #ifdefs
  85. video::IVideoDriver* driver = device->getVideoDriver();
  86. scene::ISceneManager * smgr = device->getSceneManager();
  87. stabilizeScreenBackground(driver);
  88. logTestString("Testing driver %ls\n", driver->getName());
  89. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255, 0, 255, 0));
  90. smgr->drawAll();
  91. driver->endScene();
  92. smgr->addCameraSceneNode();
  93. video::ITexture* texture = driver->getTexture ("media/tools.png");
  94. scene::ISceneNode * img = smgr->addCubeSceneNode();
  95. img->setMaterialTexture(0, texture);
  96. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor (255, 0, 255, 0));
  97. smgr->drawAll();
  98. driver->endScene();
  99. smgr->clear(); // Remove anything that used the texture
  100. driver->removeTexture(texture);
  101. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  102. smgr->drawAll();
  103. driver->endScene();
  104. smgr->addCameraSceneNode();
  105. texture = driver->getTexture("media/tools.png");
  106. img = smgr->addCubeSceneNode();
  107. img->setMaterialTexture(0, texture);
  108. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, irr::video::SColor (255, 0, 255, 0));
  109. smgr->drawAll();
  110. driver->endScene();
  111. device->closeDevice();
  112. device->run();
  113. device->drop();
  114. return true;
  115. }
  116. static bool testTextureMatrixInMixedScenes(video::E_DRIVER_TYPE driverType)
  117. {
  118. irr::IrrlichtDevice* device = createDevice(driverType, dimension2du(160,120));
  119. if (!device)
  120. return true;
  121. video::IVideoDriver* driver = device->getVideoDriver();
  122. scene::ISceneManager* sceneManager = device->getSceneManager();
  123. gui::IGUIEnvironment* gui = device->getGUIEnvironment();
  124. if (!driver->queryFeature(video::EVDF_TEXTURE_MATRIX))
  125. {
  126. device->closeDevice();
  127. device->run();
  128. device->drop();
  129. return true;
  130. }
  131. stabilizeScreenBackground(driver);
  132. logTestString("Testing driver %ls\n", driver->getName());
  133. scene::ICameraSceneNode* camera = sceneManager->addCameraSceneNode();
  134. camera->setPosition(vector3df(0,10,0));
  135. gui::IGUIStaticText* stext = gui->addStaticText(L" ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 ",
  136. rect<s32>(5,100,150,125),false,false,0,false);
  137. stext->setBackgroundColor(video::SColor(255,128,0,0));
  138. stext->setOverrideColor(video::SColor(255,255,255,255));
  139. gui->addEditBox(L"Test edit box", rect<s32>(5,50,150,75));
  140. gui->addCheckBox(true, rect<s32>(5, 20, 150, 45),0,-1,L"Test CheckBox");
  141. video::SMaterial mat;
  142. mat.MaterialType = video::EMT_SOLID;
  143. mat.setFlag(video::EMF_LIGHTING, false);
  144. // problem doesn't occur if the scale defaults: (1.f,1.f).
  145. mat.getTextureMatrix(0).setTextureScale(2.0,2.0);
  146. scene::IAnimatedMesh* pmesh = sceneManager->addHillPlaneMesh("testMesh",dimension2d<f32>(50,50),dimension2d<u32>(6,6),&mat);
  147. sceneManager->addAnimatedMeshSceneNode(pmesh);
  148. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  149. sceneManager->drawAll();
  150. gui->drawAll();
  151. driver->endScene();
  152. bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureMatrixInMixedScenes.png", 99.33f);
  153. device->closeDevice();
  154. device->run();
  155. device->drop();
  156. return result;
  157. }
  158. // animated texture matrix test.
  159. static bool textureMatrix(video::E_DRIVER_TYPE driverType)
  160. {
  161. irr::IrrlichtDevice* device = createDevice(driverType, dimension2du(160,120));
  162. if (!device)
  163. return true;
  164. video::IVideoDriver* driver = device->getVideoDriver();
  165. scene::ISceneManager* sceneManager = device->getSceneManager();
  166. if (!driver->queryFeature(video::EVDF_TEXTURE_MATRIX))
  167. {
  168. device->closeDevice();
  169. device->run();
  170. device->drop();
  171. return true;
  172. }
  173. stabilizeScreenBackground(driver);
  174. logTestString("Testing driver %ls\n", driver->getName());
  175. scene::ICameraSceneNode* camera = sceneManager->addCameraSceneNode();
  176. camera->setPosition(vector3df(0,0,-10));
  177. // set up plane mesh to face the camera
  178. scene::IMesh* mesh = sceneManager->getGeometryCreator()->createPlaneMesh(dimension2df(150,150), core::dimension2du(1,1),0,core::dimension2df(1,1));
  179. scene::IMeshSceneNode* node = sceneManager->addMeshSceneNode(mesh, 0, -1, vector3df(0, 0, 150), vector3df(-90, 0, 0));
  180. if (mesh)
  181. mesh->drop();
  182. // set the hillplane material texture & save a reference
  183. // to the texture matrix.
  184. video::SMaterial& material = node->getMaterial(0);
  185. video::ITexture* tex = driver->getTexture("../media/water.jpg");
  186. material.setTexture(0,tex);
  187. material.setFlag(video::EMF_LIGHTING,false);
  188. matrix4& textureMatrix = material.TextureLayer[0].getTextureMatrix();
  189. const vector2df rcenter, scale(1.f, 1.f);
  190. vector2df trans;
  191. trans.X += 0.0005f;
  192. textureMatrix.buildTextureTransform(0.f, rcenter, trans, scale);
  193. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  194. sceneManager->drawAll();
  195. driver->endScene();
  196. bool result = takeScreenshotAndCompareAgainstReference(driver, "-textureMatrix.png");
  197. trans.X += 0.45f;
  198. textureMatrix.buildTextureTransform(0.f, rcenter, trans, scale);
  199. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, video::SColor(255,100,101,140));
  200. sceneManager->drawAll();
  201. driver->endScene();
  202. result &= takeScreenshotAndCompareAgainstReference(driver, "-textureMatrix2.png");
  203. device->closeDevice();
  204. device->run();
  205. device->drop();
  206. return result;
  207. }
  208. bool danglingTexturePointer()
  209. {
  210. // A demo of the OpenGL "white texture" bug in Irrlicht
  211. // Author: Matt Giuca
  212. // (Vaguely based on the Irrlicht 2D graphics tutorial)
  213. // I have found that in some situations, when using the OpenGL driver, some
  214. // textures appear white.
  215. // This is caused by deleting a texture while it is active (the last texture
  216. // read or written to), and then loading a new texture at the same memory
  217. // location. The new texture will not be loaded properly.
  218. // This demo triggers the bug (though there is some probability that it won't
  219. // be triggered; just run it again until it shows a white square instead of
  220. // the Irrlicht logo).
  221. // This is only a problem in the OpenGL driver
  222. irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL,
  223. irr::core::dimension2d<irr::u32>(160, 120));
  224. if (!device)
  225. return true;
  226. irr::video::IVideoDriver* driver = device->getVideoDriver();
  227. stabilizeScreenBackground(driver);
  228. // Load a texture from a file
  229. // This binds and uploads to OpenGL texture #2.
  230. irr::video::ITexture* logo2 = driver->getTexture("../media/irrlichtlogo2.png");
  231. // Remove the texture from the driver (delete it from hardware)
  232. // This leaves CurrentTexture pointing at logo2
  233. driver->removeTexture(logo2);
  234. // Load another texture from a file
  235. // There is a good probability that logo3 will be allocated the same
  236. // memory address as logo2. If that happens,
  237. // COpenGLDriver::setActiveTexture will not bother to call glBindTextures
  238. // (thinking that logo3 is the same texture as logo2).
  239. // Therefore, the logo3 texture will be uploaded to texture #0, not #2.
  240. irr::video::ITexture* logo3 = driver->getTexture("../media/irrlichtlogo3.png");
  241. device->run();
  242. {
  243. driver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, irr::video::SColor(255,100,101,140));
  244. // This is required to trigger the white appearance (this unbinds the
  245. // texture, forcing draw2DImage to rebind the logo3 texture (#2)).
  246. driver->setMaterial(irr::video::SMaterial());
  247. // Since logo3 was uploaded to #0, not #2, this will bind texture #2,
  248. // which has never been written to. OpenGL considers an empty texture
  249. // to be white.
  250. driver->draw2DImage(logo3, irr::core::position2d<irr::s32>(20, 20));
  251. driver->endScene();
  252. }
  253. const bool result = takeScreenshotAndCompareAgainstReference(driver, "-texturePointer.png");
  254. device->closeDevice();
  255. device->run();
  256. device->drop();
  257. return result;
  258. }
  259. bool textureRenderStates(void)
  260. {
  261. bool result = true;
  262. TestWithAllDrivers(renderAndLoad);
  263. TestWithAllDrivers(renderAndRemove);
  264. TestWithAllDrivers(testTextureMatrixInMixedScenes);
  265. TestWithAllDrivers(manyTextures);
  266. TestWithAllDrivers(textureMatrix);
  267. result &= danglingTexturePointer();
  268. return result;
  269. }