rays 0.1.27 → 0.1.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/exception.cpp +45 -0
  3. data/.doc/ext/rays/native.cpp +2 -0
  4. data/.doc/ext/rays/painter.cpp +7 -2
  5. data/.doc/ext/rays/shader.cpp +100 -6
  6. data/VERSION +1 -1
  7. data/ext/rays/defs.h +1 -0
  8. data/ext/rays/exception.cpp +45 -0
  9. data/ext/rays/native.cpp +2 -0
  10. data/ext/rays/painter.cpp +7 -2
  11. data/ext/rays/shader.cpp +101 -5
  12. data/include/rays/exception.h +11 -0
  13. data/include/rays/ruby/bitmap.h +0 -1
  14. data/include/rays/ruby/bounds.h +0 -2
  15. data/include/rays/ruby/camera.h +0 -1
  16. data/include/rays/ruby/color.h +0 -2
  17. data/include/rays/ruby/color_space.h +0 -1
  18. data/include/rays/ruby/defs.h +30 -0
  19. data/include/rays/ruby/exception.h +28 -0
  20. data/include/rays/ruby/font.h +0 -1
  21. data/include/rays/ruby/image.h +0 -1
  22. data/include/rays/ruby/matrix.h +0 -1
  23. data/include/rays/ruby/painter.h +0 -1
  24. data/include/rays/ruby/point.h +0 -2
  25. data/include/rays/ruby/polygon.h +0 -1
  26. data/include/rays/ruby/polyline.h +0 -1
  27. data/include/rays/ruby/rays.h +0 -1
  28. data/include/rays/ruby/shader.h +0 -1
  29. data/include/rays/ruby.h +2 -0
  30. data/include/rays/shader.h +48 -1
  31. data/lib/rays/painter.rb +6 -5
  32. data/lib/rays/point.rb +1 -0
  33. data/lib/rays/shader.rb +18 -5
  34. data/rays.gemspec +2 -2
  35. data/src/exception.cpp +13 -0
  36. data/src/image.cpp +6 -4
  37. data/src/ios/bitmap.mm +18 -1
  38. data/src/opengl.cpp +21 -7
  39. data/src/opengl.h +5 -3
  40. data/src/osx/bitmap.mm +18 -1
  41. data/src/osx/font.mm +0 -2
  42. data/src/osx/opengl.mm +17 -2
  43. data/src/painter.cpp +196 -125
  44. data/src/shader.cpp +333 -53
  45. data/src/shader.h +53 -14
  46. data/src/shader_program.cpp +53 -27
  47. data/src/shader_program.h +8 -1
  48. data/src/shader_source.cpp +2 -2
  49. data/src/texture.cpp +75 -63
  50. data/test/test_image.rb +45 -10
  51. data/test/test_painter.rb +26 -4
  52. data/test/test_point.rb +6 -5
  53. data/test/test_rays.rb +2 -2
  54. data/test/test_shader.rb +151 -14
  55. metadata +11 -6
data/src/shader.cpp CHANGED
@@ -1,6 +1,7 @@
1
1
  #include "shader.h"
2
2
 
3
3
 
4
+ #include <regex>
4
5
  #include "rays/exception.h"
5
6
  #include "opengl.h"
6
7
  #include "image.h"
@@ -12,54 +13,21 @@ namespace Rays
12
13
  {
13
14
 
14
15
 
15
- static const ShaderSource&
16
- get_vertex_shader_source ()
17
- {
18
- static const ShaderSource SOURCE(
19
- GL_VERTEX_SHADER,
20
- "attribute vec3 " ATTRIB_POSITION ";"
21
- "varying vec4 " VARYING_POSITION ";"
22
- "uniform mat4 " UNIFORM_POSITION_MATRIX ";"
23
- "attribute vec3 " ATTRIB_TEXCOORD ";"
24
- "varying vec4 " VARYING_TEXCOORD ";"
25
- "uniform mat4 " UNIFORM_TEXCOORD_MATRIX ";"
26
- "attribute vec4 " ATTRIB_COLOR ";"
27
- "varying vec4 " VARYING_COLOR ";"
28
- "void main ()"
29
- "{"
30
- " vec4 pos = vec4(" ATTRIB_POSITION ", 1.0);"
31
- " vec4 texcoord = vec4(" ATTRIB_TEXCOORD ", 1.0);"
32
- VARYING_POSITION " = pos;"
33
- VARYING_TEXCOORD " = " UNIFORM_TEXCOORD_MATRIX " * texcoord;"
34
- VARYING_COLOR " = " ATTRIB_COLOR ";"
35
- " gl_Position = " UNIFORM_POSITION_MATRIX " * pos;"
36
- "}");
37
- return SOURCE;
38
- }
39
-
40
- static ShaderSource
41
- make_fragment_shader_source (const char* source)
42
- {
43
- static String SHARED_HEADER =
44
- "#ifdef GL_ES\n"
45
- "precision mediump float;\n"
46
- "#endif\n"
47
- "uniform sampler2D " UNIFORM_TEXTURE ";"
48
- "uniform vec2 " UNIFORM_TEXTURE_SIZE ";"
49
- "uniform vec2 " UNIFORM_TEXCOORD_MIN ";"
50
- "uniform vec2 " UNIFORM_TEXCOORD_MAX ";"
51
- "vec2 normalizeTexCoord(vec2 texcoord)"
52
- "{"
53
- " vec2 min = " UNIFORM_TEXCOORD_MIN ";"
54
- " vec2 len = " UNIFORM_TEXCOORD_MAX " - min;"
55
- " return (mod(texcoord - min, len) + min) / " UNIFORM_TEXTURE_SIZE ";"
56
- "}"
57
- "vec4 sampleTexture(vec2 texcoord)"
58
- "{"
59
- " return texture2D(" UNIFORM_TEXTURE ", normalizeTexCoord(texcoord));"
60
- "}\n";
61
- return ShaderSource(GL_FRAGMENT_SHADER, SHARED_HEADER + source);
62
- }
16
+ #define A_POSITION (names.attribute_position_names[0])
17
+ #define A_TEXCOORD (names.attribute_texcoord_names[0])
18
+ #define A_COLOR (names.attribute_color_names[0])
19
+ #define V_POSITION (names.varying_position_name)
20
+ #define V_TEXCOORD (names.varying_texcoord_name)
21
+ #define V_COLOR (names.varying_color_name)
22
+ #define U_POSITION_MATRIX (names.uniform_position_matrix_names[0])
23
+ #define U_TEXCOORD_MATRIX (names.uniform_texcoord_matrix_names[0])
24
+ #define U_TEXCOORD_MIN (names.uniform_texcoord_min_names[0])
25
+ #define U_TEXCOORD_MAX (names.uniform_texcoord_max_names[0])
26
+ #define U_TEXCOORD_OFFSET (names.uniform_texcoord_offset_names[0])
27
+ #define U_TEXTURE (names.uniform_texture_names[0])
28
+
29
+
30
+ static ShaderEnv DEFAULT_ENV;
63
31
 
64
32
 
65
33
  struct Shader::Data
@@ -67,23 +35,157 @@ namespace Rays
67
35
 
68
36
  std::unique_ptr<ShaderProgram> program;
69
37
 
38
+ std::unique_ptr<ShaderEnv> env;
39
+
40
+ Data (
41
+ const char* fragment_shader_source,
42
+ const char* vertex_shader_source,
43
+ ShaderEnv* env_)
44
+ {
45
+ if (!fragment_shader_source) return;
46
+
47
+ if (env_)
48
+ this->env.reset(new ShaderEnv(*env_));
49
+
50
+ program.reset(new ShaderProgram(
51
+ make_vertex_shader_source(vertex_shader_source),
52
+ make_fragment_shader_source(fragment_shader_source),
53
+ env_ ? ShaderEnv_get_flags(*env_) : 0));
54
+ }
55
+
56
+ ShaderSource make_vertex_shader_source (const char* source)
57
+ {
58
+ if (source)
59
+ return ShaderSource(GL_VERTEX_SHADER, source);
60
+ else
61
+ {
62
+ return ShaderEnv_get_default_vertex_shader_source(
63
+ env ? env.get() : &DEFAULT_ENV);
64
+ }
65
+ }
66
+
67
+ ShaderSource make_fragment_shader_source (const char* source)
68
+ {
69
+ #ifdef IOS
70
+ static const String SHARED_HEADER = "precision mediump float;\n";
71
+ static const std::regex PRECISION(R"(^\s*precision\s+\w+p\s+float\s*;)");
72
+
73
+ if (!std::regex_search(source, PRECISION))
74
+ return ShaderSource(GL_FRAGMENT_SHADER, SHARED_HEADER + source);
75
+ else
76
+ return ShaderSource(GL_FRAGMENT_SHADER, source);
77
+ #else
78
+ return ShaderSource(GL_FRAGMENT_SHADER, source);
79
+ #endif
80
+ }
81
+
70
82
  };// Shader::Data
71
83
 
72
84
 
85
+ static Shader
86
+ make_default_shader_for_shape ()
87
+ {
88
+ const ShaderBuiltinVariableNames& names =
89
+ ShaderEnv_get_builtin_variable_names(DEFAULT_ENV);
90
+ return Shader(
91
+ "varying vec4 " + V_COLOR + ";\n"
92
+ "void main ()\n"
93
+ "{\n"
94
+ " gl_FragColor = " + V_COLOR + ";\n"
95
+ "}\n");
96
+ }
97
+
98
+ static Shader
99
+ make_default_shader_for_texture ()
100
+ {
101
+ const ShaderBuiltinVariableNames& names =
102
+ ShaderEnv_get_builtin_variable_names(DEFAULT_ENV);
103
+ return Shader(
104
+ "varying vec4 " + V_TEXCOORD + ";\n"
105
+ "varying vec4 " + V_COLOR + ";\n"
106
+ "uniform vec3 " + U_TEXCOORD_MIN + ";\n"
107
+ "uniform vec3 " + U_TEXCOORD_MAX + ";\n"
108
+ "uniform sampler2D " + U_TEXTURE + ";\n"
109
+ "void main ()\n"
110
+ "{\n"
111
+ " vec2 min__ = " + U_TEXCOORD_MIN + ".xy;\n"
112
+ " vec2 len__ = " + U_TEXCOORD_MAX + ".xy - min__;\n"
113
+ " vec2 texcoord__ = mod(" + V_TEXCOORD + ".xy - min__, len__) + min__;\n"
114
+ " vec4 color__ = texture2D(" + U_TEXTURE + ", texcoord__);\n"
115
+ " gl_FragColor = " + V_COLOR + " * color__;\n"
116
+ "}\n");
117
+ }
118
+
119
+ static Shader
120
+ make_shader_for_text ()
121
+ {
122
+ const ShaderBuiltinVariableNames& names =
123
+ ShaderEnv_get_builtin_variable_names(DEFAULT_ENV);
124
+ return Shader(
125
+ "varying vec4 " + V_TEXCOORD + ";\n"
126
+ "varying vec4 " + V_COLOR + ";\n"
127
+ "uniform sampler2D " + U_TEXTURE + ";\n"
128
+ "void main ()\n"
129
+ "{\n"
130
+ " vec4 col__ = texture2D(" + U_TEXTURE + ", " + V_TEXCOORD + ".xy);\n"
131
+ #ifdef OSX
132
+ // restore premultiplied rgb values
133
+ " vec3 rgb__ = col__.a != 0.0 ? col__.rgb / col__.a : col__.rgb;\n"
134
+ " gl_FragColor = " + V_COLOR + " * vec4(rgb__, col__.a);\n"
135
+ #else
136
+ " gl_FragColor = " + V_COLOR + " * col__;\n"
137
+ #endif
138
+ "}\n");
139
+ }
140
+
73
141
  const ShaderProgram*
74
142
  Shader_get_program (const Shader& shader)
75
143
  {
76
144
  return shader.self->program ? shader.self->program.get() : NULL;
77
145
  }
78
146
 
147
+ const ShaderBuiltinVariableNames&
148
+ Shader_get_builtin_variable_names (const Shader& shader)
149
+ {
150
+ return ShaderEnv_get_builtin_variable_names(
151
+ shader.self->env ? *shader.self->env : DEFAULT_ENV);
152
+ }
153
+
154
+ const Shader&
155
+ Shader_get_default_shader_for_shape ()
156
+ {
157
+ static const Shader SHADER = make_default_shader_for_shape();
158
+ return SHADER;
159
+ }
160
+
161
+ const Shader&
162
+ Shader_get_default_shader_for_texture ()
163
+ {
164
+ static const Shader SHADER = make_default_shader_for_texture();
165
+ return SHADER;
166
+ }
167
+
168
+ const Shader&
169
+ Shader_get_shader_for_text ()
170
+ {
171
+ static const Shader SHADER = make_shader_for_text();
172
+ return SHADER;
173
+ }
79
174
 
80
- Shader::Shader (const char* source)
175
+
176
+ Shader::Shader (
177
+ const char* fragment_shader_source,
178
+ const char* vertex_shader_source)
179
+ : self(new Data(fragment_shader_source, vertex_shader_source, NULL))
81
180
  {
82
- if (!source) return;
181
+ }
83
182
 
84
- self->program.reset(new ShaderProgram(
85
- get_vertex_shader_source(),
86
- make_fragment_shader_source(source)));
183
+ Shader::Shader (
184
+ const char* fragment_shader_source,
185
+ const char* vertex_shader_source,
186
+ ShaderEnv env)
187
+ : self(new Data(fragment_shader_source, vertex_shader_source, &env))
188
+ {
87
189
  }
88
190
 
89
191
  Shader::~Shader ()
@@ -217,6 +319,22 @@ namespace Rays
217
319
  self->program->set_uniform(name, Image_get_texture(texture));
218
320
  }
219
321
 
322
+ const char*
323
+ Shader::vertex_shader_source () const
324
+ {
325
+ return self->program
326
+ ? self->program->vertex_shader_source().source()
327
+ : NULL;
328
+ }
329
+
330
+ const char*
331
+ Shader::fragment_shader_source () const
332
+ {
333
+ return self->program
334
+ ? self->program->fragment_shader_source().source()
335
+ : NULL;
336
+ }
337
+
220
338
  Shader::operator bool () const
221
339
  {
222
340
  return self->program && *self->program;
@@ -241,4 +359,166 @@ namespace Rays
241
359
  }
242
360
 
243
361
 
362
+ struct ShaderEnv::Data
363
+ {
364
+
365
+ ShaderBuiltinVariableNames names;
366
+
367
+ uint flags;
368
+
369
+ ShaderSource default_vertex_shader_source;
370
+
371
+ Data (const ShaderBuiltinVariableNames& names, uint flags)
372
+ : names(names), flags(flags)
373
+ {
374
+ }
375
+
376
+ String make_default_vertex_shader_source_code ()
377
+ {
378
+ return
379
+ "attribute vec3 " + A_POSITION + ";\n"
380
+ "attribute vec3 " + A_TEXCOORD + ";\n"
381
+ "attribute vec4 " + A_COLOR + ";\n"
382
+ "varying vec4 " + V_POSITION + ";\n"
383
+ "varying vec4 " + V_TEXCOORD + ";\n"
384
+ "varying vec4 " + V_COLOR + ";\n"
385
+ "uniform mat4 " + U_POSITION_MATRIX + ";\n"
386
+ "uniform mat4 " + U_TEXCOORD_MATRIX + ";\n"
387
+ "void main ()\n"
388
+ "{\n"
389
+ " vec4 pos__ = vec4(" + A_POSITION + ", 1.0);\n"
390
+ " vec4 texcoord__ = vec4(" + A_TEXCOORD + ", 1.0);\n"
391
+ " " + V_POSITION + " = pos__;\n"
392
+ " " + V_TEXCOORD + " = " + U_TEXCOORD_MATRIX + " * texcoord__;\n"
393
+ " " + V_COLOR + " = " + A_COLOR + ";\n"
394
+ " gl_Position = " + U_POSITION_MATRIX + " * pos__;\n"
395
+ "}\n";
396
+ }
397
+
398
+ };// ShaderEnv::Data
399
+
400
+
401
+ const ShaderBuiltinVariableNames&
402
+ ShaderEnv_get_builtin_variable_names (const ShaderEnv& env)
403
+ {
404
+ return env.self->names;
405
+ }
406
+
407
+ uint
408
+ ShaderEnv_get_flags (const ShaderEnv& env)
409
+ {
410
+ return env.self->flags;
411
+ }
412
+
413
+ const ShaderSource&
414
+ ShaderEnv_get_default_vertex_shader_source (ShaderEnv* env)
415
+ {
416
+ if (!env)
417
+ argument_error(__FILE__, __LINE__);
418
+
419
+ ShaderEnv::Data* self = env->self.get();
420
+
421
+ if (!self->default_vertex_shader_source)
422
+ {
423
+ self->default_vertex_shader_source = ShaderSource(
424
+ GL_VERTEX_SHADER, self->make_default_vertex_shader_source_code());
425
+ }
426
+ return self->default_vertex_shader_source;
427
+ }
428
+
429
+
430
+ ShaderEnv::ShaderEnv (
431
+ const NameList& a_position_names,
432
+ const NameList& a_texcoord_names,
433
+ const NameList& a_color_names,
434
+ const char* v_position_name,
435
+ const char* v_texcoord_name,
436
+ const char* v_color_name,
437
+ const NameList& u_position_matrix_names,
438
+ const NameList& u_texcoord_matrix_names,
439
+ const NameList& u_texcoord_min_names,
440
+ const NameList& u_texcoord_max_names,
441
+ const NameList& u_texcoord_offset_names,
442
+ const NameList& u_texture_names,
443
+ uint flags)
444
+ : self(new Data(
445
+ ShaderBuiltinVariableNames(
446
+ a_position_names, a_texcoord_names, a_color_names,
447
+ v_position_name, v_texcoord_name, v_color_name,
448
+ u_position_matrix_names, u_texcoord_matrix_names,
449
+ u_texcoord_min_names, u_texcoord_max_names, u_texcoord_offset_names,
450
+ u_texture_names),
451
+ flags))
452
+ {
453
+ }
454
+
455
+
456
+ static void
457
+ validate_name (const String& name, const char* for_variable)
458
+ {
459
+ assert(for_variable);
460
+
461
+ if (name.empty())
462
+ {
463
+ argument_error(
464
+ __FILE__, __LINE__,
465
+ "invalid variable name '%s' for '%s'", name.c_str(), for_variable);
466
+ }
467
+ }
468
+
469
+ static void
470
+ validate_names (
471
+ ShaderEnv::NameList* names,
472
+ const char* for_variable,
473
+ const char* default_name)
474
+ {
475
+ assert(names && for_variable && default_name);
476
+
477
+ if (names->empty()) names->emplace_back(default_name);
478
+
479
+ for (const auto& name : *names)
480
+ validate_name(name, for_variable);
481
+ }
482
+
483
+ ShaderBuiltinVariableNames::ShaderBuiltinVariableNames (
484
+ const ShaderEnv::NameList& a_position,
485
+ const ShaderEnv::NameList& a_texcoord,
486
+ const ShaderEnv::NameList& a_color,
487
+ const char* v_position,
488
+ const char* v_texcoord,
489
+ const char* v_color,
490
+ const ShaderEnv::NameList& u_position_matrix,
491
+ const ShaderEnv::NameList& u_texcoord_matrix,
492
+ const ShaderEnv::NameList& u_texcoord_min,
493
+ const ShaderEnv::NameList& u_texcoord_max,
494
+ const ShaderEnv::NameList& u_texcoord_offset,
495
+ const ShaderEnv::NameList& u_texture)
496
+ : attribute_position_names(a_position),
497
+ attribute_texcoord_names(a_texcoord),
498
+ attribute_color_names(a_color),
499
+ varying_position_name(v_position ? v_position : "v_Position"),
500
+ varying_texcoord_name(v_texcoord ? v_texcoord : "v_TexCoord"),
501
+ varying_color_name( v_color ? v_color : "v_Color"),
502
+ uniform_position_matrix_names(u_position_matrix),
503
+ uniform_texcoord_matrix_names(u_texcoord_matrix),
504
+ uniform_texcoord_min_names(u_texcoord_min),
505
+ uniform_texcoord_max_names(u_texcoord_max),
506
+ uniform_texcoord_offset_names(u_texcoord_offset),
507
+ uniform_texture_names(u_texture)
508
+ {
509
+ validate_names(&attribute_position_names, "attribute_position", "a_Position");
510
+ validate_names(&attribute_texcoord_names, "attribute_texcoord", "a_TexCoord");
511
+ validate_names(&attribute_color_names, "attribute_color", "a_Color");
512
+ validate_name(varying_position_name, "varying_position");
513
+ validate_name(varying_texcoord_name, "varying_texcoord");
514
+ validate_name(varying_color_name, "varying_color");
515
+ validate_names(&uniform_position_matrix_names, "uniform_position_matrix", "u_PositionMatrix");
516
+ validate_names(&uniform_texcoord_matrix_names, "uniform_texcoord_matrix", "u_TexCoordMatrix");
517
+ validate_names(&uniform_texcoord_min_names, "uniform_texcoord_min", "u_TexCoordMin");
518
+ validate_names(&uniform_texcoord_max_names, "uniform_texcoord_max", "u_TexCoordMax");
519
+ validate_names(&uniform_texcoord_offset_names, "uniform_texcoord_offset", "u_TexCoordOffset");
520
+ validate_names(&uniform_texture_names, "uniform_texture", "u_Texture");
521
+ }
522
+
523
+
244
524
  }// Rays
data/src/shader.h CHANGED
@@ -11,26 +11,65 @@ namespace Rays
11
11
  {
12
12
 
13
13
 
14
- #define ATTRIB_POSITION "a_Position"
15
- #define VARYING_POSITION "v_Position"
16
- #define UNIFORM_POSITION_MATRIX "u_PositionMatrix"
17
- #define ATTRIB_TEXCOORD "a_TexCoord"
18
- #define VARYING_TEXCOORD "v_TexCoord"
19
- #define UNIFORM_TEXCOORD_MIN "u_TexCoordMin"
20
- #define UNIFORM_TEXCOORD_MAX "u_TexCoordMax"
21
- #define UNIFORM_TEXCOORD_MATRIX "u_TexCoordMatrix"
22
- #define ATTRIB_COLOR "a_Color"
23
- #define VARYING_COLOR "v_Color"
24
- //#define UNIFORM_COLOR_MATRIX "u_ColorMatrix"
25
- #define UNIFORM_TEXTURE "u_Texture"
26
- #define UNIFORM_TEXTURE_SIZE "u_TextureSize"
14
+ class ShaderSource;
15
+ class ShaderProgram;
27
16
 
28
17
 
29
- class ShaderProgram;
18
+ struct ShaderBuiltinVariableNames
19
+ {
20
+
21
+ ShaderEnv::NameList attribute_position_names;
22
+ ShaderEnv::NameList attribute_texcoord_names;
23
+ ShaderEnv::NameList attribute_color_names;
24
+
25
+ String varying_position_name;
26
+ String varying_texcoord_name;
27
+ String varying_color_name;
28
+
29
+ ShaderEnv::NameList uniform_position_matrix_names;
30
+ ShaderEnv::NameList uniform_texcoord_matrix_names;
31
+ ShaderEnv::NameList uniform_texcoord_min_names;
32
+ ShaderEnv::NameList uniform_texcoord_max_names;
33
+ ShaderEnv::NameList uniform_texcoord_offset_names;
34
+ ShaderEnv::NameList uniform_texture_names;
35
+
36
+ ShaderBuiltinVariableNames (
37
+ const ShaderEnv::NameList& attribute_position_names,
38
+ const ShaderEnv::NameList& attribute_texcoord_names,
39
+ const ShaderEnv::NameList& attribute_color_names,
40
+ const char* varying_position_name,
41
+ const char* varying_texcoord_name,
42
+ const char* varying_color_name,
43
+ const ShaderEnv::NameList& uniform_position_matrix_names,
44
+ const ShaderEnv::NameList& uniform_texcoord_matrix_names,
45
+ const ShaderEnv::NameList& uniform_texcoord_min_names,
46
+ const ShaderEnv::NameList& uniform_texcoord_max_names,
47
+ const ShaderEnv::NameList& uniform_texcoord_offset_names,
48
+ const ShaderEnv::NameList& uniform_texture_names);
49
+
50
+ };// ShaderBuiltinVariableNames
30
51
 
31
52
 
32
53
  const ShaderProgram* Shader_get_program (const Shader& shader);
33
54
 
55
+ const ShaderBuiltinVariableNames& Shader_get_builtin_variable_names (
56
+ const Shader& shader);
57
+
58
+ const Shader& Shader_get_default_shader_for_shape ();
59
+
60
+ const Shader& Shader_get_default_shader_for_texture ();
61
+
62
+ const Shader& Shader_get_shader_for_text ();
63
+
64
+
65
+ const ShaderBuiltinVariableNames& ShaderEnv_get_builtin_variable_names (
66
+ const ShaderEnv& env);
67
+
68
+ uint ShaderEnv_get_flags (const ShaderEnv& env);
69
+
70
+ const ShaderSource& ShaderEnv_get_default_vertex_shader_source (
71
+ ShaderEnv* env);
72
+
34
73
 
35
74
  }// Rays
