Search…

Load Texture trong SDL

02/11/20205 min read
Cách load hình ảnh lên màn hình sử dụng framework SDL (Simple DirectMedia Layer).

Các đối tượng sử dụng trong bài viết

  • SDL_Window: struct giữ tất cả các thông tin của cửa sổ được tạo ra, chẳng hạn như size, postion, border, fullscreen.
  • SDL_Renderer: struct xử lý tất cả các công việc rendering lên cửa sổ.
  • SDL_Surface: chứa 1 tập hợp các pixel (a collection of pixels) để có thể render lên cửa sổ sử dụng software rendering (CPU).
  • SDL_Texture: chứa 1 tập hợp các pixel (a collection of pixels) để có thể render lên cửa sổ sử dụng hardware rendering (GPU).
  • SDL_Rect: struct đại diện cho 1 hình chữ nhật gồm có các thông tin là x, y, w, h.

Tạo đối tượng SDL_Texuture

Sử dụng project ở bài viết Xử Lý Sự Kiện trong SDL nhưng giữ lại main loop và main event, tiếp tục khai báo thêm 1 số biến sử dụng trong chương trình là renderer, tempSurface, texture, sourceRect, desRect.

int main()
{
	SDL_Window* window = NULL;
	SDL_Renderer* renderer = NULL;
	SDL_Surface* tempSurface = NULL;
	SDL_Texture* texture = NULL;
	SDL_Event mainEvent;
        SDL_Rect sourceRect;
        SDL_Rect desRect;
	bool isRunning = true;

	//initializes  the subsystems
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		printf("Unable to initialize SDL %s\n", SDL_GetError());
		return -1;
	}

	//Create window
	window = SDL_CreateWindow("Stdio.vn - SDL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 640, SDL_WINDOW_SHOWN);
	if (window == NULL)
	{
		printf("Could not create window %s", SDL_GetError());
		return -1;
	}
	//main loop
	while (isRunning)
	{
		//main event
		while (SDL_PollEvent(&mainEvent))
		{
			switch (mainEvent.type)
			{
				//User - requested quit
				case SDL_QUIT:
				{
					isRunning = false;
					break;
				}
                default:
                {
                    break;
                }
            }
		}
	}

	//Destroy a window.
	SDL_DestroyWindow(window);

	//cleans up all initialized subsystems
	SDL_Quit();
	return 0;
}

Tạo đối tượng renderer để có thể render lên cửa sổ bằng cách:

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
	printf("Could not create render %s", SDL_GetError());
	return -1;
}

Tiếp theo tạo tempSurface từ 1 file hình có đuôi mở rộng là .bmp và tạo texture từ tempSurface đó. Sau đó hủy tempSurface. Ở đây, file hình ảnh có tên là texture_demo.bmp được đặt trong thư mục gốc của solution.

tempSurface = SDL_LoadBMP("texture_demo.bmp");
texture = SDL_CreateTextureFromSurface(renderer, tempSurface);
SDL_FreeSurface(tempSurface);

* Hàm SDL_LoadBMP() chỉ nhận được hình ảnh có đuôi mở rộng là .bmp.

Sử dụng hàm SDL_QueryTexture() để lấy ra thông tin chiều rộng và chiều cao của texture.

SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h);

Đoạn code trên có khai báo đối tượng SDL_Rect với 2 biến là sourceRect và desRect, chức năng của chúng như sau:

  • sourceRect: sử dụng để thông tin về chiều cao, chiều rộng của texture muốn vẽ. Ví dụ có 1 texture được load lên, để vẽ 1 phần nào đó của texture thay vì vẽ toàn bộ texture đó lên mà hình, sử dụng đối tượng hình chữ nhật này để fix lại x, y, w, h.
  • desRect: sử dụng để xác định tọa độ của texture muốn vẽ trên màn hình.

Vẽ Texture lên màn hình

Lấy thông tin về chiều cao và chiều rộng của texture sau khi texure được tạo:

SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h);

sourceRect.x = desRect.x = 0;
sourceRect.y = desRect.y = 0;
desRect.w = sourceRect.w;
desRect.h = sourceRect.h;

Set background màu đen cho cửa sổ sử dụng hàm:

SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

Với tham số thứ nhất chính là đối tượng renderer, 3 tham số tiếp theo lần lượt là các giá trị màu r, g, b, a.

Trong main loop, tiến hành vẽ texture lên cửa sổ:

