diff options
Diffstat (limited to 'drivers')
23 files changed, 700 insertions, 70 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 047eaaf0ac..6f686690bf 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1162,7 +1162,65 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { - // This isn't really working yet, so disabling for now. + if (storage->frame.current_rt->copy_screen_effect.color == 0) { + ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers"); + ERR_FAIL(); + } + + glDisable(GL_BLEND); + + state.canvas_texscreen_used = true; + + Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); + + Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); + + if (p_rect != Rect2()) { + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + glClearColor(1, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); + + const Vector2 vertpos[4] = { + Vector2(-1, -1), + Vector2(-1, 1), + Vector2(1, 1), + Vector2(1, -1), + }; + + const Vector2 uvpos[4] = { + Vector2(0, 0), + Vector2(0, 1), + Vector2(1, 1), + Vector2(1, 0) + }; + + const int indexpos[6] = { + 0, 1, 2, + 2, 3, 0 + }; + + _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + + // back to canvas, force rebind + state.using_texture_rect = false; + state.canvas_shader.bind(); + _bind_canvas_texture(state.current_tex, state.current_normal); + _set_uniforms(); + + glEnable(GL_BLEND); } void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { @@ -1178,6 +1236,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons state.current_tex = RID(); state.current_tex_ptr = NULL; state.current_normal = RID(); + state.canvas_texscreen_used = false; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1265,7 +1324,18 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr) { if (shader_ptr->canvas_item.uses_screen_texture) { - _copy_texscreen(Rect2()); + if (!state.canvas_texscreen_used) { + //copy if not copied before + _copy_texscreen(Rect2()); + + // blend mode will have been enabled so make sure we disable it again later on + //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; + } + + if (storage->frame.current_rt->copy_screen_effect.color) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } } if (shader_ptr != shader_cache) { diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index e4783e907b..ae677b606d 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -524,7 +524,11 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance glGenerateMipmap(GL_TEXTURE_CUBE_MAP); glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth); //resize depth buffer +#ifdef JAVASCRIPT_ENABLED + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size, size); +#else glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, size, size); +#endif for (int i = 0; i < 6; i++) { glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]); @@ -990,6 +994,12 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G e->depth_layer = e->instance->depth_layer; e->priority = p_material->render_priority; + if (has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + //add element to opaque + RenderList::Element *eo = render_list.add_element(); + *eo = *e; + } + int rpsize = e->instance->reflection_probe_instances.size(); if (rpsize > 0) { bool first = true; @@ -2873,7 +2883,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ if (light->type == VS::LIGHT_OMNI) { // cubemap only - if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE) { + if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) { int cubemap_index = shadow_cubemaps.size() - 1; // find an appropriate cubemap to render to @@ -2969,7 +2979,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false); // convert cubemap to dual paraboloid if needed - if (light->type == VS::LIGHT_OMNI && light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && p_pass == 5) { + if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) && p_pass == 5) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); @@ -3131,7 +3141,7 @@ void RasterizerSceneGLES2::initialize() { } // cubemaps for shadows - { + if (storage->config.support_write_depth) { //not going to be used int max_shadow_cubemap_sampler_size = 512; int cube_size = max_shadow_cubemap_sampler_size; diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index 42ac621e45..0d917f4da2 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -473,6 +473,7 @@ public: virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0); virtual void light_instance_mark_visible(RID p_light_instance); + virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_write_depth; } LightInstance **render_light_instances; int render_directional_lights; diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 0622a353df..f0deff4791 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1715,8 +1715,196 @@ RID RasterizerStorageGLES2::mesh_create() { return mesh_owner.make_rid(mesh); } +static PoolVector<uint8_t> _unpack_half_floats(const PoolVector<uint8_t> &array, uint32_t &format, int p_vertices) { + + uint32_t p_format = format; + + static int src_size[VS::ARRAY_MAX]; + static int dst_size[VS::ARRAY_MAX]; + static int to_convert[VS::ARRAY_MAX]; + + int src_stride = 0; + int dst_stride = 0; + + for (int i = 0; i < VS::ARRAY_MAX; i++) { + + to_convert[i] = 0; + if (!(p_format & (1 << i))) { + src_size[i] = 0; + dst_size[i] = 0; + continue; + } + + switch (i) { + + case VS::ARRAY_VERTEX: { + + if (p_format & VS::ARRAY_COMPRESS_VERTEX) { + + if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { + src_size[i] = 4; + dst_size[i] = 8; + to_convert[i] = 2; + } else { + src_size[i] = 8; + dst_size[i] = 12; + to_convert[i] = 3; + } + + format &= ~VS::ARRAY_COMPRESS_VERTEX; + } else { + + if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { + src_size[i] = 8; + dst_size[i] = 8; + } else { + src_size[i] = 12; + dst_size[i] = 12; + } + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_format & VS::ARRAY_COMPRESS_NORMAL) { + src_size[i] = 4; + dst_size[i] = 4; + } else { + src_size[i] = 12; + dst_size[i] = 12; + } + + } break; + case VS::ARRAY_TANGENT: { + + if (p_format & VS::ARRAY_COMPRESS_TANGENT) { + src_size[i] = 4; + dst_size[i] = 4; + } else { + src_size[i] = 16; + dst_size[i] = 16; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_format & VS::ARRAY_COMPRESS_COLOR) { + src_size[i] = 4; + dst_size[i] = 4; + } else { + src_size[i] = 16; + dst_size[i] = 16; + } + + } break; + case VS::ARRAY_TEX_UV: { + + if (p_format & VS::ARRAY_COMPRESS_TEX_UV) { + src_size[i] = 4; + to_convert[i] = 2; + format &= ~VS::ARRAY_COMPRESS_TEX_UV; + } else { + src_size[i] = 8; + } + + dst_size[i] = 8; + + } break; + case VS::ARRAY_TEX_UV2: { + + if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) { + src_size[i] = 4; + to_convert[i] = 2; + format &= ~VS::ARRAY_COMPRESS_TEX_UV2; + } else { + src_size[i] = 8; + } + + dst_size[i] = 8; + + } break; + case VS::ARRAY_BONES: { + + if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) { + src_size[i] = 8; + dst_size[i] = 8; + } else { + src_size[i] = 4; + dst_size[i] = 4; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) { + src_size[i] = 8; + dst_size[i] = 8; + } else { + src_size[i] = 16; + dst_size[i] = 16; + } + + } break; + case VS::ARRAY_INDEX: { + + src_size[i] = 0; + dst_size[i] = 0; + + } break; + } + + src_stride += src_size[i]; + dst_stride += dst_size[i]; + } + + PoolVector<uint8_t> ret; + ret.resize(p_vertices * dst_stride); + + PoolVector<uint8_t>::Read r = array.read(); + PoolVector<uint8_t>::Write w = ret.write(); + + int src_offset = 0; + int dst_offset = 0; + + for (int i = 0; i < VS::ARRAY_MAX; i++) { + + if (src_size[i] == 0) { + continue; //no go + } + const uint8_t *rptr = r.ptr(); + uint8_t *wptr = w.ptr(); + if (to_convert[i]) { //converting + + for (int j = 0; j < p_vertices; j++) { + const uint16_t *src = (const uint16_t *)&rptr[src_stride * j + src_offset]; + float *dst = (float *)&wptr[dst_stride * j + dst_offset]; + + for (int k = 0; k < to_convert[i]; k++) { + + dst[k] = Math::half_to_float(src[k]); + } + } + + } else { + //just copy + for (int j = 0; j < p_vertices; j++) { + for (int k = 0; k < src_size[i]; k++) { + wptr[dst_stride * j + dst_offset + k] = rptr[src_stride * j + src_offset + k]; + } + } + } + + src_offset += src_size[i]; + dst_offset += dst_size[i]; + } + + r = PoolVector<uint8_t>::Read(); + w = PoolVector<uint8_t>::Write(); + + return ret; +} + void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const PoolVector<uint8_t> &p_array, int p_vertex_count, const PoolVector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<PoolVector<uint8_t> > &p_blend_shapes, const Vector<AABB> &p_bone_aabbs) { - PoolVector<uint8_t> array = p_array; Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); @@ -1735,6 +1923,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: Surface::Attrib attribs[VS::ARRAY_MAX]; int stride = 0; + bool uses_half_float = false; for (int i = 0; i < VS::ARRAY_MAX; i++) { @@ -1763,6 +1952,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: if (p_format & VS::ARRAY_COMPRESS_VERTEX) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += attribs[i].size * 2; + uses_half_float = true; } else { attribs[i].type = GL_FLOAT; stride += attribs[i].size * 4; @@ -1823,6 +2013,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: if (p_format & VS::ARRAY_COMPRESS_TEX_UV) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += 4; + uses_half_float = true; } else { attribs[i].type = GL_FLOAT; stride += 8; @@ -1838,6 +2029,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += 4; + uses_half_float = true; } else { attribs[i].type = GL_FLOAT; stride += 8; @@ -1900,6 +2092,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } //validate sizes + PoolVector<uint8_t> array = p_array; int array_size = stride * p_vertex_count; int index_array_size = 0; @@ -1931,6 +2124,15 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: ERR_FAIL_COND(array.size() != array_size); + if (!config.support_half_float_vertices && uses_half_float) { + + uint32_t new_format = p_format; + PoolVector<uint8_t> unpacked_array = _unpack_half_floats(array, new_format, p_vertex_count); + + mesh_add_surface(p_mesh, new_format, p_primitive, unpacked_array, p_vertex_count, p_index_array, p_index_count, p_aabb, p_blend_shapes, p_bone_aabbs); + return; //do not go any further, above function used unpacked stuff will be used instead. + } + if (p_format & VS::ARRAY_FORMAT_INDEX) { index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count; @@ -4007,7 +4209,11 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glGenRenderbuffers(1, &rt->depth); glBindRenderbuffer(GL_RENDERBUFFER, rt->depth); +#ifdef JAVASCRIPT_ENABLED + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, rt->width, rt->height); +#else glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, rt->width, rt->height); +#endif glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -4045,7 +4251,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // copy texscreen buffers - { + if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) { + int w = rt->width; int h = rt->height; @@ -4053,10 +4260,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glGenFramebuffers(1, &rt->copy_screen_effect.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -4218,7 +4432,11 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) { glGenRenderbuffers(1, &cls->depth); glBindRenderbuffer(GL_RENDERBUFFER, cls->depth); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, cls->size, cls->height); +#ifdef JAVASCRIPT_ENABLED + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, cls->size, cls->height); +#else + glRenderbufferStorage(GL_RENDERBUFFER, _DEPTH_COMPONENT24_OES, cls->size, cls->height); +#endif glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth); glBindRenderbuffer(GL_RENDERBUFFER, 0); @@ -4665,6 +4883,19 @@ void RasterizerStorageGLES2::initialize() { config.support_32_bits_indices = config.extensions.has("GL_OES_element_index_uint"); #endif +#ifdef GLES_OVER_GL + config.support_write_depth = true; +#else + config.support_write_depth = config.extensions.has("GL_EXT_frag_depth"); +#endif + +#ifdef JAVASCRIPT_ENABLED + config.support_half_float_vertices = false; +#else + //every other platform, be it mobile or desktop, supports this (even if not in the GLES2 spec). + config.support_half_float_vertices = true; +#endif + frame.count = 0; frame.delta = 0; frame.current_rt = NULL; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index ae14aaa9c0..ed21238db6 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -80,6 +80,8 @@ public: bool use_rgba_2d_shadows; bool support_32_bits_indices; + bool support_write_depth; + bool support_half_float_vertices; } config; struct Resources { diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index 65d4b63bb9..3bf5baec14 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -229,6 +229,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -242,6 +243,11 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { strings.push_back("#define USE_GLES_OVER_GL\n"); #else strings.push_back("#version 100\n"); +//angle does not like +#ifdef JAVASCRIPT_ENABLED + strings.push_back("#define USE_HIGHP_PRECISION\n"); +#endif + #endif int define_line_ofs = 1; @@ -323,6 +329,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { if (iloglen < 0) { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?"); @@ -344,6 +351,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { Memory::free_static(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -398,6 +406,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?"); @@ -420,6 +429,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -447,6 +457,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL program link log. What the frick?"); @@ -471,6 +482,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -514,6 +526,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } + return &v; } @@ -678,9 +694,26 @@ void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { } void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { + ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 468971471c..d493880d0b 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -104,6 +104,7 @@ private: Vector<StringName> texture_uniforms; Vector<StringName> custom_uniforms; Vector<CharString> custom_defines; + Set<uint32_t> versions; }; struct Version { @@ -465,6 +466,8 @@ public: void set_custom_shader(uint32_t p_code_id); void free_custom_shader(uint32_t p_code_id); + uint32_t get_version_key() const { return conditional_version.version; } + void set_uniform_default(int p_idx, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 0de60d7421..c4a8c8b990 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif uniform highp mat4 projection_matrix; @@ -215,14 +215,42 @@ VERTEX_SHADER_CODE /* clang-format off */ [fragment] +#ifndef USE_GLES_OVER_GL + +#ifdef GL_EXT_shader_texture_lod +#extension GL_EXT_shader_texture_lod : enable +#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) +#endif + +#endif + +#ifdef GL_ARB_shader_texture_lod +#extension GL_ARB_shader_texture_lod : enable +#endif + + +#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) +#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) +#endif + + + + #ifdef USE_GLES_OVER_GL #define lowp #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif uniform sampler2D color_texture; // texunit:-1 /* clang-format on */ @@ -433,19 +461,14 @@ FRAGMENT_SHADER_CODE #ifdef SHADOW_USE_GRADIENT -#define SHADOW_TEST(m_ofs) \ - { \ - highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ - shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); \ - } + /* clang-format off */ + /* GLSL es 100 doesn't support line continuation characters(backslashes) */ +#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); shadow_attenuation += 1.0 - smoothstep(sd, sd + shadow_gradient, sz); } #else -#define SHADOW_TEST(m_ofs) \ - { \ - highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); \ - shadow_attenuation += step(sz, sd); \ - } +#define SHADOW_TEST(m_ofs) { highp float sd = SHADOW_DEPTH(shadow_texture, vec2(m_ofs, sh)); shadow_attenuation += step(sz, sd); } + /* clang-format on */ #endif diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index f3c2a7eec4..931b3f3708 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif attribute highp vec4 vertex_attrib; // attrib:0 @@ -29,7 +29,7 @@ varying vec2 uv_interp; varying vec2 uv2_interp; #ifdef USE_COPY_SECTION -uniform vec4 copy_section; +uniform highp vec4 copy_section; #endif void main() { @@ -61,9 +61,14 @@ void main() { #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) varying vec3 cube_interp; diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl index 06274a7698..7643297a14 100644 --- a/drivers/gles2/shaders/cubemap_filter.glsl +++ b/drivers/gles2/shaders/cubemap_filter.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif attribute highp vec2 vertex; // attrib:0 @@ -25,22 +25,42 @@ void main() { /* clang-format off */ [fragment] +#ifndef USE_GLES_OVER_GL + +#ifdef GL_EXT_shader_texture_lod +#extension GL_EXT_shader_texture_lod : enable +#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) +#endif + +#endif + +#ifdef GL_ARB_shader_texture_lod #extension GL_ARB_shader_texture_lod : enable +#endif -#ifndef GL_ARB_shader_texture_lod -#define texture2DLod(img, coord, lod) texture2D(img, coord) -#define textureCubeLod(img, coord, lod) textureCube(img, coord) +#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) +#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) #endif + + #ifdef USE_GLES_OVER_GL #define lowp #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif + #ifdef USE_SOURCE_PANORAMA uniform sampler2D source_panorama; //texunit:0 #else @@ -118,7 +138,13 @@ vec3 texelCoordToVec(vec2 uv, int faceID) { faceUvVectors[5][2] = vec3(0.0, 0.0, 1.0); // +z face // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. - vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; + vec3 result; + for (int i = 0; i < 6; i++) { + if (i == faceID) { + result = (faceUvVectors[i][0] * uv.x) + (faceUvVectors[i][1] * uv.y) + faceUvVectors[i][2]; + break; + } + } return normalize(result); } diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index b2b9458ed2..c7f5c97133 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -655,20 +655,41 @@ VERTEX_SHADER_CODE /* clang-format off */ [fragment] + +#ifndef USE_GLES_OVER_GL + +#ifdef GL_EXT_shader_texture_lod +#extension GL_EXT_shader_texture_lod : enable +#define texture2DLod(img, coord, lod) texture2DLodEXT(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCubeLodEXT(img, coord, lod) +#endif + +#endif + +#ifdef GL_ARB_shader_texture_lod #extension GL_ARB_shader_texture_lod : enable +#endif -#ifndef GL_ARB_shader_texture_lod -#define texture2DLod(img, coord, lod) texture2D(img, coord) -#define textureCubeLod(img, coord, lod) textureCube(img, coord) +#if !defined(GL_EXT_shader_texture_lod) && !defined(GL_ARB_shader_texture_lod) +#define texture2DLod(img, coord, lod) texture2D(img, coord, lod) +#define textureCubeLod(img, coord, lod) textureCube(img, coord, lod) #endif + + + #ifdef USE_GLES_OVER_GL #define lowp #define mediump #define highp #else -precision mediump float; +#if defined(USE_HIGHP_PRECISION) +precision highp float; precision highp int; +#else +precision mediump float; +precision mediump int; +#endif #endif #include "stdlib.glsl" diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index d53b27eb88..966466d9bc 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1832,6 +1832,7 @@ void RasterizerSceneGLES3::_render_geometry(RenderList::Element *e) { storage->info.render.vertices_count += s->index_array_len * amount; } else #endif + if (s->index_array_len > 0) { glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); @@ -2677,13 +2678,6 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr glBindBuffer(GL_UNIFORM_BUFFER, 0); } -// Drop -O3 for this function as it triggers a GCC bug up until at least GCC 8.2.1. -// This refers to GH issue #19633. -// The bug has been reported to the GCC project. -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC push_options -#pragma GCC optimize("-O2") -#endif void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows) { LightInstance *li = directional_lights[p_index]; @@ -2784,7 +2778,7 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[j].camera * modelview; - store_camera(shadow_mtx, &ubo_data.shadow_matrix1[16 * j]); + store_camera(shadow_mtx, &ubo_data.shadow.matrix[16 * j]); ubo_data.light_clamp[0] = atlas_rect.position.x; ubo_data.light_clamp[1] = atlas_rect.position.y; @@ -2801,9 +2795,6 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform glBindBufferBase(GL_UNIFORM_BUFFER, 3, state.directional_ubo); } -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC pop_options -#endif void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas) { @@ -2898,7 +2889,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c Transform proj = (p_camera_inverse_transform * li->transform).inverse(); - store_transform(proj, ubo_data.shadow_matrix1); + store_transform(proj, ubo_data.shadow.matrix1); ubo_data.light_params[3] = 1.0; //means it has shadow ubo_data.light_clamp[0] = float(x) / atlas_size; @@ -2987,7 +2978,7 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c CameraMatrix shadow_mtx = rectm * bias * li->shadow_transform[0].camera * modelview; - store_camera(shadow_mtx, ubo_data.shadow_matrix1); + store_camera(shadow_mtx, ubo_data.shadow.matrix1); } li->light_index = state.spot_light_count; @@ -4141,9 +4132,19 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glDepthFunc(GL_LEQUAL); - state.used_contact_shadows = true; + state.used_contact_shadows = false; + + for (int i = 0; i < p_light_cull_count; i++) { + + ERR_BREAK(i >= RenderList::MAX_LIGHTS); + + LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) { + state.used_contact_shadows = true; + } + } - if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { //detect with state.used_contact_shadows too + if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]) { //detect with state.used_contact_shadows too //pre z pass glDisable(GL_BLEND); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 9772b5dd23..325617745a 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -569,10 +569,15 @@ public: float light_params[4]; //spot attenuation, spot angle, specular, shadow enabled float light_clamp[4]; float light_shadow_color_contact[4]; - float shadow_matrix1[16]; //up to here for spot and omni, rest is for directional - float shadow_matrix2[16]; - float shadow_matrix3[16]; - float shadow_matrix4[16]; + union { + struct { + float matrix1[16]; //up to here for spot and omni, rest is for directional + float matrix2[16]; + float matrix3[16]; + float matrix4[16]; + }; + float matrix[4 * 16]; + } shadow; float shadow_split_offsets[4]; }; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 24673c8755..8b3f1a1b77 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1056,6 +1056,128 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) return texture->images[p_layer]; } + // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole** + // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading + // everything just to throw everything but one layer away is A Bad Idea. + // + // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it + // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels. + if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) { + // can't read a layer that doesn't exist + ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref<Image>()); + + // get some information about the texture + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + + bool compressed; + bool srgb; + + _get_gl_image_and_format( + Ref<Image>(), + texture->format, + texture->flags, + real_format, + gl_format, + gl_internal_format, + gl_type, + compressed, + srgb); + + PoolVector<uint8_t> data; + + // TODO need to decide between RgbaUnorm and RgbaFloat32 for output + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); // add some more memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + // generate temporary resources + GLuint tmp_fbo; + glGenFramebuffers(1, &tmp_fbo); + + GLuint tmp_color_attachment; + glGenTextures(1, &tmp_color_attachment); + + // now bring the OpenGL context into the correct state + { + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo); + + // back color attachment with memory, then set properties + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tmp_color_attachment); + // TODO support HDR properly + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // use the color texture as color attachment for this render pass + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0); + + // more GL state, wheeeey + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + + // use volume tex for reading + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + // set up copy shader for proper use + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY); + shaders.copy.bind(); + + // calculate the normalized z coordinate for the layer + float layer = (float)p_layer / (float)texture->alloc_depth; + + shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer); + + glBindVertexArray(resources.quadie_array); + } + + // clear color attachment, then perform copy + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // read the image into the host buffer + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + // remove temp resources and unset some GL state + { + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false); + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDeleteTextures(1, &tmp_color_attachment); + glDeleteFramebuffers(1, &tmp_fbo); + } + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + } + #ifdef GLES_OVER_GL Image::Format real_format; @@ -1172,9 +1294,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) glViewport(0, 0, texture->alloc_width, texture->alloc_height); - shaders.copy.bind(); - shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.bind(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index edc2a6c054..64396cadd1 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -204,6 +204,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -324,6 +325,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Vertex shader compilation failed with empty log"); @@ -345,6 +347,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { memfree(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -418,6 +421,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Fragment shader compilation failed with empty log"); } else { @@ -440,6 +444,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -486,6 +491,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_COND_V(iloglen <= 0, NULL); } @@ -508,6 +514,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -559,6 +566,9 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } return &v; } @@ -742,7 +752,23 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; //bye + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 1f98f4883d..1ed30986bf 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -117,6 +117,7 @@ private: uint32_t version; Vector<StringName> texture_uniforms; Vector<CharString> custom_defines; + Set<uint32_t> versions; }; struct Version { diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 3b36bc7cc1..e1a0813efc 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -61,19 +61,35 @@ in vec3 cube_interp; #else in vec2 uv_interp; #endif -/* clang-format on */ #ifdef USE_ASYM_PANO uniform highp mat4 pano_transform; uniform highp vec4 asym_proj; #endif +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_TEXTURE3D +#endif +#ifdef USE_TEXTURE2DARRAY +#endif + #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 +#elif defined(USE_TEXTURE3D) +uniform sampler3D source_3d; //texunit:0 +#elif defined(USE_TEXTURE2DARRAY) +uniform sampler2DArray source_2d_array; //texunit:0 #else uniform sampler2D source; //texunit:0 #endif +/* clang-format on */ + +#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) +uniform float layer; +#endif + #ifdef USE_MULTIPLIER uniform float multiplier; #endif @@ -97,7 +113,6 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) { #endif -uniform float stuff; uniform vec2 pixel_size; in vec2 uv2_interp; @@ -147,6 +162,10 @@ void main() { #elif defined(USE_CUBEMAP) vec4 color = texture(source_cube, normalize(cube_interp)); +#elif defined(USE_TEXTURE3D) + vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); +#elif defined(USE_TEXTURE2DARRAY) + vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); #else vec4 color = textureLod(source, uv_interp, 0.0); #endif diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 86aac2801a..1a8ad5e1ef 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -165,10 +165,8 @@ uniform int spot_light_count; out vec4 diffuse_light_interp; out vec4 specular_light_interp; - void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, inout vec3 diffuse, inout vec3 specular) { - float NdotL = dot(N, L); float cNdotL = max(NdotL, 0.0); // clamped NdotL float NdotV = dot(N, V); @@ -225,8 +223,6 @@ void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, float roughness, in specular += specular_brdf_NL * light_color * (1.0 / M_PI); } - - } void light_process_omni(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, float roughness, inout vec3 diffuse, inout vec3 specular) { diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 7284226ae7..e011176806 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -407,6 +407,10 @@ size_t DirAccessUnix::get_space_left() { #endif }; +String DirAccessUnix::get_filesystem_type() const { + return ""; //TODO this should be implemented +} + DirAccessUnix::DirAccessUnix() { dir_stream = 0; diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h index 4da7e42b64..b85ae719ff 100644 --- a/drivers/unix/dir_access_unix.h +++ b/drivers/unix/dir_access_unix.h @@ -82,6 +82,9 @@ public: virtual size_t get_space_left(); + virtual String get_filesystem_type() const; + + DirAccessUnix(); ~DirAccessUnix(); }; diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp index c20f707684..c32e063736 100644 --- a/drivers/windows/dir_access_windows.cpp +++ b/drivers/windows/dir_access_windows.cpp @@ -346,6 +346,35 @@ size_t DirAccessWindows::get_space_left() { return (size_t)bytes; } +String DirAccessWindows::get_filesystem_type() const { + String path = fix_path(const_cast<DirAccessWindows*>(this)->get_current_dir()); + print_line("fixed path: "+path); + int unit_end = path.find(":"); + ERR_FAIL_COND_V(unit_end==-1,String()); + String unit = path.substr(0,unit_end+1) + "\\"; + print_line("unit: "+unit); + + TCHAR szVolumeName[100] = ""; + TCHAR szFileSystemName[10] = ""; + DWORD dwSerialNumber = 0; + DWORD dwMaxFileNameLength = 0; + DWORD dwFileSystemFlags = 0; + + if(::GetVolumeInformation(unit.utf8().get_data(), + szVolumeName, + sizeof(szVolumeName), + &dwSerialNumber, + &dwMaxFileNameLength, + &dwFileSystemFlags, + szFileSystemName, + sizeof(szFileSystemName)) == TRUE) { + + return String(szFileSystemName); + } + + ERR_FAIL_V(""); +} + DirAccessWindows::DirAccessWindows() { p = memnew(DirAccessWindowsPrivate); diff --git a/drivers/windows/dir_access_windows.h b/drivers/windows/dir_access_windows.h index 2e2d23f4e2..b8599d5c26 100644 --- a/drivers/windows/dir_access_windows.h +++ b/drivers/windows/dir_access_windows.h @@ -82,6 +82,9 @@ public: //virtual FileType get_file_type() const; size_t get_space_left(); + virtual String get_filesystem_type() const; + + DirAccessWindows(); ~DirAccessWindows(); }; diff --git a/drivers/windows/thread_windows.cpp b/drivers/windows/thread_windows.cpp index 1bcd5a10d4..8a2992e0c2 100644 --- a/drivers/windows/thread_windows.cpp +++ b/drivers/windows/thread_windows.cpp @@ -52,6 +52,7 @@ DWORD ThreadWindows::thread_callback(LPVOID userdata) { t->id = (ID)GetCurrentThreadId(); // must implement t->callback(t->user); + SetEvent(t->handle); ScriptServer::thread_exit(); @@ -63,13 +64,9 @@ Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void ThreadWindows *tr = memnew(ThreadWindows); tr->callback = p_callback; tr->user = p_user; - tr->handle = CreateThread( - NULL, // default security attributes - 0, // use default stack size - thread_callback, // thread function name - tr, // argument to thread function - 0, // use default creation flags - NULL); // returns the thread identifier + tr->handle = CreateEvent(NULL, TRUE, FALSE, NULL); + + QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION); return tr; } |