diff --git a/bazaar/GLPainter/Code.cpp b/bazaar/GLPainter/Code.cpp new file mode 100644 index 000000000..72d2b535c --- /dev/null +++ b/bazaar/GLPainter/Code.cpp @@ -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> 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; +} + +}; diff --git a/bazaar/GLPainter/GLPainter.h b/bazaar/GLPainter/GLPainter.h new file mode 100644 index 000000000..04fa58adb --- /dev/null +++ b/bazaar/GLPainter/GLPainter.h @@ -0,0 +1,95 @@ +#ifndef _GLDrawDemo_Ugl_h_ +#define _GLDrawDemo_Ugl_h_ + +#include +#include + +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 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& pt); + GLMesh& Index(const int *indices, int count); + GLMesh& Index(const Vector& 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>& polygon); +void GLDrawPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha); + +void GLStencilPolygon(GLMesh& mesh, const Vector>& polygon); +void GLDrawStencilPolygon(Sizef vs, Point at, const GLMesh& mesh, Sizef scale, Color color, double alpha); + +}; + +#endif diff --git a/bazaar/GLPainter/GLPainter.upp b/bazaar/GLPainter/GLPainter.upp new file mode 100644 index 000000000..acc668898 --- /dev/null +++ b/bazaar/GLPainter/GLPainter.upp @@ -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; + diff --git a/bazaar/GLPainter/Image.cpp b/bazaar/GLPainter/Image.cpp new file mode 100644 index 000000000..4218d1b66 --- /dev/null +++ b/bazaar/GLPainter/Image.cpp @@ -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) + ); +} + +}; + + diff --git a/bazaar/GLPainter/Mesh.cpp b/bazaar/GLPainter/Mesh.cpp new file mode 100644 index 000000000..3c53b72a9 --- /dev/null +++ b/bazaar/GLPainter/Mesh.cpp @@ -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& pt) +{ + Buffer 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()); +} + +}; \ No newline at end of file diff --git a/bazaar/GLPainter/Polygon.cpp b/bazaar/GLPainter/Polygon.cpp new file mode 100644 index 000000000..1dbdd8c8a --- /dev/null +++ b/bazaar/GLPainter/Polygon.cpp @@ -0,0 +1,46 @@ +#include "GLPainter.h" + +namespace Upp { + +void GLMakePolygon(GLMesh& mesh, const Vector>& polygon) +{ + Vector vertex; + Vector 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) + ); +} + +} \ No newline at end of file diff --git a/bazaar/GLPainter/StencilPolygon.cpp b/bazaar/GLPainter/StencilPolygon.cpp new file mode 100644 index 000000000..cccb2c175 --- /dev/null +++ b/bazaar/GLPainter/StencilPolygon.cpp @@ -0,0 +1,75 @@ +#include "GLPainter.h" + +namespace Upp { + +void GLStencilPolygon(GLMesh& mesh, const Vector>& polygon) +{ + Vector vertex; + Vector 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); +} + +}; \ No newline at end of file