Merge pull request #83489 from groud/implement_tile_map_normals

Allow normal maps on TileMaps that use texture padding
This commit is contained in:
Rémi Verschelde 2023-10-18 16:54:44 +02:00
commit 65e7ddadd7
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 114 additions and 33 deletions

View File

@ -1496,6 +1496,9 @@ CanvasItem::~CanvasItem() {
void CanvasTexture::set_diffuse_texture(const Ref<Texture2D> &p_diffuse) { void CanvasTexture::set_diffuse_texture(const Ref<Texture2D> &p_diffuse) {
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_diffuse.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
if (diffuse_texture == p_diffuse) {
return;
}
diffuse_texture = p_diffuse; diffuse_texture = p_diffuse;
RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID(); RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID();
@ -1508,9 +1511,13 @@ Ref<Texture2D> CanvasTexture::get_diffuse_texture() const {
void CanvasTexture::set_normal_texture(const Ref<Texture2D> &p_normal) { void CanvasTexture::set_normal_texture(const Ref<Texture2D> &p_normal) {
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_normal.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
if (normal_texture == p_normal) {
return;
}
normal_texture = p_normal; normal_texture = p_normal;
RID tex_rid = normal_texture.is_valid() ? normal_texture->get_rid() : RID(); RID tex_rid = normal_texture.is_valid() ? normal_texture->get_rid() : RID();
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_NORMAL, tex_rid); RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_NORMAL, tex_rid);
emit_changed();
} }
Ref<Texture2D> CanvasTexture::get_normal_texture() const { Ref<Texture2D> CanvasTexture::get_normal_texture() const {
return normal_texture; return normal_texture;
@ -1518,9 +1525,13 @@ Ref<Texture2D> CanvasTexture::get_normal_texture() const {
void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) { void CanvasTexture::set_specular_texture(const Ref<Texture2D> &p_specular) {
ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Can't self-assign a CanvasTexture"); ERR_FAIL_COND_MSG(Object::cast_to<CanvasTexture>(p_specular.ptr()) != nullptr, "Can't self-assign a CanvasTexture");
if (specular_texture == p_specular) {
return;
}
specular_texture = p_specular; specular_texture = p_specular;
RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID(); RID tex_rid = specular_texture.is_valid() ? specular_texture->get_rid() : RID();
RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid); RS::get_singleton()->canvas_texture_set_channel(canvas_texture, RS::CANVAS_TEXTURE_CHANNEL_SPECULAR, tex_rid);
emit_changed();
} }
Ref<Texture2D> CanvasTexture::get_specular_texture() const { Ref<Texture2D> CanvasTexture::get_specular_texture() const {
@ -1528,8 +1539,12 @@ Ref<Texture2D> CanvasTexture::get_specular_texture() const {
} }
void CanvasTexture::set_specular_color(const Color &p_color) { void CanvasTexture::set_specular_color(const Color &p_color) {
if (specular == p_color) {
return;
}
specular = p_color; specular = p_color;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess); RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
emit_changed();
} }
Color CanvasTexture::get_specular_color() const { Color CanvasTexture::get_specular_color() const {
@ -1537,8 +1552,12 @@ Color CanvasTexture::get_specular_color() const {
} }
void CanvasTexture::set_specular_shininess(real_t p_shininess) { void CanvasTexture::set_specular_shininess(real_t p_shininess) {
if (shininess == p_shininess) {
return;
}
shininess = p_shininess; shininess = p_shininess;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess); RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
emit_changed();
} }
real_t CanvasTexture::get_specular_shininess() const { real_t CanvasTexture::get_specular_shininess() const {
@ -1546,16 +1565,24 @@ real_t CanvasTexture::get_specular_shininess() const {
} }
void CanvasTexture::set_texture_filter(CanvasItem::TextureFilter p_filter) { void CanvasTexture::set_texture_filter(CanvasItem::TextureFilter p_filter) {
if (texture_filter == p_filter) {
return;
}
texture_filter = p_filter; texture_filter = p_filter;
RS::get_singleton()->canvas_texture_set_texture_filter(canvas_texture, RS::CanvasItemTextureFilter(p_filter)); RS::get_singleton()->canvas_texture_set_texture_filter(canvas_texture, RS::CanvasItemTextureFilter(p_filter));
emit_changed();
} }
CanvasItem::TextureFilter CanvasTexture::get_texture_filter() const { CanvasItem::TextureFilter CanvasTexture::get_texture_filter() const {
return texture_filter; return texture_filter;
} }
void CanvasTexture::set_texture_repeat(CanvasItem::TextureRepeat p_repeat) { void CanvasTexture::set_texture_repeat(CanvasItem::TextureRepeat p_repeat) {
if (texture_repeat == p_repeat) {
return;
}
texture_repeat = p_repeat; texture_repeat = p_repeat;
RS::get_singleton()->canvas_texture_set_texture_repeat(canvas_texture, RS::CanvasItemTextureRepeat(p_repeat)); RS::get_singleton()->canvas_texture_set_texture_repeat(canvas_texture, RS::CanvasItemTextureRepeat(p_repeat));
emit_changed();
} }
CanvasItem::TextureRepeat CanvasTexture::get_texture_repeat() const { CanvasItem::TextureRepeat CanvasTexture::get_texture_repeat() const {
return texture_repeat; return texture_repeat;

View File

@ -4758,30 +4758,18 @@ void TileSetAtlasSource::_queue_update_padded_texture() {
call_deferred(SNAME("_update_padded_texture")); call_deferred(SNAME("_update_padded_texture"));
} }
void TileSetAtlasSource::_update_padded_texture() { Ref<ImageTexture> TileSetAtlasSource::_create_padded_image_texture(const Ref<Texture2D> &p_source) {
if (!padded_texture_needs_update) { ERR_FAIL_COND_V(p_source.is_null(), Ref<ImageTexture>());
return;
}
padded_texture_needs_update = false;
padded_texture = Ref<ImageTexture>();
if (!texture.is_valid()) { Ref<Image> src_image = p_source->get_image();
return; if (src_image.is_null()) {
} Ref<ImageTexture> ret;
ret.instantiate();
if (!use_texture_padding) { return ret;
return;
} }
Size2 size = get_atlas_grid_size() * (texture_region_size + Vector2i(2, 2)); Size2 size = get_atlas_grid_size() * (texture_region_size + Vector2i(2, 2));
Ref<Image> image = Image::create_empty(size.x, size.y, false, src_image->get_format());
Ref<Image> src = texture->get_image();
if (!src.is_valid()) {
return;
}
Ref<Image> image = Image::create_empty(size.x, size.y, false, src->get_format());
for (KeyValue<Vector2i, TileAlternativesData> kv : tiles) { for (KeyValue<Vector2i, TileAlternativesData> kv : tiles) {
for (int frame = 0; frame < (int)kv.value.animation_frames_durations.size(); frame++) { for (int frame = 0; frame < (int)kv.value.animation_frames_durations.size(); frame++) {
@ -4797,24 +4785,89 @@ void TileSetAtlasSource::_update_padded_texture() {
Vector2i frame_coords = kv.key + (kv.value.size_in_atlas + kv.value.animation_separation) * ((kv.value.animation_columns > 0) ? Vector2i(frame % kv.value.animation_columns, frame / kv.value.animation_columns) : Vector2i(frame, 0)); Vector2i frame_coords = kv.key + (kv.value.size_in_atlas + kv.value.animation_separation) * ((kv.value.animation_columns > 0) ? Vector2i(frame % kv.value.animation_columns, frame / kv.value.animation_columns) : Vector2i(frame, 0));
Vector2i base_pos = frame_coords * (texture_region_size + Vector2i(2, 2)) + Vector2i(1, 1); Vector2i base_pos = frame_coords * (texture_region_size + Vector2i(2, 2)) + Vector2i(1, 1);
image->blit_rect(*src, src_rect, base_pos); image->blit_rect(*src_image, src_rect, base_pos);
image->blit_rect(*src, top_src_rect, base_pos + Vector2i(0, -1)); image->blit_rect(*src_image, top_src_rect, base_pos + Vector2i(0, -1));
image->blit_rect(*src, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y)); image->blit_rect(*src_image, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y));
image->blit_rect(*src, left_src_rect, base_pos + Vector2i(-1, 0)); image->blit_rect(*src_image, left_src_rect, base_pos + Vector2i(-1, 0));
image->blit_rect(*src, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0)); image->blit_rect(*src_image, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0));
image->set_pixelv(base_pos + Vector2i(-1, -1), src->get_pixelv(src_rect.position)); image->set_pixelv(base_pos + Vector2i(-1, -1), src_image->get_pixelv(src_rect.position));
image->set_pixelv(base_pos + Vector2i(src_rect.size.x, -1), src->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, 0))); image->set_pixelv(base_pos + Vector2i(src_rect.size.x, -1), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, 0)));
image->set_pixelv(base_pos + Vector2i(-1, src_rect.size.y), src->get_pixelv(src_rect.position + Vector2i(0, src_rect.size.y - 1))); image->set_pixelv(base_pos + Vector2i(-1, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(0, src_rect.size.y - 1)));
image->set_pixelv(base_pos + Vector2i(src_rect.size.x, src_rect.size.y), src->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1))); image->set_pixelv(base_pos + Vector2i(src_rect.size.x, src_rect.size.y), src_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1)));
} }
} }
if (!padded_texture.is_valid()) { return ImageTexture::create_from_image(image);
padded_texture.instantiate(); }
void TileSetAtlasSource::_update_padded_texture() {
if (!padded_texture_needs_update) {
return;
} }
padded_texture->set_image(image); padded_texture_needs_update = false;
if (padded_texture.is_valid()) {
padded_texture->disconnect_changed(callable_mp(this, &TileSetAtlasSource::_queue_update_padded_texture));
}
padded_texture = Ref<CanvasTexture>();
if (texture.is_null()) {
return;
}
if (!use_texture_padding) {
return;
}
padded_texture.instantiate();
Ref<CanvasTexture> src_canvas_texture = texture;
if (src_canvas_texture.is_valid()) {
// Use all textures.
// Diffuse
Ref<Texture2D> src = src_canvas_texture->get_diffuse_texture();
Ref<ImageTexture> image_texture;
if (src.is_valid()) {
image_texture = _create_padded_image_texture(src);
} else {
image_texture.instantiate();
}
padded_texture->set_diffuse_texture(image_texture);
// Normal
src = src_canvas_texture->get_normal_texture();
image_texture.instantiate();
if (src.is_valid()) {
image_texture = _create_padded_image_texture(src);
} else {
image_texture.instantiate();
}
padded_texture->set_normal_texture(image_texture);
// Specular
src = src_canvas_texture->get_specular_texture();
image_texture.instantiate();
if (src.is_valid()) {
image_texture = _create_padded_image_texture(src);
} else {
image_texture.instantiate();
}
padded_texture->set_specular_texture(image_texture);
// Other properties.
padded_texture->set_specular_color(src_canvas_texture->get_specular_color());
padded_texture->set_specular_shininess(src_canvas_texture->get_specular_shininess());
padded_texture->set_texture_filter(src_canvas_texture->get_texture_filter());
padded_texture->set_texture_repeat(src_canvas_texture->get_texture_repeat());
} else {
// Use only diffuse.
Ref<ImageTexture> image_texture = _create_padded_image_texture(texture);
padded_texture->set_diffuse_texture(image_texture);
}
padded_texture->connect_changed(callable_mp(this, &TileSetAtlasSource::_queue_update_padded_texture));
emit_changed(); emit_changed();
} }

View File

@ -641,9 +641,10 @@ private:
void _create_coords_mapping_cache(Vector2i p_atlas_coords); void _create_coords_mapping_cache(Vector2i p_atlas_coords);
bool use_texture_padding = true; bool use_texture_padding = true;
Ref<ImageTexture> padded_texture; Ref<CanvasTexture> padded_texture;
bool padded_texture_needs_update = false; bool padded_texture_needs_update = false;
void _queue_update_padded_texture(); void _queue_update_padded_texture();
Ref<ImageTexture> _create_padded_image_texture(const Ref<Texture2D> &p_source);
void _update_padded_texture(); void _update_padded_texture();
protected: protected: