YoonaAI commited on
Commit
ddd54d7
·
1 Parent(s): bf91b23

Upload 9 files

Browse files
lib/renderer/gl/cam_render.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
5
+ # holder of all proprietary rights on this computer program.
6
+ # You can only use this computer program if you have closed
7
+ # a license agreement with MPG or you get the right to use the computer
8
+ # program from someone who is authorized to grant you that right.
9
+ # Any use of the computer program without a valid license is prohibited and
10
+ # liable to prosecution.
11
+ #
12
+ # Copyright©2019 Max-Planck-Gesellschaft zur Förderung
13
+ # der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
14
+ # for Intelligent Systems. All rights reserved.
15
+ #
16
+ # Contact: [email protected]
17
+
18
+ from .render import Render
19
+
20
+ GLUT = None
21
+
22
+
23
+ class CamRender(Render):
24
+ def __init__(self,
25
+ width=1600,
26
+ height=1200,
27
+ name='Cam Renderer',
28
+ program_files=['simple.fs', 'simple.vs'],
29
+ color_size=1,
30
+ ms_rate=1,
31
+ egl=False):
32
+ Render.__init__(self,
33
+ width,
34
+ height,
35
+ name,
36
+ program_files,
37
+ color_size,
38
+ ms_rate=ms_rate,
39
+ egl=egl)
40
+ self.camera = None
41
+
42
+ if not egl:
43
+ global GLUT
44
+ import OpenGL.GLUT as GLUT
45
+ GLUT.glutDisplayFunc(self.display)
46
+ GLUT.glutKeyboardFunc(self.keyboard)
47
+
48
+ def set_camera(self, camera):
49
+ self.camera = camera
50
+ self.projection_matrix, self.model_view_matrix = camera.get_gl_matrix()
51
+
52
+ def keyboard(self, key, x, y):
53
+ # up
54
+ eps = 1
55
+ # print(key)
56
+ if key == b'w':
57
+ self.camera.center += eps * self.camera.direction
58
+ elif key == b's':
59
+ self.camera.center -= eps * self.camera.direction
60
+ if key == b'a':
61
+ self.camera.center -= eps * self.camera.right
62
+ elif key == b'd':
63
+ self.camera.center += eps * self.camera.right
64
+ if key == b' ':
65
+ self.camera.center += eps * self.camera.up
66
+ elif key == b'x':
67
+ self.camera.center -= eps * self.camera.up
68
+ elif key == b'i':
69
+ self.camera.near += 0.1 * eps
70
+ self.camera.far += 0.1 * eps
71
+ elif key == b'o':
72
+ self.camera.near -= 0.1 * eps
73
+ self.camera.far -= 0.1 * eps
74
+
75
+ self.projection_matrix, self.model_view_matrix = self.camera.get_gl_matrix(
76
+ )
77
+
78
+ def show(self):
79
+ if GLUT is not None:
80
+ GLUT.glutMainLoop()
lib/renderer/gl/color_render.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2019 Shunsuke Saito, Zeng Huang, and Ryota Natsume
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+ import numpy as np
25
+ import random
26
+
27
+ from .framework import *
28
+ from .cam_render import CamRender
29
+
30
+
31
+ class ColorRender(CamRender):
32
+ def __init__(self, width=1600, height=1200, name='Color Renderer', egl=False):
33
+ program_files = ['color.vs', 'color.fs']
34
+ CamRender.__init__(self,
35
+ width,
36
+ height,
37
+ name,
38
+ program_files=program_files,
39
+ color_size=3, egl=egl)
40
+
41
+ # WARNING: this differs from vertex_buffer and vertex_data in Render
42
+ self.vert_buffer = {}
43
+ self.vert_data = {}
44
+
45
+ # normal
46
+ self.norm_buffer = {}
47
+ self.norm_data = {}
48
+
49
+ self.color_buffer = {}
50
+ self.color_data = {}
51
+
52
+ self.vertex_dim = {}
53
+ self.n_vertices = {}
54
+
55
+ self.rot_mat_unif = glGetUniformLocation(self.program, 'RotMat')
56
+ self.rot_matrix = np.eye(3)
57
+
58
+ self.norm_mat_unif = glGetUniformLocation(self.program, 'NormMat')
59
+ self.normalize_matrix = np.eye(4)
60
+
61
+ def set_norm_mat(self, scale, center):
62
+ N = np.eye(4)
63
+ N[:3, :3] = scale * np.eye(3)
64
+ N[:3, 3] = -scale * center
65
+
66
+ self.normalize_matrix = N
67
+
68
+ def set_mesh(self, vertices, faces, color, normals, mat_name='all'):
69
+
70
+ self.vert_data[mat_name] = vertices[faces.reshape([-1])]
71
+ self.n_vertices[mat_name] = self.vert_data[mat_name].shape[0]
72
+ self.vertex_dim[mat_name] = self.vert_data[mat_name].shape[1]
73
+ self.color_data[mat_name] = color[faces.reshape([-1])]
74
+ self.norm_data[mat_name] = normals[faces.reshape([-1])]
75
+
76
+ if mat_name not in self.vert_buffer.keys():
77
+ self.vert_buffer[mat_name] = glGenBuffers(1)
78
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_buffer[mat_name])
79
+ glBufferData(GL_ARRAY_BUFFER, self.vert_data[mat_name], GL_STATIC_DRAW)
80
+
81
+ if mat_name not in self.color_buffer.keys():
82
+ self.color_buffer[mat_name] = glGenBuffers(1)
83
+ glBindBuffer(GL_ARRAY_BUFFER, self.color_buffer[mat_name])
84
+ glBufferData(GL_ARRAY_BUFFER, self.color_data[mat_name],
85
+ GL_STATIC_DRAW)
86
+
87
+ if mat_name not in self.norm_buffer.keys():
88
+ self.norm_buffer[mat_name] = glGenBuffers(1)
89
+ glBindBuffer(GL_ARRAY_BUFFER, self.norm_buffer[mat_name])
90
+ glBufferData(GL_ARRAY_BUFFER, self.norm_data[mat_name], GL_STATIC_DRAW)
91
+
92
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
93
+
94
+ def cleanup(self):
95
+
96
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
97
+
98
+ for key in self.vert_data:
99
+ glDeleteBuffers(1, [self.vert_buffer[key]])
100
+ glDeleteBuffers(1, [self.color_buffer[key]])
101
+ glDeleteBuffers(1, [self.norm_buffer[key]])
102
+
103
+ self.norm_buffer = {}
104
+ self.norm_data = {}
105
+
106
+ self.vert_buffer = {}
107
+ self.vert_data = {}
108
+
109
+ self.color_buffer = {}
110
+ self.color_data = {}
111
+
112
+ self.render_texture_mat = {}
113
+
114
+ self.vertex_dim = {}
115
+ self.n_vertices = {}
116
+
117
+ def draw(self):
118
+ self.draw_init()
119
+
120
+ glEnable(GL_MULTISAMPLE)
121
+
122
+ glUseProgram(self.program)
123
+ glUniformMatrix4fv(self.norm_mat_unif, 1, GL_FALSE,
124
+ self.normalize_matrix.transpose())
125
+ glUniformMatrix4fv(self.model_mat_unif, 1, GL_FALSE,
126
+ self.model_view_matrix.transpose())
127
+ glUniformMatrix4fv(self.persp_mat_unif, 1, GL_FALSE,
128
+ self.projection_matrix.transpose())
129
+ glUniformMatrix3fv(self.rot_mat_unif, 1, GL_FALSE,
130
+ self.rot_matrix.transpose())
131
+
132
+ for mat in self.vert_buffer:
133
+
134
+ # Handle vertex buffer
135
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_buffer[mat])
136
+ glEnableVertexAttribArray(0)
137
+ glVertexAttribPointer(0, self.vertex_dim[mat], GL_DOUBLE, GL_FALSE,
138
+ 0, None)
139
+
140
+ # Handle color buffer
141
+ glBindBuffer(GL_ARRAY_BUFFER, self.color_buffer[mat])
142
+ glEnableVertexAttribArray(1)
143
+ glVertexAttribPointer(1, 3, GL_DOUBLE, GL_FALSE, 0, None)
144
+
145
+ # Handle normal buffer
146
+ glBindBuffer(GL_ARRAY_BUFFER, self.norm_buffer[mat])
147
+ glEnableVertexAttribArray(2)
148
+ glVertexAttribPointer(2, 3, GL_DOUBLE, GL_FALSE, 0, None)
149
+
150
+ glDrawArrays(GL_TRIANGLES, 0, self.n_vertices[mat])
151
+
152
+ glDisableVertexAttribArray(2)
153
+ glDisableVertexAttribArray(1)
154
+ glDisableVertexAttribArray(0)
155
+
156
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
157
+
158
+ glUseProgram(0)
159
+
160
+ glDisable(GL_MULTISAMPLE)
161
+
162
+ self.draw_end()
lib/renderer/gl/framework.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Mario Rosasco, 2016
2
+ # adapted from framework.cpp, Copyright (C) 2010-2012 by Jason L. McKesson
3
+ # This file is licensed under the MIT License.
4
+ #
5
+ # NB: Unlike in the framework.cpp organization, the main loop is contained
6
+ # in the tutorial files, not in this framework file. Additionally, a copy of
7
+ # this module file must exist in the same directory as the tutorial files
8
+ # to be imported properly.
9
+
10
+ import os
11
+ from OpenGL.GL import *
12
+
13
+
14
+ # Function that creates and compiles shaders according to the given type (a GL enum value) and
15
+ # shader program (a file containing a GLSL program).
16
+ def loadShader(shaderType, shaderFile):
17
+ # check if file exists, get full path name
18
+ strFilename = findFileOrThrow(shaderFile)
19
+ shaderData = None
20
+ with open(strFilename, 'r') as f:
21
+ shaderData = f.read()
22
+
23
+ shader = glCreateShader(shaderType)
24
+ glShaderSource(
25
+ shader,
26
+ shaderData) # note that this is a simpler function call than in C
27
+
28
+ # This shader compilation is more explicit than the one used in
29
+ # framework.cpp, which relies on a glutil wrapper function.
30
+ # This is made explicit here mainly to decrease dependence on pyOpenGL
31
+ # utilities and wrappers, which docs caution may change in future versions.
32
+ glCompileShader(shader)
33
+
34
+ status = glGetShaderiv(shader, GL_COMPILE_STATUS)
35
+ if status == GL_FALSE:
36
+ # Note that getting the error log is much simpler in Python than in C/C++
37
+ # and does not require explicit handling of the string buffer
38
+ strInfoLog = glGetShaderInfoLog(shader)
39
+ strShaderType = ""
40
+ if shaderType is GL_VERTEX_SHADER:
41
+ strShaderType = "vertex"
42
+ elif shaderType is GL_GEOMETRY_SHADER:
43
+ strShaderType = "geometry"
44
+ elif shaderType is GL_FRAGMENT_SHADER:
45
+ strShaderType = "fragment"
46
+
47
+ print("Compilation failure for " + strShaderType + " shader:\n" +
48
+ str(strInfoLog))
49
+
50
+ return shader
51
+
52
+
53
+ # Function that accepts a list of shaders, compiles them, and returns a handle to the compiled program
54
+ def createProgram(shaderList):
55
+ program = glCreateProgram()
56
+
57
+ for shader in shaderList:
58
+ glAttachShader(program, shader)
59
+
60
+ glLinkProgram(program)
61
+
62
+ status = glGetProgramiv(program, GL_LINK_STATUS)
63
+ if status == GL_FALSE:
64
+ # Note that getting the error log is much simpler in Python than in C/C++
65
+ # and does not require explicit handling of the string buffer
66
+ strInfoLog = glGetProgramInfoLog(program)
67
+ print("Linker failure: \n" + str(strInfoLog))
68
+
69
+ for shader in shaderList:
70
+ glDetachShader(program, shader)
71
+
72
+ return program
73
+
74
+
75
+ # Helper function to locate and open the target file (passed in as a string).
76
+ # Returns the full path to the file as a string.
77
+ def findFileOrThrow(strBasename):
78
+ # Keep constant names in C-style convention, for readability
79
+ # when comparing to C(/C++) code.
80
+ if os.path.isfile(strBasename):
81
+ return strBasename
82
+
83
+ LOCAL_FILE_DIR = "data" + os.sep
84
+ GLOBAL_FILE_DIR = os.path.dirname(
85
+ os.path.abspath(__file__)) + os.sep + "data" + os.sep
86
+
87
+ strFilename = LOCAL_FILE_DIR + strBasename
88
+ if os.path.isfile(strFilename):
89
+ return strFilename
90
+
91
+ strFilename = GLOBAL_FILE_DIR + strBasename
92
+ if os.path.isfile(strFilename):
93
+ return strFilename
94
+
95
+ raise IOError('Could not find target file ' + strBasename)
lib/renderer/gl/glcontext.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Headless GPU-accelerated OpenGL context creation on Google Colaboratory.
2
+
3
+ Typical usage:
4
+
5
+ # Optional PyOpenGL configuratiopn can be done here.
6
+ # import OpenGL
7
+ # OpenGL.ERROR_CHECKING = True
8
+
9
+ # 'glcontext' must be imported before any OpenGL.* API.
10
+ from lucid.misc.gl.glcontext import create_opengl_context
11
+
12
+ # Now it's safe to import OpenGL and EGL functions
13
+ import OpenGL.GL as gl
14
+
15
+ # create_opengl_context() creates a GL context that is attached to an
16
+ # offscreen surface of the specified size. Note that rendering to buffers
17
+ # of other sizes and formats is still possible with OpenGL Framebuffers.
18
+ #
19
+ # Users are expected to directly use the EGL API in case more advanced
20
+ # context management is required.
21
+ width, height = 640, 480
22
+ create_opengl_context((width, height))
23
+
24
+ # OpenGL context is available here.
25
+
26
+ """
27
+
28
+ from __future__ import print_function
29
+
30
+ # pylint: disable=unused-import,g-import-not-at-top,g-statement-before-imports
31
+
32
+ try:
33
+ import OpenGL
34
+ except:
35
+ print('This module depends on PyOpenGL.')
36
+ print('Please run "\033[1m!pip install -q pyopengl\033[0m" '
37
+ 'prior importing this module.')
38
+ raise
39
+
40
+ import ctypes
41
+ from ctypes import pointer, util
42
+ import os
43
+
44
+ os.environ['PYOPENGL_PLATFORM'] = 'egl'
45
+
46
+ # OpenGL loading workaround.
47
+ #
48
+ # * PyOpenGL tries to load libGL, but we need libOpenGL, see [1,2].
49
+ # This could have been solved by a symlink libGL->libOpenGL, but:
50
+ #
51
+ # * Python 2.7 can't find libGL and linEGL due to a bug (see [3])
52
+ # in ctypes.util, that was only wixed in Python 3.6.
53
+ #
54
+ # So, the only solution I've found is to monkeypatch ctypes.util
55
+ # [1] https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/
56
+ # [2] https://devblogs.nvidia.com/linking-opengl-server-side-rendering/
57
+ # [3] https://bugs.python.org/issue9998
58
+ _find_library_old = ctypes.util.find_library
59
+ try:
60
+
61
+ def _find_library_new(name):
62
+ return {
63
+ 'GL': 'libOpenGL.so',
64
+ 'EGL': 'libEGL.so',
65
+ }.get(name, _find_library_old(name))
66
+
67
+ util.find_library = _find_library_new
68
+ import OpenGL.GL as gl
69
+ import OpenGL.EGL as egl
70
+ except:
71
+ print('Unable to load OpenGL libraries. '
72
+ 'Make sure you use GPU-enabled backend.')
73
+ print('Press "Runtime->Change runtime type" and set '
74
+ '"Hardware accelerator" to GPU.')
75
+ raise
76
+ finally:
77
+ util.find_library = _find_library_old
78
+
79
+
80
+ def create_opengl_context(surface_size=(640, 480)):
81
+ """Create offscreen OpenGL context and make it current.
82
+
83
+ Users are expected to directly use EGL API in case more advanced
84
+ context management is required.
85
+
86
+ Args:
87
+ surface_size: (width, height), size of the offscreen rendering surface.
88
+ """
89
+ egl_display = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY)
90
+
91
+ major, minor = egl.EGLint(), egl.EGLint()
92
+ egl.eglInitialize(egl_display, pointer(major), pointer(minor))
93
+
94
+ config_attribs = [
95
+ egl.EGL_SURFACE_TYPE, egl.EGL_PBUFFER_BIT, egl.EGL_BLUE_SIZE, 8,
96
+ egl.EGL_GREEN_SIZE, 8, egl.EGL_RED_SIZE, 8, egl.EGL_DEPTH_SIZE, 24,
97
+ egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_BIT, egl.EGL_NONE
98
+ ]
99
+ config_attribs = (egl.EGLint * len(config_attribs))(*config_attribs)
100
+
101
+ num_configs = egl.EGLint()
102
+ egl_cfg = egl.EGLConfig()
103
+ egl.eglChooseConfig(egl_display, config_attribs, pointer(egl_cfg), 1,
104
+ pointer(num_configs))
105
+
106
+ width, height = surface_size
107
+ pbuffer_attribs = [
108
+ egl.EGL_WIDTH,
109
+ width,
110
+ egl.EGL_HEIGHT,
111
+ height,
112
+ egl.EGL_NONE,
113
+ ]
114
+ pbuffer_attribs = (egl.EGLint * len(pbuffer_attribs))(*pbuffer_attribs)
115
+ egl_surf = egl.eglCreatePbufferSurface(egl_display, egl_cfg,
116
+ pbuffer_attribs)
117
+
118
+ egl.eglBindAPI(egl.EGL_OPENGL_API)
119
+
120
+ context_attribs = None
121
+ # context_attribs = [
122
+ # egl.EGL_CONTEXT_MAJOR_VERSION,
123
+ # 4,
124
+ # egl.EGL_CONTEXT_MINOR_VERSION,
125
+ # 1,
126
+ # egl.EGL_NONE,
127
+ # ]
128
+
129
+ egl_context = egl.eglCreateContext(egl_display, egl_cfg,
130
+ egl.EGL_NO_CONTEXT, context_attribs)
131
+ egl.eglMakeCurrent(egl_display, egl_surf, egl_surf, egl_context)
132
+
133
+ buffer_type = egl.EGLint()
134
+ out = egl.eglQueryContext(egl_display, egl_context,
135
+ egl.EGL_CONTEXT_CLIENT_VERSION, buffer_type)
136
+ # print(buffer_type)
lib/renderer/gl/init_gl.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ _glut_window = None
2
+ _context_inited = None
3
+
4
+
5
+ def initialize_GL_context(width=512, height=512, egl=False):
6
+ '''
7
+ default context uses GLUT
8
+ '''
9
+ if not egl:
10
+ import OpenGL.GLUT as GLUT
11
+ display_mode = GLUT.GLUT_DOUBLE | GLUT.GLUT_RGB | GLUT.GLUT_DEPTH
12
+ global _glut_window
13
+ if _glut_window is None:
14
+ GLUT.glutInit()
15
+ GLUT.glutInitDisplayMode(display_mode)
16
+ GLUT.glutInitWindowSize(width, height)
17
+ GLUT.glutInitWindowPosition(0, 0)
18
+ _glut_window = GLUT.glutCreateWindow("My Render.")
19
+ else:
20
+ from .glcontext import create_opengl_context
21
+ global _context_inited
22
+ if _context_inited is None:
23
+ create_opengl_context((width, height))
24
+ _context_inited = True
lib/renderer/gl/norm_render.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2019 Shunsuke Saito, Zeng Huang, and Ryota Natsume
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+ from OpenGL.GLUT import *
25
+
26
+ from .render2 import Render
27
+
28
+
29
+ class NormRender(Render):
30
+ def __init__(self,
31
+ width=1600,
32
+ height=1200,
33
+ name='Cam Renderer',
34
+ program_files=['simple.fs', 'simple.vs'],
35
+ color_size=1,
36
+ ms_rate=1):
37
+ Render.__init__(self, width, height, name, program_files, color_size,
38
+ ms_rate)
39
+ self.camera = None
40
+
41
+ glutDisplayFunc(self.display)
42
+ glutKeyboardFunc(self.keyboard)
43
+
44
+ def set_camera(self, camera):
45
+ self.camera = camera
46
+ self.projection_matrix, self.model_view_matrix = camera.get_gl_matrix()
47
+
48
+ def set_matrices(self, projection, modelview):
49
+ self.projection_matrix = projection
50
+ self.model_view_matrix = modelview
51
+
52
+ def keyboard(self, key, x, y):
53
+ # up
54
+ eps = 1
55
+ # print(key)
56
+ if key == b'w':
57
+ self.camera.center += eps * self.camera.direction
58
+ elif key == b's':
59
+ self.camera.center -= eps * self.camera.direction
60
+ if key == b'a':
61
+ self.camera.center -= eps * self.camera.right
62
+ elif key == b'd':
63
+ self.camera.center += eps * self.camera.right
64
+ if key == b' ':
65
+ self.camera.center += eps * self.camera.up
66
+ elif key == b'x':
67
+ self.camera.center -= eps * self.camera.up
68
+ elif key == b'i':
69
+ self.camera.near += 0.1 * eps
70
+ self.camera.far += 0.1 * eps
71
+ elif key == b'o':
72
+ self.camera.near -= 0.1 * eps
73
+ self.camera.far -= 0.1 * eps
74
+
75
+ self.projection_matrix, self.model_view_matrix = self.camera.get_gl_matrix(
76
+ )
77
+
78
+ def show(self):
79
+ glutMainLoop()
lib/renderer/gl/prt_render.py ADDED
@@ -0,0 +1,450 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
5
+ # holder of all proprietary rights on this computer program.
6
+ # You can only use this computer program if you have closed
7
+ # a license agreement with MPG or you get the right to use the computer
8
+ # program from someone who is authorized to grant you that right.
9
+ # Any use of the computer program without a valid license is prohibited and
10
+ # liable to prosecution.
11
+ #
12
+ # Copyright©2019 Max-Planck-Gesellschaft zur Förderung
13
+ # der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
14
+ # for Intelligent Systems. All rights reserved.
15
+ #
16
+ # Contact: [email protected]
17
+
18
+ import numpy as np
19
+ import random
20
+
21
+ from .framework import *
22
+ from .cam_render import CamRender
23
+
24
+
25
+ class PRTRender(CamRender):
26
+ def __init__(self,
27
+ width=1600,
28
+ height=1200,
29
+ name='PRT Renderer',
30
+ uv_mode=False,
31
+ ms_rate=1,
32
+ egl=False):
33
+ program_files = ['prt.vs', 'prt.fs'
34
+ ] if not uv_mode else ['prt_uv.vs', 'prt_uv.fs']
35
+ CamRender.__init__(self,
36
+ width,
37
+ height,
38
+ name,
39
+ program_files=program_files,
40
+ color_size=8,
41
+ ms_rate=ms_rate,
42
+ egl=egl)
43
+
44
+ # WARNING: this differs from vertex_buffer and vertex_data in Render
45
+ self.vert_buffer = {}
46
+ self.vert_data = {}
47
+
48
+ self.vert_label_buffer = {}
49
+ self.vert_label_data = {}
50
+
51
+ self.norm_buffer = {}
52
+ self.norm_data = {}
53
+
54
+ self.tan_buffer = {}
55
+ self.tan_data = {}
56
+
57
+ self.btan_buffer = {}
58
+ self.btan_data = {}
59
+
60
+ self.prt1_buffer = {}
61
+ self.prt1_data = {}
62
+
63
+ self.prt2_buffer = {}
64
+ self.prt2_data = {}
65
+
66
+ self.prt3_buffer = {}
67
+ self.prt3_data = {}
68
+
69
+ self.uv_buffer = {}
70
+ self.uv_data = {}
71
+
72
+ self.render_texture_mat = {}
73
+
74
+ self.vertex_dim = {}
75
+ self.n_vertices = {}
76
+ self.label_dim = {}
77
+
78
+ self.norm_mat_unif = glGetUniformLocation(self.program, 'NormMat')
79
+ self.normalize_matrix = np.eye(4)
80
+
81
+ self.shcoeff_unif = glGetUniformLocation(self.program, 'SHCoeffs')
82
+ self.shcoeffs = np.zeros((9, 3))
83
+ self.shcoeffs[0, :] = 1.0
84
+ #self.shcoeffs[1:,:] = np.random.rand(8,3)
85
+
86
+ self.hasAlbedoUnif = glGetUniformLocation(self.program, 'hasAlbedoMap')
87
+ self.hasNormalUnif = glGetUniformLocation(self.program, 'hasNormalMap')
88
+
89
+ self.analyticUnif = glGetUniformLocation(self.program, 'analytic')
90
+ self.analytic = False
91
+
92
+ self.rot_mat_unif = glGetUniformLocation(self.program, 'RotMat')
93
+ self.rot_matrix = np.eye(3)
94
+
95
+ def set_texture(self, mat_name, smplr_name, texture):
96
+ # texture_image: H x W x 3
97
+ width = texture.shape[1]
98
+ height = texture.shape[0]
99
+ texture = np.flip(texture, 0)
100
+ img_data = np.fromstring(texture.tostring(), np.uint8)
101
+
102
+ if mat_name not in self.render_texture_mat:
103
+ self.render_texture_mat[mat_name] = {}
104
+ if smplr_name in self.render_texture_mat[mat_name].keys():
105
+ glDeleteTextures([self.render_texture_mat[mat_name][smplr_name]])
106
+ del self.render_texture_mat[mat_name][smplr_name]
107
+
108
+ self.render_texture_mat[mat_name][smplr_name] = glGenTextures(1)
109
+ glActiveTexture(GL_TEXTURE0)
110
+
111
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
112
+ glBindTexture(GL_TEXTURE_2D,
113
+ self.render_texture_mat[mat_name][smplr_name])
114
+
115
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
116
+ GL_UNSIGNED_BYTE, img_data)
117
+
118
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3)
119
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
120
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
121
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
122
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
123
+ GL_LINEAR_MIPMAP_LINEAR)
124
+
125
+ glGenerateMipmap(GL_TEXTURE_2D)
126
+
127
+ def set_albedo(self, texture_image, mat_name='all'):
128
+ self.set_texture(mat_name, 'AlbedoMap', texture_image)
129
+
130
+ def set_normal_map(self, texture_image, mat_name='all'):
131
+ self.set_texture(mat_name, 'NormalMap', texture_image)
132
+
133
+ def set_mesh(self,
134
+ vertices,
135
+ faces,
136
+ norms,
137
+ faces_nml,
138
+ uvs,
139
+ faces_uvs,
140
+ prt,
141
+ faces_prt,
142
+ tans,
143
+ bitans,
144
+ verts_label=None,
145
+ mat_name='all'):
146
+
147
+ self.vert_data[mat_name] = vertices[faces.reshape([-1])]
148
+ self.vert_label_data[mat_name] = verts_label[faces.reshape([-1])]
149
+ self.n_vertices[mat_name] = self.vert_data[mat_name].shape[0]
150
+ self.vertex_dim[mat_name] = self.vert_data[mat_name].shape[1]
151
+ self.label_dim[mat_name] = self.vert_label_data[mat_name].shape[1]
152
+
153
+ if mat_name not in self.vert_buffer.keys():
154
+ self.vert_buffer[mat_name] = glGenBuffers(1)
155
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_buffer[mat_name])
156
+ glBufferData(GL_ARRAY_BUFFER, self.vert_data[mat_name], GL_STATIC_DRAW)
157
+
158
+ if mat_name not in self.vert_label_buffer.keys():
159
+ self.vert_label_buffer[mat_name] = glGenBuffers(1)
160
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_label_buffer[mat_name])
161
+ glBufferData(GL_ARRAY_BUFFER, self.vert_label_data[mat_name],
162
+ GL_STATIC_DRAW)
163
+
164
+ self.uv_data[mat_name] = uvs[faces_uvs.reshape([-1])]
165
+ if mat_name not in self.uv_buffer.keys():
166
+ self.uv_buffer[mat_name] = glGenBuffers(1)
167
+ glBindBuffer(GL_ARRAY_BUFFER, self.uv_buffer[mat_name])
168
+ glBufferData(GL_ARRAY_BUFFER, self.uv_data[mat_name], GL_STATIC_DRAW)
169
+
170
+ self.norm_data[mat_name] = norms[faces_nml.reshape([-1])]
171
+ if mat_name not in self.norm_buffer.keys():
172
+ self.norm_buffer[mat_name] = glGenBuffers(1)
173
+ glBindBuffer(GL_ARRAY_BUFFER, self.norm_buffer[mat_name])
174
+ glBufferData(GL_ARRAY_BUFFER, self.norm_data[mat_name], GL_STATIC_DRAW)
175
+
176
+ self.tan_data[mat_name] = tans[faces_nml.reshape([-1])]
177
+ if mat_name not in self.tan_buffer.keys():
178
+ self.tan_buffer[mat_name] = glGenBuffers(1)
179
+ glBindBuffer(GL_ARRAY_BUFFER, self.tan_buffer[mat_name])
180
+ glBufferData(GL_ARRAY_BUFFER, self.tan_data[mat_name], GL_STATIC_DRAW)
181
+
182
+ self.btan_data[mat_name] = bitans[faces_nml.reshape([-1])]
183
+ if mat_name not in self.btan_buffer.keys():
184
+ self.btan_buffer[mat_name] = glGenBuffers(1)
185
+ glBindBuffer(GL_ARRAY_BUFFER, self.btan_buffer[mat_name])
186
+ glBufferData(GL_ARRAY_BUFFER, self.btan_data[mat_name], GL_STATIC_DRAW)
187
+
188
+ self.prt1_data[mat_name] = prt[faces_prt.reshape([-1])][:, :3]
189
+ self.prt2_data[mat_name] = prt[faces_prt.reshape([-1])][:, 3:6]
190
+ self.prt3_data[mat_name] = prt[faces_prt.reshape([-1])][:, 6:]
191
+
192
+ if mat_name not in self.prt1_buffer.keys():
193
+ self.prt1_buffer[mat_name] = glGenBuffers(1)
194
+ if mat_name not in self.prt2_buffer.keys():
195
+ self.prt2_buffer[mat_name] = glGenBuffers(1)
196
+ if mat_name not in self.prt3_buffer.keys():
197
+ self.prt3_buffer[mat_name] = glGenBuffers(1)
198
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt1_buffer[mat_name])
199
+ glBufferData(GL_ARRAY_BUFFER, self.prt1_data[mat_name], GL_STATIC_DRAW)
200
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt2_buffer[mat_name])
201
+ glBufferData(GL_ARRAY_BUFFER, self.prt2_data[mat_name], GL_STATIC_DRAW)
202
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt3_buffer[mat_name])
203
+ glBufferData(GL_ARRAY_BUFFER, self.prt3_data[mat_name], GL_STATIC_DRAW)
204
+
205
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
206
+
207
+ def set_mesh_mtl(self,
208
+ vertices,
209
+ faces,
210
+ norms,
211
+ faces_nml,
212
+ uvs,
213
+ faces_uvs,
214
+ tans,
215
+ bitans,
216
+ prt,
217
+ verts_label=None):
218
+ for key in faces:
219
+ self.vert_data[key] = vertices[faces[key].reshape([-1])]
220
+ self.vert_label_data[key] = verts_label[faces[key].reshape([-1])]
221
+ self.n_vertices[key] = self.vert_data[key].shape[0]
222
+ self.vertex_dim[key] = self.vert_data[key].shape[1]
223
+ self.label_dim[key] = self.vert_label_data[key].shape[1]
224
+
225
+ if key not in self.vert_buffer.keys():
226
+ self.vert_buffer[key] = glGenBuffers(1)
227
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_buffer[key])
228
+ glBufferData(GL_ARRAY_BUFFER, self.vert_data[key], GL_STATIC_DRAW)
229
+
230
+ if key not in self.vert_label_buffer.keys():
231
+ self.vert_label_buffer[key] = glGenBuffers(1)
232
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_label_buffer[key])
233
+ glBufferData(GL_ARRAY_BUFFER, self.vert_label_data[key],
234
+ GL_STATIC_DRAW)
235
+
236
+ self.uv_data[key] = uvs[faces_uvs[key].reshape([-1])]
237
+ if key not in self.uv_buffer.keys():
238
+ self.uv_buffer[key] = glGenBuffers(1)
239
+ glBindBuffer(GL_ARRAY_BUFFER, self.uv_buffer[key])
240
+ glBufferData(GL_ARRAY_BUFFER, self.uv_data[key], GL_STATIC_DRAW)
241
+
242
+ self.norm_data[key] = norms[faces_nml[key].reshape([-1])]
243
+ if key not in self.norm_buffer.keys():
244
+ self.norm_buffer[key] = glGenBuffers(1)
245
+ glBindBuffer(GL_ARRAY_BUFFER, self.norm_buffer[key])
246
+ glBufferData(GL_ARRAY_BUFFER, self.norm_data[key], GL_STATIC_DRAW)
247
+
248
+ self.tan_data[key] = tans[faces_nml[key].reshape([-1])]
249
+ if key not in self.tan_buffer.keys():
250
+ self.tan_buffer[key] = glGenBuffers(1)
251
+ glBindBuffer(GL_ARRAY_BUFFER, self.tan_buffer[key])
252
+ glBufferData(GL_ARRAY_BUFFER, self.tan_data[key], GL_STATIC_DRAW)
253
+
254
+ self.btan_data[key] = bitans[faces_nml[key].reshape([-1])]
255
+ if key not in self.btan_buffer.keys():
256
+ self.btan_buffer[key] = glGenBuffers(1)
257
+ glBindBuffer(GL_ARRAY_BUFFER, self.btan_buffer[key])
258
+ glBufferData(GL_ARRAY_BUFFER, self.btan_data[key], GL_STATIC_DRAW)
259
+
260
+ self.prt1_data[key] = prt[faces[key].reshape([-1])][:, :3]
261
+ self.prt2_data[key] = prt[faces[key].reshape([-1])][:, 3:6]
262
+ self.prt3_data[key] = prt[faces[key].reshape([-1])][:, 6:]
263
+
264
+ if key not in self.prt1_buffer.keys():
265
+ self.prt1_buffer[key] = glGenBuffers(1)
266
+ if key not in self.prt2_buffer.keys():
267
+ self.prt2_buffer[key] = glGenBuffers(1)
268
+ if key not in self.prt3_buffer.keys():
269
+ self.prt3_buffer[key] = glGenBuffers(1)
270
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt1_buffer[key])
271
+ glBufferData(GL_ARRAY_BUFFER, self.prt1_data[key], GL_STATIC_DRAW)
272
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt2_buffer[key])
273
+ glBufferData(GL_ARRAY_BUFFER, self.prt2_data[key], GL_STATIC_DRAW)
274
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt3_buffer[key])
275
+ glBufferData(GL_ARRAY_BUFFER, self.prt3_data[key], GL_STATIC_DRAW)
276
+
277
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
278
+
279
+ def cleanup(self):
280
+
281
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
282
+ for key in self.vert_data:
283
+ glDeleteBuffers(1, [self.vert_buffer[key]])
284
+ glDeleteBuffers(1, [self.norm_buffer[key]])
285
+ glDeleteBuffers(1, [self.uv_buffer[key]])
286
+ glDeleteBuffers(1, [self.vert_label_buffer[key]])
287
+
288
+ glDeleteBuffers(1, [self.tan_buffer[key]])
289
+ glDeleteBuffers(1, [self.btan_buffer[key]])
290
+ glDeleteBuffers(1, [self.prt1_buffer[key]])
291
+ glDeleteBuffers(1, [self.prt2_buffer[key]])
292
+ glDeleteBuffers(1, [self.prt3_buffer[key]])
293
+
294
+ glDeleteBuffers(1, [])
295
+
296
+ for smplr in self.render_texture_mat[key]:
297
+ glDeleteTextures([self.render_texture_mat[key][smplr]])
298
+
299
+ self.vert_buffer = {}
300
+ self.vert_data = {}
301
+
302
+ self.vert_label_buffer = {}
303
+ self.vert_label_data = {}
304
+
305
+ self.norm_buffer = {}
306
+ self.norm_data = {}
307
+
308
+ self.tan_buffer = {}
309
+ self.tan_data = {}
310
+
311
+ self.btan_buffer = {}
312
+ self.btan_data = {}
313
+
314
+ self.prt1_buffer = {}
315
+ self.prt1_data = {}
316
+
317
+ self.prt2_buffer = {}
318
+ self.prt2_data = {}
319
+
320
+ self.prt3_buffer = {}
321
+ self.prt3_data = {}
322
+
323
+ self.uv_buffer = {}
324
+ self.uv_data = {}
325
+
326
+ self.render_texture_mat = {}
327
+
328
+ self.vertex_dim = {}
329
+ self.n_vertices = {}
330
+ self.label_dim = {}
331
+
332
+ def randomize_sh(self):
333
+ self.shcoeffs[0, :] = 0.8
334
+ self.shcoeffs[1:, :] = 1.0 * np.random.rand(8, 3)
335
+
336
+ def set_sh(self, sh):
337
+ self.shcoeffs = sh
338
+
339
+ def set_norm_mat(self, scale, center):
340
+ N = np.eye(4)
341
+ N[:3, :3] = scale * np.eye(3)
342
+ N[:3, 3] = -scale * center
343
+
344
+ self.normalize_matrix = N
345
+
346
+ def draw(self):
347
+ self.draw_init()
348
+
349
+ glDisable(GL_BLEND)
350
+ #glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
351
+ glEnable(GL_MULTISAMPLE)
352
+
353
+ glUseProgram(self.program)
354
+ glUniformMatrix4fv(self.norm_mat_unif, 1, GL_FALSE,
355
+ self.normalize_matrix.transpose())
356
+ glUniformMatrix4fv(self.model_mat_unif, 1, GL_FALSE,
357
+ self.model_view_matrix.transpose())
358
+ glUniformMatrix4fv(self.persp_mat_unif, 1, GL_FALSE,
359
+ self.projection_matrix.transpose())
360
+
361
+ if 'AlbedoMap' in self.render_texture_mat['all']:
362
+ glUniform1ui(self.hasAlbedoUnif, GLuint(1))
363
+ else:
364
+ glUniform1ui(self.hasAlbedoUnif, GLuint(0))
365
+
366
+ if 'NormalMap' in self.render_texture_mat['all']:
367
+ glUniform1ui(self.hasNormalUnif, GLuint(1))
368
+ else:
369
+ glUniform1ui(self.hasNormalUnif, GLuint(0))
370
+
371
+ glUniform1ui(self.analyticUnif,
372
+ GLuint(1) if self.analytic else GLuint(0))
373
+
374
+ glUniform3fv(self.shcoeff_unif, 9, self.shcoeffs)
375
+
376
+ glUniformMatrix3fv(self.rot_mat_unif, 1, GL_FALSE,
377
+ self.rot_matrix.transpose())
378
+
379
+ for mat in self.vert_buffer:
380
+ # Handle vertex buffer
381
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_buffer[mat])
382
+ glEnableVertexAttribArray(0)
383
+ glVertexAttribPointer(0, self.vertex_dim[mat], GL_DOUBLE, GL_FALSE,
384
+ 0, None)
385
+
386
+ # Handle normal buffer
387
+ glBindBuffer(GL_ARRAY_BUFFER, self.norm_buffer[mat])
388
+ glEnableVertexAttribArray(1)
389
+ glVertexAttribPointer(1, 3, GL_DOUBLE, GL_FALSE, 0, None)
390
+
391
+ # Handle uv buffer
392
+ glBindBuffer(GL_ARRAY_BUFFER, self.uv_buffer[mat])
393
+ glEnableVertexAttribArray(2)
394
+ glVertexAttribPointer(2, 2, GL_DOUBLE, GL_FALSE, 0, None)
395
+
396
+ # Handle tan buffer
397
+ glBindBuffer(GL_ARRAY_BUFFER, self.tan_buffer[mat])
398
+ glEnableVertexAttribArray(3)
399
+ glVertexAttribPointer(3, 3, GL_DOUBLE, GL_FALSE, 0, None)
400
+
401
+ # Handle btan buffer
402
+ glBindBuffer(GL_ARRAY_BUFFER, self.btan_buffer[mat])
403
+ glEnableVertexAttribArray(4)
404
+ glVertexAttribPointer(4, 3, GL_DOUBLE, GL_FALSE, 0, None)
405
+
406
+ # Handle PTR buffer
407
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt1_buffer[mat])
408
+ glEnableVertexAttribArray(5)
409
+ glVertexAttribPointer(5, 3, GL_DOUBLE, GL_FALSE, 0, None)
410
+
411
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt2_buffer[mat])
412
+ glEnableVertexAttribArray(6)
413
+ glVertexAttribPointer(6, 3, GL_DOUBLE, GL_FALSE, 0, None)
414
+
415
+ glBindBuffer(GL_ARRAY_BUFFER, self.prt3_buffer[mat])
416
+ glEnableVertexAttribArray(7)
417
+ glVertexAttribPointer(7, 3, GL_DOUBLE, GL_FALSE, 0, None)
418
+
419
+ # Handle vertex label buffer
420
+ glBindBuffer(GL_ARRAY_BUFFER, self.vert_label_buffer[mat])
421
+ glEnableVertexAttribArray(8)
422
+ glVertexAttribPointer(8, self.label_dim[mat], GL_DOUBLE, GL_FALSE,
423
+ 0, None)
424
+
425
+ for i, smplr in enumerate(self.render_texture_mat[mat]):
426
+ glActiveTexture(GL_TEXTURE0 + i)
427
+ glBindTexture(GL_TEXTURE_2D,
428
+ self.render_texture_mat[mat][smplr])
429
+ glUniform1i(glGetUniformLocation(self.program, smplr), i)
430
+
431
+ glDrawArrays(GL_TRIANGLES, 0, self.n_vertices[mat])
432
+
433
+ glDisableVertexAttribArray(8)
434
+ glDisableVertexAttribArray(7)
435
+ glDisableVertexAttribArray(6)
436
+ glDisableVertexAttribArray(5)
437
+ glDisableVertexAttribArray(4)
438
+ glDisableVertexAttribArray(3)
439
+ glDisableVertexAttribArray(2)
440
+ glDisableVertexAttribArray(1)
441
+ glDisableVertexAttribArray(0)
442
+
443
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
444
+
445
+ glUseProgram(0)
446
+
447
+ glDisable(GL_BLEND)
448
+ glDisable(GL_MULTISAMPLE)
449
+
450
+ self.draw_end()
lib/renderer/gl/render.py ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ # Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
5
+ # holder of all proprietary rights on this computer program.
6
+ # You can only use this computer program if you have closed
7
+ # a license agreement with MPG or you get the right to use the computer
8
+ # program from someone who is authorized to grant you that right.
9
+ # Any use of the computer program without a valid license is prohibited and
10
+ # liable to prosecution.
11
+ #
12
+ # Copyright©2019 Max-Planck-Gesellschaft zur Förderung
13
+ # der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
14
+ # for Intelligent Systems. All rights reserved.
15
+ #
16
+ # Contact: [email protected]
17
+
18
+ from ctypes import *
19
+
20
+ import numpy as np
21
+ from .framework import *
22
+
23
+ GLUT = None
24
+
25
+
26
+ # NOTE: Render class assumes GL context is created already.
27
+ class Render:
28
+ def __init__(self,
29
+ width=1600,
30
+ height=1200,
31
+ name='GL Renderer',
32
+ program_files=['simple.fs', 'simple.vs'],
33
+ color_size=1,
34
+ ms_rate=1,
35
+ egl=False):
36
+ self.width = width
37
+ self.height = height
38
+ self.name = name
39
+ self.use_inverse_depth = False
40
+ self.egl = egl
41
+
42
+ glEnable(GL_DEPTH_TEST)
43
+
44
+ glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE)
45
+ glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE)
46
+ glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE)
47
+
48
+ # init program
49
+ shader_list = []
50
+
51
+ for program_file in program_files:
52
+ _, ext = os.path.splitext(program_file)
53
+ if ext == '.vs':
54
+ shader_list.append(loadShader(GL_VERTEX_SHADER, program_file))
55
+ elif ext == '.fs':
56
+ shader_list.append(loadShader(GL_FRAGMENT_SHADER,
57
+ program_file))
58
+ elif ext == '.gs':
59
+ shader_list.append(loadShader(GL_GEOMETRY_SHADER,
60
+ program_file))
61
+
62
+ self.program = createProgram(shader_list)
63
+
64
+ for shader in shader_list:
65
+ glDeleteShader(shader)
66
+
67
+ # Init uniform variables
68
+ self.model_mat_unif = glGetUniformLocation(self.program, 'ModelMat')
69
+ self.persp_mat_unif = glGetUniformLocation(self.program, 'PerspMat')
70
+
71
+ self.vertex_buffer = glGenBuffers(1)
72
+
73
+ # Init screen quad program and buffer
74
+ self.quad_program, self.quad_buffer = self.init_quad_program()
75
+
76
+ # Configure frame buffer
77
+ self.frame_buffer = glGenFramebuffers(1)
78
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
79
+
80
+ self.intermediate_fbo = None
81
+ if ms_rate > 1:
82
+ # Configure texture buffer to render to
83
+ self.color_buffer = []
84
+ for i in range(color_size):
85
+ color_buffer = glGenTextures(1)
86
+ multi_sample_rate = ms_rate
87
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_buffer)
88
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
89
+ GL_CLAMP_TO_EDGE)
90
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
91
+ GL_CLAMP_TO_EDGE)
92
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
93
+ GL_LINEAR)
94
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
95
+ GL_LINEAR)
96
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
97
+ multi_sample_rate, GL_RGBA32F,
98
+ self.width, self.height, GL_TRUE)
99
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0)
100
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
101
+ GL_COLOR_ATTACHMENT0 + i,
102
+ GL_TEXTURE_2D_MULTISAMPLE, color_buffer,
103
+ 0)
104
+ self.color_buffer.append(color_buffer)
105
+
106
+ self.render_buffer = glGenRenderbuffers(1)
107
+ glBindRenderbuffer(GL_RENDERBUFFER, self.render_buffer)
108
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
109
+ multi_sample_rate,
110
+ GL_DEPTH24_STENCIL8, self.width,
111
+ self.height)
112
+ glBindRenderbuffer(GL_RENDERBUFFER, 0)
113
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
114
+ GL_DEPTH_STENCIL_ATTACHMENT,
115
+ GL_RENDERBUFFER, self.render_buffer)
116
+
117
+ attachments = []
118
+ for i in range(color_size):
119
+ attachments.append(GL_COLOR_ATTACHMENT0 + i)
120
+ glDrawBuffers(color_size, attachments)
121
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
122
+
123
+ self.intermediate_fbo = glGenFramebuffers(1)
124
+ glBindFramebuffer(GL_FRAMEBUFFER, self.intermediate_fbo)
125
+
126
+ self.screen_texture = []
127
+ for i in range(color_size):
128
+ screen_texture = glGenTextures(1)
129
+ glBindTexture(GL_TEXTURE_2D, screen_texture)
130
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width,
131
+ self.height, 0, GL_RGBA, GL_FLOAT, None)
132
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
133
+ GL_LINEAR)
134
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
135
+ GL_LINEAR)
136
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
137
+ GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
138
+ screen_texture, 0)
139
+ self.screen_texture.append(screen_texture)
140
+
141
+ glDrawBuffers(color_size, attachments)
142
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
143
+ else:
144
+ self.color_buffer = []
145
+ for i in range(color_size):
146
+ color_buffer = glGenTextures(1)
147
+ glBindTexture(GL_TEXTURE_2D, color_buffer)
148
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
149
+ GL_CLAMP_TO_EDGE)
150
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
151
+ GL_CLAMP_TO_EDGE)
152
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
153
+ GL_NEAREST)
154
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
155
+ GL_NEAREST)
156
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width,
157
+ self.height, 0, GL_RGBA, GL_FLOAT, None)
158
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
159
+ GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
160
+ color_buffer, 0)
161
+ self.color_buffer.append(color_buffer)
162
+
163
+ # Configure depth texture map to render to
164
+ self.depth_buffer = glGenTextures(1)
165
+ glBindTexture(GL_TEXTURE_2D, self.depth_buffer)
166
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
167
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
168
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
169
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
170
+ glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY)
171
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
172
+ GL_COMPARE_R_TO_TEXTURE)
173
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL)
174
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, self.width,
175
+ self.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
176
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
177
+ GL_TEXTURE_2D, self.depth_buffer, 0)
178
+
179
+ attachments = []
180
+ for i in range(color_size):
181
+ attachments.append(GL_COLOR_ATTACHMENT0 + i)
182
+ glDrawBuffers(color_size, attachments)
183
+ self.screen_texture = self.color_buffer
184
+
185
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
186
+
187
+ # Configure texture buffer if needed
188
+ self.render_texture = None
189
+
190
+ # NOTE: original render_texture only support one input
191
+ # this is tentative member of this issue
192
+ self.render_texture_v2 = {}
193
+
194
+ # Inner storage for buffer data
195
+ self.vertex_data = None
196
+ self.vertex_dim = None
197
+ self.n_vertices = None
198
+
199
+ self.model_view_matrix = None
200
+ self.projection_matrix = None
201
+
202
+ if not egl:
203
+ global GLUT
204
+ import OpenGL.GLUT as GLUT
205
+ GLUT.glutDisplayFunc(self.display)
206
+
207
+ def init_quad_program(self):
208
+ shader_list = []
209
+
210
+ shader_list.append(loadShader(GL_VERTEX_SHADER, "quad.vs"))
211
+ shader_list.append(loadShader(GL_FRAGMENT_SHADER, "quad.fs"))
212
+
213
+ the_program = createProgram(shader_list)
214
+
215
+ for shader in shader_list:
216
+ glDeleteShader(shader)
217
+
218
+ # vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
219
+ # positions # texCoords
220
+ quad_vertices = np.array([
221
+ -1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0,
222
+ -1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0
223
+ ])
224
+
225
+ quad_buffer = glGenBuffers(1)
226
+ glBindBuffer(GL_ARRAY_BUFFER, quad_buffer)
227
+ glBufferData(GL_ARRAY_BUFFER, quad_vertices, GL_STATIC_DRAW)
228
+
229
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
230
+
231
+ return the_program, quad_buffer
232
+
233
+ def set_mesh(self, vertices, faces):
234
+ self.vertex_data = vertices[faces.reshape([-1])]
235
+ self.vertex_dim = self.vertex_data.shape[1]
236
+ self.n_vertices = self.vertex_data.shape[0]
237
+
238
+ glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer)
239
+ glBufferData(GL_ARRAY_BUFFER, self.vertex_data, GL_STATIC_DRAW)
240
+
241
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
242
+
243
+ def set_viewpoint(self, projection, model_view):
244
+ self.projection_matrix = projection
245
+ self.model_view_matrix = model_view
246
+
247
+ def draw_init(self):
248
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
249
+ glEnable(GL_DEPTH_TEST)
250
+
251
+ glClearColor(0.0, 0.0, 0.0, 0.0)
252
+ if self.use_inverse_depth:
253
+ glDepthFunc(GL_GREATER)
254
+ glClearDepth(0.0)
255
+ else:
256
+ glDepthFunc(GL_LESS)
257
+ glClearDepth(1.0)
258
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
259
+
260
+ def draw_end(self):
261
+ if self.intermediate_fbo is not None:
262
+ for i in range(len(self.color_buffer)):
263
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, self.frame_buffer)
264
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + i)
265
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.intermediate_fbo)
266
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + i)
267
+ glBlitFramebuffer(0, 0, self.width, self.height, 0, 0,
268
+ self.width, self.height, GL_COLOR_BUFFER_BIT,
269
+ GL_NEAREST)
270
+
271
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
272
+ glDepthFunc(GL_LESS)
273
+ glClearDepth(1.0)
274
+
275
+ def draw(self):
276
+ self.draw_init()
277
+
278
+ glUseProgram(self.program)
279
+ glUniformMatrix4fv(self.model_mat_unif, 1, GL_FALSE,
280
+ self.model_view_matrix.transpose())
281
+ glUniformMatrix4fv(self.persp_mat_unif, 1, GL_FALSE,
282
+ self.projection_matrix.transpose())
283
+
284
+ glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer)
285
+
286
+ glEnableVertexAttribArray(0)
287
+ glVertexAttribPointer(0, self.vertex_dim, GL_DOUBLE, GL_FALSE, 0, None)
288
+
289
+ glDrawArrays(GL_TRIANGLES, 0, self.n_vertices)
290
+
291
+ glDisableVertexAttribArray(0)
292
+
293
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
294
+
295
+ glUseProgram(0)
296
+
297
+ self.draw_end()
298
+
299
+ def get_color(self, color_id=0):
300
+ glBindFramebuffer(
301
+ GL_FRAMEBUFFER, self.intermediate_fbo
302
+ if self.intermediate_fbo is not None else self.frame_buffer)
303
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + color_id)
304
+ data = glReadPixels(0,
305
+ 0,
306
+ self.width,
307
+ self.height,
308
+ GL_RGBA,
309
+ GL_FLOAT,
310
+ outputType=None)
311
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
312
+ rgb = data.reshape(self.height, self.width, -1)
313
+ rgb = np.flip(rgb, 0)
314
+ return rgb
315
+
316
+ def get_z_value(self):
317
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
318
+ data = glReadPixels(0,
319
+ 0,
320
+ self.width,
321
+ self.height,
322
+ GL_DEPTH_COMPONENT,
323
+ GL_FLOAT,
324
+ outputType=None)
325
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
326
+ z = data.reshape(self.height, self.width)
327
+ z = np.flip(z, 0)
328
+ return z
329
+
330
+ def display(self):
331
+ self.draw()
332
+
333
+ if not self.egl:
334
+ # First we draw a scene.
335
+ # Notice the result is stored in the texture buffer.
336
+
337
+ # Then we return to the default frame buffer since we will display on the screen.
338
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
339
+
340
+ # Do the clean-up.
341
+ glClearColor(0.0, 0.0, 0.0, 0.0)
342
+ glClear(GL_COLOR_BUFFER_BIT)
343
+
344
+ # We draw a rectangle which covers the whole screen.
345
+ glUseProgram(self.quad_program)
346
+ glBindBuffer(GL_ARRAY_BUFFER, self.quad_buffer)
347
+
348
+ size_of_double = 8
349
+ glEnableVertexAttribArray(0)
350
+ glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE,
351
+ 4 * size_of_double, None)
352
+ glEnableVertexAttribArray(1)
353
+ glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE,
354
+ 4 * size_of_double,
355
+ c_void_p(2 * size_of_double))
356
+
357
+ glDisable(GL_DEPTH_TEST)
358
+
359
+ # The stored texture is then mapped to this rectangle.
360
+ # properly assing color buffer texture
361
+ glActiveTexture(GL_TEXTURE0)
362
+ glBindTexture(GL_TEXTURE_2D, self.screen_texture[0])
363
+ glUniform1i(
364
+ glGetUniformLocation(self.quad_program, 'screenTexture'), 0)
365
+
366
+ glDrawArrays(GL_TRIANGLES, 0, 6)
367
+
368
+ glDisableVertexAttribArray(1)
369
+ glDisableVertexAttribArray(0)
370
+
371
+ glEnable(GL_DEPTH_TEST)
372
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
373
+ glUseProgram(0)
374
+
375
+ GLUT.glutSwapBuffers()
376
+ GLUT.glutPostRedisplay()
377
+
378
+ def show(self):
379
+ if not self.egl:
380
+ GLUT.glutMainLoop()
lib/renderer/gl/render2.py ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ MIT License
3
+
4
+ Copyright (c) 2019 Shunsuke Saito, Zeng Huang, and Ryota Natsume
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ '''
24
+ import numpy as np
25
+ from OpenGL.GLUT import *
26
+ from .framework import *
27
+
28
+ _glut_window = None
29
+
30
+
31
+ class Render:
32
+ def __init__(self,
33
+ width=1600,
34
+ height=1200,
35
+ name='GL Renderer',
36
+ program_files=['simple.fs', 'simple.vs'],
37
+ color_size=1,
38
+ ms_rate=1):
39
+ self.width = width
40
+ self.height = height
41
+ self.name = name
42
+ self.display_mode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH
43
+ self.use_inverse_depth = False
44
+
45
+ global _glut_window
46
+ if _glut_window is None:
47
+ glutInit()
48
+ glutInitDisplayMode(self.display_mode)
49
+ glutInitWindowSize(self.width, self.height)
50
+ glutInitWindowPosition(0, 0)
51
+ _glut_window = glutCreateWindow("My Render.")
52
+
53
+ # glEnable(GL_DEPTH_CLAMP)
54
+ glEnable(GL_DEPTH_TEST)
55
+
56
+ glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE)
57
+ glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE)
58
+ glClampColor(GL_CLAMP_VERTEX_COLOR, GL_FALSE)
59
+
60
+ # init program
61
+ shader_list = []
62
+
63
+ for program_file in program_files:
64
+ _, ext = os.path.splitext(program_file)
65
+ if ext == '.vs':
66
+ shader_list.append(loadShader(GL_VERTEX_SHADER, program_file))
67
+ elif ext == '.fs':
68
+ shader_list.append(loadShader(GL_FRAGMENT_SHADER,
69
+ program_file))
70
+ elif ext == '.gs':
71
+ shader_list.append(loadShader(GL_GEOMETRY_SHADER,
72
+ program_file))
73
+
74
+ self.program = createProgram(shader_list)
75
+
76
+ for shader in shader_list:
77
+ glDeleteShader(shader)
78
+
79
+ # Init uniform variables
80
+ self.model_mat_unif = glGetUniformLocation(self.program, 'ModelMat')
81
+ self.persp_mat_unif = glGetUniformLocation(self.program, 'PerspMat')
82
+
83
+ self.vertex_buffer = glGenBuffers(1)
84
+
85
+ # Init screen quad program and buffer
86
+ self.quad_program, self.quad_buffer = self.init_quad_program()
87
+
88
+ # Configure frame buffer
89
+ self.frame_buffer = glGenFramebuffers(1)
90
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
91
+
92
+ self.intermediate_fbo = None
93
+ if ms_rate > 1:
94
+ # Configure texture buffer to render to
95
+ self.color_buffer = []
96
+ for i in range(color_size):
97
+ color_buffer = glGenTextures(1)
98
+ multi_sample_rate = ms_rate
99
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, color_buffer)
100
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
101
+ GL_CLAMP_TO_EDGE)
102
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
103
+ GL_CLAMP_TO_EDGE)
104
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
105
+ GL_LINEAR)
106
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
107
+ GL_LINEAR)
108
+ glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,
109
+ multi_sample_rate, GL_RGBA32F,
110
+ self.width, self.height, GL_TRUE)
111
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0)
112
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
113
+ GL_COLOR_ATTACHMENT0 + i,
114
+ GL_TEXTURE_2D_MULTISAMPLE, color_buffer,
115
+ 0)
116
+ self.color_buffer.append(color_buffer)
117
+
118
+ self.render_buffer = glGenRenderbuffers(1)
119
+ glBindRenderbuffer(GL_RENDERBUFFER, self.render_buffer)
120
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER,
121
+ multi_sample_rate,
122
+ GL_DEPTH24_STENCIL8, self.width,
123
+ self.height)
124
+ glBindRenderbuffer(GL_RENDERBUFFER, 0)
125
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER,
126
+ GL_DEPTH_STENCIL_ATTACHMENT,
127
+ GL_RENDERBUFFER, self.render_buffer)
128
+
129
+ attachments = []
130
+ for i in range(color_size):
131
+ attachments.append(GL_COLOR_ATTACHMENT0 + i)
132
+ glDrawBuffers(color_size, attachments)
133
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
134
+
135
+ self.intermediate_fbo = glGenFramebuffers(1)
136
+ glBindFramebuffer(GL_FRAMEBUFFER, self.intermediate_fbo)
137
+
138
+ self.screen_texture = []
139
+ for i in range(color_size):
140
+ screen_texture = glGenTextures(1)
141
+ glBindTexture(GL_TEXTURE_2D, screen_texture)
142
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width,
143
+ self.height, 0, GL_RGBA, GL_FLOAT, None)
144
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
145
+ GL_LINEAR)
146
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
147
+ GL_LINEAR)
148
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
149
+ GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
150
+ screen_texture, 0)
151
+ self.screen_texture.append(screen_texture)
152
+
153
+ glDrawBuffers(color_size, attachments)
154
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
155
+ else:
156
+ self.color_buffer = []
157
+ for i in range(color_size):
158
+ color_buffer = glGenTextures(1)
159
+ glBindTexture(GL_TEXTURE_2D, color_buffer)
160
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
161
+ GL_CLAMP_TO_EDGE)
162
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
163
+ GL_CLAMP_TO_EDGE)
164
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
165
+ GL_NEAREST)
166
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
167
+ GL_NEAREST)
168
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, self.width,
169
+ self.height, 0, GL_RGBA, GL_FLOAT, None)
170
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
171
+ GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D,
172
+ color_buffer, 0)
173
+ self.color_buffer.append(color_buffer)
174
+
175
+ # Configure depth texture map to render to
176
+ self.depth_buffer = glGenTextures(1)
177
+ glBindTexture(GL_TEXTURE_2D, self.depth_buffer)
178
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
179
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
180
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
181
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
182
+ glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY)
183
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
184
+ GL_COMPARE_R_TO_TEXTURE)
185
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL)
186
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, self.width,
187
+ self.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None)
188
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
189
+ GL_TEXTURE_2D, self.depth_buffer, 0)
190
+
191
+ attachments = []
192
+ for i in range(color_size):
193
+ attachments.append(GL_COLOR_ATTACHMENT0 + i)
194
+ glDrawBuffers(color_size, attachments)
195
+ self.screen_texture = self.color_buffer
196
+
197
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
198
+
199
+ # Configure texture buffer if needed
200
+ self.render_texture = None
201
+
202
+ # NOTE: original render_texture only support one input
203
+ # this is tentative member of this issue
204
+ self.render_texture_v2 = {}
205
+
206
+ # Inner storage for buffer data
207
+ self.vertex_data = None
208
+ self.vertex_dim = None
209
+ self.n_vertices = None
210
+
211
+ self.model_view_matrix = None
212
+ self.projection_matrix = None
213
+
214
+ glutDisplayFunc(self.display)
215
+
216
+ def init_quad_program(self):
217
+ shader_list = []
218
+
219
+ shader_list.append(loadShader(GL_VERTEX_SHADER, "quad.vs"))
220
+ shader_list.append(loadShader(GL_FRAGMENT_SHADER, "quad.fs"))
221
+
222
+ the_program = createProgram(shader_list)
223
+
224
+ for shader in shader_list:
225
+ glDeleteShader(shader)
226
+
227
+ # vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
228
+ # positions # texCoords
229
+ quad_vertices = np.array([
230
+ -1.0, 1.0, 0.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0, -1.0, 1.0, 0.0,
231
+ -1.0, 1.0, 0.0, 1.0, 1.0, -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0
232
+ ])
233
+
234
+ quad_buffer = glGenBuffers(1)
235
+ glBindBuffer(GL_ARRAY_BUFFER, quad_buffer)
236
+ glBufferData(GL_ARRAY_BUFFER, quad_vertices, GL_STATIC_DRAW)
237
+
238
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
239
+
240
+ return the_program, quad_buffer
241
+
242
+ def set_mesh(self, vertices, faces):
243
+ self.vertex_data = vertices[faces.reshape([-1])]
244
+ self.vertex_dim = self.vertex_data.shape[1]
245
+ self.n_vertices = self.vertex_data.shape[0]
246
+
247
+ glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer)
248
+ glBufferData(GL_ARRAY_BUFFER, self.vertex_data, GL_STATIC_DRAW)
249
+
250
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
251
+
252
+ def set_viewpoint(self, projection, model_view):
253
+ self.projection_matrix = projection
254
+ self.model_view_matrix = model_view
255
+
256
+ def draw_init(self):
257
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
258
+ glEnable(GL_DEPTH_TEST)
259
+
260
+ # glClearColor(0.0, 0.0, 0.0, 0.0)
261
+ glClearColor(1.0, 1.0, 1.0, 0.0) # Black background
262
+
263
+ if self.use_inverse_depth:
264
+ glDepthFunc(GL_GREATER)
265
+ glClearDepth(0.0)
266
+ else:
267
+ glDepthFunc(GL_LESS)
268
+ glClearDepth(1.0)
269
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
270
+
271
+ def draw_end(self):
272
+ if self.intermediate_fbo is not None:
273
+ for i in range(len(self.color_buffer)):
274
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, self.frame_buffer)
275
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + i)
276
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, self.intermediate_fbo)
277
+ glDrawBuffer(GL_COLOR_ATTACHMENT0 + i)
278
+ glBlitFramebuffer(0, 0, self.width, self.height, 0, 0,
279
+ self.width, self.height, GL_COLOR_BUFFER_BIT,
280
+ GL_NEAREST)
281
+
282
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
283
+ glDepthFunc(GL_LESS)
284
+ glClearDepth(1.0)
285
+
286
+ def draw(self):
287
+ self.draw_init()
288
+
289
+ glUseProgram(self.program)
290
+ glUniformMatrix4fv(self.model_mat_unif, 1, GL_FALSE,
291
+ self.model_view_matrix.transpose())
292
+ glUniformMatrix4fv(self.persp_mat_unif, 1, GL_FALSE,
293
+ self.projection_matrix.transpose())
294
+
295
+ glBindBuffer(GL_ARRAY_BUFFER, self.vertex_buffer)
296
+
297
+ glEnableVertexAttribArray(0)
298
+ glVertexAttribPointer(0, self.vertex_dim, GL_DOUBLE, GL_FALSE, 0, None)
299
+
300
+ glDrawArrays(GL_TRIANGLES, 0, self.n_vertices)
301
+
302
+ glDisableVertexAttribArray(0)
303
+
304
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
305
+
306
+ glUseProgram(0)
307
+
308
+ self.draw_end()
309
+
310
+ def get_color(self, color_id=0):
311
+ glBindFramebuffer(
312
+ GL_FRAMEBUFFER, self.intermediate_fbo
313
+ if self.intermediate_fbo is not None else self.frame_buffer)
314
+ glReadBuffer(GL_COLOR_ATTACHMENT0 + color_id)
315
+ data = glReadPixels(0,
316
+ 0,
317
+ self.width,
318
+ self.height,
319
+ GL_RGBA,
320
+ GL_FLOAT,
321
+ outputType=None)
322
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
323
+ rgb = data.reshape(self.height, self.width, -1)
324
+ rgb = np.flip(rgb, 0)
325
+ return rgb
326
+
327
+ def get_z_value(self):
328
+ glBindFramebuffer(GL_FRAMEBUFFER, self.frame_buffer)
329
+ data = glReadPixels(0,
330
+ 0,
331
+ self.width,
332
+ self.height,
333
+ GL_DEPTH_COMPONENT,
334
+ GL_FLOAT,
335
+ outputType=None)
336
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
337
+ z = data.reshape(self.height, self.width)
338
+ z = np.flip(z, 0)
339
+ return z
340
+
341
+ def display(self):
342
+ # First we draw a scene.
343
+ # Notice the result is stored in the texture buffer.
344
+ self.draw()
345
+
346
+ # Then we return to the default frame buffer since we will display on the screen.
347
+ glBindFramebuffer(GL_FRAMEBUFFER, 0)
348
+
349
+ # Do the clean-up.
350
+ # glClearColor(0.0, 0.0, 0.0, 0.0) #Black background
351
+ glClearColor(1.0, 1.0, 1.0, 0.0) # Black background
352
+ glClear(GL_COLOR_BUFFER_BIT)
353
+
354
+ # We draw a rectangle which covers the whole screen.
355
+ glUseProgram(self.quad_program)
356
+ glBindBuffer(GL_ARRAY_BUFFER, self.quad_buffer)
357
+
358
+ size_of_double = 8
359
+ glEnableVertexAttribArray(0)
360
+ glVertexAttribPointer(0, 2, GL_DOUBLE, GL_FALSE, 4 * size_of_double,
361
+ None)
362
+ glEnableVertexAttribArray(1)
363
+ glVertexAttribPointer(1, 2, GL_DOUBLE, GL_FALSE, 4 * size_of_double,
364
+ c_void_p(2 * size_of_double))
365
+
366
+ glDisable(GL_DEPTH_TEST)
367
+
368
+ # The stored texture is then mapped to this rectangle.
369
+ # properly assing color buffer texture
370
+ glActiveTexture(GL_TEXTURE0)
371
+ glBindTexture(GL_TEXTURE_2D, self.screen_texture[0])
372
+ glUniform1i(glGetUniformLocation(self.quad_program, 'screenTexture'),
373
+ 0)
374
+
375
+ glDrawArrays(GL_TRIANGLES, 0, 6)
376
+
377
+ glDisableVertexAttribArray(1)
378
+ glDisableVertexAttribArray(0)
379
+
380
+ glEnable(GL_DEPTH_TEST)
381
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
382
+ glUseProgram(0)
383
+
384
+ glutSwapBuffers()
385
+ glutPostRedisplay()
386
+
387
+ def show(self):
388
+ glutMainLoop()