Skip to content

Commit 8330368

Browse files
committed
Add custom shader support to SpriteBase3D
1 parent 5cfa89e commit 8330368

File tree

3 files changed

+85
-29
lines changed

3 files changed

+85
-29
lines changed

scene/3d/sprite_3d.cpp

Lines changed: 78 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ void SpriteBase3D::_notification(int p_what) {
8787
}
8888
}
8989

90+
void SpriteBase3D::_validate_property(PropertyInfo &p_property) const {
91+
if (get_material_override().is_valid()) {
92+
if (p_property.name == "billboard" || p_property.name == "transparent" || p_property.name == "shaded" || p_property.name == "double_sided" || p_property.name == "no_depth_test" || p_property.name == "fixed_size" || p_property.name == "alpha_cut" || p_property.name == "alpha_scissor_threshold" || p_property.name == "alpha_hash_scale" || p_property.name == "alpha_antialiasing_mode" || p_property.name == "alpha_antialiasing_edge" || p_property.name == "texture_filter" || p_property.name == "render_priority") {
93+
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
94+
}
95+
}
96+
}
97+
9098
void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect, Rect2 p_src_rect) {
9199
ERR_FAIL_COND(p_texture.is_null());
92100

@@ -250,38 +258,46 @@ void SpriteBase3D::draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect,
250258
RS::get_singleton()->mesh_set_custom_aabb(mesh_new, aabb_new);
251259
set_aabb(aabb_new);
252260

253-
RS::get_singleton()->material_set_param(get_material(), "alpha_scissor_threshold", alpha_scissor_threshold);
254-
RS::get_singleton()->material_set_param(get_material(), "alpha_hash_scale", alpha_hash_scale);
255-
RS::get_singleton()->material_set_param(get_material(), "alpha_antialiasing_edge", alpha_antialiasing_edge);
256-
257-
BaseMaterial3D::Transparency mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_DISABLED;
258-
if (get_draw_flag(FLAG_TRANSPARENT)) {
259-
if (get_alpha_cut_mode() == ALPHA_CUT_DISCARD) {
260-
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_SCISSOR;
261-
} else if (get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS) {
262-
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS;
263-
} else if (get_alpha_cut_mode() == ALPHA_CUT_HASH) {
264-
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_HASH;
265-
} else {
266-
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA;
261+
if (get_material_override().is_null()) {
262+
RS::get_singleton()->material_set_param(get_material(), "alpha_scissor_threshold", alpha_scissor_threshold);
263+
RS::get_singleton()->material_set_param(get_material(), "alpha_hash_scale", alpha_hash_scale);
264+
RS::get_singleton()->material_set_param(get_material(), "alpha_antialiasing_edge", alpha_antialiasing_edge);
265+
266+
BaseMaterial3D::Transparency mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_DISABLED;
267+
if (get_draw_flag(FLAG_TRANSPARENT)) {
268+
if (get_alpha_cut_mode() == ALPHA_CUT_DISCARD) {
269+
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_SCISSOR;
270+
} else if (get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS) {
271+
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_DEPTH_PRE_PASS;
272+
} else if (get_alpha_cut_mode() == ALPHA_CUT_HASH) {
273+
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA_HASH;
274+
} else {
275+
mat_transparency = BaseMaterial3D::Transparency::TRANSPARENCY_ALPHA;
276+
}
267277
}
268-
}
269278

270-
RID shader_rid;
271-
StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), alpha_antialiasing_mode, &shader_rid);
279+
RID shader_rid;
280+
StandardMaterial3D::get_material_for_2d(get_draw_flag(FLAG_SHADED), mat_transparency, get_draw_flag(FLAG_DOUBLE_SIDED), get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y, false, get_draw_flag(FLAG_DISABLE_DEPTH_TEST), get_draw_flag(FLAG_FIXED_SIZE), get_texture_filter(), alpha_antialiasing_mode, &shader_rid);
272281

273-
if (last_shader != shader_rid) {
274-
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
275-
last_shader = shader_rid;
276-
}
277-
if (last_texture != p_texture->get_rid()) {
278-
RS::get_singleton()->material_set_param(get_material(), "texture_albedo", p_texture->get_rid());
279-
RS::get_singleton()->material_set_param(get_material(), "albedo_texture_size", Vector2i(p_texture->get_width(), p_texture->get_height()));
280-
last_texture = p_texture->get_rid();
281-
}
282-
if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) {
283-
RS::get_singleton()->material_set_render_priority(get_material(), get_render_priority());
284-
RS::get_singleton()->mesh_surface_set_material(mesh, 0, get_material());
282+
if (last_shader != shader_rid) {
283+
RS::get_singleton()->material_set_shader(get_material(), shader_rid);
284+
last_shader = shader_rid;
285+
}
286+
if (last_texture != p_texture->get_rid()) {
287+
RS::get_singleton()->material_set_param(get_material(), "texture_albedo", p_texture->get_rid());
288+
RS::get_singleton()->material_set_param(get_material(), "albedo_texture_size", Vector2i(p_texture->get_width(), p_texture->get_height()));
289+
last_texture = p_texture->get_rid();
290+
}
291+
if (get_alpha_cut_mode() == ALPHA_CUT_DISABLED) {
292+
RS::get_singleton()->material_set_render_priority(get_material(), get_render_priority());
293+
RS::get_singleton()->mesh_surface_set_material(mesh, 0, get_material());
294+
}
295+
} else {
296+
if (last_texture != p_texture->get_rid()) {
297+
RS::get_singleton()->material_set_param(get_material_override()->get_rid(), "texture_albedo", p_texture->get_rid());
298+
RS::get_singleton()->material_set_param(get_material_override()->get_rid(), "albedo_texture_size", Vector2i(p_texture->get_width(), p_texture->get_height()));
299+
last_texture = p_texture->get_rid();
300+
}
285301
}
286302
}
287303

