欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過OpenGL ES混合模式縮放視頻緩沖區(qū)來適應(yīng)顯示尺寸

 更新時(shí)間:2012年12月30日 17:22:01   投稿:whsnow  
當(dāng)開發(fā)基于軟件模式的游戲時(shí),通過縮放視頻緩沖區(qū)來適應(yīng)顯示尺寸是最棘手的問題之一;作為開發(fā)人員,我們必須嘗試在性能與顯示質(zhì)量之間找到最佳平衡點(diǎn)

當(dāng)開發(fā)基于軟件模式的游戲時(shí),通過縮放視頻緩沖區(qū)來適應(yīng)顯示尺寸是最棘手的問題之一。當(dāng)面對(duì)眾多不同的分辨率時(shí)(比如開放環(huán)境下的Android),該問題會(huì)變得更加麻煩,作為開發(fā)人員,我們必須嘗試在性能與顯示質(zhì)量之間找到最佳平衡點(diǎn)。正如我們?cè)诘?章中看到的,縮放視頻緩沖區(qū)從最慢到最快共有3種類型。

軟件模擬:3中類型中最慢,但最容易實(shí)現(xiàn),是沒有GPU的老款設(shè)備上的最佳選擇。但是現(xiàn)在大部分智能手機(jī)都支持硬件加速。
混合模式:這種方式混合使用軟件模擬(創(chuàng)建圖像緩沖區(qū))和硬件渲染(向顯示屏繪制)兩種模式。這種方法速度很快,而且可以在分辨率大于256×256的任意屏幕上渲染圖像。

下面我們開始介紹混合模式并探討為什么這種方法更加可行。然后,將深入研究這種方法的實(shí)現(xiàn),包括如何初始化surface并通過實(shí)際縮放來繪制到紋理。
1. 為什么使用混合縮放
這種縮放技術(shù)背后的原理很簡(jiǎn)單:
你的游戲根據(jù)給定的尺寸創(chuàng)建圖像緩沖區(qū)(通常采用像素格式RGB565,即移動(dòng)設(shè)備最常用的格式)。例如320×240,這是典型的模擬器尺寸。
當(dāng)一張分辨率為320×240的圖像需要被縮放至平板電腦的尺寸(1024×768)或其他任意相同屏幕的設(shè)備時(shí),我們可以使用軟件模擬的方式來完成縮放,但會(huì)慢的令人無法忍受。而采用混合模式進(jìn)行縮放,需要?jiǎng)?chuàng)建OpenGL ES紋理并將圖片(320×240)渲染到GL四邊形上。
紋理會(huì)通過硬件被縮放到適合顯示屏的尺寸(1024×768),從而你的游戲性能將得到顯著提升。
從實(shí)現(xiàn)的角度看,這個(gè)過程可描述如下:
初始化OpenGL ES紋理:在游戲視頻被初始化的階段,必須創(chuàng)建硬件surface。其中包含簡(jiǎn)單的紋理,要顯示的視頻圖像會(huì)被渲染至到該紋理(詳見代碼清單1與代碼清單2)。
將圖像緩沖區(qū)繪制到紋理:在游戲循環(huán)的末端,渲染要顯示的視頻圖像到紋理,該紋理會(huì)自動(dòng)縮放至適合顯示屏的尺寸(詳見代碼清單3)。
代碼清單1 創(chuàng)建RGB656格式的空紋理

