diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 4 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_gles3.cpp | 8 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_gles3.h | 2 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 63 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 26 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 131 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 21 | ||||
| -rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 2 | ||||
| -rw-r--r-- | drivers/gles3/shaders/copy.glsl | 43 | ||||
| -rw-r--r-- | drivers/gles3/shaders/cubemap_filter.glsl | 35 | ||||
| -rw-r--r-- | drivers/png/image_loader_png.cpp | 42 | ||||
| -rw-r--r-- | drivers/png/image_loader_png.h | 4 | ||||
| -rw-r--r-- | drivers/png/resource_saver_png.cpp | 26 | ||||
| -rw-r--r-- | drivers/png/resource_saver_png.h | 3 |
14 files changed, 248 insertions, 162 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 60282fb3fa..3c543365f0 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -342,12 +342,12 @@ void RasterizerGLES2::_draw_primitive(int p_points, const Vector3 *p_vertices, c /* TEXTURE API */ -Image RasterizerGLES2::_get_gl_image_and_format(const Image &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, int &r_gl_components, bool &r_has_alpha_cache, bool &r_compressed) { +Ref<Image> RasterizerGLES2::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, int &r_gl_components, bool &r_has_alpha_cache, bool &r_compressed) { r_has_alpha_cache = false; r_compressed = false; r_gl_format = 0; - Image image = p_image; + Ref<Image> image = p_image; switch (p_format) { diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index db814ec721..aa4150cbe4 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -271,9 +271,9 @@ void RasterizerGLES3::clear_render_target(const Color &p_color) { storage->frame.clear_request_color = p_color; } -void RasterizerGLES3::set_boot_image(const Image &p_image, const Color &p_color, bool p_scale) { +void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale) { - if (p_image.empty()) + if (p_image.is_null() || p_image->empty()) return; begin_frame(); @@ -290,10 +290,10 @@ void RasterizerGLES3::set_boot_image(const Image &p_image, const Color &p_color, canvas->canvas_begin(); RID texture = storage->texture_create(); - storage->texture_allocate(texture, p_image.get_width(), p_image.get_height(), p_image.get_format(), VS::TEXTURE_FLAG_FILTER); + storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), p_image->get_format(), VS::TEXTURE_FLAG_FILTER); storage->texture_set_data(texture, p_image); - Rect2 imgrect(0, 0, p_image.get_width(), p_image.get_height()); + Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); Rect2 screenrect; if (p_scale) { diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 12014cd814..ce18d6b6c1 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -48,7 +48,7 @@ public: virtual RasterizerCanvas *get_canvas(); virtual RasterizerScene *get_scene(); - virtual void set_boot_image(const Image &p_image, const Color &p_color, bool p_scale); + virtual void set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale); virtual void initialize(); virtual void begin_frame(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index a7996b09d3..5214de6d06 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -798,20 +798,20 @@ void RasterizerSceneGLES3::environment_set_background(RID p_env, VS::Environment env->bg_mode = p_bg; } -void RasterizerSceneGLES3::environment_set_skybox(RID p_env, RID p_skybox) { +void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - env->skybox = p_skybox; + env->sky = p_sky; } -void RasterizerSceneGLES3::environment_set_skybox_scale(RID p_env, float p_scale) { +void RasterizerSceneGLES3::environment_set_sky_scale(RID p_env, float p_scale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); - env->skybox_scale = p_scale; + env->sky_scale = p_scale; } void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) { @@ -836,14 +836,14 @@ void RasterizerSceneGLES3::environment_set_canvas_max_layer(RID p_env, int p_max env->canvas_max_layer = p_max_layer; } -void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_skybox_contribution) { +void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy, float p_sky_contribution) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); env->ambient_color = p_color; env->ambient_energy = p_energy; - env->ambient_skybox_contribution = p_skybox_contribution; + env->ambient_sky_contribution = p_sky_contribution; } void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { @@ -2120,12 +2120,12 @@ void RasterizerSceneGLES3::_add_geometry(RasterizerStorageGLES3::Geometry *p_geo } } -void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale) { +void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale) { - if (!p_skybox) + if (!p_sky) return; - RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_skybox->cubemap); + RasterizerStorageGLES3::Texture *tex = storage->texture_owner.getornull(p_sky->panorama); ERR_FAIL_COND(!tex); glActiveTexture(GL_TEXTURE0); @@ -2164,7 +2164,7 @@ void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox }; - //skybox uv vectors + //sky uv vectors float vw, vh, zn; p_projection.get_viewport_size(vw, vh); zn = p_projection.get_z_near(); @@ -2181,13 +2181,13 @@ void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z; } - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector3) * 8, vertices); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glBindVertexArray(state.skybox_array); + glBindVertexArray(state.sky_array); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, true); storage->shaders.copy.bind(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -2195,7 +2195,7 @@ void RasterizerSceneGLES3::_draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox glBindVertexArray(0); glColorMask(1, 1, 1, 1); - storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_CUBEMAP, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform) { @@ -2239,7 +2239,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.bg_color[2] = bg_color.b; state.ubo_data.bg_color[3] = bg_color.a; - state.env_radiance_data.ambient_contribution = env->ambient_skybox_contribution; + state.env_radiance_data.ambient_contribution = env->ambient_sky_contribution; state.ubo_data.ambient_occlusion_affect_light = env->ssao_light_affect; } else { state.ubo_data.bg_energy = 1.0; @@ -2683,7 +2683,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul ambient_linear.r *= p_env->ambient_energy; ambient_linear.g *= p_env->ambient_energy; ambient_linear.b *= p_env->ambient_energy; - contrib = p_env->ambient_skybox_contribution; + contrib = p_env->ambient_sky_contribution; } reflection_ubo.ambient[0] = ambient_linear.r; @@ -3807,7 +3807,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const Color clear_color(0, 0, 0, 0); - RasterizerStorageGLES3::SkyBox *skybox = NULL; + RasterizerStorageGLES3::Sky *sky = NULL; GLuint env_radiance_tex = 0; if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR) { @@ -3822,12 +3822,12 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const clear_color = env->bg_color.to_linear(); storage->frame.clear_request = false; - } else if (env->bg_mode == VS::ENV_BG_SKYBOX) { + } else if (env->bg_mode == VS::ENV_BG_SKY) { - skybox = storage->skybox_owner.getornull(env->skybox); + sky = storage->sky_owner.getornull(env->sky); - if (skybox) { - env_radiance_tex = skybox->radiance; + if (sky) { + env_radiance_tex = sky->radiance; } storage->frame.clear_request = false; @@ -3878,14 +3878,14 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glDrawBuffers(1, &gldb); } - if (env && env->bg_mode == VS::ENV_BG_SKYBOX) { + if (env && env->bg_mode == VS::ENV_BG_SKY) { /* if (use_mrt) { - glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for skybox, only diffuse/ambient matters + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters */ - _draw_skybox(skybox, p_cam_projection, p_cam_transform, storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP], env->skybox_scale); + _draw_sky(sky, p_cam_projection, p_cam_transform, storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_VFLIP], env->sky_scale); } //_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true); @@ -4585,14 +4585,14 @@ void RasterizerSceneGLES3::initialize() { { //quad buffers - glGenBuffers(1, &state.skybox_verts); - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glGenBuffers(1, &state.sky_verts); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, NULL, GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind - glGenVertexArrays(1, &state.skybox_array); - glBindVertexArray(state.skybox_array); - glBindBuffer(GL_ARRAY_BUFFER, state.skybox_verts); + glGenVertexArrays(1, &state.sky_array); + glBindVertexArray(state.sky_array); + glBindBuffer(GL_ARRAY_BUFFER, state.sky_verts); glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); glEnableVertexAttribArray(VS::ARRAY_VERTEX); glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, ((uint8_t *)NULL) + sizeof(Vector3)); @@ -4831,7 +4831,12 @@ void RasterizerSceneGLES3::initialize() { glGenTextures(1, &e.color); glBindTexture(GL_TEXTURE_2D, e.color); +#ifdef IPHONE_ENABLED + ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); +#else glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); +#endif glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 33698fc267..69a7e40604 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -141,8 +141,8 @@ public: GLuint brdf_texture; - GLuint skybox_verts; - GLuint skybox_array; + GLuint sky_verts; + GLuint sky_array; GLuint directional_ubo; @@ -329,16 +329,16 @@ public: VS::EnvironmentBG bg_mode; - RID skybox; - float skybox_scale; + RID sky; + float sky_scale; Color bg_color; float bg_energy; - float skybox_ambient; + float sky_ambient; Color ambient_color; float ambient_energy; - float ambient_skybox_contribution; + float ambient_sky_contribution; int canvas_max_layer; @@ -393,11 +393,11 @@ public: Environment() { bg_mode = VS::ENV_BG_CLEAR_COLOR; - skybox_scale = 1.0; + sky_scale = 1.0; bg_energy = 1.0; - skybox_ambient = 0; + sky_ambient = 0; ambient_energy = 1.0; - ambient_skybox_contribution = 0.0; + ambient_sky_contribution = 0.0; canvas_max_layer = 0; ssr_enabled = false; @@ -455,12 +455,12 @@ public: virtual RID environment_create(); virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); - virtual void environment_set_skybox(RID p_env, RID p_skybox); - virtual void environment_set_skybox_scale(RID p_env, float p_scale); + virtual void environment_set_sky(RID p_env, RID p_sky); + virtual void environment_set_sky_scale(RID p_env, float p_scale); virtual void environment_set_bg_color(RID p_env, const Color &p_color); virtual void environment_set_bg_energy(RID p_env, float p_energy); virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer); - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_skybox_contribution = 0.0); + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality); virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_far_amount, VS::EnvironmentDOFBlurQuality p_quality); @@ -700,7 +700,7 @@ public: _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_shadow); - void _draw_skybox(RasterizerStorageGLES3::SkyBox *p_skybox, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale); + void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale); void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform); void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transformm, bool p_use_shadows); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 1025acceb4..08ff687510 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -101,11 +101,11 @@ GLuint RasterizerStorageGLES3::system_fbo = 0; -Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) { +Ref<Image> RasterizerStorageGLES3::_get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool &srgb) { r_compressed = false; r_gl_format = 0; - Image image = p_image; + Ref<Image> image = p_image; srgb = false; bool need_decompress = false; @@ -538,16 +538,17 @@ Image RasterizerStorageGLES3::_get_gl_image_and_format(const Image &p_image, Ima } break; default: { - ERR_FAIL_V(Image()); + ERR_FAIL_V(Ref<Image>()); } } if (need_decompress) { - if (!image.empty()) { - image.decompress(); - ERR_FAIL_COND_V(image.is_compressed(), image); - image.convert(Image::FORMAT_RGBA8); + if (!image.is_null()) { + image = image->duplicate(); + image->decompress(); + ERR_FAIL_COND_V(image->is_compressed(), image); + image->convert(Image::FORMAT_RGBA8); } r_gl_format = GL_RGBA; @@ -607,7 +608,7 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_ texture->stored_cube_sides = 0; texture->target = (p_flags & VS::TEXTURE_FLAG_CUBEMAP) ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; - _get_gl_image_and_format(Image(), texture->format, texture->flags, format, internal_format, type, compressed, srgb); + _get_gl_image_and_format(Ref<Image>(), texture->format, texture->flags, format, internal_format, type, compressed, srgb); texture->alloc_width = texture->width; texture->alloc_height = texture->height; @@ -631,15 +632,15 @@ void RasterizerStorageGLES3::texture_allocate(RID p_texture, int p_width, int p_ texture->active = true; } -void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Image &p_image, VS::CubeMapSide p_cube_side) { +void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side) { Texture *texture = texture_owner.get(p_texture); ERR_FAIL_COND(!texture); ERR_FAIL_COND(!texture->active); ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(texture->format != p_image.get_format()); - ERR_FAIL_COND(p_image.empty()); + ERR_FAIL_COND(texture->format != p_image->get_format()); + ERR_FAIL_COND(p_image.is_null()); GLenum type; GLenum format; @@ -651,31 +652,31 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Image &p_imag texture->images[p_cube_side] = p_image; } - Image img = _get_gl_image_and_format(p_image, p_image.get_format(), texture->flags, format, internal_format, type, compressed, srgb); + Ref<Image> img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, format, internal_format, type, compressed, srgb); - if (config.shrink_textures_x2 && (p_image.has_mipmaps() || !p_image.is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { texture->alloc_height = MAX(1, texture->alloc_height / 2); texture->alloc_width = MAX(1, texture->alloc_width / 2); - if (texture->alloc_width == img.get_width() / 2 && texture->alloc_height == img.get_height() / 2) { + if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { - img.shrink_x2(); - } else if (img.get_format() <= Image::FORMAT_RGB565) { + img->shrink_x2(); + } else if (img->get_format() <= Image::FORMAT_RGB565) { - img.resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); + img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); } }; GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_cube_side] : GL_TEXTURE_2D; - texture->data_size = img.get_data().size(); - PoolVector<uint8_t>::Read read = img.get_data().read(); + texture->data_size = img->get_data().size(); + PoolVector<uint8_t>::Read read = img->get_data().read(); glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); - texture->ignore_mipmaps = compressed && !img.has_mipmaps(); + texture->ignore_mipmaps = compressed && !img->has_mipmaps(); if (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && !texture->ignore_mipmaps) glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); @@ -761,16 +762,16 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Image &p_imag } } - int mipmaps = (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && img.has_mipmaps()) ? img.get_mipmap_count() + 1 : 1; + int mipmaps = (texture->flags & VS::TEXTURE_FLAG_MIPMAPS && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; - int w = img.get_width(); - int h = img.get_height(); + int w = img->get_width(); + int h = img->get_height(); int tsize = 0; for (int i = 0; i < mipmaps; i++) { int size, ofs; - img.get_mipmap_offset_and_size(i, ofs, size); + img->get_mipmap_offset_and_size(i, ofs, size); //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h)); @@ -813,16 +814,16 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Image &p_imag //texture_set_flags(p_texture,texture->flags); } -Image RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const { +Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side) const { Texture *texture = texture_owner.get(p_texture); - ERR_FAIL_COND_V(!texture, Image()); - ERR_FAIL_COND_V(!texture->active, Image()); - ERR_FAIL_COND_V(texture->data_size == 0, Image()); - ERR_FAIL_COND_V(texture->render_target, Image()); + ERR_FAIL_COND_V(!texture, Ref<Image>()); + ERR_FAIL_COND_V(!texture->active, Ref<Image>()); + ERR_FAIL_COND_V(texture->data_size == 0, Ref<Image>()); + ERR_FAIL_COND_V(texture->render_target, Ref<Image>()); - if (!texture->images[p_cube_side].empty()) { + if (!texture->images[p_cube_side].is_null()) { return texture->images[p_cube_side]; } @@ -867,13 +868,13 @@ Image RasterizerStorageGLES3::texture_get_data(RID p_texture, VS::CubeMapSide p_ data.resize(data_size); - Image img(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, texture->format, data); + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, texture->mipmaps > 1 ? true : false, texture->format, data)); - return img; + return Ref<Image>(img); #else ERR_EXPLAIN("Sorry, It's not posible to obtain images back in OpenGL ES"); - return Image(); + return Ref<Image>(); #endif } @@ -969,6 +970,14 @@ Image::Format RasterizerStorageGLES3::texture_get_format(RID p_texture) const { return texture->format; } +uint32_t RasterizerStorageGLES3::texture_get_texid(RID p_texture) const { + + Texture *texture = texture_owner.get(p_texture); + + ERR_FAIL_COND_V(!texture, 0); + + return texture->tex_id; +} uint32_t RasterizerStorageGLES3::texture_get_width(RID p_texture) const { Texture *texture = texture_owner.get(p_texture); @@ -1204,32 +1213,32 @@ RID RasterizerStorageGLES3::texture_create_radiance_cubemap(RID p_source, int p_ return texture_owner.make_rid(ctex); } -RID RasterizerStorageGLES3::skybox_create() { +RID RasterizerStorageGLES3::sky_create() { - SkyBox *skybox = memnew(SkyBox); - skybox->radiance = 0; - return skybox_owner.make_rid(skybox); + Sky *sky = memnew(Sky); + sky->radiance = 0; + return sky_owner.make_rid(sky); } -void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, int p_radiance_size) { +void RasterizerStorageGLES3::sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size) { - SkyBox *skybox = skybox_owner.getornull(p_skybox); - ERR_FAIL_COND(!skybox); + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); - if (skybox->cubemap.is_valid()) { - skybox->cubemap = RID(); - glDeleteTextures(1, &skybox->radiance); - skybox->radiance = 0; + if (sky->panorama.is_valid()) { + sky->panorama = RID(); + glDeleteTextures(1, &sky->radiance); + sky->radiance = 0; } - skybox->cubemap = p_cube_map; - if (!skybox->cubemap.is_valid()) + sky->panorama = p_panorama; + if (!sky->panorama.is_valid()) return; //cleared - Texture *texture = texture_owner.getornull(skybox->cubemap); - if (!texture || !(texture->flags & VS::TEXTURE_FLAG_CUBEMAP)) { - skybox->cubemap = RID(); - ERR_FAIL_COND(!texture || !(texture->flags & VS::TEXTURE_FLAG_CUBEMAP)); + Texture *texture = texture_owner.getornull(sky->panorama); + if (!texture) { + sky->panorama = RID(); + ERR_FAIL_COND(!texture); } glBindVertexArray(0); @@ -1254,8 +1263,8 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in } glActiveTexture(GL_TEXTURE1); - glGenTextures(1, &skybox->radiance); - glBindTexture(GL_TEXTURE_2D, skybox->radiance); + glGenTextures(1, &sky->radiance); + glBindTexture(GL_TEXTURE_2D, sky->radiance); GLuint tmp_fb; @@ -1295,11 +1304,12 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in size = p_radiance_size; shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, true); + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_PANORAMA, true); shaders.cubemap_filter.bind(); while (mm_level) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, skybox->radiance, lod); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, sky->radiance, lod); #ifdef DEBUG_ENABLED GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE); @@ -1322,6 +1332,7 @@ void RasterizerStorageGLES3::skybox_set_texture(RID p_skybox, RID p_cube_map, in mm_level--; } shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_DUAL_PARABOLOID, false); + shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES3::USE_PANORAMA, false); //restore ranges glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); @@ -6107,12 +6118,12 @@ bool RasterizerStorageGLES3::free(RID p_rid) { info.texture_mem -= texture->total_data_size; texture_owner.free(p_rid); memdelete(texture); - } else if (skybox_owner.owns(p_rid)) { - // delete the skybox - SkyBox *skybox = skybox_owner.get(p_rid); - skybox_set_texture(p_rid, RID(), 256); - skybox_owner.free(p_rid); - memdelete(skybox); + } else if (sky_owner.owns(p_rid)) { + // delete the sky + Sky *sky = sky_owner.get(p_rid); + sky_set_texture(p_rid, RID(), 256); + sky_owner.free(p_rid); + memdelete(sky); } else if (shader_owner.owns(p_rid)) { @@ -6469,7 +6480,7 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind } - //generic quadie for copying without touching skybox + //generic quadie for copying without touching sky { //transform feedback buffers diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index bb4a7e23a1..26b7cea45e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -240,7 +240,7 @@ public: RenderTarget *render_target; - Image images[6]; + Ref<Image> images[6]; VisualServer::TextureDetectCallback detect_3d; void *detect_3d_ud; @@ -280,15 +280,16 @@ public: mutable RID_Owner<Texture> texture_owner; - Image _get_gl_image_and_format(const Image &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_type, bool &r_compressed, bool &srgb); + Ref<Image> _get_gl_image_and_format(const Ref<Image> &p_image, Image::Format p_format, uint32_t p_flags, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_type, bool &r_compressed, bool &srgb); virtual RID texture_create(); virtual void texture_allocate(RID p_texture, int p_width, int p_height, Image::Format p_format, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture, const Image &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const; + virtual void texture_set_data(RID p_texture, const Ref<Image> &p_image, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT); + virtual Ref<Image> texture_get_data(RID p_texture, VS::CubeMapSide p_cube_side = VS::CUBEMAP_LEFT) const; virtual void texture_set_flags(RID p_texture, uint32_t p_flags); virtual uint32_t texture_get_flags(RID p_texture) const; virtual Image::Format texture_get_format(RID p_texture) const; + virtual uint32_t texture_get_texid(RID p_texture) const; virtual uint32_t texture_get_width(RID p_texture) const; virtual uint32_t texture_get_height(RID p_texture) const; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); @@ -307,19 +308,19 @@ public: 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); - /* SKYBOX API */ + /* SKY API */ - struct SkyBox : public RID_Data { + struct Sky : public RID_Data { - RID cubemap; + RID panorama; GLuint radiance; int radiance_size; }; - mutable RID_Owner<SkyBox> skybox_owner; + mutable RID_Owner<Sky> sky_owner; - virtual RID skybox_create(); - virtual void skybox_set_texture(RID p_skybox, RID p_cube_map, int p_radiance_size); + virtual RID sky_create(); + virtual void sky_set_texture(RID p_sky, RID p_panorama, int p_radiance_size); /* SHADER API */ diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 89b056df84..23bcb79b46 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -383,7 +383,7 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener String vcode; vcode += _prestr(E->get().precission); vcode += _typestr(E->get().type); - vcode += " " + String(E->key()); + vcode += " " + _mkid(E->key()); vcode += ";\n"; r_gen_code.vertex_global += "out " + vcode; r_gen_code.fragment_global += "in " + vcode; diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index a87d62f2d7..f3c72a4e6f 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -2,14 +2,14 @@ layout(location=0) in highp vec4 vertex_attrib; -#ifdef USE_CUBEMAP +#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) layout(location=4) in vec3 cube_in; #else layout(location=4) in vec2 uv_in; #endif layout(location=5) in vec2 uv2_in; -#ifdef USE_CUBEMAP +#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) out vec3 cube_interp; #else out vec2 uv_interp; @@ -19,7 +19,7 @@ out vec2 uv2_interp; void main() { -#ifdef USE_CUBEMAP +#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) cube_interp = cube_in; #else uv_interp = uv_in; @@ -30,15 +30,40 @@ void main() { [fragment] +#define M_PI 3.14159265359 -#ifdef USE_CUBEMAP + +#if defined(USE_CUBEMAP) || defined(USE_PANORAMA) in vec3 cube_interp; -uniform samplerCube source_cube; //texunit:0 #else in vec2 uv_interp; +#endif + +#ifdef USE_CUBEMAP +uniform samplerCube source_cube; //texunit:0 +#else uniform sampler2D source; //texunit:0 #endif +#ifdef USE_PANORAMA + +vec4 texturePanorama(vec3 normal,sampler2D pano ) { + + vec2 st = vec2( + atan(normal.x, normal.z), + acos(normal.y) + ); + + if(st.x < 0.0) + st.x += M_PI*2.0; + + st/=vec2(M_PI*2.0,M_PI); + + return textureLod(pano,st,0.0); + +} + +#endif float sRGB_gamma_correct(float c){ float a = 0.055; @@ -60,13 +85,19 @@ void main() { //vec4 color = color_interp; -#ifdef USE_CUBEMAP +#ifdef USE_PANORAMA + + vec4 color = texturePanorama( normalize(cube_interp), source ); + +#elif defined(USE_CUBEMAP) vec4 color = texture( source_cube, normalize(cube_interp) ); #else vec4 color = texture( source, uv_interp ); #endif + + #ifdef LINEAR_TO_SRGB //regular Linear -> SRGB conversion vec3 a = vec3(0.055); diff --git a/drivers/gles3/shaders/cubemap_filter.glsl b/drivers/gles3/shaders/cubemap_filter.glsl index 768d20ad22..2aec6380f5 100644 --- a/drivers/gles3/shaders/cubemap_filter.glsl +++ b/drivers/gles3/shaders/cubemap_filter.glsl @@ -19,8 +19,12 @@ void main() { precision highp float; precision highp int; - +#ifdef USE_PANORAMA +uniform sampler2D source_panorama; //texunit:0 +#else uniform samplerCube source_cube; //texunit:0 +#endif + uniform int face_id; uniform float roughness; in highp vec2 uv_interp; @@ -165,6 +169,26 @@ vec2 Hammersley(uint i, uint N) { uniform bool z_flip; +#ifdef USE_PANORAMA + +vec4 texturePanorama(vec3 normal,sampler2D pano ) { + + vec2 st = vec2( + atan(normal.x, normal.z), + acos(normal.y) + ); + + if(st.x < 0.0) + st.x += M_PI*2.0; + + st/=vec2(M_PI*2.0,M_PI); + + return textureLod(pano,st,0.0); + +} + +#endif + void main() { #ifdef USE_DUAL_PARABOLOID @@ -188,7 +212,12 @@ void main() { #ifdef USE_DIRECT_WRITE +#ifdef USE_PANORAMA + + frag_color=vec4(texturePanorama(N,source_panorama).rgb,1.0); +#else frag_color=vec4(texture(N,source_cube).rgb,1.0); +#endif #else @@ -204,7 +233,11 @@ void main() { float ndotl = clamp(dot(N, L),0.0,1.0); if (ndotl>0.0) { +#ifdef USE_PANORAMA + sum.rgb += texturePanorama(H,source_panorama).rgb *ndotl; +#else sum.rgb += textureLod(source_cube, H, 0.0).rgb *ndotl; +#endif sum.a += ndotl; } } diff --git a/drivers/png/image_loader_png.cpp b/drivers/png/image_loader_png.cpp index c9677bed11..fe2372e3af 100644 --- a/drivers/png/image_loader_png.cpp +++ b/drivers/png/image_loader_png.cpp @@ -68,7 +68,7 @@ static void _png_warn_function(png_structp, png_const_charp text) { typedef void(PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Image *p_image) { +Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image) { png_structp png; png_infop info; @@ -201,7 +201,7 @@ Error ImageLoaderPNG::_load_image(void *rf_up, png_rw_ptr p_func, Image *p_image return OK; } -Error ImageLoaderPNG::load_image(Image *p_image, FileAccess *f) { +Error ImageLoaderPNG::load_image(Ref<Image> p_image, FileAccess *f) { Error err = _load_image(f, _read_png_data, p_image); f->close(); @@ -238,25 +238,26 @@ static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t p_len } } -static Image _load_mem_png(const uint8_t *p_png, int p_size) { +static Ref<Image> _load_mem_png(const uint8_t *p_png, int p_size) { PNGReadStatus prs; prs.image = p_png; prs.offset = 0; prs.size = p_size; - Image img; - Error err = ImageLoaderPNG::_load_image(&prs, user_read_data, &img); - ERR_FAIL_COND_V(err, Image()); + Ref<Image> img; + img.instance(); + Error err = ImageLoaderPNG::_load_image(&prs, user_read_data, img); + ERR_FAIL_COND_V(err, Ref<Image>()); return img; } -static Image _lossless_unpack_png(const PoolVector<uint8_t> &p_data) { +static Ref<Image> _lossless_unpack_png(const PoolVector<uint8_t> &p_data) { int len = p_data.size(); PoolVector<uint8_t>::Read r = p_data.read(); - ERR_FAIL_COND_V(r[0] != 'P' || r[1] != 'N' || r[2] != 'G' || r[3] != ' ', Image()); + ERR_FAIL_COND_V(r[0] != 'P' || r[1] != 'N' || r[2] != 'G' || r[3] != ' ', Ref<Image>()); return _load_mem_png(&r[4], len - 4); } @@ -271,13 +272,14 @@ static void _write_png_data(png_structp png_ptr, png_bytep data, png_size_t p_le //print_line("png write: "+itos(p_length)); } -static PoolVector<uint8_t> _lossless_pack_png(const Image &p_image) { +static PoolVector<uint8_t> _lossless_pack_png(const Ref<Image> &p_image) { - Image img = p_image; - if (img.is_compressed()) - img.decompress(); + Ref<Image> img = p_image->duplicate(); - ERR_FAIL_COND_V(img.is_compressed(), PoolVector<uint8_t>()); + if (img->is_compressed()) + img->decompress(); + + ERR_FAIL_COND_V(img->is_compressed(), PoolVector<uint8_t>()); png_structp png_ptr; png_infop info_ptr; @@ -311,7 +313,7 @@ static PoolVector<uint8_t> _lossless_pack_png(const Image &p_image) { int pngf = 0; int cs = 0; - switch (img.get_format()) { + switch (img->get_format()) { case Image::FORMAT_L8: { @@ -335,22 +337,22 @@ static PoolVector<uint8_t> _lossless_pack_png(const Image &p_image) { } break; default: { - if (img.detect_alpha()) { + if (img->detect_alpha()) { - img.convert(Image::FORMAT_RGBA8); + img->convert(Image::FORMAT_RGBA8); pngf = PNG_COLOR_TYPE_RGB_ALPHA; cs = 4; } else { - img.convert(Image::FORMAT_RGB8); + img->convert(Image::FORMAT_RGB8); pngf = PNG_COLOR_TYPE_RGB; cs = 3; } } } - int w = img.get_width(); - int h = img.get_height(); + int w = img->get_width(); + int h = img->get_height(); png_set_IHDR(png_ptr, info_ptr, w, h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -362,7 +364,7 @@ static PoolVector<uint8_t> _lossless_pack_png(const Image &p_image) { ERR_FAIL_V(PoolVector<uint8_t>()); } - PoolVector<uint8_t>::Read r = img.get_data().read(); + PoolVector<uint8_t>::Read r = img->get_data().read(); row_pointers = (png_bytep *)memalloc(sizeof(png_bytep) * h); for (int i = 0; i < h; i++) { diff --git a/drivers/png/image_loader_png.h b/drivers/png/image_loader_png.h index 78e4252e26..f94b8bce6e 100644 --- a/drivers/png/image_loader_png.h +++ b/drivers/png/image_loader_png.h @@ -42,8 +42,8 @@ class ImageLoaderPNG : public ImageFormatLoader { static void _read_png_data(png_structp png_ptr, png_bytep data, png_size_t p_length); public: - static Error _load_image(void *rf_up, png_rw_ptr p_func, Image *p_image); - virtual Error load_image(Image *p_image, FileAccess *f); + static Error _load_image(void *rf_up, png_rw_ptr p_func, Ref<Image> p_image); + virtual Error load_image(Ref<Image> p_image, FileAccess *f); virtual void get_recognized_extensions(List<String> *p_extensions) const; ImageLoaderPNG(); }; diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index b754ef97b4..1700603489 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -50,7 +50,7 @@ Error ResourceSaverPNG::save(const String &p_path, const RES &p_resource, uint32 ERR_EXPLAIN("Can't save empty texture as PNG"); ERR_FAIL_COND_V(!texture->get_width() || !texture->get_height(), ERR_INVALID_PARAMETER); - Image img = texture->get_data(); + Ref<Image> img = texture->get_data(); Error err = save_image(p_path, img); @@ -95,12 +95,14 @@ Error ResourceSaverPNG::save(const String &p_path, const RES &p_resource, uint32 return err; }; -Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { +Error ResourceSaverPNG::save_image(const String &p_path, const Ref<Image> &p_img) { - if (p_img.is_compressed()) - p_img.decompress(); + Ref<Image> img = p_img->duplicate(); - ERR_FAIL_COND_V(p_img.is_compressed(), ERR_INVALID_PARAMETER); + if (img->is_compressed()) + img->decompress(); + + ERR_FAIL_COND_V(img->is_compressed(), ERR_INVALID_PARAMETER); png_structp png_ptr; png_infop info_ptr; @@ -135,7 +137,7 @@ Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { int pngf = 0; int cs = 0; - switch (p_img.get_format()) { + switch (img->get_format()) { case Image::FORMAT_L8: { @@ -159,22 +161,22 @@ Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { } break; default: { - if (p_img.detect_alpha()) { + if (img->detect_alpha()) { - p_img.convert(Image::FORMAT_RGBA8); + img->convert(Image::FORMAT_RGBA8); pngf = PNG_COLOR_TYPE_RGB_ALPHA; cs = 4; } else { - p_img.convert(Image::FORMAT_RGB8); + img->convert(Image::FORMAT_RGB8); pngf = PNG_COLOR_TYPE_RGB; cs = 3; } } } - int w = p_img.get_width(); - int h = p_img.get_height(); + int w = img->get_width(); + int h = img->get_height(); png_set_IHDR(png_ptr, info_ptr, w, h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -187,7 +189,7 @@ Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { ERR_FAIL_V(ERR_CANT_OPEN); } - PoolVector<uint8_t>::Read r = p_img.get_data().read(); + PoolVector<uint8_t>::Read r = img->get_data().read(); row_pointers = (png_bytep *)memalloc(sizeof(png_bytep) * h); for (int i = 0; i < h; i++) { diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index c25a01c1f6..31ec35c192 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -30,11 +30,12 @@ #ifndef RESOURCE_SAVER_PNG_H #define RESOURCE_SAVER_PNG_H +#include "image.h" #include "io/resource_saver.h" class ResourceSaverPNG : public ResourceFormatSaver { public: - static Error save_image(const String &p_path, Image &p_img); + static Error save_image(const String &p_path, const Ref<Image> &p_img); virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); virtual bool recognize(const RES &p_resource) const; |