我正在尝试将一款使用SDL 1.2和OpenGL 1.3的游戏移植到Android,并最终移植到iOS。
为此,我不得不切换到SDL 1.3,这是尚未发布的下一个版本,将成为SDL 2.0,它已被移植到Android。初始结果很好,仅使用SDL和SDL_image就可以正常工作。
但是当我将OpenGL ES 1.1添加到混合中并尝试渲染纹理矩形时,我所得到的只是一个白色矩形。
你知道我哪里做错了吗?就像我说的,只要SDL/SDL_image就可以很好地显示图像。
Edit:我已经根据Ryan Maloney的建议更新了下面的代码,即使用浮动文字,我使用GL_FLOAT并尝试使用SDL_GL_BindTexture
而不是手动创建纹理。虽然也不起作用,我得到一个黑色的纹理和一些错误:没有EGL配置可用,EGLNativeWindowType 0x2a1b5380已经连接到另一个API。glBindTexture
仍然产生白色纹理。
编辑2:刚刚有了实际检查错误的光荣想法:如果我在glTexImage2D
之后调用glGetError()
,我得到GL_INVALID_OPERATION
。
#include <GLES/gl.h>
#include <SDL.h>
#include <SDL_image.h>
#include <string>
// Set to 1 to use SDL_GL_BindTexture instead of glBindTexture
#define USE_SDL_TEXTURE 0
static const int screen_width = 640;
static const int screen_height = 480;
void init_opengl()
{
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, screen_width, screen_height);
glOrthof(0, screen_width, screen_height, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
}
int next_power_of_two(int n)
{
double logbase2 = log((double) n) / log(2.0);
return (int) (pow(2, ceil(logbase2)) + 0.5);
}
SDL_Surface* convert_to_power_of_two(SDL_Surface* surface)
{
int width = next_power_of_two(surface->w);
int height = next_power_of_two(surface->h);
SDL_Surface* pot_surface = SDL_CreateRGBSurface(0, width, height, 32,
0x00ff0000, 0x0000ff00,
0x000000ff, 0xff000000);
SDL_Rect dstrect;
dstrect.w = surface->w;
dstrect.h = surface->h;
dstrect.x = 0;
dstrect.y = 0;
SDL_SetSurfaceAlphaMod(surface, 0);
SDL_BlitSurface(surface, NULL, pot_surface, &dstrect);
SDL_FreeSurface(surface);
return pot_surface;
}
GLenum get_texture_format(SDL_PixelFormat* pixel_format, GLint bpp)
{
switch (bpp) {
case 4:
return GL_RGBA;
case 3:
return GL_RGB;
}
throw "Unsupported pixel format";
}
#if USE_SDL_TEXTURE
SDL_Texture* load_image(const std::string& path, SDL_Renderer* renderer)
#else
GLuint load_image(const std::string& path)
#endif
{
SDL_Surface* surface = IMG_Load(path.c_str());
SDL_Surface* pot_surface = convert_to_power_of_two(surface);
#if USE_SDL_TEXTURE
return SDL_CreateTextureFromSurface(renderer, surface);
#else
SDL_PixelFormat* pixel_format = pot_surface->format;
GLint bpp = pixel_format->BytesPerPixel;
GLenum texture_format = get_texture_format(pixel_format, bpp);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, bpp, pot_surface->w, pot_surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, pot_surface->pixels);
SDL_FreeSurface(pot_surface);
return texture;
#endif
}
#if USE_SDL_TEXTURE
void draw_texture(SDL_Texture* texture, float width, float height)
#else
void draw_texture(GLuint texture, float width, float height)
#endif
{
#if USE_SDL_TEXTURE
SDL_GL_BindTexture(texture, NULL, NULL);
#else
glBindTexture(GL_TEXTURE_2D, texture);
#endif
GLfloat texture_coordinates[] = {0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f};
glTexCoordPointer(2, GL_FLOAT, 0, texture_coordinates);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
GLfloat vertices[] = {0.0f, height,
0.0f, 0.0f,
width, height,
width, 0.0f};
glVertexPointer(2, GL_FLOAT, 0, vertices);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
IMG_Init(IMG_INIT_PNG);
atexit(IMG_Quit);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
const Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
SDL_Window* window = SDL_CreateWindow("Foo", 0, 0,
screen_width, screen_height, flags);
#if USE_SDL_TEXTURE
SDL_Renderer* renderer = SDL_CreateRenderer(window, 1, SDL_RENDERER_ACCELERATED);
#endif
SDL_GLContext context = SDL_GL_CreateContext(window);
SDL_GL_SetSwapInterval(1);
init_opengl();
#if USE_SDL_TEXTURE
SDL_Texture* texture = load_image("character_editor_bg.png", renderer);
#else
GLuint texture = load_image("character_editor_bg.png");
#endif
SDL_Event event;
for (;;) {
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
glClear(GL_COLOR_BUFFER_BIT);
draw_texture(texture, screen_width, screen_height);
SDL_GL_SwapWindow(window);
SDL_Delay(1);
}
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
终于找到问题了。事实上,我使用glTexImage2D
完全错误,由于某种原因,它在OpenGL 1.3中工作得很好。
调用应该是这样的:
glTexImage2D(GL_TEXTURE_2D, 0, texture_format, pot_surface->w, pot_surface->h, 0,
texture_format, GL_UNSIGNED_BYTE, pot_surface->pixels);
之前,我传递了bpp
作为第三个参数,这是垃圾。