mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-20 06:05:32 -06:00
GLPainter
git-svn-id: svn://ultimatepp.org/upp/trunk@12382 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
6237a91bc9
commit
c2e134378f
9 changed files with 228 additions and 101 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ file
|
|||
Code.cpp,
|
||||
VertexData.cpp,
|
||||
Image.cpp,
|
||||
Polygon.cpp,
|
||||
TessPolygon.cpp,
|
||||
StencilPolygon.cpp,
|
||||
Line.cpp,
|
||||
Ellipse.cpp;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue