210 rader
6.2 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. LOLFX_RESOURCE_DECLARE(text);
  20. #define HAVE_SHADER_4 1
  21. /*
  22. * Text rendering interface
  23. */
  24. TextRender::TextRender(caca_canvas_t *caca, ivec2 font_size)
  25. : m_caca(caca),
  26. m_font_size(font_size),
  27. m_canvas_size(caca_get_canvas_width(m_caca),
  28. caca_get_canvas_height(m_caca)),
  29. m_fbo_size(m_font_size * m_canvas_size),
  30. m_cells(m_canvas_size.x * m_canvas_size.y),
  31. m_vbo1(0), m_vbo2(0), m_vbo3(0), m_fbo(0)
  32. {
  33. }
  34. void TextRender::Init()
  35. {
  36. m_font = new TileSet("video/resource/charset_amiga.png",
  37. ivec2(256, 256), ivec2(1));
  38. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(text));
  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. #if !HAVE_SHADER_4
  44. m_vertexid = m_shader->GetAttribLocation("in_VertexID",
  45. VertexUsage::Position, 0);
  46. #endif
  47. m_texture = m_shader->GetUniformLocation("u_Texture");
  48. m_transform = m_shader->GetUniformLocation("u_Transform");
  49. m_datasize = m_shader->GetUniformLocation("u_DataSize");
  50. m_vdecl
  51. #if HAVE_SHADER_4
  52. = new VertexDeclaration(VertexStream<uint32_t>(VertexUsage::Color),
  53. VertexStream<uint32_t>(VertexUsage::Color));
  54. #else
  55. = new VertexDeclaration(VertexStream<u8vec4>(VertexUsage::Color),
  56. VertexStream<u8vec4>(VertexUsage::Color),
  57. VertexStream<float>(VertexUsage::Position));
  58. #endif
  59. CreateBuffers();
  60. }
  61. void TextRender::CreateBuffers()
  62. {
  63. #if HAVE_SHADER_4
  64. m_vbo1 = new VertexBuffer(m_cells * sizeof(uint32_t));
  65. m_vbo2 = new VertexBuffer(m_cells * sizeof(uint32_t));
  66. #else
  67. m_vbo1 = new VertexBuffer(m_cells * sizeof(u8vec4));
  68. m_vbo2 = new VertexBuffer(m_cells * sizeof(u8vec4));
  69. m_vbo3 = new VertexBuffer(4 * m_cells * sizeof(float));
  70. float *idx = (float *)m_vbo3->Lock(0, 0);
  71. for (int i = 0; i < m_cells; i++)
  72. idx[i] = (float)i;
  73. m_vbo3->Unlock();
  74. #endif
  75. m_fbo = new Framebuffer(m_fbo_size);
  76. }
  77. void TextRender::Render()
  78. {
  79. /* Handle canvas size changes */
  80. ivec2 current_size(caca_get_canvas_width(m_caca),
  81. caca_get_canvas_height(m_caca));
  82. if (current_size != m_canvas_size)
  83. {
  84. delete m_vbo1;
  85. delete m_vbo2;
  86. delete m_vbo3;
  87. delete m_fbo;
  88. m_canvas_size = current_size;
  89. m_fbo_size = m_font_size * m_canvas_size;
  90. m_cells = m_canvas_size.x * m_canvas_size.y;
  91. CreateBuffers();
  92. }
  93. /* Transform matrix for the scene:
  94. * - translate to the centre of the glyph
  95. * - scale by 2.f * font_size / fbo_size
  96. * - translate to the lower left corner */
  97. mat4 xform = mat4::translate(-1.f, -1.f + 2.0f * m_font_size.y
  98. * m_canvas_size.y / m_fbo_size.y, 0.f)
  99. * mat4::scale(vec3((vec2)m_font_size / (vec2)m_fbo_size, 1.f)
  100. * vec3(2.f, -2.f, 1.f))
  101. * mat4::translate(0.5f, 0.5f, 0.f);
  102. /* Upload libcaca canvas contents to the vertex buffers */
  103. uint32_t *colors = (uint32_t *)m_vbo1->Lock(0, 0);
  104. uint32_t savedattr = caca_get_attr(m_caca, -1, -1);
  105. for (int j = 0; j < m_canvas_size.y; j++)
  106. for (int i = 0; i < m_canvas_size.x; i++)
  107. {
  108. uint32_t attr = caca_get_attr(m_caca, i, j);
  109. uint16_t fg = caca_attr_to_rgb12_fg(attr);
  110. uint16_t bg = caca_attr_to_rgb12_bg(attr);
  111. caca_set_color_argb(m_caca, fg, bg);
  112. attr = caca_get_attr(m_caca, -1, -1);
  113. caca_put_attr(m_caca, i, j, attr);
  114. }
  115. caca_set_attr(m_caca, savedattr);
  116. memcpy(colors, caca_get_canvas_attrs(m_caca),
  117. m_cells * sizeof(uint32_t));
  118. m_vbo1->Unlock();
  119. uint32_t *chars = (uint32_t *)m_vbo2->Lock(0, 0);
  120. memcpy(chars, caca_get_canvas_chars(m_caca),
  121. m_cells * sizeof(uint32_t));
  122. m_vbo2->Unlock();
  123. m_fbo->Bind();
  124. {
  125. RenderContext rc;
  126. rc.SetDepthTest(false);
  127. glViewport(0, 0, m_fbo_size.x, m_fbo_size.y);
  128. #if !defined HAVE_GLES_2X
  129. glEnable(GL_POINT_SPRITE);
  130. //glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  131. glDisable(GL_POINT_SMOOTH);
  132. glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  133. glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
  134. #endif
  135. m_shader->Bind();
  136. m_font->Bind();
  137. m_shader->SetUniform(m_texture, 0);
  138. m_shader->SetUniform(m_transform, xform);
  139. m_shader->SetUniform(m_datasize, vec2(m_canvas_size.x,
  140. max(m_font_size.x, m_font_size.y)));
  141. m_vdecl->SetStream(m_vbo1, m_color);
  142. m_vdecl->SetStream(m_vbo2, m_char);
  143. #if !HAVE_SHADER_4
  144. m_vdecl->SetStream(m_vbo3, m_vertexid);
  145. #endif
  146. m_vdecl->Bind();
  147. m_vdecl->DrawElements(MeshPrimitive::Points, 0, m_cells);
  148. m_vdecl->Unbind();
  149. m_font->Unbind();
  150. m_shader->Unbind();
  151. #if !defined HAVE_GLES_2X
  152. glDisable(GL_POINT_SPRITE);
  153. #endif
  154. }
  155. m_fbo->Unbind();
  156. }
  157. void TextRender::Blit(ivec2 pos, ivec2 size)
  158. {
  159. /* FIXME: this is ugly! But we will get rid of it when we
  160. * do the Direct3D port, so don't worry too much. */
  161. ShaderTexture t = m_fbo->GetTexture();
  162. uint64_t const &x = *(uint64_t const *)&t;
  163. RenderContext rc;
  164. rc.SetAlphaBlend(false);
  165. glEnable(GL_TEXTURE_2D);
  166. glBindTexture(GL_TEXTURE_2D, (int)x);
  167. glColor3f(1.0f, 1.0f, 1.0f);
  168. vec2 tc = (vec2)m_canvas_size * (vec2)m_font_size / (vec2)m_fbo_size;
  169. glLoadIdentity();
  170. glBegin(GL_QUADS);
  171. glTexCoord2f(tc.x, tc.y);
  172. glVertex2i(pos.x + size.x, pos.y);
  173. glTexCoord2f(0.0f, tc.y);
  174. glVertex2i(pos.x, pos.y);
  175. glTexCoord2f(0.0f, 0.0f);
  176. glVertex2i(pos.x, pos.y + size.y);
  177. glTexCoord2f(tc.x, 0.0f);
  178. glVertex2i(pos.x + size.x, pos.y + size.y);
  179. glEnd();
  180. }