Browse Source

GLES2 refactors

This commit unhacks some parts of the 3D rendering.

Most notably:

 - possibility to use negative texture units
   (no longer weird manual index allocation for user samplers)

 - refactoring of light code, now sorts in a different way,
   should yield better performance

 - fixes a crash while saving (because of "Illegal instruction" execution)
   when using a decent compiler (clang, it's clang. Thanks GCC for not telling me about UB).
Thomas Herzog 7 years ago
parent
commit
73fe08be2e

+ 8 - 8
drivers/gles2/rasterizer_canvas_gles2.cpp

@@ -349,7 +349,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 				state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				_bind_canvas_texture(RID(), RID());
@@ -393,7 +393,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 				state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map);
@@ -476,7 +476,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 				state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				glDisableVertexAttribArray(VS::ARRAY_COLOR);
@@ -642,7 +642,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				static const int num_points = 32;
@@ -673,7 +673,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
@@ -694,7 +694,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				_bind_canvas_texture(RID(), RID());
@@ -727,7 +727,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
 
 				if (state.canvas_shader.bind()) {
 					_set_uniforms();
-					state.canvas_shader.use_material((void *)p_material, 2);
+					state.canvas_shader.use_material((void *)p_material);
 				}
 
 				ERR_CONTINUE(primitive->points.size() < 1);
@@ -926,7 +926,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
 				state.canvas_shader.set_custom_shader(0);
 				state.canvas_shader.bind();
 			}
-			state.canvas_shader.use_material((void *)material_ptr, 2);
+			state.canvas_shader.use_material((void *)material_ptr);
 
 			shader_cache = shader_ptr;
 

+ 127 - 110
drivers/gles2/rasterizer_scene_gles2.cpp

@@ -35,6 +35,8 @@
 #include "rasterizer_canvas_gles2.h"
 #include "servers/visual/visual_server_raster.h"
 
+#include "vmap.h"
+
 #ifndef GLES_OVER_GL
 #define glClearDepth glClearDepthf
 #endif
@@ -827,7 +829,7 @@ static const GLenum gl_primitive[] = {
 	GL_TRIANGLE_FAN
 };
 
-void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_use_radiance_map, bool p_reverse_cull, bool p_shadow_atlas, bool p_skeleton_tex, Size2i p_skeleton_tex_size) {
+void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, Size2i p_skeleton_tex_size) {
 
 	// material parameters
 
@@ -864,25 +866,11 @@ void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 
 	ShaderLanguage::ShaderNode::Uniform::Hint *texture_hints = p_material->shader->texture_hints.ptrw();
 
-	int num_default_tex = p_use_radiance_map ? 1 : 0;
-
-	if (p_material->shader->spatial.uses_screen_texture) {
-		num_default_tex = MIN(num_default_tex, 2);
-	}
-
-	if (p_shadow_atlas) {
-		num_default_tex = MIN(num_default_tex, 3);
-	}
-
-	if (p_skeleton_tex) {
-		num_default_tex = MIN(num_default_tex, 4);
-
-		state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
-	}
+	state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size);
 
 	for (int i = 0; i < tc; i++) {
 
-		glActiveTexture(GL_TEXTURE0 + num_default_tex + i);
+		glActiveTexture(GL_TEXTURE0 + i);
 
 		RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(textures[i].second);
 
@@ -911,7 +899,7 @@ void RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
 
 		glBindTexture(t->target, t->tex_id);
 	}
-	state.scene_shader.use_material((void *)p_material, num_default_tex);
+	state.scene_shader.use_material((void *)p_material);
 }
 
 void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton) {
@@ -1279,7 +1267,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) {
 	}
 }
 
