SDL2 学习之路-05(色彩调制和阿尔法混合)

该代码示例展示了如何使用SDL库改变纹理的颜色、设置混合模式以及调整透明度。通过SDL_SetTextureColorMod、SDL_SetTextureBlendMode和SDL_SetTextureAlphaMod函数,可以实现对纹理的渲染效果进行自定义,包括像素颜色的修改、混合模式的选择以及透明度的控制。示例中还包含了加载图像、创建纹理以及销毁资源的相关函数。
摘要由CSDN通过智能技术生成

SDL_SetTextureColorMod可以更改渲染纹理的颜色

 SDL_SetTextureBlendMode 可以控制纹理的混合方式,为了使混合正常工作,必须先在纹理上设置混合模式。

 SDL_SetTextureAlphaMod设置纹理的透明度。

SDL_Window* window=SDL_CreateWindow("title",500,500,640,480,SDL_WINDOW_SHOWN);
SDL_Renderer* renderer=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);

SDL_Surface* loadedSurface=IMG_Load("blend.png");
SDL_Texture* texture=SDL_CreateTextureFromSurface(renderer,loadedSurface);

SDL_SetTextureColorMod(texture, 128, 255, 255);//使像素的红色分量减半

SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);//设置混合模式

SDL_SetTextureAlphaMod(texture, 128);//设置为半透明
typedef enum
{
    SDL_BLENDMODE_NONE = 0x00000000,     /**< no blending
                                              dstRGBA = srcRGBA */
    SDL_BLENDMODE_BLEND = 0x00000001,    /**< alpha blending
                                              dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
                                              dstA = srcA + (dstA * (1-srcA)) */
    SDL_BLENDMODE_ADD = 0x00000002,      /**< additive blending
                                              dstRGB = (srcRGB * srcA) + dstRGB
                                              dstA = dstA */
    SDL_BLENDMODE_MOD = 0x00000004,      /**< color modulate
                                              dstRGB = srcRGB * dstRGB
                                              dstA = dstA */
    SDL_BLENDMODE_MUL = 0x00000008,      /**< color multiply
                                              dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
                                              dstA = dstA */
    SDL_BLENDMODE_INVALID = 0x7FFFFFFF

    /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */

} SDL_BlendMode;

完整代码

CTexture.h

#pragma once
#include<SDL.h>
#include<string>
class CTexture {
public:
	CTexture(SDL_Renderer*& renderer);
	~CTexture();
	bool loadFromFile(std::string path);
	void free();
	void render(int x, int y, SDL_Rect* clip=NULL);
	int getWidth();
	int getHeight();
	void setBlendMode(SDL_BlendMode blending);
	void setColor(Uint8 red, Uint8 green, Uint8 blue);
	void setAlpha(Uint8 alpha);
private:
	SDL_Texture* m_texture;
	SDL_Renderer* m_renderer;


	int m_width;
	int m_height;
};

CTexture.cpp

#include "CTexture.h"
#include <SDL_image.h>

CTexture::CTexture(SDL_Renderer*& renderer):m_renderer{renderer}
{
	//Initialize
	m_texture = NULL;
	m_width = 0;
	m_height = 0;

	
}

CTexture::~CTexture()
{
	//Deallocate
	free();
}

bool CTexture::loadFromFile(std::string path)
{
	//Get rid of preexisting texture
	free();

	//The final texture
	SDL_Texture* newTexture = NULL;

	//Load image at specified path
	SDL_Surface* loadedSurface = IMG_Load(path.c_str());
	if (loadedSurface == NULL)
	{
		printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), IMG_GetError());
	}
	else
	{
		//Color key image
		SDL_SetColorKey(loadedSurface, true, SDL_MapRGB(loadedSurface->format, 0x00, 0xFF, 0xFF));

		//Create texture from surface pixels
		newTexture = SDL_CreateTextureFromSurface(m_renderer, loadedSurface);
		if (newTexture == NULL)
		{
			printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
		}
		else
		{
			//Get image dimensions
			m_width = loadedSurface->w;
			m_height = loadedSurface->h;
		}

		//Get rid of old loaded surface
		SDL_FreeSurface(loadedSurface);
	}

	//Return success
	m_texture = newTexture;
	return m_texture != NULL;
}

void CTexture::free()
{
	//Free texture if it exists
	if (m_texture != NULL)
	{
		SDL_DestroyTexture(m_texture);
		m_texture = NULL;
		m_width = 0;
		m_height = 0;

	
	}
}

void CTexture::render(int x, int y, SDL_Rect* clip)
{
	//Set rendering space and render to screen
	SDL_Rect renderQuad = { x, y, getWidth(), getHeight() };
	//Set clip rendering dimensions
	if (clip != NULL)
	{
		renderQuad.w = clip->w;
		renderQuad.h = clip->h;
	}
	//Render to screen
	SDL_RenderCopy(m_renderer, m_texture, clip, &renderQuad);
}

