Several visual problems

Problems building or running the engine, queries about how to use features etc.
Post Reply
Radagast
Kobold
Posts: 33
Joined: Sun Nov 24, 2013 4:23 pm

Several visual problems

Post by Radagast »

Hi all!

I'm creating a simple fallout1-like multiplayer game using Ogre 1.9.0. Several topics I've created on this forum last week was all about it :)
But now I get something very strange. This is how I see my game when playing it with my friend:
Image
My config: Win7, D3D9, debug build
My friend's config: Win10, D3D9, release build
And he has this nightmare:
Image
I can't test my app on his machine because we are living in defferent cities and he doesn't even have the debugger :(
So, the list of problems:
1) He isn't able to see the whole map texture
2) Instead of lightmap that is responsible for field of view he has random shadowed/illuminated zones
3) Very strange way of how the models are moving. It is not his problem, it just appears it release mode. To understand what it means I've made two short movies:
1. How it should be (debug mode)
[youtube]A5CcUzHiHxM[/youtube]
2. How it is in the release mode
[youtube]acTKF9W2DxI[/youtube]
So, the robot moves... actually, I don't know how it's in english, but, maybe, jerkily or spasmodically? Google translate says so :D
For moving the robot I use technique described in Intermediate Tutorial 1
How you can mention there also is a problem with FOV, but I think that this problem is somewhere inside my code that has no contacts with the Ogre (although I can't get it: how one and the same code may be working another way in release mode :? I don't have any "#ifdef _DEBUG"-like stuff in it).

What I'm doing and (I think) what is the reason of these bugs:
For lightmapping I take the "rockwall.tga" texture from Ogre standart texture pack, clone it 25 times so I get a big manual texture. Then I create another big texture of the same size and make it white and grey on light and dark cells, respectively, then make a manual material. I took this method from manual (that topic is about it)
I think it is the reason because in the old version of my game (where was no lightmapping and creating manual textures) there are no such terrible bugs.

This is how I create the big map texture:

Code: Select all

	Ogre::TexturePtr sourceTexture = Ogre::TextureManager::getSingleton().load("rockwall.tga", "General");

	// Create the texture
	const int sourceWidth = sourceTexture->getWidth(),
			  sourceHeight = sourceTexture->getHeight();
	const int N = 5; // NxN texture grid

	auto m_GroundTexture = Ogre::TextureManager::getSingleton().createManual(
		"GroundTexture",				// name
		Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D,				// type
		sourceWidth*N,					// width
		sourceHeight*N,					// height
		0,							// number of mipmaps
		sourceTexture->getFormat(),		// pixel format
		Ogre::TU_DEFAULT);				

	// Get the pixel buffer
	Ogre::HardwarePixelBufferSharedPtr	pixelBuffer = m_GroundTexture->getBuffer(),
										sourcePixelBuffer = sourceTexture->getBuffer();

	// Lock the pixel buffer and get a pixel box
	pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
	sourcePixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
	const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
	const Ogre::PixelBox& rockBox = sourcePixelBuffer->getCurrentLock();

	Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);
	Ogre::uint8* pSource = static_cast<Ogre::uint8*>(rockBox.data);

	// copying the first N texture instances
	for (int j = 0; j < sourceHeight; ++j) {

		for (int k = 0; k < N; ++k) {
			memcpy(pDest, pSource, sourceWidth*4);
			pDest += sourceWidth*4;
		}

		pSource += sourceWidth*4;
	}

	// then copy leftover (N-1)*N instances from already copied N
	for (int k = 1; k < N; ++k) {
		memcpy(pDest, pixelBox.data, sourceWidth*sourceHeight*4*N);
		pDest += sourceWidth*sourceHeight*4*N;
	}

	// Unlock the pixel buffer
	pixelBuffer->unlock();
	sourcePixelBuffer->unlock();
	sourceTexture->unload();
And this is how I create the lightmap texture:

Code: Select all

	auto m_LightmapTexture = Ogre::TextureManager::getSingleton().createManual(
		"LightmapTexture",
		Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
		Ogre::TEX_TYPE_2D,
		sourceWidth*N, sourceHeight*N,
		0,
		Ogre::PF_A8R8G8B8,
		Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE);

	m_pLightmapTexture = m_LightmapTexture.getPointer();

	pixelBuffer = m_LightmapTexture->getBuffer();
	pixelBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD);

	const Ogre::PixelBox& pixelBoxL = pixelBuffer->getCurrentLock();
	pDest = static_cast<Ogre::uint8*>(pixelBoxL.data);

	const int lightmapWidth = m_LightmapTexture->getWidth(),
			  lightmapHeight = m_LightmapTexture->getHeight();

	// shomehow the pixel format is B8G8R8X8, although I've been asking for A8R8G8B8
	// COLOUR_SHADOW_VALUE == 127
	for (int i = 0; i < lightmapWidth * lightmapHeight; ++i) {
		*pDest++ = COLOUR_SHADOW_VALUE; //blue
		*pDest++ = COLOUR_SHADOW_VALUE; //green
		*pDest++ = COLOUR_SHADOW_VALUE; //red
		++pDest;
	}

	pixelBuffer->unlock();
Creating a manual material:

Code: Select all

	auto mapMaterial = Ogre::MaterialManager::getSingleton().create(
		"GroundMaterial", // name
		Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);

	mapMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
	mapMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTexture(m_GroundTexture);
	mapMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setColourOperation(Ogre::LBO_MODULATE);

	mapMaterial->getTechnique(0)->createPass();

	mapMaterial->getTechnique(0)->getPass(1)->setSceneBlending(Ogre::SBT_MODULATE);
	mapMaterial->getTechnique(0)->getPass(1)->createTextureUnitState();
	mapMaterial->getTechnique(0)->getPass(1)->getTextureUnitState(0)->setTexture(m_LightmapTexture);
	mapMaterial->getTechnique(0)->getPass(1)->getTextureUnitState(0)->setColourOperation(Ogre::LBO_MODULATE);

	m_GroundMaterialHandle = mapMaterial->getHandle(); // for future access

And, finally, updating the lightmap every time unit changes his cell coordinates:

Code: Select all

	FieldOfView lm = *m_pGameMap->getCurFOV(); // 2d int array, positive value means that the cell is visible now
	FieldOfView& lm_old = *m_pRenderedFOV; // current rendered FOV

	Ogre::HardwarePixelBufferSharedPtr pixelBuffer = m_pLightmapTexture->getBuffer();
	// Lock the pixel buffer and get a pixel box
	pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NO_OVERWRITE);

	const Ogre::PixelBox& pixelBoxL = pixelBuffer->getCurrentLock();

	Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBoxL.data);

	const int W = m_pGameMap->getWidth(), H = m_pGameMap->getHeight();

	const int Width = m_pLightmapTexture->getWidth(),
				Height = m_pLightmapTexture->getHeight(),
				Width_1 = m_pLightmapTexture->getWidth()/float(W) + 0.5f, //width of one cell
				Height_1 = m_pLightmapTexture->getHeight()/float(H) + 0.5f; //height of one cell
				// Width and height of texture are divisible by W and H

	int y_render, x_render;

	for (int x = 0; x < W; ++x)
		for (int y = 0; y < H; ++y) {
			if ((lm(x, y) > 0) && lm_old(x, y) <= 0) { // if the cell was not visible and is now
				y_render = H - y; // some black magic, never mind, that's not a point now, I'm stuck with the textures, not with the incorrect FOV
				x_render = W - x;
				pDest = static_cast<Ogre::uint8*>(pixelBoxL.data) +
					(Width * Height_1 * (y_render - 1) + Width_1 * (x_render - 1))*4;
				for (int j = 0; j < Height_1; ++j) {
					memcpy(pDest, m_LightLine, Width_1*4); //m_LightLine is an array with the values of 255
					pDest += Width*4;
				}
			} else if ((lm(x, y) <= 0) && lm_old(x, y) > 0) { // if the cell is now invisible and was visible
				y_render = H - y;
				x_render = W - x;
				pDest = static_cast<Ogre::uint8*>(pixelBoxL.data) +
					(Width * Height_1 * (y_render - 1) + Width_1 * (x_render - 1))*4;
				for (int j = 0; j < Height_1; ++j) {
					memcpy(pDest, m_DarkLine, Width_1*4); //m_DarkLine is an array with the values of 127
					pDest += Width*4;
				}
			} // else the cell visibility remains unchanged and there is no need to change the illumination
		}

	pixelBuffer->unlock();

	lm_old = std::move( lm );
What direction should I look in to fix my problems?
Thanks for your attention, I would be very grateful for any help!
Post Reply