-void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_light_cull_result, int p_light_cull_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows) {
+void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_directional_lights, int p_directional_light_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add) {
 
 	ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
 
@@ -1289,6 +1277,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 	bool use_radiance_map = false;
 
+	VMap<RID, Vector<RenderList::Element *> > lit_objects;
+
 	for (int i = 0; i < p_element_count; i++) {
 		RenderList::Element *e = p_elements[i];
 
@@ -1297,7 +1287,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 		RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
 
 		if (p_base_env) {
-			glActiveTexture(GL_TEXTURE0);
+			glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 2);
 			glBindTexture(GL_TEXTURE_CUBE_MAP, p_base_env);
 			use_radiance_map = true;
 		}
@@ -1315,7 +1305,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 		_setup_geometry(e, skeleton);
 
-		_setup_material(material, use_radiance_map, p_reverse_cull, false, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+		_setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
 
 		if (use_radiance_map) {
 			state.scene_shader.set_uniform(SceneShaderGLES2::RADIANCE_INVERSE_XFORM, p_view_transform);
@@ -1404,66 +1394,88 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 		_render_geometry(e);
 
-		// render lights
-
 		if (material->shader->spatial.unshaded)
 			continue;
 
 		if (p_shadow)
 			continue;
 
-		state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, true);
+		for (int light = 0; light < e->instance->light_instances.size(); light++) {
 
-		state.scene_shader.bind();
+			RID light_instance = e->instance->light_instances[light];
 
-		glBlendEquation(GL_FUNC_ADD);
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+			lit_objects[light_instance].push_back(e);
+		}
+	}
 
-		{
-			bool has_shadow_atlas = shadow_atlas != NULL;
-			_setup_material(material, false, p_reverse_cull, has_shadow_atlas, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+	if (p_shadow) {
+		state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
+		state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
+		state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
+		state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, false);
+		return;
+	}
 
-			if (has_shadow_atlas) {
-				glActiveTexture(GL_TEXTURE3);
-				glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
-			}
+	state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, true);
 
-			state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
-			state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
-			state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
-			state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+	glEnable(GL_BLEND);
+	glBlendEquation(GL_FUNC_ADD);
+	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
 
-			state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+	for (int lo = 0; lo < lit_objects.size(); lo++) {
 
-			state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
-			state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
-			state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
-		}
+		RID key = lit_objects.getk(lo);
 
-		for (int j = 0; j < e->instance->light_instances.size(); j++) {
-			RID light_rid = e->instance->light_instances[j];
-			LightInstance *light = light_instance_owner.get(light_rid);
+		LightInstance *light = light_instance_owner.getornull(key);
+		RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
 
-			switch (light->light_ptr->type) {
-				case VS::LIGHT_DIRECTIONAL: {
-					continue;
-				} break;
+		const Vector<RenderList::Element *> &list = lit_objects.getv(lo);
+
+		for (int i = 0; i < list.size(); i++) {
+
+			RenderList::Element *e = list[i];
+			RasterizerStorageGLES2::Material *material = e->material;
+
+			RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
+
+			{
+				_setup_geometry(e, skeleton);
 
+				_setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+				if (shadow_atlas != NULL) {
+					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
+					glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+				}
+
+				state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
+				state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
+				state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
+				state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+
+				state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+
+				state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
+				state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
+				state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
+			}
+
+			switch (light_ptr->type) {
 				case VS::LIGHT_OMNI: {
+
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)1);
 
 					Vector3 position = p_view_transform.inverse().xform(light->transform.origin);
 
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position);
 
-					float range = light->light_ptr->param[VS::LIGHT_PARAM_RANGE];
+					float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range);
 
 					Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
-					attenuation.a = light->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+					attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
 
-					if (light->light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) {
+					if (light_ptr->shadow && shadow_atlas->shadow_owners.has(light->self)) {
 
 						uint32_t key = shadow_atlas->shadow_owners[light->self];
 
@@ -1516,10 +1528,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 					Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
 					Color attenuation = Color(0.0, 0.0, 0.0, 0.0);
-					attenuation.a = light->light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
-					float range = light->light_ptr->param[VS::LIGHT_PARAM_RANGE];
-					float spot_attenuation = light->light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
-					float angle = light->light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE];
+					attenuation.a = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION];
+					float range = light_ptr->param[VS::LIGHT_PARAM_RANGE];
+					float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION];
+					float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE];
 					angle = Math::cos(Math::deg2rad(angle));
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation);
 					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation);