36
75
 
@@ -5,6 +5,7 @@
5
5
  #include <vector>
6
6
  #include <memory>
7
7
  #include <algorithm>
8
+ #include "rays/shader.h"
8
9
  #include "rays/exception.h"
9
10
  #include "shader_source.h"
10
11
  #include "texture.h"
@@ -35,7 +36,7 @@ namespace Rays
35
36
 
36
37
  virtual ~UniformValue () {}
37
38
 
38
- virtual void apply (GLint location) const = 0;
39
+ virtual bool apply (size_t index, GLint location) const = 0;
39
40
 
40
41
  };// UniformValue
41
42
 
@@ -83,10 +84,10 @@ namespace Rays
83
84
  array[i] = args[i];
84
85
  }
85
86
 
86
- void apply (GLint location) const
87
+ bool apply (size_t index, GLint location) const
87
88
  {
88
89
  apply_value(location);
89
- OpenGL_check_error(__FILE__, __LINE__);
90
+ return !OpenGL_has_error();
90
91
  }
91
92
 
92
93
  void apply_value (GLint location) const;
@@ -149,18 +150,20 @@ namespace Rays
149
150
  {
150
151
  }
151
152
 
152
- void apply (GLint location) const
153
+ bool apply (size_t index, GLint location) const
153
154
  {
154
- if (!texture) return;
155
+ if (!texture)
156
+ shader_error(__FILE__, __LINE__, "invalid texture");
155
157
 
156
- GLint unit_max = get_texture_unit_max();
157
- GLint unit = unit_max;
158
- glGetIntegerv(GL_ACTIVE_TEXTURE, &unit);
159
- assert(unit < unit_max);
158
+ GLint unit = (GLint) (index + 1);// GL_TEXTURE0 is used by apply_builtin_uniforms()
159
+ GLint max = get_texture_unit_max();
160
+ if (unit >= max)
161
+ shader_error(__FILE__, __LINE__, "texture unit must be less than %d", max);
160
162
 
163
+ glActiveTexture(GL_TEXTURE0 + unit);
161
164
  glBindTexture(GL_TEXTURE_2D, texture.id());
162
165
  glUniform1i(location, unit);
163
- OpenGL_check_error(__FILE__, __LINE__);
166
+ return !OpenGL_has_error();
164
167
  }
165
168
 
166
169
  private:
@@ -205,15 +208,20 @@ namespace Rays
205
208
  self->applied = false;
206
209
  }
207
210
 
208
- void apply (const ShaderProgram& program) const
211
+ void apply (
212
+ size_t index, const ShaderProgram& program,
213
+ bool ignore_no_uniform_location_error) const
209
214
  {
210
215
  if (!program || self->applied) return;
211
216
  self->applied = true;
212
217
 
213
- GLint location = glGetUniformLocation(program.id(), self->name);
214
- if (location < 0) return;
218
+ const char* name = self->name;
219
+ GLint location = glGetUniformLocation(program.id(), name);
220
+ if (location < 0 && !ignore_no_uniform_location_error)
221
+ shader_error(__FILE__, __LINE__, "uniform location '%s' not found", name);
215
222
 
216
- self->value->apply(location);
223
+ if (!self->value->apply(index, location))
224
+ shader_error(__FILE__, __LINE__, "failed to apply uniform variable '%s'", name);
217
225
  }
218
226
 
219
227
  bool operator == (const Uniform& rhs) const
@@ -235,7 +243,9 @@ namespace Rays
235
243
  struct ShaderProgram::Data
