Kivy FBO доступ к Z-буферу

При создании fbo в kivy он принимает аргумент with_depthbuffer. В документации сказано, что это приведет к тому, что fbo будет выделен z-буфером. Я хотел бы попробовать использовать это для световых эффектов.

У меня вопрос, где я могу найти и использовать этот буфер? У меня есть возможность очистить его, но поиск в исходном коде бесполезен. Я заметил, что у fbo.texture есть атрибут bufferfmt. Сохранен ли буфер глубины в текстуре изображения? Могу ли я получить доступ к этому в glsl, чтобы получить глубину пикселя?

заранее спасибо

Обновлено:

Я нашел своего рода «хакерский» способ сохранения информации о глубине, присвоив gl_FragColor значению vec4 (lambert_value, -1.0 / vertex_pos.z, 1.0, 1.0) и используя эти значения при постобработке. Но, очевидно, я не могу использовать это в реальном приложении.

Обновлено:

Хорошо, я думаю, временный способ, который я придумал, кажется довольно точным для того, как это делается.

Я посетил эту страницу: https://github.com/kivy/kivy/blob/master/kivy/graphics/fbo.pyx а в строке 230 связывается буфер рендеринга, если with_depthbuffer == True.

Я посмотрел, что такое буфер рендеринга, и, по-видимому, их нельзя использовать иначе, как в текущем проходе шейдера. Это означает, что моя цель получить эту информацию из fbo не сработала.

Тогда я понял, что мне никогда не понадобится информация о глубине с точки зрения камеры, только свет. Поэтому я просто генерирую информацию о глубине, используя шейдер света. Я чувствую себя глупо. Но вот как все это происходит. Думаю, я смогу это понять. Я буду продолжать обновлять эту страницу, чтобы было немного больше информации. Спасибо за прочтение

Если вы хотите проверить это, просто щелкните / перетащите, чтобы изменить положение источника света. Есть также закомментированные строки, которые используют мой временный подход к сохранению информации о глубине, чтобы вы могли видеть, что я собираюсь сделать. Вам также понадобится какой-то объектный файл, я использовал обезьяну блендера.

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()

simple.glsl

/* 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);
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
220
1

Ответы 1

Я также пытался получить карту глубины из fbo, чтобы сделать отображение теней, но нет функции для получения карты глубины. Я думаю, что мы можем редактировать источник и создать функцию для получения карты глубины из fbo .... Я редактировал исходный код, но исходные файлы kivy скомпилированы так что нам тоже нужно его скомпилировать .... я также делаю игровой движок в kivy, который имеет загрузку объектов, загрузку текстур, шейдеры, анимацию в реальном времени, отображение нормалей, систему столкновений (с нуля) и систему множественного освещения ... вот ссылка: https://thewikihow.com/video_K5gTYC7sLVc .... Я думаю, что мы можем сделать kivy намного лучше, и это будет полезно для многих разработчиков python, которые хотят разрабатывать игры с python и хотят также экспортировать на мобильную платформу ..

Другие вопросы по теме