Mam grę, która działa całkiem dobrze (55-60 fps) na wyświetlaczu siatkówki. Chcę dodać nakładkę pełnoekranową, która łączy się z istniejącą sceną. Jednak nawet przy użyciu małej tekstury osiągi są ogromne. Czy istnieje optymalizacja, którą mogę wykonać, aby była ona użyteczna?Uderzenie wydajności z mieszania dużego quada
Jeśli używam tekstury 80x120 (tekstura jest renderowana w locie, dlatego nie jest kwadratowa), otrzymuję 25-30 FPS. Jeśli sprawię, że tekstura będzie mniejsza, wydajność wzrośnie, ale jakość nie będzie akceptowalna. Generalnie jednak jakość nakładki nie jest bardzo ważna (to tylko oświetlenie).
Wykorzystanie renderera wynosi 99%.
Nawet jeśli użyję kwadratowej tekstury z pliku (.png), wydajność jest zła.
ten sposób utworzyć teksturę:
[EAGLContext setCurrentContext:context];
// Create default framebuffer object.
glGenFramebuffers(1, &lightFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);
// Create color render buffer and allocate backing store.
glGenRenderbuffers(1, &lightRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, LIGHT_WIDTH, LIGHT_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, lightRenderbuffer);
glGenTextures(1, &lightImage);
glBindTexture(GL_TEXTURE_2D, lightImage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LIGHT_WIDTH, LIGHT_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightImage, 0);
A oto renderowania ...
/* Draw scene... */
glBlendFunc(GL_ONE, GL_ONE);
//Switch to offscreen texture buffer
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
glViewport(0, 0, LIGHT_WIDTH, LIGHT_HEIGHT);
glClearColor(ambientLight, ambientLight, ambientLight, ambientLight);
glClear(GL_COLOR_BUFFER_BIT);
/* Draw lights to texture... */
//Switch back to main frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glBindTexture(GL_TEXTURE_2D, glview.lightImage);
/* Set up drawing... */
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0);
Oto niektóre odniesienia wziąłem podczas próby zawężenia problemu. "Bez mieszania" oznacza, że mogę wyłączyć (GL_BLEND) zanim narysuję quad. "Brak przełączania bufora" oznacza, że przed rysowaniem nie przełączam się z bufora poza ekranem.
(Tests using a static 256x256 .png)
No blend, No buffer switching: 52FPS
Yes blend, No buffer switching: 29FPS //disabled the glClear, which would artificially speed up the rendering
No blend, Yes buffer switching: 29FPS
Yes blend, Yes buffer switching: 27FPS
Yes buffer switching, No drawing: 46FPS
Każda pomoc jest doceniana. Dzięki!
UPDATE
Zamiast mieszania cały lightmap potem skończyło się na napisanie cieniującego do pracy na bieżąco. Każdy fragment pobiera próbki i miesza się z mapą światła (rodzaj podobnego multiteksturowania). Początkowo przyrost wydajności był minimalny, ale potem użyłem lowpl sampler2d dla mapy światła, a następnie uzyskałem około 45 FPS.
Oto fragment shader:
lowp vec4 texColor = texture2D(tex, texCoordsVarying);
lowp vec4 lightColor = texture2D(lightMap, worldPosVarying);
lightColor.rgb *= lightColor.a;
lightColor.a = 1.0;
gl_FragColor = texColor * color * lightColor;
Podejrzewam, że 'bufor glView' przełączniki są prawdopodobnie winowajcą. Co się dzieje w tych metodach? Dlaczego nie użyć 'glBindRenderBuffer'? – Justicle
Wprowadzę te metody do wyjaśnienia. – whooops
Ok do debufowania problemu perf, spróbuj wstępnego renderowania nakładki (po prostu pozostaw to na razie statyczne), a następnie skopiuj ją do głównego bufora każdej klatki. To przynajmniej powie ci, czy przełączniki bufora są wolne (tj. Wykonywanie dwóch wywołań do glBindFrame, glBindRender, glViewport dla każdej klatki). – Justicle