1 #include "AlphaSprite.hpp"
3 #include "CreatureSkin.hpp"
4 #include "PlanetSurface.hpp"
7 #include "SunSurface.hpp"
9 #include "ArrayTexture.hpp"
10 #include "Texture.hpp"
11 #include "../app/init.hpp"
19 #include <glm/gtc/type_ptr.hpp>
20 #include <glm/gtx/transform.hpp>
25 void gl_error(std::string msg) {
26 const GLubyte *errBegin = gluErrorString(glGetError());
27 if (errBegin && *errBegin != '\0') {
28 const GLubyte *errEnd = errBegin;
29 while (*errEnd != '\0') {
33 msg.append(errBegin, errEnd);
35 throw std::runtime_error(msg);
43 Shader::Shader(GLenum type)
44 : handle(glCreateShader(type)) {
46 gl_error("glCreateShader");
52 glDeleteShader(handle);
56 Shader::Shader(Shader &&other) noexcept
57 : handle(other.handle) {
61 Shader &Shader::operator =(Shader &&other) noexcept {
62 std::swap(handle, other.handle);
67 void Shader::Source(const GLchar *src) noexcept {
68 const GLchar* src_arr[] = { src };
69 glShaderSource(handle, 1, src_arr, nullptr);
72 void Shader::Compile() noexcept {
73 glCompileShader(handle);
76 bool Shader::Compiled() const noexcept {
77 GLint compiled = GL_FALSE;
78 glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled);
79 return compiled == GL_TRUE;
82 void Shader::Log(std::ostream &out) const {
83 int log_len = 0, max_len = 0;
84 glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &max_len);
85 std::unique_ptr<char[]> log(new char[max_len]);
86 glGetShaderInfoLog(handle, max_len, &log_len, log.get());
87 out.write(log.get(), log_len);
91 void Shader::AttachToProgram(GLuint id) const noexcept {
92 glAttachShader(id, handle);
97 : handle(glCreateProgram()) {
99 gl_error("glCreateProgram");
103 Program::~Program() {
105 glDeleteProgram(handle);
110 const Shader &Program::LoadShader(GLenum type, const GLchar *src) {
111 shaders.emplace_back(type);
112 Shader &shader = shaders.back();
115 if (!shader.Compiled()) {
116 shader.Log(std::cerr);
117 throw std::runtime_error("compile shader");
123 void Program::Attach(Shader &shader) noexcept {
124 shader.AttachToProgram(handle);
127 void Program::Link() noexcept {
128 glLinkProgram(handle);
131 bool Program::Linked() const noexcept {
132 GLint linked = GL_FALSE;
133 glGetProgramiv(handle, GL_LINK_STATUS, &linked);
134 return linked == GL_TRUE;
137 void Program::Log(std::ostream &out) const {
138 int log_len = 0, max_len = 0;
139 glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &max_len);
140 std::unique_ptr<char[]> log(new char[max_len]);
141 glGetProgramInfoLog(handle, max_len, &log_len, log.get());
142 out.write(log.get(), log_len);
146 GLint Program::AttributeLocation(const GLchar *name) const noexcept {
147 return glGetAttribLocation(handle, name);
150 GLint Program::AttributeLocation(const std::string &name) const noexcept {
151 return AttributeLocation(name.c_str());
154 GLint Program::UniformLocation(const GLchar *name) const noexcept {
155 return glGetUniformLocation(handle, name);
158 GLint Program::UniformLocation(const std::string &name) const noexcept {
159 return UniformLocation(name.c_str());
163 void Program::Uniform(GLint loc, GLint val) noexcept {
164 glUniform1i(loc, val);
167 void Program::Uniform(GLint loc, float val) noexcept {
168 glUniform1f(loc, val);
171 void Program::Uniform(GLint loc, const glm::vec3 &val) noexcept {
172 glUniform3fv(loc, 1, glm::value_ptr(val));
175 void Program::Uniform(GLint loc, const glm::vec4 &val) noexcept {
176 glUniform4fv(loc, 1, glm::value_ptr(val));
179 void Program::Uniform(GLint loc, const glm::mat4 &val) noexcept {
180 glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(val));
184 constexpr int PlanetSurface::MAX_LIGHTS;
186 PlanetSurface::PlanetSurface()
190 "#version 330 core\n"
192 "layout(location = 0) in vec3 vtx_position;\n"
193 "layout(location = 1) in vec3 vtx_normal;\n"
194 "layout(location = 2) in vec3 vtx_tex_uv;\n"
198 "uniform mat4 MVP;\n"
200 "out vec3 vtx_viewspace;\n"
201 "out vec3 nrm_viewspace;\n"
202 "out vec3 frag_tex_uv;\n"
205 "gl_Position = MVP * vec4(vtx_position, 1.0);\n"
206 "vtx_viewspace = (MV * vec4(vtx_position, 1.0)).xyz;\n"
207 "nrm_viewspace = (MV * vec4(vtx_position, 0.0)).xyz;\n"
208 "frag_tex_uv = vtx_tex_uv;\n"
213 "#version 330 core\n"
215 "struct LightSource {\n"
221 "in vec3 vtx_viewspace;\n"
222 "in vec3 nrm_viewspace;\n"
223 "in vec3 frag_tex_uv;\n"
225 "uniform sampler2DArray tex_sampler;\n"
226 "uniform int num_lights;\n"
227 "uniform LightSource light[8];\n"
232 "vec3 normal = normalize(nrm_viewspace);\n"
233 "vec3 tex_color = texture(tex_sampler, frag_tex_uv).rgb;\n"
234 "vec3 total_light = tex_color * vec3(0.1, 0.1, 0.1);\n"
235 "for (int i = 0; i < num_lights; ++i) {\n"
236 "vec3 to_light = light[i].position - vtx_viewspace;\n"
237 "float distance = length(to_light) + length(vtx_viewspace);\n"
238 "vec3 light_dir = normalize(to_light);\n"
239 "float attenuation = light[i].strength / (distance * distance);\n"
240 "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * tex_color;\n"
241 "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
242 "vec3 specular = vec3(0.0, 0.0, 0.0);\n"
243 "if (dot(normal, light_dir) >= 0.0) {\n"
244 "attenuation * light[i].color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n"
246 "total_light = total_light + diffuse + specular;\n"
248 "color = total_light;\n"
252 if (!prog.Linked()) {
254 throw std::runtime_error("link program");
256 m_handle = prog.UniformLocation("M");
257 mv_handle = prog.UniformLocation("MV");
258 mvp_handle = prog.UniformLocation("MVP");
259 sampler_handle = prog.UniformLocation("tex_sampler");
260 num_lights_handle = prog.UniformLocation("num_lights");
261 for (int i = 0; i < MAX_LIGHTS; ++i) {
262 light_handle[3 * i + 0] = prog.UniformLocation("light[" + std::to_string(i) + "].position");
263 light_handle[3 * i + 1] = prog.UniformLocation("light[" + std::to_string(i) + "].color");
264 light_handle[3 * i + 2] = prog.UniformLocation("light[" + std::to_string(i) + "].strength");
268 PlanetSurface::~PlanetSurface() {
271 void PlanetSurface::Activate() noexcept {
273 glEnable(GL_DEPTH_TEST);
274 glDepthFunc(GL_LESS);
275 glEnable(GL_CULL_FACE);
279 void PlanetSurface::SetM(const glm::mat4 &mm) noexcept {
283 prog.Uniform(m_handle, m);
284 prog.Uniform(mv_handle, mv);
285 prog.Uniform(mvp_handle, mvp);
288 void PlanetSurface::SetV(const glm::mat4 &vv) noexcept {
292 prog.Uniform(mv_handle, mv);
293 prog.Uniform(mvp_handle, mvp);
296 void PlanetSurface::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
301 prog.Uniform(mv_handle, mv);
302 prog.Uniform(mvp_handle, mvp);
305 void PlanetSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
311 prog.Uniform(m_handle, m);
312 prog.Uniform(mv_handle, mv);
313 prog.Uniform(mvp_handle, mvp);
316 void PlanetSurface::SetTexture(ArrayTexture &tex) noexcept {
317 glActiveTexture(GL_TEXTURE0);
319 prog.Uniform(sampler_handle, GLint(0));
322 void PlanetSurface::SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept {
323 prog.Uniform(light_handle[3 * n + 0], pos);
324 prog.Uniform(light_handle[3 * n + 1], color);
325 prog.Uniform(light_handle[3 * n + 2], strength);
328 void PlanetSurface::SetNumLights(int n) noexcept {
329 prog.Uniform(num_lights_handle, std::min(MAX_LIGHTS, n));
333 SunSurface::SunSurface()
337 "#version 330 core\n"
339 "layout(location = 0) in vec3 vtx_position;\n"
343 "uniform mat4 MVP;\n"
345 "out vec3 vtx_viewspace;\n"
348 "gl_Position = MVP * vec4(vtx_position, 1);\n"
349 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
354 "#version 330 core\n"
356 "in vec3 vtx_viewspace;\n"
358 "uniform vec3 light_color;\n"
359 "uniform float light_strength;\n"
364 "vec3 to_light = -vtx_viewspace;\n"
365 "float distance = length(to_light);\n"
366 //"vec3 light_dir = normalize(to_light);\n"
367 "float attenuation = light_strength / (distance * distance);\n"
368 "color = attenuation * light_color;\n"
372 if (!prog.Linked()) {
374 throw std::runtime_error("link program");
376 m_handle = prog.UniformLocation("M");
377 mv_handle = prog.UniformLocation("MV");
378 mvp_handle = prog.UniformLocation("MVP");
379 light_color_handle = prog.UniformLocation("light_color");
380 light_strength_handle = prog.UniformLocation("light_strength");
382 // "resolution" of sphere
383 constexpr int size = 10;
386 vao.BindAttributes();
387 vao.EnableAttribute(0);
388 vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
389 vao.ReserveAttributes(4 * 6 * size * size, GL_STATIC_DRAW);
391 auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
393 constexpr float radius = float(size) * 0.5f;
395 for (int surface = 0; surface < 3; ++surface) {
396 for (int y = 0; y < size; ++y) {
397 for (int x = 0; x < size; ++x, ++index) {
399 pos[0][(surface + 0) % 3] = float(x + 0) - radius;
400 pos[0][(surface + 1) % 3] = float(y + 0) - radius;
401 pos[0][(surface + 2) % 3] = radius;
402 pos[1][(surface + 0) % 3] = float(x + 0) - radius;
403 pos[1][(surface + 1) % 3] = float(y + 1) - radius;
404 pos[1][(surface + 2) % 3] = radius;
405 pos[2][(surface + 0) % 3] = float(x + 1) - radius;
406 pos[2][(surface + 1) % 3] = float(y + 0) - radius;
407 pos[2][(surface + 2) % 3] = radius;
408 pos[3][(surface + 0) % 3] = float(x + 1) - radius;
409 pos[3][(surface + 1) % 3] = float(y + 1) - radius;
410 pos[3][(surface + 2) % 3] = radius;
411 attrib[4 * index + 0].position = glm::normalize(pos[0]);
412 attrib[4 * index + 1].position = glm::normalize(pos[1]);
413 attrib[4 * index + 2].position = glm::normalize(pos[2]);
414 attrib[4 * index + 3].position = glm::normalize(pos[3]);
418 for (int surface = 3; surface < 6; ++surface) {
419 for (int y = 0; y < size; ++y) {
420 for (int x = 0; x < size; ++x, ++index) {
422 pos[0][(surface + 0) % 3] = float(x + 0) - radius;
423 pos[0][(surface + 1) % 3] = float(y + 0) - radius;
424 pos[0][(surface + 2) % 3] = radius;
425 pos[1][(surface + 0) % 3] = float(x + 0) - radius;
426 pos[1][(surface + 1) % 3] = float(y + 1) - radius;
427 pos[1][(surface + 2) % 3] = radius;
428 pos[2][(surface + 0) % 3] = float(x + 1) - radius;
429 pos[2][(surface + 1) % 3] = float(y + 0) - radius;
430 pos[2][(surface + 2) % 3] = radius;
431 pos[3][(surface + 0) % 3] = float(x + 1) - radius;
432 pos[3][(surface + 1) % 3] = float(y + 1) - radius;
433 pos[3][(surface + 2) % 3] = radius;
434 attrib[4 * index + 0].position = glm::normalize(pos[0]) * -1.0f;
435 attrib[4 * index + 1].position = glm::normalize(pos[1]) * -1.0f;
436 attrib[4 * index + 2].position = glm::normalize(pos[2]) * -1.0f;
437 attrib[4 * index + 3].position = glm::normalize(pos[3]) * -1.0f;
443 vao.ReserveElements(6 * 6 * size * size, GL_STATIC_DRAW);
445 auto element = vao.MapElements(GL_WRITE_ONLY);
447 for (int surface = 0; surface < 3; ++surface) {
448 for (int y = 0; y < size; ++y) {
449 for (int x = 0; x < size; ++x, ++index) {
450 element[6 * index + 0] = 4 * index + 0;
451 element[6 * index + 1] = 4 * index + 2;
452 element[6 * index + 2] = 4 * index + 1;
453 element[6 * index + 3] = 4 * index + 1;
454 element[6 * index + 4] = 4 * index + 2;
455 element[6 * index + 5] = 4 * index + 3;
459 for (int surface = 3; surface < 6; ++surface) {
460 for (int y = 0; y < size; ++y) {
461 for (int x = 0; x < size; ++x, ++index) {
462 element[6 * index + 0] = 4 * index + 0;
463 element[6 * index + 1] = 4 * index + 1;
464 element[6 * index + 2] = 4 * index + 2;
465 element[6 * index + 3] = 4 * index + 2;
466 element[6 * index + 4] = 4 * index + 1;
467 element[6 * index + 5] = 4 * index + 3;
475 SunSurface::~SunSurface() {
478 void SunSurface::Activate() noexcept {
480 glEnable(GL_DEPTH_TEST);
481 glDepthFunc(GL_LESS);
482 glEnable(GL_CULL_FACE);
486 void SunSurface::SetM(const glm::mat4 &mm) noexcept {
490 prog.Uniform(m_handle, m);
491 prog.Uniform(mv_handle, mv);
492 prog.Uniform(mvp_handle, mvp);
495 void SunSurface::SetV(const glm::mat4 &vv) noexcept {
499 prog.Uniform(mv_handle, mv);
500 prog.Uniform(mvp_handle, mvp);
503 void SunSurface::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
508 prog.Uniform(mv_handle, mv);
509 prog.Uniform(mvp_handle, mvp);
512 void SunSurface::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
518 prog.Uniform(m_handle, m);
519 prog.Uniform(mv_handle, mv);
520 prog.Uniform(mvp_handle, mvp);
523 void SunSurface::SetLight(const glm::vec3 &color, float strength) noexcept {
524 prog.Uniform(light_color_handle, color);
525 prog.Uniform(light_strength_handle, strength);
528 void SunSurface::Draw() const noexcept {
529 constexpr int size = 10;
531 vao.DrawTriangles(6 * 6 * size * size);
535 constexpr int CreatureSkin::MAX_LIGHTS;
537 CreatureSkin::CreatureSkin()
541 "#version 330 core\n"
543 "layout(location = 0) in vec3 vtx_position;\n"
544 "layout(location = 1) in vec3 vtx_normal;\n"
545 "layout(location = 2) in vec3 vtx_tex_uv;\n"
549 "uniform mat4 MVP;\n"
551 "out vec3 vtx_viewspace;\n"
552 "out vec3 frag_tex_uv;\n"
556 "gl_Position = MVP * vec4(vtx_position, 1);\n"
557 "vtx_viewspace = (MV * vec4(vtx_position, 1)).xyz;\n"
558 "normal = normalize((MV * vec4(vtx_normal, 0)).xyz);\n"
559 "frag_tex_uv = vtx_tex_uv;\n"
564 "#version 330 core\n"
566 "struct LightSource {\n"
572 "in vec3 vtx_viewspace;\n"
573 "in vec3 frag_tex_uv;\n"
576 "uniform vec3 base_color;\n"
577 "uniform vec4 highlight_color;\n"
578 "uniform sampler2DArray tex_sampler;\n"
579 "uniform int num_lights;\n"
580 "uniform LightSource light[8];\n"
585 "vec4 tex_color = texture(tex_sampler, frag_tex_uv);\n"
586 "vec3 mat_color = mix(base_color, highlight_color.rgb, tex_color.r * tex_color.a * highlight_color.a);\n"
587 "vec3 total_light = mat_color * vec3(0.1, 0.1, 0.1);\n"
588 "for (int i = 0; i < num_lights; ++i) {\n"
589 "vec3 to_light = light[i].position - vtx_viewspace;\n"
590 "float distance = length(to_light) + length(vtx_viewspace);\n"
591 "vec3 light_dir = normalize(to_light);\n"
592 "float attenuation = light[i].strength / (distance * distance);\n"
593 "vec3 diffuse = attenuation * max(0.0, dot(normal, light_dir)) * light[i].color * mat_color;\n"
594 "vec3 view_dir = vec3(0.0, 0.0, 1.0);\n"
595 "vec3 specular = vec3(0.0, 0.0, 0.0);\n"
596 "if (dot(normal, light_dir) >= 0.0) {\n"
597 "attenuation * light[i].color * pow(max(0.0, dot(reflect(-light_dir, normal), view_dir)), 25.0);\n"
599 "total_light = total_light + diffuse + specular;\n"
601 "color = total_light;\n"
605 if (!prog.Linked()) {
607 throw std::runtime_error("link program");
609 m_handle = prog.UniformLocation("M");
610 mv_handle = prog.UniformLocation("MV");
611 mvp_handle = prog.UniformLocation("MVP");
612 base_color_handle = prog.UniformLocation("base_color");
613 highlight_color_handle = prog.UniformLocation("highlight_color");
614 sampler_handle = prog.UniformLocation("tex_sampler");
615 num_lights_handle = prog.UniformLocation("num_lights");
616 for (int i = 0; i < MAX_LIGHTS; ++i) {
617 light_handle[3 * i + 0] = prog.UniformLocation("light[" + std::to_string(i) + "].position");
618 light_handle[3 * i + 1] = prog.UniformLocation("light[" + std::to_string(i) + "].color");
619 light_handle[3 * i + 2] = prog.UniformLocation("light[" + std::to_string(i) + "].strength");
623 CreatureSkin::~CreatureSkin() {
626 void CreatureSkin::Activate() noexcept {
628 glEnable(GL_DEPTH_TEST);
629 glDepthFunc(GL_LESS);
630 glEnable(GL_CULL_FACE);
634 void CreatureSkin::SetM(const glm::mat4 &mm) noexcept {
638 prog.Uniform(m_handle, m);
639 prog.Uniform(mv_handle, mv);
640 prog.Uniform(mvp_handle, mvp);
643 void CreatureSkin::SetV(const glm::mat4 &vv) noexcept {
647 prog.Uniform(mv_handle, mv);
648 prog.Uniform(mvp_handle, mvp);
651 void CreatureSkin::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
656 prog.Uniform(mv_handle, mv);
657 prog.Uniform(mvp_handle, mvp);
660 void CreatureSkin::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
666 prog.Uniform(m_handle, m);
667 prog.Uniform(mv_handle, mv);
668 prog.Uniform(mvp_handle, mvp);
671 void CreatureSkin::SetBaseColor(const glm::vec3 &c) noexcept {
672 prog.Uniform(base_color_handle, c);
675 void CreatureSkin::SetHighlightColor(const glm::vec4 &c) noexcept {
676 prog.Uniform(highlight_color_handle, c);
679 void CreatureSkin::SetTexture(ArrayTexture &tex) noexcept {
680 glActiveTexture(GL_TEXTURE0);
682 prog.Uniform(sampler_handle, GLint(0));
685 void CreatureSkin::SetLight(int n, const glm::vec3 &pos, const glm::vec3 &color, float strength) noexcept {
686 prog.Uniform(light_handle[3 * n + 0], pos);
687 prog.Uniform(light_handle[3 * n + 1], color);
688 prog.Uniform(light_handle[3 * n + 2], strength);
691 void CreatureSkin::SetNumLights(int n) noexcept {
692 prog.Uniform(num_lights_handle, std::min(MAX_LIGHTS, n));
696 AlphaSprite::AlphaSprite()
700 "#version 330 core\n"
702 "layout(location = 0) in vec3 vtx_position;\n"
703 "layout(location = 1) in vec2 vtx_texture;\n"
707 "uniform mat4 MVP;\n"
709 "out vec2 frag_tex_uv;\n"
712 "gl_Position = MVP * vec4(vtx_position, 1);\n"
713 "frag_tex_uv = vtx_texture;\n"
718 "#version 330 core\n"
720 "in vec2 frag_tex_uv;\n"
722 "uniform sampler2D tex_sampler;\n"
723 "uniform vec4 fg_color;\n"
724 "uniform vec4 bg_color;\n"
729 "vec4 tex_color = texture(tex_sampler, frag_tex_uv);\n"
730 "vec4 factor = mix(bg_color, fg_color, tex_color.a);\n"
731 "color = vec4((tex_color * factor).rgb, factor.a);\n"
735 if (!prog.Linked()) {
737 throw std::runtime_error("link program");
739 m_handle = prog.UniformLocation("M");
740 mv_handle = prog.UniformLocation("MV");
741 mvp_handle = prog.UniformLocation("MVP");
742 sampler_handle = prog.UniformLocation("tex_sampler");
743 fg_color_handle = prog.UniformLocation("fg_color");
744 bg_color_handle = prog.UniformLocation("bg_color");
747 vao.BindAttributes();
748 vao.EnableAttribute(0);
749 vao.EnableAttribute(1);
750 vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
751 vao.AttributePointer<glm::vec2>(1, false, offsetof(Attributes, texture));
752 vao.ReserveAttributes(4, GL_STATIC_DRAW);
754 auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
755 attrib[0].position = glm::vec3(-0.5f, -0.5f, 0.0f);
756 attrib[0].texture = glm::vec2(0.0f, 0.0f);
757 attrib[1].position = glm::vec3(-0.5f, 0.5f, 0.0f);
758 attrib[1].texture = glm::vec2(0.0f, 1.0f);
759 attrib[2].position = glm::vec3( 0.5f, -0.5f, 0.0f);
760 attrib[2].texture = glm::vec2(1.0f, 0.0f);
761 attrib[3].position = glm::vec3( 0.5f, 0.5f, 0.0f);
762 attrib[3].texture = glm::vec2(1.0f, 1.0f);
765 vao.ReserveElements(7, GL_STATIC_DRAW);
767 auto element = vao.MapElements(GL_WRITE_ONLY);
776 AlphaSprite::~AlphaSprite() {
779 void AlphaSprite::Activate() noexcept {
781 glEnable(GL_DEPTH_TEST);
782 glDepthFunc(GL_LESS);
783 glEnable(GL_CULL_FACE);
785 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
788 void AlphaSprite::SetM(const glm::mat4 &mm) noexcept {
792 prog.Uniform(m_handle, m);
793 prog.Uniform(mv_handle, mv);
794 prog.Uniform(mvp_handle, mvp);
797 void AlphaSprite::SetVP(const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
802 prog.Uniform(mv_handle, mv);
803 prog.Uniform(mvp_handle, mvp);
806 void AlphaSprite::SetMVP(const glm::mat4 &mm, const glm::mat4 &vv, const glm::mat4 &pp) noexcept {
812 prog.Uniform(m_handle, m);
813 prog.Uniform(mv_handle, mv);
814 prog.Uniform(mvp_handle, mvp);
817 void AlphaSprite::SetTexture(Texture &tex) noexcept {
818 glActiveTexture(GL_TEXTURE0);
820 prog.Uniform(sampler_handle, GLint(0));
823 void AlphaSprite::SetFgColor(const glm::vec4 &color) noexcept {
824 prog.Uniform(fg_color_handle, color);
827 void AlphaSprite::SetBgColor(const glm::vec4 &color) noexcept {
828 prog.Uniform(bg_color_handle, color);
831 void AlphaSprite::DrawRect() const noexcept {
833 vao.DrawTriangleStrip(4);
842 "#version 330 core\n"
844 "layout(location = 0) in vec2 vtx_position;\n"
850 // disamond rule adjust
851 //"vec3 position = vtx_position + vec3(0.5, 0.5, 0.0);\n"
852 "gl_Position = P * vec4(vtx_position, z, 1);\n"
857 "#version 330 core\n"
868 if (!prog.Linked()) {
870 throw std::runtime_error("link program");
872 p_handle = prog.UniformLocation("P");
873 z_handle = prog.UniformLocation("z");
874 c_handle = prog.UniformLocation("c");
877 vao.BindAttributes();
878 vao.EnableAttribute(0);
879 vao.AttributePointer<glm::vec2>(0, false, offsetof(Attributes, position));
880 vao.ReserveAttributes(255, GL_DYNAMIC_DRAW);
882 vao.ReserveElements(255, GL_DYNAMIC_DRAW);
889 void Canvas::Resize(float w, float h) noexcept {
890 prog.Uniform(p_handle, glm::ortho(0.0f, w, h, 0.0f, 1.0e4f, -1.0e4f));
893 void Canvas::ZIndex(float z) noexcept {
894 prog.Uniform(z_handle, -z);
897 void Canvas::SetColor(const glm::vec4 &color) noexcept {
898 prog.Uniform(c_handle, color);
901 void Canvas::Activate() noexcept {
903 glEnable(GL_DEPTH_TEST);
904 glDepthFunc(GL_LESS);
905 glEnable(GL_CULL_FACE);
907 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
910 void Canvas::DrawLine(const glm::vec2 &p1, const glm::vec2 &p2, float width) {
911 glm::vec2 d = glm::normalize(p2 - p1) * (width * 0.5f);
912 glm::vec2 n = glm::vec2(d.y, -d.x);
914 vao.BindAttributes();
916 auto attr = vao.MapAttributes(GL_WRITE_ONLY);
917 attr[0].position = p1 - d + n;
918 attr[1].position = p1 - d - n;
919 attr[2].position = p2 + d + n;
920 attr[3].position = p2 + d - n;
924 auto elem = vao.MapElements(GL_WRITE_ONLY);
930 vao.DrawTriangleStrip(4);
934 void Canvas::DrawRect(const glm::vec2 &p1, const glm::vec2 &p2, float width) {
935 glm::vec2 min(std::min(p1.x, p2.x), std::min(p1.y, p2.y));
936 glm::vec2 max(std::max(p1.x, p2.x), std::max(p1.y, p2.y));
937 glm::vec2 dg1(min.x, max.y);
938 glm::vec2 dg2(max.x, min.y);
939 glm::vec2 d(width * 0.5f, width * 0.5f);
940 glm::vec2 n(d.y, -d.x);
942 vao.BindAttributes();
944 auto attr = vao.MapAttributes(GL_WRITE_ONLY);
945 attr[0].position = min + d;
946 attr[1].position = min - d;
947 attr[2].position = dg1 + n;
948 attr[3].position = dg1 - n;
949 attr[4].position = max - d;
950 attr[5].position = max + d;
951 attr[6].position = dg2 - n;
952 attr[7].position = dg2 + n;
956 auto elem = vao.MapElements(GL_WRITE_ONLY);
968 vao.DrawTriangleStrip(10);
972 void Canvas::FillRect(const glm::vec2 &p1, const glm::vec2 &p2) {
973 glm::vec2 min(std::min(p1.x, p2.x), std::min(p1.y, p2.y));
974 glm::vec2 max(std::max(p1.x, p2.x), std::max(p1.y, p2.y));
975 glm::vec2 dg1(min.x, max.y);
976 glm::vec2 dg2(max.x, min.y);
978 vao.BindAttributes();
980 auto attr = vao.MapAttributes(GL_WRITE_ONLY);
981 attr[0].position = min;
982 attr[1].position = dg1;
983 attr[2].position = dg2;
984 attr[3].position = max;
988 auto elem = vao.MapElements(GL_WRITE_ONLY);
994 vao.DrawTriangleStrip(4);