//main loop
while (isRunning)
{
	SDL_RenderClear(renderer);
	//main event
	while (SDL_PollEvent(&mainEvent))
	{
		switch (mainEvent.type)
		{
			//User - requested quit
			case SDL_QUIT:
			{
				isRunning = false;
				break;
			}
			default:
			{
				break;
			}
		}
	}

	SDL_RenderCopy(renderer, texture, &sourceRect, &desRect);
	SDL_RenderPresent(renderer);
}
  • SDL_RenderClear(): xóa màn hình sau mỗi frame với màu của background được set.
  • SDL_RenderCopy(): hàm sử dụng để render texture với các tham số:
    • renderer: đối tượng được sử dụng để render.
    • texture: đối tượng texture muốn render.
    • sourceRect: 1 phần nào đó của texture muốn render. Nếu để NULL nó sẽ render toàn bộ texture.
    • desRect: hình chữ nhật xác đinh tọa độ mà texture muốn vẽ trên cửa sổ. Nếu chiều rộng và chiều cao lớn hơn hoặc nhỏ hơn texture muốn vẽ thì texture sẽ bị scale theo hình chữ nhật này. Nếu để NULL texture sẽ được vẽ full màn hình.
  • SDL_RenderPresent(): cập nhập, vẽ lên cửa sổ.

Kết quả sau khi chạy chương trình:

ss_1

Bây giờ, thay đổi các thông số của sourceRectdesSource để có thể vẽ được 1/4 hình ảnh ở vị trí x= 200, y = 200 trên màn hình:

sourceRect.x = 0;
sourceRect.y = 0;
sourceRect.w = sourceRect.w / 2;
sourceRect.h = sourceRect.h / 2;

desRect.x = 200;
desRect.y = 200;
desRect.w = sourceRect.w;
desRect.h = sourceRect.h;

Source code toàn bộ chương trình

#include <stdio.h>
#include <SDL.h>

#undef main
int main()
{

	SDL_Window* window = NULL;
	SDL_Renderer* renderer = NULL;
	SDL_Surface* tempSurface = NULL;
	SDL_Texture* texture = NULL;
	SDL_Event mainEvent;
	SDL_Rect sourceRect;
	SDL_Rect desRect;
	bool isRunning = true;

	//initializes  the subsystems
	if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
	{
		printf("Unable to initialize SDL %s\n", SDL_GetError());
		return -1;
	}

	//Create window
	window = SDL_CreateWindow("Stdio.vn - SDL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 640, SDL_WINDOW_SHOWN);
	if (window == NULL)
	{
		printf("Could not create window %s", SDL_GetError());
		return -1;
	}


	//create a renderer
	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
	if (renderer == NULL)
	{
		printf("Could not create render %s", SDL_GetError());
		return -1;
	}

	//create a tempSurface
	tempSurface = SDL_LoadBMP("texture_demo.bmp");
	//create a texutre from surface
	texture = SDL_CreateTextureFromSurface(renderer, tempSurface);
	//free surface
	SDL_FreeSurface(tempSurface);


	SDL_QueryTexture(texture, NULL, NULL, &sourceRect.w, &sourceRect.h);

	sourceRect.x = 0;
	sourceRect.y = 0;
	sourceRect.w = sourceRect.w / 2;
	sourceRect.h = sourceRect.h / 2;

	desRect.x = 200;
	desRect.y = 200;
	desRect.w = sourceRect.w;
	desRect.h = sourceRect.h;

	//set background color
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);

	//main loop
	while (isRunning)
	{
		// clear the window to black
		SDL_RenderClear(renderer);
		//main event
		while (SDL_PollEvent(&mainEvent))
		{
			switch (mainEvent.type)
			{
				//User - requested quit
				case SDL_QUIT:
				{
					isRunning = false;
					break;
				}
				default:
				{
					break;
				}
			}
		}

		// copy a portion of the texture to the current rendering target.
		SDL_RenderCopy(renderer, texture, &sourceRect, NULL);
		//draw to the screen
		SDL_RenderPresent(renderer);
	}

	//Destroy a window.
	SDL_DestroyWindow(window);

	//Destroy a renderer
	SDL_DestroyRenderer(renderer);

	//cleans up all initialized subsystems
	SDL_Quit();
	return 0;
}

Download demo

Stdio_SDL_LoadTexure_VS2013.zip

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024