復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">// 紋理ID
static unsigned int mTextureID;
// 被用來計(jì)算圖片繪制在紋理上的X、Y偏移量
static int xoffset;
static int yoffset;
/**
* 創(chuàng)建RGB565格式的空紋理
* 參數(shù): (w,h) 紋理的寬, 高
* (x_offsety_offset): 圖片繪制在紋理上的X、Y偏移量
*/
static void CreateEmptyTextureRGB565 (int w, int h, int x_offset, int y_offset)
{
int size = w * h * 2;
xoffset = x_offset;
yoffset = y_offset;
// 緩沖區(qū)
unsigned short * pixels = (unsigned short *)malloc(size);
memset(pixels, 0, size);
// 初始化GL狀態(tài)
glDisable(GL_DITHER);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glClearColor(.5f, .5f, .5f, 1);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
// 創(chuàng)建紋理
glGenTextures(1, &mTextureID);
glBindTexture(GL_TEXTURE_2D, mTextureID);
// 紋理參數(shù)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// RGB565格式的紋理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_
SHORT_5_6_5 , pixels);
free (pixels);
} </SPAN>

代碼清單2展示了CreateEmptyTextureRGB565的實(shí)現(xiàn)過程,創(chuàng)建RGB656格式的空紋理用于繪制,參數(shù)如下:
w和h:要顯示的視頻圖片的尺寸。
x_offset和y_offset:坐標(biāo)系中X軸、Y軸的偏移量,視頻圖片將會(huì)按照這個(gè)坐標(biāo)被渲染到紋理。但是為什么我們需要這些參數(shù)?請(qǐng)繼續(xù)閱讀。
在OpenGL中創(chuàng)建紋理,我們只需要調(diào)用:
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">glGenTextures(1, &mTextureID);
glBindTexture(GL_TEXTURE_2D, mTextureID);</SPAN>

這里的mTextureID是整型變量,用于存儲(chǔ)紋理的ID。然后需要設(shè)置下面這些紋理參數(shù):
GL_TEXTURE_MIN_FILTER:指定紋理縮小的方式,當(dāng)像素被紋理化后并映射到某個(gè)大于單個(gè)紋理元素的區(qū)域時(shí)使用的縮小方式為GL_NEAREST,返回距離像素被紋理化后的中心最近(曼哈頓距離)的紋理元素的值。
GL_TEXTURE_MAG_FILTER:指定紋理放大的方式,當(dāng)像素被紋理化后并映射到某個(gè)小于或等于單個(gè)紋理元素的區(qū)域時(shí)使用的放大方式為GL_LINEAR,返回4個(gè)距離像素被紋理化后的中心最近的紋理元素的加權(quán)平均值。
GL_TEXTURE_WRAP_S:用于設(shè)置紋理坐標(biāo)系中S軸方向上的紋理映射方式為GL_CLAMP,將紋理坐標(biāo)限制在(0,1)范圍內(nèi),當(dāng)映射單張圖像到對(duì)象時(shí),可以有效防止畫面重疊。
GL_TEXTURE_WRAP_T:用于設(shè)置紋理坐標(biāo)系中T軸方向上的紋理映射的方式為GL_CLAMP。
最后,我們通過glTexImage2D函數(shù)及以下參數(shù)來指定二維紋理:
GL_TEXTURE_2D:指定目標(biāo)紋理的類型為二維紋理。
Level:指定圖像紋理的詳細(xì)程度。0是最基本的圖像紋理層。
Internal format:指定紋理的顏色成分,在這個(gè)例子中是RGB格式。
Width and height:紋理的尺寸,必須是2的冪。
Format:指定像素?cái)?shù)據(jù)的格式,同時(shí)也必須與內(nèi)部格式相同。
Type:指定像素?cái)?shù)據(jù)的數(shù)據(jù)類型,在本例中使用RGB565(16位)格式。
Pixels:指向內(nèi)存中圖像數(shù)據(jù)的指針,必須使用RGR656編碼。
注意:紋理的尺寸必須是2的冪,如256、512、1024等。但是,要顯示的視頻圖像的尺寸可以是任意尺寸。這就意味著,紋理的尺寸必須是大于或等于要顯示的視頻圖像尺寸的2的冪。稍后我們將進(jìn)行詳細(xì)介紹。
現(xiàn)在,讓我們來看一看混合視頻縮放的實(shí)際實(shí)現(xiàn),接下來的兩個(gè)小節(jié)將介紹如何初始化用來縮放的surface以及如何實(shí)現(xiàn)實(shí)際的繪制。
2. 初始化surface
要進(jìn)行縮放,就必須保證紋理的尺寸大于或等于要顯示的視頻圖像的尺寸。否則,當(dāng)圖像渲染的時(shí)候,會(huì)看到白色或黑色的屏幕。在代碼清單2中,JNI_RGB565_SurfaceInit函數(shù)將確保產(chǎn)生有效的紋理尺寸。使用圖像的寬度和高度為參數(shù),然后調(diào)用getBestTexSize函數(shù)來獲取最接近要求的紋理尺寸,最后通過調(diào)用CreateEmptyTextureRGB565函數(shù)來創(chuàng)建空的紋理。注意,如果圖像尺寸小于紋理尺寸,就通過計(jì)算X、Y坐標(biāo)的偏移量來將其置于屏幕的中心。
代碼清單2 初始化surface
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">// 獲取下一個(gè)POT紋理尺寸,該尺寸大于或等于圖像尺寸(WH)
static void getBestTexSize(int w, int h, int *tw, int *th)
{
int width = 256, height = 256;
#define MAX_WIDTH 1024
#define MAX_HEIGHT 1024
while ( width < w && width < MAX_WIDTH) { width *= 2; }
while ( height < h && height < MAX_HEIGHT) { height *= 2; }
*tw = width;
*th = height;
}
/**
* 初始化RGB565 surface
* 參數(shù): (w,h) 圖像的寬高
*/
void JNI_RGB565_SurfaceInit(int w, int h)
{
//最小紋理的寬高
int texw = 256;
int texh = 256;
// 得到紋理尺寸 (必須是POT) >= WxH
getBestTexSize(w, h, &texw, &texh);
// 圖片在屏幕中心?
int offx = texw > w ? (texw - w)/2 : 0;
int offy = texh > h ? (texh - h)/2 : 0;
if ( w > texw || h > texh)
printf ("Error: Invalid surface size %sx%d", w, h);
// 創(chuàng)建OpenGL紋理,用于渲染
CreateEmptyTextureRGB565 (texw, texh, offx, offy);
}
</SPAN>

