SDL2系列教程6-纹理

创建纹理

如上一课所述,纹理是GPU渲染等效于表面。因此,纹理几乎总是使用函数SDL_CreateTextureFromSurface()从曲面创建。这个函数或多或少地做你期望的 - 参数是渲染上下文和从中创建纹理的表面。与其他创建函数一样,它将在失败时返回NULL。

以这种方式创建纹理时,数据将被复制到纹理,允许您释放用于加载图像的表面。

// create window, renderer

SDL_Surface* image = SDL_LoadBMP("image.bmp");

SDL_Texture* texture = SDL_CreateTextureFromSurface( renderer, image );

SDL_FreeSurface( image );
image = NULL;

if( !texture ) {
	// etc
}

您还可以使用函数SDL_CreateTexture()创建空白纹理。此函数采用要创建的纹理的渲染上下文,像素格式,宽度和高度。

SDL_Texture* texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC, 1024, 1024 );

这对渲染图像没有用,但是编辑像素数据或渲染到纹理是必要的。

纹理设置

SDL提供了几个影响它们渲染方式的纹理属性。这些设置反映了上一课的渲染选项。

询问

函数SDL_QueryTexture()用于检索纹理的基本设置,包括格式,访问,宽度和高度。

int w, h, access;
unsigned int format;

SDL_QueryTexture( texture, &format, &access, &width, &height );

Αlpha

纹理可能包含alpha数据,但SDL还提供整体纹理alpha设置。更改此值将导致整个纹理淡入或淡出。函数SDL_GetTextureAlphaMod()SDL_SetTextureAlphaMod()用于此目的。

// decrease alpha by 25

unsigned char alpha;

SDL_GetTextureAlphaMod( texture, &alpha );

SDL_SetTextureAlphaMod( texture, alpha - 25 );

混合模式

混合模式可以使用函数SDL_GetTextureBlendMode()SDL_SetTextureBlendMode()修改每个纹理。这些函数使用SDL_BlendMode结构进行操作,该结构可以不包括混合,alpha混合(默认),添加混合和调制混合。

SDL_SetTextureBlendMode( texture, SDL_BLENDMODE_ADD );

颜色Mod

与绘图一样,可以为每个纹理设置颜色修改器。正如您所期望的那样,函数SDL_GetTextureColorMod()SDL_SetTextureColorMod()用于此目的。请注意,颜色修饰符不包括alpha-您必须单独获取和设置alpha。

// swizzle colors

unsigned char r, g, b;

SDL_GetTextureColorMod( texture, &r, &g, &b );

SDL_SetTextureColorMod( texture, g, b, r );

渲染纹理

实际上,在屏幕上绘制纹理与blitting表面非常相似,只是您有更多选项。SDL_RenderCopy()是直接并行:它采用渲染上下文,纹理,源矩形和目标矩形。

SDL_Rect dst;
dst.x = 0;
dst.y = 0;
dst.w = 100;
dst.h = 100;

SDL_RenderCopy( renderer, texture, NULL, &dst );

旋转和翻转

函数SDL_RenderCopyEx()(Ex = Extended)提供了一些渲染选项。这些包括围绕点旋转和垂直/水平翻转。这些只是作为参数传递。请注意,旋转角度以度为单位,但大多数数学函数/库使用弧度。

SDL_Rect dst;
dst.x = 0;
dst.y = 0;
dst.w = 100;
dst.h = 100;

SDL_Point rotPoint;
rotPoint.x = 25;
rotPoint.y = 25;

SDL_RenderCopyEx( renderer, texture, NULL, &dst, 90, &rotPoint, SDL_FLIP_HORIZONTAL );

像素

与曲面一样,您可以直接编辑纹理的像素数据。但是,它比简单地访问“像素”成员要复杂得多。

从曲面创建纹理使用默认的SDL_TextureAccess值SDL_TEXTUREACCESS_STATIC,这意味着无法更改纹理。如果您计划直接编辑纹理的像素数据,则必须使用SDL_TEXTUREACCESS_STREAMING。该标志告诉SDL可以通过外部代码更改纹理。

但是,这不是你所要做的。要访问纹理的像素数据,必须使用函数SDL_LockTexture()。此函数告诉SDL停止对纹理的任何其他访问,直到用户完成它。参数包括要编辑的纹理区域,将设置为像素数据的指针,以及将设置为像素间距的整数。“音调”只是一条水平像素线的长度(以字节为单位) - 您可以说是第一维的大小。请注意,像素数据仅用于写入 - 不保证包含先前的正确值。

纹理创建时指定的像素格式决定了像素数据的格式。它非常简单:... RGBA8888表示第一个红色,然后是绿色,然后是蓝色,然后是alpha,每个值是8位(一个字节)。... RGB444表示第一个红色,然后是绿色,然后是蓝色,没有alpha,每个值四个位。

SDL_Texture* texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, 1024, 1024);

unsigned char* pixels;
int pitch;

SDL_LockTexture( texture, NULL, (void**)&pixels, &pitch );

// set pixels to solid white
for(int i = 0; i < pitch * textureHeight; i++) {
	pixels[i] = 255;
}

最后,一旦完成对纹理的写入,您必须调用SDL_UnlockTexture()来应用您的更改并发信号通知SDL它可以再次使用纹理。

SDL_UnlockTexture( texture );

渲染到纹理

虽然从技术上讲,您可以通过编辑像素数据来进行任何纹理修改,但直接渲染到纹理通常会更加方便。从本质上讲,这意味着使用完整的渲染API,而不是绘制到屏幕,绘制到纹理。

必须使用访问SDL_TEXTUREACCESS_TARGET创建纹理以启用渲染纹理。除此之外,纹理与正常使用相同。函数SDL_SetRenderTarget()用于在渲染到纹理或屏幕之间进行更改。参数非常简单:渲染上下文和要呈现的纹理或呈现给屏幕的NULL。

请注意,渲染到纹理时不应调用SDL_RenderPresent()

SDL_Texture* texture = SDL_CreateTexture( renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1024, 1024);

// draw to the texture
SDL_SetRenderTarget( renderer, texture );

// draw a point onto the texture
SDL_RenderDrawPoint( renderer, 123, 456 );

// now draw to the window
SDL_SetRenderTarget( renderer, NULL );

销毁纹理

最后,与表面一样,当程序关闭时(或不再使用它们)时,必须释放纹理。这只是使用函数SDL_DestroyTexture()完成的

SDL_DestroyTexture( texture );
texture = NULL;

完整代码下载地址:

https://download.csdn.net/download/cyf15238622067/10697469

测试效果:鼠标指向不同位置,箭头指向不同方向,而且颜色不断变化。

猜你喜欢

转载自blog.csdn.net/cyf15238622067/article/details/82907529