# Copyright (C) 2022 RozK # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from pathlib import Path from engine import create_shader, resolve_input, select_shader, unselect_shader, destroy_shader def _cleanup(line): return line.partition('//')[0].strip() def _filter(line): return line def _subst(line): if line.startswith('#include '): path = Path('.') / 'game' / 'shaders' lines = [] for name in line.split()[1:]: lines.extend(_load_source(path / name.strip('"'))) return lines return [line] def _load_source(path): assert path.exists() lines = filter(_filter, map(_cleanup, open(path, 'rt'))) source = [] for line in lines: source.extend(_subst(line)) return source def _convert(line): return bytes(line, 'utf-8') + b'\n' def _parse(shader, vert_lines, frag_lines): uniforms = [] for line in vert_lines: if line.startswith('uniform '): uniforms.append(line.split()[-1].strip(';')) for line in frag_lines: if line.startswith('uniform '): name = line.split()[-1].strip(';') if name not in uniforms: uniforms.append(name) for name in uniforms: setattr(shader, name, resolve_input(shader._shader, bytes(name, 'utf-8'))) class Shader: __slots__ = '_shader', '__dict__' def __init__(self, vert_name, frag_name = ''): path = Path('.') / 'game' / 'shaders' assert path.exists() if not frag_name: frag_name = vert_name print("Loading vertex shader", vert_name) vert_lines = _load_source(path / (vert_name + '_opengles.vert')) assert vert_lines print("Loading fragment shader", frag_name) frag_lines = _load_source(path / (frag_name + '_opengles.frag')) assert frag_lines self._shader = create_shader(list(map(_convert, vert_lines)), list(map(_convert, frag_lines))) _parse(self, vert_lines, frag_lines) def __del__(self): destroy_shader(self._shader) def select(self): select_shader(self._shader) def unselect(self): unselect_shader(self._shader)