python - Depth buffer does not work on Android, but does work on Linux (using Kivy) -
i wrote simple example of problem.
from kivy.app import app kivy.uix.widget import widget kivy.core.window import window kivy.resources import resource_find kivy.graphics.transformation import matrix kivy.graphics import * kivy.graphics.opengl import * import random class root(widget): def __init__(self, *larg, **kw): super(root, self).__init__(*larg, **kw) self.vertices = [[-1,-1, 0, 1,-1, 0, 1, 1, 0, -1, 1, 0]] kw['shader_file'] = 'shaders.glsl' self.canvas = rendercontext(compute_normal_mat=true) shader_file = kw.pop('shader_file') self.canvas.shader.source = resource_find(shader_file) self.canvas: self.cb = callback(self.setup_gl_context) pushmatrix() translate(0, 0, -5) in xrange(10): translate(.5, 0, -.5) self.render(self.vertices, (random.random(), random.random(), random.random())) popmatrix() self.cb = callback(self.reset_gl_context) asp = float(window.width) / window.height / 2.0 proj = matrix().view_clip(-asp, asp, -0.5, 0.5, 1, 100, 1) self.canvas['projection_mat'] = proj def setup_gl_context(self, *args): glenable(gl_depth_test) def reset_gl_context(self, *args): gldisable(gl_depth_test) def render(self, vertices, color): in xrange(len(vertices)): changestate(kd=color, ka=color, ks=(.3, .3, .3), tr=1., ns=1., intensity=1.) mesh(vertices=vertices[i], indices=[0, 1, 2, 3, 0, 2], fmt=[('v_pos', 3, 'float')], mode='triangles') class testapp(app): def build(self): return root() if __name__ == '__main__': testapp().run()
note: used this shaders.glsl
.
it renders 10 squares, have same dimensions, random colors. every new square relatively translated translate(.5, 0, -.5)
, last rendered 1 furthest one. since there glenable(gl_depth_test)
, when run on linux, rendered correctly:
but after had created *.apk using buildozer (in buildzer.spec
changed title
, name
, version
, added glsl
include_exts
) , ran on android (4.4), rendered uncorrectly (like if gl_depth_test
disabled):
the problem might difference between opengl es , openggl, think, gl_depth_test
should work on both. there might problem packaging, not seem it. can me, please?
as reto koradi had suggested, looked again deeper kivy documentation. discovered framebuffer (module kivy.graphics.fbo
), offscreen window, acts kivy canvas. (probably unlike canvas) has with_depthbuffer
parameter, set false
default.
so solution set with_depthbuffer = true
in framebuffer , use framebuffer's rendered texture in canvas in order display it.
i not sure why necessary android, not linux. there might better option, not include creating (sometimes meaningless) framebuffer, method @ least works on both platforms.
i modified example code:
from kivy.app import app kivy.uix.widget import widget kivy.core.window import window kivy.resources import resource_find kivy.graphics.transformation import matrix kivy.graphics import * kivy.graphics.opengl import * import random class root(widget): def __init__(self, *larg, **kw): super(root, self).__init__(*larg, **kw) self.vertices = [[-1,-1, 0, 1,-1, 0, 1, 1, 0, -1, 1, 0]] self.canvas: self.fbo = fbo(with_depthbuffer = true, size = window.size) rectangle(size=window.size, texture=self.fbo.texture) kw['shader_file'] = 'shaders.glsl' shader_file = kw.pop('shader_file') self.fbo.shader.source = resource_find(shader_file) self.fbo: self.cb = callback(self.setup_gl_context) pushmatrix() translate(0, 0, -5) in xrange(10): translate(.5, 0, -.5) self.render(self.vertices, (random.random(), random.random(), random.random())) popmatrix() self.cb = callback(self.reset_gl_context) asp = float(window.width) / window.height / 2.0 proj = matrix().view_clip(-asp, asp, -0.5, 0.5, 1, 100, 1) self.fbo['projection_mat'] = proj def setup_gl_context(self, *args): glenable(gl_depth_test) def reset_gl_context(self, *args): gldisable(gl_depth_test) def render(self, vertices, color): in xrange(len(vertices)): changestate(kd=color, ka=color, ks=(.3, .3, .3), tr=1., ns=1., intensity=1.) mesh(vertices=vertices[i], indices=[0, 1, 2, 3, 0, 2], fmt=[('v_pos', 3, 'float')], mode='triangles') class testapp(app): def build(self): return root() if __name__ == '__main__': testapp().run()
Comments
Post a Comment