summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp30
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp241
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h11
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp1
-rw-r--r--drivers/gles3/shaders/scene.glsl56
-rw-r--r--editor/editor_node.cpp51
-rw-r--r--editor/editor_node.h9
-rw-r--r--editor/editor_settings.cpp5
-rw-r--r--platform/javascript/SCsub6
-rw-r--r--platform/javascript/detect.py3
-rw-r--r--platform/javascript/power_javascript.cpp2
-rw-r--r--platform/javascript/power_javascript.h2
-rw-r--r--scene/2d/screen_button.cpp23
-rw-r--r--scene/2d/screen_button.h1
-rw-r--r--scene/gui/dialogs.cpp14
-rw-r--r--scene/main/node.cpp7
-rw-r--r--scene/resources/packed_scene.cpp25
-rw-r--r--scene/resources/packed_scene.h2
-rw-r--r--scene/resources/shader_graph.cpp2
-rw-r--r--servers/visual/shader_types.cpp4
20 files changed, 325 insertions, 170 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index b5d58ee997..d3936801dd 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1528,7 +1528,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
GIProbeInstance *gipi = gi_probe_instance_owner.getptr(ridp[0]);
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 10);
glBindTexture(GL_TEXTURE_3D, gipi->tex_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM1, gipi->transform_to_data * p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS1, gipi->bounds);
@@ -1540,7 +1540,7 @@ void RasterizerSceneGLES3::_setup_light(RenderList::Element *e, const Transform
GIProbeInstance *gipi2 = gi_probe_instance_owner.getptr(ridp[1]);
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 7);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 11);
glBindTexture(GL_TEXTURE_3D, gipi2->tex_cache);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_XFORM2, gipi2->transform_to_data * p_view_transform);
state.scene_shader.set_uniform(SceneShaderGLES3::GI_PROBE_BOUNDS2, gipi2->bounds);
@@ -1804,24 +1804,26 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
}
}
+
+
+ if ((prev_base_type == VS::INSTANCE_MULTIMESH) != (e->instance->base_type == VS::INSTANCE_MULTIMESH)) {
+ state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, e->instance->base_type == VS::INSTANCE_MULTIMESH);
+ rebind = true;
+ }
+
if (prev_skeleton != skeleton) {
if (prev_skeleton.is_valid() != skeleton.is_valid()) {
state.scene_shader.set_conditional(SceneShaderGLES3::USE_SKELETON, skeleton.is_valid());
rebind = true;
}
+
if (skeleton.is_valid()) {
RasterizerStorageGLES3::Skeleton *sk = storage->skeleton_owner.getornull(skeleton);
- if (sk->size) {
- glBindBufferBase(GL_UNIFORM_BUFFER, 7, sk->ubo);
- }
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6);
+ glBindTexture(GL_TEXTURE_2D,sk->texture);
}
}
- if ((prev_base_type == VS::INSTANCE_MULTIMESH) != (e->instance->base_type == VS::INSTANCE_MULTIMESH)) {
- state.scene_shader.set_conditional(SceneShaderGLES3::USE_INSTANCING, e->instance->base_type == VS::INSTANCE_MULTIMESH);
- rebind = true;
- }
-
if (material != prev_material || rebind) {
storage->info.render_material_switch_count++;
@@ -1833,6 +1835,8 @@ void RasterizerSceneGLES3::_render_list(RenderList::Element **p_elements, int p_
}
}
+
+
if (!(e->sort_key & RenderList::SORT_KEY_UNSHADED_FLAG) && !p_directional_add && !p_shadow) {
_setup_light(e, p_view_transform);
}
@@ -3567,7 +3571,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//bind depth for read
- glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 8);
+ glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 9);
glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->depth);
}
@@ -4515,8 +4519,8 @@ void RasterizerSceneGLES3::initialize() {
glGenTextures(1, &directional_shadow.depth);
glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index ed4be1cb3d..526b4ab9ce 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -3038,7 +3038,7 @@ Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
int sbs = sk->size;
ERR_CONTINUE(bs > sbs);
- float *skb = sk->bones.ptr();
+ const float *texture = sk->skel_texture.ptr();
bool first = true;
if (sk->use_2d) {
@@ -3047,16 +3047,18 @@ Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
if (!skused[j])
continue;
- float *dataptr = &skb[8 * j];
+
+ int base_ofs = ((j / 256) * 256) * 2 * 4 + (j % 256) * 4;
Transform mtx;
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.origin[0] = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.origin[1] = dataptr[7];
+ mtx.basis[0].x=texture[base_ofs+0];
+ mtx.basis[0].y=texture[base_ofs+1];
+ mtx.origin.x=texture[base_ofs+3];
+ base_ofs+=256*4;
+ mtx.basis[1].x=texture[base_ofs+0];
+ mtx.basis[1].y=texture[base_ofs+1];
+ mtx.origin.y=texture[base_ofs+3];
Rect3 baabb = mtx.xform(skbones[j]);
if (first) {
@@ -3072,21 +3074,24 @@ Rect3 RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
if (!skused[j])
continue;
- float *dataptr = &skb[12 * j];
+ int base_ofs = ((j / 256) * 256) * 3 * 4 + (j % 256) * 4;
Transform mtx;
- mtx.basis.elements[0][0] = dataptr[0];
- mtx.basis.elements[0][1] = dataptr[1];
- mtx.basis.elements[0][2] = dataptr[2];
- mtx.origin.x = dataptr[3];
- mtx.basis.elements[1][0] = dataptr[4];
- mtx.basis.elements[1][1] = dataptr[5];
- mtx.basis.elements[1][2] = dataptr[6];
- mtx.origin.y = dataptr[7];
- mtx.basis.elements[2][0] = dataptr[8];
- mtx.basis.elements[2][1] = dataptr[9];
- mtx.basis.elements[2][2] = dataptr[10];
- mtx.origin.z = dataptr[11];
+
+ mtx.basis[0].x=texture[base_ofs+0];
+ mtx.basis[0].y=texture[base_ofs+1];
+ mtx.basis[0].z=texture[base_ofs+2];
+ mtx.origin.x=texture[base_ofs+3];
+ base_ofs+=256*4;
+ mtx.basis[1].x=texture[base_ofs+0];
+ mtx.basis[1].y=texture[base_ofs+1];
+ mtx.basis[1].z=texture[base_ofs+2];
+ mtx.origin.y=texture[base_ofs+3];
+ base_ofs+=256*4;
+ mtx.basis[2].x=texture[base_ofs+0];
+ mtx.basis[2].y=texture[base_ofs+1];
+ mtx.basis[2].z=texture[base_ofs+2];
+ mtx.origin.z=texture[base_ofs+3];
Rect3 baabb = mtx.xform(skbones[j]);
if (first) {
@@ -3921,6 +3926,9 @@ RID RasterizerStorageGLES3::immediate_get_material(RID p_immediate) const {
RID RasterizerStorageGLES3::skeleton_create() {
Skeleton *skeleton = memnew(Skeleton);
+
+ glGenTextures(1,&skeleton->texture);
+
return skeleton_owner.make_rid(skeleton);
}
@@ -3933,49 +3941,28 @@ void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton, int p_bones, bool
if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton)
return;
- if (skeleton->ubo) {
- glDeleteBuffers(1, &skeleton->ubo);
- skeleton->ubo = 0;
- }
-
- skeleton->size = p_bones;
- if (p_2d_skeleton) {
- skeleton->bones.resize(p_bones * 8);
- for (int i = 0; i < skeleton->bones.size(); i += 8) {
- skeleton->bones[i + 0] = 1;
- skeleton->bones[i + 1] = 0;
- skeleton->bones[i + 2] = 0;
- skeleton->bones[i + 3] = 0;
- skeleton->bones[i + 4] = 0;
- skeleton->bones[i + 5] = 1;
- skeleton->bones[i + 6] = 0;
- skeleton->bones[i + 7] = 0;
- }
+ skeleton->size=p_bones;
+ skeleton->use_2d=p_2d_skeleton;
+ int height = p_bones/256;
+ if (p_bones%256)
+ height++;
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D,skeleton->texture);
+
+ if (skeleton->use_2d) {
+ skeleton->skel_texture.resize(256*height*2*4);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height*2, 0, GL_RGBA, GL_FLOAT, NULL);
} else {
- skeleton->bones.resize(p_bones * 12);
- for (int i = 0; i < skeleton->bones.size(); i += 12) {
- skeleton->bones[i + 0] = 1;
- skeleton->bones[i + 1] = 0;
- skeleton->bones[i + 2] = 0;
- skeleton->bones[i + 3] = 0;
- skeleton->bones[i + 4] = 0;
- skeleton->bones[i + 5] = 1;
- skeleton->bones[i + 6] = 0;
- skeleton->bones[i + 7] = 0;
- skeleton->bones[i + 8] = 0;
- skeleton->bones[i + 9] = 0;
- skeleton->bones[i + 10] = 1;
- skeleton->bones[i + 11] = 0;
- }
+ skeleton->skel_texture.resize(256*height*3*4);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 256, height*3, 0, GL_RGBA, GL_FLOAT, NULL);
}
- if (p_bones) {
- glGenBuffers(1, &skeleton->ubo);
- glBindBuffer(GL_UNIFORM_BUFFER, skeleton->ubo);
- glBufferData(GL_UNIFORM_BUFFER, skeleton->bones.size() * sizeof(float), NULL, GL_DYNAMIC_DRAW);
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
- }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list);
@@ -3997,19 +3984,25 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform(RID p_skeleton, int p_b
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(skeleton->use_2d);
- float *bones = skeleton->bones.ptr();
- bones[p_bone * 12 + 0] = p_transform.basis.elements[0][0];
- bones[p_bone * 12 + 1] = p_transform.basis.elements[0][1];
- bones[p_bone * 12 + 2] = p_transform.basis.elements[0][2];
- bones[p_bone * 12 + 3] = p_transform.origin.x;
- bones[p_bone * 12 + 4] = p_transform.basis.elements[1][0];
- bones[p_bone * 12 + 5] = p_transform.basis.elements[1][1];
- bones[p_bone * 12 + 6] = p_transform.basis.elements[1][2];
- bones[p_bone * 12 + 7] = p_transform.origin.y;
- bones[p_bone * 12 + 8] = p_transform.basis.elements[2][0];
- bones[p_bone * 12 + 9] = p_transform.basis.elements[2][1];
- bones[p_bone * 12 + 10] = p_transform.basis.elements[2][2];
- bones[p_bone * 12 + 11] = p_transform.origin.z;
+ float *texture = skeleton->skel_texture.ptr();
+
+ int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4;
+
+ texture[base_ofs+0]=p_transform.basis[0].x;
+ texture[base_ofs+1]=p_transform.basis[0].y;
+ texture[base_ofs+2]=p_transform.basis[0].z;
+ texture[base_ofs+3]=p_transform.origin.x;
+ base_ofs+=256*4;
+ texture[base_ofs+0]=p_transform.basis[1].x;
+ texture[base_ofs+1]=p_transform.basis[1].y;
+ texture[base_ofs+2]=p_transform.basis[1].z;
+ texture[base_ofs+3]=p_transform.origin.y;
+ base_ofs+=256*4;
+ texture[base_ofs+0]=p_transform.basis[2].x;
+ texture[base_ofs+1]=p_transform.basis[2].y;
+ texture[base_ofs+2]=p_transform.basis[2].z;
+ texture[base_ofs+3]=p_transform.origin.z;
+
if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list);
@@ -4024,22 +4017,30 @@ Transform RasterizerStorageGLES3::skeleton_bone_get_transform(RID p_skeleton, in
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform());
ERR_FAIL_COND_V(skeleton->use_2d, Transform());
- float *bones = skeleton->bones.ptr();
- Transform mtx;
- mtx.basis.elements[0][0] = bones[p_bone * 12 + 0];
- mtx.basis.elements[0][1] = bones[p_bone * 12 + 1];
- mtx.basis.elements[0][2] = bones[p_bone * 12 + 2];
- mtx.origin.x = bones[p_bone * 12 + 3];
- mtx.basis.elements[1][0] = bones[p_bone * 12 + 4];
- mtx.basis.elements[1][1] = bones[p_bone * 12 + 5];
- mtx.basis.elements[1][2] = bones[p_bone * 12 + 6];
- mtx.origin.y = bones[p_bone * 12 + 7];
- mtx.basis.elements[2][0] = bones[p_bone * 12 + 8];
- mtx.basis.elements[2][1] = bones[p_bone * 12 + 9];
- mtx.basis.elements[2][2] = bones[p_bone * 12 + 10];
- mtx.origin.z = bones[p_bone * 12 + 11];
-
- return mtx;
+ const float *texture = skeleton->skel_texture.ptr();
+
+ Transform ret;
+
+ int base_ofs = ((p_bone / 256) * 256) * 3 * 4 + (p_bone % 256) * 4;
+
+ ret.basis[0].x=texture[base_ofs+0];
+ ret.basis[0].y=texture[base_ofs+1];
+ ret.basis[0].z=texture[base_ofs+2];
+ ret.origin.x=texture[base_ofs+3];
+ base_ofs+=256*4;
+ ret.basis[1].x=texture[base_ofs+0];
+ ret.basis[1].y=texture[base_ofs+1];
+ ret.basis[1].z=texture[base_ofs+2];
+ ret.origin.y=texture[base_ofs+3];
+ base_ofs+=256*4;
+ ret.basis[2].x=texture[base_ofs+0];
+ ret.basis[2].y=texture[base_ofs+1];
+ ret.basis[2].z=texture[base_ofs+2];
+ ret.origin.z=texture[base_ofs+3];
+
+
+ return ret;
+
}
void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) {
@@ -4049,15 +4050,20 @@ void RasterizerStorageGLES3::skeleton_bone_set_transform_2d(RID p_skeleton, int
ERR_FAIL_INDEX(p_bone, skeleton->size);
ERR_FAIL_COND(!skeleton->use_2d);
- float *bones = skeleton->bones.ptr();
- bones[p_bone * 12 + 0] = p_transform.elements[0][0];
- bones[p_bone * 12 + 1] = p_transform.elements[1][0];
- bones[p_bone * 12 + 2] = 0;
- bones[p_bone * 12 + 3] = p_transform.elements[2][0];
- bones[p_bone * 12 + 4] = p_transform.elements[0][1];
- bones[p_bone * 12 + 5] = p_transform.elements[1][1];
- bones[p_bone * 12 + 6] = 0;
- bones[p_bone * 12 + 7] = p_transform.elements[2][1];
+ float *texture = skeleton->skel_texture.ptr();
+
+ int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4;
+
+ texture[base_ofs+0]=p_transform[0][0];
+ texture[base_ofs+1]=p_transform[1][0];
+ texture[base_ofs+2]=0;
+ texture[base_ofs+3]=p_transform[2][0];
+ base_ofs+=256*4;
+ texture[base_ofs+0]=p_transform[0][1];
+ texture[base_ofs+1]=p_transform[1][1];
+ texture[base_ofs+2]=0;
+ texture[base_ofs+3]=p_transform[2][1];
+
if (!skeleton->update_list.in_list()) {
skeleton_update_list.add(&skeleton->update_list);
@@ -4071,28 +4077,41 @@ Transform2D RasterizerStorageGLES3::skeleton_bone_get_transform_2d(RID p_skeleto
ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D());
ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D());
- Transform2D mtx;
+ const float *texture = skeleton->skel_texture.ptr();
+
+ Transform2D ret;
+
+ int base_ofs = ((p_bone / 256) * 256) * 2 * 4 + (p_bone % 256) * 4;
- float *bones = skeleton->bones.ptr();
- mtx.elements[0][0] = bones[p_bone * 12 + 0];
- mtx.elements[1][0] = bones[p_bone * 12 + 1];
- mtx.elements[2][0] = bones[p_bone * 12 + 3];
- mtx.elements[0][1] = bones[p_bone * 12 + 4];
- mtx.elements[1][1] = bones[p_bone * 12 + 5];
- mtx.elements[2][1] = bones[p_bone * 12 + 7];
+ ret[0][0]=texture[base_ofs+0];
+ ret[1][0]=texture[base_ofs+1];
+ ret[2][0]=texture[base_ofs+3];
+ base_ofs+=256*4;
+ ret[0][1]=texture[base_ofs+0];
+ ret[1][1]=texture[base_ofs+1];
+ ret[2][1]=texture[base_ofs+3];
- return mtx;
+ return ret;
}
void RasterizerStorageGLES3::update_dirty_skeletons() {
+ glActiveTexture(GL_TEXTURE0);
+
while (skeleton_update_list.first()) {
Skeleton *skeleton = skeleton_update_list.first()->self();
if (skeleton->size) {
- glBindBuffer(GL_UNIFORM_BUFFER, skeleton->ubo);
- glBufferSubData(GL_UNIFORM_BUFFER, 0, skeleton->bones.size() * sizeof(float), skeleton->bones.ptr());
- glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+
+
+ int height = skeleton->size/256;
+ if (skeleton->size%256)
+ height++;
+
+
+ glBindTexture(GL_TEXTURE_2D,skeleton->texture);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256,height*(skeleton->use_2d?2:3), GL_RGBA, GL_FLOAT, skeleton->skel_texture.ptr());
}
for (Set<RasterizerScene::InstanceBase *>::Element *E = skeleton->instances.front(); E; E = E->next()) {
@@ -5957,6 +5976,8 @@ bool RasterizerStorageGLES3::free(RID p_rid) {
}
skeleton_allocate(p_rid, 0, false);
+
+ glDeleteTextures(1,&skeleton->texture);
skeleton_owner.free(p_rid);
memdelete(skeleton);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 343cee2133..50617b8124 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -769,18 +769,19 @@ public:
/* SKELETON API */
struct Skeleton : RID_Data {
- int size;
bool use_2d;
- Vector<float> bones; //4x3 or 4x2 depending on what is needed
- GLuint ubo;
+ int size;
+ Vector<float> skel_texture;
+ GLuint texture;
SelfList<Skeleton> update_list;
Set<RasterizerScene::InstanceBase *> instances; //instances using skeleton
Skeleton()
: update_list(this) {
- size = 0;
+ size=0;
+
use_2d = false;
- ubo = 0;
+ texture = 0;
}
};
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 12934a82e7..48ca86ebe2 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -624,6 +624,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv";
actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture";
+ actions[VS::SHADER_CANVAS_ITEM].renames["POSITION"] = "(gl_FragCoord.xy)";
actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord";
actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec";
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index a0bf6cd58b..ffc41e611b 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -146,13 +146,10 @@ out highp float dp_clip;
#endif
-#ifdef USE_SKELETON
-
-layout(std140) uniform SkeletonData { //ubo:7
-
- mat3x4 skeleton[MAX_SKELETON_BONES];
-};
+#define SKELETON_TEXTURE_WIDTH 256
+#ifdef USE_SKELETON
+uniform highp sampler2D skeleton_texture; //texunit:-6
#endif
out highp vec4 position_interp;
@@ -173,15 +170,41 @@ void main() {
color_interp = color_attrib;
#endif
-
#ifdef USE_SKELETON
-
{
//skeleton transform
- highp mat3x4 m=skeleton[bone_indices.x]*bone_weights.x;
- m+=skeleton[bone_indices.y]*bone_weights.y;
- m+=skeleton[bone_indices.z]*bone_weights.z;
- m+=skeleton[bone_indices.w]*bone_weights.w;
+ ivec2 tex_ofs = ivec2( bone_indices.x%256, (bone_indices.x/256)*3 );
+ highp mat3x4 m = mat3x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0)
+ ) * bone_weights.x;
+
+ tex_ofs = ivec2( bone_indices.y%256, (bone_indices.y/256)*3 );
+
+ m+= mat3x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0)
+ ) * bone_weights.y;
+
+ tex_ofs = ivec2( bone_indices.z%256, (bone_indices.z/256)*3 );
+
+ m+= mat3x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0)
+ ) * bone_weights.z;
+
+
+ tex_ofs = ivec2( bone_indices.w%256, (bone_indices.w/256)*3 );
+
+ m+= mat3x4(
+ texelFetch(skeleton_texture,tex_ofs,0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,1),0),
+ texelFetch(skeleton_texture,tex_ofs+ivec2(0,2),0)
+ ) * bone_weights.w;
+
vertex.xyz = vertex * m;
@@ -190,8 +213,7 @@ void main() {
tangent.xyz = vec4(tangent.xyz,0.0) * mn;
#endif
}
-#endif // USE_SKELETON1
-
+#endif
#ifdef USE_INSTANCING
@@ -493,7 +515,7 @@ layout(location=0) out vec4 frag_color;
#endif
in highp vec4 position_interp;
-uniform highp sampler2D depth_buffer; //texunit:-8
+uniform highp sampler2D depth_buffer; //texunit:-9
float contact_shadow_compute(vec3 pos, vec3 dir, float max_distance) {
@@ -926,7 +948,7 @@ void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 ta
#ifdef USE_GI_PROBES
-uniform mediump sampler3D gi_probe1; //texunit:-6
+uniform mediump sampler3D gi_probe1; //texunit:-11
uniform highp mat4 gi_probe_xform1;
uniform highp vec3 gi_probe_bounds1;
uniform highp vec3 gi_probe_cell_size1;
@@ -934,7 +956,7 @@ uniform highp float gi_probe_multiplier1;
uniform highp float gi_probe_bias1;
uniform bool gi_probe_blend_ambient1;
-uniform mediump sampler3D gi_probe2; //texunit:-7
+uniform mediump sampler3D gi_probe2; //texunit:-10
uniform highp mat4 gi_probe_xform2;
uniform highp vec3 gi_probe_bounds2;
uniform highp vec3 gi_probe_cell_size2;
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 00df0f337d..6a2222345a 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -925,6 +925,11 @@ void EditorNode::_save_scene(String p_file, int idx) {
return;
}
+ // force creation of node path cache
+ // (hacky but needed for the tree to update properly)
+ Node *dummy_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
+ memdelete(dummy_scene);
+
int flg = 0;
if (EditorSettings::get_singleton()->get("filesystem/on_save/compress_binary_resources"))
flg |= ResourceSaver::FLAG_COMPRESS;
@@ -4716,6 +4721,44 @@ void EditorNode::_open_imported() {
load_scene(open_import_request, true, false, true, true);
}
+void EditorNode::dim_editor(bool p_dimming) {
+ static int dim_count = 0;
+ bool dim_ui = EditorSettings::get_singleton()->get("interface/dim_editor_on_dialog_popup");
+ if (p_dimming) {
+ if (dim_ui && dim_count == 0)
+ _start_dimming(true);
+ dim_count++;
+ } else {
+ dim_count--;
+ if (dim_count < 1)
+ _start_dimming(false);
+ }
+}
+
+void EditorNode::_start_dimming(bool p_dimming) {
+ _dimming = p_dimming;
+ _dim_time = 0.0f;
+ _dim_timer->start();
+}
+
+void EditorNode::_dim_timeout() {
+
+ _dim_time += _dim_timer->get_wait_time();
+ float wait_time = EditorSettings::get_singleton()->get("interface/dim_transition_time");
+
+ float c = 1.0f - (float)EditorSettings::get_singleton()->get("interface/dim_amount");
+
+ Color base = _dimming ? Color(1, 1, 1) : Color(c, c, c);
+ Color final = _dimming ? Color(c, c, c) : Color(1, 1, 1);
+
+ if (_dim_time + _dim_timer->get_wait_time() >= wait_time) {
+ gui_base->set_modulate(final);
+ _dim_timer->stop();
+ } else {
+ gui_base->set_modulate(base.linear_interpolate(final, _dim_time / wait_time));
+ }
+}
+
void EditorNode::_bind_methods() {
ClassDB::bind_method("_menu_option", &EditorNode::_menu_option);
@@ -4792,6 +4835,7 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported);
ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported);
+ ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout);
ADD_SIGNAL(MethodInfo("play_pressed"));
ADD_SIGNAL(MethodInfo("pause_pressed"));
@@ -6102,6 +6146,13 @@ EditorNode::EditorNode() {
FileAccess::set_file_close_fail_notify_callback(_file_access_close_error_notify);
waiting_for_first_scan = true;
+
+ _dimming = false;
+ _dim_time = 0.0f;
+ _dim_timer = memnew(Timer);
+ _dim_timer->set_wait_time(0.01666f);
+ _dim_timer->connect("timeout", this, "_dim_timeout");
+ add_child(_dim_timer);
}
EditorNode::~EditorNode() {
diff --git a/editor/editor_node.h b/editor/editor_node.h
index cb165bdf21..ef8ae34475 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -598,6 +598,13 @@ private:
void _tool_menu_insert_item(const ToolMenuItem &p_item);
void _rebuild_tool_menu() const;
+ bool _dimming;
+ float _dim_time;
+ Timer *_dim_timer;
+
+ void _start_dimming(bool p_dimming);
+ void _dim_timeout();
+
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -753,6 +760,8 @@ public:
void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu);
void remove_tool_menu_item(const String &p_name);
+ void dim_editor(bool p_dimming);
+
EditorNode();
~EditorNode();
void get_singleton(const char *arg1, bool arg2);
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index 8794a34f62..9e5021af6e 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -502,6 +502,11 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
hints["interface/custom_font"] = PropertyInfo(Variant::STRING, "interface/custom_font", PROPERTY_HINT_GLOBAL_FILE, "*.fnt", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
set("interface/custom_theme", "");
hints["interface/custom_theme"] = PropertyInfo(Variant::STRING, "interface/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ set("interface/dim_editor_on_dialog_popup", true);
+ set("interface/dim_amount", 0.6f);
+ hints["interface/dim_amount"] = PropertyInfo(Variant::REAL, "interface/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
+ set("interface/dim_transition_time", 0.11f);
+ hints["interface/dim_transition_time"] = PropertyInfo(Variant::REAL, "interface/dim_transition_time", PROPERTY_HINT_RANGE, "0,1,0.001", PROPERTY_USAGE_DEFAULT);
set("filesystem/directories/autoscan_project_path", "");
hints["filesystem/directories/autoscan_project_path"] = PropertyInfo(Variant::STRING, "filesystem/directories/autoscan_project_path", PROPERTY_HINT_GLOBAL_DIR);
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index bd7b0c304d..02ff2090f9 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -2,15 +2,13 @@
Import('env')
-env.Tool('textfile')
-env.Tool('zip')
-
javascript_files = [
"os_javascript.cpp",
"audio_driver_javascript.cpp",
"javascript_main.cpp",
"audio_server_javascript.cpp",
- "javascript_eval.cpp"
+ "power_javascript.cpp",
+ "javascript_eval.cpp",
]
env_javascript = env.Clone()
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 799b550899..c828045179 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -35,7 +35,7 @@ def get_flags():
def create(env):
# remove Windows' .exe suffix
- return env.Clone(PROGSUFFIX='')
+ return env.Clone(tools=['textfile', 'zip'], PROGSUFFIX='')
def escape_sources_backslashes(target, source, env, for_signature):
@@ -97,7 +97,6 @@ def configure(env):
env.Append(LINKFLAGS=['-s', 'ALLOW_MEMORY_GROWTH=1'])
env.extra_suffix = '.webassembly' + env.extra_suffix
else:
- env.Append(CPPFLAGS=['-s', 'ASM_JS=1'])
env.Append(LINKFLAGS=['-s', 'ASM_JS=1'])
env.Append(LINKFLAGS=['--separate-asm'])
diff --git a/platform/javascript/power_javascript.cpp b/platform/javascript/power_javascript.cpp
index d734999917..24158a34fe 100644
--- a/platform/javascript/power_javascript.cpp
+++ b/platform/javascript/power_javascript.cpp
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "power_javascript.h"
-#include "core/error_macros.h"
+#include "error_macros.h"
bool PowerJavascript::UpdatePowerInfo() {
// TODO Javascript implementation
diff --git a/platform/javascript/power_javascript.h b/platform/javascript/power_javascript.h
index 53c702b98e..78a896c430 100644
--- a/platform/javascript/power_javascript.h
+++ b/platform/javascript/power_javascript.h
@@ -30,6 +30,8 @@
#ifndef PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_
#define PLATFORM_JAVASCRIPT_POWER_JAVASCRIPT_H_
+#include "os/power.h"
+
class PowerJavascript {
private:
int nsecs_left;
diff --git a/scene/2d/screen_button.cpp b/scene/2d/screen_button.cpp
index 9b9fa6cfa8..db822ed306 100644
--- a/scene/2d/screen_button.cpp
+++ b/scene/2d/screen_button.cpp
@@ -135,7 +135,7 @@ void TouchScreenButton::_notification(int p_what) {
update();
if (!get_tree()->is_editor_hint())
- set_process_input(true);
+ set_process_input(is_visible_in_tree());
if (action.operator String() != "" && InputMap::get_singleton()->has_action(action)) {
action_id = InputMap::get_singleton()->get_action_id(action);
@@ -147,10 +147,21 @@ void TouchScreenButton::_notification(int p_what) {
if (is_pressed())
_release(true);
} break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (get_tree()->is_editor_hint())
+ break;
+ if (is_visible_in_tree()) {
+ set_process_input(true);
+ } else {
+ set_process_input(false);
+ if (is_pressed())
+ _release();
+ }
+ } break;
case NOTIFICATION_PAUSED: {
- // So the button can be pressed again even though the release gets unhandled because of coming during pause
- allow_repress = true;
- }
+ if (is_pressed())
+ _release();
+ } break;
}
}
@@ -230,7 +241,7 @@ void TouchScreenButton::_input(const InputEvent &p_event) {
if (!is_visible_in_tree())
return;
- const bool can_press = finger_pressed == -1 || allow_repress;
+ const bool can_press = finger_pressed == -1;
if (!can_press)
return; //already fingering
@@ -276,7 +287,6 @@ void TouchScreenButton::_input(const InputEvent &p_event) {
void TouchScreenButton::_press(int p_finger_pressed) {
finger_pressed = p_finger_pressed;
- allow_repress = false;
if (action_id != -1) {
@@ -394,7 +404,6 @@ void TouchScreenButton::_bind_methods() {
TouchScreenButton::TouchScreenButton() {
finger_pressed = -1;
- allow_repress = false;
action_id = -1;
passby_press = false;
visibility = VISIBILITY_ALWAYS;
diff --git a/scene/2d/screen_button.h b/scene/2d/screen_button.h
index d648920b21..201d908bf6 100644
--- a/scene/2d/screen_button.h
+++ b/scene/2d/screen_button.h
@@ -56,7 +56,6 @@ private:
StringName action;
bool passby_press;
int finger_pressed;
- bool allow_repress;
int action_id;
VisibilityMode visibility;
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index d081eda86d..89008b56bf 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -31,6 +31,10 @@
#include "print_string.h"
#include "translation.h"
+#ifdef TOOLS_ENABLED
+#include "editor/editor_node.h"
+#endif
+
void WindowDialog::_post_popup() {
drag_type = DRAG_NONE; // just in case
@@ -199,6 +203,16 @@ void WindowDialog::_notification(int p_what) {
set_default_cursor_shape(CURSOR_ARROW);
}
} break;
+#ifdef TOOLS_ENABLED
+ case NOTIFICATION_POST_POPUP: {
+ if (get_tree() && get_tree()->is_editor_hint())
+ EditorNode::get_singleton()->dim_editor(true);
+ } break;
+ case NOTIFICATION_POPUP_HIDE: {
+ if (get_tree() && get_tree()->is_editor_hint())
+ EditorNode::get_singleton()->dim_editor(false);
+ } break;
+#endif
}
}
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 864e26a651..0245944154 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2498,8 +2498,11 @@ void Node::_replace_connections_target(Node *p_new_target) {
Connection &c = E->get();
- c.source->disconnect(c.signal, this, c.method);
- c.source->connect(c.signal, p_new_target, c.method, c.binds, c.flags);
+ if (c.flags & CONNECT_PERSIST) {
+ c.source->disconnect(c.signal, this, c.method);
+ ERR_CONTINUE(!p_new_target->has_method(c.method));
+ c.source->connect(c.signal, p_new_target, c.method, c.binds, c.flags);
+ }
}
}
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 0c2f07aa4a..e46d9db7bc 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -995,12 +995,12 @@ int SceneState::find_node_by_path(const NodePath &p_node) const {
if (_get_base_scene_state().is_valid()) {
int idx = _get_base_scene_state()->find_node_by_path(p_node);
if (idx >= 0) {
- if (!base_scene_node_remap.has(idx)) {
- int ridx = nodes.size() + base_scene_node_remap.size();
- base_scene_node_remap[ridx] = idx;
+ int rkey = _find_base_scene_node_remap_key(idx);
+ if (rkey == -1) {
+ rkey = nodes.size() + base_scene_node_remap.size();
+ base_scene_node_remap[rkey] = idx;
}
-
- return base_scene_node_remap[idx];
+ return rkey;
}
}
return -1;
@@ -1013,11 +1013,24 @@ int SceneState::find_node_by_path(const NodePath &p_node) const {
//the node in the instanced scene, as a property may be missing
//from the local one
int idx = _get_base_scene_state()->find_node_by_path(p_node);
- base_scene_node_remap[nid] = idx;
+ if (idx != -1) {
+ base_scene_node_remap[nid] = idx;
+ }
}
return nid;
}
+
+int SceneState::_find_base_scene_node_remap_key(int p_idx) const {
+
+ for (Map<int, int>::Element *E = base_scene_node_remap.front(); E; E = E->next()) {
+ if (E->value() == p_idx) {
+ return E->key();
+ }
+ }
+ return -1;
+}
+
Variant SceneState::get_property_value(int p_node, const StringName &p_property, bool &found) const {
found = false;
diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h
index 5fa54413a8..b0e89205cb 100644
--- a/scene/resources/packed_scene.h
+++ b/scene/resources/packed_scene.h
@@ -100,6 +100,8 @@ class SceneState : public Reference {
PoolVector<String> _get_node_groups(int p_idx) const;
+ int _find_base_scene_node_remap_key(int p_idx) const;
+
protected:
static void _bind_methods();
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 49e987727d..28b8490cb4 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -1469,6 +1469,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Position","POSITION","",SLOT_TYPE_VEC,SLOT_IN},
//canvas item fragment out
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
{MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
@@ -1489,6 +1490,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN},
+ {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Position","POSITION","",SLOT_TYPE_VEC,SLOT_IN},
//canvas item light out
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightColor","LIGHT.rgb","",SLOT_TYPE_VEC,SLOT_OUT},
{MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightAlpha","LIGHT.a","",SLOT_TYPE_SCALAR,SLOT_OUT},
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index cd9afa7735..c5e31b235a 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -138,7 +138,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT;
@@ -150,7 +150,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"] = ShaderLanguage::TYPE_VEC4;