236
244
  {
237
245
 
238
- GLuint id = 0;
246
+ GLuint id = 0;
247
+
248
+ uint flags = 0;
239
249
 
240
250
  ShaderSource vertex, fragment;
241
251
 
@@ -266,7 +276,7 @@ namespace Rays
266
276
  void set_uniform_texture (const char* name, const UniformValue* value)
267
277
  {
268
278
  if (uniform_textures.size() >= (size_t) get_texture_unit_max())
269
- opengl_error(__FILE__, __LINE__, "too many texture units.");
279
+ shader_error(__FILE__, __LINE__, "too many texture units.");
270
280
 
271
281
  set_uniform(&uniform_textures, name, value);
272
282
  }
@@ -311,7 +321,14 @@ namespace Rays
311
321
  GLint status = GL_FALSE;
312
322
  glGetProgramiv(id, GL_LINK_STATUS, &status);
313
323
  if (status == GL_FALSE)
314
- opengl_error(__FILE__, __LINE__, get_link_log().c_str());
324
+ shader_error(__FILE__, __LINE__, get_link_log().c_str());
325
+
326
+ glValidateProgram(id);
327
+
328
+ GLint validate = GL_FALSE;
329
+ glGetProgramiv(id, GL_VALIDATE_STATUS, &validate);
330
+ if (validate == GL_FALSE)
331
+ OpenGL_check_error(__FILE__, __LINE__, "shader program validation failed");
315
332
  }
316
333
 
317
334
  void attach_shader (const ShaderSource& source) const
@@ -343,17 +360,13 @@ namespace Rays
343
360
  if (applied) return;
344
361
  applied = true;
345
362
 
346
- for (const auto& value : uniform_values)
347
- value.apply(program);
363
+ bool ignore_no_loc = flags & ShaderEnv::IGNORE_NO_UNIFORM_LOCATION_ERROR;
348
364
 
349
- int unit = 0;
350
- for (const auto& texture : uniform_textures)
351
- {
352
- glActiveTexture(unit++);
353
- texture.apply(program);
354
- }
365
+ for (size_t i = 0; i < uniform_values.size(); ++i)
366
+ uniform_values[i].apply(i, program, ignore_no_loc);
355
367
 
356
- OpenGL_check_error(__FILE__, __LINE__);
368
+ for (size_t i = 0; i < uniform_textures.size(); ++i)
369
+ uniform_textures[i].apply(i, program, ignore_no_loc);
357
370
  }
358
371
 
359
372
  };// ShaderProgram::Data
@@ -383,10 +396,11 @@ namespace Rays
383
396
 
384
397
 
385
398
  ShaderProgram::ShaderProgram (
386
- const ShaderSource& vertex, const ShaderSource& fragment)
399
+ const ShaderSource& vertex, const ShaderSource& fragment, uint flags)
387
400
  {
388
401
  self->vertex = vertex;
389
402
  self->fragment = fragment;
403
+ self->flags = flags;
390
404
  }
391
405
 
392
406
  ShaderProgram::~ShaderProgram ()
@@ -500,6 +514,18 @@ namespace Rays
500
514
  self->set_uniform_texture(name, new UniformTexture(texture));
501
515
  }
502
516
 
517
+ const ShaderSource&
518
+ ShaderProgram::vertex_shader_source () const
519
+ {
520
+ return self->vertex;
521
+ }
522
+
523
+ const ShaderSource&
524
+ ShaderProgram::fragment_shader_source () const
525
+ {
526
+ return self->fragment;
527
+ }
528
+
503
529
  GLuint
504
530
  ShaderProgram::id () const
505
531
  {
data/src/shader_program.h CHANGED
@@ -25,7 +25,10 @@ namespace Rays
25
25
 
26
26
  public:
27
27
 
28
- ShaderProgram (const ShaderSource& vertex, const ShaderSource& fragment);
28
+ ShaderProgram (
29
+ const ShaderSource& vertex,
30
+ const ShaderSource& fragment,
31
+ uint flags);
29
32
 
30
33
  ~ShaderProgram ();
31
34
 
@@ -59,6 +62,10 @@ namespace Rays
59
62
 
60
63
  GLuint id () const;
61
64
 
65
+ const ShaderSource& vertex_shader_source () const;
66
+
67
+ const ShaderSource& fragment_shader_source () const;
68
+
62
69
  operator bool () const;
63
70
 
64
71
  bool operator ! () const;