rays 0.1.27 → 0.1.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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;