Small fixes required to get platformer to work.

Added back CanvasItemMaterial
This commit is contained in:
Juan Linietsky 2017-06-23 14:31:21 -03:00
parent 33c146adbc
commit 8ef1c41a4e
9 changed files with 333 additions and 12 deletions

View file

@ -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) {

View file

@ -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);

View file

@ -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";

View file

@ -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;

View file

@ -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") ;

View file

@ -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;

View file

@ -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";

View file

@ -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();
}

View file

@ -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");