我正在使用我的光手在一些手機上面臨一些性能問題。 着色器根據正常圖計算線條和點光線。 這也表明命中目標(這是一個2D自上而下的射手遊戲)。OpenGL ES着色器在較舊的手機上出現巨大的性能問題
我正在開發索尼Xperia Z5 Compact,其中一切正常 就好。然後我在我非常古老的三星Galaxy S2上試了一下,其中 真的很慢。由於電話的年齡我不在乎。
現在我嘗試了Galaxy S4和Galaxy S5,但它似乎並沒有比Galaxy S2更快地運行 。我也有編輯時間(大約90秒),但我設法通過優化代碼將它簡化爲幾秒鐘(儘管我認爲它仍然很雜亂,但我並不真正注意着色器)。
我真的不知道這裏的瓶頸是什麼,以及爲什麼它沒有在S4和S5上跑得更快。
這是我的着色器:
#ifdef GL_ES
#define LOWP lowp
precision highp float;
#else
#define LOWP
#endif
#define MAX_NUM_POINTLIGHTS 16
uniform vec3 lpos[MAX_NUM_POINTLIGHTS]; // Light position
uniform vec3 foff[MAX_NUM_POINTLIGHTS]; // Light falloff
uniform vec4 acol[MAX_NUM_POINTLIGHTS]; // Ambient color
uniform vec4 lcol[MAX_NUM_POINTLIGHTS]; // Light color
//textures
uniform sampler2D u_texture1; // diffuse texture
uniform sampler2D u_texture2; // normalmap
varying vec4 vColor;
varying vec2 vTexCoord;
varying float vFlags;
uniform vec2 Resolution; //resolution of screen
const float WORLD_WIDTH = 1440.0;
const float WORLD_HEIGHT = 2560.0;
vec3 getPointLightColor(const vec4);
vec3 rotateVector(const vec3 vector, const float angle);
vec2 screenCoordToWorldCoord(const vec2 screencoord);
vec3 calculatePointLight(const vec4 DiffuseColor, vec3 LightPos, const vec3 Falloff, const vec4 LightColor, const vec4 AmbientColor);
const float stdratio = WORLD_HEIGHT/WORLD_WIDTH;
vec2 worldFragCoord;
const float worldRatio_W_DIV_H = WORLD_WIDTH/WORLD_HEIGHT;
const vec2 worldSize = vec2(WORLD_WIDTH, WORLD_HEIGHT);
// Light variables
vec3 NormalMap;
vec2 worldFragCoordNormalized;
vec3 N;
void main() {
worldFragCoord = screenCoordToWorldCoord(gl_FragCoord.xy);
// Common light calculations
NormalMap = texture2D(u_texture2, vTexCoord).rgb;
worldFragCoordNormalized = worldFragCoord/vec2(1440.0, 2560.0);
N = normalize(NormalMap * 2.0 - 1.0);
vec4 DiffuseColor = texture2D(u_texture1, vTexCoord);
vec2 fragcoord = gl_FragCoord.xy;
vec3 pointcolor = getPointLightColor(DiffuseColor);
vec4 finalColor;
// green channel of vColor indicates hit
if (vColor.g > 0.0 && vColor.a == 0.0) {
vec4 fragcol = vec4(pointcolor, DiffuseColor.a);
vec4 addColor;
if (vColor.g > 0.67)
addColor = vec4(1.0,1.0,1.0, DiffuseColor.a*vColor.g);
else if (vColor.g > 0.52)
addColor = vec4(1.0,0.0,0.0, DiffuseColor.a*vColor.g);
else if (vColor.g > 0.37)
addColor = vec4(0.0,0.0,1.0, DiffuseColor.a*vColor.g);
else if (vColor.g > 0.22)
addColor = vec4(1.0,1.0,0.0, DiffuseColor.a*vColor.g);
else
addColor = vec4(0.0,1.0,1.0, DiffuseColor.a*vColor.g);
finalColor = addColor*addColor.a + fragcol*(1.0-addColor.a);
}
else
finalColor = vec4(pointcolor, DiffuseColor.a);
gl_FragColor = finalColor;
}
vec3 rotateVector(const vec3 vector, const float angle){
float degree = radians(360.0*angle); // Angle is normalized to 0 - 1
float cos_ = cos(degree);
float sin_ = sin(degree);
return vec3(vector.x*cos_ - vector.y*sin_, vector.x*sin_ + vector.y*cos_, vector.z);
}
vec3 calculatePointLight(const vec4 DiffuseColor, vec3 LightPos, const vec3 Falloff, const vec4 LightColor, const vec4 AmbientColor){
if (LightPos.x == 0.0 && LightPos.y == 0.0)
return vec3(0.0);
LightPos.xy = LightPos.xy/worldSize;
//The delta position of light
vec3 LightDir = vec3(LightPos.xy - worldFragCoordNormalized, LightPos.z);
//Correct for aspect ratio
LightDir.x *= worldRatio_W_DIV_H;
//Determine distance (used for attenuation) BEFORE we normalize our LightDir
float D = length(LightDir);
//normalize our vectors
vec3 L = normalize(LightDir);
vec3 NN = N;
if (vColor.a == 0.0)
NN = normalize(rotateVector(NN, vColor.r));
//Pre-multiply light color with intensity
//Then perform "NN dot L" to determine our diffuse term
vec3 Diffuse = (LightColor.rgb * LightColor.a) * max(dot(NN, L), 0.0);
//pre-multiply ambient color with intensity
vec3 Ambient = AmbientColor.rgb * AmbientColor.a;
//calculate attenuation
float Attenuation = 1.0/(Falloff.x + (Falloff.y*D) + (Falloff.z*D*D));
//the calculation which brings it all together
vec3 Intensity = Ambient + Diffuse * Attenuation;
vec3 FinalColor = DiffuseColor.rgb * Intensity;
return FinalColor;
}
vec3 getPointLightColor(const vec4 DiffuseColor){
vec3 sum = vec3(0.0);
for (int i = 0; i < MAX_NUM_POINTLIGHTS; i++)
{
sum += calculatePointLight(DiffuseColor, lpos[i], foff[i], lcol[i], acol[i]);
}
return sum;
}
vec2 screenCoordToWorldCoord(const vec2 screencoord){
float ratio = Resolution.y/Resolution.x;
vec2 resCoord;
if (ratio == stdratio){
// Ratio is standard
resCoord = screencoord * (WORLD_HEIGHT/Resolution.y);
} else if (ratio > stdratio) {
// Screen gets extended vertically (black bars top/bottom)
float screenheight = Resolution.x * stdratio;
float bottom = (Resolution.y - screenheight)/2.0;
resCoord = vec2(screencoord.x, screencoord.y - bottom);
resCoord *= (WORLD_WIDTH/Resolution.x);
} else {
// Screen gets extended horizontally (black bars left/right)
float screenwidth = Resolution.y/stdratio;
float left = (Resolution.x - screenwidth)/2.0;
resCoord = vec2(screencoord.x - left, screencoord.y);
resCoord *= (WORLD_HEIGHT/Resolution.y);
}
return resCoord;
}
將嘗試找到時間來消化其他地方比我的手機,但作爲一般規則:循環和條件是麻煩,往往甚至與做不必要的工作,並通過一些組合夾具,步驟等有效地丟棄它。 – Tommy
我有這些循環展開之前,但我讀了循環與常量就好了。你認爲這些條件是否會導致這種情況? – Draz
是的 - 假設編譯器很聰明(而且相當安全),如果需要的話,帶有常量的循環會自動展開。添加一個'if(我
Tommy