sprite_stroke_drawer.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Flexlay - A Generic 2D Game Editor
  2. // Copyright (C) 2002 Ingo Ruhnke <grumbel@gmx.de>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. #include "sprite_stroke_drawer.hpp"
  17. #include <ClanLib/Display/canvas.h>
  18. #include <ClanLib/gl.h>
  19. #include <assert.h>
  20. #include "stroke_drawer_impl.hpp"
  21. #include "drawer_properties.hpp"
  22. #include "bitmap_layer.hpp"
  23. CL_ProgramObject* program = 0;
  24. class SpriteStrokeDrawerImpl : public StrokeDrawerImpl
  25. {
  26. public:
  27. SpriteStrokeDrawer::DrawMode mode;
  28. SpriteStrokeDrawerImpl() {}
  29. void draw(const Stroke& stroke, CL_GraphicContext* gc);
  30. StrokeDrawerImpl* clone() const;
  31. };
  32. SpriteStrokeDrawer::SpriteStrokeDrawer(StrokeDrawer drawer)
  33. {
  34. impl = std::dynamic_pointer_cast<SpriteStrokeDrawerImpl>(drawer.impl);
  35. assert(impl.get());
  36. }
  37. SpriteStrokeDrawer::SpriteStrokeDrawer()
  38. : impl(new SpriteStrokeDrawerImpl())
  39. {
  40. impl->mode = SpriteStrokeDrawer::DM_NORMAL;
  41. }
  42. void
  43. SpriteStrokeDrawerImpl::draw(const Stroke& stroke, CL_GraphicContext* gc)
  44. {
  45. if (DrawerProperties::current()->get_brush().is_null() || stroke.get_dab_count() == 0)
  46. return;
  47. Stroke::Dabs dabs = stroke.get_interpolated_dabs(DrawerProperties::current()->get_spacing()
  48. * DrawerProperties::current()->get_size(),
  49. DrawerProperties::current()->get_spacing()
  50. * DrawerProperties::current()->get_size());
  51. for(Stroke::Dabs::iterator i = dabs.begin(); i != dabs.end(); ++i)
  52. {
  53. Dab& dab = *i;
  54. CL_Sprite sprite = DrawerProperties::current()->get_brush().get_sprite();
  55. CL_Color color = DrawerProperties::current()->get_color();
  56. sprite.set_color(color);
  57. sprite.set_alpha((color.get_alpha()/255.0f) * dab.pressure);
  58. sprite.set_scale(DrawerProperties::current()->get_size() * dab.pressure,
  59. DrawerProperties::current()->get_size() * dab.pressure);
  60. if (gc != 0)
  61. {
  62. /* Correct function:
  63. 1: dest
  64. 2: src
  65. R = R1 A1 (1 - A2) + R2 A2
  66. G = G1 A1 (1 - A2) + G2 A2
  67. B = B1 A1 (1 - A2) + B2 A2
  68. A = A1 (1 - A2) + A2
  69. // This is currently used, leads to premultiplied alpha
  70. Aout = Afgd + (1 - Afgd) * Abkg
  71. Cout' = Cfgd' + (1 - Afgd) * Cbkg'
  72. where
  73. Cfgd' = Cfgd * Afgd
  74. Cbkg' = Cbkg * Abkg
  75. Cout' = Cout * Aout
  76. Aout = (1 - (1 - Afgd) * (1 - Abkg))
  77. Cout = (Cfgd * Afgd) + (1 - Afgd * Cbkg * Abkg) / Aout
  78. where
  79. Cfgd = red, green, blue of foreground
  80. Cbkg = red, green, blue of background
  81. Afgd = alpha of foreground
  82. Abkg = alpha of background
  83. */
  84. // DO Multipass:
  85. // 1: GL_ZERO, GL_DST_ALPHA
  86. // 2: GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
  87. /*brush.set_blend_func_separate(blend_zero, blend_dst_alpha,
  88. blend_zero, blend_one);
  89. brush.draw(dab.pos.x, dab.pos.y, gc);*/
  90. switch (mode)
  91. {
  92. case SpriteStrokeDrawer::DM_NORMAL:
  93. sprite.set_blend_func_separate(blend_src_alpha, blend_one_minus_src_alpha,
  94. blend_one, blend_one_minus_src_alpha);
  95. sprite.draw(dab.pos.x, dab.pos.y, gc);
  96. break;
  97. case SpriteStrokeDrawer::DM_ADDITION:
  98. sprite.set_blend_func_separate(blend_src_alpha, blend_one,
  99. blend_zero, blend_one);
  100. //blend_one, blend_one_minus_src_alpha);
  101. sprite.draw(dab.pos.x, dab.pos.y, gc);
  102. break;
  103. case SpriteStrokeDrawer::DM_ERASE:
  104. sprite.set_blend_func(blend_zero, blend_one_minus_src_alpha);
  105. sprite.draw(dab.pos.x, dab.pos.y, gc);
  106. break;
  107. case SpriteStrokeDrawer::DM_SMUDGE:
  108. {
  109. if (i != dabs.begin())
  110. {
  111. CL_Canvas* canvas = BitmapLayer::current()->get_canvas();
  112. CL_PixelBuffer buffer = canvas->get_pixeldata(CL_Rect(CL_Point(static_cast<int>((i-1)->pos.x) - sprite.get_width()/2,
  113. static_cast<int>((i-1)->pos.y) - sprite.get_height()/2),
  114. CL_Size(sprite.get_width(), sprite.get_height())));
  115. CL_Surface surface(buffer);
  116. //surface.set_blend_func_separate(blend_src_alpha, blend_one_minus_src_alpha,
  117. // blend_one, blend_zero);
  118. surface.set_alignment(origin_center);
  119. surface.set_alpha(0.5);
  120. //surface.set_scale(DrawerProperties::current()->get_size(),
  121. // DrawerProperties::current()->get_size());
  122. surface.draw(dab.pos.x, dab.pos.y, gc);
  123. }
  124. }
  125. break;
  126. case SpriteStrokeDrawer::DM_SHADER:
  127. {
  128. #if 0
  129. CL_OpenGLState state(gc);
  130. state.set_active();
  131. state.setup_2d();
  132. if (program == 0)
  133. {
  134. program = new CL_ProgramObject();
  135. CL_ShaderObject shader("shader", &(Flexlay::current()->resources));
  136. std::cout << "Shader status: " << (shader.get_compile_status() ? "true" : "false") << std::endl;
  137. std::cout << "Shader log: " << shader.get_info_log() << std::endl;
  138. std::cout << "Shader handle: " << shader.get_handle() << std::endl;
  139. program->attach(shader);
  140. program->link();
  141. std::cout << "Program status: " << (program->get_link_status() ? "true" : "false") << std::endl;
  142. std::cout << "Program log: " << program->get_info_log() << std::endl;
  143. std::cout << "Program handle: " << program->get_handle() << std::endl;
  144. clUseProgram(program->get_handle());
  145. }
  146. else
  147. {
  148. clUseProgram(program->get_handle());
  149. }
  150. CL_OpenGLSurface glsurface(sprite.get_frame_surface(0));
  151. glActiveTexture(GL_TEXTURE0);
  152. glsurface.bind();
  153. glEnable(GL_TEXTURE_2D);
  154. /*CL_OpenGLSurface glsurface2(SketchLayer::current()->get_background_surface());
  155. glActiveTexture(GL_TEXTURE1);
  156. glsurface2.bind();
  157. glEnable(GL_TEXTURE_2D);*/
  158. clUniform1i(program->get_attribute_location("mytex"), 0);
  159. //clUniform1i(program->get_attribute_location("background"), 1);
  160. //program->validate();
  161. //std::cout << "Program validate status: " << (program->get_validate_status() ? "true" : "false") << std::endl;
  162. //std::cout << "Program log: " << program->get_info_log() << std::endl;
  163. clBegin(CL_QUADS);
  164. clColor4b(color.get_red(), color.get_green(), color.get_blue(), color.get_alpha());
  165. float size = base_size * dab.pressure;
  166. clVertex2f((dab.pos.x - sprite.get_width()/2) * size, (dab.pos.y - sprite.get_height()/2) * size);
  167. clTexCoord2d(0.0, 0.0);
  168. clVertex2f((dab.pos.x + sprite.get_width()/2) * size, (dab.pos.y - sprite.get_height()/2) * size);
  169. clTexCoord2d(1.0, 0.0);
  170. clVertex2f((dab.pos.x + sprite.get_width()/2) * size, (dab.pos.y + sprite.get_height()/2) * size);
  171. clTexCoord2d(1.0, 1.0);
  172. clVertex2f((dab.pos.x - sprite.get_width()/2) * size, (dab.pos.y + sprite.get_height()/2) * size);
  173. clTexCoord2d(0.0, 1.0);
  174. clEnd();
  175. state.set_active();
  176. clUseProgram(0);
  177. #endif
  178. }
  179. break;
  180. default:
  181. std::cout << "Error: SpriteStrokeDrawer: Unknown draw mode: " << mode << std::endl;
  182. break;
  183. }
  184. }
  185. else
  186. {
  187. switch (mode)
  188. {
  189. case SpriteStrokeDrawer::DM_NORMAL:
  190. sprite.set_blend_func(blend_src_alpha, blend_one_minus_src_alpha);
  191. sprite.draw(dab.pos.x, dab.pos.y, gc);
  192. break;
  193. case SpriteStrokeDrawer::DM_ADDITION:
  194. sprite.set_blend_func(blend_src_alpha, blend_one);
  195. sprite.draw(dab.pos.x, dab.pos.y, gc);
  196. break;
  197. case SpriteStrokeDrawer::DM_ERASE:
  198. sprite.set_blend_func(blend_zero, blend_one_minus_src_alpha);
  199. sprite.draw(dab.pos.x, dab.pos.y, gc);
  200. break;
  201. case SpriteStrokeDrawer::DM_SMUDGE:
  202. sprite.set_blend_func(blend_src_alpha, blend_one_minus_src_alpha);
  203. sprite.draw(dab.pos.x, dab.pos.y, gc);
  204. break;
  205. default:
  206. std::cout << "Error: SpriteStrokeDrawer: Unknown draw mode: " << mode << std::endl;
  207. break;
  208. }
  209. }
  210. }
  211. }
  212. void
  213. SpriteStrokeDrawer::set_mode(DrawMode mode)
  214. {
  215. impl->mode = mode;
  216. }
  217. SpriteStrokeDrawer::DrawMode
  218. SpriteStrokeDrawer::get_mode()
  219. {
  220. return impl->mode;
  221. }
  222. StrokeDrawerImpl*
  223. SpriteStrokeDrawerImpl::clone() const
  224. {
  225. SpriteStrokeDrawerImpl* drawer = new SpriteStrokeDrawerImpl();
  226. *drawer = *this;
  227. return drawer;
  228. }
  229. StrokeDrawer
  230. SpriteStrokeDrawer::to_drawer()
  231. {
  232. return StrokeDrawer(impl);
  233. }
  234. /* EOF */