3. 繪制到紋理
最后,為了將圖像顯示到屏幕上(也稱作surface翻轉(zhuǎn)),我們調(diào)用JNI_RGB565_Flip函數(shù),其參數(shù)是像素?cái)?shù)組(使用RGR656編碼)和要顯示的圖像尺寸。JNI_RGB565_Flip函數(shù)通過調(diào)用DrawIntoTextureRGB565將圖像繪制到紋理并交換緩沖區(qū)。注意交換緩沖區(qū)的函數(shù)是用Java編碼的,而不是用C語(yǔ)言編碼的,因此我們需要一個(gè)方法來調(diào)用Java的交換函數(shù)。我們可以通過使用JNI方法調(diào)用某個(gè)Java方法來完成緩沖區(qū)的交換工作(見代碼清單3)。
代碼清單3 用四邊形將圖像緩沖區(qū)繪制到紋理
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">// 四邊形頂點(diǎn)的X、Y和Z坐標(biāo)
static const float vertices[] = {
-1.0f, -1.0f, 0,
1.0f, -1.0f, 0,
1.0f, 1.0f, 0,
-1.0f, 1.0f, 0
};
// 四邊形坐標(biāo)(0-1)
static const float coords[] = {
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
// 四邊形頂點(diǎn)索引
static const unsigned short indices[] = { 0, 1, 2, 3};
/**
* 使用四邊形像素(RGB565的unsigned short)將像素?cái)?shù)組繪制到全部屏幕
*
*/
static void DrawIntoTextureRGB565 (unsigned short * pixels, int w, int h)
{
// 清除屏幕
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 啟用頂點(diǎn)和紋理坐標(biāo)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, mTextureID);
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5 , pixels);
// 繪制四邊形
glFrontFace(GL_CCW);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(2, GL_FLOAT, 0, coords);
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);
}
// 翻轉(zhuǎn)surface (繪制到紋理中)
void JNI_RGB565_Flip(unsigned short *pixels , int width, int height)
{
if ( ! pixels) {
return;
}
DrawIntoTextureRGB565 (pixels, width, height);
// 在這里必須交換GLES緩沖區(qū)
jni_swap_buffers ();
}
</SPAN>

