#+TITLE: Draw a textured square with kivy
#+DATE:  2014-08-05 12:00:00 UTC
#+DESCRIPTION: Kivy example drawing a square and loading an image and applying to the quad as a simple texture. 
#+FILETAGS: python:opengl:kivy:glsl
#+CATEGORY: python
#+SLUG: draw-a-textured-square-with-kivy
#+BEGIN_COMMENT
.. title: Draw a textured square with kivy
.. slug: draw-a-textured-square-with-kivy
.. date: 2014-08-05 12:00:00 UTC
.. tags: python, opengl, kivy, glsl
.. category: python
.. description: Kivy example drawing a square and loading an image and applying to the quad as a simple texture. 
.. type: text
#+END_COMMENT

#+CAPTION: Kivy textured quad
[[../../../images/kivy/quad-texture.png]]

[[http://bazaar.launchpad.net/~oly/python-examples/trunk/files/head:/python-examples/kivy/kivy-opengl-texture/][Textured quad source code]]

This example expands on the first and simply loads a texture and applys it to two triangles which make up a square.

#+BEGIN_SRC python :tangle kivy-opengl-texture.py
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.opengl import *
from kivy.graphics import *


class Renderer(Widget):
    def __init__(self, **kwargs):
        self.canvas = RenderContext(compute_normal_mat=True)
        self._tpath = resource_find('testing.png')
        self.canvas.shader.source = resource_find('shaders-opengl-texture.glsl')

        super(Renderer, self).__init__(**kwargs)
        with self.canvas:
            self.cb = Callback(self.setup_gl_context)
            PushMatrix()
            self.setup_scene()
            PopMatrix()
            self.cb = Callback(self.reset_gl_context)
        Clock.schedule_interval(self.update_glsl, 1 / 60.)

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

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

    def update_glsl(self, *largs):
        proj = Matrix().view_clip(0, self.width, 0, self.height, 1, 100, 0)
        self.canvas['projection_mat'] = proj

    def setup_scene(self):
        Color(0, 0, 0, 1)
        PushMatrix()

        indices = [0, 1, 2, 3, 0, 2]
        vertex_format = [
            ('v_pos', 3, 'float'),
            ('v_uv', 2, 'float'),
        ]

        vertices = [
          10.0 , 10.0 , 1.0, 0.0, 0.0,
          10.0 , 200.0, 1.0, 0.0, 1.0,
          200.0, 200.0, 1.0, 1.0, 1.0,
          200.0, 10.0 , 1.0, 1.0, 0.0,
        ]

        UpdateNormalMatrix()
        self.mesh = Mesh(
            vertices=vertices,
            indices=indices,
            fmt=vertex_format,
            mode='triangles',
        )
        self.mesh.texture = Image(self._tpath).texture
        PopMatrix()


class RendererApp(App):
    def build(self):
        return Renderer()

if __name__ == "__main__":
    RendererApp().run()
#+END_SRC

#+BEGIN_SRC glsl :tangle shaders-opengl-texture.glsl
---VERTEX SHADER-------------------------------------------------------
#ifdef GL_ES
    precision highp float;
#endif

attribute vec3  v_pos;
attribute vec2  v_uv;

uniform mat4 modelview_mat;
uniform mat4 projection_mat;

varying vec2 uv_vec;

void main (void) {
    vec4 pos = modelview_mat * vec4(v_pos,1.0);
    gl_Position = projection_mat * pos;
    uv_vec = v_uv;
}


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

varying vec4 frag_color;
varying vec2 uv_vec;

uniform sampler2D tex;

void main (void){
    vec4 color = texture2D(tex, uv_vec);
    gl_FragColor = color;
}
#+END_SRC

