Source code for ipymd.visualise.opengl.renderers.base

from OpenGL.GL import (shaders,
                       GL_VERTEX_SHADER, GL_FRAGMENT_SHADER,
                       glUseProgram, GL_FALSE, GLfloat, GL_TRUE)
from ctypes import POINTER

from ..shaders import set_uniform, compileShader
import pkgutil




[docs]class AbstractRenderer(object): '''AbstractRenderer is the standard interface for renderers. Each renderer have to implement an initialization function __init__ and a draw method to do the actual drawing using OpenGL or by using other, more basic, renderers. Usually the renderers have also some custom functions that they use to update themselves. For example a SphereRenderer implements the function update_positions to move the spheres around without having to regenerate all of the other properties. .. seealso:: :doc:`/graphics` for a tutorial on how to develop a simple renderer. **Parameters** widget: :py:class:`chemlab.graphics.QChemlabWidget` The parent `QChemlabWidget`. Renderers can use the widget to access the camera, lights, and other informations. args, kwargs: Any other argument that they may use. ''' def __init__(self, widget, *args, **kwargs): pass
[docs] def draw(self): '''Generic drawing function to be implemented by the subclasses. ''' pass
[docs]class ShaderBaseRenderer(AbstractRenderer): ''' Instruments OpenGL with a vertex and a fragment shader. This renderer automatically binds light and camera information. Subclasses should not reimplement the ``draw`` method but the ``draw_vertices`` method where you can bind and draw the objects. **Parameters** widget: The parent :py:class:`~chemlab.graphics.QChemlabWidget` vertex: str Vertex program as a string fragment: str Fragment program as a string ''' def __init__(self, widget, vertex, fragment): self.viewer = widget self.VERTEX_SHADER = vertex self.FRAGMENT_SHADER = fragment self.compile_shader()
[docs] def draw(self): self.setup_shader() self.draw_vertices() glUseProgram(0)
[docs] def draw_vertices(self): '''Method to be reimplemented by the subclasses. ''' raise NotImplementedError()
[docs] def compile_shader(self): vertex = compileShader(self.VERTEX_SHADER, GL_VERTEX_SHADER) fragment = compileShader(self.FRAGMENT_SHADER, GL_FRAGMENT_SHADER) self.shader = shaders.compileProgram(vertex, fragment)
[docs] def setup_shader(self): glUseProgram(self.shader) # Setup the uniforms set_uniform(self.shader, "mvproj", "mat4fv", self.viewer.mvproj) set_uniform(self.shader, "lightDir", "3f", self.viewer.ldir) set_uniform(self.shader, "camera", "3f", self.viewer.camera.position)
[docs]class DefaultRenderer(ShaderBaseRenderer): '''Same as :py:class:`~chemlab.graphics.renderers.ShaderBaseRenderer` with the default shaders. You can find the shaders in ``chemlab/graphics/renderers/shaders/`` under the names of ``default_persp.vert`` and ``default_persp.frag``. ''' def __init__(self, widget): vert = pkgutil.get_data("ipymd.visualise.opengl.renderers.opengl_shaders", "default_persp.vert") frag = pkgutil.get_data("ipymd.visualise.opengl.renderers.opengl_shaders", "default_light.frag") super(DefaultRenderer, self).__init__(widget, vert, frag)
[docs] def setup_shader(self): super(DefaultRenderer, self).setup_shader() set_uniform(self.shader, "viewmatrix", "mat4fv", self.viewer.camera._get_rotation_matrix().transpose())
[docs] def draw_vertices(self): '''Subclasses should reimplement this method. ''' raise NotImplementedError()