A simple method for generating lightmap and minimap of tianlong Babu using ogre

Source: Internet
Author: User

Since I became a client master in a startup company, I have no time to write a blog. No one in the company has full project experience and is always exploring, however, the project is still running smoothly because the first child is not afraid of tigers. However, I always think it is necessary to calm down and summarize my work experience. Unfortunately, I am afraid I will wait until this project is finished.

It's a little time on weekends, so you can take the time to write anything.

The importance of lightmap is needless to say. There is no need to dynamically render all shadows. Just paste a lightmap of static objects that will not be moved for a lifetime. Unfortunately, ogre only provides dynamic shadows for us, it cannot help people.

How to generate lightmap like tianlong Babu? If you go to Baidu, they will tell you various methods, such as ray tracing, shader, etc.

All of the above tells you to create a shadow by yourself. However, ogre has helped us generate a dynamic shadow, so we do not have to generate a shadow by ourselves,

You only need to use the dynamic shadow to render a static shadow, and save it.

So how can we use the dynamic shadow of ogre to generate a static shadow image?

1) First, learn to render a thumbnail of A minimap. You should see the thumbnail. Create a camera with a vertical view, and take a parallel projection.

2) Improved minimap to render only the terrain queue in the vertical view of the camera's viewport. Do not render other queues

In this way, the minimap is only effective after the shadow and terrain texture are mixed.

Ogre: renderqueueinvocationsequence * rqis =
Ogre: Root: getsingleton (). createrenderqueueinvocationsequence ("lightmap maker ");
Ogre: renderqueueinvocation * rqi =
Rqis-> Add (Ogre: render_queue_world_geometry_1, "world geometry ");
Viewport-> setrenderqueueinvocationsequencename ("lightmap maker ");

3) make another improvement. Set the terrain material to basewhite and full White. Then, the minimap becomes a lightmap.

4) the shadow of ogre is not easy to use, so you need to optimize it, or use shader to implement it and write it later.

//////// This is a dynamic shadow image ,,,,,,,,,,,,,,,,,,,,,,,,,,

 

//////////////////////////

//// // This is the image with lightmap attached.

 

.

. //// // This is the shadow ,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

Attach the code and look at the ideas!

View plaincopy to clipboardprint?
··· · 50 ······· · 90 ····· · 140 · 150
/*
@ Filename wxlightmapmaker. h
@ Creator luoyinan
@ Data 2010.6.14
@ Remarks create a scene illumination Map
*/
# Ifndef _ wx_lightmap_maker_h __
# DEFINE _ wx_lightmap_maker_h __

# Include "scenemanipulator. H"

Namespace WX
{
Class lightmapmaker
{
Public:
Lightmapmaker (scenemanipulator * Manipulator );
~ Lightmapmaker (void );

// Initialization, including creating render texture and camera
Void initial (void );
// Destroy render texture
Void destroy (void );

// Save the illumination map to a file
// The format "emei.lightmap.png" also supports full paths, such as.../../data/scene/emei.lightmap.png"
Void outputtexture (const ogre: string & filename );

Protected:

Scenemanipulator * mscenemanipulator;
Ogre: rendertexture * mrendertexture;

};
}
# Endif
/*
@ Filename wxlightmapmaker. h
@ Creator luoyinan
@ Data 2010.6.14
@ Remarks create a scene illumination Map
*/
# Ifndef _ wx_lightmap_maker_h __
# DEFINE _ wx_lightmap_maker_h __

# Include "scenemanipulator. H"

Namespace WX
{
Class lightmapmaker
{
Public:
Lightmapmaker (scenemanipulator * Manipulator );
~ Lightmapmaker (void );

// Initialization, including creating render texture and camera
Void initial (void );
// Destroy render texture
Void destroy (void );

// Save the illumination map to a file
// The format "emei.lightmap.png" also supports full paths, such as.../../data/scene/emei.lightmap.png"
Void outputtexture (const ogre: string & filename );

Protected:

Scenemanipulator * mscenemanipulator;
Ogre: rendertexture * mrendertexture;

};
}
# Endif view plaincopy to clipboardprint?
··· · 50 ······· · 90 ····· · 140 · 150
# Include "wxlightmapmaker. H"

