{"id":840,"date":"2022-11-19T16:59:27","date_gmt":"2022-11-19T15:59:27","guid":{"rendered":"https:\/\/betalord.com\/code\/?p=840"},"modified":"2023-04-05T19:58:17","modified_gmt":"2023-04-05T17:58:17","slug":"smooth-line-drawing-without-shader","status":"publish","type":"post","link":"https:\/\/betalord.com\/code\/2022\/11\/19\/smooth-line-drawing-without-shader\/","title":{"rendered":"Smooth line drawing (without shader)"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"840\" class=\"elementor elementor-840\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-0740634 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"0740634\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-e06599d\" data-id=\"e06599d\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-8048135 elementor-widget elementor-widget-text-editor\" data-id=\"8048135\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The question is: how to draw smooth line (antialiased) with libGDX without using shaders and by using Batch (normally SpriteBatch) without needing to flush the batch after every draw (or at the end of drawing)?<\/p><p>I solved this problem by drawing 5 quads using SpriteBatch. Here&#8217;s the code and diagram (they are both self-explanatory):<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ecb4fc0 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ecb4fc0\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c214e44\" data-id=\"c214e44\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2d3e418 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"2d3e418\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-java'>\t\/**\r\n\t * This method draws smooth line without using shaders, so there is not need to flush batch after drawing a line.\r\n\t * It draws 5 regions in order to create smooth line (see the diagram).\r\n\t * \r\n\t * @param batch batch that is in &quot;drawing&quot; mode (between begin() and end())\r\n\t * @param x1 p1.x\r\n\t * @param y1 p1.y\r\n\t * @param x2 p2.x\r\n\t * @param y2 p2.y\r\n\t * @param thickness thickness of line (1 means 1 pixel thick)\r\n\t * @param feather feather we use to create &quot;smoothness&quot;. Value of 1.0 means we will draw the line 1 pixel outwards, slowly diminishing the alpha channel value until 0.\r\n\t * @param color line&#039;s color\r\n\t *\/\r\n\tpublic void line(Batch batch, float x1, float y1, float x2, float y2, float thickness, float feather, Color color) {\r\n\t\t\/*\r\n\t\t * Note that we don&#039;t set UV coordinates correctly (which are texture coordinates), since we don&#039;t\r\n\t\t * really care - we just need white color value at every pixel. OpenGL takes care of it automatically\r\n\t\t * (seeing we always sample pixel [0,0] it will take value at that pixel, which is white).\r\n\t\t *\/\r\n\t\t\r\n\t\tVector2 p1 = new Vector2(x1, y1);\r\n\t\tVector2 p2 = new Vector2(x2, y2);\r\n\t\t\r\n\t\tbatch.setShader(null); \/\/ just in case some shader is bound\r\n\t\t\r\n\t\tVector2 h = new Vector2(p2).sub(p1).nor().rotate90(1).scl(thickness\/2); \/\/ half-thickness vector (see diagram)\r\n\t\tVector2 fy = new Vector2(h).nor().scl(feather); \/\/ feather vector (see diagram)\r\n\t\tVector2 fx = new Vector2(fy).rotate90(-1); \/\/ feather vector (see diagram)\r\n\t\t\r\n\t\t\/\/ inner and outer points (see diagram)\r\n\t\tVector2 i1, i2, i3, i4, o1, o2, o3, o4;\r\n\t\ti1 = new Vector2(p1).add(h);\r\n\t\ti2 = new Vector2(p2).add(h);\r\n\t\ti3 = new Vector2(p2).sub(h);\r\n\t\ti4 = new Vector2(p1).sub(h);\r\n\t\to1 = new Vector2(i1).sub(fx).add(fy);\r\n\t\to2 = new Vector2(i2).add(fx).add(fy);\r\n\t\to3 = new Vector2(i3).add(fx).sub(fy);\r\n\t\to4 = new Vector2(i4).sub(fx).sub(fy);\r\n\t\t\r\n\t\tfloat c1 = color.toFloatBits(); \/\/ inner color\r\n\t\tfloat c2 = GUIUtils.createColor(color, 0).toFloatBits(); \/\/ outer color\r\n\t\t\r\n\t\tbatch.draw(CommonAssets.tex1x1, new float[]{\r\n\t\t\t\t\/\/ f1:\r\n\t\t\t\ti1.x, i1.y, c1, 0, 0,\r\n\t\t\t\ti2.x, i2.y, c1, 0, 0,\r\n\t\t\t\to2.x, o2.y, c2, 0, 0,\r\n\t\t\t\to1.x, o1.y, c2, 0, 0,\r\n\t\t\t\t\r\n\t\t\t\t\/\/ f2:\r\n\t\t\t\ti3.x, i3.y, c1, 0, 0,\r\n\t\t\t\ti2.x, i2.y, c1, 0, 0,\r\n\t\t\t\to2.x, o2.y, c2, 0, 0,\r\n\t\t\t\to3.x, o3.y, c2, 0, 0,\r\n\t\t\t\t\r\n\t\t\t\t\/\/ f3:\r\n\t\t\t\ti4.x, i4.y, c1, 0, 0,\r\n\t\t\t\ti3.x, i3.y, c1, 0, 0,\r\n\t\t\t\to3.x, o3.y, c2, 0, 0,\r\n\t\t\t\to4.x, o4.y, c2, 0, 0,\r\n\t\t\t\t\r\n\t\t\t\t\/\/ f4:\r\n\t\t\t\ti1.x, i1.y, c1, 0, 0,\r\n\t\t\t\ti4.x, i4.y, c1, 0, 0,\r\n\t\t\t\to4.x, o4.y, c2, 0, 0,\r\n\t\t\t\to1.x, o1.y, c2, 0, 0,\r\n\t\t\t\t\r\n\t\t\t\t\/\/ f0:\r\n\t\t\t\ti1.x, i1.y, c1, 0, 0,\r\n\t\t\t\ti2.x, i2.y, c1, 0, 0,\r\n\t\t\t\ti3.x, i3.y, c1, 0, 0,\r\n\t\t\t\ti4.x, i4.y, c1, 0, 0,\r\n\t\t},\r\n\t\t0, 100);\r\n\t}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c46d6a6 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c46d6a6\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-b9095ca\" data-id=\"b9095ca\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-af5efe0 elementor-widget elementor-widget-image\" data-id=\"af5efe0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"841\" src=\"https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line.jpg\" class=\"attachment-large size-large wp-image-839\" alt=\"\" srcset=\"https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line.jpg 1024w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-300x246.jpg 300w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-768x631.jpg 768w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-1000x821.jpg 1000w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-230x189.jpg 230w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-350x287.jpg 350w, https:\/\/betalord.com\/code\/wp-content\/uploads\/2022\/11\/GeometryDrawer-smooth-line-480x394.jpg 480w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>The question is: how to draw smooth line (antialiased) with libGDX without using shaders and by using Batch (normally SpriteBatch) without needing [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[10],"class_list":["post-840","post","type-post","status-publish","format-standard","hentry","category-article","tag-libgdx"],"_links":{"self":[{"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/posts\/840","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/comments?post=840"}],"version-history":[{"count":9,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/posts\/840\/revisions"}],"predecessor-version":[{"id":865,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/posts\/840\/revisions\/865"}],"wp:attachment":[{"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/media?parent=840"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/categories?post=840"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/betalord.com\/code\/wp-json\/wp\/v2\/tags?post=840"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}