使用OpenGL渲染到紋理
(1) 使用glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT)清除顏色與深度緩沖區(qū)。
(2) 啟用客戶端狀態(tài):當(dāng)glDrawElements函數(shù)被調(diào)用時(shí),寫入頂點(diǎn)數(shù)組與紋理坐標(biāo)數(shù)組。
(3) 通過glActiveTexture函數(shù)選擇要激活的紋理單元,初始值是GL_TEXTURE0。
(4) 將已經(jīng)生成的紋理綁定到等待被紋理化的目標(biāo)。GL_TEXTURE_2D (一個(gè)二維紋理)是默認(rèn)的紋理綁定目標(biāo),mTextureID是紋理的ID。
(5) 通過glTexSubImage2D函數(shù)來指定二維紋理子圖,參數(shù)如下:
GL_TEXTURE_2D:指定目標(biāo)紋理類型。
level:指定圖像的詳細(xì)程度(即層數(shù))。0是基本的圖像紋理層。
Xoffset:指定紋理像素在X軸方向上、紋理數(shù)組內(nèi)的偏移量。
Yoffset:指定紋理像素在Y軸方向上、紋理數(shù)組內(nèi)的偏移量。
width:指定紋理子圖的寬度。
height:指定紋理子圖的高度
format:指定像素?cái)?shù)據(jù)的格式。
Type:指定像素?cái)?shù)據(jù)的數(shù)據(jù)類型。
data:指定指向內(nèi)存中圖像數(shù)據(jù)的指針。
(6) 通過調(diào)用以下函數(shù)繪制四邊形頂點(diǎn)、坐標(biāo)與索引:
glFrontFace:?jiǎn)⒂盟倪呅蔚恼妗?br />glVertexPointer:定義四邊形的頂點(diǎn)數(shù)據(jù)數(shù)組,頂點(diǎn)數(shù)據(jù)大小為3,數(shù)據(jù)類型是GL_FLOAT,數(shù)組中每個(gè)頂點(diǎn)間的間隔(步長(zhǎng))為0。
glTexCoordPointer:定義四邊形的紋理數(shù)組,紋理坐標(biāo)大小為2,數(shù)據(jù)類型是GL_FLOAT,間隔為0。
glDrawElements:通過數(shù)據(jù)數(shù)組以三角形扇(GL_TRIANGLE_FAN)的方式渲染多邊形,有4個(gè)頂點(diǎn),類型為短整型(GL_UNSIGNED_SHORT),外加指向索引的指針。
注意,從代碼清單3中我們可以看到四邊形的兩個(gè)軸坐標(biāo)都在[−1,1]區(qū)間內(nèi)。這是因?yàn)镺penGL的坐標(biāo)系統(tǒng)在(−1,1)之間,原點(diǎn)(0,0)在窗口中心(如圖3-10所示)。
 
在理想的世界里,我們不應(yīng)該過多地?fù)?dān)心視頻緩沖區(qū)的尺寸(尤其是使用軟件模擬僅有的定標(biāo)器/渲染器)。當(dāng)在Android中使用OpenGL縮放視頻時(shí),這卻是事實(shí)。在這個(gè)示例中,緩沖區(qū)的尺寸至關(guān)重要。接下來你將學(xué)習(xí)如何處理任意尺寸的視頻,這一點(diǎn)在OpenGL中工作得不是很好。
4. 當(dāng)圖像的尺寸不是2的冪時(shí)會(huì)發(fā)生什么
如前所述,當(dāng)圖像的尺寸是2的冪時(shí)混合縮放會(huì)非常完美。但是,也有可能圖像緩沖區(qū)不是2的冪。例如,在處理Demo引擎的章節(jié)中有一段320×240尺寸的視頻。在這種情況下,圖像仍然被縮放,但是會(huì)縮放到紋理尺寸的百分比大小。在圖2和3中可以看到這個(gè)效果。
 
