GLPainter

git-svn-id: svn://ultimatepp.org/upp/trunk@12370 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-10-16 09:49:42 +00:00
parent 6e8d1aed0c
commit 6d0c7ce353
7 changed files with 466 additions and 0 deletions

82
bazaar/GLPainter/Code.cpp Normal file
View file

@ -0,0 +1,82 @@
#include "GLPainter.h"
namespace Upp {
GLCode::GLCode(const char *vertex_shader, const char *pixel_shader)
{
Create(vertex_shader, pixel_shader);
Vector<Tuple2<int, const char *>> ins;
CParser p(vertex_shader);
int ii = 0;
while(!p.IsEof() && !p.Char('{'))
if(p.Id("attribute") || p.Id("in")) {
String id;
while(!p.IsEof() && !p.Char(';'))
if(p.IsId())
id = p.ReadId();
else
p.SkipTerm();
if(id.GetCount())
glBindAttribLocation(program, ii++, id);
}
else
p.SkipTerm();
}
GLCode& GLCode::Uniform(int i, double a)
{
Use();
glUniform1f(i, (float)a);
return *this;
}
GLCode& GLCode::Uniform(int i, double a, double b)
{
Use();
glUniform2f(i, (float)a, (float)b);
return *this;
}
GLCode& GLCode::Uniform(int i, double a, double b, double c)
{
Use();
glUniform3f(i, (float)a, (float)b, (float)c);
return *this;
}
GLCode& GLCode::Uniform(int i, double a, double b, double c, double d)
{
Use();
glUniform4f(i, (float)a, (float)b, (float)c, (float)d);
return *this;
}
GLCode& GLCode::Uniform(const char *id, double a)
{
Use();
glUniform1f(GetUniform(id), (float)a);
return *this;
}
GLCode& GLCode::Uniform(const char *id, double a, double b)
{
Use();
glUniform2f(GetUniform(id), (float)a, (float)b);
return *this;
}
GLCode& GLCode::Uniform(const char *id, double a, double b, double c)
{
Use();
glUniform3f(GetUniform(id), (float)a, (float)b, (float)c);
return *this;
}
GLCode& GLCode::Uniform(const char *id, double a, double b, double c, double d)
{
Use();
glUniform4f(GetUniform(id), (float)a, (float)b, (float)c, (float)d);
return *this;
}
};

View file

@ -0,0 +1,95 @@
#ifndef _GLDrawDemo_Ugl_h_
#define _GLDrawDemo_Ugl_h_
#include <GLDraw/GLDraw.h>
#include <plugin/tess2/tess2.h>
namespace Upp {
struct GLCode : GLProgram {
GLCode(const char *vertex_shader, const char *pixel_shader);
int operator[](const char *id) { return GetUniform(id); }
GLCode& Uniform(int i, double a);
GLCode& Uniform(int i, double a, double b);
GLCode& Uniform(int i, double a, double b, double c);
GLCode& Uniform(int i, double a, double b, double c, double d);
GLCode& Uniform(const char *id, double a);
GLCode& Uniform(const char *id, double a, double b);
GLCode& Uniform(const char *id, double a, double b, double c);
GLCode& Uniform(const char *id, double a, double b, double c, double d);
GLCode& operator()(const char *id, double a) { return Uniform(id, a); }
GLCode& operator()(const char *id, double a, double b) { return Uniform(id, a, b); }
GLCode& operator()(const char *id, double a, double b, double c) { return Uniform(id, a, b, c); }
GLCode& operator()(const char *id, double a, double b, double c, double d) { return Uniform(id, a, b, c, d); }
GLCode& operator()(int i, double a) { return Uniform(i, a); }
GLCode& operator()(int i, double a, double b) { return Uniform(i, a, b); }
GLCode& operator()(int i, double a, double b, double c) { return Uniform(i, a, b, c); }
GLCode& operator()(int i, double a, double b, double c, double d) { return Uniform(i, a, b, c, d); }
GLCode& operator()(const char *id, Pointf p) { return Uniform(id, p.x, p.y); }
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); }
};
/*
class GLTexture {
int textureid = 0;
public:
void Clear() { if(textureid)
void Set(const Image& img, dword flags);
operator GLuint() const { return textureid; }
GLuint operator~() const { return textureid; }
void Bind() const {
GLTexture();
GLTexture(const Image& img) { Set(img); }
~GLTexture() { Clear(); }
}
*/
Sizef GLMakeViewScale(Size view_size);
void GLBind(const Image& img, dword style = TEXTURE_LINEAR|TEXTURE_MIPMAP);
void GLDrawImage(Sizef vs, const Rect& rect, const Image& img, double alpha);
class GLMesh {
GLuint VAO, EBO;
int elements;
Vector<GLuint> VBO;
public:
GLMesh& Add(const void *data, int type, int ntuple, int count);
GLMesh& Add(const float *data, int ntuple, int count) { return Add(data, GL_FLOAT, ntuple, count); }
GLMesh& Add(const Vector<Pointf>& pt);
GLMesh& Index(const int *indices, int count);
GLMesh& 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;
GLMesh();
~GLMesh();
};
const GLMesh& GLRectMesh();
void GLMakePolygon(GLMesh& mesh, const Vector<Vector<Pointf>>& polygon);
void GLDrawPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha);
void GLStencilPolygon(GLMesh& mesh, const Vector<Vector<Pointf>>& polygon);
void GLDrawStencilPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha);
};
#endif

