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);
1487 gluTessNormal(m_tobj, 0, 0, 1);
1488 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1490 if (ConfigureBrush()) {
1491 gluTessBeginPolygon(m_tobj,
this);
1492 gluTessBeginContour(m_tobj);
1494 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas
1497 for (
int i = 0; i < n; i++) {
1498 double *p =
new double[6];
1505 float xn = points[i].x - cx;
1506 float yn = points[i].y - cy;
1507 p[0] = xn * c - yn * s + cx;
1508 p[1] = xn * s + yn * c + cy;
1511 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1513 gluTessVertex(m_tobj, p, p);
1515 gluTessEndContour(m_tobj);
1516 gluTessEndPolygon(m_tobj);
1519 gluDeleteTess(m_tobj);
1534void ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1535 wxCoord yoffset,
float scale) {
1536#if wxUSE_GRAPHICS_CONTEXT
1538 wxGraphicsPath gpath = pgc->CreatePath();
1539 gpath.MoveToPoint(points[0].x *
scale + xoffset,
1540 points[0].y *
scale + yoffset);
1541 for (
int i = 1; i < n; i++)
1542 gpath.AddLineToPoint(points[i].x *
scale + xoffset,
1543 points[i].y *
scale + yoffset);
1544 gpath.AddLineToPoint(points[0].x *
scale + xoffset,
1545 points[0].y *
scale + yoffset);
1547 pgc->SetPen(GetPen());
1548 pgc->SetBrush(GetBrush());
1549 pgc->DrawPath(gpath);
1551 for (
int i = 0; i < n; i++)
1552 dc->CalcBoundingBox(points[i].x *
scale + xoffset,
1553 points[i].y *
scale + yoffset);
1556 DrawPolygon(n, points, xoffset, yoffset,
scale);
1559void ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1562 if (x < 0 || y < 0) {
1563 int dx = (x < 0 ? -x : 0);
1564 int dy = (y < 0 ? -y : 0);
1565 int w = bitmap.GetWidth() - dx;
1566 int h = bitmap.GetHeight() - dy;
1568 if (w <= 0 || h <= 0)
return;
1569 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1576 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1584#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1585 wxImage image = bmp.ConvertToImage();
1586 int w = image.GetWidth(), h = image.GetHeight();
1589 unsigned char *d = image.GetData();
1590 unsigned char *a = image.GetAlpha();
1593 if (image.HasMask()) a = 0;
1595 unsigned char mr, mg, mb;
1596 if (!a && !image.GetOrFindMaskColour(&mr, &mg, &mb)) {
1597 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1600 unsigned char *e =
new unsigned char[4 * w * h];
1602 for (
int y = 0; y < h; y++)
1603 for (
int x = 0; x < w; x++) {
1604 unsigned char r, g, b;
1605 int off = (y * w + x);
1615 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1621 glColor4f(1, 1, 1, 1);
1622 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1625 glRasterPos2i(x, y);
1627 if (image.GetData())
1628 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1636void ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y,
float angle) {
1637 if (dc) dc->DrawText(text, x, y);
1645 m_texfont.Build(m_font, 1.0,
1647 m_texfont.GetTextExtent(text, &w, &h);
1648 m_texfont.SetColor(m_textforegroundcolour);
1652 glEnable(GL_TEXTURE_2D);
1653 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1655 m_texfont.RenderString(text, x, y, angle);
1657 glDisable(GL_TEXTURE_2D);
1658 glDisable(GL_BLEND);
1662 sdc.SetFont(m_font);
1663 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1668 temp_dc.SelectObject(bmp);
1671 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1675 temp_dc.SetFont(m_font);
1676 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1677 temp_dc.DrawText(text, 0, 0);
1678 temp_dc.SelectObject(wxNullBitmap);
1682 wxImage image = bmp.ConvertToImage();
1685 int dx = (x < 0 ? -x : 0);
1686 int dy = (y < 0 ? -y : 0);
1687 w = bmp.GetWidth() - dx;
1688 h = bmp.GetHeight() - dy;
1690 if (w <= 0 || h <= 0)
return;
1691 image = image.GetSubImage(wxRect(dx, dy, w, h));
1696 unsigned char *data =
new unsigned char[w * h * 4];
1697 unsigned char *im = image.GetData();
1700 unsigned int r = m_textforegroundcolour.Red();
1701 unsigned int g = m_textforegroundcolour.Green();
1702 unsigned int b = m_textforegroundcolour.Blue();
1703 for (
int i = 0; i < h; i++) {
1704 for (
int j = 0; j < w; j++) {
1705 unsigned int index = ((i * w) + j) * 4;
1707 data[index + 1] = g;
1708 data[index + 2] = b;
1709 data[index + 3] = im[((i * w) + j) * 3];
1714 unsigned int texobj;
1716 glGenTextures(1, &texobj);
1717 glBindTexture(GL_TEXTURE_2D, texobj);
1719 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1722 int TextureWidth = NextPow2(w);
1723 int TextureHeight = NextPow2(h);
1724 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1725 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1726 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1729 glEnable(GL_TEXTURE_2D);
1731 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1733 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1760 if (m_glchartCanvas) {
1761 shader = ptexture_2D_shader_program[m_canvasIndex];
1768 shader = m_ptexture_2D_shader_program;
1770 shader->SetUniformMatrix4fv(
"MVMatrix",
1771 (
float *)&(m_vp.vp_matrix_transform));
1775 shader->SetUniform1i(
"uTex", 0);
1780 mat4x4_rotate_Z(Q, I, 0);
1786 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
1813 shader->SetAttributePointerf(
"aPos", co1);
1814 shader->SetAttributePointerf(
"aUV", tco1);
1816 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1820 glDisable(GL_BLEND);
1821 glDisable(GL_TEXTURE_2D);
1823 glDeleteTextures(1, &texobj);
1831void ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1832 wxCoord *descent, wxCoord *externalLeading,
1839 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1842 if (font) f = *font;
1847 m_texfont.Build(f, 1.0, m_dpi_factor);
1848 m_texfont.GetTextExtent(
string, w, h);
1851 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1855 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1861 if (w && (*w > 500)) *w = 500;
1862 if (h && (*h > 500)) *h = 500;
1865void ocpnDC::ResetBoundingBox() {
1866 if (dc) dc->ResetBoundingBox();
1869void ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
1870 if (dc) dc->CalcBoundingBox(x, y);
1873bool ocpnDC::ConfigurePen() {
1874 if (!m_pen.IsOk())
return false;
1875 if (m_pen == *wxTRANSPARENT_PEN)
return false;
1877 wxColour c = m_pen.GetColour();
1878 int width = m_pen.GetWidth();
1880#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1881 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1883 glLineWidth(wxMax(g_GLMinSymbolLineWidth, width));
1888bool ocpnDC::ConfigureBrush() {
1889 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
1892 wxColour c = m_brush.GetColour();
1893#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1894 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1900void ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1901 int format,
const unsigned char *data) {
1903#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1905 glRasterPos2i(x, y);
1907 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
1909 glDisable(GL_BLEND);
1918 if (!m_glchartCanvas && !m_glcanvas)
return;
1921 m_vp.SetVPTransformMatrix();
1929 if (m_pcolor_tri_shader_program) {
1930 m_pcolor_tri_shader_program->Bind();
1931 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
1932 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1933 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1935 m_pcolor_tri_shader_program->UnBind();
1937 if (m_pAALine_shader_program) {
1938 m_pAALine_shader_program->Bind();
1939 m_pAALine_shader_program->SetUniformMatrix4fv(
1940 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1941 m_pAALine_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1943 m_pAALine_shader_program->UnBind();
1946 if (m_pcircle_filled_shader_program) {
1947 m_pcircle_filled_shader_program->Bind();
1948 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
1949 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1950 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1952 m_pcircle_filled_shader_program->UnBind();
1955 if (m_ptexture_2D_shader_program) {
1956 m_ptexture_2D_shader_program->Bind();
1957 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
1958 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1959 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1961 m_ptexture_2D_shader_program->UnBind();
1969#ifdef USE_ANDROID_GLES2
1970const GLchar *odc_preamble =
"\n";
1972const GLchar *odc_preamble =
1974 "#define precision\n"
1982static const GLchar *odc_color_tri_vertex_shader_source =
1983 "attribute vec2 position;\n"
1984 "uniform mat4 MVMatrix;\n"
1985 "uniform mat4 TransformMatrix;\n"
1986 "uniform vec4 color;\n"
1987 "varying vec4 fragColor;\n"
1989 " fragColor = color;\n"
1990 " gl_Position = MVMatrix * TransformMatrix * vec4(position, 0.0, 1.0);\n"
1993static const GLchar *odc_color_tri_fragment_shader_source =
1994 "precision lowp float;\n"
1995 "varying vec4 fragColor;\n"
1997 " gl_FragColor = fragColor;\n"
2000static const GLchar *odc_AALine_vertex_shader_source =
2001 "uniform vec2 uViewPort; //Width and Height of the viewport\n"
2002 "varying vec2 vLineCenter;\n"
2003 "attribute vec2 position;\n"
2004 "uniform mat4 MVMatrix;\n"
2005 "uniform mat4 TransformMatrix;\n"
2008 " vec4 pp = MVMatrix * vec4(position, 0.0, 1.0);\n"
2009 " gl_Position = pp;\n"
2010 " vec2 vp = uViewPort;\n"
2011 " vLineCenter = 0.5*(pp.xy + vec2(1, 1))*vp;\n"
2014static const GLchar *odc_AALine_fragment_shader_source =
2015 "precision mediump float;\n"
2016 "uniform float uLineWidth;\n"
2017 "uniform vec4 color;\n"
2018 "uniform float uBlendFactor; //1.5..2.5\n"
2019 "varying vec2 vLineCenter;\n"
2022 " vec4 col = color;\n"
2023 " float d = length(vLineCenter-gl_FragCoord.xy);\n"
2024 " float w = uLineWidth;\n"
2028 " if(float((w/2-d)/(w/2)) < .5){\n"
2029 " //col.w *= pow(float((w-d)/w), uBlendFactor);\n"
2030 " col.w *= pow(float((w/2-d)/(w/2)), uBlendFactor);\n"
2033 " gl_FragColor = col;\n"
2037static const GLchar *odc_circle_filled_vertex_shader_source =
2038 "precision highp float;\n"
2039 "attribute vec2 aPos;\n"
2040 "uniform mat4 MVMatrix;\n"
2041 "uniform mat4 TransformMatrix;\n"
2043 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2046static const GLchar *odc_circle_filled_fragment_shader_source =
2047 "precision highp float;\n"
2048 "uniform float border_width;\n"
2049 "uniform float circle_radius;\n"
2050 "uniform vec4 circle_color;\n"
2051 "uniform vec4 border_color;\n"
2052 "uniform vec2 circle_center;\n"
2054 "float d = distance(gl_FragCoord.xy, circle_center);\n"
2055 "if (d < (circle_radius - border_width)) { gl_FragColor = circle_color; }\n"
2056 "else if (d < circle_radius) { gl_FragColor = border_color; }\n"
2057 "else { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); }\n"
2061static const GLchar *odc_texture_2D_vertex_shader_source =
2062 "attribute vec2 aPos;\n"
2063 "attribute vec2 aUV;\n"
2064 "uniform mat4 MVMatrix;\n"
2065 "uniform mat4 TransformMatrix;\n"
2066 "varying vec2 varCoord;\n"
2068 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2069 " varCoord = aUV;\n"
2072static const GLchar *odc_texture_2D_fragment_shader_source =
2073 "precision lowp float;\n"
2074 "uniform sampler2D uTex;\n"
2075 "varying vec2 varCoord;\n"
2077 " gl_FragColor = texture2D(uTex, varCoord);\n"
2081void ocpnDC::BuildShaders() {
2083 if (!m_pcolor_tri_shader_program) {
2085 shaderProgram->addShaderFromSource(odc_color_tri_vertex_shader_source,
2087 shaderProgram->addShaderFromSource(odc_color_tri_fragment_shader_source,
2088 GL_FRAGMENT_SHADER);
2089 shaderProgram->linkProgram();
2091 if (shaderProgram->isOK()) m_pcolor_tri_shader_program = shaderProgram;
2094 if (!m_pAALine_shader_program) {
2096 shaderProgram->addShaderFromSource(odc_AALine_fragment_shader_source,
2097 GL_FRAGMENT_SHADER);
2098 shaderProgram->addShaderFromSource(odc_AALine_vertex_shader_source,
2100 shaderProgram->linkProgram();
2102 if (shaderProgram->isOK()) m_pAALine_shader_program = shaderProgram;
2105 if (!m_pcircle_filled_shader_program) {
2107 shaderProgram->addShaderFromSource(odc_circle_filled_vertex_shader_source,
2109 shaderProgram->addShaderFromSource(odc_circle_filled_fragment_shader_source,
2110 GL_FRAGMENT_SHADER);
2111 shaderProgram->linkProgram();
2113 if (shaderProgram->isOK()) m_pcircle_filled_shader_program = shaderProgram;
2116 if (!m_ptexture_2D_shader_program) {
2118 shaderProgram->addShaderFromSource(odc_texture_2D_vertex_shader_source,
2120 shaderProgram->addShaderFromSource(odc_texture_2D_fragment_shader_source,
2121 GL_FRAGMENT_SHADER);
2122 shaderProgram->linkProgram();
2124 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.