40#include "ocpn_frame.h"
50#include <wx/graphics.h>
51#include <wx/dcclient.h>
56#include "model/cutil.h"
57#include "model/config_vars.h"
60#include "glChartCanvas.h"
64wxArrayPtrVoid gTesselatorVertices;
66#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
67extern GLint color_tri_shader_program;
68extern GLint circle_filled_shader_program;
69extern GLint texture_2D_shader_program;
76#define PI 3.1415926535897931160E0
81 : m_glchartCanvas(&canvas),
85 m_brush(wxNullBrush) {
86#if wxUSE_GRAPHICS_CONTEXT
91 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
95ocpnDC::ocpnDC(wxGLCanvas &canvas)
96 : m_glchartCanvas(NULL),
100 m_brush(wxNullBrush) {
101#if wxUSE_GRAPHICS_CONTEXT
107ocpnDC::ocpnDC(wxDC &pdc)
108 : m_glchartCanvas(NULL),
112 m_brush(wxNullBrush) {
113#if wxUSE_GRAPHICS_CONTEXT
115 auto pmdc =
dynamic_cast<wxMemoryDC *
>(dc);
117 pgc = wxGraphicsContext::Create(*pmdc);
119 auto pcdc =
dynamic_cast<wxClientDC *
>(dc);
120 if (pcdc) pgc = wxGraphicsContext::Create(*pcdc);
128 : m_glchartCanvas(NULL),
132 m_brush(wxNullBrush) {
133#if wxUSE_GRAPHICS_CONTEXT
140#if wxUSE_GRAPHICS_CONTEXT
146 free(s_odc_tess_work_buf);
148 delete m_pcolor_tri_shader_program;
149 delete m_pAALine_shader_program;
150 delete m_pcircle_filled_shader_program;
151 delete m_ptexture_2D_shader_program;
156 m_buseTex = GetLocaleCanonicalName().IsSameAs(_T(
"en_US"));
161 m_textforegroundcolour = wxColour(0, 0, 0);
163 s_odc_tess_work_buf = NULL;
166#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
167 s_odc_tess_vertex_idx = 0;
168 s_odc_tess_vertex_idx_this = 0;
169 s_odc_tess_buf_len = 0;
171 s_odc_tess_work_buf = (GLfloat *)malloc(100 *
sizeof(GLfloat));
172 s_odc_tess_buf_len = 100;
174 m_pcolor_tri_shader_program = NULL;
175 m_pAALine_shader_program = NULL;
176 m_pcircle_filled_shader_program = NULL;
177 m_ptexture_2D_shader_program = NULL;
182 m_glchartCanvas = canvas;
183 m_canvasIndex = m_glchartCanvas->GetCanvasIndex();
187void ocpnDC::Clear() {
192 wxBrush tmpBrush = m_brush;
194 if (m_glchartCanvas) {
195 SetBrush(wxBrush(m_glchartCanvas->GetBackgroundColour()));
196 m_glchartCanvas->GetSize(&w, &h);
197 }
else if (m_glcanvas) {
198 SetBrush(wxBrush(m_glcanvas->GetBackgroundColour()));
199 m_glcanvas->GetSize(&w, &h);
203 DrawRectangle(0, 0, w, h);
209void ocpnDC::SetBackground(
const wxBrush &brush) {
211 dc->SetBackground(brush);
215 m_glchartCanvas->SetBackgroundColour(brush.GetColour());
217 m_glcanvas->SetBackgroundColour(brush.GetColour());
224void ocpnDC::SetPen(
const wxPen &pen) {
226 if (pen == wxNullPen)
227 dc->SetPen(*wxTRANSPARENT_PEN);
234void ocpnDC::SetBrush(
const wxBrush &brush) {
241void ocpnDC::SetTextForeground(
const wxColour &colour) {
243 dc->SetTextForeground(colour);
245 m_textforegroundcolour = colour;
248void ocpnDC::SetFont(
const wxFont &font) {
255const wxPen &ocpnDC::GetPen()
const {
256 if (dc)
return dc->GetPen();
260const wxBrush &ocpnDC::GetBrush()
const {
261 if (dc)
return dc->GetBrush();
265const wxFont &ocpnDC::GetFont()
const {
266 if (dc)
return dc->GetFont();
270void ocpnDC::GetSize(wxCoord *width, wxCoord *height)
const {
272 dc->GetSize(width, height);
275 if (m_glchartCanvas) {
276 *width = m_glchartCanvas->GetGLCanvasWidth();
277 *height = m_glchartCanvas->GetGLCanvasHeight();
278 }
else if (m_glcanvas) {
279 m_glcanvas->GetSize(width, height);
285void ocpnDC::SetGLAttrs(
bool highQuality) {
290 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
291 if (g_GLOptions.m_GLPolygonSmoothing) glEnable(GL_POLYGON_SMOOTH);
292 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
295 glDisable(GL_LINE_SMOOTH);
296 glDisable(GL_POLYGON_SMOOTH);
302void ocpnDC::SetGLStipple()
const {
305#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
306 switch (m_pen.GetStyle()) {
307 case wxPENSTYLE_DOT: {
308 glLineStipple(1, 0x3333);
309 glEnable(GL_LINE_STIPPLE);
312 case wxPENSTYLE_LONG_DASH: {
313 glLineStipple(1, 0xFFF8);
314 glEnable(GL_LINE_STIPPLE);
317 case wxPENSTYLE_SHORT_DASH: {
318 glLineStipple(1, 0x3F3F);
319 glEnable(GL_LINE_STIPPLE);
322 case wxPENSTYLE_DOT_DASH: {
323 glLineStipple(1, 0x8FF1);
324 glEnable(GL_LINE_STIPPLE);
336void DrawEndCap(
float x1,
float y1,
float t1,
float angle) {
337#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
338 const int steps = 16;
341 for (
int i = 0; i <= steps; i++) {
342 float a = angle + M_PI / 2 + M_PI / steps * i;
344 float xb = x1 + t1 / 2 * cos(a);
345 float yb = y1 + t1 / 2 * sin(a);
360void ocpnDC::DrawGLThickLine(
float x1,
float y1,
float x2,
float y2, wxPen pen,
364 float angle = atan2f(y2 - y1, x2 - x1);
365 float t1 = pen.GetWidth();
366 float t2sina1 = t1 / 2 * sinf(angle);
367 float t2cosa1 = t1 / 2 * cosf(angle);
371 if (m_glchartCanvas) {
372 shader = pcolor_tri_shader_program[m_canvasIndex];
378 shader = m_pcolor_tri_shader_program;
380 shader->SetUniformMatrix4fv(
"MVMatrix",
381 (
float *)&(m_vp.vp_matrix_transform));
384 wxColor c = pen.GetColour();
386 colorv[0] = c.Red() / float(256);
387 colorv[1] = c.Green() / float(256);
388 colorv[2] = c.Blue() / float(256);
389 colorv[3] = c.Alpha() / float(256);
390 shader->SetUniform4fv(
"color", colorv);
393 shader->SetAttributePointerf(
"position", vert);
398 int n_dashes = pen.GetDashes(&dashes);
400 float lpix = sqrtf(powf((
float)(x1 - x2), 2) + powf((
float)(y1 - y2), 2));
404 float ldraw = t1 * dashes[0];
405 float lspace = t1 * dashes[1];
407 while (lrun < lpix) {
409 float xb = xa + ldraw * cosf(angle);
410 float yb = ya + ldraw * sinf(angle);
412 if ((lrun + ldraw) >= lpix)
418 vert[0] = xa + t2sina1;
419 vert[1] = ya - t2cosa1;
420 vert[2] = xb + t2sina1;
421 vert[3] = yb - t2cosa1;
422 vert[4] = xb - t2sina1;
423 vert[5] = yb + t2cosa1;
424 vert[6] = xb - t2sina1;
425 vert[7] = yb + t2cosa1;
426 vert[8] = xa - t2sina1;
427 vert[9] = ya + t2cosa1;
428 vert[10] = xa + t2sina1;
429 vert[11] = ya - t2cosa1;
431 glDrawArrays(GL_TRIANGLES, 0, 6);
438 xb = xa + lspace * cos(angle);
439 yb = ya + lspace * sin(angle);
447 vert[0] = x1 + t2sina1;
448 vert[1] = y1 - t2cosa1;
449 vert[2] = x2 + t2sina1;
450 vert[3] = y2 - t2cosa1;
451 vert[4] = x2 - t2sina1;
452 vert[5] = y2 + t2cosa1;
453 vert[6] = x2 - t2sina1;
454 vert[7] = y2 + t2cosa1;
455 vert[8] = x1 - t2sina1;
456 vert[9] = y1 + t2cosa1;
457 vert[10] = x1 + t2sina1;
458 vert[11] = y1 - t2cosa1;
460 glDrawArrays(GL_TRIANGLES, 0, 6);
478 if (dc) dc->DrawLine(x1, y1, x2, y2);
480 else if (ConfigurePen()) {
481 bool b_draw_thick =
false;
483 float pen_width = wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth());
491 if (g_GLOptions.m_GLLineSmoothing) glEnable(GL_LINE_SMOOTH);
494 if (pen_width > 1.0) {
496 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
497 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
498 if (pen_width > parms[1])
501 glLineWidth(pen_width);
503 glLineWidth(pen_width);
507 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
508 if (pen_width > parms[1])
511 glLineWidth(pen_width);
513 glLineWidth(pen_width);
516#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
518 DrawGLThickLine(x1, y1, x2, y2, m_pen, b_hiqual);
526 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
531 GetSize(&width, &height);
535 shader->SetUniform2fv(
"uViewPort", vpx);
538 colorv[0] = m_pen.GetColour().Red() / float(256);
539 colorv[1] = m_pen.GetColour().Green() / float(256);
540 colorv[2] = m_pen.GetColour().Blue() / float(256);
543 shader->SetUniform4fv(
"color", colorv);
546 shader->SetAttributePointerf(
"position", fBuf);
550 int n_dashes = m_pen.GetDashes(&dashes);
552 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
553 float cosa = cosf(angle);
554 float sina = sinf(angle);
555 float t1 = m_pen.GetWidth();
557 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
561 float ldraw = t1 * dashes[0];
562 float lspace = t1 * dashes[1];
564 ldraw = wxMax(ldraw, 4.0);
565 lspace = wxMax(lspace, 4.0);
566 lpix = wxMin(lpix, 2000.0);
568 while (lrun < lpix) {
570 float xb = xa + ldraw * cosa;
571 float yb = ya + ldraw * sina;
573 if ((lrun + ldraw) >= lpix)
584 glDrawArrays(GL_LINES, 0, 2);
586 xa = xa + (lspace + ldraw) * cosa;
587 ya = ya + (lspace + ldraw) * sina;
588 lrun += lspace + ldraw;
597 glDrawArrays(GL_LINES, 0, 2);
603 if (m_glchartCanvas) {
604 shader = pcolor_tri_shader_program[m_canvasIndex];
611 shader = m_pcolor_tri_shader_program;
613 shader->SetUniformMatrix4fv(
"MVMatrix",
614 (
float *)&(m_vp.vp_matrix_transform));
618 colorv[0] = m_pen.GetColour().Red() / float(256);
619 colorv[1] = m_pen.GetColour().Green() / float(256);
620 colorv[2] = m_pen.GetColour().Blue() / float(256);
623 shader->SetUniform4fv(
"color", colorv);
625 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
628 shader->SetAttributePointerf(
"position", fBuf);
631 int n_dashes = m_pen.GetDashes(&dashes);
633 float angle = atan2f((
float)(y2 - y1), (
float)(x2 - x1));
634 float cosa = cosf(angle);
635 float sina = sinf(angle);
636 float t1 = m_pen.GetWidth();
638 float lpix = sqrtf(powf(x1 - x2, 2) + powf(y1 - y2, 2));
642 float ldraw = t1 * dashes[0];
643 float lspace = t1 * dashes[1];
645 ldraw = wxMax(ldraw, 4.0);
646 lspace = wxMax(lspace, 4.0);
649 while (lrun < lpix) {
651 float xb = xa + ldraw * cosa;
652 float yb = ya + ldraw * sina;
654 if ((lrun + ldraw) >= lpix)
665 glDrawArrays(GL_LINES, 0, 2);
667 xa = xa + (lspace + ldraw) * cosa;
668 ya = ya + (lspace + ldraw) * sina;
669 lrun += lspace + ldraw;
678 glDrawArrays(GL_LINES, 0, 2);
687 glDisable(GL_LINE_STIPPLE);
690 glDisable(GL_LINE_SMOOTH);
698void ocpnDC::DrawGLThickLines(
int n, wxPoint points[], wxCoord xoffset,
699 wxCoord yoffset, wxPen pen,
bool b_hiqual) {
703 wxPoint p0 = points[0];
704 for (
int i = 1; i < n; i++) {
705 DrawGLThickLine(p0.x + xoffset, p0.y + yoffset, points[i].x + xoffset,
706 points[i].y + yoffset, pen, b_hiqual);
713void ocpnDC::DrawLines(
int n, wxPoint points[], wxCoord xoffset,
714 wxCoord yoffset,
bool b_hiqual) {
715 if (dc) dc->DrawLines(n, points, xoffset, yoffset);
717 else if (ConfigurePen()) {
722 SetGLAttrs(b_hiqual);
724 bool b_draw_thick =
false;
726 glDisable(GL_LINE_STIPPLE);
732 if (m_pen.GetWidth() > 1) {
734 glGetIntegerv(GL_SMOOTH_LINE_WIDTH_RANGE, &parms[0]);
735 if (glGetError()) glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
737 if (m_pen.GetWidth() > parms[1])
740 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
742 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
744 if (m_pen.GetWidth() > 1) {
746 glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, &parms[0]);
747 if (m_pen.GetWidth() > parms[1])
750 glLineWidth(wxMax(g_GLMinSymbolLineWidth, m_pen.GetWidth()));
752 glLineWidth(wxMax(g_GLMinSymbolLineWidth, 1));
755 if (b_draw_thick || m_pen.GetStyle() != wxPENSTYLE_SOLID) {
756 DrawGLThickLines(n, points, xoffset, yoffset, m_pen, b_hiqual);
759 glDisable(GL_LINE_STIPPLE);
760 glDisable(GL_LINE_SMOOTH);
761 glDisable(GL_POLYGON_SMOOTH);
769 if (workBufSize < (
size_t)n * 2) {
770 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
774 for (
int i = 0; i < n; i++) {
775 workBuf[i * 2] = points[i].x + xoffset;
776 workBuf[(i * 2) + 1] = points[i].y + yoffset;
789 GetSize(&width, &height);
793 shader->SetUniform2fv(
"uViewPort", vpx);
796 colorv[0] = m_pen.GetColour().Red() / float(256);
797 colorv[1] = m_pen.GetColour().Green() / float(256);
798 colorv[2] = m_pen.GetColour().Blue() / float(256);
801 shader->SetUniform4fv(
"color", colorv);
803 shader->SetAttributePointerf(
"position", workBuf);
805 glDrawArrays(GL_LINE_STRIP, 0, n);
810 if (m_glchartCanvas) {
811 shader = pcolor_tri_shader_program[m_canvasIndex];
818 shader = m_pcolor_tri_shader_program;
820 shader->SetUniformMatrix4fv(
"MVMatrix",
821 (
float *)&(m_vp.vp_matrix_transform));
825 colorv[0] = m_pen.GetColour().Red() / float(256);
826 colorv[1] = m_pen.GetColour().Green() / float(256);
827 colorv[2] = m_pen.GetColour().Blue() / float(256);
830 shader->SetUniform4fv(
"color", colorv);
832 shader->SetAttributePointerf(
"position", workBuf);
834 glDrawArrays(GL_LINE_STRIP, 0, n);
841 glDisable(GL_LINE_STIPPLE);
842 glDisable(GL_LINE_SMOOTH);
843 glDisable(GL_POLYGON_SMOOTH);
850void ocpnDC::StrokeLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) {
851#if wxUSE_GRAPHICS_CONTEXT
853 pgc->SetPen(GetPen());
854 pgc->StrokeLine(x1, y1, x2, y2);
856 dc->CalcBoundingBox(x1, y1);
857 dc->CalcBoundingBox(x2, y2);
863void ocpnDC::StrokeLines(
int n, wxPoint *points) {
867#if wxUSE_GRAPHICS_CONTEXT
869 wxPoint2DDouble *dPoints =
870 (wxPoint2DDouble *)malloc(n *
sizeof(wxPoint2DDouble));
871 for (
int i = 0; i < n; i++) {
872 dPoints[i].m_x = points[i].x;
873 dPoints[i].m_y = points[i].y;
875 pgc->SetPen(GetPen());
876 pgc->StrokeLines(n, dPoints);
880 DrawLines(n, points, 0, 0,
true);
883void ocpnDC::DrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
884 if (dc) dc->DrawRectangle(x, y, w, h);
887 DrawRoundedRectangle(x, y, w, h, 0);
893static void drawrrhelper(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
896#if !defined(USE_ANDROID_GLES2) && !defined(ocpnUSE_GLSL)
897 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
901 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
904 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
907 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
910 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
916 for (
int i = 0; i < steps; i++) {
917 glVertex2i(x0 + floor(x), y0 + floor(y));
918 x += dx + ddx / 2, y += dy + ddy / 2;
919 dx += ddx, dy += ddy;
921 glVertex2i(x0 + floor(x), y0 + floor(y));
926void ocpnDC::drawrrhelperGLES2(wxCoord x0, wxCoord y0, wxCoord r,
int quadrant,
929 if (steps == 0)
return;
931 float step = 1.0 / steps, rs = 2.0 * r * step, rss = rs * step, x, y, dx, dy,
935 x = r, y = 0, dx = 0, dy = -rs, ddx = -rss, ddy = rss;
938 x = 0, y = -r, dx = -rs, dy = 0, ddx = rss, ddy = rss;
941 x = -r, y = 0, dx = 0, dy = rs, ddx = rss, ddy = -rss;
944 x = 0, y = r, dx = rs, dy = 0, ddx = -rss, ddy = -rss;
950 for (
int i = 0; i < steps; i++) {
951 workBuf[workBufIndex++] = x0 + floor(x);
952 workBuf[workBufIndex++] = y0 + floor(y);
954 x += dx + ddx / 2, y += dy + ddy / 2;
955 dx += ddx, dy += ddy;
958 workBuf[workBufIndex++] = x0 + floor(x);
959 workBuf[workBufIndex++] = y0 + floor(y);
963void ocpnDC::DrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
965 if (dc) dc->DrawRoundedRectangle(x, y, w, h, r);
968 if (!m_glchartCanvas)
return;
971 int steps = ceil(sqrt((
float)r));
973 wxCoord x1 = x + r, x2 = x + w - r;
974 wxCoord y1 = y + r, y2 = y + h - r;
980 size_t bufReq = (steps + 1) * 8 * 2;
982 if (workBufSize < bufReq) {
983 workBuf = (
float *)realloc(workBuf, bufReq *
sizeof(
float));
984 workBufSize = bufReq;
989 drawrrhelperGLES2(x2, y1, r, 0, steps);
990 drawrrhelperGLES2(x1, y1, r, 1, steps);
991 drawrrhelperGLES2(x1, y2, r, 2, steps);
992 drawrrhelperGLES2(x2, y2, r, 3, steps);
999 fcolorv[0] = m_brush.GetColour().Red() / float(256);
1000 fcolorv[1] = m_brush.GetColour().Green() / float(256);
1001 fcolorv[2] = m_brush.GetColour().Blue() / float(256);
1002 fcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1003 shader->SetUniform4fv(
"color", fcolorv);
1012 mat4x4_rotate_Z(Q, I, angle);
1020 (
float(*)[4])m_glchartCanvas->m_pParentCanvas->GetpVP()
1021 ->vp_matrix_transform,
1023 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1025 shader->SetAttributePointerf(
"position", workBuf);
1028 glDrawArrays(GL_TRIANGLE_FAN, 0, workBufIndex / 2);
1032 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1033 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1034 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1035 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1037 shader->SetUniform4fv(
"color", bcolorv);
1040 glDrawArrays(GL_LINE_LOOP, 0, workBufIndex / 2);
1047void ocpnDC::DrawCircle(wxCoord x, wxCoord y, wxCoord radius) {
1049 dc->DrawCircle(x, y, radius);
1057 coords[0] = x - radius;
1058 coords[1] = y + radius;
1059 coords[2] = x + radius;
1060 coords[3] = y + radius;
1061 coords[4] = x - radius;
1062 coords[5] = y - radius;
1063 coords[6] = x + radius;
1064 coords[7] = y - radius;
1067 if (m_glchartCanvas) {
1068 shader = pcircle_filled_shader_program[m_canvasIndex];
1074 shader = m_pcircle_filled_shader_program;
1076 shader->SetUniformMatrix4fv(
"MVMatrix",
1077 (
float *)&(m_vp.vp_matrix_transform));
1083 shader->SetUniform1f(
"circle_radius", radius);
1089 GetSize(&width, &height);
1090 ctrv[1] = height - y;
1091 shader->SetUniform2fv(
"circle_center", ctrv);
1095 if (m_brush.IsOk()) {
1096 colorv[0] = m_brush.GetColour().Red() / float(256);
1097 colorv[1] = m_brush.GetColour().Green() / float(256);
1098 colorv[2] = m_brush.GetColour().Blue() / float(256);
1099 colorv[3] = (m_brush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT) ? 0.0 : 1.0;
1101 shader->SetUniform4fv(
"circle_color", colorv);
1106 bcolorv[0] = m_pen.GetColour().Red() / float(256);
1107 bcolorv[1] = m_pen.GetColour().Green() / float(256);
1108 bcolorv[2] = m_pen.GetColour().Blue() / float(256);
1109 bcolorv[3] = m_pen.GetColour().Alpha() / float(256);
1111 shader->SetUniform4fv(
"border_color", bcolorv);
1115 shader->SetUniform1f(
"border_width", m_pen.GetWidth());
1117 shader->SetUniform1f(
"border_width", 2);
1119 shader->SetAttributePointerf(
"aPos", coords);
1122 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1128void ocpnDC::StrokeCircle(wxCoord x, wxCoord y, wxCoord radius) {
1129#if wxUSE_GRAPHICS_CONTEXT
1131 wxGraphicsPath gpath = pgc->CreatePath();
1132 gpath.AddCircle(x, y, radius);
1134 pgc->SetPen(GetPen());
1135 pgc->SetBrush(GetBrush());
1136 pgc->DrawPath(gpath);
1139 dc->CalcBoundingBox(x + radius + 2, y + radius + 2);
1140 dc->CalcBoundingBox(x - radius - 2, y - radius - 2);
1143 DrawCircle(x, y, radius);
1146void ocpnDC::DrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord height) {
1147 if (dc) dc->DrawEllipse(x, y, width, height);
1150 float r1 = width / 2, r2 = height / 2;
1151 float cx = x + r1, cy = y + r2;
1157 float steps = floorf(
1158 wxMax(sqrtf(sqrtf((
float)(width * width + height * height))), 1) *
1162 glDisable(GL_BLEND);
1167void ocpnDC::DrawPolygon(
int n, wxPoint points[], wxCoord xoffset,
1168 wxCoord yoffset,
float scale,
float angle) {
1169 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1184 if (m_glchartCanvas) {
1185 line_shader = pAALine_shader_program[m_canvasIndex];
1186 mvmatrix = (
float *)&(
1187 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1189 line_shader = m_pAALine_shader_program;
1190 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1195 line_shader->Bind();
1197 line_shader->SetUniform1f(
"uLineWidth", m_pen.GetWidth());
1198 line_shader->SetUniform1f(
"uBlendFactor", 2.0);
1203 GetSize(&width, &height);
1207 line_shader->SetUniform2fv(
"uViewPort", vpx);
1210 colorv[0] = m_pen.GetColour().Red() / float(256);
1211 colorv[1] = m_pen.GetColour().Green() / float(256);
1212 colorv[2] = m_pen.GetColour().Blue() / float(256);
1215 line_shader->SetUniform4fv(
"color", colorv);
1222 mat4x4_rotate_Z(Q, I, angle);
1235 line_shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1237 line_shader->UnBind();
1241 if (ConfigureBrush())
1242 DrawPolygonTessellated(n, points, xoffset, yoffset);
1246 if (workBufSize < (
size_t)n * 2) {
1247 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1248 workBufSize = n * 4;
1251 for (
int i = 0; i < n; i++) {
1252 workBuf[i * 2] = (points[i].x *
scale);
1253 workBuf[i * 2 + 1] = (points[i].y *
scale);
1256 line_shader->Bind();
1257 line_shader->SetAttributePointerf(
"position", workBuf);
1260 glDrawArrays(GL_LINE_LOOP, 0, n);
1267 line_shader->UnBind();
1272 if (workBufSize < (
size_t)n * 2) {
1273 workBuf = (
float *)realloc(workBuf, (n * 4) *
sizeof(float));
1274 workBufSize = n * 4;
1277 for (
int i = 0; i < n; i++) {
1278 workBuf[i * 2] = (points[i].x *
scale);
1279 workBuf[i * 2 + 1] = (points[i].y *
scale);
1286 if (m_glchartCanvas) {
1287 shader = pcolor_tri_shader_program[m_canvasIndex];
1288 mvmatrix = (
float *)&(
1289 m_glchartCanvas->m_pParentCanvas->GetpVP()->vp_matrix_transform);
1291 shader = m_pcolor_tri_shader_program;
1292 mvmatrix = (
float *)&(m_vp.vp_matrix_transform);
1299 mat4x4_rotate_Z(Q, I, angle);
1305 mat4x4_mul(X, (
float(*)[4])mvmatrix, Q);
1306 shader->SetUniformMatrix4fv(
"MVMatrix", (GLfloat *)X);
1310 bcolorv[0] = m_brush.GetColour().Red() / float(256);
1311 bcolorv[1] = m_brush.GetColour().Green() / float(256);
1312 bcolorv[2] = m_brush.GetColour().Blue() / float(256);
1313 bcolorv[3] = m_brush.GetColour().Alpha() / float(256);
1314 shader->SetUniform4fv(
"color", bcolorv);
1316 shader->SetAttributePointerf(
"position", workBuf);
1321 float x1 = workBuf[4];
1322 float y1 = workBuf[5];
1323 workBuf[4] = workBuf[6];
1324 workBuf[5] = workBuf[7];
1328 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1329 }
else if (n == 3) {
1330 glDrawArrays(GL_TRIANGLES, 0, 3);
1334 if (m_glchartCanvas) {
1335 shader->SetUniformMatrix4fv(
1336 "MVMatrix", (GLfloat *)m_glchartCanvas->m_pParentCanvas->GetpVP()
1337 ->vp_matrix_transform);
1345 for (
int i = 0; i < n; i++) {
1346 workBuf[i * 2] = (points[i].x *
scale);
1347 workBuf[i * 2 + 1] = (points[i].y *
scale);
1350 line_shader->Bind();
1352 line_shader->SetAttributePointerf(
"position", workBuf);
1354 glDrawArrays(GL_LINE_LOOP, 0, n);
1361 line_shader->UnBind();
1387#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1389static std::list<double *> odc_combine_work_data;
1390static void odc_combineCallbackD(GLdouble coords[3], GLdouble *vertex_data[4],
1391 GLfloat weight[4], GLdouble **dataOut,
1399void odc_vertexCallbackD_GLSL(GLvoid *vertex,
void *data) {
1403 if (pDC->s_odc_tess_vertex_idx > pDC->s_odc_tess_buf_len - 8) {
1404 int new_buf_len = pDC->s_odc_tess_buf_len + 100;
1405 GLfloat *tmp = pDC->s_odc_tess_work_buf;
1407 pDC->s_odc_tess_work_buf = (GLfloat *)realloc(
1408 pDC->s_odc_tess_work_buf, new_buf_len *
sizeof(GLfloat));
1409 if (NULL == pDC->s_odc_tess_work_buf) {
1413 pDC->s_odc_tess_buf_len = new_buf_len;
1416 GLdouble *pointer = (GLdouble *)vertex;
1418 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[0];
1419 pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx++] = (float)pointer[1];
1421 pDC->s_odc_nvertex++;
1424void odc_beginCallbackD_GLSL(GLenum mode,
void *data) {
1426 pDC->s_odc_tess_vertex_idx_this = pDC->s_odc_tess_vertex_idx;
1427 pDC->s_odc_tess_mode = mode;
1428 pDC->s_odc_nvertex = 0;
1431void odc_endCallbackD_GLSL(
void *data) {
1435 GLShaderProgram *shader = pcolor_tri_shader_program[pDC->m_canvasIndex];
1439 wxColour c = pDC->GetBrush().GetColour();
1441 colorv[0] = c.Red() / float(256);
1442 colorv[1] = c.Green() / float(256);
1443 colorv[2] = c.Blue() / float(256);
1444 colorv[3] = c.Alpha() / float(256);
1445 shader->SetUniform4fv(
"color", colorv);
1447 float *bufPt = &(pDC->s_odc_tess_work_buf[pDC->s_odc_tess_vertex_idx_this]);
1448 shader->SetAttributePointerf(
"position", bufPt);
1450 glDrawArrays(pDC->s_odc_tess_mode, 0, pDC->s_odc_nvertex);
1460void ocpnDC::DrawPolygonTessellated(
int n, wxPoint points[], wxCoord xoffset,
1462 if (dc) dc->DrawPolygon(n, points, xoffset, yoffset);
1465 if (!m_glchartCanvas)
return;
1467#if !defined(ocpnUSE_GLES) || \
1468 defined(USE_ANDROID_GLES2)
1472 DrawPolygon(n, points, xoffset, yoffset);
1476#if defined(USE_ANDROID_GLES2) || defined(ocpnUSE_GLSL)
1477 m_tobj = gluNewTess();
1478 s_odc_tess_vertex_idx = 0;
1480 gluTessCallback(m_tobj, GLU_TESS_VERTEX_DATA,
1481 (_GLUfuncptr)&odc_vertexCallbackD_GLSL);
1482 gluTessCallback(m_tobj, GLU_TESS_BEGIN_DATA,
1483 (_GLUfuncptr)&odc_beginCallbackD_GLSL);
1484 gluTessCallback(m_tobj, GLU_TESS_END_DATA,
1485 (_GLUfuncptr)&odc_endCallbackD_GLSL);
1486 gluTessCallback(m_tobj, GLU_TESS_COMBINE_DATA,
1487 (_GLUfuncptr)&odc_combineCallbackD);
1490 gluTessNormal(m_tobj, 0, 0, 1);
1491 gluTessProperty(m_tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO);
1493 if (ConfigureBrush()) {
1494 gluTessBeginPolygon(m_tobj,
this);
1495 gluTessBeginContour(m_tobj);
1497 ViewPort *pvp = m_glchartCanvas->m_pParentCanvas
1500 for (
int i = 0; i < n; i++) {
1501 double *p =
new double[6];
1508 float xn = points[i].x - cx;
1509 float yn = points[i].y - cy;
1510 p[0] = xn * c - yn * s + cx;
1511 p[1] = xn * s + yn * c + cy;
1514 p[0] = points[i].x, p[1] = points[i].y, p[2] = 0;
1516 gluTessVertex(m_tobj, p, p);
1518 gluTessEndContour(m_tobj);
1519 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;
Wrapper class for OpenGL shader programs.
Represents the view port for chart display in OpenCPN.
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.
PlugIn Object Definition/API.