選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 

178 行
5.3 KiB

  1. //
  2. // Neercs
  3. //
  4. #if defined HAVE_CONFIG_H
  5. # include "config.h"
  6. #endif
  7. #include <cmath>
  8. #include <cstdio>
  9. #include <cstdlib>
  10. #include <ctime>
  11. #include <string>
  12. #include "core.h"
  13. #include "lolgl.h"
  14. using namespace std;
  15. using namespace lol;
  16. #include "../neercs.h"
  17. #include "render.h"
  18. #include "text-render.h"
  19. extern char const *lolfx_text;
  20. /*
  21. * Text rendering interface
  22. */
  23. TextRender::TextRender(caca_canvas_t *caca, ivec2 font_size)
  24. : m_caca(caca),
  25. m_font_size(font_size),
  26. m_canvas_size(caca_get_canvas_width(m_caca),
  27. caca_get_canvas_height(m_caca)),
  28. m_fbo_size(m_font_size * m_canvas_size),
  29. m_cells(m_canvas_size.x * m_canvas_size.y)
  30. {
  31. }
  32. void TextRender::Init()
  33. {
  34. m_font = new TileSet("tools/neercs/video/resource/charset_p0t-noodle.png",
  35. ivec2(256, 256), ivec2(1));
  36. m_shader = Shader::Create(lolfx_text);
  37. m_coord = m_shader->GetAttribLocation("in_Position",
  38. VertexUsage::Position, 0);
  39. m_color = m_shader->GetAttribLocation("in_Attr",
  40. VertexUsage::Color, 0);
  41. m_char = m_shader->GetAttribLocation("in_Char",
  42. VertexUsage::Color, 1);
  43. m_texture = m_shader->GetUniformLocation("in_Texture");
  44. m_transform = m_shader->GetUniformLocation("in_Transform");
  45. m_vdecl
  46. = new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position),
  47. VertexStream<uint32_t>(VertexUsage::Color),
  48. VertexStream<uint32_t>(VertexUsage::Color));
  49. CreateBuffers();
  50. }
  51. void TextRender::CreateBuffers()
  52. {
  53. m_vbo1 = new VertexBuffer(m_cells * sizeof(vec2));
  54. vec2 *vertices = (vec2 *)m_vbo1->Lock(0, 0);
  55. for (int j = 0; j < m_canvas_size.y; j++)
  56. for (int i = 0; i < m_canvas_size.x; i++)
  57. vertices[j * m_canvas_size.x + i] = vec2(i, j);
  58. m_vbo1->Unlock();
  59. m_vbo2 = new VertexBuffer(m_cells * sizeof(int32_t));
  60. m_vbo3 = new VertexBuffer(m_cells * sizeof(int32_t));
  61. m_fbo = new FrameBuffer(m_fbo_size);
  62. }
  63. void TextRender::Render()
  64. {
  65. /* Handle canvas size changes */
  66. ivec2 current_size(caca_get_canvas_width(m_caca),
  67. caca_get_canvas_height(m_caca));
  68. if (current_size != m_canvas_size)
  69. {
  70. delete m_vbo1;
  71. delete m_vbo2;
  72. delete m_vbo3;
  73. delete m_fbo;
  74. m_canvas_size = current_size;
  75. m_fbo_size = m_font_size * m_canvas_size;
  76. m_cells = m_canvas_size.x * m_canvas_size.y;
  77. CreateBuffers();
  78. }
  79. /* Transform matrix for the scene:
  80. * - translate to the centre of the glyph
  81. * - scale by 2.f * font_size / fbo_size
  82. * - translate to the lower left corner */
  83. mat4 xform = mat4::translate(-1.f, -1.f + 2.0f * m_font_size.y
  84. * m_canvas_size.y / m_fbo_size.y, 0.f)
  85. * mat4::scale(vec3(2.f * m_font_size / m_fbo_size, 1.f)
  86. * vec3(1.f, -1.f, 1.f))
  87. * mat4::translate(0.5f, 0.5f, 0.f);
  88. /* Upload libcaca canvas contents to the vertex buffers */
  89. uint32_t *colors = (uint32_t *)m_vbo2->Lock(0, 0);
  90. for (int j = 0; j < m_canvas_size.y; j++)
  91. for (int i = 0; i < m_canvas_size.x; i++)
  92. {
  93. uint32_t attr = caca_get_attr(m_caca, i, j);
  94. uint16_t fg = caca_attr_to_rgb12_fg(attr);
  95. uint16_t bg = caca_attr_to_rgb12_bg(attr);
  96. caca_set_color_argb(m_caca, fg, bg);
  97. attr = caca_get_attr(m_caca, -1, -1);
  98. caca_put_attr(m_caca, i, j, attr);
  99. }
  100. memcpy(colors, caca_get_canvas_attrs(m_caca),
  101. m_cells * sizeof(uint32_t));
  102. m_vbo2->Unlock();
  103. uint32_t *chars = (uint32_t *)m_vbo3->Lock(0, 0);
  104. memcpy(chars, caca_get_canvas_chars(m_caca),
  105. m_cells * sizeof(uint32_t));
  106. m_vbo3->Unlock();
  107. m_fbo->Bind();
  108. glViewport(0, 0, m_fbo_size.x, m_fbo_size.y);
  109. glDisable(GL_DEPTH_TEST);
  110. glEnable(GL_POINT_SPRITE);
  111. //glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  112. glDisable(GL_POINT_SMOOTH);
  113. glPointSize((float)max(m_font_size.x, m_font_size.y));
  114. m_shader->Bind();
  115. m_font->Bind();
  116. m_shader->SetUniform(m_texture, 0);
  117. m_shader->SetUniform(m_transform, xform);
  118. m_vdecl->SetStream(m_vbo1, m_coord);
  119. m_vdecl->SetStream(m_vbo2, m_color);
  120. m_vdecl->SetStream(m_vbo3, m_char);
  121. m_vdecl->Bind();
  122. m_vdecl->DrawElements(MeshPrimitive::Points, 0, m_cells);
  123. m_vdecl->Unbind();
  124. m_font->Unbind();
  125. m_shader->Unbind();
  126. glDisable(GL_POINT_SPRITE);
  127. m_fbo->Unbind();
  128. }
  129. void TextRender::Blit(ivec2 pos, ivec2 size)
  130. {
  131. /* FIXME: this is ugly! But we will get rid of it when we
  132. * do the Direct3D port, so don't worry too much. */
  133. ShaderTexture t = m_fbo->GetTexture();
  134. uint64_t const &x = *(uint64_t const *)&t;
  135. glDisable(GL_BLEND);
  136. glEnable(GL_TEXTURE_2D);
  137. glBindTexture(GL_TEXTURE_2D, (int)x);
  138. glColor3f(1.0f, 1.0f, 1.0f);
  139. vec2 tc = (vec2)m_canvas_size * m_font_size / m_fbo_size;
  140. glLoadIdentity();
  141. glBegin(GL_QUADS);
  142. glTexCoord2f(tc.x, tc.y);
  143. glVertex2i(pos.x + size.x, pos.y);
  144. glTexCoord2f(0.0f, tc.y);
  145. glVertex2i(pos.x, pos.y);
  146. glTexCoord2f(0.0f, 0.0f);
  147. glVertex2i(pos.x, pos.y + size.y);
  148. glTexCoord2f(tc.x, 0.0f);
  149. glVertex2i(pos.x + size.x, pos.y + size.y);
  150. glEnd();
  151. }