@@ -1576,9 +1588,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 				} break;
 
-				default: {
-					print_line("wat.");
-				} break;
+				default: break;
 			}
 
 			float energy = light->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
@@ -1590,62 +1600,57 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 			_render_geometry(e);
 		}
+	}
 
-		for (int j = 0; j < p_light_cull_count; j++) {
-			RID light_rid = p_light_cull_result[j];
-
-			LightInstance *light = light_instance_owner.getornull(light_rid);
+	for (int dl = 0; dl < p_directional_light_count; dl++) {
+		RID light_rid = p_directional_lights[dl];
+		LightInstance *light = light_instance_owner.getornull(light_rid);
+		RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
 
-			RasterizerStorageGLES2::Light *light_ptr = light->light_ptr;
+		switch (light_ptr->directional_shadow_mode) {
+			case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
+			} break;
+			case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
+				state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
+				state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
+			} break;
 
-			switch (light_ptr->type) {
-				case VS::LIGHT_DIRECTIONAL: {
-
-					switch (light_ptr->directional_shadow_mode) {
-						case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: {
-						} break;
-						case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: {
-							state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true);
-							state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
-						} break;
-
-						case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
-							state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
-							state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
-						} break;
-						default:
-							break;
-					}
+			case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: {
+				state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true);
+				state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM_BLEND, light_ptr->directional_blend_splits);
+			} break;
+			default:
+				break;
+		}
 
-					{
-						_setup_material(material, false, p_reverse_cull, false, skeleton ? (skeleton->tex_id != 0) : 0, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
+		for (int i = 0; i < p_element_count; i++) {
 
-						if (directional_shadow.depth) {
-							glActiveTexture(GL_TEXTURE3);
-							glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
-						}
+			RenderList::Element *e = p_elements[i];
+			RasterizerStorageGLES2::Material *material = e->material;
+			RasterizerStorageGLES2::Skeleton *skeleton = storage->skeleton_owner.getornull(e->instance->skeleton);
 
-						state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
-						state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
-						state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
-						state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
+			{
+				_setup_material(material, p_reverse_cull, Size2i(skeleton ? skeleton->size * 3 : 0, 0));
 
-						state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
+				if (directional_shadow.depth) {
+					glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); // TODO move into base pass
+					glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+				}
 
-						state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
-						state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
-						state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
-					}
-					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)0);
-					Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
-					state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
+				state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, p_view_transform.inverse());
+				state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_INVERSE_MATRIX, p_view_transform);
+				state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_MATRIX, p_projection);
+				state.scene_shader.set_uniform(SceneShaderGLES2::PROJECTION_INVERSE_MATRIX, p_projection.inverse());
 
-				} break;
+				state.scene_shader.set_uniform(SceneShaderGLES2::TIME, storage->frame.time[0]);
 
-				default: {
-					continue;
-				} break;
+				state.scene_shader.set_uniform(SceneShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
+				state.scene_shader.set_uniform(SceneShaderGLES2::NORMAL_MULT, 1.0); // TODO mirror?
+				state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform);
 			}
+			state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_TYPE, (int)0);
+			Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized();
+			state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction);
 
 			float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY];
 			float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR];
@@ -1753,10 +1758,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
 
 			_render_geometry(e);
 		}
-
-		state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
 	}
 
+	state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_PASS, false);
+
 	state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
 	state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, false);
 	state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, false);
@@ -1911,9 +1916,21 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
 		}
 	}
 