# Include "gamescene/terraindata. H"
# Include "gamescene/wxscene. H"
# Include "gamescene/wxsceneinfo. H"
# Include "gamescene/wxstaticentityobject. H"
# Include "gamescene/wxmodelobject. H"
Namespace WX
{
//----------------------------------------------------------------------------------
Lightmapmaker: lightmapmaker (scenemanipulator * Manipulator)
: Mscenemanipulator (Manipulator)
, Mrendertexture (0)
{

}

//--------------------------------------------------------------------------------
Lightmapmaker ::~ Lightmapmaker (void)
{

}

//--------------------------------------------------------------------------------
Void lightmapmaker: initial (void)
{
// Make sure the terrain has been loaded
Terraindata * Data = mscenemanipulator-> getterraindata ();
Assert (Data & "terraindata * = NULL ");

// Create a lightmap camera to vertically overlook the entire map
Ogre: scenemanager * mscenemanager = mscenemanipulator-> getscenemanager ();
// If (mscenemanipulator-> getterraindata ()-> mlightmapimage = NULL)
{
Static const string mslightmapmaker ("lightmap maker ");
Ogre: Camera * camera = 0;
Try
{
Camera = mscenemanager-> getcamera (mslightmapmaker );
}
Catch (const ogre: exception & E)
{
// Only an exception is prompted and the program is not exited.
If (E. getnumber () = E. err_item_not_found)
{
// MessageBox (null, E. What (), "an exception has occured! ", Mb_ OK | mb_iconerror | mb_taskmodal );
}
Else
{
Throw;
}

}
If (! Camera)
{
Camera = mscenemanager-> createcamera (mslightmapmaker );
Camera-> setautoaspectratio (true );
Camera-> setprojectiontype (Ogre: pt_orthographic); // parallel projection
// In ogre1.6, the parallel projection size is changed to setorthow.wwidth and setorthow.wheight,
// Instead of the FOV and subsection used in the previous version, so...
Camera-> setfovy (Ogre: Degree (90 ));
Camera-> setorthow.wwidth (mscenemanipulator-> getterraindata ()-> getxsize () * mscenemanipulator-> getbasescale ());
Camera-> setorthow.wheight (mscenemanipulator-> getterraindata ()-> getzsize () * mscenemanipulator-> getbasescale ());

Ogre: quaternion orientation;
Orientation. fromaxes (Ogre: vector3: unit_x, ogre: vector3: negative_unit_z, ogre: vector3: unit_y );
Camera-> setorientation (orientation );
}

// Calculate the box of all objects to determine the camera parameters.
Ogre: axisalignedbox AABB;
Ogre: scenemanager: movableobjectiterator ITM =
Mscenemanager-> getmovableobjectiterator (Ogre: entityfactory: factory_type_name );
While (ITM. hasmoreelements ())
{
Ogre: movableobject * movable = ITM. getnext ();
AABB. Merge (movable-> getworldboundingbox (true ));
}
Camera-> setnearclipdistance (32 * mscenemanipulator-> getbasescale ()/2 );
Camera-> setfarclipdistance (camera-> getnearclipdistance () + AABB. getmaximum (). Y-AABB. getminimum (). y );
Camera-> setposition (0, camera-> getnearclipdistance () + AABB. getmaximum (). Y, 0 );

// Adjust the shadow Parameter
Ogre: real distance = camera-> getnearclipdistance () * ogre: Math: SQRT (1 + ogre: Math: sqr (camera-> getaspectratio ()));
Mscenemanager-> setshadowfardistance (distance );
Ogre: Real camheight = camera-> getposition (). Y;
Mscenemanager-> setshadowdirlighttextureoffset (camheight/distance );


// Create the RTT texture of lightmap, which is 8 times the terrain size, just like tianlong.
Ogre: textureptr ptexture = (Ogre: textureptr) Ogre: texturemanager: getsingleton (). getbyname ("lightmaprtttex ");
If (ptexture. isnull ())
{
Size_t width = data-> getxsize () * 8;
Size_t Height = data-> getzsize () * 8;
Ptexture = ogre: texturemanager: getsingleton (). createmanual (
"Lightmaprtttex", ogre: resourcegroupmanager: default_resource_group_name,
Ogre: tex_type_2d,
Width, height, 1, 0, ogre: pf_byte_rgb,
Ogre: tu_rendertarget, 0 );
}
Ogre: hardwarepixelbuffersharedptr pbuffer = ptexture-> getbuffer (0, 0 );
Mrendertexture = pbuffer-> getrendertarget (0 );

// Create a lightmap View
Ogre: viewport * viewport = mrendertexture-> addviewport (mscenemanipulator-> getscenemanager ()-> getcamera ("lightmap maker "));
Viewport-> setoverlaysenabled (false );
Viewport-> setskiesenabled (false );
Viewport-> setshadowsenabled (true );
// Customize a rendering queue call group and only render the terrain queue. This is the key. We only need the shadow and do not need any other.
// If you have rendered all of them, it will become mini map and thumbnail.
Ogre: renderqueueinvocationsequence * rqis =
Ogre: Root: getsingleton (). createrenderqueueinvocationsequence ("lightmap maker ");
Ogre: renderqueueinvocation * rqi =
Rqis-> Add (Ogre: render_queue_world_geometry_1, "world geometry ");
Viewport-> setrenderqueueinvocationsequencename ("lightmap maker ");
}

}
//--------------------------------------------------------------------------------
Void lightmapmaker: Destroy (void)
{
If (mrendertexture)
{
Mscenemanipulator-> getscenemanager ()-> destroycamera ("lightmap maker ");

Mrendertexture-> removeallviewports ();

Ogre: texturemanager: getsingleton (). Remove ("lightmaprtttex ");

Mrendertexture = NULL;
}
}

//--------------------------------------------------------------------------------
Void lightmapmaker: outputtexture (const ogre: string & filename)
{
// Skip this step if lightmap already exists.
If (mscenemanipulator-> getterraindata ()-> mlightmapimage)
{
// Do you need a prompt?
Return;
}

// Let all static objects cast shadows to make lightmap
Scene: objectsbytyperange objests = mscenemanipulator-> getsceneinfo ()-> findobjectsbytype (staticentityobject: mstype );
For (Scene: objectsbytypeiterator it = objests. First; it! = Objests. Second; ++ it)
{
Objectptr object = (* it );
Object-> setpropertyasstring ("cast shadows", "true ");
// Object-> setpropertyasstring ("receive shadows", "true ");
}
Objests = mscenemanipulator-> getsceneinfo ()-> findobjectsbytype (modelobject: mstype );
For (Scene: objectsbytypeiterator it = objests. First; it! = Objests. Second; ++ it)
{
Objectptr object = (* it );
Object-> setpropertyasstring ("cast shadows", "true ");
// Object-> setpropertyasstring ("receive shadows", "true ");
}

// Use basewhite to replace the original terrain material and reconstruct the terrain
Terraindata: materialtemplates & Materials = mscenemanipulator-> getterraindata ()-> mmaterialtemplates;
Terraindata: materialtemplates materialscopy (materials );
Materials ["onelayer"] = "basewhite ";
Materials ["onelayerlightmap"] = "basewhite ";
Materials ["twolayer"] = "basewhite ";
Materials ["twolayerlightmap"] = "basewhite ";
Mscenemanipulator-> getterrain ()-> buildgeometry (mscenemanipulator-> getbasescenenode (), true );

// Update
// Mscenemanipulator-> getscenemanager ()-> _ updatescenegraph (mscenemanipulator-> getscenemanager ()-> getcamera ("lightmap maker "));
Mrendertexture-> Update ();

// Save lightmap to a file
Ogre: String lightmapfilename (filename );
String basename, path, outextention;
If (filename. Empty ())
{
Wx: terraindata * Data = mscenemanipulator-> getterraindata ();
Ogre: stringutil: splitbasefilename (data-> mheightmapfilename, basename, outextention );
Lightmapfilename = basename + ".lightmap.png ";
}
Mrendertexture-> writecontentstofile (lightmapfilename );

// Load lightmap
Static const string temp_group_name = "# temp #"; // temporary Resource Group
Ogre: stringutil: splitfilename (lightmapfilename, basename, PATH );
Mscenemanipulator-> getterraindata ()-> mlightmapfilename = basename;
Ogre: resourcegroupmanager & RGM = ogre: resourcegroupmanager: getsingleton ();
RGM. addresourcelocation (path, "filesystem", temp_group_name, false );
// This function is originally protected. We 'd better re-load the entire terrain in the future, instead of loading lightmap separately.
Mscenemanipulator-> getterraindata ()-> _ loadlightmap (basename, "image", temp_group_name );

// Replace the original terrain material and reconstruct the terrain
STD: swap (materials, materialscopy );
Mscenemanipulator-> getterrain ()-> buildgeometry (mscenemanipulator-> getbasescenenode (), true );

// All static objects no longer need to cast shadows, because we have lightmap
Objests = mscenemanipulator-> getsceneinfo ()-> findobjectsbytype (staticentityobject: mstype );
For (Scene: objectsbytypeiterator it = objests. First; it! = Objests. Second; ++ it)
{
Objectptr object = (* it );
Object-> setpropertyasstring ("cast shadows", "false ");
// Object-> setpropertyasstring ("receive shadows", "true ");
}
Objests = mscenemanipulator-> getsceneinfo ()-> findobjectsbytype (modelobject: mstype );
For (Scene: objectsbytypeiterator it = objests. First; it! = Objests. Second; ++ it)
{
Objectptr object = (* it );
Object-> setpropertyasstring ("cast shadows", "false ");
// Object-> setpropertyasstring ("receive shadows", "true ");
}

// Destroy a temporary Resource Group
RGM. destroyresourcegroup (temp_group_name );
}


}

Original article, reprinted please note, thank you!

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/qq18052887/archive/2010/08/15/5812611.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.