@@ -477,6 +493,37 @@ Ref<TriangleMesh> SpriteBase3D::generate_triangle_mesh() const {
477493
return triangle_mesh;
478494
}
479495

496+
PackedStringArray SpriteBase3D::get_configuration_warnings() const {
497+
PackedStringArray warnings = GeometryInstance3D::get_configuration_warnings();
498+
Ref<Material> mat_override = get_material_override();
499+
if (mat_override.is_valid()) {
500+
RID shader = mat_override->get_shader_rid();
501+
if (shader.is_null()) {
502+
warnings.push_back(RTR("Material Override must be assigned a shader in order to work correctly."));
503+
} else {
504+
List<PropertyInfo> parameters;
505+
RS::get_singleton()->get_shader_parameter_list(shader, &parameters);
506+
bool found_texture_albedo = false;
507+
bool found_albedo_texture_size = false;
508+
for (const PropertyInfo &parameter : parameters) {
509+
if (!found_texture_albedo && parameter.name == "texture_albedo" && parameter.type == Variant::OBJECT && parameter.hint_string == "Texture2D") {
510+
found_texture_albedo = true;
511+
} else if (!found_albedo_texture_size && parameter.name == "albedo_texture_size" && parameter.type == Variant::VECTOR2I) {
512+
found_albedo_texture_size = true;
513+
}
514+
}
515+
516+
if (!found_texture_albedo) {
517+
warnings.push_back(RTR("Sprite shaders must contain uniform \"texture_albedo\" of type: sampler2D."));
518+
}
519+
if (!found_albedo_texture_size) {
520+
warnings.push_back(RTR("Sprite shaders must contain uniform \"albedo_texture_size\" of type: ivec2."));
521+
}
522+
}
523+
}
524+
return warnings;
525+
}
526+
480527
void SpriteBase3D::set_draw_flag(DrawFlags p_flag, bool p_enable) {
481528
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
482529

@@ -747,6 +794,8 @@ SpriteBase3D::SpriteBase3D() {
747794
RS::get_singleton()->mesh_surface_make_offsets_from_format(sd.format, sd.vertex_count, sd.index_count, mesh_surface_offsets, vertex_stride, normal_tangent_stride, attrib_stride, skin_stride);
748795
RS::get_singleton()->mesh_add_surface(mesh, sd);
749796
set_base(mesh);
797+
798+
connect(CoreStringName(property_list_changed), callable_mp((Node *)this, &Node::update_configuration_warnings));
750799
}
751800

752801
SpriteBase3D::~SpriteBase3D() {

scene/3d/sprite_3d.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class SpriteBase3D : public GeometryInstance3D {
103103
void _notification(int p_what);
104104
static void _bind_methods();
105105
virtual void _draw() = 0;
106+
void _validate_property(PropertyInfo &p_property) const;
106107
void draw_texture_rect(Ref<Texture2D> p_texture, Rect2 p_dst_rect, Rect2 p_src_rect);
107108
_FORCE_INLINE_ void set_aabb(const AABB &p_aabb) { aabb = p_aabb; }
108109
_FORCE_INLINE_ RID &get_mesh() { return mesh; }
@@ -173,6 +174,7 @@ class SpriteBase3D : public GeometryInstance3D {
173174
virtual AABB get_aabb() const override;
174175

175176
virtual Ref<TriangleMesh> generate_triangle_mesh() const override;
177+
virtual PackedStringArray get_configuration_warnings() const override;
176178

177179
SpriteBase3D();
178180
~SpriteBase3D();

scene/3d/visual_instance_3d.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ VisualInstance3D::~VisualInstance3D() {
224224
}
225225

226226
void GeometryInstance3D::set_material_override(const Ref<Material> &p_material) {
227+
bool changed = material_override != p_material;
227228
if (material_override.is_valid()) {
228229
material_override->disconnect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
229230
}
@@ -232,6 +233,10 @@ void GeometryInstance3D::set_material_override(const Ref<Material> &p_material)
232233
material_override->connect(CoreStringName(property_list_changed), callable_mp((Object *)this, &Object::notify_property_list_changed));
233234
}
234235
RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID());
236+
if (changed) {
237+
notify_property_list_changed();
238+
update_configuration_warnings();
239+
}
235240
}
236241

237242
Ref<Material> GeometryInstance3D::get_material_override() const {

0 commit comments

Comments
 (0)