3d Kivy FBO访问Z缓冲区

3d Kivy FBO访问Z缓冲区,3d,glsl,kivy,buffer,lighting,3d,Glsl,Kivy,Buffer,Lighting,在kivy中创建fbo时,它接受“with_depthbuffer”作为参数。在文档中,它说这将导致fbo分配z缓冲区。我想尝试使用这个灯光效果 我的问题是,在哪里可以找到并使用缓冲区? 我可以选择清除它,但是查看源代码并没有帮助。 我注意到fbo.texture有一个bufferfmt属性。深度缓冲区是否存储在图像纹理中?我可以在glsl中访问它以获得像素的深度吗 提前谢谢 编辑: 我找到了一种保存深度信息的“黑客”方法,将gl_FragColor指定给vec4(lambert_值,-1.0/

在kivy中创建fbo时,它接受“with_depthbuffer”作为参数。在文档中,它说这将导致fbo分配z缓冲区。我想尝试使用这个灯光效果

我的问题是,在哪里可以找到并使用缓冲区? 我可以选择清除它,但是查看源代码并没有帮助。 我注意到fbo.texture有一个bufferfmt属性。深度缓冲区是否存储在图像纹理中?我可以在glsl中访问它以获得像素的深度吗

提前谢谢

编辑:

我找到了一种保存深度信息的“黑客”方法,将gl_FragColor指定给vec4(lambert_值,-1.0/vertex_pos.z,1.0,1.0),并在后处理中使用这些值。但显然我不能在实际应用中使用它

编辑:

好吧,我想我提出的临时方法似乎相当准确

我访问了这个页面: 在第230行,如果_depthbuffer==True,则绑定渲染缓冲区

我查看了渲染缓冲区是什么,显然它们只能在当前着色器过程中使用。这意味着我从fbo那里得到信息的目标行不通

然后我意识到我永远不需要从相机的角度获得深度信息,只需要光线。所以我只是使用灯光的着色器生成深度信息。我觉得自己很愚蠢。但事情就是这样发展的。我想我能弄明白。我会不断更新这个页面,这样会有更多的信息。谢谢你的阅读

如果要测试它,只需单击/拖动以更改灯光位置。 还有一些注释行使用我的临时方法来保存深度信息,这样你就可以看到我想要的东西。 你还需要某种类型的对象文件,我使用了blender monkey

main.py

post_shader = '''
#ifdef GL_ES
precision highp float;
#endif

/* Outputs from the vertex shader */
varying vec4 frag_color;
varying vec2 tex_coord0;

/* uniform texture samplers */
uniform sampler2D texture0;

uniform vec2 mouse_pos;

void main(void)
{
    float distance = length(gl_FragCoord.xy - mouse_pos) * .02;
    vec4 pixel = texture2D(texture0, tex_coord0);
    vec3 color = pixel.rgb / distance;
    gl_FragColor = vec4(color, 1.0);

    // uncomment for desired results
    // float brightness = clamp(pixel.r / distance, .1, .8) * pixel.g;
    // gl_FragColor = vec4(brightness, brightness, brightness, 1.0);
}
'''


from kivy.app import App
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.resources import resource_find
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics.opengl import *
from kivy.graphics import *
from objloader import ObjFile


class Renderer(Widget):
    def __init__(self, **kwargs):
        self.canvas = RenderContext(use_parent_projection=True)
        # self.canvas.shader.fs = resource_find('post_shader.glsl')
        self.canvas.shader.fs = post_shader

        scene = ObjFile(resource_find("Models/monkey.obj"))
        m = list(scene.objects.values())[0]

        self.z_pos = 0
        self.d = 1

        super(Renderer, self).__init__(**kwargs)

        with self.canvas:
            self.fbo = Fbo(compute_normal_matrix=True,
                           with_depthbuffer=True)
            self.fbo.shader.source = resource_find('simple.glsl')
            self.display = Rectangle()

        with self.fbo:
            self.cb = Callback(self.setup_gl_context)
            ClearColor(1, 0, 0, 0)
            ClearBuffers(clear_depth=True)

            PushMatrix()
            self.translation = Translate(0, 0, -3)
            self.rot = Rotate(1, 0, 1, 0)

            UpdateNormalMatrix()
            Color(rgb=(0, 0, 0))
            self.mesh = Mesh(vertices=m.vertices,
                             indices=m.indices,
                             fmt=m.vertex_format,
                             mode='triangles')

            PopMatrix()
            self.cb = Callback(self.reset_gl_context)

        self.display.texture = self.fbo.texture

        Clock.schedule_interval(self.update, 1 / 60.)

    def setup_gl_context(self, *args):
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)

    def reset_gl_context(self, *args):
        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)

    def on_touch_move(self, touch):
        self.canvas['mouse_pos'] = touch.pos

    def update(self, dt):
        self.z_pos += self.d * dt
        if self.d > 0:
            if self.z_pos > -2:
                self.d *= -1
        elif self.z_pos < -15:
            self.d *= -1
        self.translation.z = self.z_pos
        self.rot.angle += dt * 10

    def on_size(self, *args):
        self.display.size = self.size
        self.fbo['projection_mat'].perspective(90, self.width / float(self.height), .1, 25)


class RendererApp(App):
    def build(self):
        root = FloatLayout()
        root.add_widget(Renderer())

        return root


if __name__ == "__main__":
    RendererApp().run()

我还尝试从fbo获取深度贴图以制作阴影贴图,但没有获取深度贴图的函数。我认为我们可以编辑源代码并创建一个从fbo获取深度贴图的函数…我编辑了源代码,但kivy源文件已编译,所以我们也需要编译它…我还在kivy中制作游戏引擎,其中包含对象加载、纹理加载、着色器,动画实时,法线贴图,碰撞系统(从头开始)和多重灯光系统也。。。这里是链接:……我认为我们可以让kivy做得更好,这将有助于许多愿意使用python开发游戏并希望导出到移动平台的python开发人员

/* simple.glsl

simple diffuse lighting based on laberts cosine law; see e.g.:
    http://en.wikipedia.org/wiki/Lambertian_reflectance
    http://en.wikipedia.org/wiki/Lambert%27s_cosine_law
*/

---VERTEX SHADER-------------------------------------------------------
#ifdef GL_ES
    precision highp float;
#endif

attribute vec3  v_pos;
attribute vec3  v_normal;

uniform mat4 modelview_mat;
uniform mat4 projection_mat;

varying vec4 normal_vec;
varying vec4 vertex_pos;

void main (void) {
    //compute vertex position in eye_space and normalize normal vector
    vec4 pos = modelview_mat * vec4(v_pos,1.0);
    vertex_pos = pos;
    normal_vec = vec4(v_normal, 0.0);
    gl_Position = projection_mat * pos;
}


---FRAGMENT SHADER-----------------------------------------------------
#ifdef GL_ES
    precision highp float;
#endif

varying vec4 normal_vec;
varying vec4 vertex_pos;

uniform mat4 normal_mat;

void main (void){
    //correct normal, and compute light vector (assume light at the eye)
    vec4 v_normal = normalize( normal_mat * normal_vec ) ;
    vec4 v_light = normalize( vec4(0,0,0,1) - vertex_pos );
    //reflectance based on lamberts law of cosine
    float theta = clamp(dot(v_normal, v_light), 0.0, 1.0);

    gl_FragColor = vec4(theta, theta, theta, 1.0);

//    uncomment for desired results
//    gl_FragColor = vec4(theta, -3.0 / vertex_pos.z, 1.0, 1.0);
}