mirror of
https://github.com/luanti-org/luanti.git
synced 2025-10-27 22:05:17 +01:00
Move crack overlay to shader
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
uniform sampler2D baseTexture;
|
uniform sampler2D baseTexture;
|
||||||
|
#define crackTexture texture1
|
||||||
|
uniform sampler2D crackTexture;
|
||||||
|
|
||||||
uniform vec3 dayLight;
|
uniform vec3 dayLight;
|
||||||
uniform lowp vec4 fogColor;
|
uniform lowp vec4 fogColor;
|
||||||
@@ -9,6 +11,10 @@ uniform float fogShadingParameter;
|
|||||||
uniform highp vec3 cameraOffset;
|
uniform highp vec3 cameraOffset;
|
||||||
uniform vec3 cameraPosition;
|
uniform vec3 cameraPosition;
|
||||||
uniform float animationTimer;
|
uniform float animationTimer;
|
||||||
|
uniform float crackAnimationLength;
|
||||||
|
uniform float crackLevel;
|
||||||
|
uniform float crackTextureScale;
|
||||||
|
|
||||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||||
// shadow texture
|
// shadow texture
|
||||||
uniform sampler2D ShadowMapSampler;
|
uniform sampler2D ShadowMapSampler;
|
||||||
@@ -411,9 +417,18 @@ float getShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// maps [0, N] to [0, 1] like GL_REPEAT would
|
||||||
|
vec2 uv_repeat(vec2 v)
|
||||||
|
{
|
||||||
|
if (v.x > 1.0)
|
||||||
|
v.x = fract(v.x);
|
||||||
|
if (v.y > 1.0)
|
||||||
|
v.y = fract(v.y);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec3 color;
|
|
||||||
vec2 uv = varTexCoord.st;
|
vec2 uv = varTexCoord.st;
|
||||||
|
|
||||||
vec4 base = texture2D(baseTexture, uv).rgba;
|
vec4 base = texture2D(baseTexture, uv).rgba;
|
||||||
@@ -429,8 +444,19 @@ void main(void)
|
|||||||
discard;
|
discard;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
color = base.rgb;
|
// Apply crack overlay
|
||||||
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
|
float crack_progress = min(crackLevel, crackAnimationLength - 1.0);
|
||||||
|
if (crack_progress >= 0.0) {
|
||||||
|
// undo scaling of e.g. world-aligned nodes
|
||||||
|
vec2 orig_uv = uv_repeat(uv * vec2(crackTextureScale));
|
||||||
|
|
||||||
|
vec2 cuv_offset = vec2(0.0, crack_progress / crackAnimationLength);
|
||||||
|
vec2 cuv_factor = vec2(1.0, 1.0 / crackAnimationLength);
|
||||||
|
vec4 crack = texture2D(crackTexture, cuv_offset + orig_uv * cuv_factor);
|
||||||
|
base = mix(base, crack, crack.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 col = vec4(base.rgb * varColor.rgb, 1.0);
|
||||||
|
|
||||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||||
// Fragment normal, can differ from vNormal which is derived from vertex normals.
|
// Fragment normal, can differ from vNormal which is derived from vertex normals.
|
||||||
@@ -570,5 +596,5 @@ void main(void)
|
|||||||
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
|
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
|
||||||
col = vec4(col.rgb, base.a);
|
col = vec4(col.rgb, base.a);
|
||||||
|
|
||||||
gl_FragData[0] = col;
|
gl_FragColor = col;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -285,6 +285,7 @@ public:
|
|||||||
return m_animation_time;
|
return m_animation_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @return integer ∊ [0, crack_animation_length] or -1 for invalid
|
||||||
int getCrackLevel();
|
int getCrackLevel();
|
||||||
v3s16 getCrackPos();
|
v3s16 getCrackPos();
|
||||||
void setCrack(int level, v3s16 pos);
|
void setCrack(int level, v3s16 pos);
|
||||||
|
|||||||
@@ -1054,7 +1054,7 @@ void MapblockMeshGenerator::drawTorchlikeNode()
|
|||||||
default: tileindex = 2; // side (or invalid, shouldn't happen)
|
default: tileindex = 2; // side (or invalid, shouldn't happen)
|
||||||
}
|
}
|
||||||
TileSpec tile;
|
TileSpec tile;
|
||||||
useTile(&tile, tileindex, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
|
useTile(&tile, tileindex, 0, MATERIAL_FLAG_BACKFACE_CULLING);
|
||||||
|
|
||||||
float size = BS / 2 * cur_node.f->visual_scale;
|
float size = BS / 2 * cur_node.f->visual_scale;
|
||||||
v3f vertices[4] = {
|
v3f vertices[4] = {
|
||||||
@@ -1108,7 +1108,7 @@ void MapblockMeshGenerator::drawSignlikeNode()
|
|||||||
{
|
{
|
||||||
u8 wall = cur_node.n.getWallMounted(nodedef);
|
u8 wall = cur_node.n.getWallMounted(nodedef);
|
||||||
TileSpec tile;
|
TileSpec tile;
|
||||||
useTile(&tile, 0, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
|
useTile(&tile, 0, 0, MATERIAL_FLAG_BACKFACE_CULLING);
|
||||||
static const float offset = BS / 16;
|
static const float offset = BS / 16;
|
||||||
float size = BS / 2 * cur_node.f->visual_scale;
|
float size = BS / 2 * cur_node.f->visual_scale;
|
||||||
// Wall at X+ of node
|
// Wall at X+ of node
|
||||||
@@ -1294,9 +1294,10 @@ void MapblockMeshGenerator::drawPlantlikeNode()
|
|||||||
void MapblockMeshGenerator::drawPlantlikeRootedNode()
|
void MapblockMeshGenerator::drawPlantlikeRootedNode()
|
||||||
{
|
{
|
||||||
drawSolidNode();
|
drawSolidNode();
|
||||||
|
|
||||||
TileSpec tile;
|
TileSpec tile;
|
||||||
useTile(&tile, 0, MATERIAL_FLAG_CRACK_OVERLAY, 0, true);
|
useTile(&tile, 0, 0, 0, true);
|
||||||
cur_node.origin += v3f(0.0, BS, 0.0);
|
cur_node.origin += v3f(0, BS, 0);
|
||||||
cur_node.p.Y++;
|
cur_node.p.Y++;
|
||||||
if (data->m_smooth_lighting) {
|
if (data->m_smooth_lighting) {
|
||||||
getSmoothLightFrame();
|
getSmoothLightFrame();
|
||||||
@@ -1379,10 +1380,7 @@ void MapblockMeshGenerator::drawFirelikeNode()
|
|||||||
void MapblockMeshGenerator::drawFencelikeNode()
|
void MapblockMeshGenerator::drawFencelikeNode()
|
||||||
{
|
{
|
||||||
TileSpec tile_nocrack;
|
TileSpec tile_nocrack;
|
||||||
useTile(&tile_nocrack, 0, 0, 0);
|
useTile(&tile_nocrack, 0, 0, MATERIAL_FLAG_CRACK);
|
||||||
|
|
||||||
for (auto &layer : tile_nocrack.layers)
|
|
||||||
layer.material_flags &= ~MATERIAL_FLAG_CRACK;
|
|
||||||
|
|
||||||
// Put wood the right way around in the posts
|
// Put wood the right way around in the posts
|
||||||
TileSpec tile_rot = tile_nocrack;
|
TileSpec tile_rot = tile_nocrack;
|
||||||
@@ -1529,7 +1527,7 @@ void MapblockMeshGenerator::drawRaillikeNode()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TileSpec tile;
|
TileSpec tile;
|
||||||
useTile(&tile, tile_index, MATERIAL_FLAG_CRACK_OVERLAY, MATERIAL_FLAG_BACKFACE_CULLING);
|
useTile(&tile, tile_index, 0, MATERIAL_FLAG_BACKFACE_CULLING);
|
||||||
|
|
||||||
static const float offset = BS / 64;
|
static const float offset = BS / 64;
|
||||||
static const float size = BS / 2;
|
static const float size = BS / 2;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ private:
|
|||||||
video::SColor blendLightColor(const v3f &vertex_pos);
|
video::SColor blendLightColor(const v3f &vertex_pos);
|
||||||
video::SColor blendLightColor(const v3f &vertex_pos, const v3f &vertex_normal);
|
video::SColor blendLightColor(const v3f &vertex_pos, const v3f &vertex_normal);
|
||||||
|
|
||||||
void useTile(TileSpec *tile_ret, int index = 0, u8 set_flags = MATERIAL_FLAG_CRACK_OVERLAY,
|
void useTile(TileSpec *tile_ret, int index = 0, u8 set_flags = 0,
|
||||||
u8 reset_flags = 0, bool special = false);
|
u8 reset_flags = 0, bool special = false);
|
||||||
void getTile(int index, TileSpec *tile_ret);
|
void getTile(int index, TileSpec *tile_ret);
|
||||||
void getTile(v3s16 direction, TileSpec *tile_ret);
|
void getTile(v3s16 direction, TileSpec *tile_ret);
|
||||||
|
|||||||
@@ -179,21 +179,29 @@ class GameGlobalShaderUniformSetter : public IShaderUniformSetter
|
|||||||
{
|
{
|
||||||
Sky *m_sky;
|
Sky *m_sky;
|
||||||
Client *m_client;
|
Client *m_client;
|
||||||
|
|
||||||
CachedVertexShaderSetting<float> m_animation_timer_vertex{"animationTimer"};
|
CachedVertexShaderSetting<float> m_animation_timer_vertex{"animationTimer"};
|
||||||
CachedPixelShaderSetting<float> m_animation_timer_pixel{"animationTimer"};
|
CachedPixelShaderSetting<float> m_animation_timer_pixel{"animationTimer"};
|
||||||
CachedVertexShaderSetting<float>
|
CachedVertexShaderSetting<float>
|
||||||
m_animation_timer_delta_vertex{"animationTimerDelta"};
|
m_animation_timer_delta_vertex{"animationTimerDelta"};
|
||||||
CachedPixelShaderSetting<float>
|
CachedPixelShaderSetting<float>
|
||||||
m_animation_timer_delta_pixel{"animationTimerDelta"};
|
m_animation_timer_delta_pixel{"animationTimerDelta"};
|
||||||
|
int m_crack_animation_length_i;
|
||||||
|
CachedPixelShaderSetting<float> m_crack_animation_length{"crackAnimationLength"};
|
||||||
|
int m_crack_level_i = -1;
|
||||||
|
CachedPixelShaderSetting<float> m_crack_level{"crackLevel"};
|
||||||
|
int m_crack_texture_scale_i = 0;
|
||||||
|
CachedPixelShaderSetting<float> m_crack_texture_scale{"crackTextureScale"};
|
||||||
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
|
CachedPixelShaderSetting<float, 3> m_day_light{"dayLight"};
|
||||||
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
|
CachedPixelShaderSetting<float, 3> m_minimap_yaw{"yawVec"};
|
||||||
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
|
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel{"cameraOffset"};
|
||||||
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
|
CachedVertexShaderSetting<float, 3> m_camera_offset_vertex{"cameraOffset"};
|
||||||
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{ "cameraPosition" };
|
CachedPixelShaderSetting<float, 3> m_camera_position_pixel{"cameraPosition"};
|
||||||
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{ "cameraPosition" };
|
CachedVertexShaderSetting<float, 3> m_camera_position_vertex{"cameraPosition"};
|
||||||
CachedVertexShaderSetting<float, 2> m_texel_size0_vertex{"texelSize0"};
|
CachedVertexShaderSetting<float, 2> m_texel_size0_vertex{"texelSize0"};
|
||||||
CachedPixelShaderSetting<float, 2> m_texel_size0_pixel{"texelSize0"};
|
CachedPixelShaderSetting<float, 2> m_texel_size0_pixel{"texelSize0"};
|
||||||
v2f m_texel_size0;
|
v2f m_texel_size0;
|
||||||
|
|
||||||
CachedStructPixelShaderSetting<float, 7> m_exposure_params_pixel{
|
CachedStructPixelShaderSetting<float, 7> m_exposure_params_pixel{
|
||||||
"exposureParams",
|
"exposureParams",
|
||||||
std::array<const char*, 7> {
|
std::array<const char*, 7> {
|
||||||
@@ -235,9 +243,9 @@ public:
|
|||||||
|
|
||||||
void setSky(Sky *sky) { m_sky = sky; }
|
void setSky(Sky *sky) { m_sky = sky; }
|
||||||
|
|
||||||
GameGlobalShaderUniformSetter(Sky *sky, Client *client) :
|
GameGlobalShaderUniformSetter(Sky *sky, Game *game) :
|
||||||
m_sky(sky),
|
m_sky(sky),
|
||||||
m_client(client)
|
m_client(game->getClient())
|
||||||
{
|
{
|
||||||
for (auto &name : SETTING_CALLBACKS)
|
for (auto &name : SETTING_CALLBACKS)
|
||||||
g_settings->registerChangedCallback(name, settingsCallback, this);
|
g_settings->registerChangedCallback(name, settingsCallback, this);
|
||||||
@@ -245,6 +253,7 @@ public:
|
|||||||
m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
|
m_user_exposure_compensation = g_settings->getFloat("exposure_compensation", -1.0f, 1.0f);
|
||||||
m_bloom_enabled = g_settings->getBool("enable_bloom");
|
m_bloom_enabled = g_settings->getBool("enable_bloom");
|
||||||
m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled;
|
m_volumetric_light_enabled = g_settings->getBool("enable_volumetric_lighting") && m_bloom_enabled;
|
||||||
|
m_crack_animation_length_i = game->crack_animation_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
~GameGlobalShaderUniformSetter()
|
~GameGlobalShaderUniformSetter()
|
||||||
@@ -284,6 +293,15 @@ public:
|
|||||||
m_texel_size0_vertex.set(m_texel_size0, services);
|
m_texel_size0_vertex.set(m_texel_size0, services);
|
||||||
m_texel_size0_pixel.set(m_texel_size0, services);
|
m_texel_size0_pixel.set(m_texel_size0, services);
|
||||||
|
|
||||||
|
{
|
||||||
|
float tmp = m_crack_animation_length_i;
|
||||||
|
m_crack_animation_length.set(&tmp, services);
|
||||||
|
tmp = m_crack_level_i;
|
||||||
|
m_crack_level.set(&tmp, services);
|
||||||
|
tmp = m_crack_texture_scale_i;
|
||||||
|
m_crack_texture_scale.set(&tmp, services);
|
||||||
|
}
|
||||||
|
|
||||||
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
const auto &lighting = m_client->getEnv().getLocalPlayer()->getLighting();
|
||||||
|
|
||||||
const AutoExposure &exposure_params = lighting.exposure;
|
const AutoExposure &exposure_params = lighting.exposure;
|
||||||
@@ -357,6 +375,11 @@ public:
|
|||||||
|
|
||||||
void onSetMaterial(const video::SMaterial &material) override
|
void onSetMaterial(const video::SMaterial &material) override
|
||||||
{
|
{
|
||||||
|
// This is set only for node materials which have a crack, see mapblock_mesh.cpp.
|
||||||
|
auto pair = MapBlockMesh::unpackCrackMaterialParam(material.MaterialTypeParam);
|
||||||
|
m_crack_level_i = pair.first;
|
||||||
|
m_crack_texture_scale_i = pair.second;
|
||||||
|
|
||||||
video::ITexture *texture = material.getTexture(0);
|
video::ITexture *texture = material.getTexture(0);
|
||||||
if (texture) {
|
if (texture) {
|
||||||
core::dimension2du size = texture->getSize();
|
core::dimension2du size = texture->getSize();
|
||||||
@@ -371,11 +394,11 @@ public:
|
|||||||
class GameGlobalShaderUniformSetterFactory : public IShaderUniformSetterFactory
|
class GameGlobalShaderUniformSetterFactory : public IShaderUniformSetterFactory
|
||||||
{
|
{
|
||||||
Sky *m_sky = nullptr;
|
Sky *m_sky = nullptr;
|
||||||
Client *m_client;
|
Game *m_game;
|
||||||
std::vector<GameGlobalShaderUniformSetter *> created_nosky;
|
std::vector<GameGlobalShaderUniformSetter*> created_nosky;
|
||||||
public:
|
public:
|
||||||
GameGlobalShaderUniformSetterFactory(Client *client) :
|
GameGlobalShaderUniformSetterFactory(Game *game) :
|
||||||
m_client(client)
|
m_game(game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void setSky(Sky *sky)
|
void setSky(Sky *sky)
|
||||||
@@ -391,7 +414,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (str_starts_with(name, "shadow/"))
|
if (str_starts_with(name, "shadow/"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto *scs = new GameGlobalShaderUniformSetter(m_sky, m_client);
|
auto *scs = new GameGlobalShaderUniformSetter(m_sky, m_game);
|
||||||
if (!m_sky)
|
if (!m_sky)
|
||||||
created_nosky.push_back(scs);
|
created_nosky.push_back(scs);
|
||||||
return scs;
|
return scs;
|
||||||
@@ -957,10 +980,19 @@ bool Game::createClient(const GameStartData &start_data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pre-calculate crack length
|
||||||
|
video::ITexture *t = texture_src->getTexture("crack_anylength.png");
|
||||||
|
if (t) {
|
||||||
|
v2u32 size = t->getOriginalSize();
|
||||||
|
crack_animation_length = size.Y / size.X;
|
||||||
|
} else {
|
||||||
|
crack_animation_length = 5;
|
||||||
|
}
|
||||||
|
|
||||||
shader_src->addShaderConstantSetter(
|
shader_src->addShaderConstantSetter(
|
||||||
std::make_unique<NodeShaderConstantSetter>());
|
std::make_unique<NodeShaderConstantSetter>());
|
||||||
|
|
||||||
auto scsf_up = std::make_unique<GameGlobalShaderUniformSetterFactory>(client);
|
auto scsf_up = std::make_unique<GameGlobalShaderUniformSetterFactory>(this);
|
||||||
auto* scsf = scsf_up.get();
|
auto* scsf = scsf_up.get();
|
||||||
shader_src->addShaderUniformSetterFactory(std::move(scsf_up));
|
shader_src->addShaderUniformSetterFactory(std::move(scsf_up));
|
||||||
|
|
||||||
@@ -988,16 +1020,6 @@ bool Game::createClient(const GameStartData &start_data)
|
|||||||
sky = make_irr<Sky>(-1, m_rendering_engine, texture_src, shader_src);
|
sky = make_irr<Sky>(-1, m_rendering_engine, texture_src, shader_src);
|
||||||
scsf->setSky(sky.get());
|
scsf->setSky(sky.get());
|
||||||
|
|
||||||
/* Pre-calculated values
|
|
||||||
*/
|
|
||||||
video::ITexture *t = texture_src->getTexture("crack_anylength.png");
|
|
||||||
if (t) {
|
|
||||||
v2u32 size = t->getOriginalSize();
|
|
||||||
crack_animation_length = size.Y / size.X;
|
|
||||||
} else {
|
|
||||||
crack_animation_length = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!initGui())
|
if (!initGui())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|||||||
@@ -1039,17 +1039,14 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
|||||||
// A special texture modification
|
// A special texture modification
|
||||||
|
|
||||||
/*
|
/*
|
||||||
[crack:N:P
|
[crack[o][:<tiles>]:<frame_count>:<frame>
|
||||||
[cracko:N:P
|
|
||||||
Adds a cracking texture
|
Adds a cracking texture
|
||||||
N = animation frame count, P = crack progression
|
NOTE: Crack rendering does not use this, it's for mods only.
|
||||||
*/
|
*/
|
||||||
if (str_starts_with(part_of_name, "[crack"))
|
if (str_starts_with(part_of_name, "[crack"))
|
||||||
{
|
{
|
||||||
CHECK_BASEIMG();
|
CHECK_BASEIMG();
|
||||||
|
|
||||||
// Crack image number and overlay option
|
|
||||||
// Format: crack[o][:<tiles>]:<frame_count>:<frame>
|
|
||||||
bool use_overlay = (part_of_name[6] == 'o');
|
bool use_overlay = (part_of_name[6] == 'o');
|
||||||
Strfnd sf(part_of_name);
|
Strfnd sf(part_of_name);
|
||||||
sf.next(":");
|
sf.next(":");
|
||||||
@@ -1276,9 +1273,7 @@ bool ImageSource::generateImagePart(std::string_view part_of_name,
|
|||||||
[inventorycube{topimage{leftimage{rightimage
|
[inventorycube{topimage{leftimage{rightimage
|
||||||
In every subimage, replace ^ with &.
|
In every subimage, replace ^ with &.
|
||||||
Create an "inventory cube".
|
Create an "inventory cube".
|
||||||
NOTE: This should be used only on its own.
|
NOTE: Inventory rendering does not use this, it's for mods only.
|
||||||
Example (a grass block (not actually used in game):
|
|
||||||
"[inventorycube{grass.png{mud.png&grass_side.png{mud.png&grass_side.png"
|
|
||||||
*/
|
*/
|
||||||
else if (str_starts_with(part_of_name, "[inventorycube"))
|
else if (str_starts_with(part_of_name, "[inventorycube"))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -648,25 +648,6 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||||||
p.applyTileColor();
|
p.applyTileColor();
|
||||||
|
|
||||||
// Generate animation data
|
// Generate animation data
|
||||||
// - Cracks
|
|
||||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK) {
|
|
||||||
// Find the texture name plus ^[crack:N:
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
os << m_tsrc->getTextureName(p.layer.texture_id) << "^[crack";
|
|
||||||
if (p.layer.material_flags & MATERIAL_FLAG_CRACK_OVERLAY)
|
|
||||||
os << "o"; // use ^[cracko
|
|
||||||
u8 tiles = p.layer.scale;
|
|
||||||
if (tiles > 1)
|
|
||||||
os << ":" << (u32)tiles;
|
|
||||||
os << ":" << (u32)p.layer.animation_frame_count << ":";
|
|
||||||
m_crack_materials.insert(std::make_pair(
|
|
||||||
std::pair<u8, u32>(layer, i), os.str()));
|
|
||||||
// Replace tile texture with the cracked one
|
|
||||||
p.layer.texture = m_tsrc->getTextureForMesh(
|
|
||||||
os.str() + "0",
|
|
||||||
&p.layer.texture_id);
|
|
||||||
}
|
|
||||||
// - Texture animation
|
|
||||||
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
|
if (p.layer.material_flags & MATERIAL_FLAG_ANIMATION) {
|
||||||
// Add to MapBlockMesh in order to animate these tiles
|
// Add to MapBlockMesh in order to animate these tiles
|
||||||
m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer));
|
m_animation_info.emplace(std::make_pair(layer, i), AnimationInfo(p.layer));
|
||||||
@@ -689,6 +670,17 @@ MapBlockMesh::MapBlockMesh(Client *client, MeshMakeData *data):
|
|||||||
p.layer.applyMaterialOptions(material, layer);
|
p.layer.applyMaterialOptions(material, layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle crack
|
||||||
|
if (p.layer.material_flags & MATERIAL_FLAG_CRACK) {
|
||||||
|
auto *t = m_tsrc->getTextureForMesh("crack_anylength.png");
|
||||||
|
material.setTexture(TEXTURE_LAYER_CRACK, t);
|
||||||
|
material.MaterialTypeParam =
|
||||||
|
packCrackMaterialParam(-1, MYMAX(1, p.layer.scale));
|
||||||
|
|
||||||
|
m_crack_materials.emplace_back(layer, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to buffer
|
||||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
||||||
buf->Material = material;
|
buf->Material = material;
|
||||||
if (p.layer.isTransparent()) {
|
if (p.layer.isTransparent()) {
|
||||||
@@ -752,22 +744,14 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
|||||||
|
|
||||||
// Cracks
|
// Cracks
|
||||||
if (crack != m_last_crack) {
|
if (crack != m_last_crack) {
|
||||||
for (auto &crack_material : m_crack_materials) {
|
for (auto &it : m_crack_materials) {
|
||||||
|
scene::IMeshBuffer *buf = m_mesh[it.first]->getMeshBuffer(it.second);
|
||||||
|
assert(buf);
|
||||||
|
video::SMaterial &mat = buf->getMaterial();
|
||||||
|
|
||||||
// TODO crack on animated tiles does not work
|
auto pair = unpackCrackMaterialParam(mat.MaterialTypeParam);
|
||||||
auto anim_it = m_animation_info.find(crack_material.first);
|
pair.first = crack;
|
||||||
if (anim_it != m_animation_info.end())
|
mat.MaterialTypeParam = packCrackMaterialParam(pair.first, pair.second);
|
||||||
continue;
|
|
||||||
|
|
||||||
scene::IMeshBuffer *buf = m_mesh[crack_material.first.first]->
|
|
||||||
getMeshBuffer(crack_material.first.second);
|
|
||||||
|
|
||||||
// Create new texture name from original
|
|
||||||
std::string s = crack_material.second + itos(crack);
|
|
||||||
u32 new_texture_id = 0;
|
|
||||||
video::ITexture *new_texture =
|
|
||||||
m_tsrc->getTextureForMesh(s, &new_texture_id);
|
|
||||||
buf->getMaterial().setTexture(0, new_texture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_last_crack = crack;
|
m_last_crack = crack;
|
||||||
@@ -776,6 +760,7 @@ bool MapBlockMesh::animate(bool faraway, float time, int crack,
|
|||||||
// Texture animation
|
// Texture animation
|
||||||
for (auto &it : m_animation_info) {
|
for (auto &it : m_animation_info) {
|
||||||
scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second);
|
scene::IMeshBuffer *buf = m_mesh[it.first.first]->getMeshBuffer(it.first.second);
|
||||||
|
assert(buf);
|
||||||
video::SMaterial &material = buf->getMaterial();
|
video::SMaterial &material = buf->getMaterial();
|
||||||
it.second.updateTexture(material, time);
|
it.second.updateTexture(material, time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ public:
|
|||||||
// faraway: whether the block is far away from the camera (~50 nodes)
|
// faraway: whether the block is far away from the camera (~50 nodes)
|
||||||
// time: the global animation time, 0 .. 60 (repeats every minute)
|
// time: the global animation time, 0 .. 60 (repeats every minute)
|
||||||
// daynight_ratio: 0 .. 1000
|
// daynight_ratio: 0 .. 1000
|
||||||
// crack: -1 .. CRACK_ANIMATION_LENGTH-1 (-1 for off)
|
// crack: -1 .. CRACK_ANIMATION_LENGTH (-1 for off)
|
||||||
// Returns true if anything has been changed.
|
// Returns true if anything has been changed.
|
||||||
bool animate(bool faraway, float time, int crack, u32 daynight_ratio);
|
bool animate(bool faraway, float time, int crack, u32 daynight_ratio);
|
||||||
|
|
||||||
@@ -257,8 +257,28 @@ public:
|
|||||||
return m_transparent_buffers;
|
return m_transparent_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Texture layer in SMaterial where the crack texture is put
|
||||||
|
*/
|
||||||
|
static const int TEXTURE_LAYER_CRACK = 1;
|
||||||
|
|
||||||
|
static float packCrackMaterialParam(int crack, u8 layer_scale)
|
||||||
|
{
|
||||||
|
// +1 so that the default MaterialTypeParam = 0 is a no-op,
|
||||||
|
// since the shader needs to know when to actually apply the crack.
|
||||||
|
u32 n = (layer_scale << 16) | (u16) (crack + 1);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
static std::pair<int, u8> unpackCrackMaterialParam(float param)
|
||||||
|
{
|
||||||
|
u32 n = param;
|
||||||
|
return std::make_pair<int, u8>((n & 0xffff) - 1, (n >> 16) & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
typedef std::pair<u8 /* layer index */, u32 /* buffer index */> MeshIndex;
|
||||||
|
|
||||||
irr_ptr<scene::IMesh> m_mesh[MAX_TILE_LAYERS];
|
irr_ptr<scene::IMesh> m_mesh[MAX_TILE_LAYERS];
|
||||||
std::vector<MinimapMapblock*> m_minimap_mapblocks;
|
std::vector<MinimapMapblock*> m_minimap_mapblocks;
|
||||||
ITextureSource *m_tsrc;
|
ITextureSource *m_tsrc;
|
||||||
@@ -274,13 +294,12 @@ private:
|
|||||||
// Animation info: cracks
|
// Animation info: cracks
|
||||||
// Last crack value passed to animate()
|
// Last crack value passed to animate()
|
||||||
int m_last_crack;
|
int m_last_crack;
|
||||||
// Maps mesh and mesh buffer (i.e. material) indices to base texture names
|
// Indicates which materials to apply the crack to
|
||||||
std::map<std::pair<u8, u32>, std::string> m_crack_materials;
|
std::vector<MeshIndex> m_crack_materials;
|
||||||
|
|
||||||
// Animation info: texture animation
|
// Animation info: texture animation
|
||||||
// Maps mesh and mesh buffer indices to TileSpecs
|
// Maps mesh and mesh buffer indices to TileSpecs
|
||||||
// Keys are pairs of (mesh index, buffer index in the mesh)
|
std::map<MeshIndex, AnimationInfo> m_animation_info;
|
||||||
std::map<std::pair<u8, u32>, AnimationInfo> m_animation_info;
|
|
||||||
|
|
||||||
// list of all semitransparent triangles in the mapblock
|
// list of all semitransparent triangles in the mapblock
|
||||||
std::vector<MeshTriangle> m_transparent_triangles;
|
std::vector<MeshTriangle> m_transparent_triangles;
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ class MainShaderUniformSetter : public IShaderUniformSetter
|
|||||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"};
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture2{"texture2"};
|
||||||
CachedPixelShaderSetting<SamplerLayer_t> m_texture3{"texture3"};
|
CachedPixelShaderSetting<SamplerLayer_t> m_texture3{"texture3"};
|
||||||
|
|
||||||
// commonly used way to pass material color to shader
|
// common material variables passed to shader
|
||||||
video::SColor m_material_color;
|
video::SColor m_material_color;
|
||||||
CachedPixelShaderSetting<float, 4> m_material_color_setting{"materialColor"};
|
CachedPixelShaderSetting<float, 4> m_material_color_setting{"materialColor"};
|
||||||
|
|
||||||
@@ -700,12 +700,8 @@ void ShaderSource::generateShader(ShaderInfo &shaderinfo)
|
|||||||
)";
|
)";
|
||||||
}
|
}
|
||||||
|
|
||||||
// map legacy semantic texture names to texture identifiers
|
// legacy semantic texture name
|
||||||
fragment_header += R"(
|
fragment_header += "#define baseTexture texture0\n";
|
||||||
#define baseTexture texture0
|
|
||||||
#define normalTexture texture1
|
|
||||||
#define textureFlags texture2
|
|
||||||
)";
|
|
||||||
|
|
||||||
/// Unique name of this shader, for debug/logging
|
/// Unique name of this shader, for debug/logging
|
||||||
std::string log_name = name;
|
std::string log_name = name;
|
||||||
|
|||||||
@@ -30,11 +30,8 @@ enum MaterialType : u8 {
|
|||||||
#define MATERIAL_FLAG_BACKFACE_CULLING 0x01
|
#define MATERIAL_FLAG_BACKFACE_CULLING 0x01
|
||||||
// Should a crack be drawn?
|
// Should a crack be drawn?
|
||||||
#define MATERIAL_FLAG_CRACK 0x02
|
#define MATERIAL_FLAG_CRACK 0x02
|
||||||
// Should the crack be drawn on transparent pixels (unset) or not (set)?
|
// Does this layer have texture animation?
|
||||||
// Ignored if MATERIAL_FLAG_CRACK is not set.
|
|
||||||
#define MATERIAL_FLAG_CRACK_OVERLAY 0x04
|
|
||||||
#define MATERIAL_FLAG_ANIMATION 0x08
|
#define MATERIAL_FLAG_ANIMATION 0x08
|
||||||
//#define MATERIAL_FLAG_HIGHLIGHTED 0x10
|
|
||||||
#define MATERIAL_FLAG_TILEABLE_HORIZONTAL 0x20
|
#define MATERIAL_FLAG_TILEABLE_HORIZONTAL 0x20
|
||||||
#define MATERIAL_FLAG_TILEABLE_VERTICAL 0x40
|
#define MATERIAL_FLAG_TILEABLE_VERTICAL 0x40
|
||||||
|
|
||||||
@@ -78,7 +75,7 @@ struct TileLayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Two tiles are not equal if they must have different vertices.
|
* Two layers are not equal if they must have different vertices.
|
||||||
*/
|
*/
|
||||||
bool operator!=(const TileLayer &other) const
|
bool operator!=(const TileLayer &other) const
|
||||||
{
|
{
|
||||||
@@ -127,7 +124,6 @@ struct TileLayer
|
|||||||
|
|
||||||
MaterialType material_type = TILE_MATERIAL_BASIC;
|
MaterialType material_type = TILE_MATERIAL_BASIC;
|
||||||
u8 material_flags =
|
u8 material_flags =
|
||||||
//0 // <- DEBUG, Use the one below
|
|
||||||
MATERIAL_FLAG_BACKFACE_CULLING |
|
MATERIAL_FLAG_BACKFACE_CULLING |
|
||||||
MATERIAL_FLAG_TILEABLE_HORIZONTAL|
|
MATERIAL_FLAG_TILEABLE_HORIZONTAL|
|
||||||
MATERIAL_FLAG_TILEABLE_VERTICAL;
|
MATERIAL_FLAG_TILEABLE_VERTICAL;
|
||||||
|
|||||||
Reference in New Issue
Block a user