Hi, the triangle is drawn perfectly on PC (imgui > example_glfw_opengl3), but it isn’t drawn (invisible) on Android (imgui > example_android_opengl3). What could be the possible cause of that problem? However, the ImGui UI is drawn (visible) on Android, and it’s drawn using OpenGL.
As a beginner, it’s impossible to post something on Stack Overflow that requires a high-quality thread. Similarly, it’s difficult to post the same thing on the ImGui GitHub discussion because they specify that only ImGui-specific thread should be posted there.
Functions from Cxxdroid:
// Originated from Cxxdroid (Android app) > OpenGL ES
#if !defined(__ANDROID__)
// OpenGL
#ifdef USE_OPENGL
#ifdef OPENGL_LOADER_GL3W
#include "GL/gl3w.h"
#elif OPENGL_LOADER_GLEW
#include "GL/glew.h"
#elif OPENGL_LOADER_GLAD
// TODO
#endif
#endif
#else // ANDROID
#include <android/log.h>
#ifdef USE_OPENGL
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#endif
#endif
const char *VERTEX_SHADER =
"attribute vec4 position;\n"
"attribute vec4 color;\n"
"varying vec4 vcolor;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.xyz, 1.0);\n"
"vcolor = color;\n"
"}";
const char *FRAGMENT_SHADER =
"precision mediump float;\n"
"varying vec4 vcolor;\n"
"void main()\n"
"{\n"
"gl_FragColor = vec4 (vcolor.xyz, 1.0);\n"
"}";
static GLfloat vertexes[] = {0.0f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f};
static GLfloat colors[12] = {};
void triangle_init()
{
// Load shaders
GLuint vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &VERTEX_SHADER, NULL);
glCompileShader(vertex);
GLuint fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &FRAGMENT_SHADER, NULL);
glCompileShader(fragment);
// Combine shaders into program
GLuint program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
// Use it
glUseProgram(program);
// Point position attribute to vertexes
GLint position = glGetAttribLocation(program, "position");
glEnableVertexAttribArray(position);
glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, vertexes);
// Point color attribute to colors
GLint color = glGetAttribLocation(program, "color");
glEnableVertexAttribArray(color);
glVertexAttribPointer(color, 4, GL_FLOAT, GL_FALSE, 0, colors);
}
void triangle_render() {
static double timemillis = 0.0;
timemillis += 1000.0 / 60.0;
// Animate colors
for (int i = 0; i < 3; i++)
{
colors[i * 4 + 0] = sin(i * M_PI * 2 / 3 + timemillis / 1000) / 2 + 0.5f;
colors[i * 4 + 1] = sin((i + 1) * M_PI * 2 / 3 + timemillis / 1000) / 2 + 0.5f;
colors[i * 4 + 2] = sin((i + 2) * M_PI * 2 / 3 + timemillis / 1000) / 2 + 0.5f;
colors[i * 4 + 3] = 1.0f;
}
// Clear screen
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Other functions:
bool setupGraphics(int renderingApi) {
if (renderingApi == RENDERINGAPI_OPENGL) {
#ifdef USE_OPENGL
// Initialize OpenGL loader - Referenced from [GLSL-PathTracer > "src/Main.cpp"](https://github.com/knightcrawler25/GLSL-PathTracer)
{
#if GL_VERSION_3_2
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
bool err = gl3wInit() != 0;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
bool err = glewInit() != GLEW_OK;
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLAD)
bool err = gladLoadGL() == 0;
#endif
if (err) {
fprintf(stderr, "Failed to initialize OpenGL loader!\n");
return false;
}
#endif
}
#endif
} else if (renderingApi == RENDERINGAPI_VULKAN) {
#ifdef USE_VULKAN
// TODO
#endif
}
triangle_init();
return true;
}
void imGuiFrame() {
ImGui::Begin("Test");
ImGui::Text("Hello, world!");
ImGui::End();
}
void renderFrame(int renderingApi) {
if (renderingApi == RENDERINGAPI_OPENGL) {
#ifdef USE_OPENGL
triangle_render();
#endif
} else if (renderingApi == RENDERINGAPI_VULKAN) {
#ifdef USE_VULKAN
// TODO
#endif
}
}
How is the function renderFrame() called?:
ImGui::Render();
ImDrawData* mainDrawData = ImGui::GetDrawData();
const bool mainIsMinimized = (mainDrawData->DisplaySize.x <= 0.0f || mainDrawData->DisplaySize.y <= 0.0f);
if (renderingApi == RENDERINGAPI_OPENGL) {
#ifdef USE_OPENGL
glViewport(0, 0, int(displaySize.x), int(displaySize.y));
glClearColor(params.clearColor.x * params.clearColor.w, params.clearColor.y * params.clearColor.w, params.clearColor.z * params.clearColor.w, params.clearColor.w);
//_/--------------------------------------------------\_
// Callback (renderFrame())
if (params.mainParams.func_renderFrame) {
params.mainParams.func_renderFrame(renderingApi);
}
// \--------------------------------------------------/
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
#if !defined(__ANDROID__)
// .
#else // ANDROID
eglSwapBuffers(g_EglDisplay, g_EglSurface);
#endif
#endif
} else if (renderingApi == RENDERINGAPI_VULKAN) {
...
}
From:
I added a line that calls the function setupGraphics()
in the function android_main()
just before the loop. Should I call it in Init()? It’s difficult to do in my code because params
is not available there. However, I don’t believe it will fix the problem because I’ve tried as many methods as possible, but I’m not sure.
I added a line that calls the function renderFrame()
in the function MainLoopStep()
just before calling ImGui_ImplOpenGL3_RenderDrawData()
.