git-svn-id: svn://db.shs.com.ru/libs@627 a8b55f48-bf90-11e4-a774-851b48703e85

This commit is contained in:
2019-11-22 20:22:30 +00:00
parent 09248aae34
commit e65ee56ee4
21 changed files with 527 additions and 208 deletions

View File

@@ -44,7 +44,7 @@ Mesh * assimpMesh(const aiMesh * m) {
QVector<QVector3D> & v(ret->vertices()); v.resize(vcnt);
QVector<QVector2D> & t(ret->texcoords()); t.resize(vcnt);
QVector< Vector3i> & ind(ret->indices());
QVector< Vector3i> & ind(ret->indicesTriangles());
for (int i = 0; i < vcnt; ++i)
v[i] = fromAiVector3D(m->mVertices[i]);

View File

@@ -26,10 +26,11 @@ using namespace QGLEngineShaders;
static int _count = 0;
Mesh::Mesh(): buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW),
buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW),
buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW),
buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
Mesh::Mesh(GLenum geom_type_): geom_type(geom_type_),
buffer_geom(GL_ARRAY_BUFFER, GL_STATIC_DRAW),
buffer_ind (GL_ELEMENT_ARRAY_BUFFER, GL_STATIC_DRAW),
buffer_obj (GL_ARRAY_BUFFER, GL_STREAM_DRAW),
buffer_sel (GL_ARRAY_BUFFER, GL_STREAM_DRAW) {
vao = 0;
hash_ = 0;
changed = hash_changed = objects_changed = selected_changed = true;
@@ -49,6 +50,8 @@ Mesh * Mesh::clone() {
c->normals_ = normals_ ;
c->texcoords_ = texcoords_;
c->triangles_ = triangles_;
c->lines_ = lines_;
c->geom_type = geom_type;
c->hash_ = hash_;
c->hash_changed = hash_changed;
//qDebug() << "clone VBO";
@@ -163,7 +166,8 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
v.tex = texcoords_ [i];
}
int gsize = data_.size() * sizeof(Vertex);
int isize = triangles_.size() * sizeof(Vector3i);
int tsize = triangles_.size() * sizeof(Vector3i);
int lsize = lines_.size() * sizeof(Vector2i);
f->glBindVertexArray(vao);
buffer_geom.bind(f);
@@ -172,8 +176,13 @@ bool Mesh::rebuffer(QOpenGLExtraFunctions * f) {
prepareDrawGeom(f);
buffer_ind.bind(f);
buffer_ind.resize(f, isize);
buffer_ind.load(f, triangles_.constData(), isize);
if (geom_type == GL_TRIANGLES) {
buffer_ind.resize(f, tsize);
buffer_ind.load(f, triangles_.constData(), tsize);
} else {
buffer_ind.resize(f, lsize);
buffer_ind.load(f, lines_.constData(), lsize);
}
buffer_obj.bind(f);
prepareDrawObj(f);
@@ -247,10 +256,13 @@ void Mesh::draw(QOpenGLExtraFunctions * f, int count) {
if (isEmpty()) return;
if (!isInit()) init(f);
if (changed) rebuffer(f);
//qDebug() << "draw" << vert_count << count;
//qDebug() << "draw" << geom_type << vert_count << count;
f->glBindVertexArray(vao);
f->glDrawElementsInstanced(GL_TRIANGLES, triangles_.size() * 3, GL_UNSIGNED_INT, 0, count);
if (geom_type == GL_TRIANGLES)
f->glDrawElementsInstanced(geom_type, triangles_.size() * 3, GL_UNSIGNED_INT, 0, count);
else
f->glDrawElementsInstanced(geom_type, lines_.size() * 2, GL_UNSIGNED_INT, 0, count);
f->glBindVertexArray(0);
}
@@ -262,6 +274,7 @@ void Mesh::clear() {
bitangents_.clear();
texcoords_.clear();
triangles_.clear();
lines_.clear();
data_.clear();
changed = hash_changed = true;
}
@@ -290,6 +303,7 @@ uint Mesh::hash() const {
hash_ ^= qHashBits(normals_ .constData(), normals_ .size() * sizeof(QVector3D));
hash_ ^= qHashBits(texcoords_.constData(), texcoords_.size() * sizeof(QVector2D));
hash_ ^= qHashBits(triangles_.constData(), triangles_.size() * sizeof( Vector3i));
hash_ ^= qHashBits(lines_ .constData(), lines_ .size() * sizeof( Vector2i));
}
return hash_;
}
@@ -327,6 +341,10 @@ void Mesh::append(const Mesh * m) {
for (int i = 0; i < tri.size(); ++i)
tri[i] += vcnt;
triangles_.append(tri);
QVector<Vector2i> lin = m->lines_;
for (int i = 0; i < lin.size(); ++i)
lin[i] += vcnt;
lines_.append(lin);
}
@@ -336,7 +354,7 @@ bool Mesh::saveToFile(const QString & filename) {
QByteArray ba;
if (f.open(QFile::WriteOnly)) {
QDataStream out(&ba, QFile::WriteOnly);
out << vertices_ << normals_ << texcoords_ << triangles_;
out << vertices_ << normals_ << texcoords_ << triangles_ << lines_;
ba = qCompress(ba);
f.resize(0);
f.write(ba);
@@ -356,7 +374,7 @@ bool Mesh::loadFromFile(const QString & filename) {
if (ba.isEmpty()) return false;
ba = qUncompress(ba);
QDataStream in(ba);
in >> vertices_ >> normals_ >> texcoords_ >> triangles_;
in >> vertices_ >> normals_ >> texcoords_ >> triangles_ >> lines_;
changed = hash_changed = true;
f.close();
return !isEmpty();
@@ -397,7 +415,8 @@ Box3D Mesh::boundingBox() const {
QDataStream & operator <<(QDataStream & s, const Mesh * m) {
ChunkStream cs;
//qDebug() << "place VBO" << m.vertices_.size() << m.normals_.size() << m.texcoords_.size() << m.colors_.size() << "...";
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_).add(6, m->triangles_);
cs.add(1, m->vertices_).add(2, m->normals_).add(3, m->texcoords_)
.add(6, m->triangles_).add(7, m->lines_).add(10, int(m->geom_type));
//qDebug() << "place VBO done" << cs.data().size() << "...";
s << /*qCompress*/(cs.data()); return s;
}
@@ -411,10 +430,12 @@ QDataStream & operator >>(QDataStream & s, Mesh *& m) {
ChunkStream cs(s);
while (!cs.atEnd()) {
switch (cs.read()) {
case 1: cs.get(m->vertices_ ); break;
case 2: cs.get(m->normals_ ); break;
case 3: cs.get(m->texcoords_); break;
case 6: cs.get(m->triangles_); break;
case 1 : cs.get(m->vertices_ ); break;
case 2 : cs.get(m->normals_ ); break;
case 3 : cs.get(m->texcoords_); break;
case 6 : cs.get(m->triangles_); break;
case 7 : cs.get(m->lines_ ); break;
case 10: m->geom_type = cs.getData<int>(); break;
}
}
m->changed = true;

View File

@@ -32,7 +32,7 @@ class Mesh
friend QDataStream & operator <<(QDataStream & s, const Mesh * m);
friend QDataStream & operator >>(QDataStream & s, Mesh *& m);
public:
Mesh();
Mesh(GLenum geom_type_ = GL_TRIANGLES);
~Mesh();
Mesh * clone();
@@ -50,6 +50,7 @@ public:
int verticesCount() const {return vertices_.size();}
int trianglesCount() const {return triangles_.size();}
int linesCount() const {return lines_.size();}
bool isInit() const {return vao != 0;}
bool isEmpty() const {return vertices_.isEmpty();}
uint hash() const;
@@ -57,10 +58,12 @@ public:
QVector<QVector3D> & vertices () {changed = hash_changed = true; return vertices_;}
QVector<QVector3D> & normals () {changed = hash_changed = true; return normals_;}
QVector<QVector2D> & texcoords() {changed = hash_changed = true; return texcoords_;}
QVector< Vector3i> & indices () {changed = hash_changed = true; return triangles_;}
QVector< Vector3i> & indicesTriangles() {changed = hash_changed = true; return triangles_;}
QVector< Vector2i> & indicesLines () {changed = hash_changed = true; return lines_;}
void translatePoints(const QVector3D & dp);
void scalePoints (const QVector3D & dp);
void scalePoints (const double & s) {scalePoints(QVector3D(s, s, s));}
void append(const Mesh * m);
bool saveToFile(const QString & filename);
@@ -80,9 +83,10 @@ private:
QVector<QVector3D> vertices_, normals_, tangents_, bitangents_;
QVector<QVector2D> texcoords_;
QVector< Vector3i> triangles_;
QVector< Vector2i> lines_;
QVector<QGLEngineShaders::Vertex> data_;
GLenum vao;
GLenum vao, geom_type;
Buffer buffer_geom, buffer_ind, buffer_obj, buffer_sel;
mutable uint hash_;
mutable bool hash_changed;

View File

@@ -29,6 +29,8 @@ class ObjectBase
friend class QGLView;
friend class Scene;
friend class Renderer;
friend class RendererService;
friend class RendererSelection;
friend QDataStream & operator <<(QDataStream & s, const ObjectBase * p);
friend QDataStream & operator >>(QDataStream & s, ObjectBase *& p);
friend QDataStream & operator >>(QDataStream & s, Scene *& p);

View File

@@ -27,7 +27,7 @@ Mesh * Primitive::plane(float width, float length) {
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & i(ret->indices ());
QVector< Vector3i> & i(ret->indicesTriangles ());
float hw = width / 2.f, hl = length / 2.f;
for (int j = 0; j < 4; ++j) n << QVector3D(0., 0., 1.);
t << QVector2D(0., 0.) << QVector2D(0., 1.) << QVector2D(1., 1.) << QVector2D(1., 0.);
@@ -43,7 +43,7 @@ Mesh * Primitive::cube(float width, float length, float height) {
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & i(ret->indices ());
QVector< Vector3i> & i(ret->indicesTriangles ());
float hs = 0.5f;
int si = 0;
QMatrix4x4 mat;
@@ -92,7 +92,7 @@ Mesh * Primitive::ellipsoid(int segments_wl, int segments_h, float width, float
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & ind(ret->indices());
QVector< Vector3i> & ind(ret->indicesTriangles());
double hh = height / 2.f;
int hseg = segments_h + 1, wlseg = segments_wl + 1;
double crw, crl, a, ch, twl;
@@ -131,7 +131,7 @@ Mesh * Primitive::disc(int segments, float width, float length, bool up) {
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & ind(ret->indices());
QVector< Vector3i> & ind(ret->indicesTriangles());
segments = qMax(segments + 1, 4);
QVector3D cp;
@@ -176,7 +176,7 @@ Mesh * Primitive::cone(int segments, float width, float length, float height) {
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & ind(ret->indices());
QVector< Vector3i> & ind(ret->indicesTriangles());
int seg = qMax(segments + 1, 4);
double rx = width / 2., ry = length / 2.;
@@ -212,7 +212,7 @@ Mesh * Primitive::cylinder(int segments, float width, float length, float height
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector3i> & ind(ret->indices());
QVector< Vector3i> & ind(ret->indicesTriangles());
int seg = qMax(segments + 1, 4);
double rx = width / 2., ry = length / 2.;
@@ -261,3 +261,66 @@ Mesh * Primitive::arrow(int segments, float thick, float angle) {
delete m;
return ret;
}
Mesh * Primitive::cubeFrame(float width, float length, float height) {
Mesh * ret = new Mesh(GL_LINES);
QVector3D scale(width, length, height);
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector2i> & i(ret->indicesLines());
float hs = 0.5f;
v << QVector3D(-hs, -hs, -hs) << QVector3D(-hs, hs, -hs) << QVector3D( hs, hs, -hs) << QVector3D( hs, -hs, -hs);
v << QVector3D(-hs, -hs, hs) << QVector3D(-hs, hs, hs) << QVector3D( hs, hs, hs) << QVector3D( hs, -hs, hs);
for (int j = 0; j < 8; ++j) {
v[j] *= scale;
t << QVector2D(0, 0);
n << QVector3D(0,0,1);
}
for (int j = 0; j < 4; ++j) {
i << Vector2i(j, (j + 1) % 4);
i << Vector2i(j, j + 4);
i << Vector2i(j + 4, (j + 1) % 4 + 4);
}
return ret;
}
Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float width, float length, float height) {
Mesh * ret = new Mesh(GL_LINES);
QVector<QVector3D> & v(ret->vertices ());
QVector<QVector3D> & n(ret->normals ());
QVector<QVector2D> & t(ret->texcoords());
QVector< Vector2i> & ind(ret->indicesLines());
double hh = height / 2.f;
int hseg = segments_h + 1, wlseg = segments_wl + 1;
double crw, crl, a, ch, twl;
QVector3D cp;
for (int i = 0; i <= hseg; i++) {
ch = -cos((double)i / hseg * M_PI);
cp.setZ(ch * hh);
twl = sqrt(1. - ch * ch) / 2.;
crw = twl * width;
crl = twl * length;
int cvcnt = wlseg * 2;
for (int j = 0; j < cvcnt; j++) {
a = (double)j / (cvcnt - 1) * M_2PI;
cp.setX(crl * cos(a));
cp.setY(crw * sin(a));
v << cp; t << QVector2D((double)j / (cvcnt - 1), ch/2.f + 0.5f);
int si = v.size() - 1;
if (j > 0 && i > 0) {
ind << Vector2i(si, si - 1);
ind << Vector2i(si - cvcnt, si);
}
}
}
n.resize(v.size());
for (int i = 0; i < v.size(); i++)
n[i] = v[i].normalized();
return ret;
}

View File

@@ -40,6 +40,10 @@ Mesh * cylinder(int segments, float width = 1., float length = 1., float height
Mesh * arrow(int segments = 16, float thick = 0.04, float angle = 30.); // length = 1
Mesh * cubeFrame(float width = 1., float length = 1., float height = 1.);
Mesh * ellipsoidFrame(int segments_wl, int segments_h, float width = 1., float length = 1., float height = 1.);
}
/*

View File

@@ -29,6 +29,7 @@ class Scene: public QObject {
friend class Renderer;
friend class RendererMaterial;
friend class RendererService;
friend class RendererSelection;
friend class ObjectBase;
friend class Light;
friend QDataStream & operator <<(QDataStream & s, const Scene * p);

View File

@@ -275,6 +275,14 @@ void lengthenVector(QVector3D & v, const float & l) {
}
Vector2i::Vector2i(const QString & str) {
QString s = str.trimmed();
int i = s.indexOf("\t");
p0 = s.left(i).toInt(); s = s.right(s.length() - i - 1);
p1 = s.toInt();
}
Vector3i::Vector3i(const QString & str) {
QString s = str.trimmed();
int i = s.indexOf("\t");

View File

@@ -178,6 +178,8 @@ class RendererBase;
class Renderer;
class RendererMaterial;
class RendererService;
class RendererSelection;
struct Box3D {
GLfloat x;
@@ -211,6 +213,33 @@ struct Box3D {
inline QDebug operator <<(QDebug d, const Box3D & v) {d << "Box3D {start (" << v.x << "," << v.y << "," << v.z << "), size (" << v.length << "," << v.width << "," << v.height << ")}"; return d;}
#pragma pack(push, 1)
struct Vector2i {
Vector2i(int p0_ = 0, int p1_ = 0) {p0 = p0_; p1 = p1_;}
Vector2i(const QString & str);
Vector2i movedX(const int & o) {return Vector2i(p0 + o, p1);}
Vector2i movedY(const int & o) {return Vector2i(p0, p1 + o);}
Vector2i moved(const int & x, const int & y) {return Vector2i(p0 + x, p1 + y);}
GLint p0;
GLint p1;
bool operator ==(const Vector2i & o) const {return p0 == o.p0 && p1 == o.p1;}
bool operator !=(const Vector2i & o) const {return p0 != o.p0 || p1 != o.p1;}
void operator +=(int v) {p0 += v; p1 += v;}
QVector2D toQVector2D() const {return QVector2D(p0, p1);}
};
#pragma pack(pop)
inline Vector2i operator +(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 + s.p0, f.p1 + s.p1);}
inline Vector2i operator -(const Vector2i & f, const Vector2i & s) {return Vector2i(f.p0 - s.p0, f.p1 - s.p1);}
inline Vector2i operator /(const Vector2i & f, const int & s) {return Vector2i(f.p0 / s, f.p1 / s);}
inline uint qHash(const Vector2i & v) {return v.p0 ^ ((v.p1 << 8) | (v.p1 >> 24));}
inline QDebug operator <<(QDebug d, const Vector2i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << "}"; return d.space();}
inline QDataStream & operator <<(QDataStream & s, const Vector2i & v) {s << v.p0 << v.p1; return s;}
inline QDataStream & operator >>(QDataStream & s, Vector2i & v) {s >> v.p0 >> v.p1; return s;}
#pragma pack(push, 1)
struct Vector3i {
Vector3i(int p0_ = 0, int p1_ = 0, int p2_ = 0) {p0 = p0_; p1 = p1_; p2 = p2_;}
@@ -238,6 +267,7 @@ inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v
inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;}
inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;}
QVector3D vectorFromString(const QString & str);
QColor colorFromString(const QString & str);
inline QVector4D QColor2QVector(const QColor & c) {return QVector4D(c.redF(), c.greenF(), c.blueF(), c.alphaF());}

View File

@@ -91,7 +91,7 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this) {
//camera().aim_ = camera().pos_;
ktm_.restart();
Mesh * m = Primitive::cube();
Mesh * m = Primitive::ellipsoidFrame(5,5);
ObjectBase * o = new ObjectBase(m);
o->setColor(Qt::cyan);
scene()->addObject(o);

View File

@@ -39,6 +39,7 @@ class QGLView: public OpenGLWindow
friend class Renderer;
friend class RendererMaterial;
friend class RendererService;
friend class RendererSelection;
Q_OBJECT
Q_PROPERTY (QColor backColor READ backColor WRITE setBackColor)
Q_PROPERTY (float lineWidth READ lineWidth WRITE setLineWidth)

View File

@@ -28,25 +28,22 @@ using namespace QGLEngineShaders;
Renderer::Renderer(QGLView * view_): RendererBase(view_),
fbo_selection(view_, 4),
fbo_ds (view_, 5, true , GL_RGBA16F),
fbo_out (view_, 3, false, GL_RGBA16F),
fbo_hsmall (view_, 1, false, GL_RGB16F ),
rend_mat(this), rend_service(this) {
rend_mat(this), rend_service(this), rend_selection(this) {
quad = Primitive::plane(2., 2.);
sel_frame = quad->clone();
cam_light = new Light();
cam_light->intensity = 0.75;
cam_light->setName("Camera_Light");
line_thick_ = 2.;
id_hover = 0;
shader_files[srSelectionFill ] = "selection.glsl";
shader_files[srSelectionHalo ] = "selection_halo.glsl";
shader_files[srSelectionApply] = "selection_apply.glsl";
shader_files[srSelectionFrame] = "selection_frame.glsl";
shader_files[srService] = "service.glsl";
shader_files[srServiceFill ] = "service_fill.glsl";
shader_files[srServiceFrame] = "service_frame.glsl";
shader_files[srGeometryPass] = "ds_geom.glsl";
shader_files[srLightingPass] = "ds_light.glsl";
@@ -70,13 +67,11 @@ Renderer::Renderer(QGLView * view_): RendererBase(view_),
<< ShaderPair("dof", &shader_dof);*/
exposure_ = 1.;
edit_mode = need_init_shaders = is_camera_light = true;
proc_sel_pbo = false;
}
Renderer::~Renderer() {
delete quad;
delete sel_frame;
delete cam_light;
qDeleteAll(shaders.values());
}
@@ -86,6 +81,7 @@ void Renderer::init(int width, int height) {
resize(width, height);
rend_mat.init(width, height);
rend_service.init(width, height);
rend_selection.init(width, height);
initQuad(quad);
initTextureArrays();
need_init_shaders = true;
@@ -95,12 +91,10 @@ void Renderer::init(int width, int height) {
void Renderer::resize(int width, int height) {
rend_mat.resize(width, height);
rend_service.resize(width, height);
fbo_selection.enablePixelBuffer();
fbo_selection.resize(width, height);
rend_selection.resize(width, height);
fbo_ds .resize(width, height);
fbo_out .resize(width, height);
fbo_hsmall .resize(width / 16, height / 16);
line_thick_ = lineThickness() + 1.;
}
@@ -139,28 +133,6 @@ void Renderer::releaseShader() {
}
void Renderer::generateObjectsID(Scene & scene) {
ids.clear();
QMapIterator<Mesh*, QList<ObjectBase*> > it(scene.geometries_used);
while (it.hasNext()) {
it.next();
foreach (ObjectBase * o, it.value()) {
uint id = qHash(o);
ids[id] = o;
o->id_ = id;
}
}
}
void Renderer::fillSelectionsBuffer(const QList<ObjectBase *> & ol) {
cur_selections_.resize(ol.size());
for (int i = 0; i < ol.size(); ++i) {
cur_selections_[i] = (ol[i]->isSelected(true) ? 1 : 0);
}
}
void Renderer::fillObjectsBuffer(const QList<ObjectBase *> & ol, RenderPass pass) {
cur_objects_.resize(ol.size());
for (int i = 0; i < ol.size(); ++i) {
@@ -195,94 +167,14 @@ void Renderer::renderObjects(Scene & scene, RenderPass pass) {
}
if (mesh->selected_changed && edit_mode) {
mesh->selected_changed = false;
fillSelectionsBuffer(it.value());
mesh->loadSelections(f, cur_selections_);
rend_selection.fillSelectionsBuffer(it.value());
mesh->loadSelections(f, rend_selection.cur_selections_);
}
mesh->draw(f, it.value().size());
}
}
void Renderer::renderSelection(Scene & scene) {
QOpenGLShaderProgram * prog = 0;
if (bindShader(srSelectionFill, &prog)) {
view->hov_objects.clear();
id_hover = 0;
if (fbo_selection.queriedPoints() > 0) {
if (fbo_selection.queriedPoints() == 1) {
id_hover = fbo_selection.getPoint();
view->hov_objects.resize(1);
view->hov_objects[0] = ids.value(id_hover);
//qDebug() << id_hover;
} else {
QVector<uint> points = fbo_selection.getPoints();
QSet<uint> ids_hover;
foreach (uint i, points)
ids_hover << i;
view->hov_objects.clear();
foreach (uint i, ids_hover)
view->hov_objects << ids.value(i);
//qDebug() << ids_hover;
}
}
fbo_selection.bind();
fbo_selection.setWriteBuffers();
glEnableDepth();
glClearFramebuffer(QColor(0,0,0,0));
setUniformCamera(prog, view->camera());
renderObjects(scene, rpSelection);
//mouse_rect = fbo_selection.rect();
if (mouse_rect.isNull())
fbo_selection.queryPoint(0, mouse_pos);
else
fbo_selection.queryPoints(0, mouse_rect);
//qDebug() << id_hover;
fbo_selection.bindColorTextures();
fbo_selection.setWriteBuffers();
if (!view->hoverHalo_ && !view->selectionHalo_)
glClearFramebuffer(QColor(0,0,0,0), false);
else {
bindShader(srSelectionHalo, &prog);
setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha());
setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha());
prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f);
prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f);
prog->setUniformValue("fb_hover" , (int)sbrSrcHover);
prog->setUniformValue("fb_selection", (int)sbrSrcSelect);
prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f,
float((id_hover >> 8 ) & 0xFF) / 255.f,
float((id_hover >> 16) & 0xFF) / 255.f,
float((id_hover >> 24) & 0xFF) / 255.f));
renderQuad(prog, quad, view->camera());
}
fbo_selection.release();
}
}
void Renderer::renderSelectionFrame() {
QOpenGLShaderProgram * prog = 0;
if (bindShader(srSelectionFrame, &prog)) {
QMatrix4x4 mat;
double mrx = mouse_rect.x(), mrw = mouse_rect.width() , vw = view->width();
double mry = mouse_rect.y(), mrh = mouse_rect.height(), vh = view->height();
mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.);
mat.scale(mrw / vw, mrh / vh, 0.);
initQuad(sel_frame, mat);
prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh));
prog->setUniformValue("thickness", line_thick_);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderQuad(prog, sel_frame);
glDisable(GL_BLEND);
}
}
void Renderer::renderScene() {
initShaders();
QOpenGLExtraFunctions * f = view;
@@ -295,7 +187,7 @@ void Renderer::renderScene() {
if (scene_changed || scene.need_reload_materials) {
if (scene.need_reload_materials)
maps_hash = 0;
generateObjectsID(scene);
rend_selection.generateObjectsID(scene);
reloadMaterials(scene);
if (edit_mode)
recreateMaterialThumbnails();
@@ -321,7 +213,7 @@ void Renderer::renderScene() {
/// selection
if (edit_mode) {
renderSelection(scene);
rend_selection.renderSelection(scene);
}
/// geometry pass
@@ -362,20 +254,8 @@ void Renderer::renderScene() {
/// apply hovers and selection frame
if (edit_mode) {
if (bindShader(srSelectionApply, &prog)) {
fbo_selection.bindColorTextures();
fbo_out.bindColorTexture(0);
prog->setUniformValue("fb_out" , 0);
prog->setUniformValue("fb_hover" , (int)sbrHovered );
prog->setUniformValue("fb_select", (int)sbrSelected);
renderQuad(prog, quad, cam);
if (!mouse_rect.isNull()) {
renderSelectionFrame();
}
rend_service.renderService();
}
rend_selection.drawSelection(fbo_out);
rend_service.renderService();
} else {
fbo_out.blit(0, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size()));
}

View File

@@ -22,6 +22,7 @@
#include "renderer_base.h"
#include "renderer_material.h"
#include "renderer_service.h"
#include "renderer_selection.h"
#include <QQueue>
@@ -29,6 +30,7 @@ class Renderer: public RendererBase {
friend class QGLView;
friend class RendererMaterial;
friend class RendererService;
friend class RendererSelection;
enum RenderPass {
rpSolid,
rpTransparent,
@@ -44,7 +46,8 @@ class Renderer: public RendererBase {
srSelectionFrame,
// Service
srService,
srServiceFill,
srServiceFrame,
// Deferred shading
srGeometryPass,
@@ -58,12 +61,6 @@ class Renderer: public RendererBase {
dbrEmissionBitangX,
dbrSpeedBitangXY,
};
enum SelectionBufferRole {
sbrSrcHover,
sbrSrcSelect,
sbrHovered,
sbrSelected
};
public:
Renderer(QGLView * view_);
@@ -80,22 +77,18 @@ public:
void recreateMaterialThumbnails(bool force_all = false) {rend_mat.recreateMaterialThumbnails(force_all);}
protected:
void generateObjectsID(Scene & scene);
void fillSelectionsBuffer(const QList<ObjectBase *> & ol);
void fillObjectsBuffer(const QList<ObjectBase*> & ol, RenderPass pass);
void reloadObjects();
void renderObjects(Scene & scene, RenderPass pass);
void renderSelection(Scene & scene);
void renderSelectionFrame();
bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0);
void initShaders();
void releaseShader();
private:
float exposure_, line_thick_;
bool edit_mode, proc_sel_pbo, need_init_shaders, is_camera_light;
Framebuffer fbo_selection, fbo_ds, fbo_out, fbo_hsmall;
float exposure_;
bool edit_mode, need_init_shaders, is_camera_light;
Framebuffer fbo_ds, fbo_out, fbo_hsmall;
/*QOpenGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small;
QOpenGLShaderProgram * shader_bloom_0, * shader_bloom_1, * shader_motion_blur, * shader_fbo_add;
QOpenGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge;
@@ -105,12 +98,11 @@ private:
RendererMaterial rend_mat;
RendererService rend_service;
RendererSelection rend_selection;
Mesh * quad, * sel_frame;
Mesh * quad;
Light * cam_light;
QHash<uint, ObjectBase * > ids;
uint id_hover;
QPoint mouse_pos;
QRect mouse_rect;
QMatrix4x4 prev_view, prev_proj;

View File

@@ -50,7 +50,6 @@ protected:
QVector<QGLEngineShaders::QGLMaterial> cur_materials_;
QVector<QGLEngineShaders::QGLLightParameter> cur_lights_params_;
QVector<QGLEngineShaders::QGLLightPosition> cur_lights_pos_;
QVector<uchar> cur_selections_;
Buffer buffer_materials;
Buffer buffer_lights, buffer_lights_pos;
Texture2DArray textures_empty, textures_maps;

View File

@@ -0,0 +1,184 @@
/*
QGLView
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define GL_GLEXT_PROTOTYPES
#include <QOpenGLExtraFunctions>
#include "renderer_selection.h"
#include "qglview.h"
#include "glmesh.h"
#include <qad_types.h>
using namespace QGLEngineShaders;
RendererSelection::RendererSelection(Renderer * r_): r(r_),
fbo_selection(r->view, 4) {
sel_frame = Primitive::plane(2., 2.);
id_hover = 0;
line_thick_ = 2.;
}
RendererSelection::~RendererSelection() {
delete sel_frame;
}
void RendererSelection::init(int width, int height) {
resize(width, height);
}
void RendererSelection::resize(int width, int height) {
fbo_selection.enablePixelBuffer();
fbo_selection.resize(width, height);
line_thick_ = lineThickness() + 1.;
}
void RendererSelection::generateObjectsID(Scene & scene) {
ids.clear();
QMapIterator<Mesh*, QList<ObjectBase*> > it(scene.geometries_used);
while (it.hasNext()) {
it.next();
foreach (ObjectBase * o, it.value()) {
uint id = qHash(o);
ids[id] = o;
o->id_ = id;
}
}
foreach (ObjectBase * o, scene.lights_used) {
uint id = qHash(o);
ids[id] = o;
o->id_ = id;
}
}
void RendererSelection::fillSelectionsBuffer(const QList<ObjectBase *> & ol) {
cur_selections_.resize(ol.size());
for (int i = 0; i < ol.size(); ++i) {
cur_selections_[i] = (ol[i]->isSelected(true) ? 1 : 0);
}
}
void RendererSelection::renderSelection(Scene & scene) {
QOpenGLShaderProgram * prog = 0;
QGLView * view = r->view;
if (r->bindShader(Renderer::srSelectionFill, &prog)) {
view->hov_objects.clear();
id_hover = 0;
if (fbo_selection.queriedPoints() > 0) {
if (fbo_selection.queriedPoints() == 1) {
id_hover = fbo_selection.getPoint();
view->hov_objects.resize(1);
view->hov_objects[0] = ids.value(id_hover);
//qDebug() << id_hover;
} else {
QVector<uint> points = fbo_selection.getPoints();
QSet<uint> ids_hover;
foreach (uint i, points)
ids_hover << i;
view->hov_objects.clear();
foreach (uint i, ids_hover)
view->hov_objects << ids.value(i);
//qDebug() << ids_hover;
}
}
fbo_selection.bind();
fbo_selection.setWriteBuffers();
glEnableDepth();
glClearFramebuffer(QColor(0,0,0,0));
r->setUniformCamera(prog, view->camera());
r->renderObjects(scene, Renderer::rpSelection);
view->glClear(GL_DEPTH_BUFFER_BIT);
RendererService & rs(r->rend_service);
rs.fillOmniObjects();
rs.omni_mesh->loadObjects(view, rs.cur_objects);
fillSelectionsBuffer(light2objectList(scene.lights_used));
rs.omni_mesh->loadSelections(view, cur_selections_);
rs.omni_mesh->draw(view, rs.cur_objects.size());
//mouse_rect = fbo_selection.rect();
if (r->mouse_rect.isNull())
fbo_selection.queryPoint(0, r->mouse_pos);
else
fbo_selection.queryPoints(0, r->mouse_rect);
//qDebug() << id_hover;
fbo_selection.bindColorTextures();
fbo_selection.setWriteBuffers();
if (!view->hoverHalo_ && !view->selectionHalo_)
glClearFramebuffer(QColor(0,0,0,0), false);
else {
r->bindShader(Renderer::srSelectionHalo, &prog);
r->setUniformHalo(prog, "hover" , view->hoverHaloColor() , view->hoverHaloFillAlpha());
r->setUniformHalo(prog, "selection", view->selectionHaloColor(), view->selectionHaloFillAlpha());
prog->setUniformValue("has_hover" , view->hoverHalo_ && (id_hover > 0) ? 1.f : 0.f);
prog->setUniformValue("has_selection", view->selectionHalo_ ? 1.f : 0.f);
prog->setUniformValue("fb_hover" , (int)sbrSrcHover);
prog->setUniformValue("fb_selection", (int)sbrSrcSelect);
prog->setUniformValue("hover_id", QVector4D(float( id_hover & 0xFF) / 255.f,
float((id_hover >> 8 ) & 0xFF) / 255.f,
float((id_hover >> 16) & 0xFF) / 255.f,
float((id_hover >> 24) & 0xFF) / 255.f));
r->renderQuad(prog, r->quad, view->camera());
}
fbo_selection.release();
}
}
void RendererSelection::renderSelectionFrame() {
QOpenGLShaderProgram * prog = 0;
if (r->bindShader(Renderer::srSelectionFrame, &prog)) {
QMatrix4x4 mat;
double mrx = r->mouse_rect.x(), mrw = r->mouse_rect.width() , vw = r->view->width();
double mry = r->mouse_rect.y(), mrh = r->mouse_rect.height(), vh = r->view->height();
mat.translate(-1. + (mrw + mrx*2) / vw, 1. - (mrh + mry*2) / vh, 0.);
mat.scale(mrw / vw, mrh / vh, 0.);
r->initQuad(sel_frame, mat);
prog->setUniformValue("size", QVector2D(mrw / vw, mrh / vh));
prog->setUniformValue("thickness", line_thick_);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
r->renderQuad(prog, sel_frame);
glDisable(GL_BLEND);
}
}
void RendererSelection::drawSelection(Framebuffer & fbo_out, int index_out) {
QOpenGLShaderProgram * prog = 0;
if (r->bindShader(Renderer::srSelectionApply, &prog)) {
fbo_selection.bindColorTextures();
fbo_out.bindColorTexture(index_out);
prog->setUniformValue("fb_out" , 0);
prog->setUniformValue("fb_hover" , (int)sbrHovered );
prog->setUniformValue("fb_select", (int)sbrSelected);
r->renderQuad(prog, r->quad, r->view->camera());
if (!r->mouse_rect.isNull()) {
renderSelectionFrame();
}
}
}

View File

@@ -0,0 +1,65 @@
/*
QGLView
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RENDERER_SELECTION_H
#define RENDERER_SELECTION_H
#include "renderer_service.h"
#include <QHash>
class RendererSelection {
friend class QGLView;
friend class Renderer;
public:
RendererSelection(Renderer * r_);
virtual ~RendererSelection();
void init(int width, int height);
void resize(int width, int height);
protected:
enum SelectionBufferRole {
sbrSrcHover,
sbrSrcSelect,
sbrHovered,
sbrSelected
};
void generateObjectsID(Scene & scene);
void fillSelectionsBuffer(const QList<ObjectBase *> & ol);
void renderSelection(Scene & scene);
void renderSelectionFrame();
void drawSelection(Framebuffer & fbo_out, int index_out = 0);
QList<ObjectBase*> light2objectList(const QList<Light*> & v) {QList<ObjectBase*> ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;}
private:
Renderer * r;
Framebuffer fbo_selection;
Mesh * sel_frame;
float line_thick_;
QVector<uchar> cur_selections_;
QHash<uint, ObjectBase * > ids;
uint id_hover;
};
#endif // RENDERER_selection_H

View File

@@ -41,13 +41,23 @@ RendererService::RendererService(Renderer * r_): r(r_) {
QMatrix4x4 m; m.rotate(90., _rot[i]);
m.transposed().copyDataTo(axis_objects[i].modelmatrix);
}
box_vp_scale = 1.;
box_mesh = Primitive::cube();
box_vp_scale = box_full_scale = 1.;
box_mesh = Primitive::cube();
box_mesh_f = Primitive::cubeFrame();
omni_mesh = Primitive::ellipsoid(2, 1);
omni_mesh_f = Primitive::ellipsoidFrame(2, 1);
omni_mesh ->scalePoints(1.5);
omni_mesh_f->scalePoints(1.5);
box_mesh ->scalePoints(1.3);
omni_mesh ->scalePoints(1.3);
}
RendererService::~RendererService() {
delete box_mesh;
delete box_mesh_f;
delete omni_mesh;
delete omni_mesh_f;
delete axis_camera;
delete axis_mesh;
}
@@ -62,25 +72,26 @@ void RendererService::init(int width, int height) {
void RendererService::resize(int width, int height) {
axis_viewport = preferredIconSize(10.);
line_width = lineThickness();
box_vp_scale = 30. * appScale() / qMax(qMin(width, height), 1);
box_vp_scale = 25. * appScale() / qMax(qMin(width, height), 1);
//qDebug() << axis_viewport;
}
void RendererService::fillBoxObjects() {
box_objects.clear();
void RendererService::fillOmniObjects() {
cur_objects.clear();
Object o;
QList<Light*> ll = r->view->scene()->lights_used;
QMatrix4x4 v_mat = r->view->camera()->viewMatrix() * r->view->camera()->offsetMatrix();
QMatrix4x4 lmat;
double vps = tan(r->view->camera()->FOV() / 2. * deg2rad) * box_vp_scale;
box_full_scale = tan(r->view->camera()->FOV() / 2. * deg2rad) * box_vp_scale;
foreach (Light * l, ll) {
QVector4D lpos = QVector4D(l->worldPos(), 1.);
double dist = -(v_mat * lpos).z();
QMatrix4x4 lmat;
lmat.translate(lpos.toVector3D());
lmat.scale(dist * vps);
lmat.scale(dist * box_full_scale);
lmat.transposed().copyDataTo(o.modelmatrix);
box_objects << o;
o.object_id = l->id_;
cur_objects << o;
}
}
@@ -95,32 +106,35 @@ void RendererService::setObjectsColor(QVector<Object> & ol, QColor col) {
void RendererService::renderService() {
QOpenGLShaderProgram * prog = 0;
QOpenGLExtraFunctions * f = r->view;
if (r->bindShader(Renderer::srService, &prog)) {
f->glEnable(GL_MULTISAMPLE);
glEnableDepth();
f->glClear(GL_DEPTH_BUFFER_BIT);
glEnableDepth();
f->glEnable(GL_MULTISAMPLE);
glEnableDepth();
f->glClear(GL_DEPTH_BUFFER_BIT);
if (r->bindShader(Renderer::srServiceFrame, &prog)) {
prog->setUniformValue("qgl_ProjMatrix", r->view->camera()->projectionMatrix(r->view->aspect));
/// lights
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_CULL_FACE);
r->setUniformCamera(prog, r->view->camera());
fillBoxObjects();
fillOmniObjects();
setObjectsColor(box_objects, Qt::white);
glLineWidth(line_width*3);
box_mesh->loadObjects(f, box_objects);
box_mesh->draw(f, box_objects.size());
setObjectsColor(cur_objects, Qt::white);
prog->setUniformValue("line_width", 2.f);
prog->setUniformValue("z_offset", 0.f);
omni_mesh_f->loadObjects(f, cur_objects);
omni_mesh_f->draw(f, cur_objects.size());
setObjectsColor(box_objects, Qt::black);
glLineWidth(line_width);
box_mesh->loadObjects(f, box_objects);
box_mesh->draw(f, box_objects.size());
setObjectsColor(cur_objects, Qt::black);
prog->setUniformValue("line_width", 1.f);
prog->setUniformValue("z_offset", -1.E-3f);
omni_mesh_f->loadObjects(f, cur_objects);
omni_mesh_f->draw(f, cur_objects.size());
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
if (r->bindShader(Renderer::srServiceFill, &prog)) {
/// axis
f->glViewport(0, 0, axis_viewport.width(), axis_viewport.height());
@@ -130,7 +144,6 @@ void RendererService::renderService() {
axis_mesh->draw(f, axis_objects.size());
f->glViewport(0, 0, r->view->width(), r->view->height());
f->glDisable(GL_MULTISAMPLE);
}
f->glDisable(GL_MULTISAMPLE);
}

View File

@@ -26,6 +26,8 @@
class RendererService {
friend class QGLView;
friend class Renderer;
friend class RendererSelection;
public:
RendererService(Renderer * r_);
@@ -34,19 +36,20 @@ public:
void init(int width, int height);
void resize(int width, int height);
void fillBoxObjects();
void fillOmniObjects();
void setObjectsColor(QVector<QGLEngineShaders::Object> & ol, QColor col);
void renderService();
private:
Renderer * r;
Mesh * axis_mesh, * box_mesh;
QVector<QGLEngineShaders::Object> axis_objects, box_objects;
Mesh * axis_mesh, * box_mesh_f, * omni_mesh_f;
Mesh * box_mesh, * omni_mesh;
QVector<QGLEngineShaders::Object> axis_objects, cur_objects;
Camera * axis_camera;
QSize axis_viewport;
int line_width;
double box_vp_scale;
double box_vp_scale, box_full_scale;
};

View File

@@ -133,6 +133,7 @@ void main(void) {
//calcLight(0, normal, v);
qgl_FragColor.rgb = max(vec3(0), li * diffuse + si * specular + emission);
//qgl_FragColor.rgb = vec3(1);
qgl_FragColor.a = 1;

View File

@@ -0,0 +1,48 @@
// vert //
out vec4 object_color_g;
out float mat_scale;
void main(void) {
gl_Position = qgl_ftransform();
object_color_g = qgl_ObjectColor;
mat_scale = pow(qgl_ModelMatrix[0][0] * qgl_ModelMatrix[1][1] * qgl_ModelMatrix[2][2], 0.3333);
}
// geom //
layout (lines) in;
layout (triangle_strip, max_vertices = 4) out;
in float mat_scale[];
in vec4 object_color_g[];
out vec4 object_color;
uniform float line_width, z_offset;
uniform mat4 qgl_ProjMatrix;
void main(void) {
object_color = object_color_g[0];
vec2 dir = normalize(gl_in[0].gl_Position.xy - gl_in[1].gl_Position.xy);
vec2 side = cross(vec3(dir, 0), vec3(0, 0, 1)).xy;
vec4 vo = vec4(0, 0, z_offset, 0);
float dts = 0.05 * line_width * mat_scale[0];
dir *= dts;
side *= dts;
gl_Position = gl_in[0].gl_Position + vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
gl_Position = gl_in[1].gl_Position - vec4((dir - side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
gl_Position = gl_in[1].gl_Position - vec4((dir + side), 0, 0)*qgl_ProjMatrix + vo; EmitVertex();
EndPrimitive();
}
// frag //
in vec4 object_color;
uniform float scale;
void main(void) {
qgl_FragColor = object_color;
}