Skia渲染结果在外部OpenGL环境绘制显示黑屏求助
Skia渲染到FBO后外部OpenGL绘制黑屏排查
我尝试将Skia的渲染结果绘制到FBO而非直接绘制到窗口帧缓冲,步骤如下:
- 创建关联FBO的纹理
- 使用
SkSurfaces::WrapBackendRenderTarget,基于已创建的FBO创建SkSurface - 通过Skia的Canvas进行绘制
- 在外部OpenGL环境中将步骤1创建的纹理绘制到屏幕,但显示黑屏
完成步骤3后导出该纹理,确认其内容是正确的,相关代码片段如下:
//initialize in render thread: glfwMakeContextCurrent(native_window_); int width = 800, height = 600; sk_sp<const GrGLInterface> glInterface = GrGLMakeNativeInterface(); GrDirectContext* grDirectContext_ = GrDirectContexts::MakeGL(GrGLMakeNativeInterface(), GrContextOptions()).release(); shared_ptr<TextureData> g_texture = CITextureUtils::createTextureWithFBO(CIGLContext::getInstance(), width, height); sk_sp<SkSurface> g_surface = SkSurfaces::WrapBackendRenderTarget( grDirectContext_, GrBackendRenderTargets::MakeGL(width, height, 1, 8, GrGLFramebufferInfo{(GrGLuint)g_texture->fbo, GL_RGBA8}), kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, nullptr, nullptr); //the draw loop in render thread: SkCanvas *canvas = g_surface->getCanvas(); canvas->clear(kClearColor); canvas->save(); canvas->translate(SkIntToScalar(128), SkIntToScalar(128)); canvas->rotate(SkIntToScalar(45)); SkRect rect = SkRect::MakeXYWH(-90.5f, -90.5f, 181.0f, 181.0f); SkPaint paint; paint.setColor(SK_ColorBLUE); canvas->drawRect(rect, paint); canvas->restore(); grDirectContext_->flush(); grDirectContext_->resetContext(); // here dump the created texture, the texture has right context glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); glGetIntegerv(GL_FRAMEBUFFER_BINDING, &lOldFbo); glBindFramebuffer(GL_FRAMEBUFFER, texture->fbo); glReadPixels(0, 0, bitmap->width, bitmap->height, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->plane[0]); glBindFramebuffer(GL_FRAMEBUFFER, lOldFbo); // draw in outside opengl environment in render thread: glViewport(0, 0, width, height); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, g_texture->textureID); GLint currProgram; glGetIntegerv(GL_CURRENT_PROGRAM, &currProgram); shader_.use(); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glfwSwapBuffers((GLFWwindow*)window_);
排查方向:
- Y轴方向不匹配
Skia使用kBottomLeft_GrSurfaceOrigin,纹理原点在左下角;而OpenGL默认纹理原点在右上角。若着色器未处理Y轴翻转,会导致内容显示异常甚至黑屏。可在片段着色器中修改纹理坐标:
vec4 color = texture(u_texture, vec2(texCoord.x, 1.0 - texCoord.y));
- Skia上下文状态残留
即使调用了flush()和resetContext(),Skia可能仍占用部分OpenGL状态。建议在Skia绘制完成后:
- 明确绑定默认帧缓冲:
glBindFramebuffer(GL_FRAMEBUFFER, 0); - 重置纹理绑定状态,确保后续绘制使用正确的纹理单元
- 纹理采样参数未正确设置
若纹理未设置合理的过滤和环绕参数,会导致采样失败。创建纹理后添加:
glBindTexture(GL_TEXTURE_2D, g_texture->textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GPU命令未同步
glReadPixels会等待GPU完成,但后续绘制可能未等待Skia的渲染命令执行完毕。在grDirectContext_->flush()后添加glFinish(),确保FBO渲染完成后再进行屏幕绘制。着色器纹理绑定错误
检查着色器中纹理变量的绑定:
- 激活对应纹理单元:
glActiveTexture(GL_TEXTURE0); - 在使用着色器后设置纹理单元索引:
glUniform1i(glGetUniformLocation(shader_.ID, "u_texture"), 0);
内容的提问来源于stack exchange,提问作者xiaoming wang
相关产品推荐
相关产品推荐