在圖2中,有以下尺寸:
設(shè)備顯示器:859×480
紋理:512×256
圖像:320×240
正如我們看到的一樣,圖像被縮放到紋理寬度的62%(320/512*100)和高度的93%
(240/256*100)。因此,在任何分辨率大于256的設(shè)備上,圖像都會(huì)被縮放到設(shè)備提供分辨率的62%×93%?,F(xiàn)在我們來看看圖3。
 
圖3 縮放尺寸為2的冪的圖像
在圖3中,有以下尺寸:
設(shè)備顯示器:859×480
紋理:512×256
圖像:512×256
縮放和繪制
在圖3中,我們看見圖像被縮放到設(shè)備提供分辨率的100%,這正是我們想要的。但是如果圖像不是2的冪,那么我們要如何做呢?為了解決這個(gè)問題,我們應(yīng)該:
(1) 用軟件縮放器將320×240尺寸的圖像縮放到接近2的冪(這里是512×256)。
(2) 將已縮放的surface轉(zhuǎn)換成RGB656格式的圖像,以兼容前面介紹的DrawInto-TextureRGB565。
(3) 繪制到紋理,從而使用硬件將其縮放到顯示屏的分辨率。
這種解決辦法可能比前面介紹的方法慢,但仍然比純軟件縮放快,尤其是運(yùn)行在高分辨率設(shè)備時(shí)更明顯(如平板電腦)。
代碼清單4展示了如何使用流行的SDL_gfx庫(kù)來縮放SDL surface。
代碼清單4 用SDL_gfx庫(kù)縮放圖像
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">void JNI_Flip(SDL_Surface *surface )
{
if ( zoom ) {
// 如果surface是8位縮放,就是8位,否則surface就是32的RGBA!
SDL_Surface * sized = zoomSurface( surface, zoomx, zoomy, SMOOTHING_OFF);
JNI_FlipByBPP (sized);
// 必須清理掉!
SDL_FreeSurface(sized);
}
else {
JNI_FlipByBPP (surface);
}
}</SPAN>

縮放和繪制實(shí)現(xiàn)
要放大/縮小SDL surface,需要簡(jiǎn)單地調(diào)用SDL_gfx庫(kù)的zoomSurface:
(1) 一個(gè)SDL surface。
(2) 水平縮放因子:(0-1)
(3) 垂直縮放因子:(0-1)
(4) SMOOTHING_OFF:為了能快速繪制,禁用反鋸齒處理。
接下來,讓我們基于分辨率(每個(gè)像素的位數(shù))來翻轉(zhuǎn)SDL surface。代碼清單5展示了如何完成8位RBG格式的surface。
代碼清單5 根據(jù)分辨率翻轉(zhuǎn)SDL surface
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">/**
* 通過每個(gè)像素的位數(shù)翻轉(zhuǎn)SDL surface
*/
static void JNI_FlipByBPP (SDL_Surface *surface)
{
int bpp = surface->format->BitsPerPixel;
switch ( bpp ) {
case 8:
JNI_Flip8Bit (surface);
break;
case 16:
// 替換16位RGB (surface);
break;
case 32:
// 替換32為RGB (surface);
break;
default:
printf("Invalid depth %d for surface of size %dx%d", bpp, surface->w,
surface->h);
}
}
/**
* 替換8位SDL surface
*/
static void JNI_Flip8Bit(SDL_Surface *surface )
{
int i;
int size = surface->w * surface->h;
int bpp = surface->format->BitsPerPixel;
unsigned short pixels [size]; // RGB565
SDL_Color * colors = surface->format->palette->colors;
for ( i = 0 ; i < size ; i++ ) {
unsigned char pixel = ((unsigned char *)surface->pixels)[i];
pixels[i] = ( (colors[pixel].r >> 3) << 11)
| ( (colors[pixel].g >> 2) << 5)
| (colors[pixel].b >> 3); // RGB565
}
DrawIntoTextureRGB565 (pixels, surface->w, surface->h);
jni_swap_buffers ();
}
</SPAN>

