Renderer and Python ctypes bindings.
This commit is contained in:
		
							
								
								
									
										6
									
								
								DEPENDENCIES
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								DEPENDENCIES
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					C/C++ libraries (dev versions):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- X11
 | 
				
			||||||
 | 
					- GLX
 | 
				
			||||||
 | 
					- GLESv2
 | 
				
			||||||
 | 
					- GLM
 | 
				
			||||||
							
								
								
									
										16
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					SOURCES = cpp/opengl/render_context_glx.cpp cpp/opengl/render_opengles.cpp cpp/math.cpp cpp/render.cpp
 | 
				
			||||||
 | 
					OUTPUTFILE = engine.so
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CXXFLAGS = -fpic -std=c++20 -Wall -Werror -O2 -flto -fomit-frame-pointer -ffast-math -funroll-loops -fno-rtti -fno-exceptions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: all
 | 
				
			||||||
 | 
					all: clean $(OUTPUTFILE)
 | 
				
			||||||
 | 
						find . -name "*.o" -type f -delete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: clean
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						rm -f $(OUTPUTFILE)
 | 
				
			||||||
 | 
						find . -name "*.o" -type f -delete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
 | 
				
			||||||
 | 
						$(CXX) -shared $(CXXFLAGS) -s -o $@ $^ -lGLESv2 -lGLX -lX11
 | 
				
			||||||
							
								
								
									
										350
									
								
								__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								__init__.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,350 @@
 | 
				
			|||||||
 | 
					# 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ctypes
 | 
				
			||||||
 | 
					import struct
 | 
				
			||||||
 | 
					from array import array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_lib = ctypes.cdll.LoadLibrary("./engine/engine.so")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _flag(x):
 | 
				
			||||||
 | 
					    return 1 << x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INPUT_IDENTITY = 0
 | 
				
			||||||
 | 
					INPUT_VIEW_POSITION = 1
 | 
				
			||||||
 | 
					INPUT_VIEW_ORIENTATION = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_SRGB8_A8 = 0
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_RGBA8 = 1
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_RGB10_A2 = 2
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_32F = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_TYPECODE = ('B', 'B', 'I', 'f')
 | 
				
			||||||
 | 
					TEXTURE_FORMAT_NELEMS = (4, 4, 1, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEXTURE_FLAG_3D = _flag(0)
 | 
				
			||||||
 | 
					TEXTURE_FLAG_MIPMAPS = _flag(1)
 | 
				
			||||||
 | 
					TEXTURE_FLAG_MIN_NEAREST = 0
 | 
				
			||||||
 | 
					TEXTURE_FLAG_MIN_LINEAR = _flag(2)
 | 
				
			||||||
 | 
					TEXTURE_FLAG_MAG_NEAREST = 0
 | 
				
			||||||
 | 
					TEXTURE_FLAG_MAG_LINEAR = _flag(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VERTEX_FORMAT_VEC2_FLOAT = 1
 | 
				
			||||||
 | 
					VERTEX_FORMAT_VEC2_USHORT = 2
 | 
				
			||||||
 | 
					VERTEX_FORMAT_VEC3_FLOAT = 3
 | 
				
			||||||
 | 
					VERTEX_FORMAT_VEC3_INT10 = 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def vertex_format(*format):
 | 
				
			||||||
 | 
					    return array('B', format).tobytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSTANCE_FLAG_SPAWNED = _flag(0)
 | 
				
			||||||
 | 
					INSTANCE_FLAG_VISIBLE = _flag(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BATCH_MAX_SIZE = 65536
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BATCH_TRANSLATION_FORMAT_FLOAT = 0
 | 
				
			||||||
 | 
					BATCH_TRANSLATION_FORMAT_SHORT = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BATCH_ORIENTATION_FORMAT_NONE = 0
 | 
				
			||||||
 | 
					BATCH_ORIENTATION_FORMAT_FLOAT = 1
 | 
				
			||||||
 | 
					BATCH_ORIENTATION_FORMAT_INT10 = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#TODO: remove from engine
 | 
				
			||||||
 | 
					vec2_zero = (0.0, 0.0)
 | 
				
			||||||
 | 
					vec3_zero = (0.0, 0.0, 0.0)
 | 
				
			||||||
 | 
					vec3_right = (1.0, 0.0, 0.0)
 | 
				
			||||||
 | 
					vec3_forward = (0.0, 1.0, 0.0)
 | 
				
			||||||
 | 
					vec3_up = (0.0, 0.0, 1.0)
 | 
				
			||||||
 | 
					vec4_zero = (0.0, 0.0, 0.0, 1.0)
 | 
				
			||||||
 | 
					mat3_identity = (
 | 
				
			||||||
 | 
					    1.0, 0.0, 0.0,
 | 
				
			||||||
 | 
					    0.0, 1.0, 0.0,
 | 
				
			||||||
 | 
					    0.0, 0.0, 1.0)
 | 
				
			||||||
 | 
					mat4_identity = (
 | 
				
			||||||
 | 
					    1.0, 0.0, 0.0, 0.0,
 | 
				
			||||||
 | 
					    0.0, 1.0, 0.0, 1.0,
 | 
				
			||||||
 | 
					    0.0, 0.0, 1.0, 0.0,
 | 
				
			||||||
 | 
					    0.0, 0.0, 0.0, 1.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def vec2(v = vec2_zero):
 | 
				
			||||||
 | 
					    assert len(v) == 2
 | 
				
			||||||
 | 
					    return array('f', v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def vec3(v = vec3_zero):
 | 
				
			||||||
 | 
					    assert len(v) == 3
 | 
				
			||||||
 | 
					    return array('f', v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def vec4(v = vec4_zero):
 | 
				
			||||||
 | 
					    assert len(v) == 4
 | 
				
			||||||
 | 
					    return array('f', v)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat3(m = mat3_identity):
 | 
				
			||||||
 | 
					    assert len(m) == 9
 | 
				
			||||||
 | 
					    return array('f', m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat4(m = mat4_identity):
 | 
				
			||||||
 | 
					    assert len(m) == 16
 | 
				
			||||||
 | 
					    return array('f', m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_vec2_t = (ctypes.c_float * 2)
 | 
				
			||||||
 | 
					_vec2 = _vec2_t.from_buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_vec3_t = (ctypes.c_float * 3)
 | 
				
			||||||
 | 
					_vec3 = _vec3_t.from_buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_vec4_t = (ctypes.c_float * 4)
 | 
				
			||||||
 | 
					_vec4 = _vec4_t.from_buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat3_t = (ctypes.c_float * 9)
 | 
				
			||||||
 | 
					_mat3 = _mat3_t.from_buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat4_t = (ctypes.c_float * 16)
 | 
				
			||||||
 | 
					_mat4 = _mat4_t.from_buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _voidp(x):
 | 
				
			||||||
 | 
					    return x.buffer_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _ubytep(x):
 | 
				
			||||||
 | 
					    assert x.typecode == 'B'
 | 
				
			||||||
 | 
					    return x.buffer_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _ushortp(x):
 | 
				
			||||||
 | 
					    assert x.typecode == 'H'
 | 
				
			||||||
 | 
					    return x.buffer_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _uintp(x):
 | 
				
			||||||
 | 
					    assert x.typecode == 'I'
 | 
				
			||||||
 | 
					    return x.buffer_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def _floatp(x):
 | 
				
			||||||
 | 
					    assert x.typecode == 'f'
 | 
				
			||||||
 | 
					    return x.buffer_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat3_rotation = _lib.rk_mat3_rotation
 | 
				
			||||||
 | 
					_mat3_rotation.argtypes = (
 | 
				
			||||||
 | 
					    _mat3_t, # ret
 | 
				
			||||||
 | 
					    _vec3_t, # axis
 | 
				
			||||||
 | 
					    ctypes.c_float) # angle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat3_rotation(ret, axis, angle):
 | 
				
			||||||
 | 
					    assert len(ret) == 9 and len(axis) == 3
 | 
				
			||||||
 | 
					    _mat3_rotation(_mat3(ret), _vec3(axis), angle)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat3_mul_vec3 = _lib.rk_mat3_mul_vec3
 | 
				
			||||||
 | 
					_mat3_mul_vec3.argtypes = (
 | 
				
			||||||
 | 
					    _vec3_t, # ret
 | 
				
			||||||
 | 
					    _mat3_t, # a
 | 
				
			||||||
 | 
					    _vec3_t) # b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat3_mul_vec3(ret, a, b):
 | 
				
			||||||
 | 
					    assert len(ret) == 3 and len(a) == 9 and len(b) == 3
 | 
				
			||||||
 | 
					    _mat3_mul_vec3(_vec3(ret), _mat3(a), _vec3(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat3_mul_mat3 = _lib.rk_mat3_mul_mat3
 | 
				
			||||||
 | 
					_mat3_mul_mat3.argtypes = (
 | 
				
			||||||
 | 
					    _mat3_t, # ret
 | 
				
			||||||
 | 
					    _mat3_t, # a
 | 
				
			||||||
 | 
					    _mat3_t) # b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat3_mul_mat3(ret, a, b):
 | 
				
			||||||
 | 
					    assert len(ret) == 9 and len(a) == 9 and len(b) == 9
 | 
				
			||||||
 | 
					    _mat3_mul_mat3(_mat3(ret), _mat3(a), _mat3(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat4_mul_vec4 = _lib.rk_mat4_mul_vec4
 | 
				
			||||||
 | 
					_mat4_mul_vec4.argtypes = (
 | 
				
			||||||
 | 
					    _vec4_t, # ret
 | 
				
			||||||
 | 
					    _mat4_t, # a
 | 
				
			||||||
 | 
					    _vec4_t) # b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat4_mul_vec4(ret, a, b):
 | 
				
			||||||
 | 
					    assert len(ret) == 4 and len(a) == 16 and len(b) == 4
 | 
				
			||||||
 | 
					    _mat4_mul_vec4(_vec4(ret), _mat4(a), _vec4(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_mat4_mul_mat4 = _lib.rk_mat4_mul_mat4
 | 
				
			||||||
 | 
					_mat4_mul_mat4.argtypes = (
 | 
				
			||||||
 | 
					    _mat4_t, # ret
 | 
				
			||||||
 | 
					    _mat4_t, # a
 | 
				
			||||||
 | 
					    _mat4_t) # b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def mat4_mul_mat4(ret, a, b):
 | 
				
			||||||
 | 
					    assert len(ret) == 16 and len(a) == 16 and len(b) == 16
 | 
				
			||||||
 | 
					    _mat4_mul_mat4(_mat4(ret), _mat4(a), _mat4(b))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					initialize = _lib.rk_initialize
 | 
				
			||||||
 | 
					initialize.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					initialize.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_char_p,) # name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_load_shader = _lib.rk_load_shader
 | 
				
			||||||
 | 
					_load_shader.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					_load_shader.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_char_p,) # name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def load_shader(name):
 | 
				
			||||||
 | 
					    print("Loading shader", str(name, 'utf-8'));
 | 
				
			||||||
 | 
					    return _load_shader(name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select_shader = _lib.rk_select_shader
 | 
				
			||||||
 | 
					select_shader.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # shader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					resolve_input = _lib.rk_resolve_input
 | 
				
			||||||
 | 
					resolve_input.restype =  ctypes.c_void_p
 | 
				
			||||||
 | 
					resolve_input.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_char_p,) # name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_input_float = _lib.rk_set_input_float
 | 
				
			||||||
 | 
					set_input_float.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # input
 | 
				
			||||||
 | 
					    ctypes.c_float) # value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_set_input_vec3 = _lib.rk_set_input_vec3
 | 
				
			||||||
 | 
					_set_input_vec3.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # input
 | 
				
			||||||
 | 
					    _vec3_t, # value
 | 
				
			||||||
 | 
					    ctypes.c_uint) # mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_input_vec3(input, value, mode = INPUT_IDENTITY):
 | 
				
			||||||
 | 
					    assert len(value) == 3
 | 
				
			||||||
 | 
					    _set_input_vec3(input, _vec3(value), mode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_create_texture = _lib.rk_create_texture
 | 
				
			||||||
 | 
					_create_texture.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					_create_texture.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_uint, # slot
 | 
				
			||||||
 | 
					    ctypes.c_char_p, # input
 | 
				
			||||||
 | 
					    ctypes.c_uint, # format
 | 
				
			||||||
 | 
					    ctypes.c_uint, # width
 | 
				
			||||||
 | 
					    ctypes.c_uint, # height
 | 
				
			||||||
 | 
					    ctypes.c_uint, # nlevels
 | 
				
			||||||
 | 
					    ctypes.c_uint, # flags
 | 
				
			||||||
 | 
					    ctypes.c_void_p) # pixels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def create_texture(slot, input, format, width, height, nlevels, flags, pixels):
 | 
				
			||||||
 | 
					    assert pixels.typecode == TEXTURE_FORMAT_TYPECODE[format]
 | 
				
			||||||
 | 
					    assert len(pixels) == width * height * max(1, nlevels) * TEXTURE_FORMAT_NELEMS[format]
 | 
				
			||||||
 | 
					    return _create_texture(slot, input, format, width, height, nlevels, flags, _voidp(pixels))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_create_triangles = _lib.rk_create_triangles
 | 
				
			||||||
 | 
					_create_triangles.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					_create_triangles.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_uint, # nvertices
 | 
				
			||||||
 | 
					    ctypes.c_void_p) # vertices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def create_triangles(vertices):
 | 
				
			||||||
 | 
					    assert len(vertices) % 9 == 0
 | 
				
			||||||
 | 
					    return _create_triangles(len(vertices) // 3, _floatp(vertices))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_create_vertices = _lib.rk_create_vertices
 | 
				
			||||||
 | 
					_create_vertices.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					_create_vertices.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_char_p, # format
 | 
				
			||||||
 | 
					    ctypes.c_uint, # nvertices
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # vertices
 | 
				
			||||||
 | 
					    ctypes.c_uint, # nindices
 | 
				
			||||||
 | 
					    ctypes.c_void_p) # indices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def create_vertices(format, nvertices, vertices, indices):
 | 
				
			||||||
 | 
					    return _create_vertices(format, nvertices, _ubytep(vertices), len(indices), _ushortp(indices))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					create_batch = _lib.rk_create_batch
 | 
				
			||||||
 | 
					create_batch.restype = ctypes.c_void_p
 | 
				
			||||||
 | 
					create_batch.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_uint, # max_size
 | 
				
			||||||
 | 
					    ctypes.c_uint, # translation_format
 | 
				
			||||||
 | 
					    ctypes.c_uint) # orientation_format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set_projection = _lib.rk_set_projection
 | 
				
			||||||
 | 
					set_projection.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_float, # hfov
 | 
				
			||||||
 | 
					    ctypes.c_float, # ratio
 | 
				
			||||||
 | 
					    ctypes.c_float, # near
 | 
				
			||||||
 | 
					    ctypes.c_float) # far
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_set_view = _lib.rk_set_view
 | 
				
			||||||
 | 
					_set_view.argtypes = (
 | 
				
			||||||
 | 
					    _vec3_t, # position
 | 
				
			||||||
 | 
					    _vec3_t) # lookat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_view(position, lookat):
 | 
				
			||||||
 | 
					    assert len(position) == 3 and len(lookat) == 3
 | 
				
			||||||
 | 
					    _set_view(_vec3(position), _vec3(lookat))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					begin_frame = _lib.rk_begin_frame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select_texture = _lib.rk_select_texture
 | 
				
			||||||
 | 
					select_texture.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # texture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					draw_triangles = _lib.rk_draw_triangles
 | 
				
			||||||
 | 
					draw_triangles.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # triangles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					select_vertices = _lib.rk_select_vertices
 | 
				
			||||||
 | 
					select_vertices.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # vertices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_draw_batch = _lib.rk_draw_batch
 | 
				
			||||||
 | 
					_draw_batch.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # batch
 | 
				
			||||||
 | 
					    ctypes.c_uint, # size
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # flags
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # texlevels
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # meshes
 | 
				
			||||||
 | 
					    ctypes.c_void_p, # translations
 | 
				
			||||||
 | 
					    ctypes.c_void_p) # orientations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def draw_batch(batch, flags, texlevels, meshes, translations, orientations):
 | 
				
			||||||
 | 
					    size = len(flags)
 | 
				
			||||||
 | 
					    assert len(texlevels) == size and len(meshes) == size and len(translations) == size * 3
 | 
				
			||||||
 | 
					    assert not orientations or len(orientations) == size * 3
 | 
				
			||||||
 | 
					    _draw_batch(batch, size, _ubytep(flags), _ushortp(texlevels), _uintp(meshes), _floatp(translations),
 | 
				
			||||||
 | 
					        _floatp(orientations) if orientations else None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unselect_vertices = _lib.rk_unselect_vertices
 | 
				
			||||||
 | 
					unselect_vertices.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # vertices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unselect_texture = _lib.rk_unselect_texture
 | 
				
			||||||
 | 
					unselect_texture.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # texture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unselect_shader = _lib.rk_unselect_shader
 | 
				
			||||||
 | 
					unselect_shader.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # shader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end_frame = _lib.rk_end_frame
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destroy_batch = _lib.rk_destroy_batch
 | 
				
			||||||
 | 
					destroy_batch.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # batch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destroy_triangles = _lib.rk_destroy_triangles
 | 
				
			||||||
 | 
					destroy_triangles.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # triangles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destroy_vertices = _lib.rk_destroy_vertices
 | 
				
			||||||
 | 
					destroy_vertices.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # vertices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destroy_texture = _lib.rk_destroy_texture
 | 
				
			||||||
 | 
					destroy_texture.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # texture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					destroy_shader = _lib.rk_destroy_shader
 | 
				
			||||||
 | 
					destroy_shader.argtypes = (
 | 
				
			||||||
 | 
					    ctypes.c_void_p,) # shader
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					terminate = _lib.rk_terminate
 | 
				
			||||||
							
								
								
									
										53
									
								
								cpp/math.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								cpp/math.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "math.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: benchmark this ctypes interface against pure python maths
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_mat3_rotation(
 | 
				
			||||||
 | 
					    rk_mat3 & ret,
 | 
				
			||||||
 | 
					    rk_vec3 const & axis,
 | 
				
			||||||
 | 
					    float const angle) {
 | 
				
			||||||
 | 
					    ret = glm::mat3_cast(glm::angleAxis(angle, axis));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_mat3_mul_vec3(
 | 
				
			||||||
 | 
					    rk_vec3 & ret,
 | 
				
			||||||
 | 
					    rk_mat3 const & a,
 | 
				
			||||||
 | 
					    rk_vec3 const & b) {
 | 
				
			||||||
 | 
					    ret = a * b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_mat3_mul_mat3(
 | 
				
			||||||
 | 
					    rk_mat3 & ret,
 | 
				
			||||||
 | 
					    rk_mat3 const & a,
 | 
				
			||||||
 | 
					    rk_mat3 const & b) {
 | 
				
			||||||
 | 
					    ret = a * b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_mat4_mul_vec4(
 | 
				
			||||||
 | 
					    rk_vec4 & ret,
 | 
				
			||||||
 | 
					    rk_mat4 const & a,
 | 
				
			||||||
 | 
					    rk_vec4 const & b) {
 | 
				
			||||||
 | 
					    ret = a * b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_mat4_mul_mat4(
 | 
				
			||||||
 | 
					    rk_mat4 & ret,
 | 
				
			||||||
 | 
					    rk_mat4 const & a,
 | 
				
			||||||
 | 
					    rk_mat4 const & b) {
 | 
				
			||||||
 | 
					    ret = a * b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								cpp/math.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								cpp/math.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _RK_ENGINE_MATH_H
 | 
				
			||||||
 | 
					#define _RK_ENGINE_MATH_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "types.hpp"
 | 
				
			||||||
 | 
					#include <glm/glm.hpp>
 | 
				
			||||||
 | 
					#include <glm/ext.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef glm::vec2 rk_vec2;
 | 
				
			||||||
 | 
					typedef glm::vec3 rk_vec3;
 | 
				
			||||||
 | 
					typedef glm::vec4 rk_vec4;
 | 
				
			||||||
 | 
					typedef glm::mat3 rk_mat3;
 | 
				
			||||||
 | 
					typedef glm::mat4 rk_mat4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_mat3_rotation(
 | 
				
			||||||
 | 
					    rk_mat3 & ret,
 | 
				
			||||||
 | 
					    rk_vec3 const & axis,
 | 
				
			||||||
 | 
					    float const angle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_mat3_mul_vec3(
 | 
				
			||||||
 | 
					    rk_vec3 & ret,
 | 
				
			||||||
 | 
					    rk_mat3 const & a,
 | 
				
			||||||
 | 
					    rk_vec3 const & b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_mat3_mul_mat3(
 | 
				
			||||||
 | 
					    rk_mat3 & ret,
 | 
				
			||||||
 | 
					    rk_mat3 const & a,
 | 
				
			||||||
 | 
					    rk_mat3 const & b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_mat4_mul_vec4(
 | 
				
			||||||
 | 
					    rk_vec4 & ret,
 | 
				
			||||||
 | 
					    rk_mat4 const & a,
 | 
				
			||||||
 | 
					    rk_vec4 const & b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_mat4_mul_mat4(
 | 
				
			||||||
 | 
					    rk_mat4 & ret,
 | 
				
			||||||
 | 
					    rk_mat4 const & a,
 | 
				
			||||||
 | 
					    rk_mat4 const & b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _RK_ENGINE_MATH_H
 | 
				
			||||||
							
								
								
									
										38
									
								
								cpp/opengl/render_context.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								cpp/opengl/render_context.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _RK_ENGINE_RENDER_OPENGL_CONTEXT_H
 | 
				
			||||||
 | 
					#define _RK_ENGINE_RENDER_OPENGL_CONTEXT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../render.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_window_t rk_create_context(
 | 
				
			||||||
 | 
					    char const * name,
 | 
				
			||||||
 | 
					    int profile,
 | 
				
			||||||
 | 
					    int major,
 | 
				
			||||||
 | 
					    int minor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT char ** rk_load_shader_source(
 | 
				
			||||||
 | 
					    char const * filename,
 | 
				
			||||||
 | 
					    rk_uint * length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_free_shader_source(
 | 
				
			||||||
 | 
					    char ** shader,
 | 
				
			||||||
 | 
					    rk_uint length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_swap_buffers();
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_context();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _RK_ENGINE_RENDER_OPENGL_CONTEXT_H
 | 
				
			||||||
							
								
								
									
										254
									
								
								cpp/opengl/render_context_glx.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								cpp/opengl/render_context_glx.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,254 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Adapted from https://www.khronos.org/opengl/wiki/Tutorial:_OpenGL_3.0_Context_Creation_(GLX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "render_context.hpp"
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <GL/glx.h>
 | 
				
			||||||
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Display * rk_display = nullptr;
 | 
				
			||||||
 | 
					static Colormap rk_colormap = 0;
 | 
				
			||||||
 | 
					static Window rk_window = 0;
 | 
				
			||||||
 | 
					static GLXContext rk_context = nullptr;
 | 
				
			||||||
 | 
					static bool rk_error_occured = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
 | 
				
			||||||
 | 
					#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
 | 
				
			||||||
 | 
					typedef GLXContext (*glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, int const *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rk_printf(
 | 
				
			||||||
 | 
					    char const * messsage) {
 | 
				
			||||||
 | 
					    printf("[GLX] %s\n", messsage);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool rk_extension_supported(
 | 
				
			||||||
 | 
					    char const * extlist,
 | 
				
			||||||
 | 
					    char const * extension) {
 | 
				
			||||||
 | 
					    char const * where = strchr(extension, ' ');
 | 
				
			||||||
 | 
					    if (where || *extension == '\0') {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (char const * start = extlist;;) {
 | 
				
			||||||
 | 
					        where = strstr(start, extension);
 | 
				
			||||||
 | 
					        if (!where) {
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        char const * const terminator = where + strlen(extension);
 | 
				
			||||||
 | 
					        if ((where == start || *(where - 1) == ' ') && (*terminator == ' ' || *terminator == '\0')) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        start = terminator;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int rk_error_handler(
 | 
				
			||||||
 | 
					    Display * display,
 | 
				
			||||||
 | 
					    XErrorEvent * event) {
 | 
				
			||||||
 | 
					    rk_error_occured = true;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_window_t rk_create_context(
 | 
				
			||||||
 | 
					    char const * name,
 | 
				
			||||||
 | 
					    int profile,
 | 
				
			||||||
 | 
					    int major,
 | 
				
			||||||
 | 
					    int minor) {
 | 
				
			||||||
 | 
					    rk_display = XOpenDisplay(nullptr);
 | 
				
			||||||
 | 
					    if (!rk_display) {
 | 
				
			||||||
 | 
					        rk_printf("Failed to open X display.");
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static int const visual_attribs[] = {
 | 
				
			||||||
 | 
					        GLX_X_RENDERABLE, True,
 | 
				
			||||||
 | 
					        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
 | 
				
			||||||
 | 
					        GLX_RENDER_TYPE, GLX_RGBA_BIT,
 | 
				
			||||||
 | 
					        GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
 | 
				
			||||||
 | 
					        GLX_RED_SIZE, 8,
 | 
				
			||||||
 | 
					        GLX_GREEN_SIZE, 8,
 | 
				
			||||||
 | 
					        GLX_BLUE_SIZE, 8,
 | 
				
			||||||
 | 
					        GLX_ALPHA_SIZE, 8,
 | 
				
			||||||
 | 
					        GLX_DEPTH_SIZE, 24,
 | 
				
			||||||
 | 
					        GLX_STENCIL_SIZE, 8,
 | 
				
			||||||
 | 
					        GLX_DOUBLEBUFFER, True,
 | 
				
			||||||
 | 
					        None
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int glx_major, glx_minor;
 | 
				
			||||||
 | 
					    if (!glXQueryVersion(rk_display, &glx_major, &glx_minor) || (glx_major == 1 && glx_minor < 3) || glx_major < 1) {
 | 
				
			||||||
 | 
					        rk_printf("Invalid GLX version.");
 | 
				
			||||||
 | 
					        rk_destroy_context();
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int fbcount;
 | 
				
			||||||
 | 
					    GLXFBConfig * const fbc = glXChooseFBConfig(rk_display, DefaultScreen(rk_display), visual_attribs, &fbcount);
 | 
				
			||||||
 | 
					    if (!fbc) {
 | 
				
			||||||
 | 
					        rk_printf("Failed to retrieve a framebuffer config.");
 | 
				
			||||||
 | 
					        rk_destroy_context();
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int best_fbc = -1;
 | 
				
			||||||
 | 
					    int best_num_samp = -1;
 | 
				
			||||||
 | 
					    for (int i = 0; i < fbcount; ++i) {
 | 
				
			||||||
 | 
					        XVisualInfo * vi = glXGetVisualFromFBConfig(rk_display, fbc[i]);
 | 
				
			||||||
 | 
					        if (vi) {
 | 
				
			||||||
 | 
					            int srgb = 0;
 | 
				
			||||||
 | 
					            glXGetFBConfigAttrib(rk_display, fbc[i], GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgb);
 | 
				
			||||||
 | 
					            if (srgb) {
 | 
				
			||||||
 | 
					                int samp_buf, samples;
 | 
				
			||||||
 | 
					                glXGetFBConfigAttrib(rk_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf);
 | 
				
			||||||
 | 
					                glXGetFBConfigAttrib(rk_display, fbc[i], GLX_SAMPLES, &samples);
 | 
				
			||||||
 | 
					                if (best_fbc < 0 || (samp_buf && samples > best_num_samp)) {
 | 
				
			||||||
 | 
					                    best_fbc = i;
 | 
				
			||||||
 | 
					                    best_num_samp = samples;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            XFree(vi);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (best_fbc == -1) {
 | 
				
			||||||
 | 
					        XFree(fbc);
 | 
				
			||||||
 | 
					        rk_printf("Failed to find sRGB framebuffer.");
 | 
				
			||||||
 | 
					        rk_destroy_context();
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GLXFBConfig const bestFbc = fbc[best_fbc];
 | 
				
			||||||
 | 
					    XFree(fbc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XVisualInfo * const vi = glXGetVisualFromFBConfig(rk_display, bestFbc);
 | 
				
			||||||
 | 
					    rk_colormap = XCreateColormap(rk_display, RootWindow(rk_display, vi->screen), vi->visual, AllocNone);
 | 
				
			||||||
 | 
					    XSetWindowAttributes swa;
 | 
				
			||||||
 | 
					    swa.colormap = rk_colormap;
 | 
				
			||||||
 | 
					    swa.background_pixmap = None;
 | 
				
			||||||
 | 
					    swa.border_pixel = 0;
 | 
				
			||||||
 | 
					    swa.event_mask = StructureNotifyMask;
 | 
				
			||||||
 | 
					    rk_window = XCreateWindow(rk_display, RootWindow(rk_display, vi->screen),
 | 
				
			||||||
 | 
					                                0, 0, 1600, 900, 0, vi->depth, InputOutput, vi->visual,
 | 
				
			||||||
 | 
					                                CWBorderPixel | CWColormap | CWEventMask, &swa);
 | 
				
			||||||
 | 
					    if (!rk_window) {
 | 
				
			||||||
 | 
					        rk_printf("Failed to create window.");
 | 
				
			||||||
 | 
					        rk_destroy_context();
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    XFree(vi);
 | 
				
			||||||
 | 
					    XStoreName(rk_display, rk_window, name);
 | 
				
			||||||
 | 
					    XMapWindow( rk_display, rk_window );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char const * const glxExts = glXQueryExtensionsString(rk_display, DefaultScreen(rk_display));
 | 
				
			||||||
 | 
					    glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
 | 
				
			||||||
 | 
					    glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
 | 
				
			||||||
 | 
					        glXGetProcAddressARB((const GLubyte *)("glXCreateContextAttribsARB"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rk_error_occured = false;
 | 
				
			||||||
 | 
					    int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&rk_error_handler);
 | 
				
			||||||
 | 
					    if (!rk_extension_supported(glxExts, "GLX_ARB_create_context") || !glXCreateContextAttribsARB) {
 | 
				
			||||||
 | 
					        rk_printf("glXCreateContextAttribsARB() not found.");
 | 
				
			||||||
 | 
					        rk_destroy_context();
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const int context_attribs[] = {
 | 
				
			||||||
 | 
					            GLX_CONTEXT_MAJOR_VERSION_ARB, major,
 | 
				
			||||||
 | 
					            GLX_CONTEXT_MINOR_VERSION_ARB, minor,
 | 
				
			||||||
 | 
					            GLX_CONTEXT_PROFILE_MASK_ARB, profile,
 | 
				
			||||||
 | 
					            None
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        rk_context = glXCreateContextAttribsARB(rk_display, bestFbc, 0, True, context_attribs);
 | 
				
			||||||
 | 
					        XSync(rk_display, False);
 | 
				
			||||||
 | 
					        if (rk_error_occured || !rk_context) {
 | 
				
			||||||
 | 
					            rk_printf("Failed to create context.");
 | 
				
			||||||
 | 
					            rk_destroy_context();
 | 
				
			||||||
 | 
					            return nullptr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    XSetErrorHandler(oldHandler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!glXIsDirect(rk_display, rk_context)) {
 | 
				
			||||||
 | 
					        rk_printf("Warning: Rendering context is indirect.");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glXMakeCurrent(rk_display, rk_window, rk_context);
 | 
				
			||||||
 | 
					    return reinterpret_cast<rk_window_t>(rk_window);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_swap_buffers() {
 | 
				
			||||||
 | 
					    if (rk_display && rk_window) {
 | 
				
			||||||
 | 
					        glXSwapBuffers(rk_display, rk_window);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					char ** rk_load_shader_source(
 | 
				
			||||||
 | 
					    char const * filename,
 | 
				
			||||||
 | 
					    rk_uint * length) {
 | 
				
			||||||
 | 
					    char ** shader = nullptr;
 | 
				
			||||||
 | 
					    char buffer[1024];
 | 
				
			||||||
 | 
					    FILE * const file = fopen(filename, "rt");
 | 
				
			||||||
 | 
					    if (file) {
 | 
				
			||||||
 | 
					        int nlines = 0;
 | 
				
			||||||
 | 
					        while (fgets(buffer, sizeof(buffer), file)) {
 | 
				
			||||||
 | 
					            ++nlines;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (nlines) {
 | 
				
			||||||
 | 
					            rewind(file);
 | 
				
			||||||
 | 
					            shader = new char*[nlines];
 | 
				
			||||||
 | 
					            for (int line = 0; line < nlines; ++line) {
 | 
				
			||||||
 | 
					                shader[line] = new char[sizeof(buffer)];
 | 
				
			||||||
 | 
					                fgets(shader[line], sizeof(buffer), file);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            printf("Shader %s is empty.\n", filename);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        fclose(file);
 | 
				
			||||||
 | 
					        *length = nlines;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        printf("Cannot open shader %s.\n", filename);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return shader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_free_shader_source(
 | 
				
			||||||
 | 
					    char ** shader,
 | 
				
			||||||
 | 
					    rk_uint length) {
 | 
				
			||||||
 | 
					    if (shader) {
 | 
				
			||||||
 | 
					        for (rk_uint line = 0; line < length; ++line) {
 | 
				
			||||||
 | 
					            delete[] shader[line];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    delete[] shader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_context() {
 | 
				
			||||||
 | 
					    if (rk_display) {
 | 
				
			||||||
 | 
					        glXMakeCurrent(rk_display, 0, nullptr);
 | 
				
			||||||
 | 
					        if (rk_context) {
 | 
				
			||||||
 | 
					            glXDestroyContext(rk_display, rk_context);
 | 
				
			||||||
 | 
					            rk_context = nullptr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (rk_window) {
 | 
				
			||||||
 | 
					            XDestroyWindow(rk_display, rk_window);
 | 
				
			||||||
 | 
					            rk_window = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (rk_colormap) {
 | 
				
			||||||
 | 
					            XFreeColormap(rk_display, rk_colormap);
 | 
				
			||||||
 | 
					            rk_colormap = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        XCloseDisplay(rk_display);
 | 
				
			||||||
 | 
					        rk_display = nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										816
									
								
								cpp/opengl/render_opengles.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										816
									
								
								cpp/opengl/render_opengles.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,816 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "render_opengles.hpp"
 | 
				
			||||||
 | 
					#include <cstdio>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: move the GLX stuff to render_context_glx.cpp
 | 
				
			||||||
 | 
					#include <GL/glx.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rk_shader const * rk_current_shader = nullptr;
 | 
				
			||||||
 | 
					static rk_vertices const * rk_current_vertices = nullptr;
 | 
				
			||||||
 | 
					static bool rk_frame = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC rk_DrawElementsInstancedBaseInstance = nullptr;
 | 
				
			||||||
 | 
					static PFNGLMULTIDRAWELEMENTSINDIRECTPROC rk_MultiDrawElementsIndirect = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rk_printf(char const * messsage) {
 | 
				
			||||||
 | 
					    printf("[RK_ENGINE] %s\n", messsage);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define rk_error(message) { if (glGetError() != GL_NO_ERROR) { rk_printf(message); } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rk_debug_message_callback(
 | 
				
			||||||
 | 
					    GLenum source,
 | 
				
			||||||
 | 
					    GLenum type,
 | 
				
			||||||
 | 
					    GLuint id,
 | 
				
			||||||
 | 
					    GLenum severity,
 | 
				
			||||||
 | 
					    GLsizei length,
 | 
				
			||||||
 | 
					    GLchar const * message,
 | 
				
			||||||
 | 
					    void const * userParam) {
 | 
				
			||||||
 | 
					    if (id == 131169 || id == 131185 || id == 131218 || id == 131204) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    printf("[RK_ENGINE][GL] (id=%d) %s\n", id, message);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static __GLXextFuncPtr rk_extension(
 | 
				
			||||||
 | 
					    char const * const name,
 | 
				
			||||||
 | 
					    char const * const func) {
 | 
				
			||||||
 | 
					    __GLXextFuncPtr ext_ptr = nullptr;
 | 
				
			||||||
 | 
					    GLint num_exts = 0;
 | 
				
			||||||
 | 
					    glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts);
 | 
				
			||||||
 | 
					    for (int ext_index = 0; ext_index < num_exts; ++ext_index) {
 | 
				
			||||||
 | 
					        char const * const ext_name = reinterpret_cast<char const *>(glGetStringi(GL_EXTENSIONS, ext_index));
 | 
				
			||||||
 | 
					        if (strcmp(name, ext_name) == 0) {
 | 
				
			||||||
 | 
					            ext_ptr = glXGetProcAddressARB(reinterpret_cast<GLubyte const *>(func));
 | 
				
			||||||
 | 
					            printf("[RK_ENGINE] Using extension %s::%s\n", name, func);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return ext_ptr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_window_t rk_initialize(
 | 
				
			||||||
 | 
					    char const * name) {
 | 
				
			||||||
 | 
					    rk_window_t const window = rk_create_context(name, GLX_CONTEXT_ES_PROFILE_BIT_EXT, 3, 2);
 | 
				
			||||||
 | 
					    if (window) {
 | 
				
			||||||
 | 
					        GLubyte const * const vendor = glGetString(GL_VENDOR);
 | 
				
			||||||
 | 
					        GLubyte const * const renderer = glGetString(GL_RENDERER);
 | 
				
			||||||
 | 
					        printf("[RK_ENGINE] vendor: %s, renderer: %s\n", vendor, renderer);
 | 
				
			||||||
 | 
					        GLubyte const * const version = glGetString(GL_VERSION);
 | 
				
			||||||
 | 
					        GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION);
 | 
				
			||||||
 | 
					        printf("[RK_ENGINE] version: %s, language: %s\n", version, language);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        rk_DrawElementsInstancedBaseInstance =
 | 
				
			||||||
 | 
					            reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC>(
 | 
				
			||||||
 | 
					                rk_extension("GL_EXT_base_instance", "DrawElementsInstancedBaseInstance"));
 | 
				
			||||||
 | 
					        if (rk_DrawElementsInstancedBaseInstance) {
 | 
				
			||||||
 | 
					            rk_MultiDrawElementsIndirect =
 | 
				
			||||||
 | 
					                reinterpret_cast<PFNGLMULTIDRAWELEMENTSINDIRECTPROC>(
 | 
				
			||||||
 | 
					                    rk_extension("GL_EXT_multi_draw_indirect", "MultiDrawElementsIndirectEXT"));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        GLint context_flags = 0;
 | 
				
			||||||
 | 
					        glGetIntegerv(GL_CONTEXT_FLAGS, &context_flags);
 | 
				
			||||||
 | 
					        if (context_flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
 | 
				
			||||||
 | 
					            printf("[RK_ENGINE] Debug context enabled\n");
 | 
				
			||||||
 | 
					            glDebugMessageCallback(rk_debug_message_callback, nullptr);
 | 
				
			||||||
 | 
					            glEnable(GL_DEBUG_OUTPUT);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glDisable(GL_DEBUG_OUTPUT);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        glDisable(GL_BLEND);
 | 
				
			||||||
 | 
					        glEnable(GL_DITHER);
 | 
				
			||||||
 | 
					        glEnable(GL_DEPTH_TEST);
 | 
				
			||||||
 | 
					        glDisable(GL_SCISSOR_TEST);
 | 
				
			||||||
 | 
					        glDisable(GL_STENCIL_TEST);
 | 
				
			||||||
 | 
					        glEnable(GL_CULL_FACE);
 | 
				
			||||||
 | 
					        glFrontFace(GL_CCW);
 | 
				
			||||||
 | 
					        glCullFace(GL_BACK);
 | 
				
			||||||
 | 
					        glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return window;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rk_print_shader_infolog(GLuint shader) {
 | 
				
			||||||
 | 
					    int length;
 | 
				
			||||||
 | 
					    char infolog[1024];
 | 
				
			||||||
 | 
					    glGetShaderInfoLog(shader, sizeof(infolog), &length, infolog);
 | 
				
			||||||
 | 
					    if (length > 0) {
 | 
				
			||||||
 | 
					        rk_printf(infolog);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rk_print_program_infolog(GLuint program) {
 | 
				
			||||||
 | 
					    int length;
 | 
				
			||||||
 | 
					    char infolog[1024];
 | 
				
			||||||
 | 
					    glGetProgramInfoLog(program, sizeof(infolog), &length, infolog);
 | 
				
			||||||
 | 
					    if (length > 0) {
 | 
				
			||||||
 | 
					        rk_printf(infolog);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: external loading of shader sources
 | 
				
			||||||
 | 
					//TODO: error handling
 | 
				
			||||||
 | 
					rk_shader_t rk_load_shader(
 | 
				
			||||||
 | 
					    char const * name) {
 | 
				
			||||||
 | 
					    rk_shader * const shader = new rk_shader;
 | 
				
			||||||
 | 
					    shader->vertex = glCreateShader(GL_VERTEX_SHADER);
 | 
				
			||||||
 | 
					    shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
 | 
				
			||||||
 | 
					    shader->program = glCreateProgram();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char vertex_name[256];
 | 
				
			||||||
 | 
					    snprintf(vertex_name, sizeof(vertex_name), "%s_opengles.vert", name);
 | 
				
			||||||
 | 
					    printf("[RK_ENGINE] Loading vertex shader %s...\n", vertex_name);
 | 
				
			||||||
 | 
					    rk_uint vertex_length = 0;
 | 
				
			||||||
 | 
					    char ** vertex_source = rk_load_shader_source(vertex_name, &vertex_length);
 | 
				
			||||||
 | 
					    if (vertex_source) {
 | 
				
			||||||
 | 
					        rk_printf("Compiling vertex shader...");
 | 
				
			||||||
 | 
					        glShaderSource(shader->vertex, vertex_length, vertex_source, nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glCompileShader(shader->vertex);
 | 
				
			||||||
 | 
					    rk_error("glCompileShader() failed.");
 | 
				
			||||||
 | 
					    rk_print_shader_infolog(shader->vertex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char fragment_name[256];
 | 
				
			||||||
 | 
					    snprintf(fragment_name, sizeof(fragment_name), "%s_opengles.frag", name);
 | 
				
			||||||
 | 
					    printf("[RK_ENGINE] Loading fragment shader %s...\n", fragment_name);
 | 
				
			||||||
 | 
					    rk_uint fragment_length = 0;
 | 
				
			||||||
 | 
					    char ** fragment_source = rk_load_shader_source(fragment_name, &fragment_length);
 | 
				
			||||||
 | 
					    if (fragment_source) {
 | 
				
			||||||
 | 
					        rk_printf("Compiling fragment shader...");
 | 
				
			||||||
 | 
					        glShaderSource(shader->fragment, fragment_length, fragment_source, nullptr);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glCompileShader(shader->fragment);
 | 
				
			||||||
 | 
					    rk_error("glCompileShader() failed.");
 | 
				
			||||||
 | 
					    rk_print_shader_infolog(shader->fragment);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rk_printf("Linking program...");
 | 
				
			||||||
 | 
					    glAttachShader(shader->program, shader->vertex);
 | 
				
			||||||
 | 
					    glAttachShader(shader->program, shader->fragment);
 | 
				
			||||||
 | 
					    glLinkProgram(shader->program);
 | 
				
			||||||
 | 
					    rk_error("glLinkProgram() failed.");
 | 
				
			||||||
 | 
					    rk_print_program_infolog(shader->program);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rk_printf("Done.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glReleaseShaderCompiler();
 | 
				
			||||||
 | 
					    if (vertex_source != nullptr) {
 | 
				
			||||||
 | 
					        rk_free_shader_source(vertex_source, vertex_length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (fragment_source != nullptr) {
 | 
				
			||||||
 | 
					        rk_free_shader_source(fragment_source, fragment_length);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    shader->uniforms.view = glGetUniformLocation(shader->program, "u_view");
 | 
				
			||||||
 | 
					    shader->uniforms.view_km = glGetUniformLocation(shader->program, "u_view_km");
 | 
				
			||||||
 | 
					    shader->uniforms.projection = glGetUniformLocation(shader->program, "u_projection");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return shader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_select_shader(
 | 
				
			||||||
 | 
					    rk_shader_t _shader) {
 | 
				
			||||||
 | 
					    rk_shader * const shader = reinterpret_cast<rk_shader *>(_shader);
 | 
				
			||||||
 | 
					    if (shader) {
 | 
				
			||||||
 | 
					        rk_current_shader = shader;
 | 
				
			||||||
 | 
					        glUseProgram(shader->program);
 | 
				
			||||||
 | 
					        if (rk_frame) {
 | 
				
			||||||
 | 
					            if (shader->uniforms.view > -1) {
 | 
				
			||||||
 | 
					                glUniformMatrix4fv(shader->uniforms.view, 1, GL_FALSE, glm::value_ptr(rk_view));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (shader->uniforms.view_km > -1) {
 | 
				
			||||||
 | 
					                glUniformMatrix4fv(shader->uniforms.view_km, 1, GL_FALSE, glm::value_ptr(rk_view_km));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (shader->uniforms.projection > -1) {
 | 
				
			||||||
 | 
					                glUniformMatrix4fv(shader->uniforms.projection, 1, GL_FALSE, glm::value_ptr(rk_projection));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_input_t rk_resolve_input(
 | 
				
			||||||
 | 
					    char const * name) {
 | 
				
			||||||
 | 
					    if (!rk_current_shader || !name) {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GLint const uniform = glGetUniformLocation(rk_current_shader->program, name);
 | 
				
			||||||
 | 
					    return reinterpret_cast<rk_input_t>(uniform + 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_set_input_float(
 | 
				
			||||||
 | 
					    rk_input_t _input,
 | 
				
			||||||
 | 
					    float value) {
 | 
				
			||||||
 | 
					    GLint const input = reinterpret_cast<intptr_t>(_input) - 1;
 | 
				
			||||||
 | 
					    if (rk_current_shader && input > -1) {
 | 
				
			||||||
 | 
					        glUniform1f(input, value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_set_input_vec3(
 | 
				
			||||||
 | 
					    rk_input_t _input,
 | 
				
			||||||
 | 
					    rk_vec3 const & value,
 | 
				
			||||||
 | 
					    rk_input_mode mode) {
 | 
				
			||||||
 | 
					    GLint const input = reinterpret_cast<intptr_t>(_input) - 1;
 | 
				
			||||||
 | 
					    if (rk_current_shader && input > -1) {
 | 
				
			||||||
 | 
					        switch (mode) {
 | 
				
			||||||
 | 
					            case RK_INPUT_IDENTITY:
 | 
				
			||||||
 | 
					                glUniform3fv(input, 1, glm::value_ptr(value));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_INPUT_VIEW_POSITION: {
 | 
				
			||||||
 | 
					                glUniform3fv(input, 1, glm::value_ptr(rk_view * rk_vec4(value, 1.0)));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case RK_INPUT_VIEW_ORIENTATION: {
 | 
				
			||||||
 | 
					                glUniform3fv(input, 1, glm::value_ptr(rk_view * rk_vec4(value, 0.0)));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_texture_t rk_create_texture(
 | 
				
			||||||
 | 
					    rk_uint slot,
 | 
				
			||||||
 | 
					    char const * input,
 | 
				
			||||||
 | 
					    rk_texture_format format,
 | 
				
			||||||
 | 
					    rk_uint width,
 | 
				
			||||||
 | 
					    rk_uint height,
 | 
				
			||||||
 | 
					    rk_uint nlevels,
 | 
				
			||||||
 | 
					    rk_texture_flags flags,
 | 
				
			||||||
 | 
					    void const * pixels) {
 | 
				
			||||||
 | 
					    if (!input || width == 0 || height == 0 || !pixels || !rk_current_shader) {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    GLint internal_format;
 | 
				
			||||||
 | 
					    GLenum source_format;
 | 
				
			||||||
 | 
					    GLenum source_type;
 | 
				
			||||||
 | 
					    switch (format) {
 | 
				
			||||||
 | 
					        case RK_TEXTURE_FORMAT_SRGB8_A8:
 | 
				
			||||||
 | 
					            internal_format = GL_SRGB8_ALPHA8;
 | 
				
			||||||
 | 
					            source_format = GL_RGBA;
 | 
				
			||||||
 | 
					            source_type = GL_UNSIGNED_BYTE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_TEXTURE_FORMAT_RGBA8:
 | 
				
			||||||
 | 
					            internal_format = GL_RGBA8;
 | 
				
			||||||
 | 
					            source_format = GL_RGBA;
 | 
				
			||||||
 | 
					            source_type = GL_UNSIGNED_BYTE;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_TEXTURE_FORMAT_RGB10_A2:
 | 
				
			||||||
 | 
					            internal_format = GL_RGB10_A2;
 | 
				
			||||||
 | 
					            source_format = GL_RGBA;
 | 
				
			||||||
 | 
					            source_type = GL_UNSIGNED_INT_2_10_10_10_REV;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_TEXTURE_FORMAT_32F:
 | 
				
			||||||
 | 
					            internal_format = GL_R32F;
 | 
				
			||||||
 | 
					            source_format = GL_RED;
 | 
				
			||||||
 | 
					            source_type =  GL_FLOAT;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            return nullptr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_texture * const texture = new rk_texture;
 | 
				
			||||||
 | 
					    glActiveTexture(GL_TEXTURE0 + slot);
 | 
				
			||||||
 | 
					    glGenTextures(1, &texture->texture);
 | 
				
			||||||
 | 
					    GLenum target;
 | 
				
			||||||
 | 
					    if (nlevels) {
 | 
				
			||||||
 | 
					        if (flags & RK_TEXTURE_FLAG_3D) {
 | 
				
			||||||
 | 
					            target = GL_TEXTURE_3D;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            target = GL_TEXTURE_2D_ARRAY;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        glBindTexture(target, texture->texture);
 | 
				
			||||||
 | 
					        //TODO: glTexStorage3D
 | 
				
			||||||
 | 
					        glTexImage3D(target, 0, internal_format, width, height, nlevels, 0, source_format, source_type, pixels);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        target = GL_TEXTURE_2D;
 | 
				
			||||||
 | 
					        glBindTexture(target, texture->texture);
 | 
				
			||||||
 | 
					        //TODO: glTexStorage2D
 | 
				
			||||||
 | 
					        glTexImage2D(target, 0, internal_format, width, height, 0, source_format, source_type, pixels);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (flags & RK_TEXTURE_FLAG_MIPMAPS) {
 | 
				
			||||||
 | 
					        if (flags & RK_TEXTURE_FLAG_MIN_LINEAR) {
 | 
				
			||||||
 | 
					            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        if (flags & RK_TEXTURE_FLAG_MIN_LINEAR) {
 | 
				
			||||||
 | 
					            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (flags & RK_TEXTURE_FLAG_MAG_LINEAR) {
 | 
				
			||||||
 | 
					        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_REPEAT);
 | 
				
			||||||
 | 
					    glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_REPEAT);
 | 
				
			||||||
 | 
					    glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_REPEAT);
 | 
				
			||||||
 | 
					    if (flags & RK_TEXTURE_FLAG_MIPMAPS) {
 | 
				
			||||||
 | 
					        glGenerateMipmap(target);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    texture->slot = slot;
 | 
				
			||||||
 | 
					    texture->nlevels = nlevels;
 | 
				
			||||||
 | 
					    texture->sampler = glGetUniformLocation(rk_current_shader->program, input);
 | 
				
			||||||
 | 
					    if (texture->sampler == -1) {
 | 
				
			||||||
 | 
					        printf("[RK_ENGINE] glGetUniformLocation(%s) failed\n", input);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glBindTexture(target, 0);
 | 
				
			||||||
 | 
					    return texture;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_triangles_t rk_create_triangles(
 | 
				
			||||||
 | 
					    rk_uint nvertices,
 | 
				
			||||||
 | 
					    rk_vec3 const * vertices) {
 | 
				
			||||||
 | 
					    if (nvertices == 0 || !vertices || !rk_current_shader) {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_triangles * const triangles = new rk_triangles;
 | 
				
			||||||
 | 
					    triangles->size = nvertices;
 | 
				
			||||||
 | 
					    glGenVertexArrays(1, &triangles->array);
 | 
				
			||||||
 | 
					    glBindVertexArray(triangles->array);
 | 
				
			||||||
 | 
					    glGenBuffers(1, &triangles->vertices);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, triangles->vertices);
 | 
				
			||||||
 | 
					    glBufferData(GL_ARRAY_BUFFER, nvertices * sizeof(rk_vec3), vertices, GL_STATIC_DRAW);
 | 
				
			||||||
 | 
					    glEnableVertexAttribArray(0);
 | 
				
			||||||
 | 
					    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
				
			||||||
 | 
					    glBindVertexArray(0);
 | 
				
			||||||
 | 
					    return triangles;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_vertices_t rk_create_vertices(
 | 
				
			||||||
 | 
					    rk_vertex_format const * format,
 | 
				
			||||||
 | 
					    rk_uint nvertices,
 | 
				
			||||||
 | 
					    void const * _vertices,
 | 
				
			||||||
 | 
					    rk_uint nindices,
 | 
				
			||||||
 | 
					    rk_ushort const * indices) {
 | 
				
			||||||
 | 
					    if (!format || !nvertices || !_vertices || !nindices || !indices || !rk_current_shader) {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint vertex_size = 0;
 | 
				
			||||||
 | 
					    for (rk_vertex_format const * f = format; *f; ++f) {
 | 
				
			||||||
 | 
					        switch (*f) {
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC2_FLOAT:
 | 
				
			||||||
 | 
					                vertex_size += sizeof(float) * 2;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC2_USHORT:
 | 
				
			||||||
 | 
					                vertex_size += sizeof(rk_ushort) * 2;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC3_FLOAT:
 | 
				
			||||||
 | 
					                vertex_size += sizeof(float) * 3;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC3_INT10:
 | 
				
			||||||
 | 
					                vertex_size += sizeof(rk_uint);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                rk_printf("rk_create_vertices(): invalid format.");
 | 
				
			||||||
 | 
					                return nullptr;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!vertex_size) {
 | 
				
			||||||
 | 
					        rk_printf("rk_create_vertices(): empty format.");
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_vertices * const vertices = new rk_vertices;
 | 
				
			||||||
 | 
					    glGenVertexArrays(1, &vertices->array);
 | 
				
			||||||
 | 
					    glBindVertexArray(vertices->array);
 | 
				
			||||||
 | 
					    glGenBuffers(1, &vertices->vertices);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, vertices->vertices);
 | 
				
			||||||
 | 
					    glBufferData(GL_ARRAY_BUFFER, nvertices * vertex_size, _vertices, GL_STATIC_DRAW);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
				
			||||||
 | 
					    vertices->vertex_size = vertex_size;
 | 
				
			||||||
 | 
					    vertices->layout = 0;
 | 
				
			||||||
 | 
					    rk_uint offset = 0;
 | 
				
			||||||
 | 
					    for (rk_vertex_format const * f = format; *f; ++f, ++vertices->layout) {
 | 
				
			||||||
 | 
					        glEnableVertexAttribArray(vertices->layout);
 | 
				
			||||||
 | 
					        switch (*f) {
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC2_FLOAT:
 | 
				
			||||||
 | 
					                glVertexAttribFormat(vertices->layout, 2, GL_FLOAT, GL_FALSE, offset);
 | 
				
			||||||
 | 
					                glVertexAttribBinding(vertices->layout, RK_VERTICES_BINDING);
 | 
				
			||||||
 | 
					                offset += sizeof(float) * 2;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC2_USHORT:
 | 
				
			||||||
 | 
					                glVertexAttribFormat(vertices->layout, 2, GL_UNSIGNED_SHORT, GL_TRUE, offset);
 | 
				
			||||||
 | 
					                glVertexAttribBinding(vertices->layout, RK_VERTICES_BINDING);
 | 
				
			||||||
 | 
					                offset += sizeof(rk_ushort) * 2;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC3_FLOAT:
 | 
				
			||||||
 | 
					                glVertexAttribFormat(vertices->layout, 3, GL_FLOAT, GL_FALSE, offset);
 | 
				
			||||||
 | 
					                glVertexAttribBinding(vertices->layout, RK_VERTICES_BINDING);
 | 
				
			||||||
 | 
					                offset += sizeof(float) * 3;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case RK_VERTEX_FORMAT_VEC3_INT10:
 | 
				
			||||||
 | 
					                glVertexAttribFormat(vertices->layout, GL_BGRA, GL_INT_2_10_10_10_REV, GL_TRUE, offset);
 | 
				
			||||||
 | 
					                glVertexAttribBinding(vertices->layout, RK_VERTICES_BINDING);
 | 
				
			||||||
 | 
					                offset += sizeof(rk_uint);
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glBindVertexBuffer(RK_VERTICES_BINDING, vertices->vertices, 0, vertices->vertex_size);
 | 
				
			||||||
 | 
					    glGenBuffers(1, &vertices->indices);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertices->indices);
 | 
				
			||||||
 | 
					    glBufferData(GL_ELEMENT_ARRAY_BUFFER, nindices * sizeof(rk_ushort), indices, GL_STATIC_DRAW);
 | 
				
			||||||
 | 
					    glBindVertexArray(0);
 | 
				
			||||||
 | 
					    return vertices;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: support for mat3 orientations with packing into int10 * 3
 | 
				
			||||||
 | 
					// - maybe from quaternions inputs
 | 
				
			||||||
 | 
					// - maybe it's possible to implement efficient quaternions in glsl?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_batch_t rk_create_batch(
 | 
				
			||||||
 | 
					    rk_uint max_size,
 | 
				
			||||||
 | 
					    rk_batch_translation_format translation_format,
 | 
				
			||||||
 | 
					    rk_batch_orientation_format orientation_format) {
 | 
				
			||||||
 | 
					    if (!max_size || max_size > RK_BATCH_MAX_SIZE || !rk_current_shader || !rk_current_vertices) {
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint translation_size = 0;
 | 
				
			||||||
 | 
					    switch (translation_format) {
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					            translation_size = sizeof(float) * 4;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
				
			||||||
 | 
					            translation_size = sizeof(rk_short) * 4;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            rk_printf("rk_create_batch(): invalid translation format.");
 | 
				
			||||||
 | 
					            return nullptr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint orientation_size = 0;
 | 
				
			||||||
 | 
					    switch (orientation_format) {
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
				
			||||||
 | 
					            orientation_size = 0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					            orientation_size = sizeof(float) * 3;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
				
			||||||
 | 
					            orientation_size = sizeof(rk_uint);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            rk_printf("rk_create_batch(): invalid orientation format.");
 | 
				
			||||||
 | 
					            return nullptr;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint const params_size = translation_size + orientation_size;
 | 
				
			||||||
 | 
					    rk_batch * batch = new rk_batch;
 | 
				
			||||||
 | 
					    batch->size = max_size;
 | 
				
			||||||
 | 
					    batch->translation_format = translation_format;
 | 
				
			||||||
 | 
					    batch->orientation_format = orientation_format;
 | 
				
			||||||
 | 
					    batch->params_size = params_size;
 | 
				
			||||||
 | 
					    batch->indices = new rk_ushort[batch->size];
 | 
				
			||||||
 | 
					    batch->params = new rk_ubyte[batch->size * params_size];
 | 
				
			||||||
 | 
					    batch->commands = new rk_command[batch->size * sizeof(rk_command)];
 | 
				
			||||||
 | 
					    glGenBuffers(1, &batch->params_buffer);
 | 
				
			||||||
 | 
					    rk_uint const translation_layout = rk_current_vertices->layout;
 | 
				
			||||||
 | 
					    glEnableVertexAttribArray(translation_layout);
 | 
				
			||||||
 | 
					    switch (translation_format) {
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					            glVertexAttribFormat(translation_layout, 4, GL_FLOAT, GL_FALSE, 0);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
				
			||||||
 | 
					            glVertexAttribFormat(translation_layout, 4, GL_SHORT, GL_FALSE, 0);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glVertexAttribBinding(translation_layout, RK_PARAMS_BINDING);
 | 
				
			||||||
 | 
					    rk_uint const orientation_layout = rk_current_vertices->layout + 1;
 | 
				
			||||||
 | 
					    switch (orientation_format) {
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					            glEnableVertexAttribArray(orientation_layout);
 | 
				
			||||||
 | 
					            glVertexAttribFormat(orientation_layout, 3, GL_FLOAT, GL_FALSE, translation_size);
 | 
				
			||||||
 | 
					            glVertexAttribBinding(orientation_layout, RK_PARAMS_BINDING);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
				
			||||||
 | 
					            glEnableVertexAttribArray(orientation_layout);
 | 
				
			||||||
 | 
					            glVertexAttribFormat(orientation_layout, GL_BGRA, GL_INT_2_10_10_10_REV, GL_TRUE, translation_size);
 | 
				
			||||||
 | 
					            glVertexAttribBinding(orientation_layout, RK_PARAMS_BINDING);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glVertexBindingDivisor(RK_PARAMS_BINDING, 1);
 | 
				
			||||||
 | 
					    glBindVertexBuffer(RK_PARAMS_BINDING, batch->params_buffer, 0, batch->params_size);
 | 
				
			||||||
 | 
					    if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					        glGenBuffers(1, &batch->commands_buffer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return batch;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_begin_frame() {
 | 
				
			||||||
 | 
					    rk_frame = true;
 | 
				
			||||||
 | 
					    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_select_texture(
 | 
				
			||||||
 | 
					    rk_texture_t _texture) {
 | 
				
			||||||
 | 
					    rk_texture const * const texture = reinterpret_cast<rk_texture const *>(_texture);
 | 
				
			||||||
 | 
					    if (texture) {
 | 
				
			||||||
 | 
					        glActiveTexture(GL_TEXTURE0 + texture->slot);
 | 
				
			||||||
 | 
					        if (texture->nlevels) {
 | 
				
			||||||
 | 
					            glBindTexture(GL_TEXTURE_2D_ARRAY, texture->texture);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glBindTexture(GL_TEXTURE_2D, texture->texture);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (texture->sampler > -1) {
 | 
				
			||||||
 | 
					            glUniform1i(texture->sampler, texture->slot);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_draw_triangles(
 | 
				
			||||||
 | 
					    rk_triangles_t _triangles) {
 | 
				
			||||||
 | 
					    rk_triangles const * const triangles = reinterpret_cast<rk_triangles const *>(_triangles);
 | 
				
			||||||
 | 
					    if (triangles && rk_current_shader && !rk_current_vertices) {
 | 
				
			||||||
 | 
					        glBindVertexArray(triangles->array);
 | 
				
			||||||
 | 
					        glDrawArrays(GL_TRIANGLES, 0, triangles->size);
 | 
				
			||||||
 | 
					        glBindVertexArray(0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_select_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t _vertices) {
 | 
				
			||||||
 | 
					    rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices);
 | 
				
			||||||
 | 
					    if (vertices && rk_current_shader) {
 | 
				
			||||||
 | 
					        glBindVertexArray(vertices->array);
 | 
				
			||||||
 | 
					        rk_current_vertices = vertices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rk_uint rk_batch_filter(
 | 
				
			||||||
 | 
					    rk_uint const size,
 | 
				
			||||||
 | 
					    rk_ushort * const _indices,
 | 
				
			||||||
 | 
					    rk_instance_flags const * flags) {
 | 
				
			||||||
 | 
					    rk_ushort * indices = _indices;
 | 
				
			||||||
 | 
					    for (rk_ushort index = 0; index < size; ++index, ++flags) {
 | 
				
			||||||
 | 
					        if ((*flags & RK_INSTANCE_FLAGS_SPAWNED_VISIBLE) == RK_INSTANCE_FLAGS_SPAWNED_VISIBLE) {
 | 
				
			||||||
 | 
					            *indices++ = index;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return indices - _indices;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static rk_uint rk_batch_build_commands(
 | 
				
			||||||
 | 
					    rk_uint const count,
 | 
				
			||||||
 | 
					    rk_ushort * const indices,
 | 
				
			||||||
 | 
					    rk_command * const _commands,
 | 
				
			||||||
 | 
					    rk_mesh const * const meshes) {
 | 
				
			||||||
 | 
					    rk_command * commands = _commands;
 | 
				
			||||||
 | 
					    rk_ushort * base = indices;
 | 
				
			||||||
 | 
					    rk_ushort * const last = indices + count;
 | 
				
			||||||
 | 
					    for (rk_ushort * first = indices; first < last; base = first, ++commands) {
 | 
				
			||||||
 | 
					        rk_mesh const & mesh = meshes[*first++];
 | 
				
			||||||
 | 
					        for ( ; first < last && meshes[*first].packed == mesh.packed; ++first) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (rk_ushort * second = first; second < last; ++second) {
 | 
				
			||||||
 | 
					            rk_ushort const index = *second;
 | 
				
			||||||
 | 
					            if (meshes[index].packed == mesh.packed) {
 | 
				
			||||||
 | 
					                *second = *first;
 | 
				
			||||||
 | 
					                *first++ = index;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        commands->count = static_cast<GLuint>(mesh.count) * 3;
 | 
				
			||||||
 | 
					        commands->ninstances = first - base;
 | 
				
			||||||
 | 
					        commands->base_index = mesh.offset;
 | 
				
			||||||
 | 
					        commands->base_vertex = 0;
 | 
				
			||||||
 | 
					        commands->base_instance = base - indices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return commands - _commands;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template < typename _instance_params_t >
 | 
				
			||||||
 | 
					static void rk_batch_convert_params(
 | 
				
			||||||
 | 
					    rk_uint const count,
 | 
				
			||||||
 | 
					    rk_ushort const * const _indices,
 | 
				
			||||||
 | 
					    rk_ubyte * const _params,
 | 
				
			||||||
 | 
					    rk_vec3 const * const translations,
 | 
				
			||||||
 | 
					    rk_ushort const * const texlevels,
 | 
				
			||||||
 | 
					    rk_vec3 const * const orientations) {
 | 
				
			||||||
 | 
					    _instance_params_t * params = reinterpret_cast<_instance_params_t *>(_params);
 | 
				
			||||||
 | 
					    rk_ushort const * const last = _indices + count;
 | 
				
			||||||
 | 
					    for (rk_ushort const * indices = _indices; indices < last; ++indices, ++params) {
 | 
				
			||||||
 | 
					        rk_uint const index = *indices;
 | 
				
			||||||
 | 
					        params->set(translations[index], texlevels[index], orientations[index]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template < typename _instance_params_t >
 | 
				
			||||||
 | 
					static void rk_batch_convert_params(
 | 
				
			||||||
 | 
					    rk_uint const count,
 | 
				
			||||||
 | 
					    rk_ushort const * const _indices,
 | 
				
			||||||
 | 
					    rk_ubyte * const _params,
 | 
				
			||||||
 | 
					    rk_vec3 const * const translations,
 | 
				
			||||||
 | 
					    rk_ushort const * const texlevels) {
 | 
				
			||||||
 | 
					    _instance_params_t * params = reinterpret_cast<_instance_params_t *>(_params);
 | 
				
			||||||
 | 
					    rk_ushort const * const last = _indices + count;
 | 
				
			||||||
 | 
					    for (rk_ushort const * indices = _indices; indices < last; ++indices, ++params) {
 | 
				
			||||||
 | 
					        rk_uint const index = *indices;
 | 
				
			||||||
 | 
					        params->set(translations[index], texlevels[index]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_draw_batch(
 | 
				
			||||||
 | 
					    rk_batch_t _batch,
 | 
				
			||||||
 | 
					    rk_uint size,
 | 
				
			||||||
 | 
					    rk_instance_flags const * flags,
 | 
				
			||||||
 | 
					    rk_ushort const * texlevels,
 | 
				
			||||||
 | 
					    rk_mesh const * meshes,
 | 
				
			||||||
 | 
					    rk_vec3 const * translations,
 | 
				
			||||||
 | 
					    rk_vec3 const * orientations) {
 | 
				
			||||||
 | 
					    rk_batch & batch = *reinterpret_cast<rk_batch *>(_batch);
 | 
				
			||||||
 | 
					    if (!size || size > batch.size || !flags || !texlevels || !meshes || !translations ||
 | 
				
			||||||
 | 
					        !rk_current_shader || !rk_current_vertices) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (batch.orientation_format != RK_BATCH_ORIENTATION_FORMAT_NONE && !orientations) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint const count = rk_batch_filter(size, batch.indices, flags);
 | 
				
			||||||
 | 
					    if (!count) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rk_uint const ncommands = rk_batch_build_commands(count, batch.indices, batch.commands, meshes);
 | 
				
			||||||
 | 
					    if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.commands_buffer);
 | 
				
			||||||
 | 
					        glBufferData(GL_DRAW_INDIRECT_BUFFER, ncommands * sizeof(rk_command), batch.commands, GL_STREAM_DRAW);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    switch (batch.translation_format) {
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					            switch (batch.orientation_format) {
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_translation_float>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_params_float_float>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels, orientations);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_params_float_int10>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels, orientations);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
				
			||||||
 | 
					            switch (batch.orientation_format) {
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_translation_short>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_params_short_float>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels, orientations);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
				
			||||||
 | 
					                    rk_batch_convert_params<rk_params_short_int10>(
 | 
				
			||||||
 | 
					                        count, batch.indices, batch.params, translations, texlevels, orientations);
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, batch.params_buffer);
 | 
				
			||||||
 | 
					    glBufferData(GL_ARRAY_BUFFER, count * batch.params_size, batch.params, GL_STREAM_DRAW);
 | 
				
			||||||
 | 
					    glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
				
			||||||
 | 
					    if (batch.orientation_format == RK_BATCH_ORIENTATION_FORMAT_NONE) {
 | 
				
			||||||
 | 
					        rk_vec3 const forward(0.f, 1.f, 0.f);
 | 
				
			||||||
 | 
					        glVertexAttrib3fv(rk_current_vertices->layout + 1, glm::value_ptr(forward));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (rk_DrawElementsInstancedBaseInstance) {
 | 
				
			||||||
 | 
					        if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					            rk_MultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, ncommands, sizeof(rk_command));
 | 
				
			||||||
 | 
					            glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            rk_command const * const last_command = batch.commands + ncommands;
 | 
				
			||||||
 | 
					            for (rk_command const * command = batch.commands; command < last_command; ++command) {
 | 
				
			||||||
 | 
					                rk_DrawElementsInstancedBaseInstance(
 | 
				
			||||||
 | 
					                    GL_TRIANGLES, command->count, GL_UNSIGNED_SHORT,
 | 
				
			||||||
 | 
					                    reinterpret_cast<void const *>(command->base_index << 1),
 | 
				
			||||||
 | 
					                    command->ninstances, command->base_instance);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        rk_uint params_offset = 0;
 | 
				
			||||||
 | 
					        rk_command const * const last_command = batch.commands + ncommands;
 | 
				
			||||||
 | 
					        for (rk_command const * command = batch.commands; command < last_command; ++command) {
 | 
				
			||||||
 | 
					            glBindVertexBuffer(RK_PARAMS_BINDING, batch.params_buffer, params_offset, batch.params_size);
 | 
				
			||||||
 | 
					            params_offset += command->ninstances * batch.params_size;
 | 
				
			||||||
 | 
					            glDrawElementsInstanced(
 | 
				
			||||||
 | 
					                GL_TRIANGLES, command->count, GL_UNSIGNED_SHORT,
 | 
				
			||||||
 | 
					                reinterpret_cast<void const *>(command->base_index << 1),
 | 
				
			||||||
 | 
					                command->ninstances);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_unselect_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t _vertices) {
 | 
				
			||||||
 | 
					    rk_current_vertices = nullptr;
 | 
				
			||||||
 | 
					    glBindVertexArray(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_unselect_texture(
 | 
				
			||||||
 | 
					    rk_texture_t _texture) {
 | 
				
			||||||
 | 
					    rk_texture const * const texture = reinterpret_cast<rk_texture const *>(_texture);
 | 
				
			||||||
 | 
					    if (texture) {
 | 
				
			||||||
 | 
					        glActiveTexture(GL_TEXTURE0 + texture->slot);
 | 
				
			||||||
 | 
					        if (texture->nlevels) {
 | 
				
			||||||
 | 
					            glBindTexture(GL_TEXTURE_2D, 0);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_unselect_shader(
 | 
				
			||||||
 | 
					    rk_shader_t _shader) {
 | 
				
			||||||
 | 
					    rk_current_shader = nullptr;
 | 
				
			||||||
 | 
					    glUseProgram(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_end_frame() {
 | 
				
			||||||
 | 
					    rk_swap_buffers();
 | 
				
			||||||
 | 
					    rk_frame = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_batch(
 | 
				
			||||||
 | 
					    rk_batch_t _batch) {
 | 
				
			||||||
 | 
					    rk_batch * const batch = reinterpret_cast<rk_batch *>(_batch);
 | 
				
			||||||
 | 
					    if (batch) {
 | 
				
			||||||
 | 
					        delete[] batch->indices;
 | 
				
			||||||
 | 
					        delete[] batch->params;
 | 
				
			||||||
 | 
					        delete[] batch->commands;
 | 
				
			||||||
 | 
					        glDeleteBuffers(1, &batch->params_buffer);
 | 
				
			||||||
 | 
					        if (rk_MultiDrawElementsIndirect) {
 | 
				
			||||||
 | 
					            glDeleteBuffers(1, &batch->commands_buffer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        delete batch;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_triangles(
 | 
				
			||||||
 | 
					    rk_triangles_t _triangles) {
 | 
				
			||||||
 | 
					    rk_triangles * const triangles = reinterpret_cast<rk_triangles *>(_triangles);
 | 
				
			||||||
 | 
					    if (triangles) {
 | 
				
			||||||
 | 
					        glDeleteBuffers(1, &triangles->vertices);
 | 
				
			||||||
 | 
					        glDeleteVertexArrays(1, &triangles->array);
 | 
				
			||||||
 | 
					        delete triangles;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t _vertices) {
 | 
				
			||||||
 | 
					    rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices);
 | 
				
			||||||
 | 
					    if (vertices) {
 | 
				
			||||||
 | 
					        glDeleteBuffers(1, &vertices->indices);
 | 
				
			||||||
 | 
					        glDeleteBuffers(1, &vertices->vertices);
 | 
				
			||||||
 | 
					        glDeleteVertexArrays(1, &vertices->array);
 | 
				
			||||||
 | 
					        delete vertices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_texture(
 | 
				
			||||||
 | 
					    rk_texture_t _texture) {
 | 
				
			||||||
 | 
					    rk_texture * const texture = reinterpret_cast<rk_texture *>(_texture);
 | 
				
			||||||
 | 
					    if (texture) {
 | 
				
			||||||
 | 
					        glDeleteTextures(1, &texture->texture);
 | 
				
			||||||
 | 
					        delete texture;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_destroy_shader(
 | 
				
			||||||
 | 
					    rk_shader_t _shader) {
 | 
				
			||||||
 | 
					    rk_shader * const shader = reinterpret_cast<rk_shader *>(_shader);
 | 
				
			||||||
 | 
					    if (shader) {
 | 
				
			||||||
 | 
					        glDeleteShader(shader->vertex);
 | 
				
			||||||
 | 
					        glDeleteShader(shader->fragment);
 | 
				
			||||||
 | 
					        glDeleteProgram(shader->program);
 | 
				
			||||||
 | 
					        delete shader;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_terminate() {
 | 
				
			||||||
 | 
					    rk_destroy_context();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										143
									
								
								cpp/opengl/render_opengles.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								cpp/opengl/render_opengles.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _RK_ENGINE_RENDER_OPENGLES_H
 | 
				
			||||||
 | 
					#define _RK_ENGINE_RENDER_OPENGLES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../render.hpp"
 | 
				
			||||||
 | 
					#include "render_context.hpp"
 | 
				
			||||||
 | 
					#include <GLES3/gl32.h>
 | 
				
			||||||
 | 
					#include <GLES3/gl3ext.h>
 | 
				
			||||||
 | 
					#include <GLES3/gl3platform.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum : rk_uint {
 | 
				
			||||||
 | 
					    RK_VERTICES_BINDING = 0,
 | 
				
			||||||
 | 
					    RK_PARAMS_BINDING = 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_uniforms {
 | 
				
			||||||
 | 
					    GLint view;
 | 
				
			||||||
 | 
					    GLint view_km;
 | 
				
			||||||
 | 
					    GLint projection;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_shader {
 | 
				
			||||||
 | 
					    GLuint vertex;
 | 
				
			||||||
 | 
					    GLuint fragment;
 | 
				
			||||||
 | 
					    GLuint program;
 | 
				
			||||||
 | 
					    rk_uniforms uniforms;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_texture {
 | 
				
			||||||
 | 
					    rk_uint slot;
 | 
				
			||||||
 | 
					    rk_uint nlevels;
 | 
				
			||||||
 | 
					    GLint sampler;
 | 
				
			||||||
 | 
					    GLuint texture;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_triangles {
 | 
				
			||||||
 | 
					    rk_uint size;
 | 
				
			||||||
 | 
					    GLuint array;
 | 
				
			||||||
 | 
					    GLuint vertices;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_vertices {
 | 
				
			||||||
 | 
					    rk_uint vertex_size;
 | 
				
			||||||
 | 
					    rk_uint layout;
 | 
				
			||||||
 | 
					    GLuint array;
 | 
				
			||||||
 | 
					    GLuint vertices;
 | 
				
			||||||
 | 
					    GLuint indices;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_command {
 | 
				
			||||||
 | 
					    GLuint count;
 | 
				
			||||||
 | 
					    GLuint ninstances;
 | 
				
			||||||
 | 
					    GLuint base_index;
 | 
				
			||||||
 | 
					    GLint base_vertex;
 | 
				
			||||||
 | 
					    GLuint base_instance;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_batch {
 | 
				
			||||||
 | 
					    rk_uint size;
 | 
				
			||||||
 | 
					    rk_batch_translation_format translation_format;
 | 
				
			||||||
 | 
					    rk_batch_orientation_format orientation_format;
 | 
				
			||||||
 | 
					    rk_uint params_size;
 | 
				
			||||||
 | 
					    rk_ushort * indices;
 | 
				
			||||||
 | 
					    rk_ubyte * params;
 | 
				
			||||||
 | 
					    rk_command * commands;
 | 
				
			||||||
 | 
					    GLuint params_buffer;
 | 
				
			||||||
 | 
					    GLuint commands_buffer;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_translation_float {
 | 
				
			||||||
 | 
					    rk_vec3 xyz;
 | 
				
			||||||
 | 
					    float l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void set(rk_vec3 const & translation, rk_ushort const texlevel) {
 | 
				
			||||||
 | 
					        xyz = translation;
 | 
				
			||||||
 | 
					        l = static_cast<float>(texlevel);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_translation_short {
 | 
				
			||||||
 | 
					    rk_short x;
 | 
				
			||||||
 | 
					    rk_short y;
 | 
				
			||||||
 | 
					    rk_short z;
 | 
				
			||||||
 | 
					    rk_ushort l;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void set(rk_vec3 const & translation, rk_ushort const texlevel) {
 | 
				
			||||||
 | 
					        x = static_cast<rk_short>(translation.x);
 | 
				
			||||||
 | 
					        y = static_cast<rk_short>(translation.y);
 | 
				
			||||||
 | 
					        z = static_cast<rk_short>(translation.z);
 | 
				
			||||||
 | 
					        l = texlevel;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_orientation_float {
 | 
				
			||||||
 | 
					    rk_vec3 xyz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void set(rk_vec3 const & orientation) {
 | 
				
			||||||
 | 
					        xyz = orientation;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct rk_orientation_int10 {
 | 
				
			||||||
 | 
					    rk_uint xyz;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void set(rk_vec3 const & orientation) {
 | 
				
			||||||
 | 
					        #define _pack_10(x) static_cast<rk_uint>(static_cast<rk_int>((x) * ((x) < 0.f ? 512.f : 511.f)) & 1023)
 | 
				
			||||||
 | 
					        xyz = _pack_10(orientation.x) << 20 | _pack_10(orientation.y) << 10 | _pack_10(orientation.z);
 | 
				
			||||||
 | 
					        #undef _pack_10
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template < typename _translation_t, typename _orientation_t >
 | 
				
			||||||
 | 
					struct rk_params {
 | 
				
			||||||
 | 
					    _translation_t translation;
 | 
				
			||||||
 | 
					    _orientation_t orientation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void set(rk_vec3 const & translation, rk_ushort const texlevel, rk_vec3 const & orientation) {
 | 
				
			||||||
 | 
					        this->translation.set(translation, texlevel);
 | 
				
			||||||
 | 
					        this->orientation.set(orientation);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef rk_params<rk_translation_float, rk_orientation_float> rk_params_float_float;
 | 
				
			||||||
 | 
					typedef rk_params<rk_translation_float, rk_orientation_int10> rk_params_float_int10;
 | 
				
			||||||
 | 
					typedef rk_params<rk_translation_short, rk_orientation_float> rk_params_short_float;
 | 
				
			||||||
 | 
					typedef rk_params<rk_translation_short, rk_orientation_int10> rk_params_short_int10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _RK_ENGINE_RENDER_OPENGLES_H
 | 
				
			||||||
							
								
								
									
										48
									
								
								cpp/render.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								cpp/render.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "render.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rk_vec3 rk_view_origin;
 | 
				
			||||||
 | 
					rk_vec3 rk_view_lookat;
 | 
				
			||||||
 | 
					rk_mat4 rk_view;
 | 
				
			||||||
 | 
					rk_mat4 rk_view_km;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float rk_projection_hfov;
 | 
				
			||||||
 | 
					float rk_projection_ratio;
 | 
				
			||||||
 | 
					float rk_projection_near;
 | 
				
			||||||
 | 
					float rk_projection_far;
 | 
				
			||||||
 | 
					rk_mat4 rk_projection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rk_set_projection(
 | 
				
			||||||
 | 
					    float hfov,
 | 
				
			||||||
 | 
					    float ratio,
 | 
				
			||||||
 | 
					    float near,
 | 
				
			||||||
 | 
					    float far) {
 | 
				
			||||||
 | 
					    rk_projection_hfov = hfov;
 | 
				
			||||||
 | 
					    rk_projection_ratio = ratio;
 | 
				
			||||||
 | 
					    rk_projection_near = near;
 | 
				
			||||||
 | 
					    rk_projection_far = far;
 | 
				
			||||||
 | 
					    rk_projection = glm::perspectiveRH(hfov, ratio, near, far);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern void rk_set_view(
 | 
				
			||||||
 | 
					    rk_vec3 const & position,
 | 
				
			||||||
 | 
					    rk_vec3 const & lookat) {
 | 
				
			||||||
 | 
					    rk_view_origin = position;
 | 
				
			||||||
 | 
					    rk_view_lookat = lookat;
 | 
				
			||||||
 | 
					    rk_view = glm::lookAtRH(position, lookat, glm::vec3(0.0f, 0.0f, 1.0f));
 | 
				
			||||||
 | 
					    rk_view_km = glm::lookAtRH(position * 0.001f, lookat * 0.001f, glm::vec3(0.0f, 0.0f, 1.0f));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										208
									
								
								cpp/render.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								cpp/render.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,208 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _RK_ENGINE_RENDER_H
 | 
				
			||||||
 | 
					#define _RK_ENGINE_RENDER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "types.hpp"
 | 
				
			||||||
 | 
					#include "math.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern rk_vec3 rk_view_origin;
 | 
				
			||||||
 | 
					extern rk_vec3 rk_view_lookat;
 | 
				
			||||||
 | 
					extern rk_mat4 rk_view;
 | 
				
			||||||
 | 
					extern rk_mat4 rk_view_km; //TODO: remove from engine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern float rk_projection_hfov;
 | 
				
			||||||
 | 
					extern float rk_projection_ratio;
 | 
				
			||||||
 | 
					extern float rk_projection_near;
 | 
				
			||||||
 | 
					extern float rk_projection_far;
 | 
				
			||||||
 | 
					extern rk_mat4 rk_projection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_window_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_shader_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_input_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_texture_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_triangles_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_vertices_t;
 | 
				
			||||||
 | 
					typedef rk_handle_t rk_batch_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RK_FLAG(bit) (1 << (bit))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_input_mode : rk_uint {
 | 
				
			||||||
 | 
					    RK_INPUT_IDENTITY = 0,
 | 
				
			||||||
 | 
					    RK_INPUT_VIEW_POSITION = 1,
 | 
				
			||||||
 | 
					    RK_INPUT_VIEW_ORIENTATION = 2
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_texture_format : rk_uint {
 | 
				
			||||||
 | 
					    RK_TEXTURE_FORMAT_SRGB8_A8 = 0,
 | 
				
			||||||
 | 
					    RK_TEXTURE_FORMAT_RGBA8 = 1,
 | 
				
			||||||
 | 
					    RK_TEXTURE_FORMAT_RGB10_A2 = 2,
 | 
				
			||||||
 | 
					    RK_TEXTURE_FORMAT_32F = 3
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_texture_flags : rk_uint {
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_3D = RK_FLAG(0),
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_MIPMAPS = RK_FLAG(1),
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_MIN_NEAREST = 0,
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_MIN_LINEAR = RK_FLAG(2),
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_MAG_NEAREST = 0,
 | 
				
			||||||
 | 
					    RK_TEXTURE_FLAG_MAG_LINEAR = RK_FLAG(3),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_vertex_format : rk_ubyte {
 | 
				
			||||||
 | 
					    RK_VERTEX_FORMAT_END = 0,
 | 
				
			||||||
 | 
					    RK_VERTEX_FORMAT_VEC2_FLOAT = 1,
 | 
				
			||||||
 | 
					    RK_VERTEX_FORMAT_VEC2_USHORT = 2,
 | 
				
			||||||
 | 
					    RK_VERTEX_FORMAT_VEC3_FLOAT = 3,
 | 
				
			||||||
 | 
					    RK_VERTEX_FORMAT_VEC3_INT10 = 4,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_instance_flags : rk_ubyte {
 | 
				
			||||||
 | 
					    RK_INSTANCE_FLAG_SPAWNED = RK_FLAG(0),
 | 
				
			||||||
 | 
					    RK_INSTANCE_FLAG_VISIBLE = RK_FLAG(1)
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum : rk_ubyte { RK_INSTANCE_FLAGS_SPAWNED_VISIBLE = RK_INSTANCE_FLAG_SPAWNED | RK_INSTANCE_FLAG_VISIBLE };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum : rk_uint { RK_BATCH_MAX_SIZE = 65536 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_batch_translation_format : rk_uint {
 | 
				
			||||||
 | 
					    RK_BATCH_TRANSLATION_FORMAT_FLOAT = 0,
 | 
				
			||||||
 | 
					    RK_BATCH_TRANSLATION_FORMAT_SHORT = 1
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rk_batch_orientation_format : rk_uint {
 | 
				
			||||||
 | 
					    RK_BATCH_ORIENTATION_FORMAT_NONE = 0,
 | 
				
			||||||
 | 
					    RK_BATCH_ORIENTATION_FORMAT_FLOAT = 1,
 | 
				
			||||||
 | 
					    RK_BATCH_ORIENTATION_FORMAT_INT10 = 2
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					union rk_mesh {
 | 
				
			||||||
 | 
					    rk_uint packed;
 | 
				
			||||||
 | 
					    struct {
 | 
				
			||||||
 | 
					        rk_ushort offset;
 | 
				
			||||||
 | 
					        rk_ushort count;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_window_t rk_initialize(
 | 
				
			||||||
 | 
					    char const * name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_shader_t rk_load_shader(
 | 
				
			||||||
 | 
					    char const * name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_select_shader(
 | 
				
			||||||
 | 
					    rk_shader_t _shader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_input_t rk_resolve_input(
 | 
				
			||||||
 | 
					    char const * name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_set_input_float(
 | 
				
			||||||
 | 
					    rk_input_t input,
 | 
				
			||||||
 | 
					    float value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_set_input_vec3(
 | 
				
			||||||
 | 
					    rk_input_t input,
 | 
				
			||||||
 | 
					    rk_vec3 const & value,
 | 
				
			||||||
 | 
					    rk_input_mode mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_texture_t rk_create_texture(
 | 
				
			||||||
 | 
					    rk_uint slot,
 | 
				
			||||||
 | 
					    char const * input,
 | 
				
			||||||
 | 
					    rk_texture_format format,
 | 
				
			||||||
 | 
					    rk_uint width,
 | 
				
			||||||
 | 
					    rk_uint height,
 | 
				
			||||||
 | 
					    rk_uint nlevels,
 | 
				
			||||||
 | 
					    rk_texture_flags flags,
 | 
				
			||||||
 | 
					    void const * pixels);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_triangles_t rk_create_triangles(
 | 
				
			||||||
 | 
					    rk_uint nvertices,
 | 
				
			||||||
 | 
					    rk_vec3 const * vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_vertices_t rk_create_vertices(
 | 
				
			||||||
 | 
					    rk_vertex_format const * format,
 | 
				
			||||||
 | 
					    rk_uint nvertices,
 | 
				
			||||||
 | 
					    void const * vertices,
 | 
				
			||||||
 | 
					    rk_uint nindices,
 | 
				
			||||||
 | 
					    rk_ushort const * indices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT rk_batch_t rk_create_batch(
 | 
				
			||||||
 | 
					    rk_uint max_size,
 | 
				
			||||||
 | 
					    rk_batch_translation_format translation_format,
 | 
				
			||||||
 | 
					    rk_batch_orientation_format orientation_format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: export math function and take a projection matrix instead of its parameters
 | 
				
			||||||
 | 
					RK_EXPORT void rk_set_projection(
 | 
				
			||||||
 | 
					    float hfov,
 | 
				
			||||||
 | 
					    float ratio,
 | 
				
			||||||
 | 
					    float near,
 | 
				
			||||||
 | 
					    float far);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: export math function and take a view matrix instead of its parameters
 | 
				
			||||||
 | 
					RK_EXPORT void rk_set_view(
 | 
				
			||||||
 | 
					    rk_vec3 const & position,
 | 
				
			||||||
 | 
					    rk_vec3 const & lookat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_begin_frame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_select_texture(
 | 
				
			||||||
 | 
					    rk_texture_t texture);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_draw_triangles(
 | 
				
			||||||
 | 
					    rk_triangles_t triangles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_select_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_draw_batch(
 | 
				
			||||||
 | 
					    rk_batch_t batch,
 | 
				
			||||||
 | 
					    rk_uint size,
 | 
				
			||||||
 | 
					    rk_instance_flags const * flags,
 | 
				
			||||||
 | 
					    rk_ushort const * texlevels,
 | 
				
			||||||
 | 
					    rk_mesh const * meshes,
 | 
				
			||||||
 | 
					    rk_vec3 const * translations,
 | 
				
			||||||
 | 
					    rk_vec3 const * orientations);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_unselect_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_unselect_texture(
 | 
				
			||||||
 | 
					    rk_texture_t texture);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_unselect_shader(
 | 
				
			||||||
 | 
					    rk_shader_t shader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_end_frame();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_batch(
 | 
				
			||||||
 | 
					    rk_batch_t batch);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_triangles(
 | 
				
			||||||
 | 
					    rk_triangles_t triangles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_vertices(
 | 
				
			||||||
 | 
					    rk_vertices_t vertices);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_texture(
 | 
				
			||||||
 | 
					    rk_texture_t texture);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_destroy_shader(
 | 
				
			||||||
 | 
					    rk_shader_t shader);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RK_EXPORT void rk_terminate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _RK_ENGINE_RENDER_H
 | 
				
			||||||
							
								
								
									
										36
									
								
								cpp/types.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								cpp/types.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					// 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 <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//TODO: use glm types
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _RK_ENGINE_TYPES_H
 | 
				
			||||||
 | 
					#define _RK_ENGINE_TYPES_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cstdbool>
 | 
				
			||||||
 | 
					#include <cstdint>
 | 
				
			||||||
 | 
					#include <cstddef>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RK_EXPORT extern "C"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef void * rk_handle_t;
 | 
				
			||||||
 | 
					typedef uint8_t rk_ubyte;
 | 
				
			||||||
 | 
					typedef int16_t rk_short;
 | 
				
			||||||
 | 
					typedef uint16_t rk_ushort;
 | 
				
			||||||
 | 
					typedef int32_t rk_int;
 | 
				
			||||||
 | 
					typedef uint32_t rk_uint;
 | 
				
			||||||
 | 
					typedef int64_t rk_long;
 | 
				
			||||||
 | 
					typedef uint64_t rk_ulong;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _RK_ENGINE_TYPES_H
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								docs/batch.odg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/batch.odg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								docs/batch.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/batch.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								docs/batch.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/batch.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 99 KiB  | 
		Reference in New Issue
	
	Block a user