View file

@ -0,0 +1,17 @@
description "OpenGL based GLDraw demo\377";
uses
CtrlLib,
GLDraw,
GLCtrl,
plugin/jpg,
plugin/tess2;
file
GLPainter.h,
Code.cpp,
Mesh.cpp,
Image.cpp,
Polygon.cpp,
StencilPolygon.cpp;

View file

@ -0,0 +1,74 @@
#include "GLPainter.h"
namespace Upp {
void GLBind(const Image& img, dword style)
{
glBindTexture(GL_TEXTURE_2D, GetTextureForImage(style, img));
}
Sizef GLMakeViewScale(Size view_size)
{
return Sizef(2.0 / view_size.cx, -2.0 / view_size.cy);
}
const GLMesh& GLRectMesh()
{
static GLMesh mesh;
ONCELOCK {
static const float box[] = {
0, 0, // 0
0, 1, // 1
1, 0, // 2
1, 1, // 3
};
static const int ndx[] = {
0, 1, 2, 1, 2, 3
};
mesh.Add(box, 2, 4).Index(ndx, 6);
}
return mesh;
}
void GLDrawImage(Sizef vs, const Rect& rect, const Image& img, double alpha)
{
static GLCode program(R"(
#version 330 core
uniform vec2 offset;
uniform vec2 scale;
in vec2 aPos;
out vec2 tPos;
void main()
{
gl_Position = vec4(scale * aPos + offset, 0, 1);
tPos = aPos;
}
)", R"(
#version 330 core
in vec2 tPos;
uniform float alpha;
uniform sampler2D s_texture;
void main()
{
gl_FragColor = alpha * texture2D(s_texture, tPos);
}
)");
static int offset = program["offset"];
static int scale = program["scale"];
static int ialpha = program["alpha"];
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
GLBind(img);
GLRectMesh().Draw(
program(offset, vs * rect.TopLeft() + Sizef(-1, 1))
(scale, vs * rect.GetSize())
(ialpha, alpha)
);
}
};

77
bazaar/GLPainter/Mesh.cpp Normal file
View file

