[Dynamic Shadow Map] support added at 90% !

hotgloupi

10-11-2007 11:31:06

Hi John, Hi all !

I worked two weeks to finally find a relatively good way to add support for loading color map from a dynamic shadow map.
First, is there someone interested by this?
Second, I need to improve "dynamic" feature by loading sometimes new color for trees (there is no really need for grass). Can you explain a strategy to use reloadGemetry(x,z) efficiently : just reload in view, reload n trees by frame...
Am I irritating?
bye !

JohnJ

10-11-2007 21:53:31

Hi (sorry I forgot to reply earlier!)

The reload strategy I plan to implement for dynamic reloading is simple: after calling some function to enable dynamic reloading, a unrefreshed page will be reloaded after a given interval. Preferably, closer pages will be given higher refresh priority, and there will also need to be a system to determine how long it's been since a page has been refreshed.

Also, I'm sure there's someone who would find your dynamic shadow map feature useful, including myself. I may not be able to now, but eventually I am planning to implement some sort of feature to do this in the "official" version, so looking at your code may be very helpful!

Am I irritating?
Certainly not :)

hotgloupi

10-11-2007 23:17:26

Ok!

I had think to do like that, I'll try to understand how know which trees are close to camera, and for frequency update, I think update() method can easily do that.

If you want to take a look at my modifications, don't be afraid about my dirty code, i'll reimplement it soon cleanly :)



Index: include/GrassLoader.h
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/include/GrassLoader.h,v
retrieving revision 1.19
diff -r1.19 GrassLoader.h
327a328,337
> /** \brief Sets the color map used for this grass layer
>
> Overloaded to accept a pointer to any data. See the original setColorMap() documentation above
> for more detailed information on color maps.
>
> \note The texture data you provide is NOT copied into RAM, so you must delete this data field after
> unload grasslayer.*/
> void setDynamicColorMap(Ogre::uchar* data, unsigned int width, unsigned int height, MapChannel channel = CHANNEL_ALPHA);
>
>

Index: include/PropertyMaps.h
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/include/PropertyMaps.h,v
retrieving revision 1.3
diff -r1.3 PropertyMaps.h
135a136
> static ColorMap *load(Ogre::uchar *data, unsigned int width, unsigned int height, MapChannel channel = CHANNEL_ALPHA);
221a223
> ColorMap(Ogre::uchar *data, unsigned int width, unsigned int height, MapChannel channel);
239a242,248
>
> //specific members for dynamic color map
> Ogre::uchar* dynamicData;
> bool isDynamic;
> unsigned int dynamicWidth;
> unsigned int dynamicHeight;
>
244c253
< #endif
\ No newline at end of file
---
> #endif

