28 #include <wx/wxprec.h>
40 #include "ocpn_frame.h"
50 #include <wx/graphics.h>
51 #include <wx/dcclient.h>
56 #include "model/cutil.h"
57 #include "model/config_vars.h"
60 #include "glChartCanvas.h"
64 wxArrayPtrVoid gTesselatorVertices;
66 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
67 extern GLint color_tri_shader_program;
68 extern GLint circle_filled_shader_program;
69 extern GLint texture_2D_shader_program;
76 #define PI 3.1415926535897931160E0
81 : m_glchartCanvas(&canvas), m_glcanvas(NULL), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
82 #if wxUSE_GRAPHICS_CONTEXT
87 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
91 ocpnDC::ocpnDC(wxGLCanvas &canvas)
92 : m_glchartCanvas(NULL), m_glcanvas(&canvas), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
93 #if wxUSE_GRAPHICS_CONTEXT
99 ocpnDC::ocpnDC(wxDC &pdc)
100 : m_glchartCanvas(NULL), m_glcanvas(NULL), dc(&pdc), m_pen(wxNullPen), m_brush(wxNullBrush) {
101 #if wxUSE_GRAPHICS_CONTEXT
103 wxMemoryDC *pmdc = wxDynamicCast(dc, wxMemoryDC);
105 pgc = wxGraphicsContext::Create(*pmdc);
107 wxClientDC *pcdc = wxDynamicCast(dc, wxClientDC);
108 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
116 : m_glchartCanvas(NULL), m_glcanvas(NULL), dc(NULL), m_pen(wxNullPen), m_brush(wxNullBrush) {
117 #if wxUSE_GRAPHICS_CONTEXT
124 #if wxUSE_GRAPHICS_CONTEXT
130 free(s_odc_tess_work_buf);
132 delete m_pcolor_tri_shader_program;
133 delete m_pAALine_shader_program;
134 delete m_pcircle_filled_shader_program;
135 delete m_ptexture_2D_shader_program;
140 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
145 m_textforegroundcolour = wxColour(0, 0, 0);
147 s_odc_tess_work_buf = NULL;
150 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
151 s_odc_tess_vertex_idx = 0;
152 s_odc_tess_vertex_idx_this = 0;
153 s_odc_tess_buf_len = 0;
155 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
156 s_odc_tess_buf_len = 100;
158 m_pcolor_tri_shader_program = NULL;
159 m_pAALine_shader_program = NULL;
160 m_pcircle_filled_shader_program = NULL;
161 m_ptexture_2D_shader_program = NULL;
167 m_glchartCanvas = canvas;
168 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
172 void ocpnDC::Clear() {
177 wxBrush tmpBrush = m_brush;
179 if (m_glchartCanvas) {
180 SetBrush(wxBrush(m_glchartCanvas->GetBackgroundColour()));
181 m_glchartCanvas->GetSize(&w, &h);
183 else if (m_glcanvas) {
184 SetBrush(wxBrush(m_glcanvas->GetBackgroundColour()));
185 m_glcanvas->GetSize(&w, &h);
190 DrawRectangle(0, 0, w, h);
196 void ocpnDC::SetBackground(
const wxBrush &brush) {
198 dc->SetBackground(brush);
202 m_glchartCanvas->SetBackgroundColour(brush.GetColour());
204 m_glcanvas->SetBackgroundColour(brush.GetColour());
211 void ocpnDC::SetPen(
const wxPen &pen) {
213 if (pen == wxNullPen)
214 dc->SetPen(*wxTRANSPARENT_PEN);
221 void ocpnDC::SetBrush(
const wxBrush &brush) {
228 void ocpnDC::SetTextForeground(
const wxColour &colour) {
230 dc->SetTextForeground(colour);
232 m_textforegroundcolour = colour;
235 void ocpnDC::SetFont(
const wxFont &font) {
242 const wxPen &ocpnDC::GetPen()
const {
243 if (dc)
return dc->GetPen();
247 const wxBrush &ocpnDC::GetBrush()
const {
248 if (dc)
return dc->GetBrush();
252 const wxFont &ocpnDC::GetFont()
const {
253 if (dc)
return dc->GetFont();
257 void ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
259 dc->GetSize(width, height);
262 if (m_glchartCanvas){
263 *width = m_glchartCanvas->GetGLCanvasWidth();
264 *height = m_glchartCanvas->GetGLCanvasHeight();
266 else if (m_glcanvas){
267 m_glcanvas->GetSize(width, height);
273 void ocpnDC::SetGLAttrs(
bool highQuality) {
278 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
279 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
280 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
283 glDisable(GL_LINE_SMOOTH);
284 glDisable(GL_POLYGON_SMOOTH);
290 void ocpnDC::SetGLStipple()
const {
293 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
294 switch (m_pen.GetStyle()) {
295 case wxPENSTYLE_DOT: {
296 glLineStipple(1, 0x3333);
297 glEnable(GL_LINE_STIPPLE);
300 case wxPENSTYLE_LONG_DASH: {
301 glLineStipple(1, 0xFFF8);
302 glEnable(GL_LINE_STIPPLE);
305 case wxPENSTYLE_SHORT_DASH: {
306 glLineStipple(1, 0x3F3F);
307 glEnable(GL_LINE_STIPPLE);
310 case wxPENSTYLE_DOT_DASH: {
311 glLineStipple(1, 0x8FF1);
312 glEnable(GL_LINE_STIPPLE);
324 void DrawEndCap(
float x1,
float y1,
float t1,
float angle) {
325 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
326 const int steps = 16;
329 for (
int i = 0; i <= steps; i++) {
330 float a = angle + M_PI / 2 + M_PI / steps * i;
332 float xb = x1 + t1 / 2 * cos(a);
333 float yb = y1 + t1 / 2 * sin(a);
348 void ocpnDC::DrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
352 float angle = atan2f(y2 - y1, x2 - x1);
353 float t1 = pen.GetWidth();
354 float t2sina1 = t1 / 2 * sinf(angle);
355 float t2cosa1 = t1 / 2 * cosf(angle);
359 if (m_glchartCanvas){
360 shader = pcolor_tri_shader_program[m_canvasIndex];
366 shader = m_pcolor_tri_shader_program;
368 shader->SetUniformMatrix4fv(
"MVMatrix", (
float *)&(m_vp.vp_matrix_transform));
371 wxColor c = pen.GetColour();
373 colorv[0] = c.Red() / float(256);
374 colorv[1] = c.Green() / float(256);
375 colorv[2] = c.Blue() / float(256);
376 colorv[3] = c.Alpha() / float(256);
377 shader->SetUniform4fv(
"color", colorv);
380 shader->SetAttributePointerf(
"position", vert);
386 int n_dashes = pen.GetDashes(&dashes);
388 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
392 float ldraw = t1 * dashes[0];
393 float lspace = t1 * dashes[1];
395 while (lrun < lpix) {
397 float xb = xa + ldraw * cosf(angle);
398 float yb = ya + ldraw * sinf(angle);
400 if ((lrun + ldraw) >= lpix)
406 vert[0] = xa + t2sina1;
407 vert[1] = ya - t2cosa1;
408 vert[2] = xb + t2sina1;
409 vert[3] = yb - t2cosa1;
410 vert[4] = xb - t2sina1;
411 vert[5] = yb + t2cosa1;
412 vert[6] = xb - t2sina1;
413 vert[7] = yb + t2cosa1;
414 vert[8] = xa - t2sina1;
415 vert[9] = ya + t2cosa1;
416 vert[10] = xa + t2sina1;
417 vert[11] = ya - t2cosa1;
419 glDrawArrays(GL_TRIANGLES, 0, 6);
426 xb = xa + lspace * cos(angle);
427 yb = ya + lspace * sin(angle);
435 vert[0] = x1 + t2sina1;
436 vert[1] = y1 - t2cosa1;
437 vert[2] = x2 + t2sina1;
438 vert[3] = y2 - t2cosa1;
439 vert[4] = x2 - t2sina1;
440 vert[5] = y2 + t2cosa1;
441 vert[6] = x2 - t2sina1;
442 vert[7] = y2 + t2cosa1;
443 vert[8] = x1 - t2sina1;
444 vert[9] = y1 + t2cosa1;
445 vert[10] = x1 + t2sina1;
446 vert[11] = y1 - t2cosa1;
449 glDrawArrays(GL_TRIANGLES, 0, 6);
466 void ocpnDC::DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
468 if (dc) dc->DrawLine(x1, y1, x2, y2);
470 else if (ConfigurePen()) {
471 bool b_draw_thick =
false;
473 float pen_width = wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth());
481 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
484 if (pen_width > 1.0) {
486 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
487 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
488 if (pen_width > parms[1])
491 glLineWidth(pen_width);
493 glLineWidth(pen_width);
497 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
498 if (pen_width > parms[1])
501 glLineWidth(pen_width);
503 glLineWidth(pen_width);
506 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
508 DrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
516 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
521 GetSize(&width, &height);
525 shader->SetUniform2fv(
"uViewPort", vpx);
528 colorv[0] = m_pen.GetColour().Red() / float(256);
529 colorv[1] = m_pen.GetColour().Green() / float(256);
530 colorv[2] = m_pen.GetColour().Blue() / float(256);
533 shader->SetUniform4fv(
"color", colorv);
536 shader->SetAttributePointerf(
"position", fBuf);
540 int n_dashes = m_pen.GetDashes(&dashes);
542 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
543 float cosa = cosf(angle);
544 float sina = sinf(angle);
545 float t1 = m_pen.GetWidth();
547 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
551 float ldraw = t1 * dashes[0];
552 float lspace = t1 * dashes[1];
554 ldraw = wxMax(ldraw, 4.0);
555 lspace = wxMax(lspace, 4.0);
556 lpix = wxMin(lpix, 2000.0);
558 while (lrun < lpix) {
560 float xb = xa + ldraw * cosa;
561 float yb = ya + ldraw * sina;
563 if ((lrun + ldraw) >= lpix)
574 glDrawArrays(GL_LINES, 0, 2);
576 xa = xa + (lspace + ldraw) * cosa;
577 ya = ya + (lspace + ldraw) * sina;
578 lrun += lspace + ldraw;
587 glDrawArrays(GL_LINES, 0, 2);
593 if (m_glchartCanvas){
594 shader = pcolor_tri_shader_program[m_canvasIndex];
600 shader = m_pcolor_tri_shader_program;
602 shader->SetUniformMatrix4fv(
"MVMatrix", (
float *)&(m_vp.vp_matrix_transform));
606 colorv[0] = m_pen.GetColour().Red() / float(256);
607 colorv[1] = m_pen.GetColour().Green() / float(256);
608 colorv[2] = m_pen.GetColour().Blue() / float(256);
611 shader->SetUniform4fv(
"color", colorv);
613 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
616 shader->SetAttributePointerf(
"position", fBuf);
620 int n_dashes = m_pen.GetDashes(&dashes);
622 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
623 float cosa = cosf(angle);
624 float sina = sinf(angle);
625 float t1 = m_pen.GetWidth();
627 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
631 float ldraw = t1 * dashes[0];
632 float lspace = t1 * dashes[1];
634 ldraw = wxMax(ldraw, 4.0);
635 lspace = wxMax(lspace, 4.0);
638 while (lrun < lpix) {
640 float xb = xa + ldraw * cosa;
641 float yb = ya + ldraw * sina;
643 if ((lrun + ldraw) >= lpix)
654 glDrawArrays(GL_LINES, 0, 2);
656 xa = xa + (lspace + ldraw) * cosa;
657 ya = ya + (lspace + ldraw) * sina;
658 lrun += lspace + ldraw;
667 glDrawArrays(GL_LINES, 0, 2);
677 glDisable(GL_LINE_STIPPLE);
680 glDisable(GL_LINE_SMOOTH);
689 void ocpnDC::DrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,
690 wxPen pen,
bool b_hiqual) {
694 wxPoint p0 = points[0];
695 for (
int i = 1; i < n; i++) {
696 DrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
697 points[i].y + yoffset, pen, b_hiqual);
704 void ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
705 wxCoord yoffset,
bool b_hiqual) {
706 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
708 else if (ConfigurePen()) {
713 SetGLAttrs(b_hiqual);
715 bool b_draw_thick =
false;
717 glDisable(GL_LINE_STIPPLE);
723 if (m_pen.GetWidth() > 1) {
725 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
726 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
728 if (m_pen.GetWidth() > parms[1])
731 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
733 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
735 if (m_pen.GetWidth() > 1) {
737 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
738 if (m_pen.GetWidth() > parms[1])
741 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
743 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
746 if (b_draw_thick || m_pen.GetStyle() != wxPENSTYLE_SOLID) {
747 DrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
750 glDisable(GL_LINE_STIPPLE);
751 glDisable(GL_LINE_SMOOTH);
752 glDisable(GL_POLYGON_SMOOTH);
760 if (workBufSize < (
size_t)n * 2) {
761 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
765 for (
int i = 0; i < n; i++) {
766 workBuf[i * 2] = points[i].x + xoffset;
767 workBuf[(i * 2) + 1] = points[i].y + yoffset;
780 GetSize(&width, &height);
784 shader->SetUniform2fv(
"uViewPort", vpx);
787 colorv[0] = m_pen.GetColour().Red() / float(256);
788 colorv[1] = m_pen.GetColour().Green() / float(256);
789 colorv[2] = m_pen.GetColour().Blue() / float(256);
792 shader->SetUniform4fv(
"color", colorv);
794 shader->SetAttributePointerf(
"position", workBuf);
796 glDrawArrays(GL_LINE_STRIP, 0, n);
801 if (m_glchartCanvas){
802 shader = pcolor_tri_shader_program[m_canvasIndex];
808 shader = m_pcolor_tri_shader_program;
810 shader->SetUniformMatrix4fv(
"MVMatrix", (
float *)&(m_vp.vp_matrix_transform));
815 colorv[0] = m_pen.GetColour().Red() / float(256);
816 colorv[1] = m_pen.GetColour().Green() / float(256);
817 colorv[2] = m_pen.GetColour().Blue() / float(256);
820 shader->SetUniform4fv(
"color", colorv);
822 shader->SetAttributePointerf(
"position", workBuf);
824 glDrawArrays(GL_LINE_STRIP, 0, n);
832 glDisable(GL_LINE_STIPPLE);
833 glDisable(GL_LINE_SMOOTH);
834 glDisable(GL_POLYGON_SMOOTH);
841 void ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
842 #if wxUSE_GRAPHICS_CONTEXT
844 pgc->SetPen(dc->GetPen());
845 pgc->StrokeLine(x1, y1, x2, y2);
847 dc->CalcBoundingBox(x1, y1);
848 dc->CalcBoundingBox(x2, y2);
851 DrawLine(x1, y1, x2, y2,
true);
854 void ocpnDC::StrokeLines(
int n, wxPoint *points) {
858 #if wxUSE_GRAPHICS_CONTEXT
860 wxPoint2DDouble *dPoints =
861 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
862 for (
int i = 0; i < n; i++) {
863 dPoints[i].m_x = points[i].x;
864 dPoints[i].m_y = points[i].y;
866 pgc->SetPen(dc->GetPen());
867 pgc->StrokeLines(n, dPoints);
871 DrawLines(n, points, 0, 0,
true);
874 void ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
875 if (dc) dc->DrawRectangle(x, y, w, h);
878 DrawRoundedRectangle(x, y, w, h, 0);
884 static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
887 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
888 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
892 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
895 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
898 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
901 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
907 for (
int i = 0; i < steps; i++) {
908 glVertex2i(x0 + floor(x), y0 + floor(y));
909 x += dx + ddx / 2, y += dy + ddy / 2;
910 dx += ddx, dy += ddy;
912 glVertex2i(x0 + floor(x), y0 + floor(y));
917 void ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
920 if (steps == 0)
return;
922 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
926 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
929 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
932 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
935 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
941 for (
int i = 0; i < steps; i++) {
942 workBuf[workBufIndex++] = x0 + floor(x);
943 workBuf[workBufIndex++] = y0 + floor(y);
945 x += dx + ddx / 2, y += dy + ddy / 2;
946 dx += ddx, dy += ddy;
949 workBuf[workBufIndex++] = x0 + floor(x);
950 workBuf[workBufIndex++] = y0 + floor(y);
954 void ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
956 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
959 if (!m_glchartCanvas)
963 int steps = ceil(sqrt((
float)r));
965 wxCoord x1 = x + r, x2 = x + w - r;
966 wxCoord y1 = y + r, y2 = y + h - r;
972 size_t bufReq = (steps+1) * 8 * 2;
974 if (workBufSize < bufReq) {
975 workBuf = (
float *)realloc(workBuf, bufReq *
sizeof(
float));
976 workBufSize = bufReq;
981 drawrrhelperGLES2(x2, y1, r, 0, steps);
982 drawrrhelperGLES2(x1, y1, r, 1, steps);
983 drawrrhelperGLES2(x1, y2, r, 2, steps);
984 drawrrhelperGLES2(x2, y2, r, 3, steps);
991 fcolorv[0] = m_brush.GetColour().Red() / float(256);
992 fcolorv[1] = m_brush.GetColour().Green() / float(256);
993 fcolorv[2] = m_brush.GetColour().Blue() / float(256);
994 fcolorv[3] = m_brush.GetColour().Alpha() / float(256);
995 shader->SetUniform4fv(
"color", fcolorv);
1004 mat4x4_rotate_Z(Q, I, angle);
1012 X, (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform, Q);
1013 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1016 shader->SetAttributePointerf(
"position", workBuf);
1019 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1023 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1024 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1025 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1026 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1028 shader->SetUniform4fv(
"color", bcolorv);
1031 glDrawArrays(GL_LINE_LOOP, 0, workBufIndex / 2);
1038 void ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1040 dc->DrawCircle(x, y, radius);
1048 coords[0] = x - radius;
1049 coords[1] = y + radius;
1050 coords[2] = x + radius;
1051 coords[3] = y + radius;
1052 coords[4] = x - radius;
1053 coords[5] = y - radius;
1054 coords[6] = x + radius;
1055 coords[7] = y - radius;
1058 if (m_glchartCanvas){
1059 shader = pcircle_filled_shader_program[m_canvasIndex];
1065 shader = m_pcircle_filled_shader_program;
1067 shader->SetUniformMatrix4fv(
"MVMatrix", (
float *)&(m_vp.vp_matrix_transform));
1073 shader->SetUniform1f(
"circle_radius", radius);
1079 GetSize(&width, &height);
1080 ctrv[1] = height - y;
1081 shader->SetUniform2fv(
"circle_center", ctrv);
1085 if (m_brush.IsOk()) {
1086 colorv[0] = m_brush.GetColour().Red() / float(256);
1087 colorv[1] = m_brush.GetColour().Green() / float(256);
1088 colorv[2] = m_brush.GetColour().Blue() / float(256);
1089 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1091 shader->SetUniform4fv(
"circle_color", colorv);
1096 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1097 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1098 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1099 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1101 shader->SetUniform4fv(
"border_color", bcolorv);
1105 shader->SetUniform1f(
"border_width", m_pen.GetWidth());
1107 shader->SetUniform1f(
"border_width", 2);
1109 shader->SetAttributePointerf(
"aPos", coords);
1112 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1118 void ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1119 #if wxUSE_GRAPHICS_CONTEXT
1121 wxGraphicsPath gpath = pgc->CreatePath();
1122 gpath.AddCircle(x, y, radius);
1124 pgc->SetPen(GetPen());
1125 pgc->SetBrush(GetBrush());
1126 pgc->DrawPath(gpath);
1129 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1130 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1133 DrawCircle(x, y, radius);
1136 void ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) {
1137 if (dc) dc->DrawEllipse(x, y, width, height);
1140 float r1 = width / 2, r2 = height / 2;
1141 float cx = x + r1, cy = y + r2;
1147 float steps = floorf(
1148 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1152 glDisable(GL_BLEND);
1157 void ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1158 wxCoord yoffset,
float scale,
float angle) {
1159 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1175 if(m_glchartCanvas){
1176 line_shader = pAALine_shader_program[m_canvasIndex];
1177 mvmatrix = (
float *)&(m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1180 line_shader = m_pAALine_shader_program;
1181 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1186 line_shader->Bind();
1188 line_shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
1189 line_shader->SetUniform1f(
"uBlendFactor", 2.0);
1194 GetSize(&width, &height);
1198 line_shader->SetUniform2fv(
"uViewPort", vpx);
1201 colorv[0] = m_pen.GetColour().Red() / float(256);
1202 colorv[1] = m_pen.GetColour().Green() / float(256);
1203 colorv[2] = m_pen.GetColour().Blue() / float(256);
1206 line_shader->SetUniform4fv(
"color", colorv);
1213 mat4x4_rotate_Z(Q, I, angle);
1221 X, (
float(*)[4])mvmatrix,
1224 line_shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1226 line_shader->UnBind();
1230 if (ConfigureBrush())
1231 DrawPolygonTessellated(n, points, xoffset, yoffset);
1235 if (workBufSize < (
size_t)n * 2) {
1236 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1237 workBufSize = n * 4;
1240 for (
int i = 0; i < n; i++) {
1241 workBuf[i * 2] = (points[i].x *
scale);
1242 workBuf[i * 2 + 1] = (points[i].y *
scale);
1245 line_shader->Bind();
1246 line_shader->SetAttributePointerf(
"position", workBuf);
1249 glDrawArrays(GL_LINE_LOOP, 0, n);
1255 line_shader->UnBind();
1260 if (workBufSize < (
size_t)n * 2) {
1261 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1262 workBufSize = n * 4;
1265 for (
int i = 0; i < n; i++) {
1266 workBuf[i * 2] = (points[i].x *
scale);
1267 workBuf[i * 2 + 1] = (points[i].y *
scale);
1274 if(m_glchartCanvas){
1275 shader = pcolor_tri_shader_program[m_canvasIndex];
1276 mvmatrix = (
float *)&(m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1279 shader = m_pcolor_tri_shader_program;
1280 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1287 mat4x4_rotate_Z(Q, I, angle);
1293 mat4x4_mul(X, (
float(*)[4])mvmatrix, Q);
1294 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1299 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1300 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1301 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1302 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1303 shader->SetUniform4fv(
"color", bcolorv);
1305 shader->SetAttributePointerf(
"position", workBuf);
1310 float x1 = workBuf[4];
1311 float y1 = workBuf[5];
1312 workBuf[4] = workBuf[6];
1313 workBuf[5] = workBuf[7];
1317 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1318 }
else if (n == 3) {
1319 glDrawArrays(GL_TRIANGLES, 0, 3);
1323 if (m_glchartCanvas){
1324 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1332 for (
int i = 0; i < n; i++) {
1333 workBuf[i * 2] = (points[i].x *
scale);
1334 workBuf[i * 2 + 1] = (points[i].y *
scale);
1337 line_shader->Bind();
1339 line_shader->SetAttributePointerf(
"position", workBuf);
1341 glDrawArrays(GL_LINE_LOOP, 0, n);
1347 line_shader->UnBind();
1373 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1375 static std::list<double *> odc_combine_work_data;
1376 static void odc_combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
1377 GLfloat weight[4], GLdouble **dataOut,
1385 void odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1389 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1390 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1391 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1393 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1394 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1395 if (NULL == pDC->s_odc_tess_work_buf) {
1399 pDC->s_odc_tess_buf_len = new_buf_len;
1402 GLdouble *pointer = (GLdouble *)vertex;
1404 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1405 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1407 pDC->s_odc_nvertex++;
1410 void odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1412 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1413 pDC->s_odc_tess_mode = mode;
1414 pDC->s_odc_nvertex = 0;
1417 void odc_endCallbackD_GLSL(
void *data) {
1421 GLShaderProgram *shader = pcolor_tri_shader_program[pDC->m_canvasIndex];
1425 wxColour c = pDC->GetBrush().GetColour();
1427 colorv[0] = c.Red() / float(256);
1428 colorv[1] = c.Green() / float(256);
1429 colorv[2] = c.Blue() / float(256);
1430 colorv[3] = c.Alpha() / float(256);
1431 shader->SetUniform4fv(
"color", colorv);
1433 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1434 shader->SetAttributePointerf(
"position", bufPt);
1436 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1447 void ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1449 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1452 if (!m_glchartCanvas)
1455 #if !defined(ocpnUSE_GLES) || \
1456 defined(USE_ANDROID_GLES2)
1460 DrawPolygon(n, points, xoffset, yoffset);
1464 #if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1465 m_tobj = gluNewTess();
1466 s_odc_tess_vertex_idx = 0;
1468 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1469 (_GLUfuncptr)&odc_vertexCallbackD_GLSL);
1470 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1471 (_GLUfuncptr)&odc_beginCallbackD_GLSL);
1472 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1473 (_GLUfuncptr)&odc_endCallbackD_GLSL);
1474 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1475 (_GLUfuncptr)&odc_combineCallbackD);
1478 gluTessNormal(m_tobj, 0, 0, 1);
1479 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1481 if (ConfigureBrush()) {
1482 gluTessBeginPolygon(m_tobj,
this);
1483 gluTessBeginContour(m_tobj);
1485 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas->GetpVP();
1487 for (
int i = 0; i < n; i++) {
1488 double *p =
new double[6];
1490 if (fabs(pvp->rotation) > 0.01) {
1491 float cx = pvp->pix_width / 2.;
1492 float cy = pvp->pix_height / 2.;
1493 float c = cosf(pvp->rotation);
1494 float s = sinf(pvp->rotation);
1495 float xn = points[i].x - cx;
1496 float yn = points[i].y - cy;
1497 p[0] = xn * c - yn * s + cx;
1498 p[1] = xn * s + yn * c + cy;
1501 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1503 gluTessVertex(m_tobj, p, p);
1505 gluTessEndContour(m_tobj);
1506 gluTessEndPolygon(m_tobj);
1509 gluDeleteTess(m_tobj);
1525 void ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1526 wxCoord yoffset,
float scale) {
1527 #if wxUSE_GRAPHICS_CONTEXT
1529 wxGraphicsPath gpath = pgc->CreatePath();
1530 gpath.MoveToPoint(points[0].x *
scale + xoffset,
1531 points[0].y *
scale + yoffset);
1532 for (
int i = 1; i < n; i++)
1533 gpath.AddLineToPoint(points[i].x *
scale + xoffset,
1534 points[i].y *
scale + yoffset);
1535 gpath.AddLineToPoint(points[0].x *
scale + xoffset,
1536 points[0].y *
scale + yoffset);
1538 pgc->SetPen(GetPen());
1539 pgc->SetBrush(GetBrush());
1540 pgc->DrawPath(gpath);
1542 for (
int i = 0; i < n; i++)
1543 dc->CalcBoundingBox(points[i].x *
scale + xoffset,
1544 points[i].y *
scale + yoffset);
1547 DrawPolygon(n, points, xoffset, yoffset,
scale);
1550 void ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1553 if (x < 0 || y < 0) {
1554 int dx = (x < 0 ? -x : 0);
1555 int dy = (y < 0 ? -y : 0);
1556 int w = bitmap.GetWidth() - dx;
1557 int h = bitmap.GetHeight() - dy;
1559 if (w <= 0 || h <= 0)
return;
1560 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1567 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1575 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1576 wxImage image = bmp.ConvertToImage();
1577 int w = image.GetWidth(), h = image.GetHeight();
1580 unsigned char *d = image.GetData();
1581 unsigned char *a = image.GetAlpha();
1584 if (image.HasMask()) a = 0;
1586 unsigned char mr, mg, mb;
1587 if (!a && !image.GetOrFindMaskColour(&mr, &mg, &mb)) {
1588 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1591 unsigned char *e =
new unsigned char[4 * w * h];
1593 for (
int y = 0; y < h; y++)
1594 for (
int x = 0; x < w; x++) {
1595 unsigned char r, g, b;
1596 int off = (y * w + x);
1606 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1612 glColor4f(1, 1, 1, 1);
1613 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1616 glRasterPos2i(x, y);
1618 if (image.GetData())
1619 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1627 void ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y,
float angle) {
1628 if (dc) dc->DrawText(text, x, y);
1636 m_texfont.Build(m_font, 1.0, m_dpi_factor);
1637 m_texfont.GetTextExtent(text, &w, &h);
1638 m_texfont.SetColor(m_textforegroundcolour);
1642 glEnable(GL_TEXTURE_2D);
1643 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1645 m_texfont.RenderString(text, x, y, angle);
1647 glDisable(GL_TEXTURE_2D);
1648 glDisable(GL_BLEND);
1652 sdc.SetFont(m_font);
1653 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1658 temp_dc.SelectObject(bmp);
1661 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1665 temp_dc.SetFont(m_font);
1666 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1667 temp_dc.DrawText(text, 0, 0);
1668 temp_dc.SelectObject(wxNullBitmap);
1672 wxImage image = bmp.ConvertToImage();
1675 int dx = (x < 0 ? -x : 0);
1676 int dy = (y < 0 ? -y : 0);
1677 w = bmp.GetWidth() - dx;
1678 h = bmp.GetHeight() - dy;
1680 if (w <= 0 || h <= 0)
return;
1681 image = image.GetSubImage(wxRect(dx, dy, w, h));
1686 unsigned char *data =
new unsigned char[w * h * 4];
1687 unsigned char *im = image.GetData();
1690 unsigned int r = m_textforegroundcolour.Red();
1691 unsigned int g = m_textforegroundcolour.Green();
1692 unsigned int b = m_textforegroundcolour.Blue();
1693 for (
int i = 0; i < h; i++) {
1694 for (
int j = 0; j < w; j++) {
1695 unsigned int index = ((i * w) + j) * 4;
1697 data[index + 1] = g;
1698 data[index + 2] = b;
1699 data[index + 3] = im[((i * w) + j) * 3];
1704 unsigned int texobj;
1706 glGenTextures(1, &texobj);
1707 glBindTexture(GL_TEXTURE_2D, texobj);
1709 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1710 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1712 int TextureWidth = NextPow2(w);
1713 int TextureHeight = NextPow2(h);
1714 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1715 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1716 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1719 glEnable(GL_TEXTURE_2D);
1721 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1723 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1750 if (m_glchartCanvas){
1751 shader = ptexture_2D_shader_program[m_canvasIndex];
1757 shader = m_ptexture_2D_shader_program;
1759 shader->SetUniformMatrix4fv(
"MVMatrix", (
float *)&(m_vp.vp_matrix_transform));
1763 shader->SetUniform1i(
"uTex", 0);
1768 mat4x4_rotate_Z(Q, I, 0);
1774 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
1803 shader->SetAttributePointerf(
"aPos", co1);
1804 shader->SetAttributePointerf(
"aUV", tco1);
1806 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1811 glDisable(GL_BLEND);
1812 glDisable(GL_TEXTURE_2D);
1814 glDeleteTextures(1, &texobj);
1822 void ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1823 wxCoord *descent, wxCoord *externalLeading,
1830 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1833 if (font) f = *font;
1838 m_texfont.Build(f, 1.0, m_dpi_factor);
1839 m_texfont.GetTextExtent(
string, w, h);
1842 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1846 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1852 if (w && (*w > 500)) *w = 500;
1853 if (h && (*h > 500)) *h = 500;
1856 void ocpnDC::ResetBoundingBox() {
1857 if (dc) dc->ResetBoundingBox();
1860 void ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
1861 if (dc) dc->CalcBoundingBox(x, y);
1864 bool ocpnDC::ConfigurePen() {
1865 if (!m_pen.IsOk())
return false;
1866 if (m_pen == *wxTRANSPARENT_PEN)
return false;
1868 wxColour c = m_pen.GetColour();
1869 int width = m_pen.GetWidth();
1871 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1872 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1874 glLineWidth(wxMax(g_GLMinSymbolLineWidth, width));
1879 bool ocpnDC::ConfigureBrush() {
1880 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
1883 wxColour c = m_brush.GetColour();
1884 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1885 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1891 void ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1892 int format,
const unsigned char *data) {
1894 #if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1896 glRasterPos2i(x, y);
1898 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
1900 glDisable(GL_BLEND);
1909 if (!m_glchartCanvas && !m_glcanvas)
1913 m_vp.SetVPTransformMatrix();
1922 if (m_pcolor_tri_shader_program) {
1923 m_pcolor_tri_shader_program->Bind();
1924 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
1925 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1926 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1928 m_pcolor_tri_shader_program->UnBind();
1930 if (m_pAALine_shader_program) {
1931 m_pAALine_shader_program->Bind();
1932 m_pAALine_shader_program->SetUniformMatrix4fv(
1933 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1934 m_pAALine_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1936 m_pAALine_shader_program->UnBind();
1939 if (m_pcircle_filled_shader_program) {
1940 m_pcircle_filled_shader_program->Bind();
1941 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
1942 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1943 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1945 m_pcircle_filled_shader_program->UnBind();
1948 if (m_ptexture_2D_shader_program) {
1949 m_ptexture_2D_shader_program->Bind();
1950 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
1951 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1952 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1954 m_ptexture_2D_shader_program->UnBind();
1962 #ifdef USE_ANDROID_GLES2
1963 const GLchar* odc_preamble =
1966 const GLchar* odc_preamble =
1968 "#define precision\n"
1977 static const GLchar* odc_color_tri_vertex_shader_source =
1978 "attribute vec2 position;\n"
1979 "uniform mat4 MVMatrix;\n"
1980 "uniform mat4 TransformMatrix;\n"
1981 "uniform vec4 color;\n"
1982 "varying vec4 fragColor;\n"
1984 " fragColor = color;\n"
1985 " gl_Position = MVMatrix * TransformMatrix * vec4(position, 0.0, 1.0);\n"
1988 static const GLchar* odc_color_tri_fragment_shader_source =
1989 "precision lowp float;\n"
1990 "varying vec4 fragColor;\n"
1992 " gl_FragColor = fragColor;\n"
1995 static const GLchar* odc_AALine_vertex_shader_source =
1996 "uniform vec2 uViewPort; //Width and Height of the viewport\n"
1997 "varying vec2 vLineCenter;\n"
1998 "attribute vec2 position;\n"
1999 "uniform mat4 MVMatrix;\n"
2000 "uniform mat4 TransformMatrix;\n"
2003 " vec4 pp = MVMatrix * vec4(position, 0.0, 1.0);\n"
2004 " gl_Position = pp;\n"
2005 " vec2 vp = uViewPort;\n"
2006 " vLineCenter = 0.5*(pp.xy + vec2(1, 1))*vp;\n"
2010 static const GLchar* odc_AALine_fragment_shader_source =
2011 "precision mediump float;\n"
2012 "uniform float uLineWidth;\n"
2013 "uniform vec4 color;\n"
2014 "uniform float uBlendFactor; //1.5..2.5\n"
2015 "varying vec2 vLineCenter;\n"
2018 " vec4 col = color;\n"
2019 " float d = length(vLineCenter-gl_FragCoord.xy);\n"
2020 " float w = uLineWidth;\n"
2024 " if(float((w/2-d)/(w/2)) < .5){\n"
2025 " //col.w *= pow(float((w-d)/w), uBlendFactor);\n"
2026 " col.w *= pow(float((w/2-d)/(w/2)), uBlendFactor);\n"
2029 " gl_FragColor = col;\n"
2033 static const GLchar* odc_circle_filled_vertex_shader_source =
2034 "precision highp float;\n"
2035 "attribute vec2 aPos;\n"
2036 "uniform mat4 MVMatrix;\n"
2037 "uniform mat4 TransformMatrix;\n"
2039 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2042 static const GLchar* odc_circle_filled_fragment_shader_source =
2043 "precision highp float;\n"
2044 "uniform float border_width;\n"
2045 "uniform float circle_radius;\n"
2046 "uniform vec4 circle_color;\n"
2047 "uniform vec4 border_color;\n"
2048 "uniform vec2 circle_center;\n"
2050 "float d = distance(gl_FragCoord.xy, circle_center);\n"
2051 "if (d < (circle_radius - border_width)) { gl_FragColor = circle_color; }\n"
2052 "else if (d < circle_radius) { gl_FragColor = border_color; }\n"
2053 "else { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); }\n"
2057 static const GLchar* odc_texture_2D_vertex_shader_source =
2058 "attribute vec2 aPos;\n"
2059 "attribute vec2 aUV;\n"
2060 "uniform mat4 MVMatrix;\n"
2061 "uniform mat4 TransformMatrix;\n"
2062 "varying vec2 varCoord;\n"
2064 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2065 " varCoord = aUV;\n"
2068 static const GLchar* odc_texture_2D_fragment_shader_source =
2069 "precision lowp float;\n"
2070 "uniform sampler2D uTex;\n"
2071 "varying vec2 varCoord;\n"
2073 " gl_FragColor = texture2D(uTex, varCoord);\n"
2077 void ocpnDC::BuildShaders(){
2080 if (!m_pcolor_tri_shader_program) {
2082 shaderProgram->addShaderFromSource(odc_color_tri_vertex_shader_source, GL_VERTEX_SHADER);
2083 shaderProgram->addShaderFromSource(odc_color_tri_fragment_shader_source, GL_FRAGMENT_SHADER);
2084 shaderProgram->linkProgram();
2086 if (shaderProgram->isOK())
2087 m_pcolor_tri_shader_program = shaderProgram;
2090 if (!m_pAALine_shader_program) {
2092 shaderProgram->addShaderFromSource(odc_AALine_fragment_shader_source, GL_FRAGMENT_SHADER);
2093 shaderProgram->addShaderFromSource(odc_AALine_vertex_shader_source, GL_VERTEX_SHADER);
2094 shaderProgram->linkProgram();
2096 if (shaderProgram->isOK())
2097 m_pAALine_shader_program = shaderProgram;
2100 if (!m_pcircle_filled_shader_program) {
2102 shaderProgram->addShaderFromSource(odc_circle_filled_vertex_shader_source, GL_VERTEX_SHADER);
2103 shaderProgram->addShaderFromSource(odc_circle_filled_fragment_shader_source, GL_FRAGMENT_SHADER);
2104 shaderProgram->linkProgram();
2106 if (shaderProgram->isOK())
2107 m_pcircle_filled_shader_program = shaderProgram;
2110 if (!m_ptexture_2D_shader_program) {
2112 shaderProgram->addShaderFromSource(odc_texture_2D_vertex_shader_source, GL_VERTEX_SHADER);
2113 shaderProgram->addShaderFromSource(odc_texture_2D_fragment_shader_source, GL_FRAGMENT_SHADER);
2114 shaderProgram->linkProgram();
2116 if (shaderProgram->isOK())
2117 m_ptexture_2D_shader_program = shaderProgram;