Class: Nuklear::Renderer::OpenGL4

Inherits:
Nuklear::Renderer show all
Defined in:
ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c

Constant Summary

Constants inherited from Nuklear::Renderer

Vertex

Instance Attribute Summary

Attributes inherited from Nuklear::Renderer

#commands, #context, #convert_config, #drawable_size, #null_texture_handle, #vertex_indices, #vertices, #window_size

Instance Method Summary collapse

Methods inherited from Nuklear::Renderer

#nk_draw_foreach, renderer_class

Constructor Details

#initializeObject



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
# File 'ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c', line 57

VALUE renderer_initialize(VALUE self) {
  if (!gladLoadGL())
    rb_raise(rb_eStandardError, "Failed to init GLAD");
  // printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));

  rb_call_super(0, NULL);

  int status;
  int prog = glCreateProgram();
  int vert_shdr = glCreateShader(GL_VERTEX_SHADER);
  int frag_shdr = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(vert_shdr, 1, &vertex_shader, 0);
  glShaderSource(frag_shdr, 1, &fragment_shader, 0);
  glCompileShader(vert_shdr);
  glCompileShader(frag_shdr);
  glGetShaderiv(vert_shdr, GL_COMPILE_STATUS, &status);
  assert(status == GL_TRUE);
  glGetShaderiv(frag_shdr, GL_COMPILE_STATUS, &status);
  assert(status == GL_TRUE);
  glAttachShader(prog, vert_shdr);
  glAttachShader(prog, frag_shdr);
  glLinkProgram(prog);
  glGetProgramiv(prog, GL_LINK_STATUS, &status);
  assert(status == GL_TRUE);

  int uniform_tex  = glGetUniformLocation(prog, "Texture");
  int uniform_proj = glGetUniformLocation(prog, "ProjMtx");
  int attrib_pos   = glGetAttribLocation(prog, "Position");
  int attrib_uv    = glGetAttribLocation(prog, "TexCoord");
  int attrib_col   = glGetAttribLocation(prog, "Color");

  /* buffer setup */
  GLsizei vs = sizeof(struct vertex);
  size_t vp = offsetof(struct vertex, position);
  size_t vt = offsetof(struct vertex, uv);
  size_t vc = offsetof(struct vertex, col);

  GLuint vbo, ebo, vao;

  glGenBuffers(1, &vbo);
  glGenBuffers(1, &ebo);
  glGenVertexArrays(1, &vao);

  glBindVertexArray(vao);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

  glEnableVertexAttribArray((GLuint)attrib_pos);
  glEnableVertexAttribArray((GLuint)attrib_uv);
  glEnableVertexAttribArray((GLuint)attrib_col);

  glVertexAttribPointer((GLuint)attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp);
  glVertexAttribPointer((GLuint)attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt);
  glVertexAttribPointer((GLuint)attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc);

  glBindTexture(GL_TEXTURE_2D, 0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  glBindVertexArray(0);

  rb_ivar_set(self, rb_intern("@program"),      INT2FIX(prog));
  rb_ivar_set(self, rb_intern("@uniform_tex"),  INT2FIX(uniform_tex));
  rb_ivar_set(self, rb_intern("@uniform_proj"), INT2FIX(uniform_proj));
  rb_ivar_set(self, rb_intern("@vao"),          INT2FIX(vao));
  rb_ivar_set(self, rb_intern("@vbo"),          INT2FIX(vbo));
  rb_ivar_set(self, rb_intern("@ebo"),          INT2FIX(ebo));

  return self;
}

Instance Method Details

#draw(cmd) ⇒ Object



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
# File 'ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c', line 213

VALUE renderer_draw_gl(VALUE self, VALUE cmd) {
  VALUE window_size = rb_funcall(self, rb_intern("window_size"), 0);
  VALUE drawable_size = rb_funcall(self, rb_intern("drawable_size"), 0);
  VALUE window_width = rb_ary_entry(window_size, 0);
  VALUE window_height = rb_ary_entry(window_size, 1);
  VALUE drawable_width = rb_ary_entry(drawable_size, 0);
  VALUE drawable_height = rb_ary_entry(drawable_size, 1);
  int width = FIX2INT(window_width),
      height = FIX2INT(window_height);
  int display_width = FIX2INT(drawable_width),
      display_height = FIX2INT(drawable_height);
  struct nk_vec2 scale;
  scale.x = (float)display_width/(float)width;
  scale.y = (float)display_height/(float)height;

  VALUE clip_rect = rb_hash_aref(cmd, ID2SYM(rb_intern("clip_rect")));
  float x = (float) NUM2DBL(RARRAY_AREF(clip_rect, 0));
  float y = (float) NUM2DBL(RARRAY_AREF(clip_rect, 1));
  float w = (float) NUM2DBL(RARRAY_AREF(clip_rect, 2));
  float h = (float) NUM2DBL(RARRAY_AREF(clip_rect, 3));
  glBindTexture(GL_TEXTURE_2D, (GLuint) NUM2UINT(rb_hash_aref(cmd, ID2SYM(rb_intern("texture_handle")))));
  glScissor((GLint)(x * scale.x),
            (GLint)((height - (GLint)(y + h)) * scale.y),
            (GLint)(w * scale.x),
            (GLint)(h * scale.y));
  glDrawElements(GL_TRIANGLES, (GLsizei)NUM2UINT(rb_hash_aref(cmd, ID2SYM(rb_intern("element_count")))),
                 GL_UNSIGNED_SHORT, (void *) NUM2UINT(rb_hash_aref(cmd, ID2SYM(rb_intern("offset")))));
  return self;
}

#nk_convert(rcontext) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c', line 188

VALUE renderer_nk_convert_gl(VALUE self, VALUE rcontext) {
  VALUE result = rb_call_super(1, &rcontext);

  struct nk_buffer *vertices = NULL;
  struct nk_buffer *indices  = NULL;
  Data_Get_Struct(rb_funcall(self, rb_intern("vertices"), 0),       struct nk_buffer, vertices);
  Data_Get_Struct(rb_funcall(self, rb_intern("vertex_indices"), 0), struct nk_buffer, indices);

  int vao = FIX2INT(rb_ivar_get(self, rb_intern("@vao")));
  int vbo = FIX2INT(rb_ivar_get(self, rb_intern("@vbo")));
  int ebo = FIX2INT(rb_ivar_get(self, rb_intern("@ebo")));
  glBindVertexArray(vao);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  glBufferData(GL_ARRAY_BUFFER,
               MAX_VERTEX_MEMORY,
               nk_buffer_memory_const(vertices),
               GL_STREAM_DRAW);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER,
               MAX_ELEMENT_MEMORY,
               nk_buffer_memory_const(indices),
               GL_STREAM_DRAW);
  return result;
}