Index: source/GrassLoader.cpp
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/source/GrassLoader.cpp,v
retrieving revision 1.21
diff -r1.21 GrassLoader.cpp
630a620,631
> void GrassLayer::setDynamicColorMap(Ogre::uchar* data, unsigned int width, unsigned int height, MapChannel channel)
> {
> if (data){
> colorMap = ColorMap::load(data, width, height, channel);
> colorMap->setMapBounds(mapBounds);
> colorMap->setFilter(colorMapFilter);
> } else {
> colorMap->unload();
> colorMap = NULL;
> }
> }
>
Index: source/PropertyMaps.cpp
===================================================================
RCS file: /cvsroot/ogre/ogreaddons/forests/source/PropertyMaps.cpp,v
retrieving revision 1.4
diff -r1.4 PropertyMaps.cpp
214a215,219
> ColorMap *ColorMap::load(Ogre::uchar* data, unsigned int width, unsigned int height, MapChannel channel)
> {
> return new ColorMap(data, width, height, channel);
> }
>
235a241
> isDynamic = false;
302a309,321
> ColorMap::ColorMap(Ogre::uchar *data, unsigned int width, unsigned int height, MapChannel channel)
> {
> if (!(data && channel == CHANNEL_ALPHA))
> OGRE_EXCEPT(0, "Bad Color map channel for colorMap or empty pointer", "GrassLayer::setColorMap()");
> filter = MAPFILTER_BILINEAR;
>
> refCount = 0;
> isDynamic = true;
> dynamicWidth = width;
> dynamicHeight = height;
> dynamicData = data;
> }
>
306c325,337
< assert(pixels);
---
> unsigned int mapWidth, mapHeight;
> if (!isDynamic)
> {
> assert(pixels);
>
> mapWidth = (unsigned int)pixels->getWidth();
> mapHeight = (unsigned int)pixels->getHeight();
> }
> else
> {
> mapWidth = dynamicWidth;
> mapHeight = dynamicHeight;
> }
308,309d338
< unsigned int mapWidth = (unsigned int)pixels->getWidth();
< unsigned int mapHeight = (unsigned int)pixels->getHeight();
317,319c346,355
<
< uint32 *data = (uint32*)pixels->data;
< return data[mapWidth * zindex + xindex];
---
> if (!isDynamic)
> {
> uint32 *data = (uint32*)pixels->data;
> return data[mapWidth * zindex + xindex];
> }
> else
> {
> uint8 c = dynamicData[mapWidth * zindex + xindex];
> return (uint32) c | (c << 8) | (c << 16) | (c << 24);
> }
321a358,364
> #define INTERPOLATE_CHANNEL(c1, c2, ratio, ratioInv) ((uint8)(((float)c1) * ratioInv + ((float)c2) * ratio))
>
> // MACRO TO CONVERT 4 uint8 channels to uint32 color
> #define CONVERT32(a, b, c, d) (a | (b << 8) | (c << 16) | (d << 24))
>
> #define CONVERT32_FROM_ONE(a) CONVERT32(a,a,a,a)
>
337,340c380,383
< a = ratioInv * a1 + ratio * a2;
< b = ratioInv * b1 + ratio * b2;
< c = ratioInv * c1 + ratio * c2;
< d = ratioInv * d1 + ratio * d2;
---
> a = INTERPOLATE_CHANNEL(a1, a2, ratio, ratioInv);
> b = INTERPOLATE_CHANNEL(b1, b2, ratio, ratioInv);
> c = INTERPOLATE_CHANNEL(c1, c2, ratio, ratioInv);
> d = INTERPOLATE_CHANNEL(d1, d2, ratio, ratioInv);
342c385
< uint32 clr = a | (b << 8) | (c << 16) | (d << 24);
---
> uint32 clr = CONVERT32(a,b,c,d);
348c391,403
< assert(pixels);
---
> unsigned int mapWidth, mapHeight;
> if (!isDynamic)
> {
> assert(pixels);
>
> mapWidth = (unsigned int)pixels->getWidth();
> mapHeight = (unsigned int)pixels->getHeight();
> }
> else
> {
> mapWidth = dynamicWidth;
> mapHeight = dynamicHeight;
> }
350,351d404
< unsigned int mapWidth = (unsigned int)pixels->getWidth();
< unsigned int mapHeight = (unsigned int)pixels->getHeight();
367,374c420,442
<
< uint32 *data = (uint32*)pixels->data;
<
< uint32 val11 = data[mapWidth * zIndex + xIndex];
< uint32 val21 = data[mapWidth * zIndex + xIndex + 1];
< uint32 val12 = data[mapWidth * ++zIndex + xIndex];
< uint32 val22 = data[mapWidth * zIndex + xIndex + 1];
<
---
> uint32 val11, val21, val12, val22;
> if (!isDynamic)
> {
> uint32 *data = (uint32*)pixels->data;
>
> val11 = data[mapWidth * zIndex + xIndex];
> val21 = data[mapWidth * zIndex + xIndex + 1];
> val12 = data[mapWidth * ++zIndex + xIndex];
> val22 = data[mapWidth * zIndex + xIndex + 1];
> }
> else
> {
> uint8 c11 = dynamicData[mapWidth * zIndex + xIndex];
> uint8 c21 = dynamicData[mapWidth * zIndex + xIndex + 1];
> uint8 c12 = dynamicData[mapWidth * ++zIndex + xIndex] ;
> uint8 c22 = dynamicData[mapWidth * zIndex + xIndex + 1] ;
>
> uint8 v1 = INTERPOLATE_CHANNEL(c11, c21, xRatio, xRatioInv);
> uint8 v2 = INTERPOLATE_CHANNEL(c12, c22, xRatio, xRatioInv);
>
> return CONVERT32_FROM_ONE(INTERPOLATE_CHANNEL(v1, v2, zRatio, zRatioInv));
> }
>
379d446
<

hotgloupi

30-11-2007 22:22:51

After changes done before, paged geometry can update color of meshes with the color map, and if the color map change, you must to say it to paged geomtry !

A first (and naive) way work efficiently according to the fact that you don't change your lightmap every time, i mean every frame. I upload mine every minute, so since my game have about 50 fps, i have 50*60*60 = 180,000 frames to do the work !
if you have N meshes, you need to update N / 180,000 meshes per frame.
So, the rest is very easy:
static MeshRef* currentMesh;
if (mUpdateNeeded) {
if (!mUpdateInProcess) {
mPagedMeshIterator3D = new PagedMeshIterator3D(mPagedMeshLoader3D);
mUpdateInProcess = true;
}
for (int i=0 ; i<mNbUpdatedMeshPerFrame ; i++) {
if (mPagedMeshIterator3D->hasMoreElements()) {
currentMesh = mPagedMeshIterator3D->peekNextPtr();
mPagedMeshGeometry->reloadGeometryPage(currentMesh->getPosition());
mPagedMeshIterator3D->moveNext();
}
else {
mUpdateInProcess = false;
mUpdateNeeded = false;
delete mPagedMeshIterator3D;
}
}
}


I used typedef to change names of TreeLoaderXD and TreeIteratorXD to respectively PagedMeshLoaderXD and PagedMeshIteratorXD, because I won't load only trees ...
Don't forgot to call PagedGeometry::update() AFTER this code, else you'll encounter some flickering.
that's all, i'll try asap to reload efficiently grass, and i'll be authorized to set post's title to "support totally added :D"
bye seen you soon for an other chapter !

Vectrex

01-12-2007 06:06:27

when you say shadowmap do you mean lightmap? Because with realtime shadowmaps in shaders wouldn't the trees and grass be shadowed properly anyway?

hotgloupi

01-12-2007 06:08:14

Yes I mean lightmap come from PLSM2, and used by pagedGeometry as color map.