38#include <wx/graphics.h>
39#include <wx/dcclient.h>
61#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
62extern GLint color_tri_shader_program;
63extern GLint circle_filled_shader_program;
64extern GLint texture_2D_shader_program;
71#define PI 3.1415926535897931160E0
75static wxArrayPtrVoid gTesselatorVertices;
78 : m_glchartCanvas(&canvas),
82 m_brush(wxNullBrush) {
83#if wxUSE_GRAPHICS_CONTEXT
88 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
92ocpnDC::ocpnDC(wxGLCanvas &canvas)
93 : m_glchartCanvas(NULL),
97 m_brush(wxNullBrush) {
98#if wxUSE_GRAPHICS_CONTEXT
104ocpnDC::ocpnDC(wxDC &pdc)
105 : m_glchartCanvas(NULL),
109 m_brush(wxNullBrush) {
110#if wxUSE_GRAPHICS_CONTEXT
112 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
114 pgc = wxGraphicsContext::Create(*pmdc);
116 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
117 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
125 : m_glchartCanvas(NULL),
129 m_brush(wxNullBrush) {
130#if wxUSE_GRAPHICS_CONTEXT
137#if wxUSE_GRAPHICS_CONTEXT
143 free(s_odc_tess_work_buf);
145 delete m_pcolor_tri_shader_program;
146 delete m_pAALine_shader_program;
147 delete m_pcircle_filled_shader_program;
148 delete m_ptexture_2D_shader_program;
158 m_textforegroundcolour = wxColour(0, 0, 0);
160 s_odc_tess_work_buf = NULL;
163#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
164 s_odc_tess_vertex_idx = 0;
165 s_odc_tess_vertex_idx_this = 0;
166 s_odc_tess_buf_len = 0;
168 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
169 s_odc_tess_buf_len = 100;
171 m_pcolor_tri_shader_program = NULL;
172 m_pAALine_shader_program = NULL;
173 m_pcircle_filled_shader_program = NULL;
174 m_ptexture_2D_shader_program = NULL;
179 m_glchartCanvas = canvas;
180 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
184void ocpnDC::Clear() {
189 wxBrush tmpBrush = m_brush;
191 if (m_glchartCanvas) {
192 SetBrush(wxBrush(m_glchartCanvas->GetBackgroundColour()));
193 m_glchartCanvas->GetSize(&w, &h);
194 }
else if (m_glcanvas) {
195 SetBrush(wxBrush(m_glcanvas->GetBackgroundColour()));
196 m_glcanvas->GetSize(&w, &h);
200 DrawRectangle(0, 0, w, h);
206void ocpnDC::SetBackground(
const wxBrush &brush) {
208 dc->SetBackground(brush);
212 m_glchartCanvas->SetBackgroundColour(brush.GetColour());
214 m_glcanvas->SetBackgroundColour(brush.GetColour());
221void ocpnDC::SetPen(
const wxPen &pen) {
223 if (pen == wxNullPen)
224 dc->SetPen(*wxTRANSPARENT_PEN);
231void ocpnDC::SetBrush(
const wxBrush &brush) {
238void ocpnDC::SetTextForeground(
const wxColour &colour) {
240 dc->SetTextForeground(colour);
242 m_textforegroundcolour = colour;
245void ocpnDC::SetFont(
const wxFont &font) {
252const wxPen &ocpnDC::GetPen()
const {
253 if (dc)
return dc->GetPen();
257const wxBrush &ocpnDC::GetBrush()
const {
258 if (dc)
return dc->GetBrush();
262const wxFont &ocpnDC::GetFont()
const {
263 if (dc)
return dc->GetFont();
267void ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
269 dc->GetSize(width, height);
272 if (m_glchartCanvas) {
273 *width = m_glchartCanvas->GetGLCanvasWidth();
274 *height = m_glchartCanvas->GetGLCanvasHeight();
275 }
else if (m_glcanvas) {
276 m_glcanvas->GetSize(width, height);
282void ocpnDC::SetGLAttrs(
bool highQuality) {
287 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
288 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
289 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
292 glDisable(GL_LINE_SMOOTH);
293 glDisable(GL_POLYGON_SMOOTH);
299void ocpnDC::SetGLStipple()
const {
302#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
303 switch (m_pen.GetStyle()) {
304 case wxPENSTYLE_DOT: {
305 glLineStipple(1, 0x3333);
306 glEnable(GL_LINE_STIPPLE);
309 case wxPENSTYLE_LONG_DASH: {
310 glLineStipple(1, 0xFFF8);
311 glEnable(GL_LINE_STIPPLE);
314 case wxPENSTYLE_SHORT_DASH: {
315 glLineStipple(1, 0x3F3F);
316 glEnable(GL_LINE_STIPPLE);
319 case wxPENSTYLE_DOT_DASH: {
320 glLineStipple(1, 0x8FF1);
321 glEnable(GL_LINE_STIPPLE);
333void DrawEndCap(
float x1,
float y1,
float t1,
float angle) {
334#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
335 const int steps = 16;
338 for (
int i = 0; i <= steps; i++) {
339 float a = angle + M_PI / 2 + M_PI / steps * i;
341 float xb = x1 + t1 / 2 * cos(a);
342 float yb = y1 + t1 / 2 * sin(a);
357void ocpnDC::DrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
361 float angle = atan2f(y2 - y1, x2 - x1);
362 float t1 = pen.GetWidth();
363 float t2sina1 = t1 / 2 * sinf(angle);
364 float t2cosa1 = t1 / 2 * cosf(angle);
368 if (m_glchartCanvas) {
369 shader = pcolor_tri_shader_program[m_canvasIndex];
375 shader = m_pcolor_tri_shader_program;
377 shader->SetUniformMatrix4fv(
"MVMatrix",
378 (
float *)&(m_vp.vp_matrix_transform));
381 wxColor c = pen.GetColour();
383 colorv[0] = c.Red() / float(256);
384 colorv[1] = c.Green() / float(256);
385 colorv[2] = c.Blue() / float(256);
386 colorv[3] = c.Alpha() / float(256);
387 shader->SetUniform4fv(
"color", colorv);
390 shader->SetAttributePointerf(
"position", vert);
395 int n_dashes = pen.GetDashes(&dashes);
397 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
401 float ldraw = t1 * dashes[0];
402 float lspace = t1 * dashes[1];
404 while (lrun < lpix) {
406 float xb = xa + ldraw * cosf(angle);
407 float yb = ya + ldraw * sinf(angle);
409 if ((lrun + ldraw) >= lpix)
415 vert[0] = xa + t2sina1;
416 vert[1] = ya - t2cosa1;
417 vert[2] = xb + t2sina1;
418 vert[3] = yb - t2cosa1;
419 vert[4] = xb - t2sina1;
420 vert[5] = yb + t2cosa1;
421 vert[6] = xb - t2sina1;
422 vert[7] = yb + t2cosa1;
423 vert[8] = xa - t2sina1;
424 vert[9] = ya + t2cosa1;
425 vert[10] = xa + t2sina1;
426 vert[11] = ya - t2cosa1;
428 glDrawArrays(GL_TRIANGLES, 0, 6);
435 xb = xa + lspace * cos(angle);
436 yb = ya + lspace * sin(angle);
444 vert[0] = x1 + t2sina1;
445 vert[1] = y1 - t2cosa1;
446 vert[2] = x2 + t2sina1;
447 vert[3] = y2 - t2cosa1;
448 vert[4] = x2 - t2sina1;
449 vert[5] = y2 + t2cosa1;
450 vert[6] = x2 - t2sina1;
451 vert[7] = y2 + t2cosa1;
452 vert[8] = x1 - t2sina1;
453 vert[9] = y1 + t2cosa1;
454 vert[10] = x1 + t2sina1;
455 vert[11] = y1 - t2cosa1;
457 glDrawArrays(GL_TRIANGLES, 0, 6);
475 if (dc) dc->DrawLine(x1, y1, x2, y2);
477 else if (ConfigurePen()) {
478 bool b_draw_thick =
false;
480 float pen_width = wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth());
488 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
491 if (pen_width > 1.0) {
493 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
494 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
495 if (pen_width > parms[1])
498 glLineWidth(pen_width);
500 glLineWidth(pen_width);
504 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
505 if (pen_width > parms[1])
508 glLineWidth(pen_width);
510 glLineWidth(pen_width);
513#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
515 DrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
523 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
528 GetSize(&width, &height);
532 shader->SetUniform2fv(
"uViewPort", vpx);
535 colorv[0] = m_pen.GetColour().Red() / float(256);
536 colorv[1] = m_pen.GetColour().Green() / float(256);
537 colorv[2] = m_pen.GetColour().Blue() / float(256);
540 shader->SetUniform4fv(
"color", colorv);
543 shader->SetAttributePointerf(
"position", fBuf);
547 int n_dashes = m_pen.GetDashes(&dashes);
549 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
550 float cosa = cosf(angle);
551 float sina = sinf(angle);
552 float t1 = m_pen.GetWidth();
554 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
558 float ldraw = t1 * dashes[0];
559 float lspace = t1 * dashes[1];
561 ldraw = wxMax(ldraw, 4.0);
562 lspace = wxMax(lspace, 4.0);
563 lpix = wxMin(lpix, 2000.0);
565 while (lrun < lpix) {
567 float xb = xa + ldraw * cosa;
568 float yb = ya + ldraw * sina;
570 if ((lrun + ldraw) >= lpix)
581 glDrawArrays(GL_LINES, 0, 2);
583 xa = xa + (lspace + ldraw) * cosa;
584 ya = ya + (lspace + ldraw) * sina;
585 lrun += lspace + ldraw;
594 glDrawArrays(GL_LINES, 0, 2);
600 if (m_glchartCanvas) {
601 shader = pcolor_tri_shader_program[m_canvasIndex];
608 shader = m_pcolor_tri_shader_program;
610 shader->SetUniformMatrix4fv(
"MVMatrix",
611 (
float *)&(m_vp.vp_matrix_transform));
615 colorv[0] = m_pen.GetColour().Red() / float(256);
616 colorv[1] = m_pen.GetColour().Green() / float(256);
617 colorv[2] = m_pen.GetColour().Blue() / float(256);
620 shader->SetUniform4fv(
"color", colorv);
622 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
625 shader->SetAttributePointerf(
"position", fBuf);
628 int n_dashes = m_pen.GetDashes(&dashes);
630 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
631 float cosa = cosf(angle);
632 float sina = sinf(angle);
633 float t1 = m_pen.GetWidth();
635 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
639 float ldraw = t1 * dashes[0];
640 float lspace = t1 * dashes[1];
642 ldraw = wxMax(ldraw, 4.0);
643 lspace = wxMax(lspace, 4.0);
646 while (lrun < lpix) {
648 float xb = xa + ldraw * cosa;
649 float yb = ya + ldraw * sina;
651 if ((lrun + ldraw) >= lpix)
662 glDrawArrays(GL_LINES, 0, 2);
664 xa = xa + (lspace + ldraw) * cosa;
665 ya = ya + (lspace + ldraw) * sina;
666 lrun += lspace + ldraw;
675 glDrawArrays(GL_LINES, 0, 2);
684 glDisable(GL_LINE_STIPPLE);
687 glDisable(GL_LINE_SMOOTH);
695void ocpnDC::DrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
696 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
700 wxPoint p0 = points[0];
701 for (
int i = 1; i < n; i++) {
702 DrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
703 points[i].y + yoffset, pen, b_hiqual);
710void ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
711 wxCoord yoffset,
bool b_hiqual) {
712 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
714 else if (ConfigurePen()) {
719 SetGLAttrs(b_hiqual);
721 bool b_draw_thick =
false;
723 glDisable(GL_LINE_STIPPLE);
729 if (m_pen.GetWidth() > 1) {
731 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
732 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
734 if (m_pen.GetWidth() > parms[1])
737 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
739 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
741 if (m_pen.GetWidth() > 1) {
743 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
744 if (m_pen.GetWidth() > parms[1])
747 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
749 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
752 if (b_draw_thick || m_pen.GetStyle() != wxPENSTYLE_SOLID) {
753 DrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
756 glDisable(GL_LINE_STIPPLE);
757 glDisable(GL_LINE_SMOOTH);
758 glDisable(GL_POLYGON_SMOOTH);
766 if (workBufSize < (
size_t)n * 2) {
767 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
771 for (
int i = 0; i < n; i++) {
772 workBuf[i * 2] = points[i].x + xoffset;
773 workBuf[(i * 2) + 1] = points[i].y + yoffset;
786 GetSize(&width, &height);
790 shader->SetUniform2fv(
"uViewPort", vpx);
793 colorv[0] = m_pen.GetColour().Red() / float(256);
794 colorv[1] = m_pen.GetColour().Green() / float(256);
795 colorv[2] = m_pen.GetColour().Blue() / float(256);
798 shader->SetUniform4fv(
"color", colorv);
800 shader->SetAttributePointerf(
"position", workBuf);
802 glDrawArrays(GL_LINE_STRIP, 0, n);
807 if (m_glchartCanvas) {
808 shader = pcolor_tri_shader_program[m_canvasIndex];
815 shader = m_pcolor_tri_shader_program;
817 shader->SetUniformMatrix4fv(
"MVMatrix",
818 (
float *)&(m_vp.vp_matrix_transform));
822 colorv[0] = m_pen.GetColour().Red() / float(256);
823 colorv[1] = m_pen.GetColour().Green() / float(256);
824 colorv[2] = m_pen.GetColour().Blue() / float(256);
827 shader->SetUniform4fv(
"color", colorv);
829 shader->SetAttributePointerf(
"position", workBuf);
831 glDrawArrays(GL_LINE_STRIP, 0, n);
838 glDisable(GL_LINE_STIPPLE);
839 glDisable(GL_LINE_SMOOTH);
840 glDisable(GL_POLYGON_SMOOTH);
847void ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
848#if wxUSE_GRAPHICS_CONTEXT
850 pgc->SetPen(GetPen());
851 pgc->StrokeLine(x1, y1, x2, y2);
853 dc->CalcBoundingBox(x1, y1);
854 dc->CalcBoundingBox(x2, y2);
860void ocpnDC::StrokeLines(
int n, wxPoint *points) {
864#if wxUSE_GRAPHICS_CONTEXT
866 wxPoint2DDouble *dPoints =
867 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
868 for (
int i = 0; i < n; i++) {
869 dPoints[i].m_x = points[i].x;
870 dPoints[i].m_y = points[i].y;
872 pgc->SetPen(GetPen());
873 pgc->StrokeLines(n, dPoints);
877 DrawLines(n, points, 0, 0,
true);
880void ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
881 if (dc) dc->DrawRectangle(x, y, w, h);
884 DrawRoundedRectangle(x, y, w, h, 0);
890static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
893#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
894 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
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;
904 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
907 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
913 for (
int i = 0; i < steps; i++) {
914 glVertex2i(x0 + floor(x), y0 + floor(y));
915 x += dx + ddx / 2, y += dy + ddy / 2;
916 dx += ddx, dy += ddy;
918 glVertex2i(x0 + floor(x), y0 + floor(y));
923void ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
926 if (steps == 0)
return;
928 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
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;
938 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
941 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
947 for (
int i = 0; i < steps; i++) {
948 workBuf[workBufIndex++] = x0 + floor(x);
949 workBuf[workBufIndex++] = y0 + floor(y);
951 x += dx + ddx / 2, y += dy + ddy / 2;
952 dx += ddx, dy += ddy;
955 workBuf[workBufIndex++] = x0 + floor(x);
956 workBuf[workBufIndex++] = y0 + floor(y);
960void ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
962 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
965 if (!m_glchartCanvas)
return;
968 int steps = ceil(sqrt((
float)r));
970 wxCoord x1 = x + r, x2 = x + w - r;
971 wxCoord y1 = y + r, y2 = y + h - r;
977 size_t bufReq = (steps + 1) * 8 * 2;
979 if (workBufSize < bufReq) {
980 workBuf = (
float *)realloc(workBuf, bufReq *
sizeof(
float));
981 workBufSize = bufReq;
986 drawrrhelperGLES2(x2, y1, r, 0, steps);
987 drawrrhelperGLES2(x1, y1, r, 1, steps);
988 drawrrhelperGLES2(x1, y2, r, 2, steps);
989 drawrrhelperGLES2(x2, y2, r, 3, steps);
996 fcolorv[0] = m_brush.GetColour().Red() / float(256);
997 fcolorv[1] = m_brush.GetColour().Green() / float(256);
998 fcolorv[2] = m_brush.GetColour().Blue() / float(256);
999 fcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1000 shader->SetUniform4fv(
"color", fcolorv);
1009 mat4x4_rotate_Z(Q, I, angle);
1017 (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()
1018 ->vp_matrix_transform,
1020 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1022 shader->SetAttributePointerf(
"position", workBuf);
1025 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1029 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1030 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1031 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1032 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1034 shader->SetUniform4fv(
"color", bcolorv);
1037 glDrawArrays(GL_LINE_LOOP, 0, workBufIndex / 2);
1044void ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1046 dc->DrawCircle(x, y, radius);
1054 coords[0] = x - radius;
1055 coords[1] = y + radius;
1056 coords[2] = x + radius;
1057 coords[3] = y + radius;
1058 coords[4] = x - radius;
1059 coords[5] = y - radius;
1060 coords[6] = x + radius;
1061 coords[7] = y - radius;
1064 if (m_glchartCanvas) {
1065 shader = pcircle_filled_shader_program[m_canvasIndex];
1071 shader = m_pcircle_filled_shader_program;
1073 shader->SetUniformMatrix4fv(
"MVMatrix",
1074 (
float *)&(m_vp.vp_matrix_transform));
1080 shader->SetUniform1f(
"circle_radius", radius);
1086 GetSize(&width, &height);
1087 ctrv[1] = height - y;
1088 shader->SetUniform2fv(
"circle_center", ctrv);
1092 if (m_brush.IsOk()) {
1093 colorv[0] = m_brush.GetColour().Red() / float(256);
1094 colorv[1] = m_brush.GetColour().Green() / float(256);
1095 colorv[2] = m_brush.GetColour().Blue() / float(256);
1096 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1098 shader->SetUniform4fv(
"circle_color", colorv);
1103 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1104 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1105 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1106 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1108 shader->SetUniform4fv(
"border_color", bcolorv);
1112 shader->SetUniform1f(
"border_width", m_pen.GetWidth());
1114 shader->SetUniform1f(
"border_width", 2);
1116 shader->SetAttributePointerf(
"aPos", coords);
1119 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1125void ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1126#if wxUSE_GRAPHICS_CONTEXT
1128 wxGraphicsPath gpath = pgc->CreatePath();
1129 gpath.AddCircle(x, y, radius);
1131 pgc->SetPen(GetPen());
1132 pgc->SetBrush(GetBrush());
1133 pgc->DrawPath(gpath);
1136 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1137 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1140 DrawCircle(x, y, radius);
1143void ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) {
1144 if (dc) dc->DrawEllipse(x, y, width, height);
1147 float r1 = width / 2, r2 = height / 2;
1148 float cx = x + r1, cy = y + r2;
1154 float steps = floorf(
1155 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1159 glDisable(GL_BLEND);
1164void ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1165 wxCoord yoffset,
float scale,
float angle) {
1166 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1181 if (m_glchartCanvas) {
1182 line_shader = pAALine_shader_program[m_canvasIndex];
1183 mvmatrix = (
float *)&(
1184 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1186 line_shader = m_pAALine_shader_program;
1187 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1192 line_shader->Bind();
1194 line_shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
1195 line_shader->SetUniform1f(
"uBlendFactor", 2.0);
1200 GetSize(&width, &height);
1204 line_shader->SetUniform2fv(
"uViewPort", vpx);
1207 colorv[0] = m_pen.GetColour().Red() / float(256);
1208 colorv[1] = m_pen.GetColour().Green() / float(256);
1209 colorv[2] = m_pen.GetColour().Blue() / float(256);
1212 line_shader->SetUniform4fv(
"color", colorv);
1219 mat4x4_rotate_Z(Q, I, angle);
1232 line_shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1234 line_shader->UnBind();
1238 if (ConfigureBrush())
1239 DrawPolygonTessellated(n, points, xoffset, yoffset);
1243 if (workBufSize < (
size_t)n * 2) {
1244 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1245 workBufSize = n * 4;
1248 for (
int i = 0; i < n; i++) {
1249 workBuf[i * 2] = (points[i].x *
scale);
1250 workBuf[i * 2 + 1] = (points[i].y *
scale);
1253 line_shader->Bind();
1254 line_shader->SetAttributePointerf(
"position", workBuf);
1257 glDrawArrays(GL_LINE_LOOP, 0, n);
1264 line_shader->UnBind();
1269 if (workBufSize < (
size_t)n * 2) {
1270 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1271 workBufSize = n * 4;
1274 for (
int i = 0; i < n; i++) {
1275 workBuf[i * 2] = (points[i].x *
scale);
1276 workBuf[i * 2 + 1] = (points[i].y *
scale);
1283 if (m_glchartCanvas) {
1284 shader = pcolor_tri_shader_program[m_canvasIndex];
1285 mvmatrix = (
float *)&(
1286 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1288 shader = m_pcolor_tri_shader_program;
1289 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1296 mat4x4_rotate_Z(Q, I, angle);
1302 mat4x4_mul(X, (
float(*)[4])mvmatrix, Q);
1303 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1307 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1308 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1309 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1310 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1311 shader->SetUniform4fv(
"color", bcolorv);
1313 shader->SetAttributePointerf(
"position", workBuf);
1318 float x1 = workBuf[4];
1319 float y1 = workBuf[5];
1320 workBuf[4] = workBuf[6];
1321 workBuf[5] = workBuf[7];
1325 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1326 }
else if (n == 3) {
1327 glDrawArrays(GL_TRIANGLES, 0, 3);
1331 if (m_glchartCanvas) {
1332 shader->SetUniformMatrix4fv(
1333 "MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()
1334 ->vp_matrix_transform);
1342 for (
int i = 0; i < n; i++) {
1343 workBuf[i * 2] = (points[i].x *
scale);
1344 workBuf[i * 2 + 1] = (points[i].y *
scale);
1347 line_shader->Bind();
1349 line_shader->SetAttributePointerf(
"position", workBuf);
1351 glDrawArrays(GL_LINE_LOOP, 0, n);
1358 line_shader->UnBind();
1384#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1386static std::list<double *> odc_combine_work_data;
1387static void odc_combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
1388 GLfloat weight[4], GLdouble **dataOut,
1396void odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1400 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1401 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1402 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1404 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1405 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1406 if (NULL == pDC->s_odc_tess_work_buf) {
1410 pDC->s_odc_tess_buf_len = new_buf_len;
1413 GLdouble *pointer = (GLdouble *)vertex;
1415 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1416 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1418 pDC->s_odc_nvertex++;
1421void odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1423 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1424 pDC->s_odc_tess_mode = mode;
1425 pDC->s_odc_nvertex = 0;
1428void odc_endCallbackD_GLSL(
void *data) {
1432 GLShaderProgram *shader = pcolor_tri_shader_program[pDC->m_canvasIndex];
1436 wxColour c = pDC->GetBrush().GetColour();
1438 colorv[0] = c.Red() / float(256);
1439 colorv[1] = c.Green() / float(256);
1440 colorv[2] = c.Blue() / float(256);
1441 colorv[3] = c.Alpha() / float(256);
1442 shader->SetUniform4fv(
"color", colorv);
1444 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1445 shader->SetAttributePointerf(
"position", bufPt);
1447 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1457void ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1459 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1462 if (!m_glchartCanvas)
return;
1464#if !defined(ocpnUSE_GLES) || \
1465 defined(USE_ANDROID_GLES2)
1469 DrawPolygon(n, points, xoffset, yoffset);
1473#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1474 m_tobj = gluNewTess();
1475 s_odc_tess_vertex_idx = 0;
1477 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1478 (_GLUfuncptr)&odc_vertexCallbackD_GLSL);
1479 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1480 (_GLUfuncptr)&odc_beginCallbackD_GLSL);
1481 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1482 (_GLUfuncptr)&odc_endCallbackD_GLSL);
1483 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1484 (_GLUfuncptr)&odc_combineCallbackD);
1486 gluTessNormal(m_tobj, 0, 0, 1);
1487 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1489 if (ConfigureBrush()) {
1490 std::vector<std::unique_ptr<double[]>> vertex_data;
1491 vertex_data.reserve(n);
1493 gluTessBeginPolygon(m_tobj,
this);
1494 gluTessBeginContour(m_tobj);
1496 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas->GetpVP();
1498 for (
int i = 0; i < n; i++) {
1499 auto p = std::make_unique<double[]>(6);
1506 float xn = points[i].x - cx;
1507 float yn = points[i].y - cy;
1508 p[0] = xn * c - yn * s + cx;
1509 p[1] = xn * s + yn * c + cy;
1512 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1514 gluTessVertex(m_tobj, p.get(), p.get());
1515 vertex_data.push_back(std::move(p));
1517 gluTessEndContour(m_tobj);
1518 gluTessEndPolygon(m_tobj);
1522 gluDeleteTess(m_tobj);
1537void ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1538 wxCoord yoffset,
float scale) {
1539#if wxUSE_GRAPHICS_CONTEXT
1541 wxGraphicsPath gpath = pgc->CreatePath();
1542 gpath.MoveToPoint(points[0].x *
scale + xoffset,
1543 points[0].y *
scale + yoffset);
1544 for (
int i = 1; i < n; i++)
1545 gpath.AddLineToPoint(points[i].x *
scale + xoffset,
1546 points[i].y *
scale + yoffset);
1547 gpath.AddLineToPoint(points[0].x *
scale + xoffset,
1548 points[0].y *
scale + yoffset);
1550 pgc->SetPen(GetPen());
1551 pgc->SetBrush(GetBrush());
1552 pgc->DrawPath(gpath);
1554 for (
int i = 0; i < n; i++)
1555 dc->CalcBoundingBox(points[i].x *
scale + xoffset,
1556 points[i].y *
scale + yoffset);
1559 DrawPolygon(n, points, xoffset, yoffset,
scale);
1562void ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1565 if (x < 0 || y < 0) {
1566 int dx = (x < 0 ? -x : 0);
1567 int dy = (y < 0 ? -y : 0);
1568 int w = bitmap.GetWidth() - dx;
1569 int h = bitmap.GetHeight() - dy;
1571 if (w <= 0 || h <= 0)
return;
1572 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1579 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1587#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1588 wxImage image = bmp.ConvertToImage();
1589 int w = image.GetWidth(), h = image.GetHeight();
1592 unsigned char *d = image.GetData();
1593 unsigned char *a = image.GetAlpha();
1596 if (image.HasMask()) a = 0;
1598 unsigned char mr, mg, mb;
1599 if (!a && !image.GetOrFindMaskColour(&mr, &mg, &mb)) {
1600 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1603 unsigned char *e =
new unsigned char[4 * w * h];
1605 for (
int y = 0; y < h; y++)
1606 for (
int x = 0; x < w; x++) {
1607 unsigned char r, g, b;
1608 int off = (y * w + x);
1618 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1624 glColor4f(1, 1, 1, 1);
1625 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1628 glRasterPos2i(x, y);
1630 if (image.GetData())
1631 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1639void ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y,
float angle) {
1640 if (dc) dc->DrawText(text, x, y);
1648 m_texfont.Build(m_font, 1.0,
1650 m_texfont.GetTextExtent(text, &w, &h);
1651 m_texfont.SetColor(m_textforegroundcolour);
1655 glEnable(GL_TEXTURE_2D);
1656 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1658 m_texfont.RenderString(text, x, y, angle);
1660 glDisable(GL_TEXTURE_2D);
1661 glDisable(GL_BLEND);
1665 sdc.SetFont(m_font);
1666 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1671 temp_dc.SelectObject(bmp);
1674 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1678 temp_dc.SetFont(m_font);
1679 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1680 temp_dc.DrawText(text, 0, 0);
1681 temp_dc.SelectObject(wxNullBitmap);
1685 wxImage image = bmp.ConvertToImage();
1688 int dx = (x < 0 ? -x : 0);
1689 int dy = (y < 0 ? -y : 0);
1690 w = bmp.GetWidth() - dx;
1691 h = bmp.GetHeight() - dy;
1693 if (w <= 0 || h <= 0)
return;
1694 image = image.GetSubImage(wxRect(dx, dy, w, h));
1699 unsigned char *data =
new unsigned char[w * h * 4];
1700 unsigned char *im = image.GetData();
1703 unsigned int r = m_textforegroundcolour.Red();
1704 unsigned int g = m_textforegroundcolour.Green();
1705 unsigned int b = m_textforegroundcolour.Blue();
1706 for (
int i = 0; i < h; i++) {
1707 for (
int j = 0; j < w; j++) {
1708 unsigned int index = ((i * w) + j) * 4;
1710 data[index + 1] = g;
1711 data[index + 2] = b;
1712 data[index + 3] = im[((i * w) + j) * 3];
1717 unsigned int texobj;
1719 glGenTextures(1, &texobj);
1720 glBindTexture(GL_TEXTURE_2D, texobj);
1722 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1723 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1725 int TextureWidth = NextPow2(w);
1726 int TextureHeight = NextPow2(h);
1727 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1728 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1729 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1732 glEnable(GL_TEXTURE_2D);
1734 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1736 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1763 if (m_glchartCanvas) {
1764 shader = ptexture_2D_shader_program[m_canvasIndex];
1771 shader = m_ptexture_2D_shader_program;
1773 shader->SetUniformMatrix4fv(
"MVMatrix",
1774 (
float *)&(m_vp.vp_matrix_transform));
1778 shader->SetUniform1i(
"uTex", 0);
1783 mat4x4_rotate_Z(Q, I, 0);
1789 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
1816 shader->SetAttributePointerf(
"aPos", co1);
1817 shader->SetAttributePointerf(
"aUV", tco1);
1819 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1823 glDisable(GL_BLEND);
1824 glDisable(GL_TEXTURE_2D);
1826 glDeleteTextures(1, &texobj);
1834void ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1835 wxCoord *descent, wxCoord *externalLeading,
1842 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1845 if (font) f = *font;
1850 m_texfont.Build(f, 1.0, m_dpi_factor);
1851 m_texfont.GetTextExtent(
string, w, h);
1854 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1858 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1864 if (w && (*w > 500)) *w = 500;
1865 if (h && (*h > 500)) *h = 500;
1868void ocpnDC::ResetBoundingBox() {
1869 if (dc) dc->ResetBoundingBox();
1872void ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
1873 if (dc) dc->CalcBoundingBox(x, y);
1876bool ocpnDC::ConfigurePen() {
1877 if (!m_pen.IsOk())
return false;
1878 if (m_pen == *wxTRANSPARENT_PEN)
return false;
1880 wxColour c = m_pen.GetColour();
1881 int width = m_pen.GetWidth();
1883#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1884 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1886 glLineWidth(wxMax(g_GLMinSymbolLineWidth, width));
1891bool ocpnDC::ConfigureBrush() {
1892 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
1895 wxColour c = m_brush.GetColour();
1896#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1897 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1903void ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1904 int format,
const unsigned char *data) {
1906#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1908 glRasterPos2i(x, y);
1910 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
1912 glDisable(GL_BLEND);
1921 if (!m_glchartCanvas && !m_glcanvas)
return;
1924 m_vp.SetVPTransformMatrix();
1932 if (m_pcolor_tri_shader_program) {
1933 m_pcolor_tri_shader_program->Bind();
1934 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
1935 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1936 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1938 m_pcolor_tri_shader_program->UnBind();
1940 if (m_pAALine_shader_program) {
1941 m_pAALine_shader_program->Bind();
1942 m_pAALine_shader_program->SetUniformMatrix4fv(
1943 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1944 m_pAALine_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1946 m_pAALine_shader_program->UnBind();
1949 if (m_pcircle_filled_shader_program) {
1950 m_pcircle_filled_shader_program->Bind();
1951 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
1952 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1953 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1955 m_pcircle_filled_shader_program->UnBind();
1958 if (m_ptexture_2D_shader_program) {
1959 m_ptexture_2D_shader_program->Bind();
1960 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
1961 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1962 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1964 m_ptexture_2D_shader_program->UnBind();
1972#ifdef USE_ANDROID_GLES2
1973const GLchar *odc_preamble =
"\n";
1975const GLchar *odc_preamble =
1977 "#define precision\n"
1985static const GLchar *odc_color_tri_vertex_shader_source =
1986 "attribute vec2 position;\n"
1987 "uniform mat4 MVMatrix;\n"
1988 "uniform mat4 TransformMatrix;\n"
1989 "uniform vec4 color;\n"
1990 "varying vec4 fragColor;\n"
1992 " fragColor = color;\n"
1993 " gl_Position = MVMatrix * TransformMatrix * vec4(position, 0.0, 1.0);\n"
1996static const GLchar *odc_color_tri_fragment_shader_source =
1997 "precision lowp float;\n"
1998 "varying vec4 fragColor;\n"
2000 " gl_FragColor = fragColor;\n"
2003static const GLchar *odc_AALine_vertex_shader_source =
2004 "uniform vec2 uViewPort; //Width and Height of the viewport\n"
2005 "varying vec2 vLineCenter;\n"
2006 "attribute vec2 position;\n"
2007 "uniform mat4 MVMatrix;\n"
2008 "uniform mat4 TransformMatrix;\n"
2011 " vec4 pp = MVMatrix * vec4(position, 0.0, 1.0);\n"
2012 " gl_Position = pp;\n"
2013 " vec2 vp = uViewPort;\n"
2014 " vLineCenter = 0.5*(pp.xy + vec2(1, 1))*vp;\n"
2017static const GLchar *odc_AALine_fragment_shader_source =
2018 "precision mediump float;\n"
2019 "uniform float uLineWidth;\n"
2020 "uniform vec4 color;\n"
2021 "uniform float uBlendFactor; //1.5..2.5\n"
2022 "varying vec2 vLineCenter;\n"
2025 " vec4 col = color;\n"
2026 " float d = length(vLineCenter-gl_FragCoord.xy);\n"
2027 " float w = uLineWidth;\n"
2031 " if(float((w/2-d)/(w/2)) < .5){\n"
2032 " //col.w *= pow(float((w-d)/w), uBlendFactor);\n"
2033 " col.w *= pow(float((w/2-d)/(w/2)), uBlendFactor);\n"
2036 " gl_FragColor = col;\n"
2040static const GLchar *odc_circle_filled_vertex_shader_source =
2041 "precision highp float;\n"
2042 "attribute vec2 aPos;\n"
2043 "uniform mat4 MVMatrix;\n"
2044 "uniform mat4 TransformMatrix;\n"
2046 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2049static const GLchar *odc_circle_filled_fragment_shader_source =
2050 "precision highp float;\n"
2051 "uniform float border_width;\n"
2052 "uniform float circle_radius;\n"
2053 "uniform vec4 circle_color;\n"
2054 "uniform vec4 border_color;\n"
2055 "uniform vec2 circle_center;\n"
2057 "float d = distance(gl_FragCoord.xy, circle_center);\n"
2058 "if (d < (circle_radius - border_width)) { gl_FragColor = circle_color; }\n"
2059 "else if (d < circle_radius) { gl_FragColor = border_color; }\n"
2060 "else { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); }\n"
2064static const GLchar *odc_texture_2D_vertex_shader_source =
2065 "attribute vec2 aPos;\n"
2066 "attribute vec2 aUV;\n"
2067 "uniform mat4 MVMatrix;\n"
2068 "uniform mat4 TransformMatrix;\n"
2069 "varying vec2 varCoord;\n"
2071 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2072 " varCoord = aUV;\n"
2075static const GLchar *odc_texture_2D_fragment_shader_source =
2076 "precision lowp float;\n"
2077 "uniform sampler2D uTex;\n"
2078 "varying vec2 varCoord;\n"
2080 " gl_FragColor = texture2D(uTex, varCoord);\n"
2084void ocpnDC::BuildShaders() {
2086 if (!m_pcolor_tri_shader_program) {
2088 shaderProgram->addShaderFromSource(odc_color_tri_vertex_shader_source,
2090 shaderProgram->addShaderFromSource(odc_color_tri_fragment_shader_source,
2091 GL_FRAGMENT_SHADER);
2092 shaderProgram->linkProgram();
2094 if (shaderProgram->isOK()) m_pcolor_tri_shader_program = shaderProgram;
2097 if (!m_pAALine_shader_program) {
2099 shaderProgram->addShaderFromSource(odc_AALine_fragment_shader_source,
2100 GL_FRAGMENT_SHADER);
2101 shaderProgram->addShaderFromSource(odc_AALine_vertex_shader_source,
2103 shaderProgram->linkProgram();
2105 if (shaderProgram->isOK()) m_pAALine_shader_program = shaderProgram;
2108 if (!m_pcircle_filled_shader_program) {
2110 shaderProgram->addShaderFromSource(odc_circle_filled_vertex_shader_source,
2112 shaderProgram->addShaderFromSource(odc_circle_filled_fragment_shader_source,
2113 GL_FRAGMENT_SHADER);
2114 shaderProgram->linkProgram();
2116 if (shaderProgram->isOK()) m_pcircle_filled_shader_program = shaderProgram;
2119 if (!m_ptexture_2D_shader_program) {
2121 shaderProgram->addShaderFromSource(odc_texture_2D_vertex_shader_source,
2123 shaderProgram->addShaderFromSource(odc_texture_2D_fragment_shader_source,
2124 GL_FRAGMENT_SHADER);
2125 shaderProgram->linkProgram();
2127 if (shaderProgram->isOK()) m_ptexture_2D_shader_program = shaderProgram;
Generic Chart canvas base.
Wrapper class for OpenGL shader programs.
ViewPort - Core geographic projection and coordinate transformation engine.
int pix_height
Height of the viewport in physical pixels.
double rotation
Rotation angle of the viewport in radians.
int pix_width
Width of the viewport in physical pixels.
OpenGL chart rendering canvas.
Device context class that can use either wxDC or OpenGL for drawing.
void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, bool b_hiqual=true)
Draw a line between two points using either wxDC or OpenGL.
Global variables stored in configuration file.
Extern C linked utilities.
OpenGL chart rendering canvas.
PlugIn Object Definition/API.
wxString GetLocaleCanonicalName()
Gets system locale canonical name.
Layer to use wxDC or opengl.