int CTexture::getWidth()
{
	return m_width;
}

int CTexture::getHeight()
{
	return m_height;
}

void CTexture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
	//Modulate texture
	SDL_SetTextureColorMod(m_texture, red, green, blue);
}

void CTexture::setBlendMode(SDL_BlendMode blending)
{
	//Set blending function
	SDL_SetTextureBlendMode(m_texture, blending);
}

void CTexture::setAlpha(Uint8 alpha)
{
	//Modulate texture alpha
	SDL_SetTextureAlphaMod(m_texture, alpha);
}

main.cpp

#include <SDL.h>
#include <SDL_image.h>
#include <stdio.h>
#include <string>
#include "CTexture.h"

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

//Starts up SDL and creates window
bool init();

//Loads media
bool loadMedia();

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;
//The window renderer
SDL_Renderer* gRenderer = NULL;
//Scene sprites

CTexture* pModulatedTexture =NULL;
CTexture* pBackgroundTexture = NULL;
bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Set texture filtering to linear
		if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
		{
			printf("Warning: Linear texture filtering not enabled!");
		}

		//Create window
		gWindow = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
		if (gWindow == NULL)
		{
			printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Create renderer for window
			gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
			if (gRenderer == NULL)
			{
				printf("Renderer could not be created! SDL Error: %s\n", SDL_GetError());
				success = false;
			}
			else
			{
				//Initialize renderer color
				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);

				
				
				//Initialize PNG loading
				int imgFlags = IMG_INIT_PNG;
				if (!(IMG_Init(imgFlags) & imgFlags))
				{
					printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
					success = false;
				}

				pBackgroundTexture = new CTexture(gRenderer);
				pModulatedTexture = new CTexture(gRenderer);
			}
		}
	}

	return success;
}

bool loadMedia()
{
	//Loading success flag
	bool success = true;
	//Load front alpha texture
	if (!pModulatedTexture->loadFromFile("src/fadeout.png"))
	{
		printf("Failed to load front texture!\n");
		success = false;
	}
	else
	{
		//Set standard alpha blending
		pModulatedTexture->setBlendMode(SDL_BLENDMODE_BLEND);
	}

	//Load background texture
	if (!pBackgroundTexture->loadFromFile("src/fadein.png"))
	{
		printf("Failed to load background texture!\n");
		success = false;
	}

	return success;
}

void close()
{
	//Free loaded images
	pModulatedTexture->free();
	pBackgroundTexture->free();
	//Destroy window	
	SDL_DestroyRenderer(gRenderer);
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;
	gRenderer = NULL;

	
	pModulatedTexture = NULL;
	pBackgroundTexture = NULL;
	//Quit SDL subsystems
	IMG_Quit();
	SDL_Quit();
}

int main(int argc, char* args[])
{
	//Start up SDL and create window
	if (!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Load media
		if (!loadMedia())
		{
			printf("Failed to load media!\n");
		}
		else
		{
			//Main loop flag
			bool quit = false;

			//Event handler
			SDL_Event e;

			//Modulation components
			Uint8 r = 255;
			Uint8 g = 255;
			Uint8 b = 255;
			Uint8 a = 128;
			//While application is running
			while (!quit)
			{
				//Handle events on queue
				while (SDL_PollEvent(&e) != 0)
				{
					//User requests quit
					if (e.type == SDL_QUIT)
					{
						quit = true;
					}
					//On keypress change rgb values
					else if (e.type == SDL_KEYDOWN)
					{
						switch (e.key.keysym.sym)
						{
							//Increase red
						case SDLK_q:
							r += 32;
							break;

							//Increase green
						case SDLK_e:
							g += 32;
							break;

							//Increase blue
						case SDLK_r:
							b += 32;
							break;

							//Decrease red
						case SDLK_a:
							r -= 32;
							break;

							//Decrease green
						case SDLK_d:
							g -= 32;
							break;

							//Decrease blue
						case SDLK_f:
							b -= 32;
							break;

						case SDLK_w:
							if (a + 32 > 255)
							{
								a = 255;
							}
							//Increment otherwise
							else
							{
								a += 32;
							}
							break;

						case SDLK_s:
							if (a - 32 < 0)
							{
								a = 0;
							}
							//Increment otherwise
							else
							{
								a -= 32;
							}
							break;
						}
						

					}
				}

				//Clear screen
				SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF);
				SDL_RenderClear(gRenderer);

				//Render background
				pBackgroundTexture->render(0, 0,NULL);
				//Render front blended
				pModulatedTexture->setAlpha(a);
				pModulatedTexture->setColor(r, g, b);

				pModulatedTexture->render(0, 0,NULL);
				//Update screen
				SDL_RenderPresent(gRenderer);
			}
		}
	}

	//Free resources and close SDL
	close();

	return 0;
}

效果截图:

参考文章:Lazy Foo' Productions - Alpha Blending

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平面海螺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值