При создании 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);
}





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