Small fixes required to get platformer to work.
Added back CanvasItemMaterial
This commit is contained in:
parent
33c146adbc
commit
8ef1c41a4e
9 changed files with 333 additions and 12 deletions
|
@ -5288,6 +5288,7 @@ void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_de
|
|||
|
||||
if (particles->clear) {
|
||||
particles->cycle_number = 0;
|
||||
particles->random_seed = Math::rand();
|
||||
} else if (new_phase < particles->phase) {
|
||||
particles->cycle_number++;
|
||||
}
|
||||
|
@ -5298,6 +5299,8 @@ void RasterizerStorageGLES3::_particles_process(Particles *particles, float p_de
|
|||
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::DELTA, p_delta * particles->speed_scale);
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::CLEAR, particles->clear);
|
||||
glUniform1ui(shaders.particles.get_uniform_location(ParticlesShaderGLES3::RANDOM_SEED), particles->random_seed);
|
||||
|
||||
if (particles->use_local_coords)
|
||||
shaders.particles.set_uniform(ParticlesShaderGLES3::EMISSION_TRANSFORM, Transform());
|
||||
else
|
||||
|
@ -5353,6 +5356,33 @@ void RasterizerStorageGLES3::update_particles() {
|
|||
|
||||
Particles *particles = particle_update_list.first()->self();
|
||||
|
||||
if (particles->inactive && !particles->emitting) {
|
||||
|
||||
particle_update_list.remove(particle_update_list.first());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (particles->emitting) {
|
||||
if (particles->inactive) {
|
||||
//restart system from scratch
|
||||
particles->prev_ticks = 0;
|
||||
particles->phase = 0;
|
||||
particles->prev_phase = 0;
|
||||
particles->clear = true;
|
||||
particles->particle_valid_histories[0] = false;
|
||||
particles->particle_valid_histories[1] = false;
|
||||
}
|
||||
particles->inactive = false;
|
||||
particles->inactive_time = 0;
|
||||
} else {
|
||||
particles->inactive_time += particles->speed_scale * frame.delta;
|
||||
if (particles->inactive_time > particles->lifetime * 1.2) {
|
||||
particles->inactive = true;
|
||||
particle_update_list.remove(particle_update_list.first());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Material *material = material_owner.getornull(particles->process_material);
|
||||
if (!material || !material->shader || material->shader->mode != VS::SHADER_PARTICLES) {
|
||||
|
||||
|
|
|
@ -1033,6 +1033,8 @@ public:
|
|||
|
||||
struct Particles : public GeometryOwner {
|
||||
|
||||
bool inactive;
|
||||
float inactive_time;
|
||||
bool emitting;
|
||||
int amount;
|
||||
float lifetime;
|
||||
|
@ -1060,6 +1062,7 @@ public:
|
|||
float phase;
|
||||
float prev_phase;
|
||||
uint64_t prev_ticks;
|
||||
uint32_t random_seed;
|
||||
|
||||
uint32_t cycle_number;
|
||||
|
||||
|
@ -1088,6 +1091,7 @@ public:
|
|||
frame_remainder = 0;
|
||||
histories_enabled = false;
|
||||
speed_scale = 1.0;
|
||||
random_seed = 0;
|
||||
|
||||
custom_aabb = Rect3(Vector3(-4, -4, -4), Vector3(8, 8, 8));
|
||||
|
||||
|
@ -1098,6 +1102,8 @@ public:
|
|||
prev_ticks = 0;
|
||||
|
||||
clear = true;
|
||||
inactive = true;
|
||||
inactive_time = false;
|
||||
|
||||
glGenBuffers(2, particle_buffers);
|
||||
glGenVertexArrays(2, particle_vaos);
|
||||
|
|
|
@ -795,6 +795,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
|
|||
actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index";
|
||||
actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity";
|
||||
actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform";
|
||||
actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed";
|
||||
|
||||
actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
|
||||
actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
|
||||
|
|
|
@ -37,6 +37,7 @@ uniform bool clear;
|
|||
uniform uint cycle;
|
||||
uniform float lifetime;
|
||||
uniform mat4 emission_transform;
|
||||
uniform uint random_seed;
|
||||
|
||||
|
||||
out highp vec4 out_color; //tfb:
|
||||
|
@ -104,7 +105,9 @@ void main() {
|
|||
bool shader_active = velocity_active.a > 0.5;
|
||||
|
||||
if (system_phase > prev_system_phase) {
|
||||
if (prev_system_phase < restart_phase && system_phase >= restart_phase) {
|
||||
// restart_phase >= prev_system_phase is used so particles emit in the first frame they are processed
|
||||
|
||||
if (restart_phase >= prev_system_phase && restart_phase < system_phase ) {
|
||||
restart=true;
|
||||
#ifdef USE_FRACTIONAL_DELTA
|
||||
local_delta = (system_phase - restart_phase) * lifetime;
|
||||
|
@ -112,12 +115,12 @@ void main() {
|
|||
}
|
||||
|
||||
} else {
|
||||
if (prev_system_phase < restart_phase) {
|
||||
if (restart_phase >= prev_system_phase) {
|
||||
restart=true;
|
||||
#ifdef USE_FRACTIONAL_DELTA
|
||||
local_delta = (1.0 - restart_phase + system_phase) * lifetime;
|
||||
#endif
|
||||
} else if (system_phase >= restart_phase) {
|
||||
} else if (restart_phase < system_phase ) {
|
||||
restart=true;
|
||||
#ifdef USE_FRACTIONAL_DELTA
|
||||
local_delta = (system_phase - restart_phase) * lifetime;
|
||||
|
|
|
@ -39,6 +39,196 @@
|
|||
#include "scene/scene_string_names.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
Mutex *CanvasItemMaterial::material_mutex = NULL;
|
||||
SelfList<CanvasItemMaterial>::List CanvasItemMaterial::dirty_materials;
|
||||
Map<CanvasItemMaterial::MaterialKey, CanvasItemMaterial::ShaderData> CanvasItemMaterial::shader_map;
|
||||
|
||||
void CanvasItemMaterial::init_shaders() {
|
||||
|
||||
#ifndef NO_THREADS
|
||||
material_mutex = Mutex::create();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::finish_shaders() {
|
||||
|
||||
#ifndef NO_THREADS
|
||||
memdelete(material_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_update_shader() {
|
||||
|
||||
dirty_materials.remove(&element);
|
||||
|
||||
MaterialKey mk = _compute_key();
|
||||
if (mk.key == current_key.key)
|
||||
return; //no update required in the end
|
||||
|
||||
if (shader_map.has(current_key)) {
|
||||
shader_map[current_key].users--;
|
||||
if (shader_map[current_key].users == 0) {
|
||||
//deallocate shader, as it's no longer in use
|
||||
VS::get_singleton()->free(shader_map[current_key].shader);
|
||||
shader_map.erase(current_key);
|
||||
}
|
||||
}
|
||||
|
||||
current_key = mk;
|
||||
|
||||
if (shader_map.has(mk)) {
|
||||
|
||||
VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader);
|
||||
shader_map[mk].users++;
|
||||
return;
|
||||
}
|
||||
|
||||
//must create a shader!
|
||||
|
||||
String code = "shader_type canvas_item;\nrender_mode ";
|
||||
switch (blend_mode) {
|
||||
case BLEND_MODE_MIX: code += "blend_mix"; break;
|
||||
case BLEND_MODE_ADD: code += "blend_add"; break;
|
||||
case BLEND_MODE_SUB: code += "blend_sub"; break;
|
||||
case BLEND_MODE_MUL: code += "blend_mul"; break;
|
||||
case BLEND_MODE_PREMULT_ALPHA: code += "blend_premul_alpha"; break;
|
||||
}
|
||||
|
||||
switch (light_mode) {
|
||||
case LIGHT_MODE_NORMAL: break;
|
||||
case LIGHT_MODE_UNSHADED: code += "unshaded"; break;
|
||||
case LIGHT_MODE_LIGHT_ONLY: code += "light_only"; break;
|
||||
}
|
||||
code += ";\n"; //thats it.
|
||||
|
||||
ShaderData shader_data;
|
||||
shader_data.shader = VS::get_singleton()->shader_create();
|
||||
shader_data.users = 1;
|
||||
|
||||
VS::get_singleton()->shader_set_code(shader_data.shader, code);
|
||||
|
||||
shader_map[mk] = shader_data;
|
||||
|
||||
VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader);
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::flush_changes() {
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->lock();
|
||||
|
||||
while (dirty_materials.first()) {
|
||||
|
||||
dirty_materials.first()->self()->_update_shader();
|
||||
}
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->unlock();
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_queue_shader_change() {
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->lock();
|
||||
|
||||
if (!element.in_list()) {
|
||||
dirty_materials.add(&element);
|
||||
}
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->unlock();
|
||||
}
|
||||
|
||||
bool CanvasItemMaterial::_is_shader_dirty() const {
|
||||
|
||||
bool dirty = false;
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->lock();
|
||||
|
||||
dirty = element.in_list();
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->unlock();
|
||||
|
||||
return dirty;
|
||||
}
|
||||
void CanvasItemMaterial::set_blend_mode(BlendMode p_blend_mode) {
|
||||
|
||||
blend_mode = p_blend_mode;
|
||||
_queue_shader_change();
|
||||
}
|
||||
|
||||
CanvasItemMaterial::BlendMode CanvasItemMaterial::get_blend_mode() const {
|
||||
return blend_mode;
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::set_light_mode(LightMode p_light_mode) {
|
||||
|
||||
light_mode = p_light_mode;
|
||||
_queue_shader_change();
|
||||
}
|
||||
|
||||
CanvasItemMaterial::LightMode CanvasItemMaterial::get_light_mode() const {
|
||||
|
||||
return light_mode;
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_validate_property(PropertyInfo &property) const {
|
||||
}
|
||||
|
||||
void CanvasItemMaterial::_bind_methods() {
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &CanvasItemMaterial::set_blend_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_blend_mode"), &CanvasItemMaterial::get_blend_mode);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_light_mode", "light_mode"), &CanvasItemMaterial::set_light_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_light_mode"), &CanvasItemMaterial::get_light_mode);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,Premult Alpha"), "set_blend_mode", "get_blend_mode");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mode", PROPERTY_HINT_ENUM, "Normal,Unshaded,Light Only"), "set_light_mode", "get_light_mode");
|
||||
|
||||
BIND_CONSTANT(BLEND_MODE_MIX);
|
||||
BIND_CONSTANT(BLEND_MODE_ADD);
|
||||
BIND_CONSTANT(BLEND_MODE_SUB);
|
||||
BIND_CONSTANT(BLEND_MODE_MUL);
|
||||
BIND_CONSTANT(BLEND_MODE_PREMULT_ALPHA);
|
||||
BIND_CONSTANT(LIGHT_MODE_NORMAL);
|
||||
BIND_CONSTANT(LIGHT_MODE_UNSHADED);
|
||||
BIND_CONSTANT(LIGHT_MODE_LIGHT_ONLY);
|
||||
}
|
||||
|
||||
CanvasItemMaterial::CanvasItemMaterial()
|
||||
: element(this) {
|
||||
|
||||
blend_mode = BLEND_MODE_MIX;
|
||||
light_mode = LIGHT_MODE_NORMAL;
|
||||
|
||||
current_key.key = 0;
|
||||
current_key.invalid_key = 1;
|
||||
_queue_shader_change();
|
||||
}
|
||||
|
||||
CanvasItemMaterial::~CanvasItemMaterial() {
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->lock();
|
||||
|
||||
if (shader_map.has(current_key)) {
|
||||
shader_map[current_key].users--;
|
||||
if (shader_map[current_key].users == 0) {
|
||||
//deallocate shader, as it's no longer in use
|
||||
VS::get_singleton()->free(shader_map[current_key].shader);
|
||||
shader_map.erase(current_key);
|
||||
}
|
||||
|
||||
VS::get_singleton()->material_set_shader(_get_material(), RID());
|
||||
}
|
||||
|
||||
if (material_mutex)
|
||||
material_mutex->unlock();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CanvasItem::is_visible_in_tree() const {
|
||||
|
@ -665,7 +855,7 @@ bool CanvasItem::is_draw_behind_parent_enabled() const {
|
|||
return behind;
|
||||
}
|
||||
|
||||
void CanvasItem::set_material(const Ref<ShaderMaterial> &p_material) {
|
||||
void CanvasItem::set_material(const Ref<Material> &p_material) {
|
||||
|
||||
material = p_material;
|
||||
RID rid;
|
||||
|
@ -686,7 +876,7 @@ bool CanvasItem::get_use_parent_material() const {
|
|||
return use_parent_material;
|
||||
}
|
||||
|
||||
Ref<ShaderMaterial> CanvasItem::get_material() const {
|
||||
Ref<Material> CanvasItem::get_material() const {
|
||||
|
||||
return material;
|
||||
}
|
||||
|
@ -788,8 +978,8 @@ void CanvasItem::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d);
|
||||
//ClassDB::bind_method(D_METHOD("get_viewport"),&CanvasItem::get_viewport);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_material", "material:ShaderMaterial"), &CanvasItem::set_material);
|
||||
ClassDB::bind_method(D_METHOD("get_material:ShaderMaterial"), &CanvasItem::get_material);
|
||||
ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &CanvasItem::set_material);
|
||||
ClassDB::bind_method(D_METHOD("get_material:Material"), &CanvasItem::get_material);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_use_parent_material", "enable"), &CanvasItem::set_use_parent_material);
|
||||
ClassDB::bind_method(D_METHOD("get_use_parent_material"), &CanvasItem::get_use_parent_material);
|
||||
|
@ -815,7 +1005,7 @@ void CanvasItem::_bind_methods() {
|
|||
ADD_PROPERTYNO(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask");
|
||||
|
||||
ADD_GROUP("Material", "");
|
||||
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial"), "set_material", "get_material");
|
||||
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,CanvasItemMaterial"), "set_material", "get_material");
|
||||
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "use_parent_material"), "set_use_parent_material", "get_use_parent_material");
|
||||
//exporting these two things doesn't really make much sense i think
|
||||
//ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), "set_as_toplevel","is_set_as_toplevel") ;
|
||||
|
|
|
@ -42,6 +42,92 @@ class Font;
|
|||
|
||||
class StyleBox;
|
||||
|
||||
class CanvasItemMaterial : public Material {
|
||||
|
||||
GDCLASS(CanvasItemMaterial, Material)
|
||||
|
||||
public:
|
||||
enum BlendMode {
|
||||
BLEND_MODE_MIX,
|
||||
BLEND_MODE_ADD,
|
||||
BLEND_MODE_SUB,
|
||||
BLEND_MODE_MUL,
|
||||
BLEND_MODE_PREMULT_ALPHA
|
||||
};
|
||||
|
||||
enum LightMode {
|
||||
LIGHT_MODE_NORMAL,
|
||||
LIGHT_MODE_UNSHADED,
|
||||
LIGHT_MODE_LIGHT_ONLY
|
||||
};
|
||||
|
||||
private:
|
||||
union MaterialKey {
|
||||
|
||||
struct {
|
||||
uint32_t blend_mode : 4;
|
||||
uint32_t light_mode : 4;
|
||||
uint32_t invalid_key : 1;
|
||||
};
|
||||
|
||||
uint32_t key;
|
||||
|
||||
bool operator<(const MaterialKey &p_key) const {
|
||||
return key < p_key.key;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderData {
|
||||
RID shader;
|
||||
int users;
|
||||
};
|
||||
|
||||
static Map<MaterialKey, ShaderData> shader_map;
|
||||
|
||||
MaterialKey current_key;
|
||||
|
||||
_FORCE_INLINE_ MaterialKey _compute_key() const {
|
||||
|
||||
MaterialKey mk;
|
||||
mk.key = 0;
|
||||
mk.blend_mode = blend_mode;
|
||||
mk.light_mode = light_mode;
|
||||
return mk;
|
||||
}
|
||||
|
||||
static Mutex *material_mutex;
|
||||
static SelfList<CanvasItemMaterial>::List dirty_materials;
|
||||
SelfList<CanvasItemMaterial> element;
|
||||
|
||||
void _update_shader();
|
||||
_FORCE_INLINE_ void _queue_shader_change();
|
||||
_FORCE_INLINE_ bool _is_shader_dirty() const;
|
||||
|
||||
BlendMode blend_mode;
|
||||
LightMode light_mode;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _validate_property(PropertyInfo &property) const;
|
||||
|
||||
public:
|
||||
void set_blend_mode(BlendMode p_blend_mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
|
||||
void set_light_mode(LightMode p_light_mode);
|
||||
LightMode get_light_mode() const;
|
||||
|
||||
static void init_shaders();
|
||||
static void finish_shaders();
|
||||
static void flush_changes();
|
||||
|
||||
CanvasItemMaterial();
|
||||
virtual ~CanvasItemMaterial();
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(CanvasItemMaterial::BlendMode)
|
||||
VARIANT_ENUM_CAST(CanvasItemMaterial::LightMode)
|
||||
|
||||
class CanvasItem : public Node {
|
||||
|
||||
GDCLASS(CanvasItem, Node);
|
||||
|
@ -83,7 +169,7 @@ private:
|
|||
bool notify_local_transform;
|
||||
bool notify_transform;
|
||||
|
||||
Ref<ShaderMaterial> material;
|
||||
Ref<Material> material;
|
||||
|
||||
mutable Transform2D global_transform;
|
||||
mutable bool global_invalid;
|
||||
|
@ -203,8 +289,8 @@ public:
|
|||
RID get_canvas() const;
|
||||
Ref<World2D> get_world_2d() const;
|
||||
|
||||
void set_material(const Ref<ShaderMaterial> &p_material);
|
||||
Ref<ShaderMaterial> get_material() const;
|
||||
void set_material(const Ref<Material> &p_material);
|
||||
Ref<Material> get_material() const;
|
||||
|
||||
void set_use_parent_material(bool p_use_parent_material);
|
||||
bool get_use_parent_material() const;
|
||||
|
|
|
@ -571,7 +571,7 @@ void ParticlesMaterial::_update_shader() {
|
|||
code += "\n";
|
||||
|
||||
code += " uint base_number=NUMBER/uint(trail_divisor);\n";
|
||||
code += " uint alt_seed=hash(base_number+uint(1));\n";
|
||||
code += " uint alt_seed=hash(base_number+uint(1)+RANDOM_SEED);\n";
|
||||
code += " float angle_rand=rand_from_seed(alt_seed);\n";
|
||||
code += " float scale_rand=rand_from_seed(alt_seed);\n";
|
||||
code += " float hue_rot_rand=rand_from_seed(alt_seed);\n";
|
||||
|
|
|
@ -469,6 +469,9 @@ void register_scene_types() {
|
|||
ClassDB::register_class<Shader>();
|
||||
ClassDB::register_class<ShaderMaterial>();
|
||||
ClassDB::register_virtual_class<CanvasItem>();
|
||||
ClassDB::register_class<CanvasItemMaterial>();
|
||||
SceneTree::add_idle_callback(CanvasItemMaterial::flush_changes);
|
||||
CanvasItemMaterial::init_shaders();
|
||||
ClassDB::register_class<Node2D>();
|
||||
ClassDB::register_class<Particles2D>();
|
||||
//ClassDB::register_class<ParticleAttractor2D>();
|
||||
|
@ -663,5 +666,6 @@ void unregister_scene_types() {
|
|||
|
||||
SpatialMaterial::finish_shaders();
|
||||
ParticlesMaterial::finish_shaders();
|
||||
CanvasItemMaterial::finish_shaders();
|
||||
SceneStringNames::free();
|
||||
}
|
||||
|
|
|
@ -212,6 +212,7 @@ ShaderTypes::ShaderTypes() {
|
|||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["NUMBER"] = ShaderLanguage::TYPE_UINT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"] = ShaderLanguage::TYPE_INT;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["EMISSION_TRANSFORM"] = ShaderLanguage::TYPE_MAT4;
|
||||
shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RANDOM_SEED"] = ShaderLanguage::TYPE_UINT;
|
||||
|
||||
shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard");
|
||||
shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force");
|
||||
|
|
Loading…
Reference in a new issue