From c83742ba86eadd03800369c3fb5b1c23f083c59e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 28 Sep 2018 20:32:40 -0300 Subject: [PATCH] -Lightmap and lightmap capture support for GLES2 -Added hint to not show some properties when running on low end gfx --- core/object.h | 1 + drivers/dummy/rasterizer_dummy.h | 2 + drivers/gles2/rasterizer_gles2.h | 2 + drivers/gles2/rasterizer_scene_gles2.cpp | 90 ++++++++++++++++- drivers/gles2/rasterizer_storage_gles2.cpp | 110 +++++++++++++++------ drivers/gles2/rasterizer_storage_gles2.h | 15 +++ drivers/gles2/shaders/scene.glsl | 88 +++++++++++++---- drivers/gles3/rasterizer_gles3.h | 2 + drivers/gles3/rasterizer_storage_gles3.cpp | 6 +- editor/editor_inspector.cpp | 3 + gles_builders.py | 5 +- scene/resources/material.cpp | 12 +++ scene/resources/material.h | 2 + scene/resources/texture.cpp | 3 + servers/visual/rasterizer.h | 2 + servers/visual/visual_server_raster.cpp | 3 + servers/visual/visual_server_raster.h | 2 + servers/visual/visual_server_wrap_mt.h | 4 + servers/visual_server.h | 2 + 19 files changed, 295 insertions(+), 59 deletions(-) diff --git a/core/object.h b/core/object.h index 0825aac3018..c883d44f369 100644 --- a/core/object.h +++ b/core/object.h @@ -116,6 +116,7 @@ enum PropertyUsageFlags { PROPERTY_USAGE_NIL_IS_VARIANT = 1 << 19, PROPERTY_USAGE_INTERNAL = 1 << 20, PROPERTY_USAGE_DO_NOT_SHARE_ON_DUPLICATE = 1 << 21, // If the object is duplicated also this property will be duplicated + PROPERTY_USAGE_HIGH_END_GFX = 1 << 22, PROPERTY_USAGE_DEFAULT = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK, PROPERTY_USAGE_DEFAULT_INTL = PROPERTY_USAGE_STORAGE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_NETWORK | PROPERTY_USAGE_INTERNATIONALIZED, diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index f2c47a4f116..9315026623a 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -803,6 +803,8 @@ public: _create_func = _create_current; } + virtual bool is_low_end() const { return true; } + RasterizerDummy() {} ~RasterizerDummy() {} }; diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index c76d5f7f20a..45a9db73f2e 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -66,6 +66,8 @@ public: static void make_current(); static void register_config(); + virtual bool is_low_end() const { return true; } + RasterizerGLES2(); ~RasterizerGLES2(); }; diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 63a71f2ba82..06d355802a8 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -2028,6 +2028,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, glDisable(GL_BLEND); } + RasterizerStorageGLES2::Texture *prev_lightmap = NULL; + float lightmap_energy = 1.0; + bool prev_use_lightmap_capture = false; + for (int i = 0; i < p_element_count; i++) { RenderList::Element *e = p_elements[i]; @@ -2039,6 +2043,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, LightInstance *light = NULL; ReflectionProbeInstance *refprobe_1 = NULL; ReflectionProbeInstance *refprobe_2 = NULL; + RasterizerStorageGLES2::Texture *lightmap = NULL; + bool use_lightmap_capture = false; if (!p_shadow) { @@ -2147,15 +2153,44 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, refprobe_1 != NULL); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, refprobe_2 != NULL); if (refprobe_1 != NULL && refprobe_1 != prev_refprobe_1) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_1->cubemap); } if (refprobe_2 != NULL && refprobe_2 != prev_refprobe_2) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 6); glBindTexture(GL_TEXTURE_CUBE_MAP, refprobe_2->cubemap); } rebind = true; } + + use_lightmap_capture = !unshaded && !accum_pass && !e->instance->lightmap_capture_data.empty(); + + if (use_lightmap_capture != prev_use_lightmap_capture) { + + state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, use_lightmap_capture); + rebind = true; + } + + if (!unshaded && !accum_pass && e->instance->lightmap.is_valid()) { + + lightmap = storage->texture_owner.getornull(e->instance->lightmap); + lightmap_energy = 1.0; + if (lightmap) { + RasterizerStorageGLES2::LightmapCapture *capture = storage->lightmap_capture_data_owner.getornull(e->instance->lightmap_capture->base); + if (capture) { + lightmap_energy = capture->energy; + } + } + } + + if (lightmap != prev_lightmap) { + state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, lightmap != NULL); + if (lightmap != NULL) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, lightmap->tex_id); + } + rebind = true; + } } bool instancing = e->instancing; @@ -2224,6 +2259,10 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, if (refprobe_1 || refprobe_2) { _setup_refprobes(refprobe_1, refprobe_2, p_view_transform, p_env); } + + if (lightmap) { + state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_ENERGY, lightmap_energy); + } } state.scene_shader.set_uniform(SceneShaderGLES2::CAMERA_MATRIX, view_transform_inverse); @@ -2239,6 +2278,11 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_uniform(SceneShaderGLES2::WORLD_TRANSFORM, e->instance->transform); + if (use_lightmap_capture) { //this is per instance, must be set always if present + glUniform4fv(state.scene_shader.get_uniform_location(SceneShaderGLES2::LIGHTMAP_CAPTURES), 12, (const GLfloat *)e->instance->lightmap_capture_data.ptr()); + state.scene_shader.set_uniform(SceneShaderGLES2::LIGHTMAP_CAPTURE_SKY, false); + } + _render_geometry(e); prev_geometry = e->geometry; @@ -2248,6 +2292,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, prev_light = light; prev_refprobe_1 = refprobe_1; prev_refprobe_2 = refprobe_2; + prev_lightmap = lightmap; + prev_use_lightmap_capture = use_lightmap_capture; } _setup_light_type(NULL, NULL); //clear light stuff @@ -2260,6 +2306,8 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::USE_VERTEX_LIGHTING, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE1, false); state.scene_shader.set_conditional(SceneShaderGLES2::USE_REFLECTION_PROBE2, false); + state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP, false); + state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false); } void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) { @@ -2818,6 +2866,44 @@ void RasterizerSceneGLES2::set_scene_pass(uint64_t p_pass) { } bool RasterizerSceneGLES2::free(RID p_rid) { + + if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.getptr(p_rid); + + //remove from shadow atlases.. + for (Set::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(E->get()); + ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); + uint32_t key = shadow_atlas->shadow_owners[p_rid]; + uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; + + shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + shadow_atlas->shadow_owners.erase(p_rid); + } + + light_instance_owner.free(p_rid); + memdelete(light_instance); + + } else if (shadow_atlas_owner.owns(p_rid)) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.get(p_rid); + shadow_atlas_set_size(p_rid, 0); + shadow_atlas_owner.free(p_rid); + memdelete(shadow_atlas); + } else if (reflection_probe_instance_owner.owns(p_rid)) { + + ReflectionProbeInstance *reflection_instance = reflection_probe_instance_owner.get(p_rid); + + reflection_probe_release_atlas_index(p_rid); + reflection_probe_instance_owner.free(p_rid); + memdelete(reflection_instance); + + } else { + return false; + } + return true; } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 81c48c3cec7..bf51fcc0276 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -496,22 +496,6 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } -//set swizle for older format compatibility -#ifdef GLES_OVER_GL - switch (texture->format) { - - case Image::FORMAT_L8: { - - } break; - case Image::FORMAT_LA8: { - - } break; - default: { - - } break; - } -#endif - int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; int w = img->get_width(); @@ -591,7 +575,7 @@ Ref RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) PoolVector data; - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0); + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers PoolVector::Write wb = data.write(); @@ -3595,46 +3579,100 @@ void RasterizerStorageGLES2::gi_probe_dynamic_data_update(RID p_gi_probe_data, i /////// RID RasterizerStorageGLES2::lightmap_capture_create() { - return RID(); + + LightmapCapture *capture = memnew(LightmapCapture); + return lightmap_capture_data_owner.make_rid(capture); } void RasterizerStorageGLES2::lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) { -} + LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND(!capture); + capture->bounds = p_bounds; + capture->instance_change_notify(); +} AABB RasterizerStorageGLES2::lightmap_capture_get_bounds(RID p_capture) const { - return AABB(); -} + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, AABB()); + return capture->bounds; +} void RasterizerStorageGLES2::lightmap_capture_set_octree(RID p_capture, const PoolVector &p_octree) { -} + LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND(!capture); + + ERR_FAIL_COND(p_octree.size() == 0 || (p_octree.size() % sizeof(LightmapCaptureOctree)) != 0); + + capture->octree.resize(p_octree.size() / sizeof(LightmapCaptureOctree)); + if (p_octree.size()) { + PoolVector::Write w = capture->octree.write(); + PoolVector::Read r = p_octree.read(); + copymem(w.ptr(), r.ptr(), p_octree.size()); + } + capture->instance_change_notify(); +} PoolVector RasterizerStorageGLES2::lightmap_capture_get_octree(RID p_capture) const { - return PoolVector(); + + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, PoolVector()); + + if (capture->octree.size() == 0) + return PoolVector(); + + PoolVector ret; + ret.resize(capture->octree.size() * sizeof(LightmapCaptureOctree)); + { + PoolVector::Read r = capture->octree.read(); + PoolVector::Write w = ret.write(); + copymem(w.ptr(), r.ptr(), ret.size()); + } + + return ret; } void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) { + LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND(!capture); + capture->cell_xform = p_xform; } Transform RasterizerStorageGLES2::lightmap_capture_get_octree_cell_transform(RID p_capture) const { - return Transform(); + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, Transform()); + return capture->cell_xform; } void RasterizerStorageGLES2::lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) { + LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND(!capture); + capture->cell_subdiv = p_subdiv; } int RasterizerStorageGLES2::lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { - return 0; + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, 0); + return capture->cell_subdiv; } void RasterizerStorageGLES2::lightmap_capture_set_energy(RID p_capture, float p_energy) { + + LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND(!capture); + capture->energy = p_energy; } float RasterizerStorageGLES2::lightmap_capture_get_energy(RID p_capture) const { - return 0.0; + + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, 0); + return capture->energy; } const PoolVector *RasterizerStorageGLES2::lightmap_capture_get_octree_ptr(RID p_capture) const { - return NULL; + const LightmapCapture *capture = lightmap_capture_data_owner.getornull(p_capture); + ERR_FAIL_COND_V(!capture, NULL); + return &capture->octree; } /////// @@ -3773,10 +3811,10 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene inst = gi_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break;*/ - /*case VS::INSTANCE_LIGHTMAP_CAPTURE: { + case VS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break;*/ + } break; default: { if (!inst) { ERR_FAIL(); @@ -3819,11 +3857,11 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc /*case VS::INSTANCE_GI_PROBE: { inst = gi_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break; + } break; */ case VS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break;*/ + } break; default: { if (!inst) { @@ -4094,6 +4132,8 @@ VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { return VS::INSTANCE_IMMEDIATE; } else if (reflection_probe_owner.owns(p_rid)) { return VS::INSTANCE_REFLECTION_PROBE; + } else if (lightmap_capture_data_owner.owns(p_rid)) { + return VS::INSTANCE_LIGHTMAP_CAPTURE; } else { return VS::INSTANCE_NONE; } @@ -4281,7 +4321,15 @@ bool RasterizerStorageGLES2::free(RID p_rid) { memdelete(reflection_probe); return true; + } else if (lightmap_capture_data_owner.owns(p_rid)) { + // delete the texture + LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid); + lightmap_capture->instance_remove_deps(); + + lightmap_capture_data_owner.free(p_rid); + memdelete(lightmap_capture); + return true; } else { return false; } diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index e22738a3781..da7e200c964 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -1046,6 +1046,21 @@ public: /* LIGHTMAP */ + struct LightmapCapture : public Instanciable { + + PoolVector octree; + AABB bounds; + Transform cell_xform; + int cell_subdiv; + float energy; + LightmapCapture() { + energy = 1.0; + cell_subdiv = 1; + } + }; + + mutable RID_Owner lightmap_capture_data_owner; + virtual RID lightmap_capture_create(); virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds); virtual AABB lightmap_capture_get_bounds(RID p_capture) const; diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index b555cee80c8..b27bf0d12bf 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -27,15 +27,15 @@ attribute vec3 normal_attrib; // attrib:1 attribute vec4 tangent_attrib; // attrib:2 #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) attribute vec4 color_attrib; // attrib:3 #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) attribute vec2 uv_attrib; // attrib:4 #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) attribute vec2 uv2_attrib; // attrib:5 #endif @@ -102,15 +102,15 @@ varying vec3 tangent_interp; varying vec3 binormal_interp; #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) varying vec4 color_interp; #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) varying vec2 uv_interp; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) varying vec2 uv2_interp; #endif @@ -317,18 +317,18 @@ void main() { vec3 binormal = normalize(cross(normal, tangent) * binormalf); #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) color_interp = color_attrib; #ifdef USE_INSTANCING color_interp *= instance_color; #endif #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) uv_interp = uv_attrib; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) uv2_interp = uv2_attrib; #endif @@ -521,7 +521,7 @@ VERTEX_SHADER_CODE #if defined(LIGHT_USE_PSSM4) shadow_coord3 = light_shadow_matrix3 * vi4; - shadow_coord3 = light_shadow_matrix3 * vi4; + shadow_coord4 = light_shadow_matrix4 * vi4; #endif @@ -612,7 +612,7 @@ uniform mat4 world_transform; uniform highp float time; -#ifdef SCREEN_UV_USED +#if defined(SCREEN_UV_USED) uniform vec2 screen_pixel_size; #endif @@ -643,7 +643,7 @@ uniform mat4 refprobe1_local_matrix; uniform bool refprobe1_exterior; -uniform highp samplerCube reflection_probe1; //texunit:-4 +uniform highp samplerCube reflection_probe1; //texunit:-5 uniform float refprobe1_intensity; uniform vec4 refprobe1_ambient; @@ -670,7 +670,7 @@ uniform mat4 refprobe2_local_matrix; uniform bool refprobe2_exterior; -uniform highp samplerCube reflection_probe2; //texunit:-5 +uniform highp samplerCube reflection_probe2; //texunit:-6 uniform float refprobe2_intensity; uniform vec4 refprobe2_ambient; @@ -773,7 +773,16 @@ void reflection_process(samplerCube reflection_map, #endif //use refprobe 1 or 2 +#ifdef USE_LIGHTMAP +uniform mediump sampler2D lightmap; //texunit:-4 +uniform mediump float lightmap_energy; +#endif +#ifdef USE_LIGHTMAP_CAPTURE +uniform mediump vec4[12] lightmap_captures; +uniform bool lightmap_capture_sky; + +#endif #ifdef USE_RADIANCE_MAP @@ -866,15 +875,15 @@ varying vec3 tangent_interp; varying vec3 binormal_interp; #endif -#ifdef ENABLE_COLOR_INTERP +#if defined(ENABLE_COLOR_INTERP) varying vec4 color_interp; #endif -#ifdef ENABLE_UV_INTERP +#if defined(ENABLE_UV_INTERP) varying vec2 uv_interp; #endif -#ifdef ENABLE_UV2_INTERP +#if defined(ENABLE_UV2_INTERP) || defined(USE_LIGHTMAP) varying vec2 uv2_interp; #endif @@ -1285,11 +1294,11 @@ void main() { #endif float normaldepth = 1.0; -#ifdef ALPHA_SCISSOR_USED +#if defined(ALPHA_SCISSOR_USED) float alpha_scissor = 0.5; #endif -#ifdef SCREEN_UV_USED +#if defined(SCREEN_UV_USED) vec2 screen_uv = gl_FragCoord.xy * screen_pixel_size; #endif @@ -1319,7 +1328,7 @@ FRAGMENT_SHADER_CODE vec3 eye_position = -normalize(vertex_interp); -#ifdef ALPHA_SCISSOR_USED +#if defined(ALPHA_SCISSOR_USED) if (alpha < alpha_scissor) { discard; } @@ -1404,6 +1413,47 @@ FRAGMENT_SHADER_CODE #endif //use reflection probe 1 +#ifdef USE_LIGHTMAP + //ambient light will come entirely from lightmap is lightmap is used + ambient_light = texture2D(lightmap, uv2_interp).rgb * lightmap_energy; +#endif + +#ifdef USE_LIGHTMAP_CAPTURE + { + vec3 cone_dirs[12] = vec3[]( + vec3(0, 0, 1), + vec3(0.866025, 0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5), + vec3(0, 0, -1), + vec3(0.866025, 0, -0.5), + vec3(0.267617, 0.823639, -0.5), + vec3(-0.700629, 0.509037, -0.5), + vec3(-0.700629, -0.509037, -0.5), + vec3(0.267617, -0.823639, -0.5)); + + vec3 local_normal = normalize(camera_matrix * vec4(normal, 0.0)).xyz; + vec4 captured = vec4(0.0); + float sum = 0.0; + for (int i = 0; i < 12; i++) { + float amount = max(0.0, dot(local_normal, cone_dirs[i])); //not correct, but creates a nice wrap around effect + captured += lightmap_captures[i] * amount; + sum += amount; + } + + captured /= sum; + + if (lightmap_capture_sky) { + ambient_light = mix(ambient_light, captured.rgb, captured.a); + } else { + ambient_light = captured.rgb; + } + } +#endif + + #endif //BASE PASS // diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 0a264caf8fa..543011aff30 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -66,6 +66,8 @@ public: static void make_current(); static void register_config(); + virtual bool is_low_end() const { return false; } + RasterizerGLES3(); ~RasterizerGLES3(); }; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b39b7aabc02..797441c3a14 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1029,7 +1029,7 @@ Ref RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) PoolVector data; - int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1 ? -1 : 0); + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, real_format, texture->mipmaps > 1); data.resize(data_size * 2); //add some memory at the end, just in case for buggy drivers PoolVector::Write wb = data.write(); @@ -7364,7 +7364,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) { GIProbeData *gi_probe_data = gi_probe_data_owner.get(p_rid); glDeleteTextures(1, &gi_probe_data->tex_id); - gi_probe_owner.free(p_rid); + gi_probe_data_owner.free(p_rid); memdelete(gi_probe_data); } else if (lightmap_capture_data_owner.owns(p_rid)) { @@ -7372,7 +7372,7 @@ bool RasterizerStorageGLES3::free(RID p_rid) { LightmapCapture *lightmap_capture = lightmap_capture_data_owner.get(p_rid); lightmap_capture->instance_remove_deps(); - gi_probe_owner.free(p_rid); + lightmap_capture_data_owner.free(p_rid); memdelete(lightmap_capture); } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 49d9dca7013..10fc15e4681 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1449,6 +1449,9 @@ void EditorInspector::update_tree() { } else if (!(p.usage & PROPERTY_USAGE_EDITOR)) continue; + if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && VS::get_singleton()->is_low_end()) + continue; //do not show this property in low end gfx + if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) { continue; } diff --git a/gles_builders.py b/gles_builders.py index 8ed9f39393e..1e63a53f1a3 100644 --- a/gles_builders.py +++ b/gles_builders.py @@ -68,12 +68,9 @@ def include_file_in_legacygl_header(filename, header_data, depth): line = fs.readline() - if line.find("#ifdef ") != -1 or line.find("#elif defined(") != -1: + if line.find("#ifdef ") != -1: if line.find("#ifdef ") != -1: ifdefline = line.replace("#ifdef ", "").strip() - else: - ifdefline = line.replace("#elif defined(", "").strip() - ifdefline = ifdefline.replace(")", "").strip() if line.find("_EN_") != -1: enumbase = ifdefline[:ifdefline.find("_EN_")] diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index ce801c8763c..c898aaff347 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -1369,6 +1369,12 @@ void SpatialMaterial::_validate_feature(const String &text, Feature feature, Pro } } +void SpatialMaterial::_validate_high_end(const String &text, PropertyInfo &property) const { + if (property.name.begins_with(text)) { + property.usage |= PROPERTY_USAGE_HIGH_END_GFX; + } +} + void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); _validate_feature("emission", FEATURE_EMISSION, property); @@ -1382,6 +1388,12 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_feature("refraction", FEATURE_REFRACTION, property); _validate_feature("detail", FEATURE_DETAIL, property); + _validate_high_end("refraction", property); + _validate_high_end("subsurf_scatter", property); + _validate_high_end("anisotropy", property); + _validate_high_end("clearcoat", property); + _validate_high_end("depth", property); + if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { property.usage = 0; } diff --git a/scene/resources/material.h b/scene/resources/material.h index 4a2a8133416..0154874ae44 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -442,6 +442,8 @@ private: static Ref materials_for_2d[MAX_MATERIALS_FOR_2D]; //used by Sprite3D and other stuff + void _validate_high_end(const String &text, PropertyInfo &property) const; + protected: static void _bind_methods(); void _validate_property(PropertyInfo &property) const; diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 16b4ed31df8..f0e3979f13b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -207,6 +207,9 @@ void ImageTexture::set_flags(uint32_t p_flags) { flags=p_flags|cube; */ flags = p_flags; + if (w == 0 || h == 0) { + return; //uninitialized, do not set to texture + } VisualServer::get_singleton()->texture_set_flags(texture, p_flags); } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 877eb72c988..207f13ac1ae 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -1107,6 +1107,8 @@ public: virtual void end_frame(bool p_swap_buffers) = 0; virtual void finalize() = 0; + virtual bool is_low_end() const = 0; + virtual ~Rasterizer() {} }; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 6e41197e213..677c3232168 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -189,6 +189,9 @@ void VisualServerRaster::call_set_use_vsync(bool p_enable) { OS::get_singleton()->_set_use_vsync(p_enable); } +bool VisualServerRaster::is_low_end() const { + return VSG::rasterizer->is_low_end(); +} VisualServerRaster::VisualServerRaster() { VSG::canvas = memnew(VisualServerCanvas); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index ff8469ad320..ef2b767a8ad 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -690,6 +690,8 @@ public: virtual void call_set_use_vsync(bool p_enable); + virtual bool is_low_end() const; + VisualServerRaster(); ~VisualServerRaster(); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index dbc45653eac..e4d69121f0e 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -609,6 +609,10 @@ public: static void set_use_vsync_callback(bool p_enable); + virtual bool is_low_end() const { + return visual_server->is_low_end(); + } + VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread); ~VisualServerWrapMT(); diff --git a/servers/visual_server.h b/servers/visual_server.h index 5005a0422f8..100bc06db62 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -1037,6 +1037,8 @@ public: virtual void call_set_use_vsync(bool p_enable) = 0; + virtual bool is_low_end() const = 0; + VisualServer(); virtual ~VisualServer(); };