如上一课所述,纹理是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 );
纹理可能包含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 );
与绘图一样,可以为每个纹理设置颜色修改器。正如您所期望的那样,函数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
测试效果:鼠标指向不同位置,箭头指向不同方向,而且颜色不断变化。