diff --git a/qglengine/formats/loader_assimp.cpp b/qglengine/formats/loader_assimp.cpp index 84ef98d..3ab464a 100644 --- a/qglengine/formats/loader_assimp.cpp +++ b/qglengine/formats/loader_assimp.cpp @@ -81,22 +81,51 @@ Mesh * assimpMesh(const aiMesh * m) { } -ObjectBase * assimpObject(const aiNode * n, const QVector & meshes) { +Light * assimpLight(const aiLight * l) { + if (!l) return 0; + Light * ret = new Light(); + ret->setName(l->mName.C_Str()); + ret->setPos(fromAiVector3D(l->mPosition)); + ret->direction = fromAiVector3D(l->mDirection); + ret->decay_const = l->mAttenuationConstant ; + ret->decay_linear = l->mAttenuationLinear ; + ret->decay_quadratic = l->mAttenuationQuadratic; + ret->angle_start = l->mAngleInnerCone * rad2deg; + ret->angle_end = l->mAngleOuterCone * rad2deg; + if (l->mType == aiLightSource_SPOT) + ret->light_type = Light::Cone; + QVector3D col(l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b); + ret->intensity = col.length(); + col /= ret->intensity; + ret->setColor(QColor::fromRgbF(col[0], col[1], col[2])); + return ret; +} + + +ObjectBase * assimpObject(const aiNode * n, const QVector & meshes, const QMap & light_by_name) { if (!n) return 0; - ObjectBase * ret = new ObjectBase(); - ret->setName(n->mName.C_Str()); + ObjectBase * ret = 0; + QString name = n->mName.C_Str(); + Light * light = light_by_name.value(name, 0); + if (light) + ret = light->clone(); + else + ret = new ObjectBase(); + ret->setName(name); ret->setTransform(fromAiMatrix4D(n->mTransformation)); //qDebug() << "add object" << ret << ret->name(); - for (uint i = 0; i < n->mNumMeshes; ++i) { - int mi = n->mMeshes[i]; - if (meshes[mi]) { - ret->setMesh(meshes[mi]); - //qDebug() << "set mesh" << mi << ret->mesh(); - break; + if (!light) { + for (uint i = 0; i < n->mNumMeshes; ++i) { + int mi = n->mMeshes[i]; + if (meshes[mi]) { + ret->setMesh(meshes[mi]); + //qDebug() << "set mesh" << mi << ret->mesh(); + break; + } } } for (uint i = 0; i < n->mNumChildren; ++i) { - ObjectBase * co = assimpObject(n->mChildren[i], meshes); + ObjectBase * co = assimpObject(n->mChildren[i], meshes, light_by_name); if (co) ret->addChild(co); } @@ -120,14 +149,23 @@ Scene * loadScene(const QString & filepath) { QVector meshes; for (uint i = 0; i < ais->mNumMeshes; ++i) meshes << assimpMesh(ais->mMeshes[i]); + QVector lights; + for (uint i = 0; i < ais->mNumLights; ++i) + lights << assimpLight(ais->mLights[i]); + QMap light_by_name; + foreach (Light * l, lights) + light_by_name[l->name()] = l; - ObjectBase * root = assimpObject(ais->mRootNode, meshes); + ObjectBase * root = assimpObject(ais->mRootNode, meshes, light_by_name); if (!root) return 0; Scene * scene = new Scene(); scene->setName(root->name()); foreach (ObjectBase * o, root->children()) scene->addObject(o); + //foreach (ObjectBase * o, lights) + // scene->addObject(o); + qDeleteAll(lights); return scene; } diff --git a/qglengine/globject.cpp b/qglengine/globject.cpp index a016f05..968e329 100644 --- a/qglengine/globject.cpp +++ b/qglengine/globject.cpp @@ -500,6 +500,7 @@ ObjectBase * Light::clone(bool withChildren) { for (int i = 0; i < children_.size(); ++i) o->addChild(children_[i]->clone(withChildren)); } + o->color_ = color_; o->light_type = light_type; o->direction = direction; o->angle_start = angle_start; diff --git a/qglengine/globject.h b/qglengine/globject.h index 3b8c810..f03c95a 100644 --- a/qglengine/globject.h +++ b/qglengine/globject.h @@ -274,4 +274,6 @@ inline T globject_cast(const ObjectBase * object) {return reinterpret_cast(ob QDataStream & operator <<(QDataStream & s, const ObjectBase * p); QDataStream & operator >>(QDataStream & s, ObjectBase *& p); +inline QList light2objectList(const QList & v) {QList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} + #endif // GLOBJECT_H diff --git a/qglengine/glprimitives.cpp b/qglengine/glprimitives.cpp index 7b1caf1..5724e7c 100644 --- a/qglengine/glprimitives.cpp +++ b/qglengine/glprimitives.cpp @@ -371,3 +371,37 @@ Mesh * Primitive::ellipsoidFrame(int segments_wl, int segments_h, float width, f return ret; } + + +Mesh * Primitive::coneFrame(int segments, float width, float length, float height) { + Mesh * ret = new Mesh(GL_LINES); + QVector & v(ret->vertices ()); + QVector & n(ret->normals ()); + QVector & t(ret->texcoords()); + QVector< Vector2i> & ind(ret->indicesLines()); + + int seg = qMax(segments + 1, 4); + double rx = width / 2., ry = length / 2.; + QVector3D cp; + for (int i = 0; i < seg; i++) { + double a = (double)i / (seg - 1) * M_2PI; + cp.setX(ry * cos(a)); + cp.setY(rx * sin(a)); + if (i > 0) { + v << QVector3D(0, 0, height); + t << QVector2D((double)(i - 1) / (seg - 1), 1.f); + double ta = ((double)i - 0.5) / (seg - 1) * M_2PI; + n << coneNormal(rx, ry, height, ta); + } + v << cp; + t << QVector2D((double)i / (seg - 1), 0.f); + n << coneNormal(rx, ry, height, a); + int si = v.size() - 1; + if (i > 0) { + ind << Vector2i(si - 1, si); + ind << Vector2i(si - 2, si); + } + } + + return ret; +} diff --git a/qglengine/glprimitives.h b/qglengine/glprimitives.h index 934a615..2b076a4 100644 --- a/qglengine/glprimitives.h +++ b/qglengine/glprimitives.h @@ -46,6 +46,8 @@ 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.); +Mesh * coneFrame(int segments, float width = 1., float length = 1., float height = 1.); + } /* diff --git a/qglengine/glscene.cpp b/qglengine/glscene.cpp index 9f72dc2..48a0021 100644 --- a/qglengine/glscene.cpp +++ b/qglengine/glscene.cpp @@ -274,7 +274,6 @@ void Scene::removeMaterial(Material * m) { if (o->material_ == m) o->setMaterial(0); materials.removeAll(m); - materials_used.remove(m); changed_materials.removeAll(m); mat_changed = true; } @@ -388,9 +387,10 @@ void Scene::prepareTree(ObjectBase * o) { foreach (ObjectBase * co, o->children_) { if (co->isHidden()) continue; switch (co->type_) { - case ObjectBase::glLight: - lights_used << globject_cast(co); - break; + case ObjectBase::glLight: { + Light * l = globject_cast(co); + lights_used[l->light_type] << l; + } break; case ObjectBase::glMesh: if (co->mesh()) { geometries_used[co->mesh()] << co; @@ -427,15 +427,7 @@ bool Scene::prepare() { lights_used.clear(); prepareTree(root_); } - if (mat_changed) { - mat_changed = false; - materials_used.clear(); - foreach (ObjectBase * o, aol) { - Material * m = o->material(); - if (!m) continue; - materials_used << m; - } - } + mat_changed = false; return true; } diff --git a/qglengine/glscene.h b/qglengine/glscene.h index 8ab6589..6becf08 100644 --- a/qglengine/glscene.h +++ b/qglengine/glscene.h @@ -102,7 +102,7 @@ protected: void setTreeChanged(); void setTreeStructChanged(); void setMaterialsChanged() {mat_changed = true;} - void setLightsChanged() {lights_changed = true;} + void setLightsChanged() {lights_changed = tree_changed = true;} void setObjectMeshChanged(ObjectBase * o); @@ -116,8 +116,7 @@ protected: QVector materials; QMap > geometries_used; - QSet materials_used; - QList lights_used; + QMap> lights_used; // by Light::Type QVector changed_materials; SelectionMode sel_mode_; diff --git a/qglengine/glshaders.cpp b/qglengine/glshaders.cpp index d256923..1af712a 100644 --- a/qglengine/glshaders.cpp +++ b/qglengine/glshaders.cpp @@ -24,7 +24,7 @@ using namespace QGLEngineShaders; -bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file) { +bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QString & content, const QString & file, const QString & defs) { if (type == 0 || content.isEmpty()) { content.clear(); return true; @@ -43,6 +43,7 @@ bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QStr content.prepend(qgl_geometry_head); break; } + content.prepend(defs); content.prepend(qgl_common_head); bool ret = prog->addShaderFromSourceCode(type, content.toLatin1()); if (!ret) qDebug() << "[QGLView] Shader" << file << "Compile error:\n" << prog->log(); @@ -51,59 +52,57 @@ bool addShader(QOpenGLShaderProgram * prog, QOpenGLShader::ShaderType type, QStr } -bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file) { +QString prepareDefines(const QStringList & defines) { + if (defines.isEmpty()) return QString(); + QString ret; + foreach (QString s, defines) + ret.append("#define " + s + "\n"); + return ret; +} + + +bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, const QStringList & defines) { if (!prog) prog = new QOpenGLShaderProgram(); prog->removeAllShaders(); QFile f(file); if (!f.open(QIODevice::ReadOnly)) return false; QTextStream ts(&f); - QString cur_shader, line, pl; + QString cur_shader, line, pl, defs = prepareDefines(defines); QOpenGLShader::ShaderType type = 0; while (!ts.atEnd()) { line = ts.readLine(); pl = line.trimmed().remove(' ').remove('\t').mid(2).toLower(); pl.chop(2); if (pl == "vertex" || pl == "vert") { - if (!addShader(prog, type, cur_shader, file)) return false; + if (!addShader(prog, type, cur_shader, file, defs)) return false; type = QOpenGLShader::Vertex; continue; } if (pl == "fragment" || pl == "frag") { - if (!addShader(prog, type, cur_shader, file)) return false; + if (!addShader(prog, type, cur_shader, file, defs)) return false; type = QOpenGLShader::Fragment; continue; } if (pl == "geometry" || pl == "geom") { - if (!addShader(prog, type, cur_shader, file)) return false; + if (!addShader(prog, type, cur_shader, file, defs)) return false; type = QOpenGLShader::Geometry; continue; } if (pl == "tessellation_control") { - if (!addShader(prog, type, cur_shader, file)) return false; + if (!addShader(prog, type, cur_shader, file, defs)) return false; type = QOpenGLShader::TessellationControl; continue; } if (pl == "tessellation_evaluation") { - if (!addShader(prog, type, cur_shader, file)) return false; + if (!addShader(prog, type, cur_shader, file, defs)) return false; type = QOpenGLShader::TessellationEvaluation; continue; } cur_shader.append("\n"); cur_shader.append(line); } - if (!addShader(prog, type, cur_shader, file)) return false; - /// WARNING - /*prog->bindAttributeLocation("qgl_Vertex" , 1 ); - prog->bindAttributeLocation("qgl_Normal" , 2 ); - prog->bindAttributeLocation("qgl_Tangent" , 3 ); - prog->bindAttributeLocation("qgl_Bitangent" , 4 ); - prog->bindAttributeLocation("qgl_Texture" , 5 ); - prog->bindAttributeLocation("qgl_Material" , 6 ); - prog->bindAttributeLocation("qgl_Color" , 7 ); - prog->bindAttributeLocation("qgl_ModelViewMatrix" , 8 ); - prog->bindAttributeLocation("qgl_ModelViewProjectionMatrix", 12); - prog->bindAttributeLocation("qgl_NormalMatrix" , 16);*/ + if (!addShader(prog, type, cur_shader, file, defs)) return false; if (!prog->link()) { qDebug() << "[QGLView] Shader" << file << "Link error:\n" << prog->log(); return false; diff --git a/qglengine/glshaders.h b/qglengine/glshaders.h index cf3ac8f..7d571cf 100644 --- a/qglengine/glshaders.h +++ b/qglengine/glshaders.h @@ -23,7 +23,7 @@ namespace QGLEngineShaders { -bool loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file); +bool loadShadersMulti(QOpenGLShaderProgram *& prog, const QString & file, const QStringList & defines = QStringList()); void setUniformMatrices(QOpenGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view, QMatrix4x4 prevproj = QMatrix4x4(), QMatrix4x4 prevview = QMatrix4x4()); void setUniformLights(QOpenGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, int shadow_start); diff --git a/qglengine/gltexture_manager.h b/qglengine/gltexture_manager.h index 61a3236..b9473d8 100644 --- a/qglengine/gltexture_manager.h +++ b/qglengine/gltexture_manager.h @@ -31,7 +31,8 @@ public: TextureManager(QOpenGLExtraFunctions * f_): f(f_) {} virtual ~TextureManager() {} - void addSearchPath(const QString & path) {search_pathes << path;} + static void addSearchPath(const QString & path) {if (!search_pathes.contains(path)) search_pathes << path;} + static void clearSearchPathes() {search_pathes.clear();} static QStringList searchPathes() {return search_pathes;} QString findFile(const QString & path); GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); diff --git a/qglengine/qglview.cpp b/qglengine/qglview.cpp index 6476526..5ee2f63 100644 --- a/qglengine/qglview.cpp +++ b/qglengine/qglview.cpp @@ -88,9 +88,12 @@ QGLView::QGLView(): OpenGLWindow(), renderer_(this), mouse(this) { //camera().aim_ = camera().pos_; ktm_.restart(); - //Mesh * m = Primitive::torus(30, 12, 1., 0.1, 90); - Mesh * m = Primitive::disc(10, 1, 1., true, 90); - QMatrix4x4 mat; mat.rotate(90, 1,0,0); + Mesh * m = Primitive::torus(30, 12, 1., 0.1, 90); + //Mesh * m = Primitive::coneFrame(10, 1, 1., 2.); + //QMatrix4x4 mat; + //mat.rotate(90, 0,1,0); + //mat.translate(0, 0, 2); + //mat.rotate(180, 1,0,0); //m->transformPoints(mat); ObjectBase * o = new ObjectBase(m); o->setColor(Qt::cyan); diff --git a/qglengine/qglview_test/qglview_window.cpp b/qglengine/qglview_test/qglview_window.cpp index 98c44e6..60a2600 100644 --- a/qglengine/qglview_test/qglview_window.cpp +++ b/qglengine/qglview_test/qglview_window.cpp @@ -19,6 +19,7 @@ #include "qglview_window.h" #include "renderer.h" #include "glwidget.h" +#include "gltexture_manager.h" #include #include #include @@ -140,9 +141,11 @@ void QGLViewWindow::loadFile(const QString & path, bool import) { s->setName(fi.baseName()); if (import) view->scene()->addScene(s); else { + TextureManager::clearSearchPathes(); view->scene()->assignFrom(s); view->view()->focusOn(view->scene()->boundingBox()); } + TextureManager::addSearchPath(fi.absoluteDir().path()); delete s; } diff --git a/qglengine/renderer.cpp b/qglengine/renderer.cpp index 73e7ff2..e287da5 100644 --- a/qglengine/renderer.cpp +++ b/qglengine/renderer.cpp @@ -45,9 +45,10 @@ Renderer::Renderer(QGLView * view_): RendererBase(view_), shader_files[srServiceFill ] = "service_fill.glsl"; shader_files[srServiceFrame] = "service_frame.glsl"; - shader_files[srGeometryPass] = "ds_geom.glsl"; - shader_files[srLightingPass] = "ds_light.glsl"; - shader_files[srFinalPass ] = "ds_final.glsl"; + shader_files[srGeometryPass ] = "ds_geom.glsl"; + shader_files[srLightOmniPass] = "ds_light.glsl"; shader_defines[srLightOmniPass] << "FIRST_PASS"; + shader_files[srLightSpotPass] = "ds_light.glsl"; shader_defines[srLightSpotPass] << "SPOT"; + shader_files[srFinalPass ] = "ds_final.glsl"; /*shaders << ShaderPair("FXAA", &shader_fxaa) << ShaderPair("dsl_pass_0", &shader_ds_0) @@ -102,9 +103,12 @@ void Renderer::reloadShaders() { QMapIterator it(shader_files); while (it.hasNext()) { it.next(); - loadShadersMulti(shaders[it.key()], "shaders/" + it.value()); + loadShadersMulti(shaders[it.key()], "shaders/" + it.value(), shader_defines.value(it.key())); } need_init_shaders = true; + view->scene()->setLightsChanged(); + view->scene()->setTreeStructChanged(); + view->scene()->setMaterialsChanged(); } @@ -122,9 +126,12 @@ void Renderer::initShaders() { if (!need_init_shaders) return; need_init_shaders = false; initUniformBuffer(shaders.value(srGeometryPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); - initUniformBuffer(shaders.value(srLightingPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); - initUniformBuffer(shaders.value(srLightingPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); - initUniformBuffer(shaders.value(srLightingPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); + initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_materials , bpMaterials , "QGLMaterialData" ); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights , bpLightParameters, "QGLLightParameterData"); + initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights_pos, bpLightPositions , "QGLLightPositionData" ); } @@ -167,7 +174,7 @@ void Renderer::renderObjects(Scene & scene, RenderPass pass) { } if (mesh->selected_changed && edit_mode) { mesh->selected_changed = false; - rend_selection.fillSelectionsBuffer(it.value()); + fillSelectionsBuffer(rend_selection.cur_selections_, it.value()); mesh->loadSelections(f, rend_selection.cur_selections_); } mesh->draw(f, it.value().size()); @@ -200,16 +207,16 @@ void Renderer::renderScene() { } /// lights - QList ll = scene.lights_used; + QMap> ll = scene.lights_used; if (is_camera_light) { - ll << cam_light; + ll[Light::Omni] << cam_light; cam_light->setPos(cam->pos()); } if (scene.lights_changed) { scene.lights_changed = false; reloadLightsParameters(ll); } - reloadLightsPositions(ll, cam); + reloadLightsPositions(cam); /// selection if (edit_mode) { @@ -233,31 +240,35 @@ void Renderer::renderScene() { fbo_ds.bindColorTextures(); fbo_ds.bindDepthTexture(5); fbo_out.bind(); - if (bindShader(srLightingPass, &prog)) { - setUniformCamera(prog, cam); - setUniformViewCorners(prog, cam); - for (int i = 0; i < 5; ++i) - prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); - prog->setUniformValue("tex_d", 5); - prog->setUniformValue("lights_count", ll.size()); - glClearFramebuffer(view->backColor(), false); - renderQuad(prog, quad, cam); - /*QVector _fb = fbo_out.grabF(0); - if (!_fb.isEmpty()) { - double sum = 0.; - foreach (float f, _fb) sum += f; - sum /= _fb.size(); - qDebug() << "sum =" << sum; - }*/ + int ri = 1, wi = 0; + typedef QPair PassPair; + QVector passes; + passes << PassPair(srLightOmniPass, Light::Omni) << PassPair(srLightSpotPass, Light::Cone); + foreach (PassPair pass, passes) { + if (bindShader(pass.first, &prog)) { + setUniformCamera(prog, cam); + setUniformViewCorners(prog, cam); + for (int i = 0; i < 5; ++i) + prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); + prog->setUniformValue("tex_d", 5); + prog->setUniformValue("lights_start", lights_start[pass.second]); + prog->setUniformValue("lights_count", ll[pass.second].size()); + prog->setUniformValue("tex_sum", 7); + fbo_out.setWriteBuffer(wi); + fbo_out.bindColorTexture(ri, 7); + glClearFramebuffer(Qt::black, false); + renderQuad(prog, quad, cam); + piSwap(ri, wi); + } } fbo_out.release(); /// apply hovers and selection frame if (edit_mode) { - rend_selection.drawSelection(fbo_out); + rend_selection.drawSelection(fbo_out, ri); rend_service.renderService(); } else { - fbo_out.blit(0, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size())); + fbo_out.blit(ri, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size())); } } diff --git a/qglengine/renderer.h b/qglengine/renderer.h index d4a4b6d..f79f072 100644 --- a/qglengine/renderer.h +++ b/qglengine/renderer.h @@ -52,7 +52,8 @@ class Renderer: public RendererBase { // Deferred shading srGeometryPass, - srLightingPass, + srLightOmniPass, + srLightSpotPass, srFinalPass, }; enum DeferredBufferRole { @@ -95,6 +96,7 @@ private: QOpenGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge; QOpenGLShaderProgram * shader_ssao_blur, * shader_ssao_merge, * shader_dof;*/ QMap shader_files; + QMap shader_defines; QMap shaders; RendererMaterial rend_mat; diff --git a/qglengine/renderer_base.cpp b/qglengine/renderer_base.cpp index 015c6a0..a3d6b63 100644 --- a/qglengine/renderer_base.cpp +++ b/qglengine/renderer_base.cpp @@ -123,6 +123,21 @@ void RendererBase::setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * c } +void RendererBase::fillSelectionsBuffer(QVector & buffer, const QList & ol) { + buffer.resize(ol.size()); + for (int i = 0; i < ol.size(); ++i) { + buffer[i] = (ol[i]->isSelected(true) ? 1 : 0); + } +} + + +void RendererBase::fillSelectionsBuffer(QVector & buffer, bool yes, int size) { + buffer.resize(size); + for (int i = 0; i < size; ++i) + buffer[i] = (yes ? 1 : 0); +} + + void RendererBase::reloadMaterials(Scene & scene) { //qDebug() << "reloadMaterias"; QList maps[2]; @@ -199,12 +214,21 @@ void RendererBase::reloadMaterials(Scene & scene) { } -void RendererBase::reloadLightsParameters(const QList & lights) { - cur_lights_params_.resize(qMin(lights.size(), max_lights)); +void RendererBase::reloadLightsParameters(const QMap> & lights) { + lights_start.clear(); + lights_start[Light::Omni] = 0; + QMapIterator> it(lights); + current_lights.clear(); + while (it.hasNext()) { + it.next(); + lights_start[it.key()] = current_lights.size(); + current_lights.append(it.value()); + } + cur_lights_params_.resize(qMin(current_lights.size(), max_lights)); //qDebug() << "reloadLightsParameters" << cur_lights_params_.size(); for (int i = 0; i < cur_lights_params_.size(); ++i) { QGLLightParameter & so(cur_lights_params_[i]); - Light * l = lights[i]; + Light * l = current_lights[i]; double ang_start = l->angle_start / 2.f, ang_end = l->angle_end / 2.f; if (l->light_type == Light::Omni) ang_start = ang_end = 180.; @@ -227,12 +251,12 @@ void RendererBase::reloadLightsParameters(const QList & lights) { } -void RendererBase::reloadLightsPositions(const QList & lights, Camera * cam) { - cur_lights_pos_.resize(qMin(lights.size(), max_lights)); +void RendererBase::reloadLightsPositions(Camera * cam) { + cur_lights_pos_.resize(qMin(current_lights.size(), max_lights)); QMatrix4x4 mat = cam->viewMatrix() * cam->offsetMatrix(); for (int i = 0; i < cur_lights_pos_.size(); ++i) { QGLLightPosition & so(cur_lights_pos_[i]); - Light * l = lights[i]; + Light * l = current_lights[i]; QMatrix4x4 m = mat * l->worldTransform(); QVector4D pos(0, 0, 0, 1.), dir(l->direction, 1);//, dir0(light->dir0), dir1(light->dir1); pos = m * pos; diff --git a/qglengine/renderer_base.h b/qglengine/renderer_base.h index c84f304..1aaf429 100644 --- a/qglengine/renderer_base.h +++ b/qglengine/renderer_base.h @@ -36,9 +36,11 @@ protected: void setUniformMaps (QOpenGLShaderProgram * prog); void setUniformCamera (QOpenGLShaderProgram * prog, Camera * cam, bool matrices = true, QSize viewport = QSize()); void setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * cam, QSize viewport = QSize()); + void fillSelectionsBuffer(QVector & buffer, const QList & ol); + void fillSelectionsBuffer(QVector & buffer, bool yes, int size); void reloadMaterials(Scene & scene); - void reloadLightsParameters(const QList & lights); - void reloadLightsPositions (const QList & lights, Camera * cam); + void reloadLightsParameters(const QMap> & lights); + void reloadLightsPositions (Camera * cam); void markReloadTextures(); void setMapsSize(QSize sz); void initQuad(Mesh * mesh, QMatrix4x4 mat = QMatrix4x4()); @@ -55,6 +57,8 @@ protected: Texture2DArray textures_empty, textures_maps; QSize maps_size; uint maps_hash; + QMap lights_start; + QList current_lights; }; diff --git a/qglengine/renderer_material.cpp b/qglengine/renderer_material.cpp index d83a59a..58f56e3 100644 --- a/qglengine/renderer_material.cpp +++ b/qglengine/renderer_material.cpp @@ -81,17 +81,18 @@ void RendererMaterial::renderMaterial(Material * m) { fbo_mat_thumb.bindColorTextures(); fbo_mat_thumb.bindDepthTexture(5); fbo_mat_thumb.setWriteBuffer(5); - if (r->bindShader(Renderer::srLightingPass, &prog)) { + if (r->bindShader(Renderer::srLightOmniPass, &prog)) { r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size()); r->setUniformViewCorners(prog, mat_camera, fbo_mat_thumb.size()); for (int i = 0; i < 5; ++i) prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); prog->setUniformValue("tex_d", 5); + prog->setUniformValue("lights_start", 0); prog->setUniformValue("lights_count", 1); - QList mat_l; - mat_l << mat_light; + QMap> mat_l; + mat_l[Light::Omni] << mat_light; r->reloadLightsParameters(mat_l); - r->reloadLightsPositions(mat_l, mat_camera); + r->reloadLightsPositions(mat_camera); glClearFramebuffer(r->view->backColor(), false); r->renderQuad(prog, r->quad, mat_camera); r->view->scene()->setLightsChanged(); diff --git a/qglengine/renderer_selection.cpp b/qglengine/renderer_selection.cpp index e445e2b..935bfbd 100644 --- a/qglengine/renderer_selection.cpp +++ b/qglengine/renderer_selection.cpp @@ -62,29 +62,18 @@ void RendererSelection::generateObjectsID(Scene & scene) { o->id_ = id; } } - foreach (ObjectBase * o, scene.lights_used) { - uint id = qHash(o); - ids[id] = o; - o->id_ = id; + QMapIterator> lit(scene.lights_used); + while (lit.hasNext()) { + lit.next(); + foreach (ObjectBase * o, lit.value()) { + uint id = qHash(o); + ids[id] = o; + o->id_ = id; + } } } -void RendererSelection::fillSelectionsBuffer(const QList & 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::fillSelectionsBuffer(bool yes, int size) { - cur_selections_.resize(size); - for (int i = 0; i < size; ++i) - cur_selections_[i] = (yes ? 1 : 0); -} - - void RendererSelection::renderSelection(Scene & scene) { QOpenGLShaderProgram * prog = 0; QGLView * view = r->view; @@ -120,12 +109,7 @@ void RendererSelection::renderSelection(Scene & scene) { 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()); - + rs.drawLights(); rs.drawCurrentHandleObjects(); //mouse_rect = fbo_selection.rect(); diff --git a/qglengine/renderer_selection.h b/qglengine/renderer_selection.h index 7e5097a..1295004 100644 --- a/qglengine/renderer_selection.h +++ b/qglengine/renderer_selection.h @@ -27,6 +27,7 @@ class RendererSelection { friend class QGLView; friend class MouseController; friend class Renderer; + friend class RendererService; public: RendererSelection(Renderer * r_); @@ -44,12 +45,9 @@ protected: }; void generateObjectsID(Scene & scene); - void fillSelectionsBuffer(const QList & ol); - void fillSelectionsBuffer(bool yes, int size); void renderSelection(Scene & scene); void renderSelectionFrame(); void drawSelection(Framebuffer & fbo_out, int index_out = 0); - QList light2objectList(const QList & v) {QList ret; foreach (Light*i, v) ret << (ObjectBase*)i; return ret;} private: Renderer * r; diff --git a/qglengine/renderer_service.cpp b/qglengine/renderer_service.cpp index 3b91092..b2ee49e 100644 --- a/qglengine/renderer_service.cpp +++ b/qglengine/renderer_service.cpp @@ -60,6 +60,15 @@ RendererService::RendererService(Renderer * r_): r(r_) { omni_mesh_f = Primitive::ellipsoidFrame(2, 1); omni_mesh ->scalePoints(1.5); omni_mesh_f->scalePoints(1.5); + cone_mesh = Primitive::cone(8, 1., 1., 1.); + cone_mesh_f = Primitive::coneFrame(8, 1., 1., 1.); + QMatrix4x4 mat; + mat.rotate(90, 0,1,0); + mat.translate(0,0,2); + mat.rotate(180, 1,0,0); + cone_mesh ->transformPoints(mat); + cone_mesh_f->transformPoints(mat); + box_mesh ->scalePoints(1.3); omni_mesh ->scalePoints(1.3); @@ -98,6 +107,8 @@ RendererService::~RendererService() { delete box_mesh_f; delete omni_mesh; delete omni_mesh_f; + delete cone_mesh; + delete cone_mesh_f; delete axis_camera; delete axis_mesh; delete handle_move_mesh; @@ -143,7 +154,7 @@ void RendererService::fillXYZObjects() { void RendererService::fillOmniObjects() { - QList ll = r->view->scene()->lights_used; + QList ll = r->view->scene()->lights_used.value(Light::Omni); Object o; cur_objects.clear(); foreach (Light * l, ll) { @@ -247,6 +258,15 @@ void RendererService::drawCurrentHandleObjects() { } +void RendererService::drawLights() { + fillOmniObjects(); + omni_mesh->loadObjects(r->view, cur_objects); + r->fillSelectionsBuffer(r->rend_selection.cur_selections_, light2objectList(r->view->scene_->lights_used.value(Light::Omni))); + omni_mesh->loadSelections(r->view, r->rend_selection.cur_selections_); + omni_mesh->draw(r->view, cur_objects.size()); +} + + void RendererService::setObjectsColor(QVector & ol, QColor col) { QVector4D cv = QColor2QVector(col); for (int i = 0; i < ol.size(); ++i) @@ -279,7 +299,7 @@ void RendererService::renderService() { setObjectsColor(cur_objects, Qt::black); prog->setUniformValue("line_width", 1.f); - prog->setUniformValue("z_offset", -1.E-3f); + prog->setUniformValue("z_offset", -1.E-2f); omni_mesh_f->loadObjects(f, cur_objects); omni_mesh_f->draw(f, cur_objects.size()); diff --git a/qglengine/renderer_service.h b/qglengine/renderer_service.h index 746598f..9165cea 100644 --- a/qglengine/renderer_service.h +++ b/qglengine/renderer_service.h @@ -71,6 +71,7 @@ public: void fillHandleObjects(QVector3D center, HandleMesh ids[], const QVector & mats, const QVector & colors, QMatrix4x4 add_mat, int count = 3); bool calculateCenter(); void drawCurrentHandleObjects(); + void drawLights(); void setObjectsColor(QVector & ol, QColor col); void renderService(); void setCurrentAction(HandleAction ha) {current_action = ha;} @@ -81,7 +82,7 @@ private: Mesh * axis_mesh, * handle_move_mesh, * handle_rotate_mesh, * handle_scale_mesh; Mesh * handle_ms_2_mesh, * handle_scale_3_mesh; - Mesh * box_mesh_f, * omni_mesh_f, * box_mesh, * omni_mesh; + Mesh * box_mesh_f, * omni_mesh_f, * cone_mesh_f, * box_mesh, * omni_mesh, * cone_mesh; QMatrix4x4 v_mat, axis_mat; QVector3D selection_center; QVector mat_xyz, mat_ms2; diff --git a/qglengine/shaders/ds_light.glsl b/qglengine/shaders/ds_light.glsl index 8ce3578..f07d71a 100644 --- a/qglengine/shaders/ds_light.glsl +++ b/qglengine/shaders/ds_light.glsl @@ -17,8 +17,8 @@ in vec3 view_dir; uniform vec2 dt; uniform float z_near; uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4; -uniform sampler2D tex_d; -uniform int lights_count; +uniform sampler2D tex_d, tex_sum; +uniform int lights_start, lights_count; const vec3 luma = vec3(0.299, 0.587, 0.114); const float _pe = 2.4e-7; @@ -36,45 +36,45 @@ void calcLight(in int index, in vec3 n, in vec3 v) { halfV = normalize(ldir + v); NdotL = max(dot(n, ldir), 1E-6); NdotH = max(dot(n, halfV), 1E-6); - spot = step(1.01E-6, NdotL) * qgl_light_parameter[index].intensity; - /*if (qgl_Light[index].endAngle <= 90.) { - float scos = max(dot(-ldir, qgl_Light[index].direction.xyz), 0.); - spot *= scos * step(qgl_Light[index].endAngleCos, scos); - spot *= smoothstep(qgl_Light[index].endAngleCos, qgl_Light[index].startAngleCos, scos); - //lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz; - //bn = normalize(cross(lwdir, vec3(1, 0, 0))); - //bn2 = normalize(cross(lwdir, bn)); - float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02); - //spot *= clamp(1. - sdist, 0, 1); - vds = ds * bn.xyz; - vds2 = ds * bn2.xyz; - float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.; - shadow += getShadow(index, pos.xyz, vds ) * 2.; - shadow += getShadow(index, pos.xyz, - vds ) * 2.; - shadow += getShadow(index, pos.xyz, - vds2 ) * 2.; - shadow += getShadow(index, pos.xyz, + vds2 ) * 2.; - //shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5; - //shadow += getShadow(index, pos.xyz, vds + vds ); - //shadow += getShadow(index, pos.xyz, - vds - vds ); - //shadow += getShadow(index, pos.xyz, - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, + vds2 + vds2); - //shadow += getShadow(index, pos.xyz, vds + vds - vds2 ); - //shadow += getShadow(index, pos.xyz, - vds - vds - vds2 ); - //shadow += getShadow(index, pos.xyz, vds + vds + vds2 ); - //shadow += getShadow(index, pos.xyz, - vds - vds + vds2 ); - //shadow += getShadow(index, pos.xyz, vds - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, vds + vds2 + vds2); - //shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2); - //shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2); - //shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10; - spot *= mix(1., shadow / 11., shadow_on); - }*/ - //spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation)); - //li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n); - //si += spot * qgl_Light[index].color.rgb * shm_diff * light_specular(0, ldir, n, halfV, v, sh_pow); + spot = step(1.001E-6, NdotL) * qgl_light_parameter[index].intensity; +#ifdef SPOT + float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); + spot *= scos * step(qgl_light_parameter[index].endAngleCos, scos); + spot *= smoothstep(qgl_light_parameter[index].endAngleCos, qgl_light_parameter[index].startAngleCos, scos); + /*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz; + //bn = normalize(cross(lwdir, vec3(1, 0, 0))); + //bn2 = normalize(cross(lwdir, bn)); + float ds = ldist/200.;//max(abs(sdist) / 5000, 0.02); + //spot *= clamp(1. - sdist, 0, 1); + vds = ds * bn.xyz; + vds2 = ds * bn2.xyz; + float shadow = getShadow(index, pos.xyz, vec3(0)) * 3.; + shadow += getShadow(index, pos.xyz, vds ) * 2.; + shadow += getShadow(index, pos.xyz, - vds ) * 2.; + shadow += getShadow(index, pos.xyz, - vds2 ) * 2.; + shadow += getShadow(index, pos.xyz, + vds2 ) * 2.; + //shadow += getShadow(index, pos.xyz, vds - vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, vds + vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, - vds - vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, - vds + vds2 ) * 1.5; + //shadow += getShadow(index, pos.xyz, vds + vds ); + //shadow += getShadow(index, pos.xyz, - vds - vds ); + //shadow += getShadow(index, pos.xyz, - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, + vds2 + vds2); + //shadow += getShadow(index, pos.xyz, vds + vds - vds2 ); + //shadow += getShadow(index, pos.xyz, - vds - vds - vds2 ); + //shadow += getShadow(index, pos.xyz, vds + vds + vds2 ); + //shadow += getShadow(index, pos.xyz, - vds - vds + vds2 ); + //shadow += getShadow(index, pos.xyz, vds - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, vds + vds2 + vds2); + //shadow += getShadow(index, pos.xyz, - vds - vds2 - vds2); + //shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2); + //shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10; + spot *= mix(1., shadow / 11., shadow_on);*/ +#endif + spot /= (qgl_light_parameter[index].constantAttenuation + + ldist * (qgl_light_parameter[index].linearAttenuation + + ldist * qgl_light_parameter[index].quadraticAttenuation)); float NdotLs = NdotL*NdotL; float NdotHs = NdotH*NdotH; @@ -106,7 +106,6 @@ void main(void) { pos.w = 1; pos.xyz = view_dir * z; - //pos.z = -pos.z; vec3 v = normalize(-pos.xyz); //vec2 sp = gl_FragCoord.xy * dt * 2 - vec2(1, 1); @@ -127,14 +126,14 @@ void main(void) { li = vec3(0.);//qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; si = vec3(0.); for (int i = 0; i < lights_count; ++i) - calcLight(i, normal, v); - // calcLight(0, n, v, v2); - - //calcLight(0, normal, v); + calcLight(lights_start + i, normal, v); - qgl_FragColor.rgb = max(vec3(0), li * diffuse + si * specular + emission); + vec4 result = vec4(max(vec3(0), li * diffuse + si * specular + emission), 1); +#ifndef FIRST_PASS + result += texelFetch(tex_sum, tc, 0); +#endif + qgl_FragColor = result; //qgl_FragColor.rgb = vec3(1); - qgl_FragColor.a = 1; //qgl_FragData[4] = vec4(speed.xy, bn.yz);