#render(rcontext) ⇒ Object



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
# File 'ext/nuklear_renderer_opengl4/nuklear_renderer_opengl4.c', line 127

VALUE renderer_render_gl(VALUE self, VALUE rcontext) {
  struct nk_buffer *cmds;
  VALUE window_size = rb_funcall(self, rb_intern("window_size"), 0);
  VALUE drawable_size = rb_funcall(self, rb_intern("drawable_size"), 0);
  VALUE window_width = rb_ary_entry(window_size, 0);
  VALUE window_height = rb_ary_entry(window_size, 1);
  VALUE drawable_width = rb_ary_entry(drawable_size, 0);
  VALUE drawable_height = rb_ary_entry(drawable_size, 1);
  int program = FIX2INT(rb_ivar_get(self, rb_intern("@program")));
  int uniform_tex = FIX2INT(rb_ivar_get(self, rb_intern("@uniform_tex")));
  int uniform_proj = FIX2INT(rb_ivar_get(self, rb_intern("@uniform_proj")));
  int width = FIX2INT(window_width),
      height = FIX2INT(window_height);
  int display_width = FIX2INT(drawable_width),
      display_height = FIX2INT(drawable_height);
  struct nk_draw_null_texture *null_tex;
  struct nk_vec2 scale;
  VALUE context = rb_ivar_get(self, rb_intern("@context"));
  Data_Get_Struct(rb_ivar_get(context, rb_intern("@null")), struct nk_draw_null_texture, null_tex);
  Data_Get_Struct(rb_ivar_get(self, rb_intern("@commands")), struct nk_buffer, cmds);

  GLfloat ortho[4][4] = {
      {2.0f, 0.0f, 0.0f, 0.0f},
      {0.0f,-2.0f, 0.0f, 0.0f},
      {0.0f, 0.0f,-1.0f, 0.0f},
      {-1.0f,1.0f, 0.0f, 1.0f},
  };
  ortho[0][0] /= (GLfloat)width;
  ortho[1][1] /= (GLfloat)height;

  scale.x = (float)display_width/(float)width;
  scale.y = (float)display_height/(float)height;

  /* setup global state */
  glViewport(0,0,display_width,display_height);
  glEnable(GL_BLEND);
  glBlendEquation(GL_FUNC_ADD);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glDisable(GL_CULL_FACE);
  glDisable(GL_DEPTH_TEST);
  glEnable(GL_SCISSOR_TEST);
  glActiveTexture(GL_TEXTURE0);

  /* setup program */
  glUseProgram(program);
  glUniform1i(uniform_tex, 0);
  glUniformMatrix4fv(uniform_proj, 1, GL_FALSE, &ortho[0][0]);

  rb_call_super(1, &rcontext);

  glUseProgram(0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  glBindVertexArray(0);
  glDisable(GL_SCISSOR_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);

  return self;
}