-
Notifications
You must be signed in to change notification settings - Fork 72
Images
Images are essentially just OpenGL textures with a simple to use interface. They store a buffer of pixels and are then displayed to the window.
In MLX, the behaviour of the image functions work almost similarly to minilibx.
An image on its own is very simple:
/**
* An image with an individual buffer that can be rendered.
* Any value can be modified except the width/height and context.
*
* @param width The width of the image.
* @param height The height of the image.
* @param pixels The literal pixel data.
* @param instances An instance carries the X, Y, Z location data.
* @param count The element count of the instances array.
* @param enabled If true the image is drawn onto the screen, else its not.
* @param context Abstracted OpenGL data.
*/
typedef struct s_mlx_image
{
const uint32_t width;
const uint32_t height;
uint8_t *pixels;
t_mlx_instance *instances;
int32_t count;
bool enabled;
void *context;
} t_mlx_image;It holds the width, height and pixels. However images can have instances, that is, copies of itself that share the same pixel buffer.
This makes it easy to make for instance, a row of trees. They all hold the same pixel information, just different locations. Additionally the entire image can be toggled for rendering via the enabled boolean.
instances is simply an array of each individual instance, they hold the x, y and z positions of the instance,count tells us the element count of this array.
All that is needed is to call the mlx_image_to_window function to create a new copy/instance. However its also possible to move the location
of individual images quite easily:
// Modify the x & y position of an already existing instance.
img->instances[0].x += 5;
img->instances[0].y += 5;All that is needed is to simply change the values and MLX will handle the rest of updating the position.
Internally this is via a render queue, anytime the mlx_image_to_window function is used, a new entry is added into a linked list.
Every frame MLX will iterate over this linked list and execute a drawcall to draw that image onto the window.
An improvement to this rendering could be to add batched rendering.
// Creates a whole new image.
t_mlx_image *mlx_new_image(t_mlx *mlx, uint16_t width, uint16_t height)// Creates a new instance/copy of an already existing image.
void mlx_image_to_window(t_mlx_image *img, int32_t x, int32_t y, int32_t z)// Deletes an image and removes it from the render queue.
void mlx_delete_image(t_mlx *mlx, t_mlx_image *image)MLX42 works similarly to minilibx in regards to how images are drawn onto the window.
Example will create a new image and randomize its pixels every frame.
#include "MLX42/MLX42.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <memory.h>
#define WIDTH 256
#define HEIGHT 256
static t_mlx_image *g_img;
void hook(void *param)
{
t_mlx *mlx;
mlx = param;
if (mlx_is_key_down(param, MLX_KEY_ESCAPE))
mlx_quit(param);
if (mlx_is_key_down(param, MLX_KEY_P))
mlx_delete_image(mlx, g_img);
for (int x = 0; x < g_img->width; x++)
for(int y= 0; y < g_img->height; y++)
mlx_putpixel(g_img, x, y, rand() % RAND_MAX);
}
int32_t main(void)
{
t_mlx *mlx;
mlx = mlx_init(WIDTH, HEIGHT, "MLX42", true);
if (!mlx)
exit(EXIT_FAILURE);
g_img = mlx_new_image(mlx, 128, 128);
mlx_image_to_window(mlx, g_img, 0, 0);
mlx_loop_hook(mlx, &hook, mlx);
mlx_loop(mlx);
mlx_terminate(mlx);
return (EXIT_SUCCESS);
}