今天,我們要分享一些使用OpenGL著色語言(GLSL)的最佳實(shí)踐,可以優(yōu)化你的游戲性能并簡化你的工作流程。具體來說,規(guī)劃限定條件會使你的代碼更具確定性并通過減少你的工作量來提高性能。
讓我們開始于一個簡單的頂點(diǎn)著色器,并隨著不斷進(jìn)行而改變它。
這個基本的頂點(diǎn)著色器需要位置和紋理坐標(biāo)、轉(zhuǎn)換位置和輸出數(shù)據(jù)到片段著色器:
attribute vec4 vertexPosition;
attribute vec2 vertexUV;
uniform mat4 matWorldViewProjection;
varying vec2 outTexCoord;
void main()
{
outTexCoord = vertexUV;
gl_Position = matWorldViewProjection * vertexPosition;
}
為了在屏幕上畫一個網(wǎng)格,你需要創(chuàng)建一個頂點(diǎn)緩沖并用頂點(diǎn)數(shù)據(jù)填充它,對于本實(shí)例,包括位置和紋理坐標(biāo)數(shù)據(jù)。
在著色實(shí)例中,頂點(diǎn)數(shù)據(jù)可以布置這樣:
struct Vertex
{
Vector4 Position;
Vector2 TexCoords;
};
因此,我們根據(jù)如下所述定義頂點(diǎn)著色器屬性:
attribute vec4 vertexPosition;
attribute vec2 vertexUV;
為了將頂點(diǎn)數(shù)據(jù)和著色器屬性結(jié)合起來,對glGetAttribLocation 的調(diào)用將獲得命名屬性的句柄。隨著對glVertexAttribPointer的調(diào)用,然后列出了詳細(xì)的屬性格式。
GLint handleVertexPos = glGetAttribLocation( myShaderProgram, "vertexPosition" );
glVertexAttribPointer( handleVertexPos, 4, GL_FLOAT, GL_FALSE, 0, 0 );
GLint handleVertexUV = glGetAttribLocation( myShaderProgram, "vertexUV" );
glVertexAttribPointer( handleVertexUV, 2, GL_FLOAT, GL_FALSE, 0, 0 );
你可以獲得多個帶有vertexPosition 屬性的著色器,并為每個著色器調(diào)用glGetAttribLocation 會降低性能,但這會增加你的游戲加載時間。
使用規(guī)劃限定條件,你可以像如下那樣改變你的頂點(diǎn)著色器屬性聲明:
layout(location = 0) in vec4 vertexPosition;
layout(location = 1) in vec2 vertexUV;
為了達(dá)成這個目的,你還需要告訴著色器編譯器你的著色器是針對GL ES3.1版本。這是通過添加一個版本聲明實(shí)現(xiàn)的:
#version 300 es
讓我們看看如何影響著色器,變化部分以粗體標(biāo)記:
#version 300 es
layout(location = 0) in vec4 vertexPosition;
layout(location = 1) in vec2 vertexUV;
uniform mat4 matWorldViewProjection;
out vec2 outTexCoord;
void main()
{
outTexCoord = vertexUV;
gl_Position = matWorldViewProjection * vertexPosition;
}
應(yīng)當(dāng)注意到,我們還從變更到輸出改變了outTexCoord。從版本300es開始就已經(jīng)無法變更關(guān)鍵詞,并需要更換著色器進(jìn)行工作。
應(yīng)當(dāng)注意到,Vertex Attribute qualifiers和版本300es都支持OpenGL ES 3.0。等效的桌面支持OpenGL 3.3并使用330版本。
現(xiàn)在你知道你的位置屬性總是在0和你的紋理坐標(biāo)將在1,現(xiàn)在你可以不使用glGetAttribLocation而約束你的著色器格式。
const int ATTRIB_POS = 0;
const int ATTRIB_UV = 1;
glVertexAttribPointer( ATTRIB_POS, 4, GL_FLOAT, GL_FALSE, 0, 0 );
glVertexAttribPointer( ATTRIB_UV, 2, GL_FLOAT, GL_FALSE, 0, 0 );
這個簡單的變化會導(dǎo)致一個更清潔的通道、簡化的代碼,并在加載期間保持了性能。
Android性能擴(kuò)展Android Performance Patterns series