Merge pull request #83489 from groud/implement_tile_map_normals
Allow normal maps on TileMaps that use texture padding
This commit is contained in:
commit
65e7ddadd7
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSetAtlasSource::_update_padded_texture() {
|
||||||
|
if (!padded_texture_needs_update) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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();
|
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_image(image);
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue