bymulker
11-10-2008 14:58:59
hi everyone ,
With all the limits of my graphics card , i've been looking forward to do splatting by modifying the material of the terrain. This way i one would organize splat textures dynamically. I first began by color painting. It works great ;
THis is also useful for showing navigation meshes, a* path debugging, blood splatting etc.
When it comes to texture splatting i fail for i only get a 8x8 greeny texture on the terrain ;
and i made a small addon to ETM 2.3.1 -> paint2 function
Here i 'paint'. This adjusts the coverage maps. Then i tend to do whats in the shaders. The implementation is too straightforward.Does someone have any suggestions??
With all the limits of my graphics card , i've been looking forward to do splatting by modifying the material of the terrain. This way i one would organize splat textures dynamically. I first began by color painting. It works great ;
void EditableTerrain::ColorPaint(int x, int z, float intensity)
{
if(!m_paintBox)
return;
Ogre::Pass* splatPass = mTerrainMgr->getMaterial()->getTechnique(0)->getPass(0);
Ogre::TexturePtr tex = splatPass->getTextureUnitState(0)->_getTexturePtr();
HardwarePixelBufferSharedPtr buffer = tex->getBuffer();
float x_padding = m_paintBox->getWidth() * 0.5f;
float z_padding = m_paintBox->getHeight() * 0.5f;
int v1 = z - z_padding;
int v2 = z + z_padding;
int u1 = x - x_padding;
int u2 = x + x_padding;
u1 = u1 < 0 ? 0 : u1;
v1 = v1 < 0 ? 0 : v1;
Ogre::Image::Box wbox(u1, v1, u2, v2);
if(wbox.getWidth() == m_paintBox->getWidth() &&
wbox.getHeight() == m_paintBox->getHeight())
{
const Ogre::PixelBox& pbox = buffer->lock(wbox, Ogre::HardwareBuffer::HBL_DISCARD);
PixelUtil::bulkPixelConversion(*m_paintBox, pbox);
buffer->unlock();
}
}
void EditableTerrain::createEditBrush(Ogre::ColourValue& color, int width, int height)
{
ET::TerrainInfo info = mTerrainMgr->getTerrainInfo();
Ogre::Pass* splatPass = mTerrainMgr->getMaterial()->getTechnique(0)->getPass(0);
Ogre::TexturePtr tex = splatPass->getTextureUnitState(0)->_getTexturePtr();
HardwarePixelBufferSharedPtr buffer = tex->getBuffer();
Ogre::PixelFormat pf = tex->getSrcFormat();
Ogre::Image::Box box(0, 0, width, height);
if(m_paintBox)
{
delete m_paintBox->data;
delete m_paintBox;
}
m_paintBox = new PixelBox(box, pf);
m_paintBox->data = new uchar[ box.getWidth()* box.getHeight() * PixelUtil::getNumElemBytes(pf) ];
for (size_t j = box.left; j < box.right; j++)
for(size_t i = box.top; i < box.bottom; i++)
{
Ogre::Image::Box wbox(j, i, j, i);
PixelUtil::packColour(color, pf, m_paintBox->getSubVolume(wbox).data);
}
}
THis is also useful for showing navigation meshes, a* path debugging, blood splatting etc.
When it comes to texture splatting i fail for i only get a 8x8 greeny texture on the terrain ;
void EditableTerrain::paint(unsigned int textureNum, int x, int y, float intensity)
{
Ogre::Pass* splatPass = mTerrainMgr->getMaterial()->getTechnique(0)->getPass(0);
Ogre::TexturePtr tex = splatPass->getTextureUnitState(0)->_getTexturePtr();
HardwarePixelBufferSharedPtr buffer = tex->getBuffer();
Ogre::PixelFormat pf = tex->getSrcFormat();
size_t bytenum = PixelUtil::getNumElemBytes(pf);
float x_padding = mEditBrush.getWidth() * 0.5f;
float z_padding = mEditBrush.getHeight() * 0.5f;
int v1 = y - z_padding;
int v2 = y + z_padding;
int u1 = x - x_padding;
int u2 = x + x_padding;
u1 = u1 < 0 ? 0 : u1;
v1 = v1 < 0 ? 0 : v1;
Ogre::Image::Box wbox(u1, v1, u2, v2);
if(wbox.getWidth() == mEditBrush.getWidth() &&
wbox.getHeight() == mEditBrush.getHeight())
{
Ogre::PixelBox* pb = mSplatMgr->paint2(textureNum, m_textures, x, y, mEditBrush, intensity);
const Ogre::PixelBox& pbox = buffer->lock(wbox, Ogre::HardwareBuffer::HBL_DISCARD);
PixelUtil::bulkPixelConversion(*pb, pbox);
buffer->unlock();
delete pb->data;
delete pb;
}
}
and i made a small addon to ETM 2.3.1 -> paint2 function
Ogre::PixelBox* SplattingManager::paint2(unsigned int textureNum, Ogre::ImagePtrList textures, int x, int y, const Brush& brush,
float intensity)
{
Ogre::ColourValue val;
uint texture;
Ogre::Image* img;
ET::Impl::CoverageMap* cov_map;
paint(textureNum, x, y, brush, intensity, false);
img = textures[0];
Ogre::Image::Box box(0, 0, brush.getWidth(), brush.getHeight());
Ogre::PixelBox* writebox = new PixelBox(box, img->getFormat());
writebox->data = new uchar[brush.getWidth()* brush.getHeight() * 4];
for(Ogre::ImagePtrList::iterator ix = textures.begin(); ix != textures.end(); ix++)
{
img = *ix;
img->resize(128, 128);
}
for (size_t i = box.left; i < box.right; i++)
{
for (size_t j = box.top; j < box.bottom; j++)
{
val = ColourValue::ZERO;
texture = -1;
for(Ogre::ImagePtrList::iterator ix = textures.begin(); ix != textures.end(); ix++)
{
texture += 1;
img = *ix;
uint cov_map_ind = texture / mImpl->channels;
cov_map = mImpl->maps[cov_map_ind];
uint channel = texture % mImpl->channels;
Ogre::ColourValue imgcol = img->getColourAt((uint)(x+i), (uint)(y+j), 0);
float cov_val = (float) (cov_map->getValue((uint)(i), (uint)(j), channel) / 255);
Ogre::ColourValue final = imgcol * cov_val;
val += final;
}
Ogre::Image::Box wbox(j, i, j, i);
PixelUtil::packColour(val, img->getFormat(), writebox->getSubVolume(wbox).data);
}
}
return writebox;
}
Here i 'paint'. This adjusts the coverage maps. Then i tend to do whats in the shaders. The implementation is too straightforward.Does someone have any suggestions??