diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dummy/rasterizer_dummy.h | 1 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_scene_gles2.cpp | 22 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.cpp | 11 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_storage_gles2.h | 1 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 40 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 27 | ||||
-rw-r--r-- | drivers/gles2/shaders/scene.glsl | 6 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 7 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 1 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 20 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 3 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 10 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 1 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 5 | ||||
-rw-r--r-- | drivers/unix/os_unix.h | 1 |
15 files changed, 110 insertions, 46 deletions
diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index ddc0dd5fa9..214da82819 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -241,6 +241,7 @@ public: void textures_keep_original(bool p_enable) {} void texture_set_proxy(RID p_proxy, RID p_base) {} + virtual Size2 texture_size_with_proxy(RID p_texture) const { return Size2(); } void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {} /* SKY API */ diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index ae677b606d..cc9084dceb 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -998,6 +998,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G //add element to opaque RenderList::Element *eo = render_list.add_element(); *eo = *e; + eo->use_accum_ptr = &eo->use_accum; } int rpsize = e->instance->reflection_probe_instances.size(); @@ -1563,6 +1564,8 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } else { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 3, buffer + color_ofs); } + } else { + glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, 1.0, 1.0, 1.0, 1.0); } if (multi_mesh->custom_data_floats) { @@ -2066,6 +2069,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, bool prev_unshaded = false; bool prev_instancing = false; + bool prev_depth_prepass = false; state.scene_shader.set_conditional(SceneShaderGLES2::SHADELESS, false); RasterizerStorageGLES2::Material *prev_material = NULL; RasterizerStorageGLES2::Geometry *prev_geometry = NULL; @@ -2141,6 +2145,19 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, prev_unshaded = unshaded; } + bool depth_prepass = false; + + if (!p_alpha_pass && material->shader && material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + depth_prepass = true; + } + + if (depth_prepass != prev_depth_prepass) { + + state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, depth_prepass); + prev_depth_prepass = depth_prepass; + rebind = true; + } + bool base_pass = !accum_pass && !unshaded; //conditions for a base pass if (base_pass != prev_base_pass) { @@ -2432,6 +2449,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTMAP_CAPTURE, false); state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false); state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false); + state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, 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, const Basis &p_sky_orientation) { @@ -3025,7 +3043,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } - glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + if (storage->frame.current_rt) { + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + } glColorMask(1, 1, 1, 1); } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 0f52a02363..d00d572ccf 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -846,6 +846,17 @@ void RasterizerStorageGLES2::textures_keep_original(bool p_enable) { config.keep_original_textures = p_enable; } +Size2 RasterizerStorageGLES2::texture_size_with_proxy(RID p_texture) const { + + const Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!texture, Size2()); + if (texture->proxy) { + return Size2(texture->proxy->width, texture->proxy->height); + } else { + return Size2(texture->width, texture->height); + } +} + void RasterizerStorageGLES2::texture_set_proxy(RID p_texture, RID p_proxy) { Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index ed21238db6..ba48ddd185 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -342,6 +342,7 @@ public: virtual void textures_keep_original(bool p_enable); virtual void texture_set_proxy(RID p_texture, RID p_proxy); + virtual Size2 texture_size_with_proxy(RID p_texture) const; virtual void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index bff031b93a..d6e8edc421 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -318,7 +318,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener uniform_code += "uniform "; - uniform_code += _prestr(E->get().precission); + uniform_code += _prestr(E->get().precision); uniform_code += _typestr(E->get().type); uniform_code += " "; uniform_code += _mkid(E->key()); @@ -344,7 +344,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener StringBuffer<> varying_code; varying_code += "varying "; - varying_code += _prestr(E->get().precission); + varying_code += _prestr(E->get().precision); varying_code += _typestr(E->get().type); varying_code += " "; varying_code += _mkid(E->key()); @@ -806,9 +806,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; /** SPATIAL SHADER **/ @@ -831,7 +829,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; // gl_InstanceID is not available in OpenGL ES 2.0 actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0"; - actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; //builtins @@ -863,12 +860,15 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions[VS::SHADER_SPATIAL].renames["SIDE"] = "side"; + // Defined in GLES3, but not available in GLES2 + //actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; + actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; //for light actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view"; actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; + actions[VS::SHADER_SPATIAL].renames["LIGHT"] = "light"; actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; @@ -903,6 +903,12 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + // Defined in GLES3, could be implemented in GLES2 too if there's a need for it + //actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; + // Defined in GLES3, might not be possible in GLES2 as gl_FrontFacing is not available + //actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; + //actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; + bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); if (!force_lambert) { @@ -928,27 +934,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - /* PARTICLES SHADER */ - - actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; - actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; - actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; - actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; - actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart"; - actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; - actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; - actions[VS::SHADER_PARTICLES].renames["TIME"] = "time"; - actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; - actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; - actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; - actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; - actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; - actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; - actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; + // No defines for particle shaders in GLES2, there are no GPU particles vertex_name = "vertex"; fragment_name = "fragment"; diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index c4a8c8b990..643b6a5cc9 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -316,9 +316,35 @@ FRAGMENT_SHADER_GLOBALS /* clang-format on */ +void light_compute( + inout vec4 light, + inout vec2 light_vec, + inout float light_height, + inout vec4 light_color, + vec2 light_uv, + inout vec4 shadow_color, + vec3 normal, + vec2 uv, +#if defined(SCREEN_UV_USED) + vec2 screen_uv, +#endif + vec4 color) { + +#if defined(USE_LIGHT_SHADER_CODE) + + /* clang-format off */ + +LIGHT_SHADER_CODE + + /* clang-format on */ + +#endif +} + void main() { vec4 color = color_interp; + vec2 uv = uv_interp; #if !defined(COLOR_USED) //default behavior, texture by color @@ -414,7 +440,6 @@ FRAGMENT_SHADER_CODE color *= light; #ifdef USE_SHADOWS - light_vec = light_uv_interp.zw; //for shadows float angle_to_light = -atan(light_vec.x, light_vec.y); float PI = 3.14159265358979323846264; /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index c7f5c97133..6c3d3baccd 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -1498,6 +1498,12 @@ FRAGMENT_SHADER_CODE } #endif +#ifdef USE_DEPTH_PREPASS + if (alpha < 0.99) { + discard; + } +#endif + #ifdef BASE_PASS //none #ifdef USE_RADIANCE_MAP diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 966466d9bc..31f42493a3 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2343,6 +2343,10 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G state.used_screen_texture = true; } + if (p_material->shader->spatial.uses_depth_texture) { + state.used_depth_texture = true; + } + if (p_depth_pass) { if (has_blend_alpha || p_material->shader->spatial.uses_depth_texture || (has_base_alpha && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES3::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) @@ -3159,6 +3163,7 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase **p_cull_result, int p current_material_index = 0; state.used_sss = false; state.used_screen_texture = false; + state.used_depth_texture = false; //fill list for (int i = 0; i < p_cull_count; i++) { @@ -4169,7 +4174,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glColorMask(1, 1, 1, 1); - if (state.used_contact_shadows) { + if (state.used_contact_shadows || state.used_depth_texture) { glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 325617745a..fbafc59b48 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -204,6 +204,7 @@ public: bool cull_disabled; bool used_sss; bool used_screen_texture; + bool used_depth_texture; bool using_contact_shadows; VS::ViewportDebugDraw debug_draw; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 70037dfc33..4ef7db8ea9 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -112,15 +112,6 @@ void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid }, target, offset, data, size); /* clang-format on */ } - -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data) { - - /* clang-format off */ - EM_ASM({ - GLctx.bufferSubData($0, $1, HEAPU8, $2, $3); - }, target, offset, data, size); - /* clang-format on */ -} #endif void glTexStorage2DCustom(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type) { @@ -1687,6 +1678,17 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ return texture_owner.make_rid(ctex); } +Size2 RasterizerStorageGLES3::texture_size_with_proxy(RID p_texture) const { + + const Texture *texture = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!texture, Size2()); + if (texture->proxy) { + return Size2(texture->proxy->width, texture->proxy->height); + } else { + return Size2(texture->width, texture->height); + } +} + void RasterizerStorageGLES3::texture_set_proxy(RID p_texture, RID p_proxy) { Texture *texture = texture_owner.get(p_texture); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 811f9c8d80..88897e1e07 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -46,7 +46,6 @@ // WebGL 2.0 has no MapBufferRange/UnmapBuffer, but offers a non-ES style BufferSubData API instead. #ifdef __EMSCRIPTEN__ void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); #endif class RasterizerCanvasGLES3; @@ -375,6 +374,8 @@ public: virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); virtual void texture_set_proxy(RID p_texture, RID p_proxy); + virtual Size2 texture_size_with_proxy(RID p_texture) const; + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); /* SKY API */ diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index cda6dac506..da54f7a2af 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -373,7 +373,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener ucode = "uniform "; } - ucode += _prestr(E->get().precission); + ucode += _prestr(E->get().precision); ucode += _typestr(E->get().type); ucode += " " + _mkid(E->key()); ucode += ";\n"; @@ -464,7 +464,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener String vcode; String interp_mode = _interpstr(E->get().interpolation); - vcode += _prestr(E->get().precission); + vcode += _prestr(E->get().precision); vcode += _typestr(E->get().type); vcode += " " + _mkid(E->key()); vcode += ";\n"; @@ -963,9 +963,9 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - actions[VS::SHADER_SPATIAL].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; + actions[VS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; vertex_name = "vertex"; fragment_name = "fragment"; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 974eff86f3..90775c841f 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -549,7 +549,6 @@ FRAGMENT_SHADER_CODE color *= light; #ifdef USE_SHADOWS - light_vec = light_uv_interp.zw; //for shadows float angle_to_light = -atan(light_vec.x, light_vec.y); float PI = 3.14159265358979323846264; /*int i = int(mod(floor((angle_to_light+7.0*PI/6.0)/(4.0*PI/6.0))+1.0, 3.0)); // +1 pq os indices estao em ordem 2,0,1 nos arrays diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index ce1c183242..e3e2e10e82 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -469,6 +469,11 @@ String OS_Unix::get_environment(const String &p_var) const { return ""; } +bool OS_Unix::set_environment(const String &p_var, const String &p_value) const { + + return setenv(p_var.utf8().get_data(), p_value.utf8().get_data(), /* overwrite: */ true) == 0; +} + int OS_Unix::get_processor_count() const { return sysconf(_SC_NPROCESSORS_CONF); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 2a23da6f28..09ab4aa1d8 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -95,6 +95,7 @@ public: virtual bool has_environment(const String &p_var) const; virtual String get_environment(const String &p_var) const; + virtual bool set_environment(const String &p_var, const String &p_value) const; virtual String get_locale() const; virtual int get_processor_count() const; |