GLPainter

git-svn-id: svn://ultimatepp.org/upp/trunk@12382 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-10-21 07:58:01 +00:00
parent 6237a91bc9
commit c2e134378f
9 changed files with 228 additions and 101 deletions

View file

@ -94,4 +94,15 @@ GLCode& GLCode::Uniform(const char *id, double a, double b, double c, double d)
return *this;
}
GLCode& GLCode::operator()(const char *id, Color c, double alpha)
{
return Uniform(GetUniform(id), c, alpha);
}
GLCode& GLCode::operator()(int i, Color c, double alpha)
{
return Uniform(i, c.GetR() / 255.0f, c.GetG() / 255.0f, c.GetB() / 255.0f, alpha);
}
};

View file

@ -4,42 +4,19 @@ namespace Upp {
void GLDrawEllipse(const GLContext2D& dd, Pointf center, Sizef radius, Color color, double alpha)
{
static GLCode program(R"(
#version 330 core
in vec2 aPos;
void main()
{
gl_Position = vec4(2 * aPos - vec2(1, 1), 0, 1);
}
)", R"(
#version 330 core
uniform vec2 center;
uniform vec2 radius1;
uniform vec4 color;
void main()
{
gl_FragColor = color;
vec2 h = radius1 * (gl_FragCoord.xy - center);
h = h * h;
if(h.x + h.y > 1)
gl_FragColor.a = 0;
}
)");
static int icenter = program["center"];
static int iradius1 = program["radius1"];
static int icolor = program["color"];
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
static GLVertexData ellipse;
DDUMP(Sizef(center) * dd.vs + Sizef(-1, 1));
GLRectMesh().Draw(
program(icenter, center)
(iradius1, Sizef(1 / radius.cx, 1 / radius.cy))
(icolor, color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, dd.alpha * alpha)
);
ONCELOCK {
const int N = 200;
Vector<Vector<Pointf>> p;
p.Add();
for(int i = 0; i < N; i++) {
p.Top().Add(Polar(i * M_2PI / N));
}
GLPolygon(ellipse, p);
}
GLDrawPolygon(dd, center, ellipse, radius, color, alpha);
}
};
};

View file