指定SDL surface,然后檢查每個(gè)像素的格式:surface->format->BitsPerPixel,并根據(jù)該值創(chuàng)建能夠被DrawIntoTextureRGB565使用的RGB565像素?cái)?shù)組:
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">for ( i = 0 ; i < size ; i++ ) {
unsigned char pixel = ((unsigned char *)surface->pixels)[i];
// RGB565
pixels[i] = ( (colors[pixel].r >> 3) << 11)
| ( (colors[pixel].g >> 2) << 5)
| (colors[pixel].b >> 3);
}</SPAN>

從surface調(diào)色板上提取每個(gè)像素包含的紅、綠和藍(lán)值:
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">SDL_Color * colors = surface->format->palette->colors;
RED: colors[pixel].r
GREEN: colors[pixel].g
BLUE: colors[pixel].b</SPAN>

為了構(gòu)建RGB565像素,需要從每個(gè)顏色組件中拋棄最低有效位:
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">colors[pixel].r >> 3 (8 -3 = 5)
colors[pixel].g >> 2 (8 – 2 = 6)
colors[pixel].b >> 3 (8 – 3 = 5)</SPAN>

然后移動(dòng)每個(gè)組件到16位值的正確位置(5+6+5= 16——因此是RGB656):
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">pixels[i] = (RED << 11) | (GREEN << 5) | BLUE</SPAN>

最后將新的數(shù)組和圖像寬度、高度一起發(fā)送到DrawIntoTextureRGB565。最后一個(gè)問題,我們需要一種方式來告訴surface是否需要縮放。當(dāng)surface在第一次被創(chuàng)建時(shí)將完成視頻初始化。代碼清單6展示了如何用SDL創(chuàng)建軟件surface。
代碼清單6 初始化縮放surface
復(fù)制代碼 代碼如下:

<SPAN style="FONT-SIZE: 14px">// 應(yīng)該被縮放?
static char zoom = 0;
// 縮放范圍[0,1]
static double zoomx = 1.0;
static double zoomy = 1.0;
/**********************************************************
* 圖像的構(gòu)造函數(shù)
* 圖像必須是2的冪 (256×256, 512×256,...)
* 以便用OpenGL紋理進(jìn)行全屏渲染。如果圖像不是
* POT (320×240),那么它將被縮放
**********************************************************/
SDL_Surface * JNI_SurfaceNew(int width, int height, int bpp, int flags)
{
Uint32 rmask = 0, gmask = 0, bmask =0 , amask = 0;
// 紋理尺寸和偏移量
int realw = 256, realh = 256, offx = 0, offy = 0;
// 圖像必須是2的冪以便OpenGL能縮放它
if ( width > 512 ) {
Sys_Error("ERROR: INVALID IMAGE WIDTH %d (max POT 512×512)", width);
}
// 真實(shí)的W/H必須接近POT值的w/h
// 將要縮放到512×256
// 應(yīng)該是256,但是512的分辨率更高(更慢)
if ( width > 256 ) realw = 512;
// 大小不是POT,就縮放到接近于POT,可選擇:
// 256×256 (快/分辨率低) 512×256 (分辨率較高/較慢)
// 512×512 最慢
if ( ( width != 512 && width != 256) || ( height != 256 ) ) {
zoom = 1;
zoomx = realw / (float)width;
zoomy = realh / (float)height;
offx = offy = 0;
printf("WARNING Texture of size %dx%d will be scaled to %dx%d zoomx=%.3f
zoomy=%.3f"
, width, height, realw, realh, zoomx, zoomy);
}
// 創(chuàng)建渲染器使用的OpenGL紋理
CreateEmptyTextureRGB565 (realw, realh, offx, offy);
// 這是真正的被用于客戶端渲染視頻的surface
return SDL_CreateRGBSurface (SDL_SWSURFACE, width, height, bpp, rmask,
gmask, bmask,
amask);
}
</SPAN>