+	Vector<RID> directional_lights;
+
+	for (int i = 0; i < p_light_cull_count; i++) {
+		RID light_rid = p_light_cull_result[i];
+
+		LightInstance *light = light_instance_owner.getornull(light_rid);
+
+		if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) {
+			directional_lights.push_back(light_rid);
+		}
+	}
+
 	// render opaque things first
 	render_list.sort_by_key(false);
-	_render_render_list(render_list.elements, render_list.element_count, p_light_cull_result, p_light_cull_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false, false, false);
+	_render_render_list(render_list.elements, render_list.element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, false, false, false);
 
 	// alpha pass
 
@@ -1921,7 +1938,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const
 	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
 	render_list.sort_by_key(true);
-	_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_light_cull_result, p_light_cull_count, p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false, false, false);
+	_render_render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, directional_lights.ptr(), directional_lights.size(), p_cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, false, true, false, false);
 
 	glDepthMask(GL_FALSE);
 	glDisable(GL_DEPTH_TEST);
@@ -2136,7 +2153,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
 
 	state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, true);
 
-	_render_render_list(render_list.elements, render_list.element_count, NULL, 0, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, false, false, true, false, false);
+	_render_render_list(render_list.elements, render_list.element_count, NULL, 0, light_transform, light_projection, RID(), NULL, 0, bias, normal_bias, false, false, true, false);
 
 	state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH, false);
 

+ 14 - 2
drivers/gles2/rasterizer_scene_gles2.h

@@ -545,11 +545,23 @@ public:
 	void _add_geometry_with_material(RasterizerStorageGLES2::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES2::GeometryOwner *p_owner, RasterizerStorageGLES2::Material *p_material, bool p_depth_pass, bool p_shadow_pass);
 
 	void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, bool p_depth_pass, bool p_shadow_pass);
-	void _render_render_list(RenderList::Element **p_elements, int p_element_count, const RID *p_light_cull_result, int p_light_cull_count, const Transform &p_view_transform, const CameraMatrix &p_projection, RID p_shadow_atlas, Environment *p_env, GLuint p_base_env, float p_shadow_bias, float p_shadow_normal_bias, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
+	void _render_render_list(RenderList::Element **p_elements, int p_element_count,
+			const RID *p_directional_lights, int p_directional_light_count,
+			const Transform &p_view_transform,
+			const CameraMatrix &p_projection,
+			RID p_shadow_atlas,
+			Environment *p_env,
+			GLuint p_base_env,
+			float p_shadow_bias,
+			float p_shadow_normal_bias,
+			bool p_reverse_cull,
+			bool p_alpha_pass,
+			bool p_shadow,
+			bool p_directional_add);
 
 	void _draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy);
 
-	void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_use_radiance_map, bool p_reverse_cull, bool p_shadow_atlas = false, bool p_skeleton_tex = false, Size2i p_skeleton_tex_size = Size2i(0, 0));
+	void _setup_material(RasterizerStorageGLES2::Material *p_material, bool p_reverse_cull, Size2i p_skeleton_tex_size = Size2i(0, 0));
 	void _setup_geometry(RenderList::Element *p_element, RasterizerStorageGLES2::Skeleton *p_skeleton);
 	void _render_geometry(RenderList::Element *p_element);
 

+ 9 - 5
drivers/gles2/rasterizer_storage_gles2.cpp

@@ -567,7 +567,7 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
 	ERR_FAIL_COND_V(!texture->active, Ref<Image>());
 	ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref<Image>());
 
-	if (!texture->images[p_layer].is_null()) {
+	if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) {
 		return texture->images[p_layer];
 	}
 #ifdef GLES_OVER_GL
@@ -594,9 +594,13 @@ Ref<Image> RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer)
 			ofs = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, texture->format, i - 1);
 		}
 
-		glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
-		glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
+		if (texture->compressed) {
+			glPixelStorei(GL_PACK_ALIGNMENT, 4);
+			glGetCompressedTexImage(texture->target, i, &wb[ofs]);
+		} else {
+			glPixelStorei(GL_PACK_ALIGNMENT, 1);
+			glGetTexImage(texture->target, i, texture->gl_format_cache, texture->gl_type_cache, &wb[ofs]);
+		}
 	}
 
 	wb = PoolVector<uint8_t>::Write();
