Spaces:
Build error
Build error
Upload 9 files
Browse files- lib/renderer/gl/cam_render.py +80 -0
- lib/renderer/gl/color_render.py +162 -0
- lib/renderer/gl/framework.py +95 -0
- lib/renderer/gl/glcontext.py +136 -0
- lib/renderer/gl/init_gl.py +24 -0
- lib/renderer/gl/norm_render.py +79 -0
- lib/renderer/gl/prt_render.py +450 -0
- lib/renderer/gl/render.py +380 -0
- lib/renderer/gl/render2.py +388 -0
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()
|