Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow normal maps on TileMaps that use texture padding #83489

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,9 @@ CanvasItem::~CanvasItem() {

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");
if (diffuse_texture == p_diffuse) {
return;
}
diffuse_texture = p_diffuse;

RID tex_rid = diffuse_texture.is_valid() ? diffuse_texture->get_rid() : RID();
Expand All @@ -1508,54 +1511,78 @@ Ref<Texture2D> CanvasTexture::get_diffuse_texture() const {

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");
if (normal_texture == p_normal) {
return;
}
normal_texture = p_normal;
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);
emit_changed();
groud marked this conversation as resolved.
Show resolved Hide resolved
}
Ref<Texture2D> CanvasTexture::get_normal_texture() const {
return normal_texture;
}

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");
if (specular_texture == p_specular) {
return;
}
specular_texture = p_specular;
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);
emit_changed();
}

Ref<Texture2D> CanvasTexture::get_specular_texture() const {
return specular_texture;
}

void CanvasTexture::set_specular_color(const Color &p_color) {
if (specular == p_color) {
return;
}
specular = p_color;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
emit_changed();
}

Color CanvasTexture::get_specular_color() const {
return specular;
}

void CanvasTexture::set_specular_shininess(real_t p_shininess) {
if (shininess == p_shininess) {
return;
}
shininess = p_shininess;
RS::get_singleton()->canvas_texture_set_shading_parameters(canvas_texture, specular, shininess);
emit_changed();
}

real_t CanvasTexture::get_specular_shininess() const {
return shininess;
}

void CanvasTexture::set_texture_filter(CanvasItem::TextureFilter p_filter) {
if (texture_filter == p_filter) {
return;
}
texture_filter = 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 {
return texture_filter;
}

void CanvasTexture::set_texture_repeat(CanvasItem::TextureRepeat p_repeat) {
if (texture_repeat == p_repeat) {
return;
}
texture_repeat = 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 {
return texture_repeat;
Expand Down
117 changes: 85 additions & 32 deletions scene/resources/tile_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4758,30 +4758,18 @@ void TileSetAtlasSource::_queue_update_padded_texture() {
call_deferred(SNAME("_update_padded_texture"));
}

void TileSetAtlasSource::_update_padded_texture() {
if (!padded_texture_needs_update) {
return;
}
padded_texture_needs_update = false;
padded_texture = Ref<ImageTexture>();
Ref<ImageTexture> TileSetAtlasSource::_create_padded_image_texture(const Ref<Texture2D> &p_source) {
ERR_FAIL_COND_V(p_source.is_null(), Ref<ImageTexture>());

if (!texture.is_valid()) {
return;
}

if (!use_texture_padding) {
return;
Ref<Image> src_image = p_source->get_image();
if (src_image.is_null()) {
Ref<ImageTexture> ret;
ret.instantiate();
return ret;
}

Size2 size = get_atlas_grid_size() * (texture_region_size + Vector2i(2, 2));

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());
Ref<Image> image = Image::create_empty(size.x, size.y, false, src_image->get_format());

for (KeyValue<Vector2i, TileAlternativesData> kv : tiles) {
for (int frame = 0; frame < (int)kv.value.animation_frames_durations.size(); frame++) {
Expand All @@ -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 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, 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, right_src_rect, base_pos + Vector2i(src_rect.size.x, 0));
image->blit_rect(*src_image, top_src_rect, base_pos + Vector2i(0, -1));
image->blit_rect(*src_image, bottom_src_rect, base_pos + Vector2i(0, src_rect.size.y));
image->blit_rect(*src_image, left_src_rect, base_pos + Vector2i(-1, 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(src_rect.size.x, -1), src->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(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(-1, -1), src_image->get_pixelv(src_rect.position));
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_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_image->get_pixelv(src_rect.position + Vector2i(src_rect.size.x - 1, src_rect.size.y - 1)));
}
}

if (!padded_texture.is_valid()) {
padded_texture.instantiate();
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();

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->set_image(image);
padded_texture->connect_changed(callable_mp(this, &TileSetAtlasSource::_queue_update_padded_texture));
emit_changed();
}

Expand Down
3 changes: 2 additions & 1 deletion scene/resources/tile_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,10 @@ class TileSetAtlasSource : public TileSetSource {
void _create_coords_mapping_cache(Vector2i p_atlas_coords);

bool use_texture_padding = true;
Ref<ImageTexture> padded_texture;
Ref<CanvasTexture> padded_texture;
bool padded_texture_needs_update = false;
void _queue_update_padded_texture();
Ref<ImageTexture> _create_padded_image_texture(const Ref<Texture2D> &p_source);
void _update_padded_texture();

protected:
Expand Down
Loading