Heat haze

Сделал эффект “искажения пространства”, похожий на марево от жары – думаю применить его где-нибудь в игре:

Новые скриншоты

Несколько свежих скринов со всеми эффектами, которые используются в Atrium (bump/parallax mapping + glow + тени):

Эффект затенения

«Честные» динамические тени в аркадных 3D-играх не всегда бывают уместны. Как правило, разработчики ограничиваются статическими предрассчитанными тенями от неподвижных объектов и простым темным кружочком на земле под персонажем – дешево и сердито =) 
Я решил дополнить этот нехитрый метод одной простой, но важной деталью: изменение яркости персонажа в зависимости от его местоположения – в тени или на свету. 

Цвет для яркости будет считываться из карты освещения, в которой «запечены» все статические тени на карте.

Допустим, у вас есть некий блок кода, в котором вы находите точку на поверхности полигона под ногами персонажа:

// Проверяем факт пересечения
IntrStatus istatus = character.downRay.intersectTriangle(tri);
if (istatus.hit)
{
// Извлекаем точку пересечения
Vector3f ipt = istatus.intersectionPoint;

if (ipt.y > currentFloorHeight)
{
currentFloorHeight = ipt.y;

// Берем материал полигона
Material mat = materialByIndex[tri.matIndex];

// Если нет карты освещения (текстура 1), то ничего не делаем
if (mat.textures[1])
{
// Берем изображение карты освещения
Image lightmap = imageByIndex[mat.textures[1].imgIndex];

// Находим текстурные координаты точки пересечения
Vector2f tc = triObjSpaceToTexSpace(tri.vertices, tri.texCoords2, ipt);

// Конвертируем текстурные координаты в дискретные
uint imgX = cast(uint)(tc.x * lightmap.width - 0.5f);
uint imgY = cast(uint)(tc.y * lightmap.height - 0.5f);

// Считываем цвет пикселя c карты освещения
Color lumel = lightmap[imgX, imgY];

// Применяем полученный цвет к материалу персонажа
chMaterial.ambientColor = lumel;
chMaterial.diffuseColor = lumel;
chMaterial.specularColor = lumel;
}
}
}

Осталось определить функцию triObjSpaceToTexSpace. Она будет использовать барицентрические координаты:

Vector2f triObjSpaceToTexSpace(
Vector3f[3] vertices,
Vector2f[3] texCoords,
Vector3f point)
{
Vector3f v0 = vertices[2] - vertices[0];
Vector3f v1 = vertices[1] - vertices[0];
Vector3f v2 = point - vertices[0];

float dot00 = dot(v0, v0);
float dot01 = dot(v0, v1);
float dot02 = dot(v0, v2);
float dot11 = dot(v1, v1);
float dot12 = dot(v1, v2);

float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;

Vector2f t2 = texCoords[1] - texCoords[0];
Vector2f t1 = texCoords[2] - texCoords[0];

return texCoords[0] + t1 * u + t2 * v;
}