#+TITLE: Draw a simple triangle with kivy
#+DATE: 2014-07-20 12:00:00 UTC
#+DESCRIPTION: Kivy example on setting up and displaying a basic triangle
#+FILETAGS: python:opengl:kivy
#+CATEGORY: python
#+SLUG: draw-a-shaded-triangle-with-kivy
#+BEGIN_COMMENT
.. title: Draw a simple triangle with kivy
.. slug: draw-a-shaded-triangle-with-kivy
.. date: 2014-07-20 12:00:00 UTC
.. tags: python, opengl, kivy
.. category: python
.. description: Kivy example on setting up and displaying a basic triangle
.. type: text
#+END_COMMENT

#+CAPTION: Kivy shaded triangle
[[../../../images/kivy/triangle.png]]


[[http://bazaar.launchpad.net/~oly/python-examples/trunk/files/head:/python-examples/kivy/kivy_opengl_triangle][Shaded triangle source code]]

This example will create a simple triangle and render it on screen, opengl in kivy is wrapped so you use generally use helper methods for rendering.
 
the main one is meshes for loading in your points and indices and textures to draw your model and rendercontext which activates your shaders.

#+BEGIN_SRC python :tangle kivy_opengl_triangle.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.canvas.shader.source = resource_find('shaders-opengl-triangle.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_color', 4, 'float'),
        ]
        vertices = [
          10.0 , 10.0 , 1.0, 1.0, 1.0, 0.0, 0.0,
          10.0 , 200.0, 1.0, 1.0, 0.0, 1.0, 0.0,
          200.0, 200.0, 1.0, 1.0, 0.0, 0.0, 1.0,
        ]

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


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

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

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

attribute vec3  v_pos;
attribute vec4  v_color;

uniform mat4 modelview_mat;
uniform mat4 projection_mat;

varying vec4 frag_color;

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


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

varying vec4 frag_color;
varying vec2 uv_vec;

uniform sampler2D tex;

void main (void){
    gl_FragColor = frag_color;
}
#+END_SRC 