@ -0,0 +1,77 @@
#include "GLPainter.h"
namespace Upp {
GLMesh::GLMesh()
{
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &EBO);
}
GLMesh::~GLMesh()
{
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &EBO);
for(auto h : VBO)
glDeleteBuffers(1, &h);
}
GLMesh& GLMesh::Add(const void *data, int type, int ntuple, int count)
{
glBindVertexArray(VAO);
int ii = VBO.GetCount();
GLuint& vbo = VBO.Add();
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
int sz = decode(type, GL_FLOAT, sizeof(float),
GL_BYTE, sizeof(byte),
GL_UNSIGNED_BYTE, sizeof(byte),
GL_SHORT, sizeof(int16),
GL_UNSIGNED_SHORT, sizeof(uint16),
GL_INT, sizeof(int32),
GL_UNSIGNED_INT, sizeof(uint32),
(int)sizeof(double));
glBufferData(GL_ARRAY_BUFFER, sz * ntuple * count, data, GL_STATIC_DRAW);
glVertexAttribPointer(ii, ntuple, type, GL_FALSE, ntuple * sz, (void*)0);
glEnableVertexAttribArray(ii);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return *this;
}
GLMesh& GLMesh::Index(const int *indices, int count)
{
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * count, indices, GL_STATIC_DRAW);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
elements = count;
return *this;
}
void GLMesh::Draw(int mode) const
{
glBindVertexArray(VAO);
glDrawElements(mode, elements, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void GLMesh::Draw(GLCode& shaders, int mode) const
{
shaders.Use();
Draw(mode);
}
GLMesh& GLMesh::Add(const Vector<Pointf>& pt)
{
Buffer<float> f(2 * pt.GetCount());
float *t = f;
for(const Pointf& p : pt) {
*t++ = (float)p.x;
*t++ = (float)p.y;
}
return Add(f, GL_FLOAT, 2, pt.GetCount());
}
};

View file

@ -0,0 +1,46 @@
#include "GLPainter.h"
namespace Upp {
void GLMakePolygon(GLMesh& mesh, const Vector<Vector<Pointf>>& polygon)
{
Vector<Pointf> vertex;
Vector<int> ndx;
Tesselate(polygon, vertex, ndx);
mesh.Add(vertex).Index(ndx);
}
void GLDrawPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha)
{
static GLCode program(R"(
#version 330 core
in vec2 aPos;
uniform vec2 offset;
uniform vec2 scale;
void main()
{
gl_Position = vec4(scale * aPos + offset, 0, 1);
}
)", R"(
#version 330 core
uniform vec4 color;
void main()
{
gl_FragColor = color;
}
)");
RTIMING("Poly");
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
mesh.Draw(
program("offset", vs * at + Sizef(-1, 1))
("scale", vs * scale)
("color", color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, alpha)
);
}
}

View file

@ -0,0 +1,75 @@
#include "GLPainter.h"
namespace Upp {
void GLStencilPolygon(GLMesh& mesh, const Vector<Vector<Pointf>>& polygon)
{
Vector<Pointf> vertex;
Vector<int> ndx;
for(const auto& p: polygon) {
int i0 = vertex.GetCount();
for(int i = 0; i < p.GetCount(); i++) {
if(i > 1)
ndx << i0 << i0 + i - 1 << i0 + i;
vertex.Add(p[i]);
}
}
mesh.Add(vertex).Index(ndx);
}
void GLDrawStencilPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha)
{
static GLCode program(R"(
#version 330 core
in vec2 aPos;
uniform vec2 offset;
uniform vec2 scale;
void main()
{
gl_Position = vec4(scale * aPos + offset, 0, 1);
}
)", R"(
#version 330 core
uniform vec4 color;
void main()
{
gl_FragColor = color;
}
)");
RTIMING("Stencil");
program("offset", vs * at + Sizef(-1, 1))
("scale", vs * scale)
("color", color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, alpha);
glDisable(GL_BLEND);
glDisable(GL_CULL_FACE);
// glClearStencil(0);
glEnable(GL_STENCIL_TEST);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glStencilFunc(GL_NEVER, 0, 1);
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);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLRectMesh().Draw(
program("offset", -1, -1)
("scale", 2, 2)
);
glDisable(GL_STENCIL_TEST);
}
};