Optimize SVG images and convert most PNG images to WebP

master
Aaron Franke 2022-07-03 17:46:38 -05:00
parent 726822f3a7
commit c4777a66d4
No known key found for this signature in database
GPG Key ID: 40A1750B977E56BF
170 changed files with 81 additions and 356 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@
*.obj
*.pyc
*.tmp
.DS_Store

View File

@ -18,7 +18,7 @@ The mesher has a `library` property of type `VoxelBlockyLibrary`. This is a reso
First, set how many voxel types you need by setting the `voxel_count` property. If you need more later, you can increase it.
A list of voxel types is shown below:
![Screenshot of the list of voxels in VoxelBlockyLibrary](images/voxel_library_voxels_list.png)
![Screenshot of the list of voxels in VoxelBlockyLibrary](images/voxel_library_voxels_list.webp)
Each slot can contain a `VoxelBlockyModel` resource. The index shown on their left will be the ID they use in voxel data. Voxel `0` is a special case: by convention, it may be used as the default "air" voxel. You may assign a new `VoxelBlockyModel` resource to each slot, and fill in their properties.
@ -30,25 +30,25 @@ A simple start is to set the `geometry_type` to `Cube`, so the voxel will be a c
With this mesher, using atlases is recommended to allow re-using materials and reduce the number of draw calls. You can create a texture containing all the tiles your voxels can use. For example, here is one from the [blocky game](https://github.com/Zylann/voxelgame/tree/master/project/blocky_game) demo:
![Atlas used in the blocky game demo](images/blocky_game_atlas.png)
![Atlas used in the blocky game demo](images/blocky_game_atlas.webp)
This atlas is a square texture and can contain up to 16x16 tiles. This number is important and needs to be set on the `VoxelBlockyLibrary` `atlas_size` property, so texture coordinates can be generated properly when you use the `Cube` geometry type:
![VoxelBlockyLibrary atlas size property screenshot](images/voxel_library_atlas_size_property.png)
![VoxelBlockyLibrary atlas size property screenshot](images/voxel_library_atlas_size_property.webp)
Voxel types using the `Cube` geometry can have different tiles on each of their faces. You can decide which one to use by assigning properties of `Voxel`, under the `Cube tiles` category. Coordinates here are in tiles, not pixels.
![Voxel cube tile properties screenshot](images/voxel_cube_tiles_properties.png)
![Voxel cube tile properties screenshot](images/voxel_cube_tiles_properties.webp)
For example, if you want to use the "planks" tile, you may use x=3 and y=1:
![Tile coordinates](images/cube_tile_coordinates.png)
![Tile coordinates](images/cube_tile_coordinates.webp)
So far we defined a cubic voxel with specific texture coordinates on its faces, but we still have to actually assign the texture and material used to render it. This can be done in the `Material overrides` section, in which you can assign a material with the texture in it.
Make sure to assign its `albedo_texture` to your texture. You may also check the `Vertex Color/Use as albedo` property, because this will allow the mesher to bake ambient occlusion on the edge of cubes.
![Material for blocky terrain](images/material_blocky_game.png)
![Material for blocky terrain](images/material_blocky_game.webp)
Each model can use different materials with different textures, but keep in mind the more you re-use materials, the better. It reduces the number of draw calls and makes rendering faster.
@ -56,7 +56,7 @@ Each model can use different materials with different textures, but keep in mind
Creating voxel types with the `Cube` geometry is a shortcut that can be used for simple voxels, but the most versatile workflow is to use actual meshes. If you change `geometry_type` to `CustomMesh`, you are allowed to assign a mesh resource. In this mode, the `Cube tiles` properties are not available, because you will have to assign texture coordinates of the mesh within a 3D modeler like Blender.
![Blender screenshot for UV editing a block](images/blender_block_uv_mapping.png)
![Blender screenshot for UV editing a block](images/blender_block_uv_mapping.webp)
Meshes can have any shape you want, however there are a few constraints to respect:
@ -66,7 +66,7 @@ Meshes can have any shape you want, however there are a few constraints to respe
- Keep it low-poly. The mesher can deal with large models, but performance can decrease very quickly if a complex model appears a lot of times.
- Faces lying on the sides of the 1x1x1 unit cube will be the only faces that can be culled by the mesher. Make sure they are perfectly lining up. If they don't, it can cause dramatic slowdowns due to the amount of generated geometry not getting culled.
![Blender screenshot for face lining up with cube side](images/blender_face_cube_side.png)
![Blender screenshot for face lining up with cube side](images/blender_face_cube_side.webp)
The best format to use to export your meshes is OBJ. Godot imports this format by default as a mesh resource. Other formats are not suitable because Godot imports them as scenes, and `VoxelBlockyModel` resources require meshes, not scenes.
You can choose to export materials from here too, but it is recommended to do it in Godot because it allows you to re-use them.
@ -101,13 +101,13 @@ Both require to use a different material from the default one you may have used.
`VoxelBlockyModel` resources also have a `transparency_index` property. This property allows to tune how two voxels occlude their faces. For example, let's say you have two transparent voxels, glass and leaves. By default, if you put them next to each other, the face they share will be culled, allowing you to see through the leaves from the glass block:
![Screenshot of transparency index not being exploited](images/transparency_index_example1.png)
![Screenshot of transparency index not being exploited](images/transparency_index_example1.webp)
If two faces touch each other, if they have the same transparency index, they can get culled. But if their transparency index is different, they may not. This allows to see the leaves directly behind glass, instead of seeing the insides.
Here, glass has `transparency_index=2`, and leaves have `transparency_index=1`:
![Screenshot of transparency index being exploited](images/transparency_index_example2.png)
![Screenshot of transparency index being exploited](images/transparency_index_example2.webp)
### Random tick

View File

@ -4,7 +4,7 @@ Editor
Previewing in the editor
---------------------------
![Screemshot of the editor](images/editor_preview_smooth_2d_noise_terrain.png)
![Screemshot of the editor](images/editor_preview_smooth_2d_noise_terrain.webp)
### Preview options
@ -14,7 +14,7 @@ If the generator or stream is providing a type of voxel data which is not suppor
The whole terrain can be told to re-mesh or re-load by using one of the options in the `Terrain` menu:
![Re-generate menu](images/menu_regenerate.png)
![Re-generate menu](images/menu_regenerate.webp)
!!! warning
If you use a script on either [VoxelGeneratorScript](api/VoxelGeneratorScript.md) or [VoxelStreamScript](api/VoxelStreamScript.md), the `run_stream_in_editor` option will automatically turn off and the volume will not be visible. If a script gets modified while it is used by a thread in the editor, unpredictable bugs can happen. You can force it by enabling the option, but you have to make sure no change happens. This limitation is tracked in [issue177](https://github.com/Zylann/godot_voxel/issues/177).
@ -24,7 +24,7 @@ The whole terrain can be told to re-mesh or re-load by using one of the options
Blocks will only load around the node's origin by default. If the volume is very big or uses LOD, it will not load further and concentrate detail at its center. You can override this by going in the `Terrain` menu and enabling `Stream follow camera`. This will make the terrain adapt its level of detail and blocks to be around the editor's camera, and will update as the camera moves. Turning off the option will freeze the terrain.
![Stream follow camera menu](images/menu_stream_follow_camera.png)
![Stream follow camera menu](images/menu_stream_follow_camera.webp)
This option exists for large volumes because they need to stream blocks in and out as you move around. While this is often done in a controlled manner in a game, in the editor the camera could be moving very fast without any restriction, which can demand much more work for the CPU.
You can monitor the amount of ongoing tasks in the bottom panel, while the node is selected.

View File

@ -29,19 +29,19 @@ The following screenshots use a smooth `VoxelLodTerrain`.
Generates a flat ground.
![Screenshot of flat generator](images/generator_flat.png)
![Screenshot of flat generator](images/generator_flat.webp)
### [Waves](api/VoxelGeneratorWaves.md)
Generates waves.
![Screenshot of waves generator](images/generator_waves.png)
![Screenshot of waves generator](images/generator_waves.webp)
### [Image](api/VoxelGeneratorImage.md)
Generates a heightmap based on an image, repeated infinitely.
![Screenshot of image generator](images/generator_image.png)
![Screenshot of image generator](images/generator_image.webp)
!!! note
With this generator, an `Image` resource is required. By default, Godot imports image files as `StreamTexture`. You may change this in the Import dock. At time of writing, in Godot 3, this requires an editor restart.
@ -50,13 +50,13 @@ Generates a heightmap based on an image, repeated infinitely.
Generates a heightmap based on fractal noise.
![Screenshot of 2D noise generator](images/generator_noise2d.png)
![Screenshot of 2D noise generator](images/generator_noise2d.webp)
### [Noise (3D)](api/VoxelGeneratorNoise.md)
Generates a blobby terrain with overhangs using 3D fractal noise. A gradient is applied along height so the volume becomes air when going up, and closes down into matter when going down.
![Screenshot of 3D noise generator](images/generator_noise3d.png)
![Screenshot of 3D noise generator](images/generator_noise3d.webp)
Node-graph generators (VoxelGraphs)
@ -86,11 +86,11 @@ The simplest possible graph with a visible output is a flat plane. The SDF of a
Right-click the background of the graph, choose the nodes `InputY` and `SdfOutput`, then connect them together by dragging their ports together.
![Plane voxel graph screenshot](images/voxel_graph_flat.png)
![Plane voxel graph screenshot](images/voxel_graph_flat.webp)
It is possible to decide the height of the plane by subtracting a constant (`sdf = y - height`), so that `sdf == 0` will occur at a higher coordinate. To do this, an extra node must be added:
![Offset plane voxel graph screenshot](images/voxel_graph_flat_offset.png)
![Offset plane voxel graph screenshot](images/voxel_graph_flat_offset.webp)
By default, the `Add` node does nothing because its `b` port is not connected to anything. It is possible to give a default value to such port. You can set it by clicking on the node and changing it in the inspector.
@ -106,33 +106,33 @@ There are several types of noise available, each with their own parameters. At t
!!! note
After you create this node, a new `FastNoiseLite` resource must be created in its parameters. If that resource is not setup, an error will occur and no voxels will be generated.
![Voxel graph 2D noise](images/voxel_graph_noise2d.png)
![Voxel graph 2D noise](images/voxel_graph_noise2d.webp)
3D noise is more expensive to compute, but is interesting because it actually produces overhangs or even small caves. It is possible to replace 2D noise with 3D noise in the previous setup:
![Voxel graph 3D noise](images/voxel_graph_noise3d_not_expanded.png)
![Voxel graph 3D noise](images/voxel_graph_noise3d_not_expanded.webp)
You might notice that despite it being 3D, it still appears to produce a heightmap. That's because the addition of `Y` in the graph is gradually offsetting noise values towards higher and higher values when going towards the sky, which makes the surface fade away quickly. So if we multiply `Y` with a small value, it will increase slower, letting the 3D noise expand more (`sdf = y * height_multiplier - height + noise3d(x, y, z)`):
![Voxel graph 3D noise expanded](images/voxel_graph_noise3d_expanded.png)
![Voxel graph 3D noise expanded](images/voxel_graph_noise3d_expanded.webp)
#### Planet
We are not actually forced to keep generating the world like a plane. We can go even crazier, and do planets. A good way to begin a planet is to make a sphere with the `SdfSphere` node:
![Voxel graph sdf sphere node](images/voxel_graph_sphere.png)
![Voxel graph sdf sphere node](images/voxel_graph_sphere.webp)
We cannot really use 2D noise here, so we can add 3D noise as well:
![Voxel graph sdf sphere with noise](images/voxel_graph_sphere_with_noise.png)
![Voxel graph sdf sphere with noise](images/voxel_graph_sphere_with_noise.webp)
However you might still want a heightmap-like result. One way to do this is to feed the 3D noise normalized coordinates, instead of global ones. Picking a ridged fractal can also give an eroded look, although it requires to negate the noise multiplier node to invert its distance field (if we leave it positive it will look puffed instead of eroded).
![Voxel graph sdf sphere with height noise](images/voxel_graph_sphere_with_noise2.png)
![Voxel graph sdf sphere with height noise](images/voxel_graph_sphere_with_noise2.webp)
!!! note
You can obtain a donut-shaped planet if you replace the `SdfSphere` node with a `SdfTorus` node.
![Torus voxel graph](images/voxel_graph_torus.png)
![Torus voxel graph](images/voxel_graph_torus.webp)
#### Caves
@ -142,23 +142,23 @@ However you might still want a heightmap-like result. One way to do this is to f
It is possible to generate caves by subtracting noise "worms" from a base SDF terrain. To simplify the approach, let's first look at what 2D noise looks like, with a few octaves:
![Noise](images/noise.png)
![Noise](images/noise.webp)
If we multiply that noise by itself (i.e square it), we obtain this:
![Squared noise](images/squared_noise.png)
![Squared noise](images/squared_noise.webp)
And if we clamp it to highlight values below a threshold close to zero, we can notice a path-like pattern going on:
![Squared noise path highlight](images/squared_noise_with_highlight.png)
![Squared noise path highlight](images/squared_noise_with_highlight.webp)
In 2D (or in 3D when using normalized coordinates) this is the key to produce rivers, or ravines. But the problem with caves is to obtain 3D, round-shaped "worms", not just 2D shapes. So we can cheat a little, by still using 2D noise, but instead we modulate the threshold along the Y axis. We need a parabola-shaped curve for this, which can be obtained with a second-degree polynome like `y^2 - 1`:
![Cave threshold modulation](images/cave_threshold_modulation.png)
![Cave threshold modulation](images/cave_threshold_modulation.webp)
Back to the voxel graph, we may connect directly the cave generation nodes to the output just to preview what they look like, without the rest of the terrain:
![Cave voxel graph](images/caves_flat.png)
![Cave voxel graph](images/caves_flat.webp)
After tweaking noise and other values, we obtain those famous worms, but there are two problems:
@ -167,15 +167,15 @@ After tweaking noise and other values, we obtain those famous worms, but there a
We can fix the first problem by adding an extra layer of 2D noise to the Y coordinate so it can perturb the caves vertically. Re-using the ground surface noise with an extra multiplier can prove effective sometimes, so we avoid computing extra noise.
![Caves perturb](images/caves_perturb.png)
![Caves perturb](images/caves_perturb.webp)
The second problem can also be fixed with yet another layer of low-frequency noise, which can be added to the cave threshold so caves will shrink to become dead-ends on some regions. Again, adding multipliers may change how sharply that transition occurs.
![Cave voxel graph perturb and modulated](images/caves_perturb_modulated.png)
![Cave voxel graph perturb and modulated](images/caves_perturb_modulated.webp)
Finally, we can blend our terrain with caves by subtracting them. This can be done with the `SdfSmoothSubtract` node, essentially doing `terrain - caves`.
![Cave voxel graph terrain subtract](images/caves_composed.png)
![Cave voxel graph terrain subtract](images/caves_composed.webp)
There are likely variants of this to obtain different results.
@ -186,15 +186,15 @@ It is possible to use this generator with `VoxelMesherBlocky` by using an `Outpu
The simplest example is to pick any existing SDF generator, and replace `OutputSDF` with a `Select` node connected to an `OutputType`. The idea is to choose between the ID of two different voxel types (like air or stone) if the SDF value is above or below a threshold.
![Example screenshot of a basic blocky heightmap made with a graph generator](images/voxel_graph_blocky_basic_heightmap.png)
![Example screenshot of a basic blocky heightmap made with a graph generator](images/voxel_graph_blocky_basic_heightmap.webp)
If more variety is needed, `Select` nodes can be chained to combine multiple layers, using different thresholds and sources.
![Example screenshot of a blocky heightmap with two biomes made with a graph generator](images/voxel_graph_blocky_biome.png)
![Example screenshot of a blocky heightmap with two biomes made with a graph generator](images/voxel_graph_blocky_biome.webp)
`Select` creates a "cut" between the two possible values, and it may be desirable to have some sort of transition. While this isn't possible with `VoxelMesherBlocky` without a lot of different types for each value of the gradient (usually done with a shader), it is however easy to add a bit of noise to the threshold. This reproduces a similar "dithered" transition, as can be seen in Minecraft between sand and dirt.
![Example screenshot of a blocky heightmap with two biomes and dithering](images/voxel_graph_blocky_biome_dithering.png)
![Example screenshot of a blocky heightmap with two biomes and dithering](images/voxel_graph_blocky_biome_dithering.webp)
Currently, graph generators only work per voxel. That makes them good to generate base ground and biomes, but it isn't practical to generate structures like trees or villages with it. This may be easier to accomplish using a second pass on the whole block instead, using a custom generator.
@ -211,7 +211,7 @@ Contrary to many node-based or expression tools existing in Godot so far, voxel
So instead, outputs of each node are associated small buffers for a subset of the voxels, say, a 16x16 slice. Then, the graph is traversed once ahead-of-time to obtain a simple list of operations. It is guaranteed that if a node depends on another, the other will have run before.
![Graph to operations schema](images/voxel_graph_operation_list.png)
![Graph to operations schema](images/voxel_graph_operation_list.webp)
Finally, the generator executes the list, node by node, and each node computes a bunch of voxels at once instead of just one. This ensures that the CPU is almost exclusively used for the operations themselves, providing performance similar to C++, while graph traversal becomes neglibible. It also offers the opportunity to use [SIMD](https://en.wikipedia.org/wiki/SIMD) very easily, which can be even faster than if the code was written in plain C++.
@ -223,11 +223,11 @@ Before processing voxels in a specific region of space (a box), the generator fi
It is possible to inspect results of this pass in the editor by enabling it with the `Analyse range` button. The analysis will focus on the box specified in the dialog, which will appear as a yellow wireframe in the 3D viewport.
![Analyse range editor screenshot](images/range_analysis_dialog.png)
![Analyse range editor screenshot](images/range_analysis_dialog.webp)
You can also hover the output label of any node to see what range was calculated for it:
![Range analysis tooltips](images/range_analysis_tooltip.png)
![Range analysis tooltips](images/range_analysis_tooltip.webp)
!!! note
Noise is typically between -1 and 1, but we take it a step further. Ranges are approximated using maximum derivatives, which is how fast noise can vary along a given distance. Each noise algorithm has its own. We calculate noise at the center of the box, and add half of the maximum derivative, positively and negatively. In other words, in the box, we know noise cannot exceed the central value + the maximum variation along extents of the box. At close range, this can successfully detect valleys and hills, without fully computing them.
@ -244,17 +244,17 @@ It is possible to choose that threshold with the `sdf_clip_threshold` property i
It is exposed because in some situations, clipping can cause artifacts when the edge of a block is too close from a clipped one. Indeed, clipping blocks cause discontinuities in the distance field.
![Sdf clipping schema](images/sdf_clipping.png)
![Sdf clipping schema](images/sdf_clipping.webp)
Usually they happen far enough from the surface to be of any concern, but sometimes they can come close if the threshold is too low:
![Sdf clipping artifacts](images/sdf_clipping_artifacts.png)
![Sdf clipping artifacts](images/sdf_clipping_artifacts.webp)
So by default the threshold is above zero and should cover most cases.
It is also possible to instruct the generator to invert clipped blocks, which will make them stand out:
![Sdf clipping debug](images/sdf_clip_debug.png)
![Sdf clipping debug](images/sdf_clip_debug.webp)
#### Local optimization
@ -263,11 +263,11 @@ Conditionals (`if/else`) are not supported by this voxel graph implementation. T
Let's consider an example world made of two biomes, each generated with a big node setup, and blended together across the world's X axis.
![Two biomes](images/biomes.png)
![Two biomes](images/biomes.webp)
If we don't optimize this, both biomes will constantly get calculated at every point of space close enough to the surface. But if we look at the range analysis we performed earlier, and focus on one of the biomes, we notice that the range of values received by the `Mix` node are such that only one biome is blended. In other words, one of the inputs of `Mix` has no effect on its result, and is therefore ignored there.
![Ignored input](images/range_of_ignored_input.png)
![Ignored input](images/range_of_ignored_input.webp)
So each biome then only computes its own branch when far away enough from the blending area:
@ -277,7 +277,7 @@ Thanks again to range analysis, the generator is able to detect this locally, an
Internally, the generator parses the graph locally (using a faster data structure since the graph is compiled) to obtain an alternative list of operations. This list is currently nicknamed an `execution map`, because it maps the full list of operations to a reduced one.
![Execution map schema](images/voxel_graph_operation_list_optimized.png)
![Execution map schema](images/voxel_graph_operation_list_optimized.webp)
This setting can be toggled in the inspector.

View File

@ -26,7 +26,7 @@ A new build is made each time commits are pushed to the main branch, but also wh
In case there are multiple downloadable artifacts, the editor build will be the one with `opt.tools` in the name (because it is built with optimizations enabled, and includes tools).
![Github actions screenshot](images/github_actions_windows_artifacts.png)
![Github actions screenshot](images/github_actions_windows_artifacts.webp)
!!! note
You will need a Github account to be able to download development builds. Otherwise, links will not work.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 747 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 775 KiB

After

Width:  |  Height:  |  Size: 629 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 622 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 816 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 885 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 453 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 767 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 754 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 992 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Some files were not shown because too many files have changed in this diff Show More