@@ -3961,7 +3965,7 @@ void RasterizerStorageGLES2::initialize() {
 	frame.clear_request = false;
 	// config.keep_original_textures = false;
 
-	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &config.max_texture_image_units);
 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, &config.max_texture_size);
 
 	shaders.copy.init();

+ 52 - 7
drivers/gles2/shader_gles2.cpp

@@ -527,8 +527,13 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() {
 
 	for (int i = 0; i < texunit_pair_count; i++) {
 		GLint loc = glGetUniformLocation(v.id, texunit_pairs[i].name);
-		if (loc >= 0)
-			glUniform1i(loc, texunit_pairs[i].index);
+		if (loc >= 0) {
+			if (texunit_pairs[i].index < 0) {
+				glUniform1i(loc, max_image_units + texunit_pairs[i].index);
+			} else {
+				glUniform1i(loc, texunit_pairs[i].index);
+			}
+		}
 	}
 
 	if (cc) {
@@ -643,6 +648,8 @@ void ShaderGLES2::setup(
 			}
 		}
 	}
+
+	glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_image_units);
 }
 
 void ShaderGLES2::finish() {
@@ -717,7 +724,7 @@ void ShaderGLES2::free_custom_shader(uint32_t p_code_id) {
 	custom_code_map.erase(p_code_id);
 }
 
-void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
+void ShaderGLES2::use_material(void *p_material) {
 	RasterizerStorageGLES2::Material *material = (RasterizerStorageGLES2::Material *)p_material;
 
 	if (!material) {
@@ -906,20 +913,58 @@ void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
 				case ShaderLanguage::TYPE_MAT2: {
 					Transform2D val = V->get();
 
-					// TODO
+					if (value.second.size() < 4) {
+						value.second.resize(4);
+					}
+
+					value.second.write[0].real = val.elements[0][0];
+					value.second.write[1].real = val.elements[0][1];
+					value.second.write[2].real = val.elements[1][0];
+					value.second.write[3].real = val.elements[1][1];
 
 				} break;
 
 				case ShaderLanguage::TYPE_MAT3: {
 					Basis val = V->get();
 
-					// TODO
+					if (value.second.size() < 9) {
+						value.second.resize(9);
+					}
+
+					value.second.write[0].real = val.elements[0][0];
+					value.second.write[1].real = val.elements[0][1];
+					value.second.write[2].real = val.elements[0][2];
+					value.second.write[3].real = val.elements[1][0];
+					value.second.write[4].real = val.elements[1][1];
+					value.second.write[5].real = val.elements[1][2];
+					value.second.write[6].real = val.elements[2][0];
+					value.second.write[7].real = val.elements[2][1];
+					value.second.write[8].real = val.elements[2][2];
 				} break;
 
 				case ShaderLanguage::TYPE_MAT4: {
 					Transform val = V->get();
 
-					// TODO
+					if (value.second.size() < 16) {
+						value.second.resize(16);
+					}
+
+					value.second.write[0].real = val.basis.elements[0][0];
+					value.second.write[0].real = val.basis.elements[0][1];
+					value.second.write[0].real = val.basis.elements[0][2];
+					value.second.write[0].real = 0;
+					value.second.write[0].real = val.basis.elements[1][0];
+					value.second.write[0].real = val.basis.elements[1][1];
+					value.second.write[0].real = val.basis.elements[1][2];
+					value.second.write[0].real = 0;
+					value.second.write[0].real = val.basis.elements[2][0];
+					value.second.write[0].real = val.basis.elements[2][1];
+					value.second.write[0].real = val.basis.elements[2][2];
+					value.second.write[0].real = 0;
+					value.second.write[0].real = val.origin[0];
+					value.second.write[0].real = val.origin[1];
+					value.second.write[0].real = val.origin[2];
+					value.second.write[0].real = 1;
 				} break;
 
 				case ShaderLanguage::TYPE_SAMPLER2D: {
@@ -1034,7 +1079,7 @@ void ShaderGLES2::use_material(void *p_material, int p_num_predef_textures) {
 		Pair<ShaderLanguage::DataType, Vector<ShaderLanguage::ConstantNode::Value> > value;
 		value.first = ShaderLanguage::TYPE_INT;
 		value.second.resize(1);
-		value.second.write[0].sint = p_num_predef_textures + i;
+		value.second.write[0].sint = i;
 
 		// GLint location = get_uniform_location(textures[i].first);
 

+ 1 - 1
drivers/gles2/shader_gles2.h

@@ -465,7 +465,7 @@ public:
 
 	// this void* is actually a RasterizerStorageGLES2::Material, but C++ doesn't
 	// like forward declared nested classes.
-	void use_material(void *p_material, int p_num_predef_textures);
+	void use_material(void *p_material);
 
 	uint32_t get_version() const { return new_conditional_version.version; }
 

+ 10 - 12
drivers/gles2/shaders/scene.glsl

@@ -48,7 +48,7 @@ attribute highp vec4 bone_transform_row_2; // attrib:11
 attribute vec4 bone_ids; // attrib:6
 attribute highp vec4 bone_weights; // attrib:7
 
-uniform highp sampler2D bone_transforms; // texunit:4
+uniform highp sampler2D bone_transforms; // texunit:-1
 uniform ivec2 skeleton_texture_size;
 
 #endif
@@ -294,17 +294,17 @@ uniform highp float time;
 uniform vec2 screen_pixel_size;
 #endif
 
-uniform highp sampler2D depth_buffer; //texunit:1
+uniform highp sampler2D depth_buffer; //texunit:-5
 
 #if defined(SCREEN_TEXTURE_USED)
-uniform highp sampler2D screen_texture; //texunit:2
+uniform highp sampler2D screen_texture; //texunit:-6
 #endif
 
 #ifdef USE_RADIANCE_MAP
 
 #define RADIANCE_MAX_LOD 6.0
 
-uniform samplerCube radiance_map; // texunit:0
+uniform samplerCube radiance_map; // texunit:-2
 
 uniform mat4 radiance_inverse_xform;
 
@@ -345,7 +345,7 @@ uniform float light_spot_angle;
 
 
 // shadows
-uniform highp sampler2D light_shadow_atlas; //texunit:3
+uniform highp sampler2D light_shadow_atlas; //texunit:-4
 uniform float light_has_shadow;
 
 uniform mat4 light_shadow_matrix;
@@ -353,7 +353,7 @@ uniform vec4 light_clamp;
 
 // directional shadow
 
-uniform highp sampler2D light_directional_shadow; // texunit:3
+uniform highp sampler2D light_directional_shadow; // texunit:-4
 uniform vec4 light_split_offsets;
 
 uniform mat4 light_shadow_matrix1;
@@ -439,11 +439,10 @@ void light_compute(vec3 N,
 	{
 		// calculate specular reflection
 
-		 vec3 R = normalize(-reflect(L,N));
-		 float cRdotV = max(dot(R, V), 0.0);
-		 float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0);
-		 specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity;
-
+		vec3 R = normalize(-reflect(L,N));
+		float cRdotV = max(dot(R, V), 0.0);
+		float blob_intensity = pow(cRdotV, (1.0 - roughness) * 256.0);
+		specular_light += light_color * attenuation * blob_intensity * specular_blob_intensity;
 
 	}
 }
@@ -808,7 +807,6 @@ FRAGMENT_SHADER_CODE
 		              anisotropy,
 		              diffuse_light,
 		              specular_light);
-
 	}
 
 	gl_FragColor = vec4(ambient_light + diffuse_light + specular_light, alpha);