ソースを参照

Merge pull request #30635 from KoBeWi/billbo_3dns

Add a Billboard property for Sprite3D
Rémi Verschelde 6 年 前
コミット
9762372329
4 ファイル変更34 行追加7 行削除
  1. 19 2
      scene/3d/sprite_3d.cpp
  2. 3 0
      scene/3d/sprite_3d.h
  3. 10 1
      scene/resources/material.cpp
  4. 2 4
      scene/resources/material.h

+ 19 - 2
scene/3d/sprite_3d.cpp

@@ -286,6 +286,18 @@ SpriteBase3D::AlphaCutMode SpriteBase3D::get_alpha_cut_mode() const {
 	return alpha_cut;
 	return alpha_cut;
 }
 }
 
 
+void SpriteBase3D::set_billboard_mode(SpatialMaterial::BillboardMode p_mode) {
+
+	ERR_FAIL_INDEX(p_mode, 3);
+	billboard_mode = p_mode;
+	_queue_update();
+}
+
+SpatialMaterial::BillboardMode SpriteBase3D::get_billboard_mode() const {
+
+	return billboard_mode;
+}
+
 void SpriteBase3D::_bind_methods() {
 void SpriteBase3D::_bind_methods() {
 
 
 	ClassDB::bind_method(D_METHOD("set_centered", "centered"), &SpriteBase3D::set_centered);
 	ClassDB::bind_method(D_METHOD("set_centered", "centered"), &SpriteBase3D::set_centered);
@@ -318,6 +330,9 @@ void SpriteBase3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("set_alpha_cut_mode", "mode"), &SpriteBase3D::set_alpha_cut_mode);
 	ClassDB::bind_method(D_METHOD("set_alpha_cut_mode", "mode"), &SpriteBase3D::set_alpha_cut_mode);
 	ClassDB::bind_method(D_METHOD("get_alpha_cut_mode"), &SpriteBase3D::get_alpha_cut_mode);
 	ClassDB::bind_method(D_METHOD("get_alpha_cut_mode"), &SpriteBase3D::get_alpha_cut_mode);
 
 
+	ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpriteBase3D::set_billboard_mode);
+	ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpriteBase3D::get_billboard_mode);
+
 	ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
 	ClassDB::bind_method(D_METHOD("get_item_rect"), &SpriteBase3D::get_item_rect);
 	ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
 	ClassDB::bind_method(D_METHOD("generate_triangle_mesh"), &SpriteBase3D::generate_triangle_mesh);
 
 
@@ -333,6 +348,7 @@ void SpriteBase3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001"), "set_pixel_size", "get_pixel_size");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X-Axis,Y-Axis,Z-Axis"), "set_axis", "get_axis");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "axis", PROPERTY_HINT_ENUM, "X-Axis,Y-Axis,Z-Axis"), "set_axis", "get_axis");
 	ADD_GROUP("Flags", "");
 	ADD_GROUP("Flags", "");
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "billboard", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard"), "set_billboard_mode", "get_billboard_mode");
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_draw_flag", "get_draw_flag", FLAG_TRANSPARENT);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "shaded"), "set_draw_flag", "get_draw_flag", FLAG_SHADED);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "double_sided"), "set_draw_flag", "get_draw_flag", FLAG_DOUBLE_SIDED);
@@ -361,6 +377,7 @@ SpriteBase3D::SpriteBase3D() {
 		flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
 		flags[i] = i == FLAG_TRANSPARENT || i == FLAG_DOUBLE_SIDED;
 
 
 	alpha_cut = ALPHA_CUT_DISABLED;
 	alpha_cut = ALPHA_CUT_DISABLED;
+	billboard_mode = SpatialMaterial::BILLBOARD_DISABLED;
 	axis = Vector3::AXIS_Z;
 	axis = Vector3::AXIS_Z;
 	pixel_size = 0.01;
 	pixel_size = 0.01;
 	modulate = Color(1, 1, 1, 1);
 	modulate = Color(1, 1, 1, 1);
@@ -463,7 +480,7 @@ void Sprite3D::_draw() {
 		tangent = Plane(1, 0, 0, 1);
 		tangent = Plane(1, 0, 0, 1);
 	}
 	}
 
 
-	RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
+	RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
 	VS::get_singleton()->immediate_set_material(immediate, mat);
 	VS::get_singleton()->immediate_set_material(immediate, mat);
 
 
 	VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
 	VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLE_FAN, texture->get_rid());
