summaryrefslogtreecommitdiff
path: root/silx/gui/plot3d/scene/viewport.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot3d/scene/viewport.py')
-rw-r--r--silx/gui/plot3d/scene/viewport.py75
1 files changed, 69 insertions, 6 deletions
diff --git a/silx/gui/plot3d/scene/viewport.py b/silx/gui/plot3d/scene/viewport.py
index 41aa999..6de640e 100644
--- a/silx/gui/plot3d/scene/viewport.py
+++ b/silx/gui/plot3d/scene/viewport.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2015-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2015-2019 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -36,6 +36,7 @@ __license__ = "MIT"
__date__ = "24/04/2018"
+import string
import numpy
from silx.gui.colors import rgba
@@ -45,7 +46,7 @@ from ..._glutils import gl
from . import camera
from . import event
from . import transform
-from .function import DirectionalLight, ClippingPlane
+from .function import DirectionalLight, ClippingPlane, Fog
class RenderContext(object):
@@ -61,12 +62,33 @@ class RenderContext(object):
:param Context glContext: The operating system OpenGL context in use.
"""
+ _FRAGMENT_SHADER_SRC = string.Template("""
+ void scene_post(vec4 cameraPosition) {
+ gl_FragColor = $fogCall(gl_FragColor, cameraPosition);
+ }
+ """)
+
def __init__(self, viewport, glContext):
self._viewport = viewport
self._glContext = glContext
self._transformStack = [viewport.camera.extrinsic]
self._clipPlane = ClippingPlane(normal=(0., 0., 0.))
+ # cache
+ self.__cache = {}
+
+ def cache(self, key, factory, *args, **kwargs):
+ """Lazy-loading cache to store values in the context for rendering
+
+ :param key: The key to retrieve
+ :param factory: A callback taking args and kwargs as arguments
+ and returning the value to store.
+ :return: The stored or newly allocated value
+ """
+ if key not in self.__cache:
+ self.__cache[key] = factory(*args, **kwargs)
+ return self.__cache[key]
+
@property
def viewport(self):
"""Viewport doing the current rendering"""
@@ -127,8 +149,7 @@ class RenderContext(object):
@property
def clipper(self):
- """The current clipping plane
- """
+ """The current clipping plane (ClippingPlane)"""
return self._clipPlane
def setClipPlane(self, point=(0., 0., 0.), normal=(0., 0., 0.)):
@@ -143,6 +164,40 @@ class RenderContext(object):
"""
self._clipPlane = ClippingPlane(point, normal)
+ def setupProgram(self, program):
+ """Sets-up uniforms of a program using the context shader functions.
+
+ :param GLProgram program: The program to set-up.
+ It MUST be in use and using the context function.
+ """
+ self.clipper.setupProgram(self, program)
+ self.viewport.fog.setupProgram(self, program)
+
+ @property
+ def fragDecl(self):
+ """Fragment shader declaration for scene shader functions"""
+ return '\n'.join((
+ self.clipper.fragDecl,
+ self.viewport.fog.fragDecl,
+ self._FRAGMENT_SHADER_SRC.substitute(
+ fogCall=self.viewport.fog.fragCall)))
+
+ @property
+ def fragCallPre(self):
+ """Fragment shader call for scene shader functions (to do first)
+
+ It takes the camera position (vec4) as argument.
+ """
+ return self.clipper.fragCall
+
+ @property
+ def fragCallPost(self):
+ """Fragment shader call for scene shader functions (to do last)
+
+ It takes the camera position (vec4) as argument.
+ """
+ return "scene_post"
+
class Viewport(event.Notifier):
"""Rendering a single scene through a camera in part of a framebuffer.
@@ -170,6 +225,9 @@ class Viewport(event.Notifier):
ambient=(0.3, 0.3, 0.3),
diffuse=(0.7, 0.7, 0.7))
self._light.addListener(self._changed)
+ self._fog = Fog()
+ self._fog.isOn = False
+ self._fog.addListener(self._changed)
@property
def transforms(self):
@@ -224,6 +282,11 @@ class Viewport(event.Notifier):
return self._light
@property
+ def fog(self):
+ """The fog function used to render the scene"""
+ return self._fog
+
+ @property
def origin(self):
"""Origin (ox, oy) of the viewport in pixels"""
return self._origin
@@ -351,8 +414,8 @@ class Viewport(event.Notifier):
"""
bounds = self.scene.bounds(transformed=True)
if bounds is None:
- bounds = numpy.array(((0., 0., 0.), (1., 1., 1.)),
- dtype=numpy.float32)
+ bounds = numpy.array(((0., 0., 0.), (1., 1., 1.)),
+ dtype=numpy.float32)
self.camera.resetCamera(bounds)
def orbitCamera(self, direction, angle=1.):