From 104a7f99ad934256393796a3e38327aa0f268126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B5=D0=BB=D0=B8=D0=BF=D0=B5=D0=BD=D0=BA=D0=BE=20?= =?UTF-8?q?=D0=98=D0=B2=D0=B0=D0=BD?= Date: Fri, 20 Nov 2015 21:19:36 +0000 Subject: [PATCH] git-svn-id: svn://db.shs.com.ru/libs@44 a8b55f48-bf90-11e4-a774-851b48703e85 --- qglview/glframebuffer.cpp | 15 +- qglview/glframebuffer.h | 1 + qglview/glmaterial.cpp | 231 ++++++++++ qglview/glmaterial.h | 136 ++++++ qglview/globject.cpp | 42 +- qglview/globject.h | 6 +- qglview/glparticles_system.cpp | 2 +- qglview/glparticles_system.h | 2 +- qglview/glprimitives.cpp | 4 +- qglview/glprimitives.h | 4 +- qglview/glrendererbase.cpp | 224 ++++++++++ qglview/glrendererbase.h | 68 +++ qglview/glshaders.cpp | 211 +++++++++ qglview/glshaders.h | 36 ++ qglview/gltexture_manager.h | 2 +- qglview/gltypes.cpp | 459 ++------------------ qglview/gltypes.h | 165 +------ qglview/glvbo.cpp | 97 ++++- qglview/glvbo.h | 6 +- qglview/loader_3ds.cpp | 4 +- qglview/loader_ase.cpp | 16 +- qglview/loader_dae.cpp | 8 +- qglview/loader_obj.cpp | 10 +- qglview/mainwindow.cpp | 14 +- qglview/mainwindow.ui | 4 +- qglview/material_editor.cpp | 105 ++--- qglview/material_editor.h | 8 +- qglview/material_editor.ui | 592 +++++++++++--------------- qglview/material_map_editor.cpp | 72 ++++ qglview/material_map_editor.h | 54 +++ qglview/material_map_editor.ui | 165 +++++++ qglview/qglview.cpp | 77 ++-- qglview/qglview.h | 7 +- qglview/renderer_deferred_shading.cpp | 150 +++++-- qglview/renderer_deferred_shading.h | 21 +- qglview/renderer_simple.cpp | 9 +- qglview/rope_system.cpp | 2 +- qglview/rope_system.h | 2 +- qglview/shaders/dsl_pass_0.frag | 60 +-- qglview/shaders/dsl_pass_0.vert | 45 +- qglview/shaders/dsl_pass_1.frag | 64 +-- qglview/shaders/dsl_pass_1.vert | 13 +- qglview/shaders/selection.frag | 4 +- qglview/shaders/selection.vert | 4 +- qglview/shaders/selection_halo.frag | 13 +- qglview/shaders/selection_halo.vert | 6 +- qglview/water_system.cpp | 2 +- qglview/water_system.h | 4 +- 48 files changed, 1973 insertions(+), 1273 deletions(-) create mode 100644 qglview/glmaterial.cpp create mode 100644 qglview/glmaterial.h create mode 100644 qglview/glrendererbase.cpp create mode 100644 qglview/glrendererbase.h create mode 100644 qglview/glshaders.cpp create mode 100644 qglview/glshaders.h create mode 100644 qglview/material_map_editor.cpp create mode 100644 qglview/material_map_editor.h create mode 100644 qglview/material_map_editor.ui diff --git a/qglview/glframebuffer.cpp b/qglview/glframebuffer.cpp index 37d15fd..6409bad 100644 --- a/qglview/glframebuffer.cpp +++ b/qglview/glframebuffer.cpp @@ -87,7 +87,7 @@ void GLFramebuffer::bind() { QVector buffers; for (int i = 0; i < colors.size(); ++i) buffers << GL_COLOR_ATTACHMENT0 + i; - glDrawBuffers(colors.size(), buffers.constData()); + glDrawBuffers(buffers.size(), buffers.constData()); glReadBuffer(GL_COLOR_ATTACHMENT0); //glDrawBuffer(GL_COLOR_ATTACHMENT0); glViewport(0, 0, wid, hei); @@ -105,9 +105,10 @@ void GLFramebuffer::release() { void GLFramebuffer::setWriteBuffers(int indeces[]) { QVector buffers; - for (uint i = 0; i < sizeof(indeces); ++i) + for (uint i = 0; i < sizeof(indeces); ++i) { buffers << GL_COLOR_ATTACHMENT0 + indeces[i]; - glDrawBuffers(colors.size(), buffers.constData()); + } + glDrawBuffers(buffers.size(), buffers.constData()); } @@ -115,7 +116,7 @@ void GLFramebuffer::setWriteBuffers(int * indeces, int count) { QVector buffers; for (int i = 0; i < count; ++i) buffers << GL_COLOR_ATTACHMENT0 + indeces[i]; - glDrawBuffers(colors.size(), buffers.constData()); + glDrawBuffers(buffers.size(), buffers.constData()); } @@ -127,3 +128,9 @@ void GLFramebuffer::bindColorTextures() { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); } } + + +void GLFramebuffer::bindDepthTexture(int channel) { + glActiveTextureChannel(channel); + glBindTexture(GL_TEXTURE_2D, tex_d); +} diff --git a/qglview/glframebuffer.h b/qglview/glframebuffer.h index 951abcc..a048114 100644 --- a/qglview/glframebuffer.h +++ b/qglview/glframebuffer.h @@ -47,6 +47,7 @@ public: void copyDepthFrom(GLuint tex) {;} void bindColorTextures(); + void bindDepthTexture(int channel); private: bool is_depth, is_changed; diff --git a/qglview/glmaterial.cpp b/qglview/glmaterial.cpp new file mode 100644 index 0000000..f7e8aed --- /dev/null +++ b/qglview/glmaterial.cpp @@ -0,0 +1,231 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#include "gltypes.h" +#include "qglview.h" + +GLTextureManager * currentGLTextureManager; +QStringList GLTextureManagerBase::search_pathes("."); + + +bool GLCubeTexture::create() { + //qDebug("create"); + destroy(); + glGenTextures(1, &id_); + glBindTexture(GL_TEXTURE_CUBE_MAP, id_); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + //glClearError(); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + //qDebug() << glGetError(); + changed_ = false; + return id_ > 0; +} + + +void GLCubeTexture::load() { + if (isEmpty()) return; + create(); + if (!path(0).isEmpty()) loadFront(path(0)); + if (!path(1).isEmpty()) loadBack(path(1)); + if (!path(2).isEmpty()) loadLeft(path(2)); + if (!path(3).isEmpty()) loadRight(path(3)); + if (!path(4).isEmpty()) loadTop(path(4)); + if (!path(5).isEmpty()) loadBottom(path(5)); +} + + +void GLCubeTexture::loadFromDirectory(const QString & dir) { + QDir d(dir); QFileInfoList sl; + sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath()); + sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath()); +} + + +void GLCubeTexture::loadPathesFromDirectory(const QString & dir) { + QDir d(dir); QFileInfoList sl; + sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath(); + sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath(); +} + + + +GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership, bool bump) { + QString p = findFile(path, search_pathes); + if (p.isEmpty()) return 0; + int tid = ((GLTextureManagerBase*)currentGLTextureManager)->textureID(p, bump); + if (tid > 0) { + //qDebug() << "[TextureManager] Found" << path << "as" << tid; + return tid; + } + QImage image(p); + if (bump) convertToNormal(image); + //qDebug() << p << image.width() << image.height() << image.format() << bump; + tid = currentQGLView->bindTexture(image, GL_TEXTURE_2D/*, GL_RGBA, QGLContext::MipmapBindOption*/); + if (tid == 0) { + qDebug() << "[TextureManager] Can`t load" << p; + return tid; + } + qDebug() << "[TextureManager] Loaded" << p << "as" << tid; + if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids[bump ? 1 : 0].insert(p, tid); + return tid; +} + + +GLuint GLTextureManagerBase::loadTexture(const QImage & im, bool ownership, bool bump) { + if (im.isNull()) return 0; + QImage image(im); + if (bump) convertToNormal(image); + GLuint tid = currentQGLView->bindTexture(image, GL_TEXTURE_2D); + if (tid == 0) { + qDebug() << "[TextureManager] Can`t load image"; + return tid; + } + //qDebug() << "[TextureManager] Loaded image as" << tid; + if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids[bump ? 1 : 0].insert(QString(), tid); + return tid; +} + +Vector3d colorVector(QRgb c) {return Vector3d(((uchar*)(&c))[0] / 255., ((uchar*)(&c))[1] / 255., ((uchar*)(&c))[2] / 255.);} + +void GLTextureManagerBase::convertToNormal(QImage & im) { + if (im.isNull()) return; + QImage sim = im.convertToFormat(QImage::Format_ARGB32); + double sum[3] = {0., 0., 0.}; + llong a = 0; + const uchar * sd = sim.constBits(); + for (int i = 0; i < sim.height(); i++) { + for (int j = 0; j < sim.width(); j++) { + sum[2] += double(sd[a]) / 255. - 0.5; ++a; + sum[1] += double(sd[a]) / 255. - 0.5; ++a; + sum[0] += double(sd[a]) / 255. - 0.5; ++a; + ++a; + } + } + double wh = sim.width() * sim.height(); + sum[0] /= wh; + sum[1] /= wh; + sum[2] /= wh; + qDebug() << sum[0] << sum[1] << sum[2]; + if ((qAbs(sum[0]) <= 0.05) && (qAbs(sum[1]) <= 0.05) && (sum[2] >= 0.4)) /// already normal + return; + qDebug() << "convert to bump"; + QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32); + int tx, ty, w = sim.width(), h = sim.height(); + a = 0; + uchar * dd = dim.bits(); + for (int i = 0; i < sim.height(); i++) { + for (int j = 0; j < sim.width(); j++) { + tx = j - 1; + tx = tx < 0 ? w + tx : tx % w; + ty = i - 1; + ty = ty < 0 ? h + ty : ty % h; + Vector3d p[3], res; + p[0] = colorVector(sim.pixel(j, i)); + p[1] = colorVector(sim.pixel(j, ty)); + p[2] = colorVector(sim.pixel(tx, i)); + res.y = piClamp(0.5 + (p[0].length() - p[1].length()) / 2., 0., 1.); + res.x = piClamp(0.5 + (p[0].length() - p[2].length()) / 2., 0., 1.); + tx = (j + 1) % w; + ty = (i + 1) % h; + p[1] = colorVector(sim.pixel(j, ty)); + p[2] = colorVector(sim.pixel(tx, i)); + res.y = piClamp(0.5 + (p[0].length() - p[1].length()) / 2., 0., 1.); + res.x = piClamp(0.5 + (p[0].length() - p[2].length()) / 2., 0., 1.); + res.z = 1.; + dd[a] = res.z * 255; ++a; + dd[a] = res.x * 255; ++a; + dd[a] = res.y * 255; ++a; + dd[a] = 255; ++a; + } + } + im = dim; + //im.save("_bump.png"); +} + + + + +Material::Material(): map_reflection(512) { + color_diffuse = color_specular = Qt::white; + color_self_illumination = Qt::black; + glass = false; + transparency = reflectivity = 0.f; + roughness = 0.5f; + iof = 1.f; + dispersion = 0.05f; + specular = 1.f; +} + + +void Material::apply(QGLShaderProgram * prog) { + if (prog) { + setUniformMaterial(prog, *this); + } else { + GLfloat mat_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + GLfloat mat_specular[4] = {0.9f, 0.9f, 0.9f, 1.0f}; + GLfloat mat_emission[4] = {0.f, 0.f, 0.f, 1.0f}; + mat_diffuse[0] = color_diffuse.redF(); + mat_diffuse[1] = color_diffuse.greenF(); + mat_diffuse[2] = color_diffuse.blueF(); + mat_diffuse[3] = color_diffuse.alphaF() * (1.f - transparency); + mat_specular[0] = specular * color_specular.redF(); + mat_specular[1] = specular * color_specular.greenF(); + mat_specular[2] = specular * color_specular.blueF(); + mat_emission[0] = color_self_illumination.redF(); + mat_emission[1] = color_self_illumination.greenF(); + mat_emission[2] = color_self_illumination.blueF(); + glColor4f(mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]); + glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); + glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); + glMaterialf(GL_FRONT, GL_SHININESS, (1. - roughness)*100.); + glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); + glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse); + } +} + + +void Material::loadTextures(GLTextureManagerBase * tm) { + //qDebug() << "load textures"; + if (tm == 0) tm = (GLTextureManagerBase*)currentGLTextureManager; + if (!map_diffuse.bitmap_path.isEmpty()) map_diffuse.bitmap_id = tm->loadTexture(map_diffuse.bitmap_path); + if (!map_bump.bitmap_path.isEmpty()) map_bump.bitmap_id = tm->loadTexture(map_bump.bitmap_path, true, true); + if (!map_relief.bitmap_path.isEmpty()) map_relief.bitmap_id = tm->loadTexture(map_relief.bitmap_path); + if (!map_roughness.bitmap_path.isEmpty()) map_roughness.bitmap_id = tm->loadTexture(map_roughness.bitmap_path); + if (!map_specular.bitmap_path.isEmpty()) map_specular.bitmap_id = tm->loadTexture(map_specular.bitmap_path); + if (!map_self_illumination.bitmap_path.isEmpty()) map_self_illumination.bitmap_id = tm->loadTexture(map_self_illumination.bitmap_path); + //if (!map_diffuse_2.bitmap_path.isEmpty()) map_diffuse_2.bitmap_id = tm->loadTexture(map_diffuse_2.bitmap_path); + map_reflection.load(); +} diff --git a/qglview/glmaterial.h b/qglview/glmaterial.h new file mode 100644 index 0000000..637399d --- /dev/null +++ b/qglview/glmaterial.h @@ -0,0 +1,136 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#ifndef GLMATERIAL_H +#define GLMATERIAL_H + +#include "gltypes.h" + +class GLTexture { +public: + GLTexture(int _width, int _height, const GLenum & _format = GL_RGBA8, const GLenum & _target = GL_TEXTURE_2D) {wid = _width; hei = _height; format_ = _format; target_ = _target; id_ = 0;} + bool create() {destroy(); createGLTexture(id_, wid, hei, format_, target_); return id_ > 0;} + void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} + void bind() {if (id_ > 0) glBindTexture(target_, id_);} + void release() {glBindTexture(target_, 0);} + int width() const {return wid;} + int height() const {return hei;} + GLenum format() const {return format_;} + GLenum target() const {return target_;} + GLuint id() const {return id_;} +private: + int wid, hei; + GLenum format_, target_; + GLuint id_; +}; + + +class GLCubeTexture { +public: + GLCubeTexture(int _size, const GLenum & _format = GL_RGBA8) {size = _size; format_ = _format; id_ = 0; changed_ = false; pathes.resize(6);} + bool create(); + void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} + void bind() {if (changed_) {changed_ = false; create();} if (id_ > 0) glBindTexture(GL_TEXTURE_CUBE_MAP, id_);} + void release() {glBindTexture(GL_TEXTURE_CUBE_MAP, 0);} + void resize(int _size) {size = _size; changed_ = true;} + void loadFromDirectory(const QString & dir); + void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);} + void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);} + void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);} + void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);} + void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);} + void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);} + void load(); + bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;} + GLenum format() const {return format_;} + void setFormat(GLenum f) {format_ = f; changed_ = true;} + GLuint id() const {return id_;} + const QString & path(int side) const {return pathes[side];} + void setPath(int side, const QString & p) {pathes[side] = p;} + void loadPathesFromDirectory(const QString & dir); +private: + bool changed_; + int size; + GLenum format_; + GLuint id_; + QVector pathes; +}; + +class GLTextureManager; + +class GLTextureManagerBase { +public: + static void addSearchPath(const QString & path) {search_pathes << path;} + static QStringList searchPathes() {return search_pathes;} + static GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); + static GLuint loadTexture(const QImage & image, bool ownership = true, bool bump = false); + int textureID(const QString & path, bool bump = false) {return tex_ids[bump ? 1 : 0][path];} + +protected: + static void convertToNormal(QImage & im); + static QStringList search_pathes; + QMap tex_ids[2]; + +}; + +extern GLTextureManager * currentGLTextureManager; + +struct Map { + Map() {bitmap_id = 0; color_amount = 1.f; color_offset = 0.f; animation_frame_rate = -1.f;} + QString bitmap_path; + GLuint bitmap_id; + QPointF bitmap_offset; + float color_amount; + float color_offset; + QString animation; + float animation_frame_rate; +}; + +struct Material { + Material(); + void apply(QGLShaderProgram * prog); + void loadTextures(GLTextureManagerBase * tm = 0); + QString name; + QColor color_diffuse; + QColor color_specular; + QColor color_self_illumination; + bool glass; + float roughness; + float specular; + float transparency; + float reflectivity; + float iof; + float dispersion; + Map map_diffuse; + Map map_bump; + Map map_relief; + Map map_self_illumination; + Map map_roughness; + Map map_specular; + /*Map map_diffuse_2; + Map map_diffuse_3; + Map map_diffuse_4;*/ + GLCubeTexture map_reflection; +}; + +inline QDataStream & operator <<(QDataStream & s, const Map & m) {s << m.bitmap_path << m.color_amount << m.color_offset << m.animation << m.animation_frame_rate; return s;} +inline QDataStream & operator >>(QDataStream & s, Map & m) {s >> m.bitmap_path >> m.color_amount >> m.color_offset >> m.animation >> m.animation_frame_rate; return s;} +inline QDataStream & operator <<(QDataStream & s, const Material & m) {s << m.name << m.color_diffuse << m.color_specular << m.color_self_illumination << m.roughness << m.specular << m.transparency << m.reflectivity << m.glass << m.map_diffuse << m.map_bump << m.map_relief << m.map_specular << m.map_roughness; return s;} +inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.name >> m.color_diffuse >> m.color_specular >> m.color_self_illumination >> m.roughness >> m.specular >> m.transparency >> m.reflectivity >> m.glass >> m.map_diffuse >> m.map_bump >> m.map_relief >> m.map_specular >> m.map_roughness; return s;} + +#endif // GLMATERIAL_H diff --git a/qglview/globject.cpp b/qglview/globject.cpp index 6de3007..9c96e57 100644 --- a/qglview/globject.cpp +++ b/qglview/globject.cpp @@ -77,8 +77,8 @@ GLObjectBase * GLObjectBase::clone(bool withChildren) { return o; } -void GLObjectBase::draw(bool simplest) { - vbo.draw(geom_prim, simplest); +void GLObjectBase::draw(QGLShaderProgram * prog, bool simplest) { + vbo.draw(geom_prim, prog, simplest); /*if (!d_vertices.isEmpty()) { glBindBuffer(GL_ARRAY_BUFFER, 0); glVertexPointer(3, GL_FLOAT, 0, d_vertices.constData()); @@ -147,7 +147,7 @@ void GLObjectBase::buildTransform() { itransform_.setToIdentity(); GLObjectBase * p = parent_; if (p != 0) - itransform_ *= p->itransform_; + itransform_ = p->itransform_; if (raw_matrix) { itransform_.translate(pos_); itransform_ *= mat_; @@ -159,6 +159,7 @@ void GLObjectBase::buildTransform() { itransform_.rotate(angles_.x(), 1., 0., 0.); itransform_.scale(scale_); } + //qDebug() << name_ << itransform_; foreach (GLObjectBase * i, children_) i->buildTransform(); } @@ -170,29 +171,36 @@ void GLObjectBase::checkPass() { } +QMatrix4x4 GLObjectBase::worldMatrix(QMatrix4x4 parent) const { + QMatrix4x4 mat; + mat.translate(pos_); + if (raw_matrix) { + mat *= mat_; + } else { + if (angles_.z() != 0.) mat.rotate(angles_.z(), 0., 0., 1.); + if (angles_.y() != 0.) mat.rotate(angles_.y(), 0., 1., 0.); + if (angles_.x() != 0.) mat.rotate(angles_.x(), 1., 0., 0.); + mat.scale(scale_); + } + return parent * mat; +} + + void GLObjectBase::render(int * id, QMap * ids, int sh_id_loc) { if (!visible_) return; - glPushMatrix(); - if (pos_.x() != 0. || pos_.y() != 0. || pos_.z() != 0.) glTranslated(pos_.x(), pos_.y(), pos_.z()); - if (raw_matrix) { - qglMultMatrix(mat_); - } else { - if (angles_.z() != 0.) glRotated(angles_.z(), 0., 0., 1.); - if (angles_.y() != 0.) glRotated(angles_.y(), 0., 1., 0.); - if (angles_.x() != 0.) glRotated(angles_.x(), 1., 0., 0.); - if (scale_.x() != 1. || scale_.y() != 1. || scale_.z() != 1.) glScaled(scale_.x(), scale_.y(), scale_.z()); - } - material_.apply(); + //glPushMatrix(); + ///qglMultMatrix TODO + material_.apply(0); if (id != 0) { ++(*id); ids->insert(*id, this); //glVertexAttrib1f(sh_id_loc, (*id) / 255.f); //qDebug() << "assign to" << sh_id_loc << (*id) / 255.f; } - draw(); + draw(0); foreach (GLObjectBase * i, children_) i->render(id, ids, sh_id_loc); - glPopMatrix(); + //glPopMatrix(); } @@ -217,7 +225,7 @@ GLObjectBase * Light::clone(bool withChildren) { } -void Light::draw(bool simplest) { +void Light::draw(QGLShaderProgram * prog, bool simplest) { bool l = glIsEnabled(GL_LIGHTING); glDisable(GL_LIGHTING); glPointSize(8.); diff --git a/qglview/globject.h b/qglview/globject.h index 57be2e3..0b1dcd7 100644 --- a/qglview/globject.h +++ b/qglview/globject.h @@ -21,6 +21,7 @@ #include "glvbo.h" #include "glframebuffer.h" +#include "glmaterial.h" class GLObjectBase { @@ -41,7 +42,7 @@ public: void setName(const QString & name) {name_ = name;} //virtual GLuint hList() {return list;} virtual void init() {calculateBoundingBox(); vbo.init(); vbo.rebuffer(); /*material_.reflection.create();*/ /*qDebug() << "init" << vbo.buffer_;*/ is_init = true;} - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); virtual void update() {} bool isInit() const {return is_init;} bool isTexturesLoaded() const {return is_tex_loaded;} @@ -180,6 +181,7 @@ protected: void initInternal() {init(); loadTextures(); foreach (GLObjectBase * i, children_) i->initInternal();} void render(int * id = 0, QMap * ids = 0, int sh_id_loc = 0); void checkPass(); + QMatrix4x4 worldMatrix(QMatrix4x4 parent) const; int pass_; // Pass bool is_init, is_tex_loaded, accept_light, accept_fog, /*write_depth_,*/ visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix; @@ -214,7 +216,7 @@ public: Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; pos_ = p; intensity = i; /*color_ = c;*/ decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);} virtual GLObjectBase * clone(bool withChildren = true); virtual void init() {shadow_map.resize(512, 512); is_init = true;} - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); QVector3D direction; GLdouble angle_spread; diff --git a/qglview/glparticles_system.cpp b/qglview/glparticles_system.cpp index 17f088f..08c45a0 100644 --- a/qglview/glparticles_system.cpp +++ b/qglview/glparticles_system.cpp @@ -107,7 +107,7 @@ void GLParticlesSystem::update() { } -void GLParticlesSystem::draw(bool) { +void GLParticlesSystem::draw(QGLShaderProgram * prog, bool) { if (particles.isEmpty()) return; if (view_ == 0) return; pass_ = GLObjectBase::Transparent; diff --git a/qglview/glparticles_system.h b/qglview/glparticles_system.h index 9b0d26f..a8b64df 100644 --- a/qglview/glparticles_system.h +++ b/qglview/glparticles_system.h @@ -47,7 +47,7 @@ public: }; void update(); - void draw(bool); + void draw(QGLShaderProgram * prog, bool); float birthRate() const {return birthRate_;} float lifeDuration() const {return lifeDuration_;} diff --git a/qglview/glprimitives.cpp b/qglview/glprimitives.cpp index a099cb2..1c20be1 100644 --- a/qglview/glprimitives.cpp +++ b/qglview/glprimitives.cpp @@ -19,7 +19,7 @@ #include "glprimitives.h" -void GLPrimitivePoint::draw(bool simplest) { +void GLPrimitivePoint::draw(QGLShaderProgram * prog, bool simplest) { glPointSize(sz); glColor3f(material_.color_diffuse.redF(), material_.color_diffuse.greenF(), material_.color_diffuse.blueF()); glBegin(GL_POINTS); @@ -29,7 +29,7 @@ void GLPrimitivePoint::draw(bool simplest) { -void GLPrimitiveLine::draw(bool simplest) { +void GLPrimitiveLine::draw(QGLShaderProgram * prog, bool simplest) { glColor3f(material_.color_diffuse.redF(), material_.color_diffuse.greenF(), material_.color_diffuse.blueF()); glBegin(GL_LINES); glVertex3d(p0.x(), p0.y(), p0.z()); diff --git a/qglview/glprimitives.h b/qglview/glprimitives.h index f0128d1..7ee8afd 100644 --- a/qglview/glprimitives.h +++ b/qglview/glprimitives.h @@ -26,7 +26,7 @@ class GLPrimitivePoint: public GLObjectBase { public: GLPrimitivePoint(double size = 1., QVector3D pos = QVector3D()) {sz = 8.;} - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); private: double sz; }; @@ -38,7 +38,7 @@ class GLPrimitiveLine: public GLObjectBase { public: GLPrimitiveLine(QVector3D p0_ = QVector3D(), QVector3D p1_ = QVector3D()) {p0 = p0_; p1 = p1_;} - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); QVector3D point0() const {return p0;} QVector3D point1() const {return p1;} void setPoint0(const QVector3D & p) {p0 = p;} diff --git a/qglview/glrendererbase.cpp b/qglview/glrendererbase.cpp new file mode 100644 index 0000000..7d31cca --- /dev/null +++ b/qglview/glrendererbase.cpp @@ -0,0 +1,224 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#include "glrendererbase.h" +#include "globject.h" +#include "qglview.h" + + +GLRendererBase::GLRendererBase(QGLView * view_): view(*view_) { + white_image = QImage(1, 1, QImage::Format_ARGB32); + white_image.fill(0xFFFFFFFF); + white_image_id = 0; +} + + +void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) { + QVector3D lp = l.worldPos(), ld = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized(); + GLfloat pos[] = {0.f, 0.f, 0.f, 0.f}; + GLfloat dir[] = {0.f, 0.f, 0.f}; + GLfloat col[] = {0.f, 0.f, 0.f}; + pos[0] = l.light_type == Light::Directional ? -l.direction.x() : lp.x(); + pos[1] = l.light_type == Light::Directional ? -l.direction.y() : lp.y(); + pos[2] = l.light_type == Light::Directional ? -l.direction.z() : lp.z(); + pos[3] = l.light_type == Light::Directional ? 0. : 1.; + dir[0] = ld.x(); + dir[1] = ld.y(); + dir[2] = ld.z(); + col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.; + col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.; + col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.; + glEnable(gl_index); + //glLightfv(gl_index, GL_AMBIENT, ambient); + glLightfv(gl_index, GL_DIFFUSE, col); + glLightfv(gl_index, GL_SPECULAR, col); + glLightfv(gl_index, GL_POSITION, pos); + glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const); + glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear); + glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic); + if (l.light_type == Light::Cone) { + glLightfv(gl_index, GL_SPOT_DIRECTION, dir); + glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_spread); + glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp); + } else { + glLightf(gl_index, GL_SPOT_CUTOFF, 180.); + } + +} + + +void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) { + GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f}; + if (first_pass) { + ambient[0] = view.ambientColor_.redF(); + ambient[1] = view.ambientColor_.greenF(); + ambient[2] = view.ambientColor_.blueF(); + } + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); +} + + +void GLRendererBase::setupShadersLights(int lights_count) { + /*foreach (QGLShaderProgram * i, view.shaders_ppl) { + i->bind(); + i->setUniformValue("lightsCount", lights_count); + i->setUniformValue("acc_light", lights_count > 0); + //i->setUniformValue("mat", mvm); + }*/ +} + + +#define BIND_TEXTURE(ch, map) if (rp.prev_tex[ch] != mat.map.bitmap_id) { \ + rp.prev_tex[ch] = mat.map.bitmap_id; \ + glActiveTextureChannel(ch); glBindTexture(GL_TEXTURE_2D, mat.map.bitmap_id); \ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_);} + +void GLRendererBase::setupTextures(GLObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) { + if (first_object) { + glReleaseTextures(); + return; + } + setupShadersTextures(o, rp); + Material & mat(o.material_); + if (rp.light) { + if (o.accept_light) {if (!rp.prev_light) {glSetLightEnabled(true); rp.prev_light = true;}} + else {if (rp.prev_light) {glSetLightEnabled(false); rp.prev_light = false;}} + } + if (rp.fog) { + if (o.accept_fog) {if (!rp.prev_fog) {glSetFogEnabled(true); rp.prev_fog = true;}} + else {if (rp.prev_fog) {glSetFogEnabled(false); rp.prev_fog = false;}} + } + if (rp.textures) { + BIND_TEXTURE(0, map_diffuse); + BIND_TEXTURE(1, map_bump); + BIND_TEXTURE(2, map_relief); + BIND_TEXTURE(3, map_self_illumination); + BIND_TEXTURE(4, map_roughness); + BIND_TEXTURE(5, map_specular); + glActiveTextureChannel(0); + } +} + +#undef BIND_TEXTURE + + +void GLRendererBase::setupLights(int pass, int lights_per_pass) { + int light_start, light_end, lmax; + light_start = pass * lights_per_pass; + light_end = qMin((pass + 1) * lights_per_pass, view.lights_.size()); + setupAmbientLight(view.ambientColor_, pass == 0); + if (!view.lights_.isEmpty()) { + setupShadersLights(light_end - light_start); + for (int i = light_start; i < light_end; ++i) + setupLight(*view.lights_[i], i - light_start, GL_LIGHT0 + i - light_start); + lmax = light_start + 8; + for (int i = light_end; i < lmax; ++i) + glDisable(GL_LIGHT0 + i - light_start); + } else { + setupShadersLights(0); + for (int i = 0; i < 8; ++i) + glDisable(GL_LIGHT0 + i); + } +} + + +void GLRendererBase::applyFilteringParameters() { + if (view.linearFiltering_) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_); +} + + +void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) { + RenderingParameters rp; + rp.pass = pass; + rp.light_pass = light_pass; + rp.shaders = shaders; + rp.textures = textures; + rp.light = rp.prev_light = light; + rp.fog = rp.prev_fog = fog; + rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + //qDebug() << "view:" << rp.view_matrix; + for (int i = 0; i < 32; ++i) rp.prev_tex[i] = 0; + setupTextures(view.objects_, rp, true); + glSetLightEnabled(rp.prev_light); + glSetFogEnabled(rp.prev_fog); + glSetCapEnabled(GL_TEXTURE_2D, rp.textures); + glSetCapEnabled(GL_BLEND, pass == GLObjectBase::Transparent); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_CUBE_MAP); + glPushMatrix(); + renderSingleObject(view.objects_, rp); + glPopMatrix(); +} + + +void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & rp) { + if (!o.isInit()) + o.init(); + if (!o.isTexturesLoaded()) + o.loadTextures(); + if (!o.visible_) return; + if (rp.pass == o.pass_) { + Material & mat(o.material_); + QMatrix4x4 curview = rp.view_matrix * o.itransform_; + setupTextures(o, rp, false); + mat.apply((QGLShaderProgram*)rp.shaders); + glSetPolygonMode(o.render_mode != GLObjectBase::View ? o.render_mode : (view.rmode != GLObjectBase::View ? view.rmode : GL_FILL)); + glLineWidth(o.line_width > 0. ? o.line_width : view.lineWidth_); + glPointSize(o.line_width > 0. ? o.line_width : view.lineWidth_); + o.update(); + if (o.pass_ == GLObjectBase::Transparent) { + glActiveTextureChannel(3); + if (mat.reflectivity > 0.) { + glEnable(GL_TEXTURE_CUBE_MAP); + if (!mat.map_reflection.isEmpty()) mat.map_reflection.bind(); + else glDisable(GL_TEXTURE_CUBE_MAP); + } else glDisable(GL_TEXTURE_CUBE_MAP); + if (rp.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP); + GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity}; + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); + glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc); + glGetFloatv(GL_MODELVIEW_MATRIX, gm); + glMatrixMode(GL_TEXTURE); + glLoadTransposeMatrixf(gm); + glScalef(-1., -1., -1.); + glMatrixMode(GL_MODELVIEW); + glActiveTextureChannel(0); + } + if (rp.shaders) { + //qDebug() << o.name() << curview << curview.determinant(); + setUniformMatrices((QGLShaderProgram*)rp.shaders, rp.proj_matrix, curview); + } else { + glMatrixMode(GL_MODELVIEW); + setGLMatrix(curview); + } + o.draw((QGLShaderProgram*)rp.shaders); + } + foreach (GLObjectBase * i, o.children_) + renderSingleObject(*i, rp); +} diff --git a/qglview/glrendererbase.h b/qglview/glrendererbase.h new file mode 100644 index 0000000..12327fe --- /dev/null +++ b/qglview/glrendererbase.h @@ -0,0 +1,68 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#ifndef GLRENDERERBASE_H +#define GLRENDERERBASE_H + +#include "glshaders.h" + +class GLRendererBase: public QObject +{ + friend class QGLView; + Q_OBJECT +public: + GLRendererBase(QGLView * view_); + virtual void renderScene() = 0; + +protected: + struct RenderingParameters { + int pass; + int light_pass; + bool light; + bool fog; + bool textures; + bool prev_light; + bool prev_fog; + GLuint prev_tex[32]; + void * shaders; + QMatrix4x4 view_matrix; + QMatrix4x4 proj_matrix; + QGLShaderProgram * cur_shader; + }; + + virtual void setupLight(const Light & l, int inpass_index, int gl_index); + virtual void setupAmbientLight(const QColor & a, bool first_pass); + virtual void setupShadersLights(int lights_count); + virtual void setupTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false); + virtual void setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) {} + virtual void reloadShaders() {} + virtual void init(int width, int height) {} + virtual void resize(int width, int height) {} + + void setupLights(int pass, int lights_per_pass); + inline void applyFilteringParameters(); + void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); + void renderSingleObject(GLObjectBase & o, RenderingParameters & rp); + + QGLView & view; + QImage white_image; + GLuint white_image_id; + +}; + +#endif // GLRENDERERBASE_H diff --git a/qglview/glshaders.cpp b/qglview/glshaders.cpp new file mode 100644 index 0000000..c9b1f08 --- /dev/null +++ b/qglview/glshaders.cpp @@ -0,0 +1,211 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#include "gltypes.h" +#include "qglview.h" + +const char qgl_vertex_head[] = + "in vec3 _qgl_Vertex;\n" + "in vec3 qgl_Normal;\n" + "in vec2 qgl_Texture;\n" + "in vec4 qgl_Color;\n" + "out vec2 qgl_FragTexture;\n" + "out vec4 qgl_FragColor;\n" + "vec4 qgl_Vertex = vec4(_qgl_Vertex, 1.);\n" + "vec4 qgl_ftransform() {return qgl_ModelViewProjectionMatrix * qgl_Vertex;}\n"; + +const char qgl_fragment_head[] = + "in vec2 qgl_FragTexture;\n" + "in vec4 qgl_FragColor;\n" + "out vec4 qgl_FragData[gl_MaxDrawBuffers];\n"; + +const char qgl_uniform[] = + "uniform mat4 qgl_ModelViewMatrix;\n" + "uniform mat4 qgl_ProjectionMatrix;\n" + "uniform mat4 qgl_ModelViewProjectionMatrix;\n" + "uniform mat3 qgl_NormalMatrix;\n" + "uniform mat4 qgl_ModelViewMatrixInverse;\n" + "uniform mat4 qgl_ProjectionMatrixInverse;\n" + "uniform mat4 qgl_ModelViewProjectionMatrixInverse;\n" + "uniform mat4 qgl_ModelViewMatrixTranspose;\n" + "uniform mat4 qgl_ProjectionMatrixTranspose;\n" + "uniform mat4 qgl_ModelViewProjectionMatrixTranspose;\n" + "uniform mat4 qgl_ModelViewMatrixInverseTranspose;\n" + "uniform mat4 qgl_ProjectionMatrixInverseTranspose;\n" + "uniform mat4 qgl_ModelViewProjectionMatrixInverseTranspose;\n"; + +const char qgl_structs[] = + "const int qgl_MaxLights = 16;\n" + "struct QGLLight {\n" + " vec4 position;\n" + " vec4 color;\n" + " float intensity;\n" + " float constantAttenuation;\n" + " float linearAttenuation;\n" + " float quadraticAttenuation;\n" + "};\n" + "struct QGLMap {\n" + " float offset;\n" + " float amount;\n" + " sampler2D map;\n" + "};\n" + "struct QGLMaterial {\n" + " float roughness;\n" + " float specular;\n" + " float transparency;\n" + " float reflectivity;\n" + " float iof;\n" + " float dispersion;\n" + " vec4 color_diffuse;\n" + " vec4 color_specular;\n" + " vec4 color_self_illumination;\n" + " QGLMap map_diffuse;\n" + " QGLMap map_bump;\n" + " QGLMap map_relief;\n" + " QGLMap map_self_illumination;\n" + " QGLMap map_roughness;\n" + " QGLMap map_specular;\n" + "};\n" + "uniform QGLLight qgl_AmbientLight;\n" + "uniform QGLLight qgl_Light[qgl_MaxLights];\n" + "uniform QGLMaterial qgl_Material;\n"; + + +QString loadShaderFile(QGLShaderProgram * prog, QGLShader::ShaderType type, const QString & file) { + QFile f(file); + if (!f.open(QIODevice::ReadOnly)) return ""; + QString all = QString::fromUtf8(f.readAll()); + int i = all.indexOf("#version"); + QString version = all.mid(i + 8, all.indexOf("\n", i) - i - 8).trimmed(); + if (version.toInt() >= 150) { + int ip = all.indexOf("\n", i); + if (ip < 0) return all; + if (type == QGLShader::Vertex) { + all.insert(ip + 1, qgl_vertex_head); + } + if (type == QGLShader::Fragment) { + all.insert(ip + 1, qgl_fragment_head); + } + all.insert(ip + 1, qgl_structs); + all.insert(ip + 1, qgl_uniform); + } + prog->addShaderFromSourceCode(type, all); + //qDebug() << "********" << all; + return all; +} + + +bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir) { + prog->removeAllShaders(); + QDir d(dir); + QFileInfoList sl; + //qDebug() << "[QGLView] Shader \"" + name + "\" load shaders from" << d.absolutePath(); +#if QT_VERSION >= 0x040700 + sl = d.entryInfoList(QStringList(name + ".geom"), QDir::Files | QDir::NoDotAndDotDot); + foreach (const QFileInfo & i, sl) { + qDebug() << "[QGLView] Shader \"" + name + "\" add geometry shader:" << i.fileName(); + loadShaderFile(prog, QGLShader::Geometry, i.absoluteFilePath()); + } +#endif + sl = d.entryInfoList(QStringList(name + ".vert"), QDir::Files | QDir::NoDotAndDotDot); + foreach (const QFileInfo & i, sl) { + //qDebug() << "[QGLView] Shader \"" + name + "\" add vertex shader:" << i.fileName(); + loadShaderFile(prog, QGLShader::Vertex, i.absoluteFilePath()); + } + sl = d.entryInfoList(QStringList(name + ".frag"), QDir::Files | QDir::NoDotAndDotDot); + foreach (const QFileInfo & i, sl) { + //qDebug() << "[QGLView] Shader \"" + name + "\" add fragment shader:" << i.fileName(); + loadShaderFile(prog, QGLShader::Fragment, i.absoluteFilePath()); + } + if (!prog->link()) { + //qDebug() << "[QGLView] Shader \"" + name + "\" link error: " + prog->log(); + return false; + } + return true; +} + + +void setUniformMatrices(QGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view) { + QMatrix4x4 mvpm = proj * view; + QMatrix3x3 nm = view.normalMatrix(); + prog->setUniformValue("qgl_ModelViewMatrix", view); + prog->setUniformValue("qgl_ProjectionMatrix", proj); + prog->setUniformValue("qgl_ModelViewProjectionMatrix", mvpm); + prog->setUniformValue("qgl_NormalMatrix", nm); + prog->setUniformValue("qgl_ModelViewMatrixTranspose", view.transposed()); + prog->setUniformValue("qgl_ProjectionMatrixTranspose", proj.transposed()); + prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", mvpm.transposed()); +} + + +void setUniformMap(QGLShaderProgram * prog, QString map_name, const Map & map, int channel) { + prog->setUniformValue(("qgl_Material." + map_name + ".offset").toLatin1().constData(), map.color_offset); + prog->setUniformValue(("qgl_Material." + map_name + ".amount").toLatin1().constData(), map.color_amount); + prog->setUniformValue(("qgl_Material." + map_name + ".map").toLatin1().constData(), map.bitmap_id > 0 ? channel : 6); +} + + +void setUniformMaterial(QGLShaderProgram * prog, const Material & mat) { + GLfloat mat_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + mat_diffuse[0] = mat.color_diffuse.redF(); + mat_diffuse[1] = mat.color_diffuse.greenF(); + mat_diffuse[2] = mat.color_diffuse.blueF(); + mat_diffuse[3] = mat.color_diffuse.alphaF() * (1.f - mat.transparency); + glVertexAttrib4f(prog->attributeLocation("qgl_Color"), mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]); + prog->setUniformValue("qgl_Material.roughness", mat.roughness); + prog->setUniformValue("qgl_Material.specular", mat.specular); + prog->setUniformValue("qgl_Material.transparency", mat.transparency); + prog->setUniformValue("qgl_Material.reflectivity", mat.reflectivity); + prog->setUniformValue("qgl_Material.iof", mat.iof); + prog->setUniformValue("qgl_Material.dispersion", mat.dispersion); + prog->setUniformValue("qgl_Material.color_diffuse", mat.color_diffuse); + prog->setUniformValue("qgl_Material.color_self_illumination", mat.color_self_illumination); + prog->setUniformValue("qgl_Material.color_specular", mat.color_specular); + setUniformMap(prog, "map_diffuse", mat.map_diffuse, 0); + setUniformMap(prog, "map_bump", mat.map_bump, 1); + setUniformMap(prog, "map_relief", mat.map_relief, 2); + setUniformMap(prog, "map_self_illumination", mat.map_self_illumination, 3); + setUniformMap(prog, "map_roughness", mat.map_roughness, 4); + setUniformMap(prog, "map_specular", mat.map_specular, 5); + +} + + +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat) { + for (int i = 0; i < lights.size(); ++i) + setUniformLight(prog, lights[i], QString("qgl_Light[%1]").arg(i), mat); +} +/* +" vec3 position;\n" +" vec4 color;\n" +" float intensity;\n" +" float constantAttenuation;\n" +" float linearAttenuation;\n" +" float quadraticAttenuation;\n" +*/ +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat) { + QVector4D pos(light->worldPos(), 1.); + pos = mat * pos; + //qDebug() << "light" << light->name() << ulightn << pos; + prog->setUniformValue((ulightn + ".position").toLatin1().constData(), pos); + prog->setUniformValue((ulightn + ".intensity").toLatin1().constData(), GLfloat(light->intensity)); + prog->setUniformValue((ulightn + ".color").toLatin1().constData(), light->color()); + prog->setUniformValue((ulightn + ".constantAttenuation").toLatin1().constData(), GLfloat(light->decay_const)); + prog->setUniformValue((ulightn + ".linearAttenuation").toLatin1().constData(), GLfloat(light->decay_linear)); + prog->setUniformValue((ulightn + ".quadraticAttenuation").toLatin1().constData(), GLfloat(light->decay_quadratic)); +} diff --git a/qglview/glshaders.h b/qglview/glshaders.h new file mode 100644 index 0000000..ac76f60 --- /dev/null +++ b/qglview/glshaders.h @@ -0,0 +1,36 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#ifndef GLSHADERS_H +#define GLSHADERS_H + +#include "gltypes.h" + +class Map; +class Material; +class Light; + +QString loadShaderFile(QGLShaderProgram * prog, QGLShader::ShaderType type, const QString & file); +bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir = QString()); +void setUniformMatrices(QGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view); +void setUniformMap(QGLShaderProgram * prog, const Map & map, int channel); +void setUniformMaterial(QGLShaderProgram * prog, const Material & mat); +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat); +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat); + +#endif // GLSHADERS_H diff --git a/qglview/gltexture_manager.h b/qglview/gltexture_manager.h index a668ef8..50d91fe 100644 --- a/qglview/gltexture_manager.h +++ b/qglview/gltexture_manager.h @@ -19,7 +19,7 @@ #ifndef GLTEXTUREMANAGER_H #define GLTEXTUREMANAGER_H -#include "gltypes.h" +#include "glmaterial.h" #include #include diff --git a/qglview/gltypes.cpp b/qglview/gltypes.cpp index a1d0ffb..1af680b 100644 --- a/qglview/gltypes.cpp +++ b/qglview/gltypes.cpp @@ -20,11 +20,9 @@ #include "qglview.h" QGLWidget * currentQGLView; -GLTextureManager * currentGLTextureManager; Camera * currentCamera; QMatrix4x4 globCameraMatrix; QMutex globMutex; -QStringList GLTextureManagerBase::search_pathes("."); QString readCharsUntilNull(QDataStream & s) { @@ -74,7 +72,17 @@ QMatrix4x4 getGLMatrix(GLenum matrix) { qreal qm[16]; for (int i = 0; i < 16; ++i) qm[i] = gm[i]; - return QMatrix4x4(qm, 4, 4).transposed(); + return QMatrix4x4(qm).transposed(); +} + + +void setGLMatrix(QMatrix4x4 matrix) { + GLfloat gm[16]; + qreal qm[16]; + matrix.transposed().copyDataTo(qm); + for (int i = 0; i < 16; ++i) + gm[i] = qm[i]; + glLoadMatrixf(gm); } @@ -129,33 +137,16 @@ void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format, } -bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir) { - prog->removeAllShaders(); - QDir d(dir); - QFileInfoList sl; - //qDebug() << "[QGLView] Shader \"" + name + "\" load shaders from" << d.absolutePath(); -#if QT_VERSION >= 0x040700 - sl = d.entryInfoList(QStringList(name + ".geom"), QDir::Files | QDir::NoDotAndDotDot); - foreach (const QFileInfo & i, sl) { - qDebug() << "[QGLView] Shader \"" + name + "\" add geometry shader:" << i.fileName(); - prog->addShaderFromSourceFile(QGLShader::Geometry, i.absoluteFilePath()); - } -#endif - sl = d.entryInfoList(QStringList(name + ".vert"), QDir::Files | QDir::NoDotAndDotDot); - foreach (const QFileInfo & i, sl) { - //qDebug() << "[QGLView] Shader \"" + name + "\" add vertex shader:" << i.fileName(); - prog->addShaderFromSourceFile(QGLShader::Vertex, i.absoluteFilePath()); - } - sl = d.entryInfoList(QStringList(name + ".frag"), QDir::Files | QDir::NoDotAndDotDot); - foreach (const QFileInfo & i, sl) { - //qDebug() << "[QGLView] Shader \"" + name + "\" add fragment shader:" << i.fileName(); - prog->addShaderFromSourceFile(QGLShader::Fragment, i.absoluteFilePath()); - } - if (!prog->link()) { - //qDebug() << "[QGLView] Shader \"" + name + "\" link error: " + prog->log(); - return false; - } - return true; +QMatrix4x4 glMatrixPerspective(double angle, double aspect, double near_, double far_) { + QMatrix4x4 ret; + double t = 1. / (tan(angle * deg2rad / 2.)); + ret(0, 0) = t / aspect; + ret(1, 1) = t; + ret(2, 2) = far_ / (far_ - near_) - 1.; + ret(2, 3) = 2. * far_ * near_ / (far_ - near_); + ret(3, 2) = -1; + ret(3, 3) = 0.; + return ret; } @@ -180,158 +171,6 @@ QImage rotateQImageRight(const QImage & im) { -bool GLCubeTexture::create() { - //qDebug("create"); - destroy(); - glGenTextures(1, &id_); - glBindTexture(GL_TEXTURE_CUBE_MAP, id_); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); - //glClearError(); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - //qDebug() << glGetError(); - changed_ = false; - return id_ > 0; -} - - -void GLCubeTexture::load() { - if (isEmpty()) return; - create(); - if (!path(0).isEmpty()) loadFront(path(0)); - if (!path(1).isEmpty()) loadBack(path(1)); - if (!path(2).isEmpty()) loadLeft(path(2)); - if (!path(3).isEmpty()) loadRight(path(3)); - if (!path(4).isEmpty()) loadTop(path(4)); - if (!path(5).isEmpty()) loadBottom(path(5)); -} - - -void GLCubeTexture::loadFromDirectory(const QString & dir) { - QDir d(dir); QFileInfoList sl; - sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadFront(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBack(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadLeft(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadRight(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadTop(sl[0].absoluteFilePath()); - sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) loadBottom(sl[0].absoluteFilePath()); -} - - -void GLCubeTexture::loadPathesFromDirectory(const QString & dir) { - QDir d(dir); QFileInfoList sl; - sl = d.entryInfoList(QStringList("front.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[0] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("back.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[1] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("left.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[2] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("right.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[3] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("top.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[4] = sl[0].absoluteFilePath(); - sl = d.entryInfoList(QStringList("bottom.*"), QDir::Files | QDir::NoDotAndDotDot); if (!sl.isEmpty()) pathes[5] = sl[0].absoluteFilePath(); -} - - - -GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership, bool bump) { - QString p = findFile(path, search_pathes); - if (p.isEmpty()) return 0; - int tid = ((GLTextureManagerBase*)currentGLTextureManager)->textureID(p, bump); - if (tid > 0) { - //qDebug() << "[TextureManager] Found" << path << "as" << tid; - return tid; - } - QImage image(p); - if (bump) convertToNormal(image); - //qDebug() << p << image.width() << image.height() << image.format() << bump; - tid = currentQGLView->bindTexture(image, GL_TEXTURE_2D/*, GL_RGBA, QGLContext::MipmapBindOption*/); - if (tid == 0) { - qDebug() << "[TextureManager] Can`t load" << p; - return tid; - } - qDebug() << "[TextureManager] Loaded" << p << "as" << tid; - if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids[bump ? 1 : 0].insert(p, tid); - return tid; -} - - -GLuint GLTextureManagerBase::loadTexture(const QImage & im, bool ownership, bool bump) { - if (im.isNull()) return 0; - QImage image(im); - if (bump) convertToNormal(image); - GLuint tid = currentQGLView->bindTexture(image, GL_TEXTURE_2D); - if (tid == 0) { - qDebug() << "[TextureManager] Can`t load image"; - return tid; - } - //qDebug() << "[TextureManager] Loaded image as" << tid; - if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids[bump ? 1 : 0].insert(QString(), tid); - return tid; -} - -Vector3d colorVector(QRgb c) {return Vector3d(((uchar*)(&c))[0] / 255., ((uchar*)(&c))[1] / 255., ((uchar*)(&c))[2] / 255.);} - -void GLTextureManagerBase::convertToNormal(QImage & im) { - if (im.isNull()) return; - QImage sim = im.convertToFormat(QImage::Format_ARGB32); - double sum[3] = {0., 0., 0.}; - llong a = 0; - const uchar * sd = sim.constBits(); - for (int i = 0; i < sim.height(); i++) { - for (int j = 0; j < sim.width(); j++) { - sum[2] += double(sd[a]) / 255. - 0.5; ++a; - sum[1] += double(sd[a]) / 255. - 0.5; ++a; - sum[0] += double(sd[a]) / 255. - 0.5; ++a; - ++a; - } - } - double wh = sim.width() * sim.height(); - sum[0] /= wh; - sum[1] /= wh; - sum[2] /= wh; - qDebug() << sum[0] << sum[1] << sum[2]; - if ((qAbs(sum[0]) <= 0.05) && (qAbs(sum[1]) <= 0.05) && (sum[2] >= 0.4)) /// already normal - return; - qDebug() << "convert to bump"; - QImage dim = QImage(sim.width(), sim.height(), QImage::Format_ARGB32); - int tx, ty, w = sim.width(), h = sim.height(); - a = 0; - uchar * dd = dim.bits(); - for (int i = 0; i < sim.height(); i++) { - for (int j = 0; j < sim.width(); j++) { - tx = j - 1; - tx = tx < 0 ? w + tx : tx % w; - ty = i - 1; - ty = ty < 0 ? h + ty : ty % h; - Vector3d p[3], res; - p[0] = colorVector(sim.pixel(j, i)); - p[1] = colorVector(sim.pixel(j, ty)); - p[2] = colorVector(sim.pixel(tx, i)); - res.y = piClamp(0.5 + (p[0].length() - p[1].length()) / 2., 0., 1.); - res.x = piClamp(0.5 + (p[0].length() - p[2].length()) / 2., 0., 1.); - tx = (j + 1) % w; - ty = (i + 1) % h; - p[1] = colorVector(sim.pixel(j, ty)); - p[2] = colorVector(sim.pixel(tx, i)); - res.y = piClamp(0.5 + (p[0].length() - p[1].length()) / 2., 0., 1.); - res.x = piClamp(0.5 + (p[0].length() - p[2].length()) / 2., 0., 1.); - res.z = 1.; - dd[a] = res.z * 255; ++a; - dd[a] = res.x * 255; ++a; - dd[a] = res.y * 255; ++a; - dd[a] = 255; ++a; - } - } - im = dim; - //im.save("_bump.png"); -} - void Camera::anglesFromPoints() { QVector3D dv = aim_ - pos_, tv; @@ -346,7 +185,10 @@ void Camera::apply(const GLdouble & aspect) { glLoadIdentity(); if (aspect <= 1.) glScaled(aspect, aspect, 1.); - gluPerspective(fov_, aspect, depth_start, depth_end); + QMatrix4x4 pm;// = glMatrixPerspective(fov_, aspect, depth_start, depth_end); + pm.perspective(fov_, aspect, depth_start, depth_end); + //qDebug() << pm << glMatrixPerspective(fov_, aspect, depth_start, depth_end);; + setGLMatrix(pm); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslated(0., 0., -distance()); @@ -518,53 +360,6 @@ QVector3D Camera::pointFromViewport(int x_, int y_, double z_) { -Material::Material(): reflection(512) { - color_diffuse = color_specular = Qt::white; - color_self_illumination = Qt::black; - glass = false; - transparency = reflectivity = 0.f; - bump_scale = relief_scale = iof = 1.f; - dispersion = 0.05f; - shine = 0.5; - shine_strength = 1.f; - light_model = Phong; -} - - -void Material::apply() { - GLfloat mat_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - GLfloat mat_specular[4] = {0.9f, 0.9f, 0.9f, 1.0f}; - GLfloat mat_emission[4] = {0.f, 0.f, 0.f, 1.0f}; - mat_diffuse[0] = color_diffuse.redF(); - mat_diffuse[1] = color_diffuse.greenF(); - mat_diffuse[2] = color_diffuse.blueF(); - mat_diffuse[3] = color_diffuse.alphaF() * (1.f - transparency); - mat_specular[0] = shine_strength * color_specular.redF(); - mat_specular[1] = shine_strength * color_specular.greenF(); - mat_specular[2] = shine_strength * color_specular.blueF(); - mat_emission[0] = color_self_illumination.redF(); - mat_emission[1] = color_self_illumination.greenF(); - mat_emission[2] = color_self_illumination.blueF(); - glColor4f(mat_diffuse[0], mat_diffuse[1], mat_diffuse[2], mat_diffuse[3]); - //qDebug() << color_diffuse.alphaF() * (1.f - transparency); - glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); - glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); - glMaterialf(GL_FRONT, GL_SHININESS, shine); - glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission); - glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse); -} - - -void Material::loadTextures(GLTextureManagerBase * tm) { - //qDebug() << "load textures"; - if (tm == 0) tm = (GLTextureManagerBase*)currentGLTextureManager; - if (!diffuse.bitmap_path.isEmpty()) diffuse.bitmap_id = tm->loadTexture(diffuse.bitmap_path); - if (!bump.bitmap_path.isEmpty()) bump.bitmap_id = tm->loadTexture(bump.bitmap_path, true, true); - if (!relief.bitmap_path.isEmpty()) relief.bitmap_id = tm->loadTexture(relief.bitmap_path); - if (!diffuse_2.bitmap_path.isEmpty()) diffuse_2.bitmap_id = tm->loadTexture(diffuse_2.bitmap_path); - reflection.load(); -} - QColor colorFromString(const QString & str) { QString s = str.trimmed(); @@ -632,199 +427,25 @@ Vector3i::Vector3i(const QString & str) { } - -void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) { - QVector3D lp = l.worldPos(), ld = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized(); - GLfloat pos[] = {0.f, 0.f, 0.f, 0.f}; - GLfloat dir[] = {0.f, 0.f, 0.f}; - GLfloat col[] = {0.f, 0.f, 0.f}; - pos[0] = l.light_type == Light::Directional ? -l.direction.x() : lp.x(); - pos[1] = l.light_type == Light::Directional ? -l.direction.y() : lp.y(); - pos[2] = l.light_type == Light::Directional ? -l.direction.z() : lp.z(); - pos[3] = l.light_type == Light::Directional ? 0. : 1.; - dir[0] = ld.x(); - dir[1] = ld.y(); - dir[2] = ld.z(); - col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.; - col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.; - col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.; - glEnable(gl_index); - //glLightfv(gl_index, GL_AMBIENT, ambient); - glLightfv(gl_index, GL_DIFFUSE, col); - glLightfv(gl_index, GL_SPECULAR, col); - glLightfv(gl_index, GL_POSITION, pos); - glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const); - glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear); - glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic); - if (l.light_type == Light::Cone) { - glLightfv(gl_index, GL_SPOT_DIRECTION, dir); - glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_spread); - glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp); - } else { - glLightf(gl_index, GL_SPOT_CUTOFF, 180.); - } - +void glEnableDepth() { + glEnable(GL_DEPTH_TEST); + //glDepthFunc(GL_GREATER); + glDepthFunc(GL_LESS); + glDepthMask(GL_TRUE); } -void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) { - GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f}; - if (first_pass) { - ambient[0] = view.ambientColor_.redF(); - ambient[1] = view.ambientColor_.greenF(); - ambient[2] = view.ambientColor_.blueF(); - } - glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); +void glDisableDepth() { + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); } -void GLRendererBase::setupShadersLights(int lights_count) { - /*foreach (QGLShaderProgram * i, view.shaders_ppl) { - i->bind(); - i->setUniformValue("lightsCount", lights_count); - i->setUniformValue("acc_light", lights_count > 0); - //i->setUniformValue("mat", mvm); - }*/ -} - - -void GLRendererBase::setupTextures(GLObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) { - if (first_object) { - glReleaseTextures(); - return; - } - setupShadersTextures(o, rp); - Material & mat(o.material_); - if (rp.light) { - if (o.accept_light) {if (!rp.prev_light) {glSetLightEnabled(true); rp.prev_light = true;}} - else {if (rp.prev_light) {glSetLightEnabled(false); rp.prev_light = false;}} - } - if (rp.fog) { - if (o.accept_fog) {if (!rp.prev_fog) {glSetFogEnabled(true); rp.prev_fog = true;}} - else {if (rp.prev_fog) {glSetFogEnabled(false); rp.prev_fog = false;}} - } - if (rp.textures) { - if (rp.prev_tex[0] != mat.diffuse.bitmap_id) { - rp.prev_tex[0] = mat.diffuse.bitmap_id; - glActiveTextureChannel(0); glBindTexture(GL_TEXTURE_2D, mat.diffuse.bitmap_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_); - } - if (rp.prev_tex[1] != mat.bump.bitmap_id) { - rp.prev_tex[1] = mat.bump.bitmap_id; - glActiveTextureChannel(1); glBindTexture(GL_TEXTURE_2D, mat.bump.bitmap_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_); - } - if (rp.prev_tex[2] != mat.relief.bitmap_id) { - rp.prev_tex[2] = mat.relief.bitmap_id; - glActiveTextureChannel(2); glBindTexture(GL_TEXTURE_2D, mat.relief.bitmap_id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_); - } - glActiveTextureChannel(0); - } -} - - -void GLRendererBase::setupLights(int pass, int lights_per_pass) { - int light_start, light_end, lmax; - light_start = pass * lights_per_pass; - light_end = qMin((pass + 1) * lights_per_pass, view.lights_.size()); - setupAmbientLight(view.ambientColor_, pass == 0); - if (!view.lights_.isEmpty()) { - setupShadersLights(light_end - light_start); - for (int i = light_start; i < light_end; ++i) - setupLight(*view.lights_[i], i - light_start, GL_LIGHT0 + i - light_start); - lmax = light_start + 8; - for (int i = light_end; i < lmax; ++i) - glDisable(GL_LIGHT0 + i - light_start); - } else { - setupShadersLights(0); - for (int i = 0; i < 8; ++i) - glDisable(GL_LIGHT0 + i); - } -} - - -void GLRendererBase::applyFilteringParameters() { - if (view.linearFiltering_) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view.anisotropicLevel_); -} - - -void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) { - RenderingParameters rp; - rp.pass = pass; - rp.light_pass = light_pass; - rp.shaders = shaders; - rp.textures = textures; - rp.light = rp.prev_light = light; - rp.fog = rp.prev_fog = fog; - for (int i = 0; i < 32; ++i) rp.prev_tex[i] = 0; - rp.prev_light_model = Material::Phong; - setupTextures(view.objects_, rp, true); - glSetLightEnabled(rp.prev_light); - glSetFogEnabled(rp.prev_fog); - glSetCapEnabled(GL_TEXTURE_2D, rp.textures); - glSetCapEnabled(GL_BLEND, pass == GLObjectBase::Transparent); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_TEXTURE_CUBE_MAP); - renderSingleObject(view.objects_, rp); -} - - -void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & rp) { - if (!o.isInit()) - o.init(); - if (!o.isTexturesLoaded()) - o.loadTextures(); - if (!o.visible_) return; - Material & mat(o.material_); - glPushMatrix(); - if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_); - if (o.raw_matrix) { - qglMultMatrix(o.mat_); - } else { - if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.); - if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.); - if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.); - if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_); - } - if (rp.pass == o.pass_) { - setupTextures(o, rp, false); - mat.apply(); - glSetPolygonMode(o.render_mode != GLObjectBase::View ? o.render_mode : (view.rmode != GLObjectBase::View ? view.rmode : GL_FILL)); - glLineWidth(o.line_width > 0. ? o.line_width : view.lineWidth_); - glPointSize(o.line_width > 0. ? o.line_width : view.lineWidth_); - o.update(); - if (o.pass_ == GLObjectBase::Transparent) { - glActiveTextureChannel(3); - if (mat.reflectivity > 0.) { - glEnable(GL_TEXTURE_CUBE_MAP); - if (!mat.reflection.isEmpty()) mat.reflection.bind(); - else glDisable(GL_TEXTURE_CUBE_MAP); - } else glDisable(GL_TEXTURE_CUBE_MAP); - if (rp.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP); - GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity}; - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc); - glGetFloatv(GL_MODELVIEW_MATRIX, gm); - glMatrixMode(GL_TEXTURE); - glLoadTransposeMatrixf(gm); - glScalef(-1., -1., -1.); - glMatrixMode(GL_MODELVIEW); - glActiveTextureChannel(0); - } - o.draw(); - } - foreach (GLObjectBase * i, o.children_) - renderSingleObject(*i, rp); - glPopMatrix(); +void glClearFramebuffer(const QColor & color, bool depth) { + glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + glClearDepth(1.); + if (depth) + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT); } diff --git a/qglview/gltypes.h b/qglview/gltypes.h index 72acb38..90fa41e 100644 --- a/qglview/gltypes.h +++ b/qglview/gltypes.h @@ -140,11 +140,13 @@ inline QColor operator /(const QColor & c, double v) {return QColor(c.red() / v, inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());} void qglMultMatrix(const QMatrix4x4 & m); +void glEnableDepth(); +void glDisableDepth(); inline void glActiveTextureChannel(int channel) {glActiveTexture(GL_TEXTURE0 + channel); glClientActiveTexture(GL_TEXTURE0 + channel);} inline void glResetAllTransforms() {glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity();} inline void glClearError() {int c = 100; while (glGetError() != GL_NO_ERROR && --c > 0) glGetError();} inline void glClearAccumulation(const QColor & color = Qt::black) {glClearAccum(color.redF(), color.greenF(), color.blueF(), color.alphaF()); glClear(GL_ACCUM_BUFFER_BIT);} -inline void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true) {glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF()); if (depth) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); else glClear(GL_COLOR_BUFFER_BIT);} +void glClearFramebuffer(const QColor & color = Qt::black, bool depth = true); inline void glReleaseTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_CUBE_MAP, 0);}} inline void glReleaseFramebuffer() {glBindFramebuffer(GL_FRAMEBUFFER, 0);} inline void glDisableTextures(int channels = 8) {for (int i = channels - 1; i >= 0; --i) {glActiveTextureChannel(i); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_CUBE_MAP);}} @@ -155,15 +157,17 @@ inline void glSetFogEnabled(bool on) {if (on) glEnable(GL_FOG); else glDisable(G inline void glSetPolygonMode(GLenum mode) {glPolygonMode(GL_FRONT_AND_BACK, mode);} void glDrawQuad(GLfloat x = -1.f, GLfloat y = -1.f, GLfloat w = 2.f, GLfloat h = 2.f); QMatrix4x4 getGLMatrix(GLenum matrix); +void setGLMatrix(QMatrix4x4 matrix); inline void deleteGLTexture(GLuint & tex) {if (tex != 0) glDeleteTextures(1, &tex); tex = 0;} inline void deleteGLFramebuffer(GLuint & fbo) {if (fbo != 0) glDeleteFramebuffers(1, &fbo); fbo = 0;} inline void deleteGLRenderbuffer(GLuint & drbo) {if (drbo != 0) glDeleteRenderbuffers(1, &drbo); drbo = 0;} inline void deleteGLBuffer(GLuint & bo) {if (bo != 0) glDeleteBuffers(1, &bo); bo = 0;} +inline void deleteGLVertexArray(GLuint & va) {if (va != 0) glDeleteVertexArrays(1, &va); va = 0;} void createGLTexture(GLuint & tex, int width, int height, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D); void createGLTexture(GLuint & tex, const QImage & image, const GLenum & format = GL_RGBA8, const GLenum & target = GL_TEXTURE_2D); inline void qglTranslate(const QVector3D & v) {glTranslated(v.x(), v.y(), v.z());} inline void qglScale(const QVector3D & v) {glScaled(v.x(), v.y(), v.z());} -bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & dir = QString()); +QMatrix4x4 glMatrixPerspective(double angle, double aspect, double near_, double far_); QImage rotateQImageLeft(const QImage & im); QImage rotateQImageRight(const QImage & im); inline QImage rotateQImage180(const QImage & im) {return im.mirrored(true, true);} @@ -174,76 +178,6 @@ extern QGLWidget * currentQGLView; extern QMatrix4x4 globCameraMatrix; extern QMutex globMutex; - -class GLTexture { -public: - GLTexture(int _width, int _height, const GLenum & _format = GL_RGBA8, const GLenum & _target = GL_TEXTURE_2D) {wid = _width; hei = _height; format_ = _format; target_ = _target; id_ = 0;} - bool create() {destroy(); createGLTexture(id_, wid, hei, format_, target_); return id_ > 0;} - void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} - void bind() {if (id_ > 0) glBindTexture(target_, id_);} - void release() {glBindTexture(target_, 0);} - int width() const {return wid;} - int height() const {return hei;} - GLenum format() const {return format_;} - GLenum target() const {return target_;} - GLuint id() const {return id_;} -private: - int wid, hei; - GLenum format_, target_; - GLuint id_; -}; - - -class GLCubeTexture { -public: - GLCubeTexture(int _size, const GLenum & _format = GL_RGBA8) {size = _size; format_ = _format; id_ = 0; changed_ = false; pathes.resize(6);} - bool create(); - void destroy() {if (id_ > 0) glDeleteTextures(1, &id_); id_ = 0;} - void bind() {if (changed_) {changed_ = false; create();} if (id_ > 0) glBindTexture(GL_TEXTURE_CUBE_MAP, id_);} - void release() {glBindTexture(GL_TEXTURE_CUBE_MAP, 0);} - void resize(int _size) {size = _size; changed_ = true;} - void loadFromDirectory(const QString & dir); - void loadFront(const QString & path) {bind(); pathes[0] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_X);} - void loadBack(const QString & path) {bind(); pathes[1] = path; createGLTexture(id_, rotateQImageRight(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);} - void loadLeft(const QString & path) {bind(); pathes[2] = path; createGLTexture(id_, QImage(path).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);} - void loadRight(const QString & path) {bind(); pathes[3] = path; createGLTexture(id_, rotateQImage180(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);} - void loadTop(const QString & path) {bind(); pathes[4] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);} - void loadBottom(const QString & path) {bind(); pathes[5] = path; createGLTexture(id_, rotateQImageLeft(QImage(path)).scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), format_, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);} - void load(); - bool isEmpty() const {foreach (const QString & i, pathes) if (!i.isEmpty()) return false; return true;} - GLenum format() const {return format_;} - void setFormat(GLenum f) {format_ = f; changed_ = true;} - GLuint id() const {return id_;} - const QString & path(int side) const {return pathes[side];} - void setPath(int side, const QString & p) {pathes[side] = p;} - void loadPathesFromDirectory(const QString & dir); -private: - bool changed_; - int size; - GLenum format_; - GLuint id_; - QVector pathes; -}; - -class GLTextureManager; - -class GLTextureManagerBase { -public: - static void addSearchPath(const QString & path) {search_pathes << path;} - static QStringList searchPathes() {return search_pathes;} - static GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); - static GLuint loadTexture(const QImage & image, bool ownership = true, bool bump = false); - int textureID(const QString & path, bool bump = false) {return tex_ids[bump ? 1 : 0][path];} - -protected: - static void convertToNormal(QImage & im); - static QStringList search_pathes; - QMap tex_ids[2]; - -}; - -extern GLTextureManager * currentGLTextureManager; - class Camera { friend class QGLView; @@ -328,44 +262,6 @@ private: extern Camera * currentCamera; -struct Map { - Map() {bitmap_id = 0; bitmap_amount = 1.f; animation_frame_rate = -1.f;} - QString bitmap_path; - GLuint bitmap_id; - QPointF bitmap_offset; - float bitmap_amount; - QString animation; - float animation_frame_rate; -}; - -struct Material { - enum LightModel {Phong = 0, CookTorrance = 1, Minnaert = 2, Strauss = 3, OrenNayar = 4}; - Material(); - QString name; - void apply(); - void loadTextures(GLTextureManagerBase * tm = 0); - QColor color_diffuse; - QColor color_specular; - QColor color_self_illumination; - LightModel light_model; - bool glass; - float shine; - float shine_strength; - float transparency; - float reflectivity; - float iof; - float dispersion; - float bump_scale; - float relief_scale; - Map diffuse; - Map bump; - Map relief; - Map diffuse_2; - Map diffuse_3; - Map diffuse_4; - GLCubeTexture reflection; -}; - struct Box3D { GLfloat x; GLfloat y; @@ -479,14 +375,10 @@ inline uint qHash(const Vector3i & v) {return v.p0 + v.p1 * 1024 + v.p2 * 1024 * inline QDebug operator <<(QDebug d, const Vector3d& v) {d.nospace() << "{" << v.x << ", " << v.y << ", " << v.z << "}"; return d.space();} inline QDebug operator <<(QDebug d, const Vector3i & v) {d.nospace() << "{" << v.p0 << ", " << v.p1 << ", " << v.p2 << "}"; return d.space();} -inline QDataStream & operator <<(QDataStream & s, const Map & m) {s << m.bitmap_path << m.bitmap_amount << m.animation << m.animation_frame_rate; return s;} inline QDataStream & operator <<(QDataStream & s, const Vector3d & v) {s << v.x << v.y << v.z; return s;} +inline QDataStream & operator >>(QDataStream & s, Vector3d & v) {s >> v.x >> v.y >> v.z; return s;} inline QDataStream & operator <<(QDataStream & s, const Vector3i & v) {s << v.p0 << v.p1 << v.p2; return s;} -inline QDataStream & operator <<(QDataStream & s, const Material & m) {s << m.color_diffuse << m.shine << m.shine_strength << m.color_specular << m.transparency << m.diffuse << m.bump; return s;} -inline QDataStream & operator >>(QDataStream & s, Map & m) {s >> m.bitmap_path >> m.bitmap_amount >> m.animation >> m.animation_frame_rate; return s;} -inline QDataStream & operator >>(QDataStream & s, Vector3d & v) {s >> v.x >> v.y >> v.z; return s;} -inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;} -inline QDataStream & operator >>(QDataStream & s, Material & m) {s >> m.color_diffuse >> m.shine >> m.shine_strength >> m.color_specular >> m.transparency >> m.diffuse >> m.bump; return s;} +inline QDataStream & operator >>(QDataStream & s, Vector3i & v) {s >> v.p0 >> v.p1 >> v.p2; return s;} QColor colorFromString(const QString & str); inline double cosABV(const QVector3D & v0, const QVector3D & v1) { @@ -519,45 +411,4 @@ protected: Camera camera_; }; - -class GLRendererBase: public QObject -{ - friend class QGLView; - Q_OBJECT -public: - GLRendererBase(QGLView * view_): view(*view_) {} - virtual void renderScene() = 0; - -protected: - struct RenderingParameters { - int pass; - int light_pass; - bool light; - bool fog; - bool textures; - bool prev_light; - bool prev_fog; - Material::LightModel prev_light_model; - GLuint prev_tex[32]; - void * shaders; - QGLShaderProgram * cur_shader; - }; - - virtual void setupLight(const Light & l, int inpass_index, int gl_index); - virtual void setupAmbientLight(const QColor & a, bool first_pass); - virtual void setupShadersLights(int lights_count); - virtual void setupTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp, bool first_object = false); - virtual void setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) {} - virtual void reloadShaders() {} - virtual void init(int width, int height) {} - virtual void resize(int width, int height) {} - - void setupLights(int pass, int lights_per_pass); - inline void applyFilteringParameters(); - void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); - void renderSingleObject(GLObjectBase & o, RenderingParameters & rp); - - QGLView & view; -}; - #endif // GLTYPES_H diff --git a/qglview/glvbo.cpp b/qglview/glvbo.cpp index af5ded8..64f40ba 100644 --- a/qglview/glvbo.cpp +++ b/qglview/glvbo.cpp @@ -21,6 +21,7 @@ GLVBO::GLVBO(GLenum usage_) { buffer_ = 0; + va_ = 0; usage = usage_; changed = true; } @@ -32,12 +33,20 @@ GLVBO::~GLVBO() { void GLVBO::init() { - if (!isIinit()) + if (!isIinit()) { + //glGenVertexArrays(1, &va_); glGenBuffers(1, &buffer_); + } changed = true; } +void GLVBO::destroy() { + deleteGLBuffer(buffer_); + //deleteGLVertexArray(va_); +} + + bool GLVBO::rebuffer(bool clear_) { QVector data; //data.clear(); @@ -54,9 +63,12 @@ bool GLVBO::rebuffer(bool clear_) { data << colors_; has_colors = true; } else has_colors = false; + //glBindVertexArray(va_); + //qDebug() << "load buffer" << data.size() << buffer_; glBindBuffer(GL_ARRAY_BUFFER, buffer_); glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.constData(), usage); glBindBuffer(GL_ARRAY_BUFFER, 0); + //glBindVertexArray(0); vert_count = vertices_.size() / 3; changed = false; //qDebug() << "rebuff" << buffer_ << vert_count; @@ -65,35 +77,76 @@ bool GLVBO::rebuffer(bool clear_) { } -void GLVBO::draw(GLenum type, bool simplest) { +void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { if (buffer_ == 0 || vert_count == 0) return; if (changed) rebuffer(); //qDebug() << "draw" << vert_count; void * offset = (void*)(vert_count * 3 * sizeof(GLfloat)); + //glBindVertexArray(va_); + + void * offsets[3] = {0, 0, 0}; + if (has_normals) { + offsets[0] = offset; + offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); + } + if (has_texcoords) { + offsets[1] = offset; + offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); + } + if (has_colors) { + offsets[2] = offset; + } + glBindBuffer(GL_ARRAY_BUFFER, buffer_); - glMultiTexCoord3f(GL_TEXTURE2, 0.f, 1.f, 0.f); - glVertexPointer(3, GL_FLOAT, 0, 0); - if (!simplest) { + if (prog) { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + int loc = prog->attributeLocation("_qgl_Vertex"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0); + loc = prog->attributeLocation("qgl_Normal"); if (has_normals) { - glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, offset); - offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); - } else glDisableClientState(GL_NORMAL_ARRAY); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]); + } else + glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Texture"); if (has_texcoords) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, offset); - offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); - } else glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]); + } else + glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Color"); if (has_colors) { - glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(4, GL_FLOAT, 0, offset); - } else glDisableClientState(GL_COLOR_ARRAY); - }/* else { - glDisable(GL_NORMAL_ARRAY); - glDisable(GL_TEXTURE_COORD_ARRAY); - glDisable(GL_COLOR_ARRAY); - }*/ + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]); + } else + glDisableVertexAttribArray(loc); + } else { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, 0); + if (!simplest) { + if (has_normals) { + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, 0, offset); + offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); + } else glDisableClientState(GL_NORMAL_ARRAY); + if (has_texcoords) { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 0, offset); + offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); + } else glDisableClientState(GL_TEXTURE_COORD_ARRAY); + if (has_colors) { + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_FLOAT, 0, offset); + } else glDisableClientState(GL_COLOR_ARRAY); + } + } + //qDebug() << "draw" << vert_count << buffer_ << offsets[0] << offsets[1] << offsets[3]; glDrawArrays(type, 0, vert_count); + //qDebug() << "draw" << vert_count << buffer_ << "done"; glBindBuffer(GL_ARRAY_BUFFER, 0); } @@ -138,4 +191,4 @@ bool GLVBO::loadFromFile(const QString & filename) { return !isEmpty(); } return false; -} \ No newline at end of file +} diff --git a/qglview/glvbo.h b/qglview/glvbo.h index 4bc5eeb..7c07d82 100644 --- a/qglview/glvbo.h +++ b/qglview/glvbo.h @@ -31,9 +31,9 @@ public: //GLVBO & operator =(const GLVBO & o) {return *this;} void init(); - void destroy() {deleteGLBuffer(buffer_);} + void destroy(); bool rebuffer(bool clear_ = false); - void draw(GLenum type, bool simplest = false); + void draw(GLenum type, QGLShaderProgram * prog, bool simplest = false); void clear(); GLuint buffer() const {return buffer_;} @@ -52,7 +52,7 @@ public: private: QVector vertices_, normals_, texcoords_, colors_; GLenum usage; - GLuint buffer_; + GLuint buffer_, va_; int vert_count; bool changed, has_normals, has_texcoords, has_colors; diff --git a/qglview/loader_3ds.cpp b/qglview/loader_3ds.cpp index 45e99ce..7f8de82 100644 --- a/qglview/loader_3ds.cpp +++ b/qglview/loader_3ds.cpp @@ -327,8 +327,8 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { name = readCharsUntilNull(stream); //qDebug() << " mat map" << QString::number(cur_map, 16) << name; switch (cur_map) { - case LOADER_3DS_CHUNK_TEXTURE_MAP: mat.diffuse.bitmap_path = name; break; - case LOADER_3DS_CHUNK_BUMP_MAP: mat.bump.bitmap_path = name; break; + case LOADER_3DS_CHUNK_TEXTURE_MAP: mat.map_diffuse.bitmap_path = name; break; + case LOADER_3DS_CHUNK_BUMP_MAP: mat.map_bump.bitmap_path = name; break; } break; default: /*qDebug() << "???" << QString::number(cc.id, 16).rightJustified(4, '0') << cc.size;*/ stream.skipRawData(cc.size - 6); diff --git a/qglview/loader_ase.cpp b/qglview/loader_ase.cpp index c64e358..7547926 100644 --- a/qglview/loader_ase.cpp +++ b/qglview/loader_ase.cpp @@ -109,7 +109,7 @@ GLObjectBase * loadFromASEFile(const QString & filepath, double scale) { materials.resize(line.right(line.length() - mst - 14).toInt()); //qDebug() << materials.size() << "materials"; for (int i = 0; i < materials.size(); ++i) { - materials[i].diffuse.bitmap_id = 0; + materials[i].map_diffuse.bitmap_id = 0; mst = -1; while (mst < 0 && !stream.atEnd()) { line = stream.readLine(); @@ -120,15 +120,15 @@ GLObjectBase * loadFromASEFile(const QString & filepath, double scale) { line = stream.readLine().trimmed(); if (line.left(17) == "*MATERIAL_DIFFUSE") {materials[i].color_diffuse = colorFromString(line.right(line.length() - 18)); continue;} //qDebug() << "diffuse " << i << " = " << colorFromString(line.right(line.length() - 18)); if (line.left(18) == "*MATERIAL_SPECULAR") {materials[i].color_specular = colorFromString(line.right(line.length() - 19)); continue;} //qDebug() << "specular " << i << " = " << colorFromString(line.right(line.length() - 19)); - if (line.left(23) == "*MATERIAL_SHINESTRENGTH") {materials[i].shine_strength = line.right(line.length() - 24).toFloat(); continue;} - if (line.left(15) == "*MATERIAL_SHINE") {materials[i].shine = line.right(line.length() - 16).toFloat() * 100.; continue;} + if (line.left(23) == "*MATERIAL_SHINESTRENGTH") {materials[i].specular = line.right(line.length() - 24).toFloat(); continue;} + if (line.left(15) == "*MATERIAL_SHINE") {materials[i].roughness = 2. / exp(line.right(line.length() - 16).toFloat()); continue;} if (line.left(22) == "*MATERIAL_TRANSPARENCY") {materials[i].transparency = line.right(line.length() - 23).toFloat(); continue;} if (line.left(12) == "*MAP_DIFFUSE") { line = stream.readLine().trimmed(); while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].bump.bitmap_amount = line.right(line.length() - 12).toFloat(); + materials[i].map_bump.color_amount = line.right(line.length() - 12).toFloat(); while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].diffuse.bitmap_path = line.mid(9, line.length() - 10); + materials[i].map_diffuse.bitmap_path = line.mid(9, line.length() - 10); /*if (!materials[i].diffuse.bitmap_path.isEmpty()) { materials[i].diffuse.bitmap_id = currentQGLView->bindTexture(QImage(materials[i].diffuse.bitmap_path)); parent->textures << materials[i].diffuse.bitmap_id; @@ -141,10 +141,10 @@ GLObjectBase * loadFromASEFile(const QString & filepath, double scale) { if (line.left(9) == "*MAP_BUMP") { line = stream.readLine().trimmed(); while (line.left(11) != "*MAP_AMOUNT" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].bump.bitmap_amount = line.right(line.length() - 12).toFloat(); - //qDebug() << "bump amount" << materials[i].bump.bitmap_amount; + materials[i].map_bump.color_amount = line.right(line.length() - 12).toFloat(); + //qDebug() << "bump amount" << materials[i].bump.color_amount; while (line.left(7) != "*BITMAP" && !stream.atEnd()) line = stream.readLine().trimmed(); - materials[i].bump.bitmap_path = line.mid(9, line.length() - 10); + materials[i].map_bump.bitmap_path = line.mid(9, line.length() - 10); /*if (!materials[i].bump.bitmap_path.isEmpty()) { materials[i].bump.bitmap_id = currentQGLView->bindTexture(QImage(materials[i].bump.bitmap_path)); parent->textures << materials[i].bump.bitmap_id; diff --git a/qglview/loader_dae.cpp b/qglview/loader_dae.cpp index 8e73a32..5abcb03 100644 --- a/qglview/loader_dae.cpp +++ b/qglview/loader_dae.cpp @@ -140,17 +140,17 @@ QVector LoaderDAE::readMaterials(QDomElement le, QDomElement li, bool if (col.isValid()) mat.color_diffuse = col; col = readXMLColor(pn.firstChildElement("specular")); if (col.isValid()) mat.color_specular = col; - mat.shine = 2. / exp(readXMLFloat(pn.firstChildElement("shininess"))); + mat.roughness = 2. / exp(readXMLFloat(pn.firstChildElement("shininess"))); mat.transparency = readXMLFloat(pn.firstChildElement("transparency")); if (!fbx) mat.transparency = 1. - mat.transparency; text = readXMLTexture(pn.firstChildElement("diffuse"), prof, li); - if (!text.isEmpty()) mat.diffuse.bitmap_path = text; + if (!text.isEmpty()) mat.map_diffuse.bitmap_path = text; text = readXMLTexture(pn.firstChildElement("diffuse"), prof, li); - if (!text.isEmpty()) mat.diffuse.bitmap_path = text; + if (!text.isEmpty()) mat.map_diffuse.bitmap_path = text; pn = prof.firstChildElement("technique").firstChildElement("extra").firstChild(); text = readXMLTexture(pn.firstChildElement("bump"), prof, li); - if (!text.isEmpty()) mat.bump.bitmap_path = text; + if (!text.isEmpty()) mat.map_bump.bitmap_path = text; ret << mat; /* diff --git a/qglview/loader_obj.cpp b/qglview/loader_obj.cpp index 2196966..5ec5672 100644 --- a/qglview/loader_obj.cpp +++ b/qglview/loader_obj.cpp @@ -156,7 +156,7 @@ QVector readMTL(QString obj_path, QString path) { } if (line.startsWith("Ks")) { Vector3d v = readVector3d(line.mid(2).trimmed()); - mat.shine_strength = v.length(); + mat.specular = v.length(); double mc = qMax(v.x, qMax(v.y, v.z)); if (mc > 0.) v /= mc; mat.color_specular = QColor::fromRgbF(v.x, v.y, v.z); @@ -164,7 +164,7 @@ QVector readMTL(QString obj_path, QString path) { continue; } if (line.startsWith("Ns")) { - mat.shine = line.mid(2).trimmed().toDouble(); + mat.roughness = 2. / exp(line.mid(2).trimmed().toDouble()); continue; } if (line.startsWith("d")) { @@ -172,7 +172,7 @@ QVector readMTL(QString obj_path, QString path) { continue; } if (line.startsWith("map_Kd")) { - mat.diffuse.bitmap_path = findFile(line.mid(6).trimmed(), sp); + mat.map_diffuse.bitmap_path = findFile(line.mid(6).trimmed(), sp); continue; } if (line.startsWith("map_bump")) { @@ -181,9 +181,9 @@ QVector readMTL(QString obj_path, QString path) { line = line.mid(3).trimmed(); QString sv = line.left(line.indexOf(" ")); line = line.mid(sv.size()).trimmed(); - mat.bump_scale = sv.toDouble(); + mat.map_bump.color_amount = sv.toDouble(); } - mat.bump.bitmap_path = findFile(line, sp); + mat.map_bump.bitmap_path = findFile(line, sp); //qDebug() << "BUMP" << mat.name << mat.bump_scale << mat.bump.bitmap_path; continue; } diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index cb81177..40ef3ec 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -34,8 +34,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() //spinSliderShine->setDecimals(2); view->setFrameShape(QFrame::NoFrame); //view->setRenderer(new RendererDeferredShading(view)); - view->setRenderer(new RendererSimple(view)); - view->setMouseSelectionEnabled(true); + view->setRenderer(new RendererDeferredShading(view)); + view->setMouseSelectionEnabled(false); view->setMouseRotateEnabled(true); view->setBackColor(Qt::lightGray); //view->setLightingMode(QGLView::PerPixel); @@ -62,13 +62,11 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() //obj->child("teapot")->setLineWidth(2.); //obj->child("cone")->setRenderMode(GLObjectBase::Line); //view->camera().setAim(obj->child("sphere001")->pos()); - QImageReader im("D:/orders/libs/qglview/data/SU-33_maps/Map__14_Mix.tga"); - QImage i = im.read(); - qDebug() << i.size() << im.errorString(); GLTextureManager::addSearchPath("data"); GLTextureManager::addSearchPath("data/images"); GLTextureManager::addSearchPath("data/SU-33_maps"); - obj = loadFromDAEFile("data/su33t.dae");//new GLPrimitiveEllipsoid(EARTH_WL / 1E+6, EARTH_WL / 1E+6, EARTH_H / 1E+6, 500, 500);//GLPrimitiveCube(); + obj = loadFromDAEFile("data/test.dae");//new GLPrimitiveEllipsoid(EARTH_WL / 1E+6, EARTH_WL / 1E+6, EARTH_H / 1E+6, 500, 500);//GLPrimitiveCube(); + obj->setScale(0.1); //obj = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube(); view->addObject(obj); @@ -95,7 +93,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() view->setHoverHaloEnabled(false); Light * l = new Light(view->camera().pos()); l->intensity = 0.8; - view->addObject(l); + l->setName("camera"); + //view->addObject(l); view->start(-1); //view->light(0)->light_type = Light::Omni; //obj = loadFrom3DSFile("34.3DS", 0.03); @@ -148,6 +147,7 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() //view->addObject(new Light(view->camera().pos())); //show(); + //comboBox->setCurrentIndex(2); } diff --git a/qglview/mainwindow.ui b/qglview/mainwindow.ui index c5d8a9e..857fa44 100644 --- a/qglview/mainwindow.ui +++ b/qglview/mainwindow.ui @@ -7,7 +7,7 @@ 0 0 1246 - 844 + 856 @@ -45,7 +45,7 @@ - 3 + 0 diff --git a/qglview/material_editor.cpp b/qglview/material_editor.cpp index 47219a4..40854e3 100644 --- a/qglview/material_editor.cpp +++ b/qglview/material_editor.cpp @@ -23,6 +23,7 @@ MaterialEditor::MaterialEditor(QWidget * parent): QWidget(parent) { ui = new Ui::MaterialEditor(); ui->setupUi(this); + ui->frameReflection->hide(); active = true; } @@ -46,24 +47,24 @@ void MaterialEditor::setMaterial(const Material & m) { ui->colorSpecular->setColor(m.color_specular); ui->colorSelfIllum->setColor(m.color_self_illumination); ui->checkGlass->setChecked(m.glass); - ui->comboModel->setCurrentIndex((int)m.light_model); - ui->spinShine->setValue(m.shine); - ui->spinShineStrength->setValue(m.shine_strength); + ui->spinRoughness->setValue(m.roughness); + ui->spinSpecular->setValue(m.specular); ui->spinTransparent->setValue(m.transparency); ui->spinReflect->setValue(m.reflectivity); - ui->spinBump->setValue(m.bump_scale); - ui->spinRelief->setValue(m.relief_scale); ui->spinIOF->setValue(m.iof); ui->spinDispersion->setValue(m.dispersion); - ui->lineDiffuse->setProperty("GLpath", m.diffuse.bitmap_path); ui->lineDiffuse->setText(QFileInfo(m.diffuse.bitmap_path).fileName()); - ui->lineBump->setProperty("GLpath", m.bump.bitmap_path); ui->lineBump->setText(QFileInfo(m.bump.bitmap_path).fileName()); - ui->lineRelief->setProperty("GLpath", m.relief.bitmap_path); ui->lineRelief->setText(QFileInfo(m.relief.bitmap_path).fileName()); - ui->lineReflFront->setProperty("GLpath", m.reflection.path(0)); ui->lineReflFront->setText(QFileInfo(m.reflection.path(0)).fileName()); - ui->lineReflBack->setProperty("GLpath", m.reflection.path(1)); ui->lineReflBack->setText(QFileInfo(m.reflection.path(1)).fileName()); - ui->lineReflLeft->setProperty("GLpath", m.reflection.path(2)); ui->lineReflLeft->setText(QFileInfo(m.reflection.path(2)).fileName()); - ui->lineReflRight->setProperty("GLpath", m.reflection.path(3)); ui->lineReflRight->setText(QFileInfo(m.reflection.path(3)).fileName()); - ui->lineReflTop->setProperty("GLpath", m.reflection.path(4)); ui->lineReflTop->setText(QFileInfo(m.reflection.path(4)).fileName()); - ui->lineReflBottom->setProperty("GLpath", m.reflection.path(5)); ui->lineReflBottom->setText(QFileInfo(m.reflection.path(5)).fileName()); + ui->mapDiffuse->setMap(m.map_diffuse); + ui->mapSpecular->setMap(m.map_specular); + ui->mapSelfIllum->setMap(m.map_self_illumination); + ui->mapRoughness->setMap(m.map_roughness); + ui->mapBump->setMap(m.map_bump); + ui->mapRelief->setMap(m.map_relief); + ui->lineReflFront->setProperty("GLpath", m.map_reflection.path(0)); ui->lineReflFront->setText(QFileInfo(m.map_reflection.path(0)).fileName()); + ui->lineReflBack->setProperty("GLpath", m.map_reflection.path(1)); ui->lineReflBack->setText(QFileInfo(m.map_reflection.path(1)).fileName()); + ui->lineReflLeft->setProperty("GLpath", m.map_reflection.path(2)); ui->lineReflLeft->setText(QFileInfo(m.map_reflection.path(2)).fileName()); + ui->lineReflRight->setProperty("GLpath", m.map_reflection.path(3)); ui->lineReflRight->setText(QFileInfo(m.map_reflection.path(3)).fileName()); + ui->lineReflTop->setProperty("GLpath", m.map_reflection.path(4)); ui->lineReflTop->setText(QFileInfo(m.map_reflection.path(4)).fileName()); + ui->lineReflBottom->setProperty("GLpath", m.map_reflection.path(5)); ui->lineReflBottom->setText(QFileInfo(m.map_reflection.path(5)).fileName()); active = true; } @@ -74,55 +75,28 @@ Material MaterialEditor::material() { m.color_specular = ui->colorSpecular->color(); m.color_self_illumination = ui->colorSelfIllum->color(); m.glass = ui->checkGlass->isChecked(); - m.light_model = (Material::LightModel)ui->comboModel->currentIndex(); - m.shine = ui->spinShine->value(); - m.shine_strength = ui->spinShineStrength->value(); + m.roughness = ui->spinRoughness->value(); + m.specular = ui->spinSpecular->value(); m.transparency = ui->spinTransparent->value(); m.reflectivity = ui->spinReflect->value(); - m.bump_scale = ui->spinBump->value(); - m.relief_scale = ui->spinRelief->value(); m.iof = ui->spinIOF->value(); m.dispersion = ui->spinDispersion->value(); - m.diffuse.bitmap_path = ui->lineDiffuse->property("GLpath").toString(); - m.bump.bitmap_path = ui->lineBump->property("GLpath").toString(); - m.relief.bitmap_path = ui->lineRelief->property("GLpath").toString(); - m.reflection.setPath(0, ui->lineReflFront->property("GLpath").toString()); - m.reflection.setPath(1, ui->lineReflBack->property("GLpath").toString()); - m.reflection.setPath(2, ui->lineReflLeft->property("GLpath").toString()); - m.reflection.setPath(3, ui->lineReflRight->property("GLpath").toString()); - m.reflection.setPath(4, ui->lineReflTop->property("GLpath").toString()); - m.reflection.setPath(5, ui->lineReflBottom->property("GLpath").toString()); + m.map_diffuse = ui->mapDiffuse->map(); + m.map_specular = ui->mapSpecular->map(); + m.map_self_illumination = ui->mapSelfIllum->map(); + m.map_roughness = ui->mapRoughness->map(); + m.map_bump = ui->mapBump->map(); + m.map_relief = ui->mapRelief->map(); + m.map_reflection.setPath(0, ui->lineReflFront->property("GLpath").toString()); + m.map_reflection.setPath(1, ui->lineReflBack->property("GLpath").toString()); + m.map_reflection.setPath(2, ui->lineReflLeft->property("GLpath").toString()); + m.map_reflection.setPath(3, ui->lineReflRight->property("GLpath").toString()); + m.map_reflection.setPath(4, ui->lineReflTop->property("GLpath").toString()); + m.map_reflection.setPath(5, ui->lineReflBottom->property("GLpath").toString()); return m; } -void MaterialEditor::on_buttonDiffuseSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineDiffuse->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineDiffuse->setProperty("GLpath", str); - ui->lineDiffuse->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonBumpSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineBump->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineBump->setProperty("GLpath", str); - ui->lineBump->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - -void MaterialEditor::on_buttonReliefSelect_clicked() { - QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineRelief->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); - if (str.isEmpty()) return; - ui->lineRelief->setProperty("GLpath", str); - ui->lineRelief->setText(QFileInfo(str).fileName()); - materialChanged(); -} - - void MaterialEditor::on_buttonReflFrontSelect_clicked() { QString str = QFileDialog::getOpenFileName(this, "Select image", ui->lineReflFront->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); if (str.isEmpty()) return; @@ -177,27 +151,6 @@ void MaterialEditor::on_buttonReflBottomSelect_clicked() { } -void MaterialEditor::on_buttonDiffuseClear_clicked() { - ui->lineDiffuse->setText(""); - ui->lineDiffuse->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonBumpClear_clicked() { - ui->lineBump->setText(""); - ui->lineBump->setProperty("GLpath", ""); - materialChanged(); -} - - -void MaterialEditor::on_buttonReliefClear_clicked() { - ui->lineRelief->setText(""); - ui->lineRelief->setProperty("GLpath", ""); - materialChanged(); -} - - void MaterialEditor::on_buttonReflFrontClear_clicked() { ui->lineReflFront->setText(""); ui->lineReflFront->setProperty("GLpath", ""); diff --git a/qglview/material_editor.h b/qglview/material_editor.h index 2be596a..8d935c4 100644 --- a/qglview/material_editor.h +++ b/qglview/material_editor.h @@ -20,7 +20,7 @@ #define MATERIAL_EDITOR_H #include -#include "gltypes.h" +#include "glmaterial.h" namespace Ui { class MaterialEditor; @@ -43,12 +43,6 @@ protected: private slots: void materialChanged() {if (active) emit changed();} - void on_buttonDiffuseSelect_clicked(); - void on_buttonDiffuseClear_clicked(); - void on_buttonBumpSelect_clicked(); - void on_buttonBumpClear_clicked(); - void on_buttonReliefSelect_clicked(); - void on_buttonReliefClear_clicked(); void on_buttonReflFrontSelect_clicked(); void on_buttonReflFrontClear_clicked(); void on_buttonReflBackSelect_clicked(); diff --git a/qglview/material_editor.ui b/qglview/material_editor.ui index 3390a21..022b899 100644 --- a/qglview/material_editor.ui +++ b/qglview/material_editor.ui @@ -6,8 +6,8 @@ 0 0 - 327 - 593 + 470 + 692 @@ -23,79 +23,124 @@ 2 - - - + + + Diffuse + + + + + Color: + + + + + + + true + + + + + + + - - - - true - - - - - - + + + Specular + + + + + Color: + + + + + + + true + + + + + + + - - - - true + + + + Self illumination + + + + + Color: + + + + + + + true + + + + + + + - - + + + + Bump + + + + + + + + + + + + Relief + + + + + + + + + + - Light model + Glass - - - - - Phong - - - - - Cook-Torrance - - - - - Minnaert - - - - - Strauss - - - - - Oren-Nayar - - - - - + - Shininess + Roughness - - + + 1.000000000000000 @@ -110,15 +155,15 @@ - + - Shine strength + Specular - - + + 64.000000000000000 @@ -139,14 +184,14 @@ - + Transparency - + 1.000000000000000 @@ -162,14 +207,14 @@ - + Reflectivity - + 1.000000000000000 @@ -185,101 +230,6 @@ - - - - Bump scale - - - - - - - 4.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - Diffuse map - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - Bump map - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - Glass - - - @@ -306,29 +256,41 @@ - - + + - Self-illumination + Dispersion - - - - true + + + + 1.000000000000000 + + + 0.100000000000000 + + + 2 + + + 0.010000000000000 + + + 0.100000000000000 - + Reflection map - - + + QFrame::StyledPanel @@ -532,87 +494,16 @@ - - - - Dispersion - - - - - - - 1.000000000000000 - - - 0.100000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - - Relief map - - - - - - - 2 - - - - - - - - X - - - - - - - ^ - - - - - - - - - Relief scale - - - - - - - 4.000000000000000 - - - 1.000000000000000 - - - 2 - - - 0.010000000000000 - - - 0.100000000000000 + + + + Roughness + + + + + @@ -628,6 +519,15 @@ QPushButton
colorbutton.h
+ + MaterialMapEditor + QWidget +
material_map_editor.h
+ 1 + + changed() + +
@@ -638,8 +538,8 @@ materialChanged() - 272 - 17 + 326 + 49 282 @@ -654,8 +554,8 @@ materialChanged() - 271 - 39 + 325 + 128 284 @@ -664,30 +564,14 @@ - comboModel - currentIndexChanged(int) - MaterialEditor - materialChanged() - - - 279 - 98 - - - 284 - 70 - - - - - spinShine + spinRoughness valueChanged(double) MaterialEditor materialChanged() - 279 - 127 + 443 + 404 280 @@ -696,14 +580,14 @@ - spinShineStrength + spinSpecular valueChanged(double) MaterialEditor materialChanged() - 279 - 153 + 443 + 426 283 @@ -718,8 +602,8 @@ materialChanged() - 279 - 179 + 443 + 448 283 @@ -734,8 +618,8 @@ materialChanged() - 279 - 204 + 443 + 470 284 @@ -743,54 +627,6 @@ - - spinBump - valueChanged(double) - MaterialEditor - materialChanged() - - - 279 - 230 - - - 284 - 202 - - - - - lineDiffuse - textChanged(QString) - MaterialEditor - materialChanged() - - - 264 - 349 - - - 99 - 211 - - - - - lineBump - textChanged(QString) - MaterialEditor - materialChanged() - - - 264 - 376 - - - 98 - 245 - - - spinIOF valueChanged(double) @@ -798,8 +634,8 @@ materialChanged() - 279 - 291 + 443 + 492 284 @@ -814,8 +650,8 @@ materialChanged() - 279 - 121 + 443 + 382 284 @@ -830,8 +666,8 @@ materialChanged() - 322 - 63 + 376 + 202 326 @@ -846,8 +682,8 @@ materialChanged() - 313 - 313 + 460 + 514 326 @@ -856,34 +692,98 @@ - lineRelief - textChanged(QString) + mapDiffuse + changed() MaterialEditor materialChanged() - 123 - 391 + 445 + 63 - 17 - 364 + 469 + 63 - spinRelief - valueChanged(double) + mapSpecular + changed() MaterialEditor materialChanged() - 317 - 260 + 443 + 143 - 327 - 261 + 467 + 143 + + + + + mapSelfIllum + changed() + MaterialEditor + materialChanged() + + + 447 + 216 + + + 468 + 216 + + + + + mapBump + changed() + MaterialEditor + materialChanged() + + + 450 + 308 + + + 469 + 260 + + + + + mapRelief + changed() + MaterialEditor + materialChanged() + + + 450 + 353 + + + 469 + 304 + + + + + mapRoughness + changed() + MaterialEditor + materialChanged() + + + 442 + 257 + + + 474 + 250 diff --git a/qglview/material_map_editor.cpp b/qglview/material_map_editor.cpp new file mode 100644 index 0000000..ab07fd6 --- /dev/null +++ b/qglview/material_map_editor.cpp @@ -0,0 +1,72 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#include "material_map_editor.h" +#include "ui_material_map_editor.h" + + +MaterialMapEditor::MaterialMapEditor(QWidget * parent): QWidget(parent) { + ui = new Ui::MaterialMapEditor(); + ui->setupUi(this); + active = true; +} + + +void MaterialMapEditor::changeEvent(QEvent * e) { + return; + QWidget::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } +} + + +void MaterialMapEditor::setMap(const Map & m) { + active = false; + ui->linePath->setProperty("GLpath", m.bitmap_path); ui->linePath->setText(QFileInfo(m.bitmap_path).fileName()); + active = true; +} + + +Map MaterialMapEditor::map() { + Map m; + m.color_amount = ui->sliderAmount->value(); + m.color_offset = ui->sliderOffset->value(); + m.bitmap_path = ui->linePath->property("GLpath").toString(); + return m; +} + + +void MaterialMapEditor::on_buttonSelect_clicked() { + QString str = QFileDialog::getOpenFileName(this, "Select image", ui->linePath->property("GLpath").toString(), "Images(*.bmp *.jpg *.jpeg *.png *.tif *.tiff *.tga);;All files(*)"); + if (str.isEmpty()) return; + ui->linePath->setProperty("GLpath", str); + ui->linePath->setText(QFileInfo(str).fileName()); + mapChanged(); +} + + +void MaterialMapEditor::on_buttonClear_clicked() { + ui->linePath->setText(""); + ui->linePath->setProperty("GLpath", ""); + mapChanged(); +} diff --git a/qglview/material_map_editor.h b/qglview/material_map_editor.h new file mode 100644 index 0000000..c537e3f --- /dev/null +++ b/qglview/material_map_editor.h @@ -0,0 +1,54 @@ +/* + QGLView + Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com + + 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 . +*/ + +#ifndef MATERIAL_MAP_EDITOR_H +#define MATERIAL_MAP_EDITOR_H + +#include +#include "glmaterial.h" + +namespace Ui { + class MaterialMapEditor; +}; + +class MaterialMapEditor: public QWidget +{ + Q_OBJECT +public: + explicit MaterialMapEditor(QWidget * parent = 0); + + void setMap(const Map & m); + Map map(); + +protected: + void changeEvent(QEvent * e); + + bool active; + Ui::MaterialMapEditor * ui; + +private slots: + void mapChanged() {if (active) emit changed();} + void on_buttonSelect_clicked(); + void on_buttonClear_clicked(); + +signals: + void changed(); + +}; + +#endif // MATERIAL_MAP_EDITOR_H diff --git a/qglview/material_map_editor.ui b/qglview/material_map_editor.ui new file mode 100644 index 0000000..3f4ba26 --- /dev/null +++ b/qglview/material_map_editor.ui @@ -0,0 +1,165 @@ + + + MaterialMapEditor + + + + 0 + 0 + 509 + 74 + + + + + QFormLayout::AllNonFixedFieldsGrow + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + + + 2 + + + + + + + + X + + + + + + + ^ + + + + + + + + + Amount: + + + + + + + -10.000000000000000 + + + 10.000000000000000 + + + 1.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.200000000000000 + + + + + + + Offset: + + + + + + + -10.000000000000000 + + + 10.000000000000000 + + + 2 + + + 0.050000000000000 + + + 0.200000000000000 + + + + + + + + SpinSlider + QWidget +
spinslider.h
+
+
+ + + + linePath + textChanged(QString) + MaterialMapEditor + mapChanged() + + + 175 + 19 + + + 99 + 73 + + + + + sliderAmount + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 440 + 38 + + + 512 + 37 + + + + + sliderOffset + valueChanged(double) + MaterialMapEditor + mapChanged() + + + 497 + 66 + + + 511 + 65 + + + + + + mapChanged() + +
diff --git a/qglview/qglview.cpp b/qglview/qglview.cpp index cd62d0a..f4f77c2 100644 --- a/qglview/qglview.cpp +++ b/qglview/qglview.cpp @@ -23,7 +23,9 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) { setFrameShape(QFrame::NoFrame); setViewportUpdateMode(FullViewportUpdate); setCacheMode(CacheNone); - setViewport(new QGLWidget(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::AlphaChannel | QGL::DirectRendering | QGL::SampleBuffers))); + QGLFormat f(QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::AlphaChannel | QGL::DirectRendering | QGL::SampleBuffers); + f.setSwapInterval(0); + setViewport(new QGLWidget(f)); setMouseTracking(true); setFocusPolicy(Qt::WheelFocus); setScene(new QGraphicsScene()); @@ -51,7 +53,7 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) { selectionHaloFill_ = 0.5; shadow_map_size = dynamic_cubemap_size = 512; //lmode = Simple; - shader_select = shader_halo = shader_rope = 0; + shader_select = shader_halo = 0; cur_luminance = 1.; accom_time = 32.; accom_max_speed = 0.1; @@ -74,7 +76,7 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) { QGLView::~QGLView() { if (shader_select != 0) delete shader_select; if (shader_halo != 0) delete shader_halo; - if (shader_rope != 0) delete shader_rope; + //if (shader_rope != 0) delete shader_rope; } @@ -112,7 +114,7 @@ void QGLView::drawBackground(QPainter * painter, const QRectF & rect) { f = false; paintGL(); painter_->endNativePainting(); - glDisable(GL_DEPTH_TEST); + glDisableDepth(); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glReleaseTextures(); @@ -131,7 +133,7 @@ void QGLView::initializeGL() { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //glEnable(GL_TEXTURE_2D); //glEnable(GL_TEXTURE_CUBE_MAP); - glEnable(GL_DEPTH_TEST); + glEnableDepth(); glEnable(GL_CULL_FACE); glEnableClientState(GL_VERTEX_ARRAY); @@ -168,7 +170,7 @@ void QGLView::initializeGL() { shader_select = new QGLShaderProgram(context()); shader_halo = new QGLShaderProgram(context()); - shader_rope = new QGLShaderProgram(context()); + //shader_rope = new QGLShaderProgram(context()); reloadThisShaders(); is_init = true; @@ -192,16 +194,17 @@ void QGLView::initializeGL() { void QGLView::paintGL() { //QMutexLocker ml_v(&v_mutex); glEnable(GL_CULL_FACE); - //glDisble(GL_CULL_FACE); + //glDisable(GL_CULL_FACE); camera_.apply(aspect); + start_rp.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + //objects_.buildTransform(); /// Selection detect //glClearFramebuffer(QColor(100, 0, 0, 0)); if (mouseSelect_) { glReleaseTextures(); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDepthMask(GL_TRUE); + glEnableDepth(); glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_CUBE_MAP); @@ -248,8 +251,7 @@ void QGLView::paintGL() { renderHalo(sel_obj, ids.key(sel_obj), selectionHaloColor_, selectionHaloFill_); } fbo_selection.release(); - glEnable(GL_DEPTH_TEST); - glEnable(GL_RESCALE_NORMAL); + glEnableDepth(); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); @@ -277,7 +279,7 @@ void QGLView::paintGL() { glEnable(GL_BLEND); glDisable(GL_TEXTURE_CUBE_MAP); glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); + glDisableDepth(); glBlendFunc(GL_SRC_ALPHA, GL_ONE); if (selectionHalo_) { glBindTexture(GL_TEXTURE_2D, fbo_selection.colorTexture(2)); @@ -372,7 +374,17 @@ void QGLView::renderSelection() { ids.clear(); if (shaders_supported) sh_id_loc = shader_select->uniformLocation("id"); //qDebug() << sh_id_loc; + start_rp.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + glPushMatrix(); renderSingleSelection(objects_); + glPopMatrix(); +} + + +void QGLView::renderShadow() { + glPushMatrix(); + renderSingleShadow(objects_); + glPopMatrix(); } @@ -382,32 +394,27 @@ void QGLView::renderSingleSelection(GLObjectBase & o) { o.loadTextures(); } if (!o.visible_ || !o.select_) return; - glPushMatrix(); - if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_); - if (o.raw_matrix) { - qglMultMatrix(o.mat_); - } else { - if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.); - if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.); - if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.); - if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_); - } + QMatrix4x4 curview = start_rp.view_matrix * o.itransform_; ids.insert(cid, &o); - if (shaders_supported) shader_select->setUniformValue(sh_id_loc, QVector4D(float((cid >> 24) & 0xFF) / 255.f, - float((cid >> 16) & 0xFF) / 255.f, - float((cid >> 8) & 0xFF) / 255.f, - float(cid & 0xFF) / 255.f)); - else glColor4f(float((cid >> 24) & 0xFF) / 255.f, + if (shaders_supported){ + setUniformMatrices(shader_select, start_rp.proj_matrix, curview); + shader_select->setUniformValue(sh_id_loc, QVector4D(float((cid >> 24) & 0xFF) / 255.f, + float((cid >> 16) & 0xFF) / 255.f, + float((cid >> 8) & 0xFF) / 255.f, + float(cid & 0xFF) / 255.f)); + } else { + setGLMatrix(curview); + glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f); + } //qDebug() << o.name() << "assign to" << sh_id_loc << cid; //glColor4f(float((cid >> 24) & 0xFF) / 255.f, float((cid >> 16) & 0xFF) / 255.f, float((cid >> 8) & 0xFF) / 255.f, float(cid & 0xFF) / 255.f); ++cid; - o.draw(true); + o.draw(0, true); foreach (GLObjectBase * i, o.children_) renderSingleSelection(*i); - glPopMatrix(); } @@ -417,19 +424,13 @@ void QGLView::renderSingleShadow(GLObjectBase & o) { o.loadTextures(); } if (!o.visible_) return; - glPushMatrix(); - if (o.pos_.x() != 0. || o.pos_.y() != 0. || o.pos_.z() != 0.) qglTranslate(o.pos_); - if (o.angles_.z() != 0.) glRotated(o.angles_.z(), 0., 0., 1.); - if (o.angles_.y() != 0.) glRotated(o.angles_.y(), 0., 1., 0.); - if (o.angles_.x() != 0.) glRotated(o.angles_.x(), 1., 0., 0.); - if (o.scale_.x() != 1. || o.scale_.y() != 1. || o.scale_.z() != 1.) qglScale(o.scale_); + setGLMatrix(start_rp.view_matrix * o.itransform_); glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != GLObjectBase::View ? o.render_mode : (rmode != GLObjectBase::View ? rmode : GL_FILL)); glLineWidth(o.line_width > 0. ? o.line_width : lineWidth_); glPointSize(o.line_width > 0. ? o.line_width : lineWidth_); - o.draw(true); + o.draw(0, true); foreach (GLObjectBase * i, o.children_) renderSingleSelection(*i); - glPopMatrix(); } diff --git a/qglview/qglview.h b/qglview/qglview.h index b1abd87..40355f5 100644 --- a/qglview/qglview.h +++ b/qglview/qglview.h @@ -35,6 +35,7 @@ #include #include "glprimitives.h" #include "glparticles_system.h" +#include "glrendererbase.h" class QGLView: public QGraphicsView, public QGLViewBase @@ -190,7 +191,7 @@ public: void setSelectionRectBrush(const QBrush & v) {sel_brush = v;} GLdouble aspect, iaspect; - QGLShaderProgram * shader_rope; + //QGLShaderProgram * shader_rope; protected: virtual void drawBackground(QPainter * painter, const QRectF & rect); @@ -210,7 +211,7 @@ protected: inline void applyFog(); void renderSelection(); - void renderShadow() {renderSingleShadow(objects_);} + void renderShadow(); void checkCaps(); void collectLights(); @@ -222,7 +223,6 @@ private: void renderSingleSelection(GLObjectBase & o); void renderSingleShadow(GLObjectBase & o); void renderHalo(const GLObjectBase * obj, const int iid, const QColor & color, const double & fill); - void applyLightShader(Material::LightModel type); QList collectGraphicItems(); void collectGraphicItems(QList & list, QGraphicsItem * o); void reloadThisShaders(); @@ -253,6 +253,7 @@ private: SelectionMode sel_mode; Qt::MouseButton sel_button; Qt::KeyboardModifier sel_mod; + GLRendererBase::RenderingParameters start_rp; double lineWidth_, linearFiltering_, accom_time, accom_max_speed, cur_luminance; double fogDensity_, fogStart_, fogEnd_, fps_, fps_tm, hoverHaloFill_, selectionHaloFill_; int timer, fps_cnt, sh_id_loc, shadow_map_size, dynamic_cubemap_size; diff --git a/qglview/renderer_deferred_shading.cpp b/qglview/renderer_deferred_shading.cpp index 417f4ea..e3540a3 100644 --- a/qglview/renderer_deferred_shading.cpp +++ b/qglview/renderer_deferred_shading.cpp @@ -19,67 +19,86 @@ #include "renderer_deferred_shading.h" -RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), fbo(5, true, GL_RGBA16F) { +RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), fbo(6, true, GL_RGBA16F) { shader_fxaa = shader_ds_0 = shader_ds_1 = 0; } void RendererDeferredShading::renderScene() { + prepareUniform(); + QMatrix4x4 view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + QMatrix4x4 proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + QMatrix4x4 viewprojinv = (proj_matrix * view_matrix).inverted(); + corner_dirs[0] = (QVector4D(-1, -1, 1, 1) * viewprojinv).normalized(); + corner_dirs[1] = (QVector4D( 1, -1, 1, 1) * viewprojinv).normalized(); + corner_dirs[2] = (QVector4D( 1, 1, 1, 1) * viewprojinv).normalized(); + corner_dirs[3] = (QVector4D(-1, 1, 1, 1) * viewprojinv).normalized(); + //qDebug() << corner_dirs[0] << corner_dirs[1] << corner_dirs[2] << corner_dirs[3]; int passes = (view.lightsCount() - 1) / 8 + 1; - QMatrix4x4 pm = getGLMatrix(GL_PROJECTION_MATRIX);//, mvm = getGLMatrix(GL_MODELVIEW_MATRIX), pmvm = pm * mvm, lpm, lmvm, lpmvm; if (passes < 1) passes = 1; fbo.bind(); - int buffs[] = {0, 1, 2}; + int buffs[] = {0, 1, 2, 3}; fbo.setWriteBuffers(buffs); + if (white_image_id == 0) { + glActiveTextureChannel(6); + white_image_id = ((GLTextureManagerBase*)currentGLTextureManager)->loadTexture(white_image, false); + glBindTexture(GL_TEXTURE_2D, white_image_id); + glActiveTextureChannel(0); + } glClearFramebuffer(QColor(0, 0, 0, 0)); //glEnable(GL_TEXTURE_2D); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDepthMask(GL_TRUE); + glEnableDepth(); shader_ds_0->bind(); + setUniform(shader_ds_0); + shader_ds_0->setUniformValue("z_far", GLfloat(view.depthEnd())); + shader_ds_0->setUniformValue("z_near", GLfloat(view.depthStart())); shader_ds_0->setUniformValue("t0", 0); shader_ds_0->setUniformValue("t1", 1); shader_ds_0->setUniformValue("t2", 2); + shader_ds_0->setUniformValue("t3", 3); shader_ds_0->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height())); - renderObjects(GLObjectBase::Solid, 0, 0, true, false, false); + renderObjects(GLObjectBase::Solid, 0, shader_ds_0, true, false, false); //glReleaseShaders(); //fbo.release(); + glResetAllTransforms(); + prepareUniform(); glSetLightEnabled(false); glDisable(GL_BLEND); //glBlendFunc(GL_ONE, GL_ONE); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); + glDisableDepth(); shader_ds_1->bind(); + setUniform(shader_ds_1); + shader_ds_1->setUniformValue("z_far", GLfloat(view.depthEnd())); + shader_ds_1->setUniformValue("z_near", GLfloat(view.depthStart())); shader_ds_1->setUniformValue("t0", 0); shader_ds_1->setUniformValue("t1", 1); shader_ds_1->setUniformValue("t2", 2); + shader_ds_1->setUniformValue("t3", 3); + shader_ds_1->setUniformValue("td", 4); shader_ds_1->setUniformValue("back_color", view.backColor()); - shader_ds_1->setUniformValue("mat", pm.inverted()); + shader_ds_1->setUniformValue("mat_proji", proj_matrix.inverted()); shader_ds_1->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height())); - fbo.setWriteBuffer(3); + fbo.setWriteBuffer(4); fbo.bindColorTextures(); + fbo.bindDepthTexture(4); glClearFramebuffer(Qt::black, false); - QVector lpos; - GLfloat glmvm[16]; - glGetFloatv(GL_MODELVIEW_MATRIX, glmvm); - //glResetAllTransforms(); + //QVector lpos; + //qDebug() << view_matrix; for (int l = 0; l < passes; ++l) { - fbo.setWriteBuffer(4 - l % 2); - shader_ds_1->setUniformValue("tb", 3 + l % 2); - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(glmvm); - setupLights(l, 8); - shader_ds_1->setUniformValue("lightsCount", cplc); - glDrawQuad(); + fbo.setWriteBuffer(5 - l % 2); + shader_ds_1->setUniformValue("tb", 4 + l % 2); + setupDSLights(l, 16, view_matrix); + //shader_ds_1->setUniformValue("lightsCount", cplc); + drawFB(shader_ds_1); //renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled()); //renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled()); - glFinish(); + glFlush(); } fbo.release(); glReleaseShaders(); glActiveTextureChannel(0); - glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(3 + passes % 2)); + glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(4 + passes % 2)); if (view.isFXAAEnabled()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -107,9 +126,82 @@ void RendererDeferredShading::reloadShaders() { void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRendererBase::RenderingParameters & rp) { - shader_ds_0->setUniformValue("has_diffuse", object.material().diffuse.bitmap_id != 0); - shader_ds_0->setUniformValue("has_bump", object.material().bump.bitmap_id != 0); - shader_ds_0->setUniformValue("has_height", object.material().relief.bitmap_id != 0); - shader_ds_0->setUniformValue("bump_scale", object.material().bump_scale); - shader_ds_0->setUniformValue("height_scale", object.material().relief_scale); + shader_ds_0->setUniformValue("has_diffuse", object.material().map_diffuse.bitmap_id != 0); + shader_ds_0->setUniformValue("has_bump", object.material().map_bump.bitmap_id != 0); + shader_ds_0->setUniformValue("has_height", object.material().map_relief.bitmap_id != 0); + shader_ds_0->setUniformValue("bump_scale", object.material().map_bump.color_amount); + shader_ds_0->setUniformValue("height_scale", object.material().map_relief.color_amount); + glActiveTextureChannel(6); + glBindTexture(GL_TEXTURE_2D, white_image_id); +} + + +void RendererDeferredShading::setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix) { + int light_start, light_end, lmax; + light_start = pass * lights_per_pass; + light_end = qMin((pass + 1) * lights_per_pass, view.lights().size()); + lmax = light_start + 8; + amb_light.intensity = (pass == 0 ? 1. : 0.); + amb_light.setColor(pass == 0 ? view.ambientColor() : Qt::black); + amb_light.setName("ambient"); + setUniformLight(shader_ds_1, &amb_light, "qgl_AmbientLight", QMatrix4x4()); + amb_light.intensity = 0.; + QVector lv; + for (int i = light_start; i < light_end; ++i) + lv << view.lights()[i]; + amb_light.setName("null"); + for (int i = light_end; i < lmax; ++i) + lv << &amb_light; + setUniformLights(shader_ds_1, lv, view_matrix); +} + + +void RendererDeferredShading::setupAmbientLight(const QColor & a, bool first_pass) { + +} + + +void RendererDeferredShading::prepareUniform() { + pm = getGLMatrix(GL_PROJECTION_MATRIX); + mvm = getGLMatrix(GL_MODELVIEW_MATRIX); + mvpm = pm * mvm; + pim = pm.inverted(); + mvim = mvm.inverted(); + mvpim = mvpm.inverted(); + nm = mvm.normalMatrix(); +} + + +void RendererDeferredShading::setUniform(QGLShaderProgram * prog) { + //qDebug() << mvm; + prog->setUniformValue("qgl_ModelViewMatrix", mvm); + prog->setUniformValue("qgl_ProjectionMatrix", pm); + prog->setUniformValue("qgl_ModelViewProjectionMatrix", mvpm); + prog->setUniformValue("qgl_NormalMatrix", nm); + prog->setUniformValue("qgl_ModelViewMatrixInverse", mvim); + prog->setUniformValue("qgl_ProjectionMatrixInverse", pim); + prog->setUniformValue("qgl_ModelViewProjectionMatrixInverse", mvpim); + prog->setUniformValue("qgl_ModelViewMatrixTranspose", mvm.transposed()); + prog->setUniformValue("qgl_ProjectionMatrixTranspose", pm.transposed()); + prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", mvpm.transposed()); + prog->setUniformValue("qgl_ModelViewMatrixInverseTranspose", mvim.transposed()); + prog->setUniformValue("qgl_ProjectionMatrixInverseTranspose", pim.transposed()); + prog->setUniformValue("qgl_ModelViewProjectionMatrixInverseTranspose", mvpim.transposed()); +} + + +void RendererDeferredShading::drawFB(QGLShaderProgram * prog) { + glSetPolygonMode(GL_FILL); + int loc = prog->attributeLocation("qgl_Color"); + glVertexAttrib3f(loc, 1.f, 1.f, 1.f); + int locv = prog->attributeLocation("qgl_Vertex"), + loct = prog->attributeLocation("qgl_Texture"), + locc = prog->attributeLocation("view_corner"); + glBegin(GL_QUADS); + glColor3f(1.f, 1.f, 1.f); + prog->setAttributeValue(locc, corner_dirs[0]); glVertexAttrib2f(loct, 0.f, 0.f); glTexCoord2f(0.f, 0.f); glVertexAttrib2f(locv, -1.f, -1.f); glVertex2f(-1.f, -1.f); + prog->setAttributeValue(locc, corner_dirs[1]); glVertexAttrib2f(loct, 1.f, 0.f); glTexCoord2f(1.f, 0.f); glVertexAttrib2f(locv, 1.f, -1.f); glVertex2f(1.f, -1.f); + prog->setAttributeValue(locc, corner_dirs[2]); glVertexAttrib2f(loct, 1.f, 1.f); glTexCoord2f(1.f, 1.f); glVertexAttrib2f(locv, 1.f, 1.f); glVertex2f(1.f, 1.f); + prog->setAttributeValue(locc, corner_dirs[3]); glVertexAttrib2f(loct, 0.f, 1.f); glTexCoord2f(0.f, 1.f); glVertexAttrib2f(locv, -1.f, 1.f); glVertex2f(-1.f, 1.f); + glEnd(); } diff --git a/qglview/renderer_deferred_shading.h b/qglview/renderer_deferred_shading.h index 4b9d35c..2b98c0d 100644 --- a/qglview/renderer_deferred_shading.h +++ b/qglview/renderer_deferred_shading.h @@ -30,17 +30,28 @@ public: virtual void renderScene(); protected: - virtual void init(int width, int height) {fbo.resize(width, height);} - virtual void resize(int width, int height) {fbo.resize(width, height);} - virtual void reloadShaders(); - virtual void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp); - virtual void setupShadersLights(int lights_count) {cplc = lights_count;} + void init(int width, int height) {fbo.resize(width, height);} + void resize(int width, int height) {fbo.resize(width, height);} + void reloadShaders(); + void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp); + void setupShadersLights(int lights_count) {cplc = lights_count;} + void setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix); + void setupAmbientLight(const QColor & a, bool first_pass); + + void prepareUniform(); + void setUniform(QGLShaderProgram * prog); + void drawFB(QGLShaderProgram * prog); private: int cplc; GLFramebuffer fbo; QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1; + QMatrix4x4 pm, mvm, mvpm, pim, mvim, mvpim; + QMatrix3x3 nm; + QVector4D corner_dirs[4]; + Light amb_light; + }; #endif // RENDERER_DEFERRED_SHADING_H diff --git a/qglview/renderer_simple.cpp b/qglview/renderer_simple.cpp index dfc21b3..5b026df 100644 --- a/qglview/renderer_simple.cpp +++ b/qglview/renderer_simple.cpp @@ -62,9 +62,7 @@ void RendererSimple::renderScene() { if (passes > 1) fbo.setWriteBuffer(1); if (l == 0) { glClearFramebuffer(view.backColor()); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glDepthMask(GL_TRUE); + glEnableDepth(); } else { glClearFramebuffer(Qt::black, false); glEnable(GL_DEPTH_TEST); @@ -98,8 +96,7 @@ void RendererSimple::renderScene() { glBlendFunc(GL_ONE, GL_ONE); glReleaseTextures(); glBindTexture(GL_TEXTURE_2D, fbo.colorTexture(1)); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); + glDisableDepth(); fbo.setWriteBuffer(0); glDrawQuad(); } @@ -111,7 +108,7 @@ void RendererSimple::renderScene() { glBindTexture(GL_TEXTURE_2D, fbo.colorTexture()); glSetLightEnabled(false); glSetCapEnabled(GL_BLEND, false); - glDisable(GL_DEPTH_TEST); + glDisableDepth(); if (view.isFXAAEnabled()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/qglview/rope_system.cpp b/qglview/rope_system.cpp index ea004b1..4dd9677 100644 --- a/qglview/rope_system.cpp +++ b/qglview/rope_system.cpp @@ -47,7 +47,7 @@ void RopeSystem::init() { } -void RopeSystem::draw(bool simplest) { +void RopeSystem::draw(QGLShaderProgram * prog, bool simplest) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_1D, tex[0]); glGetTexImage(GL_TEXTURE_1D, 0, GL_RGBA, GL_FLOAT, pos.data()); diff --git a/qglview/rope_system.h b/qglview/rope_system.h index 90d6794..aa84df1 100644 --- a/qglview/rope_system.h +++ b/qglview/rope_system.h @@ -27,7 +27,7 @@ public: RopeSystem(); ~RopeSystem(); - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); virtual void init(); virtual void update() {} diff --git a/qglview/shaders/dsl_pass_0.frag b/qglview/shaders/dsl_pass_0.frag index 2ea6235..8bbe69c 100644 --- a/qglview/shaders/dsl_pass_0.frag +++ b/qglview/shaders/dsl_pass_0.frag @@ -1,46 +1,48 @@ -#version 130 +#version 150 in vec3 src_normal, normal;//, et; -in vec4 pos, col; +in vec4 pos; in float fogCoord; -uniform int light_model; -uniform sampler2D t0, t1, t2, t3; -uniform float bump_scale, height_scale; -uniform bool acc_fog, has_diffuse, has_bump, has_height; +uniform bool acc_fog; uniform vec2 dt; +uniform float z_far, z_near; const vec3 luma = vec3(0.299, 0.587, 0.114); void main(void) { - vec4 dc = col; - vec2 tc = gl_TexCoord[0].xy; - float hei = 0.; - if (has_height) hei = dot(texture2D(t2, gl_TexCoord[0].xy).rgb, luma) * height_scale; - if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord); + float z = pos.w;//((z_near / (z_near-z_far)) * z_far) / (pos.w - (z_far / (z_far-z_near))); + vec4 dc = qgl_FragColor; + vec2 tc = qgl_FragTexture.xy; + float hei = dot(texture2D(qgl_Material.map_relief.map, tc).rgb, luma) * qgl_Material.map_relief.amount + qgl_Material.map_relief.offset; + //if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord); vec3 n, dn; - if (has_bump) { - dn = (texture2D(t1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 1.)) * bump_scale; - dn.x = -dn.x; - dn = dn * mat3(gl_ModelViewMatrixInverse); - n = normalize(normal - dn); - } else n = normalize(normal); + dn = (texture2D(qgl_Material.map_bump.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_bump.amount + qgl_Material.map_bump.offset; + dn.x = -dn.x; + dn = dn * mat3(qgl_ModelViewMatrixInverse); + n = normalize(normal - dn); - if (has_diffuse) { + /*vec2 dpm = normalize(gl_FragCoord.xy * dt * 2. - vec2(1., 1.)), ntc; + ntc = gl_FragCoord.xy * dt * 2. - vec2(1., 1.) + dpm * hei; + dpm = gl_ModelViewProjectionMatrixInverse + dpm = dpm * gl_ModelViewProjectionMatrixInverse; + dpm += */ + //tc += 1+et.xy * hei/10;// / et.z; + dc *= texture2D(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset; - /*vec2 dpm = normalize(gl_FragCoord.xy * dt * 2. - vec2(1., 1.)), ntc; - ntc = gl_FragCoord.xy * dt * 2. - vec2(1., 1.) + dpm * hei; - dpm = gl_ModelViewProjectionMatrixInverse - dpm = dpm * gl_ModelViewProjectionMatrixInverse; - dpm += */ - //tc += 1+et.xy * hei/10;// / et.z; - dc *= texture2D(t0, tc); - } + vec4 spec = texture2D(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset; + spec *= qgl_Material.color_specular * qgl_Material.specular; + vec4 rough = texture2D(qgl_Material.map_roughness.map, tc) * qgl_Material.map_roughness.amount + qgl_Material.map_roughness.offset; + rough *= qgl_Material.roughness; + vec4 self = texture2D(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset; + self *= qgl_Material.color_self_illumination; + + qgl_FragData[0] = vec4(dc.rgb, z); + qgl_FragData[1] = vec4(n.xyz / 2. + vec3(0.5), rough); + qgl_FragData[2] = vec4(spec.rgb, hei); + qgl_FragData[3] = vec4(pos.xyz, pos.z); - gl_FragData[0] = vec4(dc.rgb, pos.w); - gl_FragData[1] = vec4(n.xyz / 2. + vec3(0.5), gl_FrontMaterial.shininess); - gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, hei); //gl_FragData[0] = vec4(et.xyz, pos.w); //gl_FragDepth = gl_FragCoord.z - clamp(hei / pos.z / pos.z / (abs(n.z) + 1), -0.01, 0.01); /*vec4 dp = pos; diff --git a/qglview/shaders/dsl_pass_0.vert b/qglview/shaders/dsl_pass_0.vert index 380d322..055a73c 100644 --- a/qglview/shaders/dsl_pass_0.vert +++ b/qglview/shaders/dsl_pass_0.vert @@ -1,7 +1,7 @@ -#version 130 +#version 150 out vec3 src_normal, normal;//, et; -out vec4 pos, col; +out vec4 pos; out float fogCoord, fs_gid; uniform bool acc_fog; @@ -9,34 +9,19 @@ uniform vec2 dt; uniform vec3 eye; void main(void) { - normal = (gl_NormalMatrix * gl_Normal); - - pos.xyz = vec3(gl_ModelViewMatrix * gl_Vertex); - col = gl_Color; - if (acc_fog) { + normal = (qgl_NormalMatrix * qgl_Normal); + pos.xyz = vec3(qgl_ModelViewMatrix * qgl_Vertex); + /*if (acc_fog) { fogCoord = (gl_Fog.end - length(pos.xyz) * 0.85) / (gl_Fog.end - gl_Fog.start); fogCoord = 1. - clamp(fogCoord, 0., 1.); - } - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_TexCoord[1] = gl_MultiTexCoord1; - gl_Position = ftransform(); - src_normal = normalize(/*gl_NormalMatrix * */vec3(pos.xy * dt * 2., 0)); - //pos = gl_Position; - - //vec3 v = normalize(-pos.xyz); // vector to the eye - - /*vec3 t = gl_NormalMatrix * vec3(1., 0., 0.); - vec3 b = gl_NormalMatrix * vec3(0., 1., 0.); - et = vec3(dot(v, t), dot(v, b), dot(v, normal));*/ - - //vec3 t = normalize(gl_NormalMatrix * vec3(gl_MultiTexCoord0.yx, 1)); - //vec3 b = cross(normal, t); - - /*mat3 tbnMatrix = mat3(t.x, b.x, normal.x, - t.y, b.y, normal.y, - t.z, b.z, normal.z); - et = tbnMatrix * v;*/ - - - pos.w = gl_Position.w; + }*/ + //gl_TexCoord[0] = gl_MultiTexCoord0; + //gl_TexCoord[1] = gl_MultiTexCoord1; + qgl_FragTexture = qgl_Texture; + qgl_FragColor = qgl_Color; + vec4 tp = qgl_ftransform(); + //tp /= tp.w; + src_normal = normalize(vec3(pos.xy * dt * 2., 0)); + pos.w = tp.w; + gl_Position = tp;//ftransform(); } diff --git a/qglview/shaders/dsl_pass_1.frag b/qglview/shaders/dsl_pass_1.frag index 345e0dc..a217907 100644 --- a/qglview/shaders/dsl_pass_1.frag +++ b/qglview/shaders/dsl_pass_1.frag @@ -1,69 +1,77 @@ -#version 130 +#version 150 //#extension GL_EXT_gpu_shader4 : enable -uniform vec3 ambient; +in vec4 view_dir; +in vec3 view_pos; -uniform sampler2D t0, t1, t2, tb; +uniform vec3 ambient; +uniform sampler2D t0, t1, t2, t3, tb; +uniform sampler2D td; uniform int gid, lightsCount; +uniform float z_near, z_far; uniform bool firstPass; uniform vec2 dt; uniform vec4 back_color; -uniform mat4 mat; +uniform mat4 mat_proji; float light_diffuse(int model, vec3 l, vec3 n) {return max(0., dot(l, n));} -float light_specular(int model, vec3 l, vec3 n, vec3 h, vec3 v, float shininess) {return max(0., pow(dot(n, h), shininess));} +//float light_specular(int model, vec3 l, vec3 n, vec3 h, vec3 v, float shininess) {return max(0., pow(dot(n, h), shininess));} vec4 pos, lpos; vec3 li, si, ldir, halfV; float sh_pow, sh_mul, dist, NdotL, spot, ldist, diff; void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { - lpos = gl_LightSource[index].position; + lpos = qgl_Light[index].position; ldir = lpos.xyz - (pos.xyz * lpos.w); ldist = length(ldir); ldir = normalize(ldir); NdotL = max(dot(n, ldir), 0.); spot = step(0., NdotL); if (NdotL > 0.) { - if (gl_LightSource[index].spotCutoff < 180.) { + /*if (gl_LightSource[index].spotCutoff < 180.) { spot = max(dot(-ldir, gl_LightSource[index].spotDirection.xyz), 0.); spot *= step(gl_LightSource[index].spotCosCutoff, spot); spot = pow(spot, (gl_LightSource[index].spotExponent + 0.001)); - } + }*/ + spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation)); halfV = normalize(ldir + v); - spot /= (gl_LightSource[index].constantAttenuation + ldist * (gl_LightSource[index].linearAttenuation + ldist * gl_LightSource[index].quadraticAttenuation)); - //li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n); - //si += spot * gl_LightSource[index].specular.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow); + ///li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n); + ///si += spot * gl_LightSource[index].specular.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow); float NdotLs = NdotL*NdotL; float ndlc = (1. - NdotLs) / NdotLs; float der = NdotLs * (sh_mul + ndlc); diff = 2. / (1. + sqrt(1. + (1. - sh_mul) * ndlc)); - li += spot * gl_LightSource[index].diffuse.rgb * diff * light_diffuse(0, ldir, n); - si += spot * gl_LightSource[index].specular.rgb * (sh_mul / (der*der) / 3.1416); + li += spot * qgl_Light[index].color.rgb * diff;// * light_diffuse(0, ldir, n); + si += spot * qgl_Light[index].color.rgb * (sh_mul / (der*der) / 3.1416); } } void main(void) { //if (d == 1.) discard; - vec4 v0 = texture2D(t0, gl_TexCoord[0].xy); + vec2 tc = qgl_FragTexture.xy; + vec4 v0 = texture2D(t0, tc); if (v0.w == 0.) { - gl_FragColor = back_color; + qgl_FragData[0] = back_color; return; } - vec4 v1 = texture2D(t1, gl_TexCoord[0].xy), v2 = texture2D(t2, gl_TexCoord[0].xy);//, v3 = texture2D(t2, gl_TexCoord[0].xy); + vec4 v1 = texture2D(t1, tc), v2 = texture2D(t2, tc), v3 = texture2D(t3, tc); vec2 sp = gl_FragCoord.xy * dt * 2 - vec2(1, 1); vec3 dc = v0.rgb, n = v1.xyz * 2. - vec3(1.); float height = v2.w; - li = gl_LightModel.ambient.rgb; + li = qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; + //li = vec3(0.); si = vec3(0.); - pos = vec4(sp, 0, 1.) * mat; - pos *= v0.w; - pos.rgb += n * height; + pos = vec4(sp, 0, 1)*mat_proji; + pos.xyz *= v0.w; + //pos.xy *= 10.; + //pos.z = v0.w; vec3 v = normalize(-pos.xyz); sh_pow = 1. / max((1. - v1.w), 0.0001); sh_mul = max(1. - v1.w, 0.0001); - if (lightsCount > 0) { + //calcLight(0, n, v, v2); + /*if (lightsCount > 0) { calcLight(0, n, v, v2); if (lightsCount > 1) { calcLight(1, n, v, v2); @@ -86,7 +94,15 @@ void main(void) { } } } - } - gl_FragColor.rgb = li * dc + si * v2.rgb + texture2D(tb, gl_TexCoord[0].xy).rgb; - //gl_FragColor.rgb = vec3(v2.rgb); + }*/ + //qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb;// + texture2D(tb, tc).rgb; + //vec4 lp = mat*qgl_Light[0].position; + lpos = qgl_Light[0].position; + ldir = lpos.xyz - pos.xyz; + ldist = length(ldir); + float d = texture2D(td, tc).r; + //float z = ((z_near / (z_near-z_far)) * z_far) / (d - (z_far / (z_far-z_near))); + float z = z_near * z_far / (d * (z_far - z_near) - z_far); + //qgl_FragData[0].rgb = vec3(abs((v0.w)+(v3.z))-0.5); + qgl_FragData[0].rgb = vec3((-z*view_pos)); } diff --git a/qglview/shaders/dsl_pass_1.vert b/qglview/shaders/dsl_pass_1.vert index f2eecdc..30b8182 100644 --- a/qglview/shaders/dsl_pass_1.vert +++ b/qglview/shaders/dsl_pass_1.vert @@ -1,6 +1,13 @@ -#version 130 +#version 150 + +in vec4 view_corner; +out vec4 view_dir; +out vec3 view_pos; void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = ftransform(); + view_dir = view_corner; + view_pos = vec3(qgl_ModelViewMatrix * vec4(qgl_Vertex.xy, 1, 1)); + qgl_FragTexture = qgl_Texture; + qgl_FragColor = qgl_Color; + gl_Position = qgl_ftransform(); } diff --git a/qglview/shaders/selection.frag b/qglview/shaders/selection.frag index e66293d..43ccb95 100644 --- a/qglview/shaders/selection.frag +++ b/qglview/shaders/selection.frag @@ -1,7 +1,7 @@ -#version 120 +#version 150 uniform vec4 id; void main(void) { - gl_FragColor = id; + qgl_FragData[0] = id; } diff --git a/qglview/shaders/selection.vert b/qglview/shaders/selection.vert index 14fc2db..3c87db4 100644 --- a/qglview/shaders/selection.vert +++ b/qglview/shaders/selection.vert @@ -1,5 +1,5 @@ -#version 120 +#version 150 void main(void) { - gl_Position = ftransform(); + gl_Position = qgl_ftransform(); } diff --git a/qglview/shaders/selection_halo.frag b/qglview/shaders/selection_halo.frag index de44a20..74d81f7 100644 --- a/qglview/shaders/selection_halo.frag +++ b/qglview/shaders/selection_halo.frag @@ -1,4 +1,4 @@ -#version 130 +#version 150 uniform vec2 dt; uniform vec4 selected, color; @@ -6,13 +6,14 @@ uniform sampler2D t0; uniform float fill; void main(void) { - vec4 ds0 = abs(textureLodOffset(t0, gl_TexCoord[0].xy, 0., ivec2(-1, 0)) - selected); - vec4 ds1 = abs(textureLodOffset(t0, gl_TexCoord[0].xy, 0., ivec2( 1, 0)) - selected); - vec4 ds2 = abs(textureLodOffset(t0, gl_TexCoord[0].xy, 0., ivec2(0, -1)) - selected); - vec4 ds3 = abs(textureLodOffset(t0, gl_TexCoord[0].xy, 0., ivec2(0, 1)) - selected); + vec2 tc = qgl_FragTexture.xy; + vec4 ds0 = abs(textureLodOffset(t0, tc, 0., ivec2(-1, 0)) - selected); + vec4 ds1 = abs(textureLodOffset(t0, tc, 0., ivec2( 1, 0)) - selected); + vec4 ds2 = abs(textureLodOffset(t0, tc, 0., ivec2(0, -1)) - selected); + vec4 ds3 = abs(textureLodOffset(t0, tc, 0., ivec2(0, 1)) - selected); float d0 = dot(ds0, vec4(1., 1., 1., 1.)), d1 = dot(ds1, vec4(1., 1., 1., 1.)), d2 = dot(ds2, vec4(1., 1., 1., 1.)), d3 = dot(ds3, vec4(1., 1., 1., 1.)); float vs = step(1e-6, d0 + d1 + d2 + d3); float vm = step(1e-3, (d0 * 255.) * (d1 * 255.) * (d2 * 255.) * (d3 * 255.)); float v = mix(vs - vm, vs - vm - vm + 1, fill); - gl_FragColor = vec4(color.rgb, v * color.a); + qgl_FragData[0] = vec4(color.rgb, v * color.a); } diff --git a/qglview/shaders/selection_halo.vert b/qglview/shaders/selection_halo.vert index f2eecdc..6bc001e 100644 --- a/qglview/shaders/selection_halo.vert +++ b/qglview/shaders/selection_halo.vert @@ -1,6 +1,6 @@ -#version 130 +#version 150 void main(void) { - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_Position = ftransform(); + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); } diff --git a/qglview/water_system.cpp b/qglview/water_system.cpp index f8563ca..c50d380 100644 --- a/qglview/water_system.cpp +++ b/qglview/water_system.cpp @@ -172,7 +172,7 @@ void WaterSystem::Particle::process(const QList * > & near_par } -void WaterSystem::draw(bool simplest) { +void WaterSystem::draw(QGLShaderProgram * prog, bool simplest) { //return; pass_ = GLObjectBase::Transparent; //qDebug() << "save states" << cv.size(); diff --git a/qglview/water_system.h b/qglview/water_system.h index f546401..aed421f 100644 --- a/qglview/water_system.h +++ b/qglview/water_system.h @@ -31,9 +31,9 @@ public: WaterSystem(); ~WaterSystem(); - virtual void draw(bool simplest = false); + virtual void draw(QGLShaderProgram * prog, bool simplest = false); virtual void update(); - virtual void init() {createGLTexture(texture, QImage("./media-record.png")); material_.diffuse.bitmap_id = texture; is_init = true;} + virtual void init() {createGLTexture(texture, QImage("./media-record.png")); material_.map_diffuse.bitmap_id = texture; is_init = true;} protected: class Chunk;