Volumes Of Fun
http://www.volumesoffun.com/phpBB3/

Using Ambient Occlusion
http://www.volumesoffun.com/phpBB3/viewtopic.php?f=2&t=156
Page 1 of 1

Author:  Jmgr [ Wed Mar 02, 2011 9:00 pm ]
Post subject:  Using Ambient Occlusion

Hi people,

Now that I have achieved texturing my cubes I would like to add ambient occlusion using the AmbientOcclusionCalculator.

I looked at the Thermite project but couldn't really find out what are the steps required to send the resulting volume to the GPU.

For now I'm computing my AmbientOcclusionVolume each time a chunk is updated and then storing it into a 3D texture. (the same thing that Thermite does)

To create the 3D texture :
Code:
mAmbientOcclusionVolumeTexture = Ogre::TextureManager::getSingleton().createManual(
   "AmbientOcclusionVolumeTexture" + Ogre::StringConverter::toString(x) + "_" + Ogre::StringConverter::toString(y), // Name of texture
     "General", // Name of resource group in which the texture should be created
     Ogre::TEX_TYPE_3D, // Texture type
     ChunkSizeX, // Width
     ChunkSizeY, // Height
     ChunkSizeZ, // Depth (Must be 1 for two dimensional textures)
     0, // Number of mipmaps
     Ogre::PF_L8, // Pixel format
     Ogre::TU_STATIC_WRITE_ONLY // usage
     );

x and y are the coordinates of the chunk.

Copying the computed volume into this texture :
Code:
Ogre::HardwarePixelBuffer* pixelBuffer = mAmbientOcclusionVolumeTexture.getPointer()->getBuffer().getPointer();
   Ogre::PixelBox pixelBox(mAmbientOcclusionVolumeTexture->getWidth(),mAmbientOcclusionVolumeTexture->getHeight(),mAmbientOcclusionVolumeTexture->getDepth(), mAmbientOcclusionVolumeTexture->getFormat(), ambientOcclusionVolume->getRawData());
   pixelBuffer->blitFromMemory(pixelBox);


I'm certainly missing something because the computation seems to take place (it's using one CPU core for some time) but nothing can be seen.

Author:  David Williams [ Wed Mar 02, 2011 9:20 pm ]
Post subject:  Re: Using Ambient Occlusion

Unfortunatly Thermite doesn't show everything you need to know - there is some shader code to go with it which is part of the game rather than being part of Thermite. Basically you need the following steps:

1) Create the 3D array comtaining the data, using the PolyVox AmbientOcclusionCalculator. You can also try just filling the array with a 3D checkerboard pattern or something, for debugging.

2) Copy the 3D array into a Ogre volume texture.

3) Declare the texture to your material. Be aware, you might need to be careful to make sure the texture has been created in code before the material actually tries to use it.
Code:
texture_unit
{
   texture AmbientOcclusionVolumeTexture 3d
   tex_address_mode clamp
}


4) Pass the texture as a parameter to your pixel shader and sample it to apply the lighting. Note that you need to know the volume size to do this:

Code:
float ambientVal = tex3D(ambientMap, (inWorldPosition.xyz + float3(0.499f, 0.499f, 0.499f)) / float3(256.0f, 64.0f, 256.0f));


I've attached some code you might find useful.

Attachments:
VoxelMaterial.zip [3.67 KiB]
Downloaded 373 times

Author:  Jmgr [ Wed Mar 02, 2011 9:30 pm ]
Post subject:  Re: Using Ambient Occlusion

Thanks, I will check this.

It seems that the zip file is corrupted?

Author:  milliams [ Wed Mar 02, 2011 9:53 pm ]
Post subject:  Re: Using Ambient Occlusion

Jmgr wrote:
It seems that the zip file is corrupted?
It extracts fine for me.

Author:  Jmgr [ Wed Mar 02, 2011 10:01 pm ]
Post subject:  Re: Using Ambient Occlusion