@@ -788,7 +805,7 @@ void AnimatedSprite3D::_draw() {
 		tangent = Plane(1, 0, 0, -1);
 		tangent = Plane(1, 0, 0, -1);
 	}
 	}
 
 
-	RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS);
+	RID mat = SpatialMaterial::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == SpatialMaterial::BILLBOARD_ENABLED, get_billboard_mode() == SpatialMaterial::BILLBOARD_FIXED_Y);
 
 
 	VS::get_singleton()->immediate_set_material(immediate, mat);
 	VS::get_singleton()->immediate_set_material(immediate, mat);
 
 

+ 3 - 0
scene/3d/sprite_3d.h

@@ -80,6 +80,7 @@ private:
 
 
 	bool flags[FLAG_MAX];
 	bool flags[FLAG_MAX];
 	AlphaCutMode alpha_cut;
 	AlphaCutMode alpha_cut;
+	SpatialMaterial::BillboardMode billboard_mode;
 	bool pending_update;
 	bool pending_update;
 	void _im_update();
 	void _im_update();
 
 
@@ -130,6 +131,8 @@ public:
 
 
 	void set_alpha_cut_mode(AlphaCutMode p_mode);
 	void set_alpha_cut_mode(AlphaCutMode p_mode);
 	AlphaCutMode get_alpha_cut_mode() const;
 	AlphaCutMode get_alpha_cut_mode() const;
+	void set_billboard_mode(SpatialMaterial::BillboardMode p_mode);
+	SpatialMaterial::BillboardMode get_billboard_mode() const;
 
 
 	virtual Rect2 get_item_rect() const = 0;
 	virtual Rect2 get_item_rect() const = 0;
 
 

+ 10 - 1
scene/resources/material.cpp

@@ -1772,7 +1772,7 @@ SpatialMaterial::TextureChannel SpatialMaterial::get_refraction_texture_channel(
 	return refraction_texture_channel;
 	return refraction_texture_channel;
 }
 }
 
 
-RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass) {
+RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard, bool p_billboard_y) {
 
 
 	int version = 0;
 	int version = 0;
 	if (p_shaded)
 	if (p_shaded)
@@ -1785,6 +1785,10 @@ RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent,
 		version |= 8;
 		version |= 8;
 	if (p_double_sided)
 	if (p_double_sided)
 		version |= 16;
 		version |= 16;
+	if (p_billboard)
+		version |= 32;
+	if (p_billboard_y)
+		version |= 64;
 
 
 	if (materials_for_2d[version].is_valid()) {
 	if (materials_for_2d[version].is_valid()) {
 		return materials_for_2d[version]->get_rid();
 		return materials_for_2d[version]->get_rid();
@@ -1800,6 +1804,11 @@ RID SpatialMaterial::get_material_rid_for_2d(bool p_shaded, bool p_transparent,
 	material->set_flag(FLAG_SRGB_VERTEX_COLOR, true);
 	material->set_flag(FLAG_SRGB_VERTEX_COLOR, true);
 	material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
 	material->set_flag(FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
 	material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha);
 	material->set_flag(FLAG_USE_ALPHA_SCISSOR, p_cut_alpha);
+	if (p_billboard) {
+		material->set_billboard_mode(BILLBOARD_ENABLED);
+	} else if (p_billboard_y) {
+		material->set_billboard_mode(BILLBOARD_FIXED_Y);
+	}
 
 
 	materials_for_2d[version] = material;
 	materials_for_2d[version] = material;
 
 

+ 2 - 4
scene/resources/material.h

@@ -437,9 +437,7 @@ private:
 
 
 	_FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const;
 	_FORCE_INLINE_ void _validate_feature(const String &text, Feature feature, PropertyInfo &property) const;
 
 
-	enum {
-		MAX_MATERIALS_FOR_2D = 32
-	};
+	static const int MAX_MATERIALS_FOR_2D = 128;
 
 
 	static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff
 	static Ref<SpatialMaterial> materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff
 
 
@@ -626,7 +624,7 @@ public:
 	static void finish_shaders();
 	static void finish_shaders();
 	static void flush_changes();
 	static void flush_changes();
 
 
-	static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass);
+	static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass, bool p_billboard = false, bool p_billboard_y = false);
 
 
 	RID get_shader_rid() const;
 	RID get_shader_rid() const;