38#include <wx/graphics.h>
39#include <wx/dcclient.h>
62#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
63extern GLint color_tri_shader_program;
64extern GLint circle_filled_shader_program;
65extern GLint texture_2D_shader_program;
72#define PI 3.1415926535897931160E0
76static wxArrayPtrVoid gTesselatorVertices;
79 : m_glchartCanvas(&canvas),
83 m_brush(wxNullBrush) {
84#if wxUSE_GRAPHICS_CONTEXT
89 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
93ocpnDC::ocpnDC(wxGLCanvas &canvas)
94 : m_glchartCanvas(NULL),
98 m_brush(wxNullBrush) {
99#if wxUSE_GRAPHICS_CONTEXT
105ocpnDC::ocpnDC(wxDC &pdc)
106 : m_glchartCanvas(NULL),
110 m_brush(wxNullBrush) {
111#if wxUSE_GRAPHICS_CONTEXT
113 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
115 pgc = wxGraphicsContext::Create(*pmdc);
117 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
118 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
126 : m_glchartCanvas(NULL),
130 m_brush(wxNullBrush) {
131#if wxUSE_GRAPHICS_CONTEXT
138#if wxUSE_GRAPHICS_CONTEXT
144 free(s_odc_tess_work_buf);
146 delete m_pcolor_tri_shader_program;
147 delete m_pAALine_shader_program;
148 delete m_pcircle_filled_shader_program;
149 delete m_ptexture_2D_shader_program;
159 m_textforegroundcolour = wxColour(0, 0, 0);
161 s_odc_tess_work_buf = NULL;
164#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
165 s_odc_tess_vertex_idx = 0;
166 s_odc_tess_vertex_idx_this = 0;
167 s_odc_tess_buf_len = 0;
169 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
170 s_odc_tess_buf_len = 100;
172 m_pcolor_tri_shader_program = NULL;
173 m_pAALine_shader_program = NULL;
174 m_pcircle_filled_shader_program = NULL;
175 m_ptexture_2D_shader_program = NULL;
180 m_glchartCanvas = canvas;
181 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
185void ocpnDC::Clear() {
190 wxBrush tmpBrush = m_brush;
192 if (m_glchartCanvas) {
193 SetBrush(wxBrush(m_glchartCanvas->GetBackgroundColour()));
194 m_glchartCanvas->GetSize(&w, &h);
195 }
else if (m_glcanvas) {
196 SetBrush(wxBrush(m_glcanvas->GetBackgroundColour()));
197 m_glcanvas->GetSize(&w, &h);
201 DrawRectangle(0, 0, w, h);
207void ocpnDC::SetBackground(
const wxBrush &brush) {
209 dc->SetBackground(brush);
213 m_glchartCanvas->SetBackgroundColour(brush.GetColour());
215 m_glcanvas->SetBackgroundColour(brush.GetColour());
222void ocpnDC::SetPen(
const wxPen &pen) {
224 if (pen == wxNullPen)
225 dc->SetPen(*wxTRANSPARENT_PEN);
232void ocpnDC::SetBrush(
const wxBrush &brush) {
239void ocpnDC::SetTextForeground(
const wxColour &colour) {
241 dc->SetTextForeground(colour);
243 m_textforegroundcolour = colour;
246void ocpnDC::SetFont(
const wxFont &font) {
253const wxPen &ocpnDC::GetPen()
const {
254 if (dc)
return dc->GetPen();
258const wxBrush &ocpnDC::GetBrush()
const {
259 if (dc)
return dc->GetBrush();
263const wxFont &ocpnDC::GetFont()
const {
264 if (dc)
return dc->GetFont();
268void ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
270 dc->GetSize(width, height);
273 if (m_glchartCanvas) {
274 *width = m_glchartCanvas->GetGLCanvasWidth();
275 *height = m_glchartCanvas->GetGLCanvasHeight();
276 }
else if (m_glcanvas) {
277 m_glcanvas->GetSize(width, height);
283void ocpnDC::SetGLAttrs(
bool highQuality) {
288 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
289 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
290 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
293 glDisable(GL_LINE_SMOOTH);
294 glDisable(GL_POLYGON_SMOOTH);
300void ocpnDC::SetGLStipple()
const {
303#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
304 switch (m_pen.GetStyle()) {
305 case wxPENSTYLE_DOT: {
306 glLineStipple(1, 0x3333);
307 glEnable(GL_LINE_STIPPLE);
310 case wxPENSTYLE_LONG_DASH: {
311 glLineStipple(1, 0xFFF8);
312 glEnable(GL_LINE_STIPPLE);
315 case wxPENSTYLE_SHORT_DASH: {
316 glLineStipple(1, 0x3F3F);
317 glEnable(GL_LINE_STIPPLE);
320 case wxPENSTYLE_DOT_DASH: {
321 glLineStipple(1, 0x8FF1);
322 glEnable(GL_LINE_STIPPLE);
334void DrawEndCap(
float x1,
float y1,
float t1,
float angle) {
335#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
336 const int steps = 16;
339 for (
int i = 0; i <= steps; i++) {
340 float a = angle + M_PI / 2 + M_PI / steps * i;
342 float xb = x1 + t1 / 2 * cos(a);
343 float yb = y1 + t1 / 2 * sin(a);
358void ocpnDC::DrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
362 float angle = atan2f(y2 - y1, x2 - x1);
363 float t1 = pen.GetWidth();
364 float t2sina1 = t1 / 2 * sinf(angle);
365 float t2cosa1 = t1 / 2 * cosf(angle);
369 if (m_glchartCanvas) {
370 shader = pcolor_tri_shader_program[m_canvasIndex];
376 shader = m_pcolor_tri_shader_program;
378 shader->SetUniformMatrix4fv(
"MVMatrix",
379 (
float *)&(m_vp.vp_matrix_transform));
382 wxColor c = pen.GetColour();
384 colorv[0] = c.Red() / float(256);
385 colorv[1] = c.Green() / float(256);
386 colorv[2] = c.Blue() / float(256);
387 colorv[3] = c.Alpha() / float(256);
388 shader->SetUniform4fv(
"color", colorv);
391 shader->SetAttributePointerf(
"position", vert);
396 int n_dashes = pen.GetDashes(&dashes);
398 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
402 float ldraw = t1 * dashes[0];
403 float lspace = t1 * dashes[1];
405 while (lrun < lpix) {
407 float xb = xa + ldraw * cosf(angle);
408 float yb = ya + ldraw * sinf(angle);
410 if ((lrun + ldraw) >= lpix)
416 vert[0] = xa + t2sina1;
417 vert[1] = ya - t2cosa1;
418 vert[2] = xb + t2sina1;
419 vert[3] = yb - t2cosa1;
420 vert[4] = xb - t2sina1;
421 vert[5] = yb + t2cosa1;
422 vert[6] = xb - t2sina1;
423 vert[7] = yb + t2cosa1;
424 vert[8] = xa - t2sina1;
425 vert[9] = ya + t2cosa1;
426 vert[10] = xa + t2sina1;
427 vert[11] = ya - t2cosa1;
429 glDrawArrays(GL_TRIANGLES, 0, 6);
436 xb = xa + lspace * cos(angle);
437 yb = ya + lspace * sin(angle);
445 vert[0] = x1 + t2sina1;
446 vert[1] = y1 - t2cosa1;
447 vert[2] = x2 + t2sina1;
448 vert[3] = y2 - t2cosa1;
449 vert[4] = x2 - t2sina1;
450 vert[5] = y2 + t2cosa1;
451 vert[6] = x2 - t2sina1;
452 vert[7] = y2 + t2cosa1;
453 vert[8] = x1 - t2sina1;
454 vert[9] = y1 + t2cosa1;
455 vert[10] = x1 + t2sina1;
456 vert[11] = y1 - t2cosa1;
458 glDrawArrays(GL_TRIANGLES, 0, 6);
476 if (dc) dc->DrawLine(x1, y1, x2, y2);
478 else if (ConfigurePen()) {
479 bool b_draw_thick =
false;
481 float pen_width = wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth());
489 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
492 if (pen_width > 1.0) {
494 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
495 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
496 if (pen_width > parms[1])
499 glLineWidth(pen_width);
501 glLineWidth(pen_width);
505 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
506 if (pen_width > parms[1])
509 glLineWidth(pen_width);
511 glLineWidth(pen_width);
514#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
516 DrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
524 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
529 GetSize(&width, &height);
533 shader->SetUniform2fv(
"uViewPort", vpx);
536 colorv[0] = m_pen.GetColour().Red() / float(256);
537 colorv[1] = m_pen.GetColour().Green() / float(256);
538 colorv[2] = m_pen.GetColour().Blue() / float(256);
541 shader->SetUniform4fv(
"color", colorv);
544 shader->SetAttributePointerf(
"position", fBuf);
548 int n_dashes = m_pen.GetDashes(&dashes);
550 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
551 float cosa = cosf(angle);
552 float sina = sinf(angle);
553 float t1 = m_pen.GetWidth();
555 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
559 float ldraw = t1 * dashes[0];
560 float lspace = t1 * dashes[1];
562 ldraw = wxMax(ldraw, 4.0);
563 lspace = wxMax(lspace, 4.0);
564 lpix = wxMin(lpix, 2000.0);
566 while (lrun < lpix) {
568 float xb = xa + ldraw * cosa;
569 float yb = ya + ldraw * sina;
571 if ((lrun + ldraw) >= lpix)
582 glDrawArrays(GL_LINES, 0, 2);
584 xa = xa + (lspace + ldraw) * cosa;
585 ya = ya + (lspace + ldraw) * sina;
586 lrun += lspace + ldraw;
595 glDrawArrays(GL_LINES, 0, 2);
601 if (m_glchartCanvas) {
602 shader = pcolor_tri_shader_program[m_canvasIndex];
609 shader = m_pcolor_tri_shader_program;
611 shader->SetUniformMatrix4fv(
"MVMatrix",
612 (
float *)&(m_vp.vp_matrix_transform));
616 colorv[0] = m_pen.GetColour().Red() / float(256);
617 colorv[1] = m_pen.GetColour().Green() / float(256);
618 colorv[2] = m_pen.GetColour().Blue() / float(256);
621 shader->SetUniform4fv(
"color", colorv);
623 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
626 shader->SetAttributePointerf(
"position", fBuf);
629 int n_dashes = m_pen.GetDashes(&dashes);
631 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
632 float cosa = cosf(angle);
633 float sina = sinf(angle);
634 float t1 = m_pen.GetWidth();
636 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
640 float ldraw = t1 * dashes[0];
641 float lspace = t1 * dashes[1];
643 ldraw = wxMax(ldraw, 4.0);
644 lspace = wxMax(lspace, 4.0);
647 while (lrun < lpix) {
649 float xb = xa + ldraw * cosa;
650 float yb = ya + ldraw * sina;
652 if ((lrun + ldraw) >= lpix)
663 glDrawArrays(GL_LINES, 0, 2);
665 xa = xa + (lspace + ldraw) * cosa;
666 ya = ya + (lspace + ldraw) * sina;
667 lrun += lspace + ldraw;
676 glDrawArrays(GL_LINES, 0, 2);
685 glDisable(GL_LINE_STIPPLE);
688 glDisable(GL_LINE_SMOOTH);
696void ocpnDC::DrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
697 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
701 wxPoint p0 = points[0];
702 for (
int i = 1; i < n; i++) {
703 DrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
704 points[i].y + yoffset, pen, b_hiqual);
711void ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
712 wxCoord yoffset,
bool b_hiqual) {
713 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
715 else if (ConfigurePen()) {
720 SetGLAttrs(b_hiqual);
722 bool b_draw_thick =
false;
724 glDisable(GL_LINE_STIPPLE);
730 if (m_pen.GetWidth() > 1) {
732 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
733 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
735 if (m_pen.GetWidth() > parms[1])
738 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
740 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
742 if (m_pen.GetWidth() > 1) {
744 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
745 if (m_pen.GetWidth() > parms[1])
748 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
750 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
753 if (b_draw_thick || m_pen.GetStyle() != wxPENSTYLE_SOLID) {
754 DrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
757 glDisable(GL_LINE_STIPPLE);
758 glDisable(GL_LINE_SMOOTH);
759 glDisable(GL_POLYGON_SMOOTH);
767 if (workBufSize < (
size_t)n * 2) {
768 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
772 for (
int i = 0; i < n; i++) {
773 workBuf[i * 2] = points[i].x + xoffset;
774 workBuf[(i * 2) + 1] = points[i].y + yoffset;
787 GetSize(&width, &height);
791 shader->SetUniform2fv(
"uViewPort", vpx);
794 colorv[0] = m_pen.GetColour().Red() / float(256);
795 colorv[1] = m_pen.GetColour().Green() / float(256);
796 colorv[2] = m_pen.GetColour().Blue() / float(256);
799 shader->SetUniform4fv(
"color", colorv);
801 shader->SetAttributePointerf(
"position", workBuf);
803 glDrawArrays(GL_LINE_STRIP, 0, n);
808 if (m_glchartCanvas) {
809 shader = pcolor_tri_shader_program[m_canvasIndex];
816 shader = m_pcolor_tri_shader_program;
818 shader->SetUniformMatrix4fv(
"MVMatrix",
819 (
float *)&(m_vp.vp_matrix_transform));
823 colorv[0] = m_pen.GetColour().Red() / float(256);
824 colorv[1] = m_pen.GetColour().Green() / float(256);
825 colorv[2] = m_pen.GetColour().Blue() / float(256);
828 shader->SetUniform4fv(
"color", colorv);
830 shader->SetAttributePointerf(
"position", workBuf);
832 glDrawArrays(GL_LINE_STRIP, 0, n);
839 glDisable(GL_LINE_STIPPLE);
840 glDisable(GL_LINE_SMOOTH);
841 glDisable(GL_POLYGON_SMOOTH);
848void ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
849#if wxUSE_GRAPHICS_CONTEXT
851 pgc->SetPen(GetPen());
852 pgc->StrokeLine(x1, y1, x2, y2);
854 dc->CalcBoundingBox(x1, y1);
855 dc->CalcBoundingBox(x2, y2);
861void ocpnDC::StrokeLines(
int n, wxPoint *points) {
865#if wxUSE_GRAPHICS_CONTEXT
867 wxPoint2DDouble *dPoints =
868 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
869 for (
int i = 0; i < n; i++) {
870 dPoints[i].m_x = points[i].x;
871 dPoints[i].m_y = points[i].y;
873 pgc->SetPen(GetPen());
874 pgc->StrokeLines(n, dPoints);
878 DrawLines(n, points, 0, 0,
true);
881void ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
882 if (dc) dc->DrawRectangle(x, y, w, h);
885 DrawRoundedRectangle(x, y, w, h, 0);
891static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
894#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
895 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
899 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
902 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
905 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
908 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
914 for (
int i = 0; i < steps; i++) {
915 glVertex2i(x0 + floor(x), y0 + floor(y));
916 x += dx + ddx / 2, y += dy + ddy / 2;
917 dx += ddx, dy += ddy;
919 glVertex2i(x0 + floor(x), y0 + floor(y));
924void ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
927 if (steps == 0)
return;
929 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
933 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
936 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
939 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
942 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
948 for (
int i = 0; i < steps; i++) {
949 workBuf[workBufIndex++] = x0 + floor(x);
950 workBuf[workBufIndex++] = y0 + floor(y);
952 x += dx + ddx / 2, y += dy + ddy / 2;
953 dx += ddx, dy += ddy;
956 workBuf[workBufIndex++] = x0 + floor(x);
957 workBuf[workBufIndex++] = y0 + floor(y);
961void ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
963 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
966 if (!m_glchartCanvas)
return;
969 int steps = ceil(sqrt((
float)r));
971 wxCoord x1 = x + r, x2 = x + w - r;
972 wxCoord y1 = y + r, y2 = y + h - r;
978 size_t bufReq = (steps + 1) * 8 * 2;
980 if (workBufSize < bufReq) {
981 workBuf = (
float *)realloc(workBuf, bufReq *
sizeof(
float));
982 workBufSize = bufReq;
987 drawrrhelperGLES2(x2, y1, r, 0, steps);
988 drawrrhelperGLES2(x1, y1, r, 1, steps);
989 drawrrhelperGLES2(x1, y2, r, 2, steps);
990 drawrrhelperGLES2(x2, y2, r, 3, steps);
997 fcolorv[0] = m_brush.GetColour().Red() / float(256);
998 fcolorv[1] = m_brush.GetColour().Green() / float(256);
999 fcolorv[2] = m_brush.GetColour().Blue() / float(256);
1000 fcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1001 shader->SetUniform4fv(
"color", fcolorv);
1010 mat4x4_rotate_Z(Q, I, angle);
1018 (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()
1019 ->vp_matrix_transform,
1021 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1023 shader->SetAttributePointerf(
"position", workBuf);
1026 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1030 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1031 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1032 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1033 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1035 shader->SetUniform4fv(
"color", bcolorv);
1038 glDrawArrays(GL_LINE_LOOP, 0, workBufIndex / 2);
1045void ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1047 dc->DrawCircle(x, y, radius);
1055 coords[0] = x - radius;
1056 coords[1] = y + radius;
1057 coords[2] = x + radius;
1058 coords[3] = y + radius;
1059 coords[4] = x - radius;
1060 coords[5] = y - radius;
1061 coords[6] = x + radius;
1062 coords[7] = y - radius;
1065 if (m_glchartCanvas) {
1066 shader = pcircle_filled_shader_program[m_canvasIndex];
1072 shader = m_pcircle_filled_shader_program;
1074 shader->SetUniformMatrix4fv(
"MVMatrix",
1075 (
float *)&(m_vp.vp_matrix_transform));
1081 shader->SetUniform1f(
"circle_radius", radius);
1087 GetSize(&width, &height);
1088 ctrv[1] = height - y;
1089 shader->SetUniform2fv(
"circle_center", ctrv);
1093 if (m_brush.IsOk()) {
1094 colorv[0] = m_brush.GetColour().Red() / float(256);
1095 colorv[1] = m_brush.GetColour().Green() / float(256);
1096 colorv[2] = m_brush.GetColour().Blue() / float(256);
1097 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1099 shader->SetUniform4fv(
"circle_color", colorv);
1104 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1105 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1106 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1107 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1109 shader->SetUniform4fv(
"border_color", bcolorv);
1113 shader->SetUniform1f(
"border_width", m_pen.GetWidth());
1115 shader->SetUniform1f(
"border_width", 2);
1117 shader->SetAttributePointerf(
"aPos", coords);
1120 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1126void ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1127#if wxUSE_GRAPHICS_CONTEXT
1129 wxGraphicsPath gpath = pgc->CreatePath();
1130 gpath.AddCircle(x, y, radius);
1132 pgc->SetPen(GetPen());
1133 pgc->SetBrush(GetBrush());
1134 pgc->DrawPath(gpath);
1137 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1138 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1141 DrawCircle(x, y, radius);
1144void ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) {
1145 if (dc) dc->DrawEllipse(x, y, width, height);
1148 float r1 = width / 2, r2 = height / 2;
1149 float cx = x + r1, cy = y + r2;
1155 float steps = floorf(
1156 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1160 glDisable(GL_BLEND);
1165void ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1166 wxCoord yoffset,
float scale,
float angle) {
1167 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1182 if (m_glchartCanvas) {
1183 line_shader = pAALine_shader_program[m_canvasIndex];
1184 mvmatrix = (
float *)&(
1185 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1187 line_shader = m_pAALine_shader_program;
1188 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1193 line_shader->Bind();
1195 line_shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
1196 line_shader->SetUniform1f(
"uBlendFactor", 2.0);
1201 GetSize(&width, &height);
1205 line_shader->SetUniform2fv(
"uViewPort", vpx);
1208 colorv[0] = m_pen.GetColour().Red() / float(256);
1209 colorv[1] = m_pen.GetColour().Green() / float(256);
1210 colorv[2] = m_pen.GetColour().Blue() / float(256);
1213 line_shader->SetUniform4fv(
"color", colorv);
1220 mat4x4_rotate_Z(Q, I, angle);
1233 line_shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1235 line_shader->UnBind();
1239 if (ConfigureBrush())
1240 DrawPolygonTessellated(n, points, xoffset, yoffset);
1244 if (workBufSize < (
size_t)n * 2) {
1245 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1246 workBufSize = n * 4;
1249 for (
int i = 0; i < n; i++) {
1250 workBuf[i * 2] = (points[i].x *
scale);
1251 workBuf[i * 2 + 1] = (points[i].y *
scale);
1254 line_shader->Bind();
1255 line_shader->SetAttributePointerf(
"position", workBuf);
1258 glDrawArrays(GL_LINE_LOOP, 0, n);
1265 line_shader->UnBind();
1270 if (workBufSize < (
size_t)n * 2) {
1271 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1272 workBufSize = n * 4;
1275 for (
int i = 0; i < n; i++) {
1276 workBuf[i * 2] = (points[i].x *
scale);
1277 workBuf[i * 2 + 1] = (points[i].y *
scale);
1284 if (m_glchartCanvas) {
1285 shader = pcolor_tri_shader_program[m_canvasIndex];
1286 mvmatrix = (
float *)&(
1287 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1289 shader = m_pcolor_tri_shader_program;
1290 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1297 mat4x4_rotate_Z(Q, I, angle);
1303 mat4x4_mul(X, (
float(*)[4])mvmatrix, Q);
1304 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1308 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1309 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1310 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1311 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1312 shader->SetUniform4fv(
"color", bcolorv);
1314 shader->SetAttributePointerf(
"position", workBuf);
1319 float x1 = workBuf[4];
1320 float y1 = workBuf[5];
1321 workBuf[4] = workBuf[6];
1322 workBuf[5] = workBuf[7];
1326 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1327 }
else if (n == 3) {
1328 glDrawArrays(GL_TRIANGLES, 0, 3);
1332 if (m_glchartCanvas) {
1333 shader->SetUniformMatrix4fv(
1334 "MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()
1335 ->vp_matrix_transform);
1343 for (
int i = 0; i < n; i++) {
1344 workBuf[i * 2] = (points[i].x *
scale);
1345 workBuf[i * 2 + 1] = (points[i].y *
scale);
1348 line_shader->Bind();
1350 line_shader->SetAttributePointerf(
"position", workBuf);
1352 glDrawArrays(GL_LINE_LOOP, 0, n);
1359 line_shader->UnBind();
1385#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1387static std::list<double *> odc_combine_work_data;
1388static void odc_combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
1389 GLfloat weight[4], GLdouble **dataOut,
1397void odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1401 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1402 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1403 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1405 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1406 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1407 if (NULL == pDC->s_odc_tess_work_buf) {
1411 pDC->s_odc_tess_buf_len = new_buf_len;
1414 GLdouble *pointer = (GLdouble *)vertex;
1416 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1417 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1419 pDC->s_odc_nvertex++;
1422void odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1424 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1425 pDC->s_odc_tess_mode = mode;
1426 pDC->s_odc_nvertex = 0;
1429void odc_endCallbackD_GLSL(
void *data) {
1433 GLShaderProgram *shader = pcolor_tri_shader_program[pDC->m_canvasIndex];
1437 wxColour c = pDC->GetBrush().GetColour();
1439 colorv[0] = c.Red() / float(256);
1440 colorv[1] = c.Green() / float(256);
1441 colorv[2] = c.Blue() / float(256);
1442 colorv[3] = c.Alpha() / float(256);
1443 shader->SetUniform4fv(
"color", colorv);
1445 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1446 shader->SetAttributePointerf(
"position", bufPt);
1448 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1458void ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1460 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1463 if (!m_glchartCanvas)
return;
1465#if !defined(ocpnUSE_GLES) || \
1466 defined(USE_ANDROID_GLES2)
1470 DrawPolygon(n, points, xoffset, yoffset);
1474#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1475 m_tobj = gluNewTess();
1476 s_odc_tess_vertex_idx = 0;
1478 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1479 (_GLUfuncptr)&odc_vertexCallbackD_GLSL);
1480 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1481 (_GLUfuncptr)&odc_beginCallbackD_GLSL);
1482 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1483 (_GLUfuncptr)&odc_endCallbackD_GLSL);
1484 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1485 (_GLUfuncptr)&odc_combineCallbackD);
1488 gluTessNormal(m_tobj, 0, 0, 1);
1489 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1491 if (ConfigureBrush()) {
1492 gluTessBeginPolygon(m_tobj,
this);
1493 gluTessBeginContour(m_tobj);
1495 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas
1498 for (
int i = 0; i < n; i++) {
1499 double *p =
new 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, p);
1516 gluTessEndContour(m_tobj);
1517 gluTessEndPolygon(m_tobj);
1520 gluDeleteTess(m_tobj);
1535void ocpnDC::StrokePolygon(
int n, wxPoint points[], wxCoord xoffset,
1536 wxCoord yoffset,
float scale) {
1537#if wxUSE_GRAPHICS_CONTEXT
1539 wxGraphicsPath gpath = pgc->CreatePath();
1540 gpath.MoveToPoint(points[0].x *
scale + xoffset,
1541 points[0].y *
scale + yoffset);
1542 for (
int i = 1; i < n; i++)
1543 gpath.AddLineToPoint(points[i].x *
scale + xoffset,
1544 points[i].y *
scale + yoffset);
1545 gpath.AddLineToPoint(points[0].x *
scale + xoffset,
1546 points[0].y *
scale + yoffset);
1548 pgc->SetPen(GetPen());
1549 pgc->SetBrush(GetBrush());
1550 pgc->DrawPath(gpath);
1552 for (
int i = 0; i < n; i++)
1553 dc->CalcBoundingBox(points[i].x *
scale + xoffset,
1554 points[i].y *
scale + yoffset);
1557 DrawPolygon(n, points, xoffset, yoffset,
scale);
1560void ocpnDC::DrawBitmap(
const wxBitmap &bitmap, wxCoord x, wxCoord y,
1563 if (x < 0 || y < 0) {
1564 int dx = (x < 0 ? -x : 0);
1565 int dy = (y < 0 ? -y : 0);
1566 int w = bitmap.GetWidth() - dx;
1567 int h = bitmap.GetHeight() - dy;
1569 if (w <= 0 || h <= 0)
return;
1570 wxBitmap newBitmap = bitmap.GetSubBitmap(wxRect(dx, dy, w, h));
1577 if (dc) dc->DrawBitmap(bmp, x, y, usemask);
1585#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1586 wxImage image = bmp.ConvertToImage();
1587 int w = image.GetWidth(), h = image.GetHeight();
1590 unsigned char *d = image.GetData();
1591 unsigned char *a = image.GetAlpha();
1594 if (image.HasMask()) a = 0;
1596 unsigned char mr, mg, mb;
1597 if (!a && !image.GetOrFindMaskColour(&mr, &mg, &mb)) {
1598 printf(
"trying to use mask to draw a bitmap without alpha or mask\n");
1601 unsigned char *e =
new unsigned char[4 * w * h];
1603 for (
int y = 0; y < h; y++)
1604 for (
int x = 0; x < w; x++) {
1605 unsigned char r, g, b;
1606 int off = (y * w + x);
1616 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1622 glColor4f(1, 1, 1, 1);
1623 GLDrawBlendData(x, y, w, h, GL_RGBA, e);
1626 glRasterPos2i(x, y);
1628 if (image.GetData())
1629 glDrawPixels(w, h, GL_RGB, GL_UNSIGNED_BYTE, image.GetData());
1637void ocpnDC::DrawText(
const wxString &text, wxCoord x, wxCoord y,
float angle) {
1638 if (dc) dc->DrawText(text, x, y);
1646 m_texfont.Build(m_font, 1.0,
1648 m_texfont.GetTextExtent(text, &w, &h);
1649 m_texfont.SetColor(m_textforegroundcolour);
1653 glEnable(GL_TEXTURE_2D);
1654 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1656 m_texfont.RenderString(text, x, y, angle);
1658 glDisable(GL_TEXTURE_2D);
1659 glDisable(GL_BLEND);
1663 sdc.SetFont(m_font);
1664 sdc.GetTextExtent(text, &w, &h, NULL, NULL, &m_font);
1669 temp_dc.SelectObject(bmp);
1672 temp_dc.SetBackground(wxBrush(wxColour(0, 0, 0)));
1676 temp_dc.SetFont(m_font);
1677 temp_dc.SetTextForeground(wxColour(255, 255, 255));
1678 temp_dc.DrawText(text, 0, 0);
1679 temp_dc.SelectObject(wxNullBitmap);
1683 wxImage image = bmp.ConvertToImage();
1686 int dx = (x < 0 ? -x : 0);
1687 int dy = (y < 0 ? -y : 0);
1688 w = bmp.GetWidth() - dx;
1689 h = bmp.GetHeight() - dy;
1691 if (w <= 0 || h <= 0)
return;
1692 image = image.GetSubImage(wxRect(dx, dy, w, h));
1697 unsigned char *data =
new unsigned char[w * h * 4];
1698 unsigned char *im = image.GetData();
1701 unsigned int r = m_textforegroundcolour.Red();
1702 unsigned int g = m_textforegroundcolour.Green();
1703 unsigned int b = m_textforegroundcolour.Blue();
1704 for (
int i = 0; i < h; i++) {
1705 for (
int j = 0; j < w; j++) {
1706 unsigned int index = ((i * w) + j) * 4;
1708 data[index + 1] = g;
1709 data[index + 2] = b;
1710 data[index + 3] = im[((i * w) + j) * 3];
1715 unsigned int texobj;
1717 glGenTextures(1, &texobj);
1718 glBindTexture(GL_TEXTURE_2D, texobj);
1720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1721 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1723 int TextureWidth = NextPow2(w);
1724 int TextureHeight = NextPow2(h);
1725 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWidth, TextureHeight, 0,
1726 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1727 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE,
1730 glEnable(GL_TEXTURE_2D);
1732 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1734 float u = (float)w / TextureWidth, v = (
float)h / TextureHeight;
1761 if (m_glchartCanvas) {
1762 shader = ptexture_2D_shader_program[m_canvasIndex];
1769 shader = m_ptexture_2D_shader_program;
1771 shader->SetUniformMatrix4fv(
"MVMatrix",
1772 (
float *)&(m_vp.vp_matrix_transform));
1776 shader->SetUniform1i(
"uTex", 0);
1781 mat4x4_rotate_Z(Q, I, 0);
1787 shader->SetUniformMatrix4fv(
"TransformMatrix", (GLfloat *)Q);
1814 shader->SetAttributePointerf(
"aPos", co1);
1815 shader->SetAttributePointerf(
"aUV", tco1);
1817 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1821 glDisable(GL_BLEND);
1822 glDisable(GL_TEXTURE_2D);
1824 glDeleteTextures(1, &texobj);
1832void ocpnDC::GetTextExtent(
const wxString &
string, wxCoord *w, wxCoord *h,
1833 wxCoord *descent, wxCoord *externalLeading,
1840 dc->GetTextExtent(
string, w, h, descent, externalLeading, font);
1843 if (font) f = *font;
1848 m_texfont.Build(f, 1.0, m_dpi_factor);
1849 m_texfont.GetTextExtent(
string, w, h);
1852 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1856 temp_dc.GetTextExtent(
string, w, h, descent, externalLeading, &f);
1862 if (w && (*w > 500)) *w = 500;
1863 if (h && (*h > 500)) *h = 500;
1866void ocpnDC::ResetBoundingBox() {
1867 if (dc) dc->ResetBoundingBox();
1870void ocpnDC::CalcBoundingBox(wxCoord x, wxCoord y) {
1871 if (dc) dc->CalcBoundingBox(x, y);
1874bool ocpnDC::ConfigurePen() {
1875 if (!m_pen.IsOk())
return false;
1876 if (m_pen == *wxTRANSPARENT_PEN)
return false;
1878 wxColour c = m_pen.GetColour();
1879 int width = m_pen.GetWidth();
1881#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1882 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1884 glLineWidth(wxMax(g_GLMinSymbolLineWidth, width));
1889bool ocpnDC::ConfigureBrush() {
1890 if (m_brush == wxNullBrush || m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT)
1893 wxColour c = m_brush.GetColour();
1894#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1895 glColor4ub(c.Red(), c.Green(), c.Blue(), c.Alpha());
1901void ocpnDC::GLDrawBlendData(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
1902 int format,
const unsigned char *data) {
1904#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
1906 glRasterPos2i(x, y);
1908 glDrawPixels(w, h, format, GL_UNSIGNED_BYTE, data);
1910 glDisable(GL_BLEND);
1919 if (!m_glchartCanvas && !m_glcanvas)
return;
1922 m_vp.SetVPTransformMatrix();
1930 if (m_pcolor_tri_shader_program) {
1931 m_pcolor_tri_shader_program->Bind();
1932 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
1933 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1934 m_pcolor_tri_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1936 m_pcolor_tri_shader_program->UnBind();
1938 if (m_pAALine_shader_program) {
1939 m_pAALine_shader_program->Bind();
1940 m_pAALine_shader_program->SetUniformMatrix4fv(
1941 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1942 m_pAALine_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1944 m_pAALine_shader_program->UnBind();
1947 if (m_pcircle_filled_shader_program) {
1948 m_pcircle_filled_shader_program->Bind();
1949 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
1950 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1951 m_pcircle_filled_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1953 m_pcircle_filled_shader_program->UnBind();
1956 if (m_ptexture_2D_shader_program) {
1957 m_ptexture_2D_shader_program->Bind();
1958 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
1959 "MVMatrix", (GLfloat *)m_vp.vp_matrix_transform);
1960 m_ptexture_2D_shader_program->SetUniformMatrix4fv(
"TransformMatrix",
1962 m_ptexture_2D_shader_program->UnBind();
1970#ifdef USE_ANDROID_GLES2
1971const GLchar *odc_preamble =
"\n";
1973const GLchar *odc_preamble =
1975 "#define precision\n"
1983static const GLchar *odc_color_tri_vertex_shader_source =
1984 "attribute vec2 position;\n"
1985 "uniform mat4 MVMatrix;\n"
1986 "uniform mat4 TransformMatrix;\n"
1987 "uniform vec4 color;\n"
1988 "varying vec4 fragColor;\n"
1990 " fragColor = color;\n"
1991 " gl_Position = MVMatrix * TransformMatrix * vec4(position, 0.0, 1.0);\n"
1994static const GLchar *odc_color_tri_fragment_shader_source =
1995 "precision lowp float;\n"
1996 "varying vec4 fragColor;\n"
1998 " gl_FragColor = fragColor;\n"
2001static const GLchar *odc_AALine_vertex_shader_source =
2002 "uniform vec2 uViewPort; //Width and Height of the viewport\n"
2003 "varying vec2 vLineCenter;\n"
2004 "attribute vec2 position;\n"
2005 "uniform mat4 MVMatrix;\n"
2006 "uniform mat4 TransformMatrix;\n"
2009 " vec4 pp = MVMatrix * vec4(position, 0.0, 1.0);\n"
2010 " gl_Position = pp;\n"
2011 " vec2 vp = uViewPort;\n"
2012 " vLineCenter = 0.5*(pp.xy + vec2(1, 1))*vp;\n"
2015static const GLchar *odc_AALine_fragment_shader_source =
2016 "precision mediump float;\n"
2017 "uniform float uLineWidth;\n"
2018 "uniform vec4 color;\n"
2019 "uniform float uBlendFactor; //1.5..2.5\n"
2020 "varying vec2 vLineCenter;\n"
2023 " vec4 col = color;\n"
2024 " float d = length(vLineCenter-gl_FragCoord.xy);\n"
2025 " float w = uLineWidth;\n"
2029 " if(float((w/2-d)/(w/2)) < .5){\n"
2030 " //col.w *= pow(float((w-d)/w), uBlendFactor);\n"
2031 " col.w *= pow(float((w/2-d)/(w/2)), uBlendFactor);\n"
2034 " gl_FragColor = col;\n"
2038static const GLchar *odc_circle_filled_vertex_shader_source =
2039 "precision highp float;\n"
2040 "attribute vec2 aPos;\n"
2041 "uniform mat4 MVMatrix;\n"
2042 "uniform mat4 TransformMatrix;\n"
2044 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2047static const GLchar *odc_circle_filled_fragment_shader_source =
2048 "precision highp float;\n"
2049 "uniform float border_width;\n"
2050 "uniform float circle_radius;\n"
2051 "uniform vec4 circle_color;\n"
2052 "uniform vec4 border_color;\n"
2053 "uniform vec2 circle_center;\n"
2055 "float d = distance(gl_FragCoord.xy, circle_center);\n"
2056 "if (d < (circle_radius - border_width)) { gl_FragColor = circle_color; }\n"
2057 "else if (d < circle_radius) { gl_FragColor = border_color; }\n"
2058 "else { gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); }\n"
2062static const GLchar *odc_texture_2D_vertex_shader_source =
2063 "attribute vec2 aPos;\n"
2064 "attribute vec2 aUV;\n"
2065 "uniform mat4 MVMatrix;\n"
2066 "uniform mat4 TransformMatrix;\n"
2067 "varying vec2 varCoord;\n"
2069 " gl_Position = MVMatrix * TransformMatrix * vec4(aPos, 0.0, 1.0);\n"
2070 " varCoord = aUV;\n"
2073static const GLchar *odc_texture_2D_fragment_shader_source =
2074 "precision lowp float;\n"
2075 "uniform sampler2D uTex;\n"
2076 "varying vec2 varCoord;\n"
2078 " gl_FragColor = texture2D(uTex, varCoord);\n"
2082void ocpnDC::BuildShaders() {
2084 if (!m_pcolor_tri_shader_program) {
2086 shaderProgram->addShaderFromSource(odc_color_tri_vertex_shader_source,
2088 shaderProgram->addShaderFromSource(odc_color_tri_fragment_shader_source,
2089 GL_FRAGMENT_SHADER);
2090 shaderProgram->linkProgram();
2092 if (shaderProgram->isOK()) m_pcolor_tri_shader_program = shaderProgram;
2095 if (!m_pAALine_shader_program) {
2097 shaderProgram->addShaderFromSource(odc_AALine_fragment_shader_source,
2098 GL_FRAGMENT_SHADER);
2099 shaderProgram->addShaderFromSource(odc_AALine_vertex_shader_source,
2101 shaderProgram->linkProgram();
2103 if (shaderProgram->isOK()) m_pAALine_shader_program = shaderProgram;
2106 if (!m_pcircle_filled_shader_program) {
2108 shaderProgram->addShaderFromSource(odc_circle_filled_vertex_shader_source,
2110 shaderProgram->addShaderFromSource(odc_circle_filled_fragment_shader_source,
2111 GL_FRAGMENT_SHADER);
2112 shaderProgram->linkProgram();
2114 if (shaderProgram->isOK()) m_pcircle_filled_shader_program = shaderProgram;
2117 if (!m_ptexture_2D_shader_program) {
2119 shaderProgram->addShaderFromSource(odc_texture_2D_vertex_shader_source,
2121 shaderProgram->addShaderFromSource(odc_texture_2D_fragment_shader_source,
2122 GL_FRAGMENT_SHADER);
2123 shaderProgram->linkProgram();
2125 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.