-
Notifications
You must be signed in to change notification settings - Fork 1
/
ogl_shader.py
254 lines (213 loc) · 5.78 KB
/
ogl_shader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
from OpenGL import GL
import OpenGL.GL.shaders
UNIFORM_LIST = [
"u_model_mat",
"u_view_mat",
"u_proj_mat",
"u_gamma",
"u_compensate",
"u_obb",
"u_lightScale",
"u_color",
"u_line",
"u_pick",
"u_mode",
"u_position_radius",
"u_color_radius",
"u_positionmap",
"u_normalsmap", # for stored vertex normals
"u_lightmap",
"u_cubemap",
"u_bouncemap"
]
SAMPLER_LIST = {
"u_positionmap": 0,
"u_normalsmap": 1,
"u_lightmap": 0,
"u_cubemap": 2,
"u_bouncemap": 1
}
SHADER_HEADER = """#version 130
#define M_PI float(3.1415926535)
"""
vertex_shader = """
in vec3 position;
in vec4 color;
in vec3 vertex_normal;
in vec4 tcs;
in vec4 vertex_info;
out vec4 ws_position;
out vec4 v_color;
out vec3 v_normal;
out vec4 v_tcs;
flat out vec4 v_info;
uniform mat4 u_proj_mat;
uniform mat4 u_view_mat;
uniform mat4 u_model_mat;
uniform int u_mode;
vec4 encode_int(in int value)
{
float r = ((value & 0x000000FF) ) / 255.0;
float g = ((value & 0x0000FF00) >> 8) / 255.0;
float b = ((value & 0x00FF0000) >> 16) / 255.0;
return vec4(r, g, b, float(value));
}
void main()
{
ws_position = u_model_mat*(vec4(position, 1.0));
gl_Position = u_proj_mat*u_view_mat*u_model_mat*(vec4(position, 1.0));
v_color = color;
v_tcs = tcs;
int info[4] = int[4](int(vertex_info.x), int(vertex_info.y), int(vertex_info.z), int(vertex_info.w));
v_info = encode_int(info[u_mode]);
// FIXME: use normal matrix instead of model matrix
v_normal = mat3(u_model_mat)*vertex_normal;
}
"""
fragment_shader = """
in vec4 v_color;
in vec3 v_normal;
in vec4 v_tcs;
uniform vec4 u_color;
out vec4 out_color;
void main()
{
vec3 color = mix(v_color.rgb, u_color.rgb, u_color.a);
vec3 n = normalize(v_normal.xyz);
const vec3 test_n = normalize(vec3(-0.4, 0.3, 0.5));
float shade = clamp(dot(test_n, n) * 0.15, -0.15, 0.15) + 0.85;
out_color.rgb = clamp(color * shade, 0.0, 1.0);
out_color.a = v_color.a;
}
"""
lightmap_fragment_shader = """
in vec4 v_color;
in vec3 v_normal;
in vec4 v_tcs;
uniform vec4 u_color;
uniform sampler2D u_lightmap;
uniform sampler2D u_bouncemap;
uniform float u_gamma;
uniform float u_compensate;
uniform float u_obb;
uniform float u_lightScale;
out vec4 out_color;
void main()
{
vec3 color = max(texture(u_lightmap, v_tcs.zw).rgb * u_lightScale, vec3(0.0));
color += max(texture(u_bouncemap, v_tcs.zw).rgb * u_lightScale, vec3(0.0));
color = pow(color, vec3(1.0 / u_gamma));
float max_v = max(color.r, max(color.g, color.b));
if (max_v > 1.0)
{
color /= max_v;
}
color *= (pow(2.0, u_obb)) / u_compensate;
vec3 n = normalize(v_normal.xyz);
const vec3 test_n = normalize(vec3(-0.4, 0.3, 0.5));
float shade = clamp(dot(test_n, n) * 0.15, -0.15, 0.15) + 0.85;
out_color.rgb = clamp(color * shade, 0.0, 1.0);
out_color.a = 1.0;
}
"""
fragment_select_shader = """
in vec4 v_color;
in vec3 v_normal;
in vec4 v_tcs;
flat in vec4 v_info;
uniform int u_mode;
uniform int u_pick;
out vec4 out_color;
void main()
{
vec3 color = mix(v_color.rgb, vec3(1., .01, 1.), float(u_pick == int(v_info.w)) * 0.5);
vec3 n = normalize(v_normal.xyz);
const vec3 test_n = normalize(vec3(-0.4, 0.3, 0.5));
float shade = clamp(dot(test_n, n) * 0.15, -0.15, 0.15) + 0.85;
out_color.rgb = clamp(color * shade, 0.0, 1.0);
out_color.a = v_color.a;
}
"""
pick_fragment_shader = """
in vec4 v_color;
in vec3 v_normal;
in vec4 v_tcs;
flat in vec4 v_info;
uniform vec4 u_line;
out vec4 out_color;
void main()
{
out_color = u_line;
}
"""
pick_mode_fragment_shader = """
in vec4 v_color;
in vec3 v_normal;
in vec4 v_tcs;
flat in vec4 v_info; // vert, surface, shader, fog
uniform vec4 u_line;
out vec4 out_color;
void main()
{
out_color = vec4(v_info.rgb, 0.0);
}
"""
SHADER_LIST = [
["Vertex_Color", vertex_shader, fragment_shader],
["Vertex_Color_Selection", vertex_shader, fragment_select_shader],
["Pick_Object", vertex_shader, pick_fragment_shader],
["Pick_Selection", vertex_shader, pick_mode_fragment_shader],
["Lightmap_Color", vertex_shader, lightmap_fragment_shader]
]
class SHADER():
def __init__(self, vertex_shader, fragment_shader):
self.uniform_loc = {}
self.program = OpenGL.GL.shaders.compileProgram(
self.compileShader(vertex_shader, GL.GL_VERTEX_SHADER),
self.compileShader(fragment_shader, GL.GL_FRAGMENT_SHADER),
validate = False
)
for uniform in UNIFORM_LIST:
self.uniform_loc[uniform] = GL.glGetUniformLocation(self.program, self.bytestr(uniform))
GL.glUseProgram(self.program)
for uniform in UNIFORM_LIST:
if uniform in SAMPLER_LIST and self.uniform_loc[uniform] > -1:
GL.glUniform1i(self.uniform_loc[uniform], SAMPLER_LIST[uniform])
GL.glUseProgram(0)
self.program.check_validate()
# Avoiding glitches in pyopengl-3.0.x and python3.4
def bytestr(self, s):
return s.encode("utf-8") + b"\000"
# Avoiding glitches in pyopengl-3.0.x and python3.4
def compileShader(self, source, shaderType):
"""
Compile shader source of given type
source -- GLSL source-code for the shader
shaderType -- GLenum GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, etc,
returns GLuint compiled shader reference
raises RuntimeError when a compilation failure occurs
"""
if isinstance(source, str):
source = [source]
elif isinstance(source, bytes):
source = [source.decode('utf-8')]
shader = GL.glCreateShader(shaderType)
source = [SHADER_HEADER + source[0]]
GL.glShaderSource(shader, source)
GL.glCompileShader(shader)
result = GL.glGetShaderiv(shader, GL.GL_COMPILE_STATUS)
if not(result):
# TODO: this will be wrong if the user has
# disabled traditional unpacking array support.
raise RuntimeError(
"""Shader compile failure (%s): %s""" % (
result,
GL.glGetShaderInfoLog(shader),
),
source,
shaderType,
)
return shader
#TODO: check if python OpenGL deletes the buffers correcly
if __name__ == "__main__":
print("Please run 'main.py'")