GLPainter

git-svn-id: svn://ultimatepp.org/upp/trunk@12423 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-10-26 23:32:09 +00:00
parent df6c72f77f
commit 469bd30ffc
10 changed files with 251 additions and 30 deletions

View file

@ -21,8 +21,11 @@ GLCode::GLCode(const char *vertex_shader, const char *pixel_shader)
while(!p.IsEof() && !p.Char('{'))
if(p.Id("attribute") || p.Id("in")) {
String id = readID();
if(id.GetCount())
if(id.GetCount()) {
DDUMP(ii);
DDUMP(id);
glBindAttribLocation(program, ii++, id);
}
}
else
p.SkipTerm();

View file

@ -11,6 +11,9 @@ void DrawGL::Init(Size sz, double alpha)
dd.alpha = alpha;
glEnable(GL_SCISSOR_TEST);
SyncScissor();
prev = Point(0, 0);
path_done = false;
}
DrawGL::~DrawGL()
@ -23,10 +26,19 @@ dword DrawGL::GetInfo() const
return DRAWTEXTLINES;
}
void DrawGL::Push()
{
auto& s = state.Add();
s.dash = clone(dash);
s.dash_start = clone(dash_start);
s.alpha = dd.alpha;
}
void DrawGL::BeginOp()
{
Cloff c = cloff.Top();
cloff.Add(c);
Push();
}
bool DrawGL::ClipOp(const Rect& r)
@ -36,6 +48,7 @@ bool DrawGL::ClipOp(const Rect& r)
c1.clip = c.clip & (r + c.offset);
c1.offset = c.offset;
SyncScissor();
Push();
return !c1.clip.IsEmpty();
}
@ -46,6 +59,7 @@ bool DrawGL::ClipoffOp(const Rect& r)
c1.clip = c.clip & (r + c.offset);
c1.offset = c.offset + (Pointf)r.TopLeft();
SyncScissor();
Push();
return !c1.clip.IsEmpty();
}
@ -54,6 +68,7 @@ bool DrawGL::IntersectClipOp(const Rect& r)
Cloff& c = cloff.Top();
c.clip = c.clip & (r + c.offset);
SyncScissor();
Push();
return !c.clip.IsEmpty();
}
@ -74,6 +89,7 @@ void DrawGL::OffsetOp(Point p)
Cloff& c1 = cloff.Add();
c1.clip = c.clip;
c1.offset = c.offset + (Pointf)p;
Push();
}
void DrawGL::EndOp()
@ -81,6 +97,13 @@ void DrawGL::EndOp()
ASSERT(cloff.GetCount());
if(cloff.GetCount())
cloff.Drop();
if(state.GetCount()) {
auto& s = state.Top();
dash = pick(s.dash);
dash_start = s.dash_start;
dd.alpha = s.alpha;
state.Drop();
}
SyncScissor();
}
@ -92,42 +115,42 @@ void DrawGL::SyncScissor()
glScissor(clip.left, view_size.cy - sz.cy - clip.top, sz.cx, sz.cy);
}
Pointf DrawGL::Offset(int x, int y)
Pointf DrawGL::Off(int x, int y)
{
Pointf o = cloff.Top().offset;
return Pointf(x + o.x, y + o.y);
}
Rectf DrawGL::Offset(int x, int y, int cx, int cy)
Rectf DrawGL::Off(int x, int y, int cx, int cy)
{
Point o = cloff.Top().offset;
return RectfC(x + o.x, y + o.y, cx, cy);
}
Rectf DrawGL::Offset(int x, int y, Size sz)
Rectf DrawGL::Off(int x, int y, Size sz)
{
return Offset(x, y, sz.cx, sz.cy);
return Off(x, y, sz.cx, sz.cy);
}
void DrawGL::SysDrawImageOp(int x, int y, const Image& img, Color color)
{
GLDrawImage(dd, Offset(x, y, img.GetSize()),
GLDrawImage(dd, Off(x, y, img.GetSize()),
IsNull(color) ? img : CachedSetColorKeepAlpha(img, color));
}
void DrawGL::SysDrawImageOp(int x, int y, const Image& img, const Rect& src, Color color)
{
GLDrawImage(dd, Offset(x, y, img.GetSize()), IsNull(color) ? img : CachedSetColorKeepAlpha(img, color),
GLDrawImage(dd, Off(x, y, img.GetSize()), IsNull(color) ? img : CachedSetColorKeepAlpha(img, color),
src);
}
void DrawGL::DrawRectOp(int x, int y, int cx, int cy, Color color)
{
Vector<Vector<Pointf>> polygon;
polygon.Add().Add(Offset(x, y));
polygon.Top().Add(Offset(x + cx, y));
polygon.Top().Add(Offset(x + cx, y + cy));
polygon.Top().Add(Offset(x, y + cy));
polygon.Add().Add(Off(x, y));
polygon.Top().Add(Off(x + cx, y));
polygon.Top().Add(Off(x + cx, y + cy));
polygon.Top().Add(Off(x, y + cy));
GLVertexData data;
GLPolygons(data, polygon);
@ -137,7 +160,7 @@ void DrawGL::DrawRectOp(int x, int y, int cx, int cy, Color color)
void DrawGL::DrawTextOp(int x, int y, int angle, const wchar *text, Font font, Color ink, int n, const int *dx)
{
GLDrawText(dd, Offset(x, y), angle * M_2PI / 3600, text, font, ink, n, dx);
GLDrawText(dd, Off(x, y), angle * M_2PI / 3600, text, font, ink, n, dx);
}
const Vector<double>& DrawGL::GetDash(int& width)
@ -180,8 +203,8 @@ void DrawGL::ApplyDash(Vector<Vector<Pointf>>& polyline, int& width)
void DrawGL::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
{
Vector<Vector<Pointf>> poly;
poly.Add().Add(Offset(x1, y1));
poly.Top().Add(Offset(x2, y2));
poly.Add().Add(Off(x1, y1));
poly.Top().Add(Off(x2, y2));
ApplyDash(poly, width);
@ -207,14 +230,14 @@ void DrawGL::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color
void DrawGL::DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor)
{
const Vector<double>& dash = GetDash(pen);
GLDrawEllipse(dd, Offset(r.CenterPoint()), Sizef(r.GetSize()) / 2, color, pen, pencolor, dash, 0);
GLDrawEllipse(dd, Off(r.CenterPoint()), Sizef(r.GetSize()) / 2, color, pen, pencolor, dash, 0);
}
void DrawGL::DoPath(Vector<Vector<Pointf>>& poly, const Point *pp, const Point *end)
{
poly.Add().Add(Offset(*pp++));
poly.Add().Add(Off(*pp++));
while(pp < end)
poly.Top().Add(Offset(*pp++));
poly.Top().Add(Off(*pp++));
}
void DrawGL::DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor)

View file

@ -21,6 +21,8 @@ file
Ellipse.cpp,
Arc.cpp,
Text.cpp,
Triangles.cpp,
DrawGL.cpp,
PainterGL.cpp,
todo.txt;

View file

@ -167,7 +167,7 @@ void GLDrawPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh,
void GLDrawConvexPolygons(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color);
template <typename Src>
void GLPolylines(GLVertexData& data, const Src& polygon);
void GLPolylines(GLVertexData& data, const Src& polygon, bool close_loops = false);
void DashPolyline(Vector<Vector<Pointf>>& polyline, const Vector<Pointf>& line,
const Vector<double>& pattern, double distance = 0);
@ -188,9 +188,22 @@ void GLDrawText(const GLContext2D& dd, Pointf pos, double angle, const wchar *te
void GLArc(Vector<Vector<Pointf>>& line, const Rectf& rc, Pointf start, Pointf end);
class GLTriangles {
Vector<float> pos;
Vector<GLubyte> color;
Vector<GLint> elements;
int ii = 0;
public:
int Vertex(Pointf p, Color c, double alpha = 1) { pos << (float)p.x << (float)p.y << (float)alpha; color << c.GetR() << c.GetG() << c.GetB(); return ii++; }
void Triangle(int a, int b, int c) { elements << a << b << c; }
void Draw(const GLContext2D& dd);
};
#include "GLPainter.hpp"
class DrawGL : public Draw {
class DrawGL : public NilPainter {
public:
virtual dword GetInfo() const;
@ -214,6 +227,15 @@ public:
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, const int *subpolygon_counts, int scc, const int *disjunct_polygon_counts, int dpcc, Color color, int width, Color outline, uint64 pattern, Color doxor);
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count, const int *counts, int count_count, int width, Color color, Color doxor);
virtual void MoveOp(const Pointf& p, bool rel);
virtual void LineOp(const Pointf& p, bool rel);
virtual void OpacityOp(double o);
virtual void CloseOp();
virtual void StrokeOp(double width, const RGBA& rgba);
virtual void FillOp(const RGBA& color);
virtual void DashOp(const Vector<double>& dash, double start);
private:
struct Cloff : Moveable<Cloff> {
@ -221,14 +243,28 @@ private:
Pointf offset;
};
struct State {
double alpha;
double dash_start;
Vector<double> dash;
};
Vector<Cloff> cloff;
Array<State> state;
GLContext2D dd;
Size view_size;
Pointf Offset(int x, int y);
Pointf Offset(Point p) { return Offset(p.x, p.y); }
Rectf Offset(int x, int y, int cx, int cy);
Rectf Offset(int x, int y, Size sz);
Pointf prev;
Vector<Vector<Pointf>> path;
bool path_done;
double dash_start;
Vector<double> dash;
void Push();
Pointf Off(int x, int y);
Pointf Off(Point p) { return Off(p.x, p.y); }
Rectf Off(int x, int y, int cx, int cy);
Rectf Off(int x, int y, Size sz);
void SyncScissor();
void DoPath(Vector<Vector<Pointf>>& poly, const Point *pp, const Point *end);
static const Vector<double>& GetDash(int& width);
@ -236,9 +272,11 @@ private:
public:
void Init(Size sz, double alpha = 1);
operator const GLContext2D&() const { return dd; }
DrawGL() {}
DrawGL(Size sz, double alpha = 1) { Init(sz, alpha); }
DrawGL(Size sz, double alpha = 1) { Init(sz, alpha); }
~DrawGL();
};

View file

@ -22,7 +22,7 @@ void GLPolygons(GLVertexData& mesh, const Src& polygon)
}
template <typename Src>
void GLPolylines(GLVertexData& data, const Src& polygon)
void GLPolylines(GLVertexData& data, const Src& polygon, bool close)
{
Vector<float> vertex;
Vector<int> ndx;
@ -33,7 +33,11 @@ void GLPolylines(GLVertexData& data, const Src& polygon)
for(const auto& p: polygon) {
int i0 = vertex.GetCount();
int ii0 = ii;
for(int i = 0; i < p.GetCount(); i++) {
int m = 1;
if(p.GetCount() && close && p[0] != p.Top())
m = 0;
for(int i = 0; i < p.GetCount() - m; i++) {
Pointf p1 = p[i];
Pointf p2 = p[i + 1 < p.GetCount() ? i + 1 : 0];
Pointf un = p1 - p2;
@ -54,7 +58,7 @@ void GLPolylines(GLVertexData& data, const Src& polygon)
ii += 4;
}
if(p.GetCount() > 2 && p.Top() == p[0]) // Line loop is closed, draw bevel join
if(p.GetCount() > 2 && (p.Top() == p[0] || close)) // Line loop is closed, draw bevel join
ndx << ii0 << ii0 + 1 << ii - 4 + 3
<< ii - 4 + 2 << ii - 4 + 3 << ii0;
}

View file

@ -6,6 +6,9 @@ void GLDrawPolylines(const GLContext2D& dd, Pointf at, const GLVertexData& mesh,
double width, Color color)
{
GL_TIMING("GLDrawPolylines");
if(IsNull(color))
return;
static GLCode program(R"(
#version 330 core

View file

@ -0,0 +1,77 @@
#include "GLDraw.h"
namespace Upp {
void DrawGL::MoveOp(const Pointf& p_, bool rel)
{
if(path_done) {
path.Clear();
path_done = false;
}
Pointf p = p_;
if(rel)
p = prev + p;
path.Add().Add(Off(p));
prev = p;
}
void DrawGL::LineOp(const Pointf& p_, bool rel)
{
if(path_done) {
path.Clear();
path_done = false;
}
if(path.GetCount() == 0)
path.Add();
Pointf p = p_;
if(rel)
p = prev + p;
path.Top().Add(Off(p));
prev = p;
}
void DrawGL::OpacityOp(double o)
{
dd.alpha *= o;
}
void DrawGL::CloseOp()
{
if(path.GetCount() && path.Top().GetCount())
if(path.Top().Top() != path.Top()[0])
path.Add(path[0]);
}
void DrawGL::StrokeOp(double width, const RGBA& rgba)
{
if(width > 0) {
GLVertexData data;
if(dash.GetCount()) {
Vector<Vector<Pointf>> r;
for(auto& l : path)
DashPolyline(r, l, dash);
GLPolylines(data, r);
}
else
GLPolylines(data, path);
GLDrawPolylines(dd, Pointf(0, 0), data, Sizef(1, 1), width, rgba);
path_done = true;
}
}
void DrawGL::FillOp(const RGBA& color)
{
GLVertexData data;
GLPolygons(data, path);
GLDrawPolygons(dd, Pointf(0, 0), data, Sizef(1, 1), color);
CloseOp();
path_done = true;
}
void DrawGL::DashOp(const Vector<double>& dash_, double start)
{
dash = clone(dash_);
dash_start = start;
}
};

View file

@ -48,6 +48,9 @@ void GLDrawPolygons(const GLContext2D& dd, bool generic, Pointf at, const GLVert
{
GL_TIMING("GLDrawPolygons");
if(IsNull(color))
return;
GLCode& program = GLSimpleCode();
static int ioffset = program["offset"];

View file

@ -0,0 +1,68 @@
#include "GLDraw.h"
namespace Upp {
void GLTriangles::Draw(const GLContext2D& dd)
{
static GLCode program(R"(
#version 330 core
in vec4 p;
in vec4 c;
uniform vec2 offset;
uniform vec2 scale;
out vec4 v_color;
void main()
{
gl_Position = vec4(scale * p.xy + offset, 0, 1);
v_color = vec4(c.r / 255.0, c.g / 255.0, c.b / 255.0, p.z);
}
)", R"(
#version 330 core
in vec4 v_color;
void main()
{
gl_FragColor = v_color;
gl_FragColor = vec4(1, 0.5, 0.5, 1);
}
)");
static int ioffset = program["offset"];
static int iscale = program["scale"];
#if 1
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), pos.begin());
glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_FALSE, 3 * sizeof(GLubyte), color.begin());
program(ioffset, Sizef(-1, 1))
(iscale, dd.vs)
;
program.Use();
glDrawElements(GL_TRIANGLES, elements.GetCount(), GL_INT, elements);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
#else
GLVertexData va;
va.Add(pos, 3);
va.Add(color, GL_BYTE, 3, elements.GetCount());
va.Index(elements);
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
program(ioffset, Sizef(-1, 1))
(iscale, dd.vs)
;
va.Draw(program);
#endif
}
};

View file

@ -409,7 +409,7 @@ protected:
virtual void StrokeOp(double width, const RGBA& color1, const RGBA& color2,
const Xform2D& transsrc,
int style);
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
virtual void StrokeOp(double width, const Pointf& f, const RGBA& color1,
const Pointf& c, double r, const RGBA& color2,
int style);
virtual void StrokeOp(double width, const Pointf& f,
@ -419,7 +419,7 @@ protected:
virtual void ClipOp();
virtual void CharacterOp(const Pointf& p, int ch, Font fnt);
virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1,
virtual void TextOp(const Pointf& p, const wchar *text, Font fnt, int n = -1,
const double *dx = NULL);
virtual void ColorStopOp(double pos, const RGBA& color);