Oh yes I see It's working with Chrome... No idea why Firefox didn't want it.

Author:  Jmgr [ Thu Mar 03, 2011 7:28 pm ]
Post subject:  Re: Using Ambient Occlusion

I'm using 16x128x16 chunks for now. Do you think that it would be possible to generate one ambient occlusion texture per chunk rather than for the whole volume ?

Also ambient occlusion computation time seems to be very high. I don't know the optimal value of fRayLength, but with 32 it takes a very long time for 16*128*16 chunks. I heard somewhere that it is possible to do this on the GPU, but my GPU skills are too low to implement that anyway ;)

Author:  David Williams [ Thu Mar 03, 2011 11:36 pm ]
Post subject:  Re: Using Ambient Occlusion

Jmgr wrote:
I'm using 16x128x16 chunks for now. Do you think that it would be possible to generate one ambient occlusion texture per chunk rather than for the whole volume ?

Probably not... I expect you would see visual artefacts because one chunk should actually cause occlusion in the next. Besides, you would then have to upload multiple volume textures to the GPU.

It should be possible to update only part of the volume texture at a time though - I don't think I did this yet in Thermite (I think I still upload the whole thing).

Jmgr wrote:
Also ambient occlusion computation time seems to be very high. I don't know the optimal value of fRayLength, but with 32 it takes a very long time for 16*128*16 chunks. I heard somewhere that it is possible to do this on the GPU, but my GPU skills are too low to implement that anyway ;)

Yes, it is currently slow. That said, you shouldn't need to make the volume texture as large as the chuck - ambient occlusion changes slowly so in Thermite I'm using a volume texture 1/4 the size of the volume in each dimension. In your case that would be 32x4x4.

I should also point out that it's all very experimental... I like the result I've got in Thermite but there's plenty of research to be done. You might decide that you don't want to store the ambient occlusion in a volume texture for example, but you would prefer to store it in the vertices. This will be much better for large volumes. You would have to implement this yourself using the Raycast class aand looking at the AmbientOcclusionCalculator as an example.

Author:  AndiNo [ Thu Apr 05, 2012 1:37 am ]
Post subject:  Re: Using Ambient Occlusion

I hope it's okay to revive this old thread :) I found it to be the most helpful in regard to ambient occlusion.
It seems AO is nearly working for me. However I could not find any information about how I should feed the generated AO data into the Ogre 3D texture. The way I do it now is most probably wrong.

Code:
   // fill Ogre texture with data
   Ogre::HardwarePixelBufferSharedPtr pixelBuffer = AOtexture->getBuffer();
   pixelBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL);
   const Ogre::PixelBox& pixelBox = pixelBuffer->getCurrentLock();
   Ogre::uint8* pDest = static_cast<Ogre::uint8*>(pixelBox.data);

   for (int z=0; z<AO_VOL_SIZE; z++)
   {
      for (int y=0; y<AO_VOL_SIZE; y++)
      {
         for (int x=0; x<AO_VOL_SIZE; x++)
         {
            *pDest++ = ambientOcclusionResult[x][y][z];
         }
      }
   }


The important line is in the for-loops. In which order do I have to write the data into the texture? Are there better methods to copy the data?

Author:  David Williams [ Thu Apr 05, 2012 8:12 am ]
Post subject:  Re: Using Ambient Occlusion

The ambient occlusion code in Thermite3D has been removed as updating AO was too slow for Voxeliens (we'll come back to that in the future) but you can still find some stuff through Git. In particular have a look at these few lines:

http://www.gitorious.org/thermite3d/the ... pp#line288

You might also find it useful to create dummy textures (e.g. going from dark to light as you move along a known axis) in order to make sure the orientation is correct.

Author:  David Williams [ Sun Apr 08, 2012 3:29 pm ]
Post subject:  Re: Using Ambient Occlusion

Bug report split off to here: viewtopic.php?f=15&t=360

Page 1 of 1 All times are UTC
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/