From 73fe08be2e378384d76ec48cf3647f2b950b52b3 Mon Sep 17 00:00:00 2001 From: Thomas Herzog Date: Mon, 6 Aug 2018 18:26:17 +0200 Subject: 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). --- drivers/gles2/rasterizer_canvas_gles2.cpp | 16 +- drivers/gles2/rasterizer_scene_gles2.cpp | 237 ++++++++++++++++------------- drivers/gles2/rasterizer_scene_gles2.h | 16 +- drivers/gles2/rasterizer_storage_gles2.cpp | 14 +- drivers/gles2/shader_gles2.cpp | 59 ++++++- drivers/gles2/shader_gles2.h | 2 +- drivers/gles2/shaders/scene.glsl | 22 ++- 7 files changed, 221 insertions(+), 145 deletions(-) diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 256d37186d..3d388c031a 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/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; diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 00a79db347..5f31bfe209 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/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 > 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 &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 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); diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index 0ce7e9ae97..f47d1f1d4e 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/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); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 697d357a7d..8c4325ccde 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -567,7 +567,7 @@ Ref RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) ERR_FAIL_COND_V(!texture->active, Ref()); ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref()); - 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 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::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(); diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index 146575973f..08ace2a9af 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/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 > 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); diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 49e45eea9f..cb515c199c 100644 --- a/drivers/gles2/shader_gles2.h +++ b/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; } diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index e08e9d1117..0fd358f1b5 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/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); -- cgit v1.2.3