在 Android 上使用 gles 2.0\egl\native activity 时没有绘制任何内容
Nothing is drawn when using gles 2.0\egl\native activity on Android
基本上我有一个非常简单的着色器在 GLES 2.0 上绘制一个非常原始的正方形,着色器编译和加载正确,而且我没有 glErrors。
我可以使用 glClear 显示 glClearColor,但没有绘制任何其他内容。
我已经链接到 GLESv2 并包含 <GLES2/gl2.h>
和 <GLES2/gl2ext.h>
这是我的 EGL 初始化代码:
//...
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_NONE
};
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs)
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)
ANativeWindow_setBuffersGeometry(engine->app->window, 320, 200, format);
surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
eglMakeCurrent(display, surface, surface, context)
//...
这是我的渲染循环,包括 egl 交换缓冲区:
void RenderSimpleScene(int iWidth, int iHeight, float mouseX, float mouseY, int mouseButtons) {
const static auto kStartTime = std::chrono::system_clock::now();
const auto elapsedMillis = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - kStartTime).count();
static bool sInitialized = false;
static GLuint programId = -1;
static GLuint vboId = -1;
// I have tried different z-values
std::vector<GLfloat> verticesData = {
-1, -1, 0.5, 1,
1, -1, 0.5, 1,
1, 1, 0.5, 1,
//
-1, -1, 0.5, 1,
1, 1, 0.5, 1,
-1, 1, 0.5, 1
};
const auto bytesPerCoord = sizeof(GLfloat);
const auto coordsPerVertex = 4;
const auto bytesPerVertex = bytesPerCoord * coordsPerVertex;
const auto numVerts = verticesData.size() / coordsPerVertex;
if (!sInitialized) {
sInitialized = true;
GetGLErrors();
const std::string vertexSource =
"#version 100\n"
"attribute vec4 aVertex;\n"
"void main() {\n"
" gl_Position = aVertex;\n"
"}\n";
const std::string fragmentSource =
"#version 100\n"
"precision mediump float;\n"
"void main() {\n"
" vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
" gl_FragColor = color;}\n";
programId = glCreateProgram();
const auto CompileFunctor = [](const std::string& iShaderSrc, const GLenum iShaderType) -> GLuint {
const auto id = glCreateShader(iShaderType);
const GLchar* srcAdr = iShaderSrc.c_str();
glShaderSource(id, 1, &srcAdr, 0);
glCompileShader(id);
GLint status = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
ASSERT(status == GL_TRUE);
GetGLErrors();
return id;
};
const auto vertexId = CompileFunctor(vertexSource, GL_VERTEX_SHADER);
const auto fragmentId = CompileFunctor(fragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(programId, vertexId);
glAttachShader(programId, fragmentId);
glLinkProgram(programId);
GLint linked = -1;
glGetProgramiv(programId, GL_LINK_STATUS, &linked);
ASSERT(linked == GL_TRUE);
GetGLErrors();
// VBO
glGenBuffers(1, (GLuint*)&vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
const auto numBytes = sizeof(verticesData.front())*verticesData.size();
glBufferData(GL_ARRAY_BUFFER, numBytes, verticesData.data(), GL_STATIC_DRAW);
GetGLErrors();
}
// Prepare GL
// The background color varies as clear color changes
glClearColor(0, 0.5, (std::sin(elapsedMillis*0.001f) + 1) * 0.33, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
glViewport(0, 0, iWidth, iHeight);
GetGLErrors();
// Activate program
glUseProgram(programId);
// VBO
glBindBuffer(GL_ARRAY_BUFFER, vboId);
ASSERT(glGetAttribLocation(programId, "aVertex") != -1);
const auto vertexLocation = glGetAttribLocation(programId, "aVertex");
glVertexAttribPointer(vertexLocation, coordsPerVertex, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(vertexLocation);
GetGLErrors();
// Render
glDrawArrays(GL_TRIANGLES, 0, numVerts);
GetGLErrors();
// Clean up
glDisableVertexAttribArray(vertexLocation);
glUseProgram(0);
GetGLErrors();
eglSwapBuffers(engine->display, engine->surface);
}
将我的初始化代码重写为这个,它起作用了:
更改 eglCreateContext(...) 是我错过的:
const int attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, selectedConfig, EGL_NO_CONTEXT, attrib_list);
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
// Get num configs
EGLint numConfigs;
eglChooseConfig(display, attribs, nullptr, 1, &numConfigs);
auto configs = std::vector<EGLConfig>(numConfigs);
EGLint fetchedConfigs = 0;
eglChooseConfig(display, attribs, configs.data(), numConfigs, &fetchedConfigs);
for (const auto& config : configs) {
EGLint depth = 0;
EGLint stencil = 0;
EGLint r = 0;
EGLint g = 0;
EGLint b = 0;
EGLint a = 0;
eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth);
eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencil);
eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
}
const auto& selectedConfig = configs.front();
EGLSurface surface;
EGLContext context;
EGLint format = -1;
eglGetConfigAttrib(display, selectedConfig, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine->app->window, 320, 200, format);
surface = eglCreateWindowSurface(display, selectedConfig, engine->app->window, NULL);
// ------ This was the crucial part ---
const int attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, selectedConfig, EGL_NO_CONTEXT, attrib_list);
// -----------------------------------
eglMakeCurrent(display, surface, surface, context);
基本上我有一个非常简单的着色器在 GLES 2.0 上绘制一个非常原始的正方形,着色器编译和加载正确,而且我没有 glErrors。
我可以使用 glClear 显示 glClearColor,但没有绘制任何其他内容。
我已经链接到 GLESv2 并包含 <GLES2/gl2.h>
和 <GLES2/gl2ext.h>
这是我的 EGL 初始化代码:
//...
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_NONE
};
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs)
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)
ANativeWindow_setBuffersGeometry(engine->app->window, 320, 200, format);
surface = eglCreateWindowSurface(display, config, engine->app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
eglMakeCurrent(display, surface, surface, context)
//...
这是我的渲染循环,包括 egl 交换缓冲区:
void RenderSimpleScene(int iWidth, int iHeight, float mouseX, float mouseY, int mouseButtons) {
const static auto kStartTime = std::chrono::system_clock::now();
const auto elapsedMillis = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - kStartTime).count();
static bool sInitialized = false;
static GLuint programId = -1;
static GLuint vboId = -1;
// I have tried different z-values
std::vector<GLfloat> verticesData = {
-1, -1, 0.5, 1,
1, -1, 0.5, 1,
1, 1, 0.5, 1,
//
-1, -1, 0.5, 1,
1, 1, 0.5, 1,
-1, 1, 0.5, 1
};
const auto bytesPerCoord = sizeof(GLfloat);
const auto coordsPerVertex = 4;
const auto bytesPerVertex = bytesPerCoord * coordsPerVertex;
const auto numVerts = verticesData.size() / coordsPerVertex;
if (!sInitialized) {
sInitialized = true;
GetGLErrors();
const std::string vertexSource =
"#version 100\n"
"attribute vec4 aVertex;\n"
"void main() {\n"
" gl_Position = aVertex;\n"
"}\n";
const std::string fragmentSource =
"#version 100\n"
"precision mediump float;\n"
"void main() {\n"
" vec4 color = vec4(1.0, 0.0, 0.0, 1.0);\n"
" gl_FragColor = color;}\n";
programId = glCreateProgram();
const auto CompileFunctor = [](const std::string& iShaderSrc, const GLenum iShaderType) -> GLuint {
const auto id = glCreateShader(iShaderType);
const GLchar* srcAdr = iShaderSrc.c_str();
glShaderSource(id, 1, &srcAdr, 0);
glCompileShader(id);
GLint status = 0;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
ASSERT(status == GL_TRUE);
GetGLErrors();
return id;
};
const auto vertexId = CompileFunctor(vertexSource, GL_VERTEX_SHADER);
const auto fragmentId = CompileFunctor(fragmentSource, GL_FRAGMENT_SHADER);
glAttachShader(programId, vertexId);
glAttachShader(programId, fragmentId);
glLinkProgram(programId);
GLint linked = -1;
glGetProgramiv(programId, GL_LINK_STATUS, &linked);
ASSERT(linked == GL_TRUE);
GetGLErrors();
// VBO
glGenBuffers(1, (GLuint*)&vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
const auto numBytes = sizeof(verticesData.front())*verticesData.size();
glBufferData(GL_ARRAY_BUFFER, numBytes, verticesData.data(), GL_STATIC_DRAW);
GetGLErrors();
}
// Prepare GL
// The background color varies as clear color changes
glClearColor(0, 0.5, (std::sin(elapsedMillis*0.001f) + 1) * 0.33, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_STENCIL_TEST);
glViewport(0, 0, iWidth, iHeight);
GetGLErrors();
// Activate program
glUseProgram(programId);
// VBO
glBindBuffer(GL_ARRAY_BUFFER, vboId);
ASSERT(glGetAttribLocation(programId, "aVertex") != -1);
const auto vertexLocation = glGetAttribLocation(programId, "aVertex");
glVertexAttribPointer(vertexLocation, coordsPerVertex, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(vertexLocation);
GetGLErrors();
// Render
glDrawArrays(GL_TRIANGLES, 0, numVerts);
GetGLErrors();
// Clean up
glDisableVertexAttribArray(vertexLocation);
glUseProgram(0);
GetGLErrors();
eglSwapBuffers(engine->display, engine->surface);
}
将我的初始化代码重写为这个,它起作用了: 更改 eglCreateContext(...) 是我错过的: const int attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; context = eglCreateContext(display, selectedConfig, EGL_NO_CONTEXT, attrib_list);
const EGLint attribs[] = {
EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE,
EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_STENCIL_SIZE, 8,
EGL_NONE
};
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
// Get num configs
EGLint numConfigs;
eglChooseConfig(display, attribs, nullptr, 1, &numConfigs);
auto configs = std::vector<EGLConfig>(numConfigs);
EGLint fetchedConfigs = 0;
eglChooseConfig(display, attribs, configs.data(), numConfigs, &fetchedConfigs);
for (const auto& config : configs) {
EGLint depth = 0;
EGLint stencil = 0;
EGLint r = 0;
EGLint g = 0;
EGLint b = 0;
EGLint a = 0;
eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth);
eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencil);
eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
}
const auto& selectedConfig = configs.front();
EGLSurface surface;
EGLContext context;
EGLint format = -1;
eglGetConfigAttrib(display, selectedConfig, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine->app->window, 320, 200, format);
surface = eglCreateWindowSurface(display, selectedConfig, engine->app->window, NULL);
// ------ This was the crucial part ---
const int attrib_list[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
context = eglCreateContext(display, selectedConfig, EGL_NO_CONTEXT, attrib_list);
// -----------------------------------
eglMakeCurrent(display, surface, surface, context);