@ -43,6 +43,8 @@ struct GLCode : GLProgram {
GLCode& operator()(int i, Pointf p) { return Uniform(i, p.x, p.y); }
GLCode& operator()(const char *id, Sizef sz) { return Uniform(id, sz.cx, sz.cy); }
GLCode& operator()(int i, Sizef sz) { return Uniform(i, sz.cx, sz.cy); }
GLCode& operator()(const char *id, Color c, double alpha = 1);
GLCode& operator()(int i, Color c, double alpha = 1);
};
class GLTexture {
@ -78,31 +80,41 @@ void GLDrawTexture(const GLContext2D& dd, const Rect& rect, const Image& img, do
void GLDrawImage(const GLContext2D& dd, const Rect& rect, const Image& img, double alpha);
class GLVertexData {
GLuint VAO = 0;
GLuint EBO = 0;
int elements;
Vector<GLuint> VBO;
struct Data {
int refcount = 1;
GLuint VAO = 0;
GLuint EBO = 0;
int elements = 0;
Vector<GLuint> VBO;
};
void Make();
Data *data = NULL;
void Do();
public:
void Clear();
GLVertexData& Add(const void *data, int type, int ntuple, int count);
GLVertexData& Add(const float *data, int ntuple, int count) { return Add(data, GL_FLOAT, ntuple, count); }
GLVertexData& Add(const float *data, int ntuple, int count) { return Add(data, GL_FLOAT, ntuple, count); }
GLVertexData& Add(const Vector<float>& data, int ntuple) { return Add(data, ntuple, data.GetCount() / ntuple); }
GLVertexData& Add(const Vector<Pointf>& pt);
GLVertexData& Index(const int *indices, int count);
GLVertexData& Index(const Vector<int>& indices) { return Index(indices, indices.GetCount()); }
GLVertexData& Index(const Vector<int>& indices) { return Index(indices, indices.GetCount()); }
void Draw(int mode = GL_TRIANGLES) const;
void Draw(GLCode& shaders, int mode = GL_TRIANGLES) const;
void Clear();
bool IsEmpty() const { return VAO == 0; }
operator bool() const { return data; }
bool IsEmpty() const { return !data; }
GLVertexData();
~GLVertexData();
GLVertexData() {}
~GLVertexData() { Clear(); }
GLVertexData(const GLVertexData& src);
GLVertexData& operator=(const GLVertexData& src);
};
const GLVertexData& GLRectMesh();
@ -121,7 +133,9 @@ void GLDrawConvexPolygon(const GLContext2D& dd, Pointf at, const GLVertexData& m
template <typename Src>
void GLPolyline(GLVertexData& data, const Src& polygon);
void GLDrawPolyline(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double width, double alpha);
void GLDrawPolyline(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, double scale, double width, Color color, double alpha);
void GLDrawStencil(Color color, double alpha);
void GLDrawEllipse(const GLContext2D& dd, Pointf center, Sizef radius, Color color, double alpha);

View file

@ -1,9 +1,11 @@
template <typename Src>
void GLPolygon(GLVertexData& mesh, const Src& polygon)
{
Vector<Pointf> vertex; // todo: Optimize!
Vector<Pointf> vertex;
Vector<int> ndx;
mesh.Clear();
for(const auto& p: polygon) {
int i0 = vertex.GetCount();
for(int i = 0; i < p.GetCount(); i++) {
@ -19,5 +21,40 @@ void GLPolygon(GLVertexData& mesh, const Src& polygon)
template <typename Src>
void GLPolyline(GLVertexData& data, const Src& polygon)
{
Vector<float> vertex;
Vector<int> ndx;
int ii = 0;
for(const auto& p: polygon) {
int i0 = vertex.GetCount();
for(int i = 0; i < p.GetCount() - 1; i++) {
Pointf p1 = p[i];
Pointf p2 = p[i + 1 < p.GetCount() ? i + 1 : 0];
Pointf un = Unit(Orthogonal(p1 - p2));
DDUMP(p1);
DDUMP(p2);
vertex << (float)p1.x << (float)p1.y << (float)un.x << (float)un.y;
vertex << (float)p1.x << (float)p1.y << -(float)un.x << -(float)un.y;
vertex << (float)p2.x << (float)p2.y << (float)un.x << (float)un.y;
vertex << (float)p2.x << (float)p2.y << -(float)un.x << -(float)un.y;
DDUMP(un);
ndx << ii << ii + 1 << ii + 2
<< ii + 3 << ii + 2 << ii + 1;
if(ii)
ndx << ii << ii + 1 << ii - 4 + 3
<< ii - 4 + 2 << ii - 4 + 3 << ii;
ii += 4;
}
}
DDUMP(vertex);
data.Add(vertex, 4).Index(ndx);
}

View file

@ -13,7 +13,7 @@ file
Code.cpp,
VertexData.cpp,
Image.cpp,
Polygon.cpp,
TessPolygon.cpp,
StencilPolygon.cpp,
Line.cpp,
Ellipse.cpp;

View file

@ -1 +1,59 @@
#include "GLPainter.h"
namespace Upp {
void GLDrawPolyline(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, double scale,
double width, Color color, double alpha)
{
static GLCode program(R"(
#version 330 core
in vec4 pos;
uniform vec2 offset;
uniform vec2 scale;
uniform float width;
void main()
{
gl_Position = vec4(scale * (pos.xy + width * pos.zw) + offset, 0, 1);
}
)", R"(
#version 330 core
uniform vec4 color;
void main()
{
gl_FragColor = color;
}
)");
static int ioffset = program["offset"];
static int iscale = program["scale"];
static int iwidth = program["width"];
static int icolor = program["color"];
alpha *= dd.alpha;
program(ioffset, Pointf(dd.vs) * at + Sizef(-1, 1))
(iscale, dd.vs * scale)
(iwidth, width / scale / 2)
(icolor, color, alpha)
;
if(alpha == 1) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
mesh.Draw(program);
}
else {
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_NEVER, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
mesh.Draw(program);
GLDrawStencil(color, dd.alpha * alpha);
}
}
};

View file

@ -2,7 +2,7 @@
namespace Upp {
void GLDrawPolygon(const GLContext2D& dd, bool generic, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha)
GLCode& GLSimpleCode()
{
static GLCode program(R"(
#version 330 core
@ -21,14 +21,39 @@ void GLDrawPolygon(const GLContext2D& dd, bool generic, Pointf at, const GLVerte
gl_FragColor = color;
}
)");
return program;
}
void GLDrawStencil(Color color, double alpha)
{
GLCode& program = GLSimpleCode();
static int ioffset = program["offset"];
static int iscale = program["iscale"];
static int iscale = program["scale"];
static int icolor = program["color"];
program("offset", Pointf(dd.vs) * at + Sizef(-1, 1))
("scale", dd.vs * scale)
("color", color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, dd.alpha * alpha);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLRectMesh().Draw(program(ioffset, -1, -1)(iscale, 2, 2)(icolor, color, alpha));
glDisable(GL_STENCIL_TEST);
}
void GLDrawPolygon(const GLContext2D& dd, bool generic, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha)
{
GLCode& program = GLSimpleCode();
static int ioffset = program["offset"];
static int iscale = program["scale"];
static int icolor = program["color"];
program(ioffset, Pointf(dd.vs) * at + Sizef(-1, 1))
(iscale, dd.vs * scale);
if(generic) {
glDisable(GL_BLEND);
@ -40,23 +65,14 @@ void GLDrawPolygon(const GLContext2D& dd, bool generic, Pointf at, const GLVerte
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
mesh.Draw(program);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
GLDrawStencil(color, dd.alpha * alpha);
}
else {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
mesh.Draw(program(icolor, color, dd.alpha * alpha));
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
program("offset", Pointf(dd.vs) * at + Sizef(-1, 1))
("scale", dd.vs * scale)
("color", color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, dd.alpha * alpha);
GLRectMesh().Draw(program("offset", -1, -1)("scale", 2, 2));
if(generic)
glDisable(GL_STENCIL_TEST);
}
void GLDrawPolygon(const GLContext2D& dd, Pointf at, const GLVertexData& mesh, Sizef scale, Color color, double alpha)

View file

@ -2,37 +2,50 @@
namespace Upp {
GLVertexData::GLVertexData() {}
void GLVertexData::Make()
GLVertexData::GLVertexData(const GLVertexData& src)
{
if(!VAO) {
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &EBO);
data = src.data;
data->refcount++;
}
GLVertexData& GLVertexData::operator=(const GLVertexData& src)
{
if(data != src.data) {
if(data) Clear();
data = src.data;
data->refcount++;
}
return *this;
}
void GLVertexData::Clear()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &EBO);
for(auto h : VBO)
glDeleteBuffers(1, &h);
VAO = EBO = 0;
VBO.Clear();
if(data && --data->refcount == 0) {
glDeleteVertexArrays(1, &data->VAO);
glDeleteBuffers(1, &data->EBO);
for(auto h : data->VBO)
glDeleteBuffers(1, &h);
delete data;
}
data = NULL;
}
GLVertexData::~GLVertexData()
void GLVertexData::Do()
{
Clear();
if(!data) {
data = new Data;
glGenVertexArrays(1, &data->VAO);
glGenBuffers(1, &data->EBO);
}
ASSERT(data->refcount == 1); // Changes are only allowed before copied
}
GLVertexData& GLVertexData::Add(const void *data, int type, int ntuple, int count)
GLVertexData& GLVertexData::Add(const void *values, int type, int ntuple, int count)
{
Make();
glBindVertexArray(VAO);
int ii = VBO.GetCount();
GLuint& vbo = VBO.Add();
Do();
glBindVertexArray(data->VAO);
int ii = data->VBO.GetCount();
GLuint& vbo = data->VBO.Add();
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
int sz = (int)decode(type, GL_FLOAT, sizeof(float),
@ -43,7 +56,7 @@ GLVertexData& GLVertexData::Add(const void *data, int type, int ntuple, int coun
GL_INT, sizeof(int32),
GL_UNSIGNED_INT, sizeof(uint32),
sizeof(double));
glBufferData(GL_ARRAY_BUFFER, sz * ntuple * count, data, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sz * ntuple * count, values, GL_STATIC_DRAW);
glVertexAttribPointer(ii, ntuple, type, GL_FALSE, ntuple * sz, (void*)0);
glEnableVertexAttribArray(ii);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -53,22 +66,23 @@ GLVertexData& GLVertexData::Add(const void *data, int type, int ntuple, int coun
GLVertexData& GLVertexData::Index(const int *indices, int count)
{
Make();
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
Do();
glBindVertexArray(data->VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data->EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
elements = count;
data->elements = count;
return *this;
}
void GLVertexData::Draw(int mode) const
{
if(VAO)
glBindVertexArray(VAO);
glDrawElements(mode, elements, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
if(data) {
glBindVertexArray(data->VAO);
glDrawElements(mode, data->elements, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
}
void GLVertexData::Draw(GLCode& shaders, int mode) const