#! /usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from OpenGL.GL import *
import OpenGL.GLUT as glut
from PIL import Image
vertex_code = """
uniform mat4 u_projection_mat;
attribute vec3 position;
varying vec4 v_color;
void main()
{
gl_Position = u_projection_mat*vec4(position, 1.0);
v_color = (vec4(position, 1.0)+1)/2.0;
} """
fragment_code = """
varying vec4 v_color;
void main()
{
gl_FragColor = v_color;
} """
# GLUT init
# --------------------------------------
glut.glutInit()
glut.glutInitDisplayMode(glut.GLUT_DOUBLE | glut.GLUT_RGBA)
glut.glutCreateWindow('Hello world!')
data = np.array([ (-0.5,-0.5,0.5),
(0.5,-0.5,0.5),
(0.5,0.5,0.5),
(-0.5,0.5,0.5)], dtype=np.float32)
index = np.array([0,1,2, 2,3,0],dtype=np.uint32)
###################
# shader construction
program = glCreateProgram()
vertex = glCreateShader(GL_VERTEX_SHADER)
fragment = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(vertex, vertex_code)
glShaderSource(fragment, fragment_code)
glCompileShader(vertex)
glCompileShader(fragment)
glAttachShader(program, vertex)
glAttachShader(program, fragment)
glLinkProgram(program)
glDetachShader(program, vertex)
glDetachShader(program, fragment)
glUseProgram(program)
###################
# VBO construction
vbo = glGenBuffers(1) # (vbo,)=glGenBuffers(1) in kivy
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, data.nbytes, data, GL_DYNAMIC_DRAW) # not working on kivy: expected sr, got numpy array
ibo= glGenBuffers(1) # (ibo,)=glGenBuffers(1) in kivy
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index, GL_STATIC_DRAW) # not working on kivy
loc = glGetAttribLocation(program, "position")
glEnableVertexAttribArray(loc)
glBindBuffer(GL_ARRAY_BUFFER, vbo)
glVertexAttribPointer(loc, 3, GL_FLOAT, False, data.strides[0], ctypes.c_void_p(0)) #not working on kivy
loc = glGetUniformLocation(program, "u_projection_mat")
glUniformMatrix4fv(loc, 1, False, np.eye(4))
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo)
###################
#FBO initialisation
(w,h)=(512,512)
glEnable(GL_TEXTURE_2D)
fbo=glGenFramebuffers(1)
tex=glGenTextures(1)
glBindFramebuffer(GL_FRAMEBUFFER, fbo)
glBindTexture(GL_TEXTURE_2D, tex)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,None) # not working on ikvy str(0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,tex,0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
#####################
# Render to FBO
glBindFramebuffer(GL_FRAMEBUFFER, fbo)
glViewport(0,0,w,h)
glClear(GL_COLOR_BUFFER_BIT)
glDrawElements(GL_TRIANGLES, len(index), GL_UNSIGNED_INT, ctypes.c_void_p(0))
image = Image.frombytes('RGBA', (w,h), glReadPixels(0,0,w,h, GL_RGBA, GL_UNSIGNED_BYTE))
image.show()
glBindFramebuffer(GL_FRAMEBUFFER, 0)
#####################
#End of FBO renderingConcernant pyOpenGL, does it mean that I'll have to write a recipe?
__version__ = '1.0'
import kivy
from kivy.app import App
from kivy.clock import Clock
from kivy.core.window import Window
from kivy.core.image import Image
from kivy.uix.widget import Widget
from kivy.resources import resource_find
from kivy.graphics.transformation import Matrix
from kivy.graphics import *
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics.opengl import *
import numpy as np
vertex_code = """
uniform mat4 u_projection_mat;
attribute vec3 a_position;
varying vec4 v_color;
void main()
{
gl_Position = u_projection_mat*vec4(a_position, 1.0);
v_color = (vec4(a_position, 1.0)+1.0)/2.0;
} """
fragment_code = """
varying vec4 v_color;
void main()
{
gl_FragColor = v_color;
} """
data = np.array([ -0.5,-0.5,0.5,
0.5,-0.5,0.5,
0.5,0.5,0.5,
-0.5,0.5,0.5], dtype=np.float32)
index = np.array([0,1,2, 2,3,0],dtype=np.uint32)
class OpenglWidget(Widget):
def __init__(self, **kwargs):
super(OpenglWidget, self).__init__(**kwargs)
self.angle=0
self.setup_kvfbo()
self.setup_glfbo()
Clock.schedule_interval(self.update_glsl,1/60.0)
def update_glsl(self, *largs):
self.angle+=0.01
if 0:
self.draw_fbo(self.kvfboid)
else:
self.draw_fbo(self.glfboid)
self.blit_fbo()
self.canvas.ask_update()
def setup_kvfbo(self):
self.kvfbo= Fbo(with_depthbuffer = True, size = Window.size, compute_normal_mat=True)
self.canvas.add(self.kvfbo)
self.canvas.add(Rectangle(size=Window.size, texture=self.kvfbo.texture))
self.kvfbo.bind() # bind the FBO in order
(self.kvfboid,)=glGetIntegerv(GL_FRAMEBUFFER_BINDING) # retrieve FBO id
#(self.kvfbotexid,)=glGetIntegerv(GL_TEXTURE_BINDING_2D) # retrieve texture id
# How to retrieve depth buffer and stencil buffer when available?
self.kvfbo.release()
def setup_glfbo(self):
## shader construction
self.program = glCreateProgram()
vertex = glCreateShader(GL_VERTEX_SHADER)
fragment = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(vertex, vertex_code)
glShaderSource(fragment, fragment_code)
glCompileShader(vertex)
glCompileShader(fragment)
glAttachShader(self.program, vertex)
glAttachShader(self.program, fragment)
glLinkProgram(self.program)
glDetachShader(self.program, vertex)
glDetachShader(self.program, fragment)
glUseProgram(self.program)
## FBO initialisation
self.w,self.h=Window.width,Window.height
glEnable(GL_TEXTURE_2D)
(self.glfboid,)=glGenFramebuffers(1)
(self.gltexid,)=glGenTextures(1)
glBindFramebuffer(GL_FRAMEBUFFER, self.glfboid)
glBindTexture(GL_TEXTURE_2D, self.gltexid)
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,self.w,self.h,0,GL_RGBA,GL_UNSIGNED_BYTE,(np.ones(self.w*self.h*4, np.uint8)*128).tobytes())
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,self.gltexid,0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glBindTexture(GL_TEXTURE_2D, 0)
## VBO construction
(self.vbo,) = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBufferData(GL_ARRAY_BUFFER, data.nbytes, data.tobytes(), GL_DYNAMIC_DRAW)
(self.ibo,)= glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ibo)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index.nbytes, index.tobytes(), GL_STATIC_DRAW)
def blit_fbo(self):
''' assumes both buffer are the same size
unfortunately, glBlitFramebuffer is not available in GLES 2.0
so we copy pixels from glfbo to memory, then blit back these pixels from memory to GPU
would be faster to draw square to kvfboid with self.gltexid as texture
'''
glBindFramebuffer(GL_FRAMEBUFFER,self.glfboid)
pixels=glReadPixels(0,0,self.w,self.h, GL_RGBA, GL_UNSIGNED_BYTE)
glBindFramebuffer(GL_FRAMEBUFFER,self.kvfboid)
#glBindTexture(GL_TEXTURE_2D,self.kvfbotexid)
glTexSubImage2D(GL_TEXTURE_2D, 0 ,0, 0, self.w, self.h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glBindFramebuffer(GL_FRAMEBUFFER,0)
def draw_fbo(self,targetfbo):
eye=np.matrix([[np.cos(self.angle),-np.sin(self.angle),0,0],
[np.sin(self.angle),np.cos(self.angle),0,0],
[0,0,1,0],
[0,0,0,1]],dtype=np.float32)
glBindFramebuffer(GL_FRAMEBUFFER,targetfbo)
glClear(GL_COLOR_BUFFER_BIT)
glBindBuffer(GL_ARRAY_BUFFER, self.vbo)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ibo)
glUseProgram(self.program)
u_loc = glGetUniformLocation(self.program, "u_projection_mat")
glUniformMatrix4fv(u_loc, 1, False, np.array(eye).flatten().tobytes() )
a_loc = glGetAttribLocation(self.program, "a_position")
glEnableVertexAttribArray(a_loc)
glVertexAttribPointer(a_loc, 3, GL_FLOAT, False, 12, 0)
glViewport(0,0,self.w,self.h)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
class MainApp(App):
def build(self):
return OpenglWidget();
if __name__=='__main__':
MainApp().run()