如果圖像的尺寸不是2的冪,那么縮放標(biāo)志將被設(shè)為1,并且水平和垂直方向的縮放因子將開始計(jì)算。然后,通過調(diào)用CreateEmptyTextureRGB565,根據(jù)寬度、高度和紋理的X、Y位移量來創(chuàng)建空紋理。最后調(diào)用SDL_CreateRGBSurface以創(chuàng)建SDL surface:
SDL_SWSURFACE:告訴SDL創(chuàng)建軟件surface。
width和height:定義surface的尺寸。
bpp:定義surface中每個(gè)像素(分辨率)的位數(shù)(8、16、24和32)。
rmask、gmask、bmask和amask:這些是每個(gè)像素格式的紅、綠、藍(lán)和alpha(透明度)的掩碼值。設(shè)置為0來讓SDL注意到它(譯者注:設(shè)置為0,OpenGL就可以寫入;設(shè)置為1,則不能寫入)。
混合縮放的經(jīng)驗(yàn)法則
總而言之,當(dāng)在游戲中像這樣使用混合縮放時(shí),請(qǐng)牢記以下經(jīng)驗(yàn)法則:
如果可以,就總是設(shè)置視頻的大小為2的冪:256×256或512×56。高于512對(duì)于這種技術(shù)來說代價(jià)太高。
如果不想設(shè)置視頻的尺寸,但又想全屏顯示,就可以像前面提到的那樣,用SDL軟件縮放到最接近的2的冪,然后再使用硬件進(jìn)行縮放。
如果視頻的尺寸大于512×512,混合縮放技術(shù)就未必有效(性能需要)。

相關(guān)文章

  • Android TextView高級(jí)顯示技巧實(shí)例小結(jié)

    Android TextView高級(jí)顯示技巧實(shí)例小結(jié)

    這篇文章主要介紹了Android TextView高級(jí)顯示技巧,結(jié)合實(shí)例形式總結(jié)分析了Android TextView控件進(jìn)行文字與圖片顯示的相關(guān)操作技巧,需要的朋友可以參考下
    2016-10-10
  • Android開發(fā)之完成登陸界面的數(shù)據(jù)保存回顯操作實(shí)例

    Android開發(fā)之完成登陸界面的數(shù)據(jù)保存回顯操作實(shí)例

    這篇文章主要介紹了Android開發(fā)之完成登陸界面的數(shù)據(jù)保存回顯操作實(shí)現(xiàn)方法,結(jié)合完整實(shí)例形式較為詳細(xì)的分析了Android針對(duì)登錄數(shù)據(jù)的保存及回顯操作技巧,需要的朋友可以參考下
    2015-12-12
  • Android UI設(shè)計(jì)與開發(fā)之實(shí)現(xiàn)應(yīng)用程序只啟動(dòng)一次引導(dǎo)界面

    Android UI設(shè)計(jì)與開發(fā)之實(shí)現(xiàn)應(yīng)用程序只啟動(dòng)一次引導(dǎo)界面

    這篇文章主要為大家詳細(xì)介紹了Android UI設(shè)計(jì)與開發(fā)之實(shí)現(xiàn)應(yīng)用程序只啟動(dòng)一次引導(dǎo)界面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • android使用Path繪制出多邊形

    android使用Path繪制出多邊形

    這篇文章主要為大家詳細(xì)介紹了android使用Path繪制出多邊形,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 最新評(píng)論