summaryrefslogtreecommitdiff
path: root/txtgameengine/shaders
diff options
context:
space:
mode:
Diffstat (limited to 'txtgameengine/shaders')
-rw-r--r--txtgameengine/shaders/__init__.py2
-rw-r--r--txtgameengine/shaders/integrated.py16
-rw-r--r--txtgameengine/shaders/shader.py50
3 files changed, 68 insertions, 0 deletions
diff --git a/txtgameengine/shaders/__init__.py b/txtgameengine/shaders/__init__.py
new file mode 100644
index 0000000..64b0cc8
--- /dev/null
+++ b/txtgameengine/shaders/__init__.py
@@ -0,0 +1,2 @@
+from .shader import Shader
+from .integrated import TextureShader, BasicShader
diff --git a/txtgameengine/shaders/integrated.py b/txtgameengine/shaders/integrated.py
new file mode 100644
index 0000000..dfa1033
--- /dev/null
+++ b/txtgameengine/shaders/integrated.py
@@ -0,0 +1,16 @@
+from .shader import Shader
+from ..app import base_path
+
+shader_base_path = base_path / 'builtin_shaders'
+
+
+class BasicShader(Shader):
+ UNIFORMS = dict()
+ VERTEX_PATH = shader_base_path / 'basic/vertex.glsl'
+ FRAGMENT_PATH = shader_base_path / 'basic/fragment.glsl'
+
+
+class TextureShader(Shader):
+ UNIFORMS = dict(textureSampler="textureSampler")
+ VERTEX_PATH = shader_base_path / 'texture/vertex.glsl'
+ FRAGMENT_PATH = shader_base_path / 'texture/fragment.glsl'
diff --git a/txtgameengine/shaders/shader.py b/txtgameengine/shaders/shader.py
new file mode 100644
index 0000000..61b6aaf
--- /dev/null
+++ b/txtgameengine/shaders/shader.py
@@ -0,0 +1,50 @@
+import typing
+
+if typing.TYPE_CHECKING:
+ from ..app import TxtGameApp
+
+
+class Shader:
+ """Wrapper class for a GL program"""
+
+ UNIFORMS: typing.Dict[str, str] = dict()
+ VERTEX_PATH: str
+ FRAGMENT_PATH: str
+
+ def __init__(self, app: 'TxtGameApp'):
+ self.app = app
+ self._prog_id = self.app.shaders.load_shaders(self.VERTEX_PATH, self.FRAGMENT_PATH)
+ self._is_bound = 0
+ self.uniform_locations = {}
+ self._fill_uniforms()
+
+ def _fill_uniforms(self):
+ with self:
+ for prop_name, shader_name in self.UNIFORMS.items():
+ self.uniform_locations[prop_name] = \
+ self.app.shaders.get_uniform_location(self._prog_id, shader_name)
+
+ def __getattr__(self, item):
+ if item in self.uniform_locations:
+ return self.uniform_locations[item]
+ raise AttributeError("Shader '%s' has no attribute or uniform named %s" % (type(self).__name__, item))
+
+ def _require_bound(self, required=False):
+ assert self._is_bound > 0 or not required
+ return self
+
+ def get_uniform_location(self, name: str):
+ return self.uniform_locations[name]
+
+ def __enter__(self):
+ self._is_bound += 1
+ if self._is_bound == 1:
+ self.app.shaders.bind_shader(self._prog_id)
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self._is_bound -= 1
+ if self._is_bound == 0:
+ self.app.shaders.bind_shader(0)
+
+ def __repr__(self):
+ return '<Shader prog_id=%d uniforms=%r>' % (self._prog_id, self.uniform_locations)