• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
  • entries
    31
  • comments
    43
  • views
    61038

ShaderMap 2 SDK Tutorial - Creating Maps

Sign in to follow this  
Followers 0
RSI

2058 views

Each map in ShaderMap 2 is a plugin. The plugin is a Windows DLL with the file extension .smp. To create a map plugin you will need to download the ShaderMap 2 SDK. http://shadermap.com/downloads/ As of this tutorial I am using version 2.0.5. You will also need Visual Studio 2008 - 2010.

Once you have the SDK downloaded and unzipped navigate to the folder 'map'. Inside you will see the VS solution file called map.sln. This solution contains 3 project files. Each project builds an example map. The 3 maps demonstrate how to build:

- source maps
- maps with no inputs
- maps with inputs

For the purpose of this tutorial I will be focusing on the third project. Right click on the project 'example_3' and set it as the default project. Open the source file 'example_3.cpp' so you can follow along.

Each map plugin uses the file 'map_plugin_core.cpp' which contains all API functions for interacting with ShaderMap 2. It is included at the top of each plugin file.

Each map plugin must implement 4 functions that are prototyped in the 'map_plugin_core.cpp' file. They are:

[source]
// Initialize plugin - Called when the plugin is loaded.
// This tells ShaderMap about the plugin and sets up the plugin property controls
BOOL on_initialize(void);

// Process plugin - called each time the map needs to be regenerated - the map_id is used to gain access to the map property values.
BOOL on_process(unsigned int map_id);

// Called just before the plugin is unloaded when ShaderMap is shutdown.
// If global resources are used this is the place to release them.
BOOL on_shutdown(void);

// Called when a project is loaded - It sends the version of the plugin with which the project was saved.
// The values are arranged in the order 0,1,2,...property index.
// If the order of the property controls have changed since the version parameter then modify the index array accordingly.
void on_arrange_load_data(unsigned int version, unsigned int index_count, unsigned int* index_array);[/source]

Here is the on_initialize function:
[source]// Initialize plugin - This tells ShaderMap about the plugin and sets up the plugin property controls
// Is called when the plugin is loaded by ShaderMap
BOOL on_initialize(void)
{
// Tell ShaderMap we are starting initialize
mp_begin_initialize();

// Set version - useful for tracking property changes
// from version to version. See on_arrange_load_data()
mp_set_version(101);

// Tell ShaderMap this map plugin is type MAP
mp_set_map_type(MAP_PLUGIN_TYPE_MAP);

// Set name and description
mp_set_name(_T("Example 3 Map"));
mp_set_description(_T("An example of normal map plugin with 1 input."));

// Set the thumbnail filename. This image must be located in "APP_DIRECTORY\plugins\(x86|x64)\maps\thumbs"
// See examples of thumbnails in that folder.
// Thumbnail must be 128 x 128 pixels but thumb is much smaller at 71 x 71 and offset from top-left by 12 pixels
mp_set_thumbnail(_T("example_3.png"));

// Set default save format for the map
mp_set_default_format(MAP_FORMAT_TGA_RGB_8);

// Is a normal map
mp_enable_normal_map(TRUE);

// Add 1 input
mp_add_input(_T("Normal Map"), _T("An image with normal vectors stored per pixel."));

// Add properties controls Property Index
// Add a coodinate system property with a default coordinate system set
mp_add_property_coordsys(_T("Coord System"), MAP_COORDSYS_X_POS_RIGHT | MAP_COORDSYS_Y_POS_DOWN | MAP_COORDSYS_Z_POS_NEAR, 0); // 0

// Tell ShaderMap initialize was success - map is added
mp_end_initialize();

// Success
return TRUE;
}[/source]

The first and last API calls are mp_begin_initialize(); and mp_end_initialize(); Everything else is between those two functions.

Here we setup the version integer, the map type (source or map), the name and description, the thumbnail filename, default file save format, if the map is a normal map or not (if so then will require a coordinate system to be set), map inputs with a description, and property controls associated with the map.

Here we have set up a map that is a normal map and takes a single normal map as input. It has one property control which is a coordinate system control. In essence this map allows the user to transform the normals of the input map to a new coordinate system. But you could make it do anything (randomize normals, etc).

The on_process function is shown below:

[source]// Process plugin - called each time the map needs to be regenerated
BOOL on_process(unsigned int map_id)
{
// Local data
unsigned int thread_limit, width, height, origin, tile_type, image_type, input_coord_system, user_coord_system, i, count_i;
float x, y, z;

const unsigned char* input_pixel_array_8;
const unsigned short* input_pixel_array_16;

unsigned char* map_pixel_d_array_8;
unsigned short* map_pixel_d_array_16;


// Get suggested thread limit for plugin process - not used in this example
thread_limit = mp_get_map_thread_limit();

// -----------------

// Get size of input
width = (int)mp_get_input_width(map_id, 0);
height = (int)mp_get_input_height(map_id, 0);
if(!width || !height)
{
LOG_ERROR_MSG(map_id, _T("Invalid input size. Width or height is zero."));
return FALSE;
}
// Get origin of input
origin = mp_get_input_origin(map_id, 0);

// Get tile type of input
tile_type = mp_get_input_tile_type(map_id, 0);

// Get image type of input
image_type = mp_get_input_image_type(map_id, 0);

// As the input is a normal map - we must get its coordinate system
input_coord_system = mp_get_input_coordsys(map_id, 0);

// -----------------

// Tell ShaderMap the tile type of this map so children of this map inherit the tile type
switch(tile_type)
{
case 0:
mp_set_map_tile_type(map_id, MAP_TILE_NONE);
break;
case 1:
mp_set_map_tile_type(map_id, MAP_TILE_X);
break;
case 2:
mp_set_map_tile_type(map_id, MAP_TILE_Y);
break;
case 3:
mp_set_map_tile_type(map_id, MAP_TILE_XY);
break;
}

// -----------------

// Allocate map pixels and get pointer to input pixel array
// 8 bit
if(image_type == MAP_IMAGE_TYPE_8)
{
// Allocate 8 bit map pixels
map_pixel_d_array_8 = new (std::nothrow) unsigned char[width * height * 4];
if(!map_pixel_d_array_8)
{
LOG_ERROR_MSG(map_id, _T("Failed to allocate map pixels."));
return FALSE;
}

// Get pixel array of input 0
input_pixel_array_8 = (const unsigned char*)mp_get_input_pixel_array(map_id, 0);
}
// 16 bit
else
{
// Allocate 16 bit map pixels
map_pixel_d_array_16 = new (std::nothrow) unsigned short[width * height * 4];
if(!map_pixel_d_array_16)
{
LOG_ERROR_MSG(map_id, _T("Failed to allocate map pixels."));
return FALSE;
}

// Get pixel array of input 0
input_pixel_array_16 = (const unsigned short*)mp_get_input_pixel_array(map_id, 0);
}

// -----------------

// Get property values
user_coord_system = mp_get_property_coordsys(map_id, 0);

// -----------------

// Set the map coordsys as defined by the user
mp_set_map_coordsys(map_id, user_coord_system);

// Get number of items in the pixel arrays
count_i = width * height * 4;

// 8 bit
if(image_type == MAP_IMAGE_TYPE_8)
{
// For every pixel
for(i=0; i {
// Convert input pixel to normal
x = 2.0f * ((float)input_pixel_array_8 / 255.0f) - 1.0f;
y = 2.0f * ((float)input_pixel_array_8[i+1] / 255.0f) - 1.0f;
z = 2.0f * ((float)input_pixel_array_8[i+2] / 255.0f) - 1.0f;

// Normalize vector
normalize_vector(x, y, z);

// Compare input coordsys with user coordsys and flip values as needed
// Adjust X
if((input_coord_system & MAP_COORDSYS_X_POS_RIGHT) != (user_coord_system & MAP_COORDSYS_X_POS_RIGHT))
{ x = -x;
}
// Adjust Y
if((input_coord_system & MAP_COORDSYS_Y_POS_DOWN) != (user_coord_system & MAP_COORDSYS_Y_POS_DOWN))
{ y = -y;
}
// Adjust Z
if((input_coord_system & MAP_COORDSYS_Z_POS_NEAR) != (user_coord_system & MAP_COORDSYS_Z_POS_NEAR))
{ z = -z;
}

// Store normal as color in the map pixel array
map_pixel_d_array_8 = (unsigned char)((x + 1.0f) / 2.0f * 255.0f);
map_pixel_d_array_8[i+1] = (unsigned char)((y + 1.0f) / 2.0f * 255.0f);
map_pixel_d_array_8[i+2] = (unsigned char)((z + 1.0f) / 2.0f * 255.0f);
map_pixel_d_array_8[i+3] = input_pixel_array_8[i+3];

// Check for cancel
if(mp_is_cancel_process())
{ delete [] map_pixel_d_array_8;
return FALSE;
}
}
}
// 16 bit
else
{
// For every pixel
for(i=0; i {
// Convert input pixel to normal
x = 2.0f * ((float)input_pixel_array_16 / 65535.0f) - 1.0f;
y = 2.0f * ((float)input_pixel_array_16[i+1] / 65535.0f) - 1.0f;
z = 2.0f * ((float)input_pixel_array_16[i+2] / 65535.0f) - 1.0f;

// Normalize vector
normalize_vector(x, y, z);

// Compare user coordsys and flip values as needed
// Adjust X
if((input_coord_system & MAP_COORDSYS_X_POS_RIGHT) != (user_coord_system & MAP_COORDSYS_X_POS_RIGHT))
{ x = -x;
}
// Adjust Y
if((input_coord_system & MAP_COORDSYS_Y_POS_DOWN) != (user_coord_system & MAP_COORDSYS_Y_POS_DOWN))
{ y = -y;
}
// Adjust Z
if((input_coord_system & MAP_COORDSYS_Z_POS_NEAR) != (user_coord_system & MAP_COORDSYS_Z_POS_NEAR))
{ z = -z;
}

// Store normal as color in the map pixel array
map_pixel_d_array_16 = (unsigned short)((x + 1.0f) / 2.0f * 65535.0f);
map_pixel_d_array_16[i+1] = (unsigned short)((y + 1.0f) / 2.0f * 65535.0f);
map_pixel_d_array_16[i+2] = (unsigned short)((z + 1.0f) / 2.0f * 65535.0f);
map_pixel_d_array_16[i+3] = input_pixel_array_16[i+3];

// Check for cancel
if(mp_is_cancel_process())
{ delete [] map_pixel_d_array_8;
return FALSE;
}
}
}

// -----------------

// Create the final map using the map pixels
// 8 bit
if(image_type == MAP_IMAGE_TYPE_8)
{
if(!mp_create_map(map_id, width, height, origin, image_type, map_pixel_d_array_8))
{
LOG_ERROR_MSG(map_id, _T("Failed to create map with mp_create_map()."));
delete [] map_pixel_d_array_8;
return FALSE;
}

// Cleanup
delete [] map_pixel_d_array_8;
map_pixel_d_array_8 = 0;
}
// 16 bit
else
{
if(!mp_create_map(map_id, width, height, origin, image_type, map_pixel_d_array_16))
{
LOG_ERROR_MSG(map_id, _T("Failed to create map with mp_create_map()."));
delete [] map_pixel_d_array_16;
return FALSE;
}

// Cleanup
delete [] map_pixel_d_array_16;
map_pixel_d_array_16 = 0;
}

// Update map progress 100%
mp_set_map_progress(map_id, 100);

// Success
return TRUE;
}[/source]

The first part of the function uses API calls to get info about the input map and the property values, The next registers the tile type of the map. A pixel array is allocated based on 8 bit or 16 bit channels at the same size as the input map. The coordinate system is registered as the one the user has defined in the coordinate system property control. Depending on the image type the pixels (normals) are copied into the new pixel array and set to the new coordinate system.

At the end of the function the pixels are sent to ShaderMap using the mp_create_map() function. Which takes the map_id, size, and array of pixels in RGBA format.

To install this plugin, add the binary *.SMP file to the ShaderMap plugins directory: "SM2_DIRECTORY\plugins\(x86 or x64)\maps\"

and install the plugin thumbnail to the directory: "SM2_DIRECTORY\plugins\(x86 or x64)\maps\thumbs\"

Now the map will be available from the Advanced Map Setup page inside ShaderMap 2.

0
Sign in to follow this  
Followers 0


0 Comments


There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now