diff --git a/qglview/CMakeLists.txt b/qglview/CMakeLists.txt index a8bfb27..29d6010 100644 --- a/qglview/CMakeLists.txt +++ b/qglview/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall") #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3") set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS}") -set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} qad_widgets) +set(LIBS ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${QT_QTXML_LIBRARY} qad_widgets) find_package(OpenGL REQUIRED) list(APPEND LIBS ${OPENGL_LIBRARIES}) @@ -42,4 +42,4 @@ endif () qt4_wrap_cpp(CMOCS_TEST "mainwindow.h" OPTIONS -nw) qt4_wrap_ui(CUIS_TEST "mainwindow.ui") add_executable(qglview_test "main.cpp" "mainwindow.cpp" ${CMOCS_TEST} ${CUIS_TEST}) -target_link_libraries(qglview_test ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} qglview qad_widgets) +target_link_libraries(qglview_test ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${QT_QTXML_LIBRARY} qglview qad_widgets) diff --git a/qglview/globject.cpp b/qglview/globject.cpp index ae6c7dd..6de3007 100644 --- a/qglview/globject.cpp +++ b/qglview/globject.cpp @@ -32,6 +32,8 @@ GLObjectBase::GLObjectBase() { blend_src = GL_SRC_ALPHA; blend_dest = GL_ONE_MINUS_SRC_ALPHA; type_ = Mesh; + raw_matrix = false; + mat_.setToIdentity(); view_ = 0; } @@ -44,6 +46,8 @@ GLObjectBase * GLObjectBase::clone(bool withChildren) { o->accept_fog = accept_fog; o->visible_ = visible_; o->type_ = type_; + o->raw_matrix = raw_matrix; + o->mat_ = mat_; o->pos_ = pos_; o->angles_ = angles_; o->scale_ = scale_; @@ -58,8 +62,12 @@ GLObjectBase * GLObjectBase::clone(bool withChildren) { o->puvws = puvws; o->faces = faces; o->uvws = uvws; + o->norms = norms; o->normals = normals; - o->vbo = vbo; + o->vbo.vertices_ = vbo.vertices_; + o->vbo.normals_ = vbo.normals_; + o->vbo.texcoords_ = vbo.texcoords_; + o->vbo.colors_ = vbo.colors_; o->view_ = 0; o->children_.clear(); if (withChildren) { @@ -126,16 +134,31 @@ void GLObjectBase::calculateBoundingBox() { } +void GLObjectBase::setTransform(const QMatrix4x4 & t) { + raw_matrix = true; + mat_ = t; + pos_ = mat_.column(3).toVector3D(); + mat_.setColumn(3, QVector4D(0., 0., 0., 1.)); + buildTransform(); +} + + void GLObjectBase::buildTransform() { itransform_.setToIdentity(); GLObjectBase * p = parent_; if (p != 0) itransform_ *= p->itransform_; - itransform_.translate(pos_); - itransform_.rotate(angles_.z(), 0., 0., 1.); - itransform_.rotate(angles_.y(), 0., 1., 0.); - itransform_.rotate(angles_.x(), 1., 0., 0.); - itransform_.scale(scale_); + if (raw_matrix) { + itransform_.translate(pos_); + itransform_ *= mat_; + //qDebug() << "raw_matrix" << itransform_; + } else { + itransform_.translate(pos_); + itransform_.rotate(angles_.z(), 0., 0., 1.); + itransform_.rotate(angles_.y(), 0., 1., 0.); + itransform_.rotate(angles_.x(), 1., 0., 0.); + itransform_.scale(scale_); + } foreach (GLObjectBase * i, children_) i->buildTransform(); } @@ -151,10 +174,14 @@ void GLObjectBase::render(int * id, QMap * ids, int sh_id_ if (!visible_) return; glPushMatrix(); if (pos_.x() != 0. || pos_.y() != 0. || pos_.z() != 0.) glTranslated(pos_.x(), pos_.y(), pos_.z()); - 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()); + 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(); if (id != 0) { ++(*id); diff --git a/qglview/globject.h b/qglview/globject.h index 6c3dbc1..57be2e3 100644 --- a/qglview/globject.h +++ b/qglview/globject.h @@ -40,7 +40,7 @@ public: QString name() const {return name_;} 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 init() {calculateBoundingBox(); vbo.init(); vbo.rebuffer(); /*material_.reflection.create();*/ /*qDebug() << "init" << vbo.buffer_;*/ is_init = true;} virtual void draw(bool simplest = false); virtual void update() {} bool isInit() const {return is_init;} @@ -99,37 +99,39 @@ public: double posZ() const {return pos_.z();} QVector3D worldPos() const {return (itransform_ * QVector4D(0, 0, 0, 1.)).toVector3D();} - void rotateX(GLdouble a) {angles_.setX(angles_.x() + a); buildTransform();} - void rotateY(GLdouble a) {angles_.setY(angles_.y() + a); buildTransform();} - void rotateZ(GLdouble a) {angles_.setZ(angles_.z() + a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} - void setRotationX(GLdouble a) {angles_.setX(a); buildTransform();} - void setRotationY(GLdouble a) {angles_.setY(a); buildTransform();} - void setRotationZ(GLdouble a) {angles_.setZ(a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} - void setRotation(const QVector3D & a) {angles_= a; buildTransform();} - void resetRotation() {angles_ = QVector3D(0., 0., 0.); buildTransform();} - QVector3D rotation() const {return angles_;} double rotationX() const {return angles_.x();} double rotationY() const {return angles_.y();} double rotationZ() const {return angles_.z();} + void rotateX(GLdouble a) {raw_matrix = false; angles_.setX(angles_.x() + a); buildTransform();} + void rotateY(GLdouble a) {raw_matrix = false; angles_.setY(angles_.y() + a); buildTransform();} + void rotateZ(GLdouble a) {raw_matrix = false; angles_.setZ(angles_.z() + a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} + void setRotationX(GLdouble a) {raw_matrix = false; angles_.setX(a); buildTransform();} + void setRotationY(GLdouble a) {raw_matrix = false; angles_.setY(a); buildTransform();} + void setRotationZ(GLdouble a) {raw_matrix = false; angles_.setZ(a); while (angles_.z() < -360.) angles_.setZ(angles_.z() + 360.); while (angles_.z() > 360.) angles_.setZ(angles_.z() - 360.); buildTransform();} + void setRotation(const QVector3D & a) {raw_matrix = false; angles_= a; buildTransform();} + void resetRotation() {raw_matrix = false; angles_ = QVector3D(0., 0., 0.); buildTransform();} QVector3D scale() {return scale_;} double scaleX() {return scale_.x();} double scaleY() {return scale_.y();} double scaleZ() {return scale_.z();} - void scale(const QVector3D & sv) {scale_ *= sv; buildTransform();} - void scale(GLdouble sx, GLdouble sy, GLdouble sz) {scale(QVector3D(sx, sy, sz)); buildTransform();} - void scale(GLdouble sx, GLdouble sy) {scale(QVector3D(sx, sy, sy)); buildTransform();} - void scale(GLdouble sx) {scale(QVector3D(sx, sx, sx)); buildTransform();} - void scaleX(GLdouble a) {scale_.setX(scale_.x() + a); buildTransform();} - void scaleY(GLdouble a) {scale_.setY(scale_.y() + a); buildTransform();} - void scaleZ(GLdouble a) {scale_.setZ(scale_.z() + a); buildTransform();} - void setScale(const QVector3D & a) {scale_ = a; buildTransform();} - void setScale(GLdouble a) {scale_ = QVector3D(a, a, a); buildTransform();} - void setScaleX(GLdouble a) {scale_.setX(a); buildTransform();} - void setScaleY(GLdouble a) {scale_.setY(a); buildTransform();} - void setScaleZ(GLdouble a) {scale_.setZ(a); buildTransform();} - void resetScale() {scale_ = QVector3D(1., 1., 1.); buildTransform();} + void scale(const QVector3D & sv) {raw_matrix = false; scale_ *= sv; buildTransform();} + void scale(GLdouble sx, GLdouble sy, GLdouble sz) {raw_matrix = false; scale(QVector3D(sx, sy, sz)); buildTransform();} + void scale(GLdouble sx, GLdouble sy) {raw_matrix = false; scale(QVector3D(sx, sy, sy)); buildTransform();} + void scale(GLdouble sx) {raw_matrix = false; scale(QVector3D(sx, sx, sx)); buildTransform();} + void scaleX(GLdouble a) {raw_matrix = false; scale_.setX(scale_.x() + a); buildTransform();} + void scaleY(GLdouble a) {raw_matrix = false; scale_.setY(scale_.y() + a); buildTransform();} + void scaleZ(GLdouble a) {raw_matrix = false; scale_.setZ(scale_.z() + a); buildTransform();} + void setScale(const QVector3D & a) {raw_matrix = false; scale_ = a; buildTransform();} + void setScale(GLdouble a) {raw_matrix = false; scale_ = QVector3D(a, a, a); buildTransform();} + void setScaleX(GLdouble a) {raw_matrix = false; scale_.setX(a); buildTransform();} + void setScaleY(GLdouble a) {raw_matrix = false; scale_.setY(a); buildTransform();} + void setScaleZ(GLdouble a) {raw_matrix = false; scale_.setZ(a); buildTransform();} + void resetScale() {raw_matrix = false; scale_ = QVector3D(1., 1., 1.); buildTransform();} + + QMatrix4x4 transform() {return mat_;} + void setTransform(const QMatrix4x4 & t); bool isAcceptLight() const {return accept_light;} void setAcceptLight(bool yes) {accept_light = yes;} @@ -164,7 +166,7 @@ public: QVector3D pos_h; QVector points, puvws; - QVector faces, uvws; + QVector faces, uvws, norms; QVector normals; //QVector d_vertices, d_normals, d_uvs; @@ -180,7 +182,7 @@ protected: void checkPass(); int pass_; // Pass - bool is_init, is_tex_loaded, accept_light, accept_fog, /*write_depth_,*/ visible_, cast_shadow, rec_shadow, select_, selected_; + bool is_init, is_tex_loaded, accept_light, accept_fog, /*write_depth_,*/ visible_, cast_shadow, rec_shadow, select_, selected_, raw_matrix; double line_width; Type type_; GeomPrimitives geom_prim; @@ -190,7 +192,7 @@ protected: QVector3D pos_, angles_, scale_; QList children_; QList textures; - QMatrix4x4 itransform_; + QMatrix4x4 itransform_, mat_; //QColor color_; QString name_; GLenum blend_src, blend_dest; diff --git a/qglview/gltexture_manager.cpp b/qglview/gltexture_manager.cpp index 22158e3..fa9c0c6 100644 --- a/qglview/gltexture_manager.cpp +++ b/qglview/gltexture_manager.cpp @@ -43,12 +43,25 @@ bool GLTextureManager::loadTextures() { void GLTextureManager::deleteTextures() { - QList texs = tex_ids.values(); - qDebug() << "[TextureManager] Delete" << texs.size() << "textures"; - if (!texs.isEmpty()) glDeleteTextures(texs.size(), &texs[0]); - tex_ids.clear(); + for (int i = 0; i < 2; ++i) { + QList texs = tex_ids[i].values(); + qDebug() << "[TextureManager] Delete" << texs.size() << "textures"; + if (!texs.isEmpty()) glDeleteTextures(texs.size(), &texs[0]); + tex_ids[i].clear(); + } qDebug() << "[TextureManager] Delete" << anim_ids.size() << "animations"; for (int i = 0; i < anim_ids.size(); ++i) glDeleteTextures(anim_ids[i].second.bitmaps.size(), anim_ids[i].second.bitmaps.data()); anim_ids.clear(); } + + +void GLTextureManager::deleteTexture(const QString & name) { + for (int i = 0; i < 2; ++i) { + if (tex_ids[i].contains(name)) { + GLuint id = tex_ids[i][name]; + glDeleteTextures(1, &id); + tex_ids[i].remove(name); + } + } +} diff --git a/qglview/gltexture_manager.h b/qglview/gltexture_manager.h index 2b18224..a668ef8 100644 --- a/qglview/gltexture_manager.h +++ b/qglview/gltexture_manager.h @@ -39,13 +39,13 @@ public: void addAnimation(const QString & dir, const QString & name) {anim_pathes << QPair(dir, name);} bool loadTextures(); void deleteTextures(); - void deleteTexture(const QString & name) {if (tex_ids.contains(name)) {glDeleteTextures(1, &tex_ids[name]); tex_ids.remove(name);}} + void deleteTexture(const QString & name); Animation * findAnimation(const QString & name) {for (int i = 0; i < anim_ids.size(); ++i) if (anim_ids[i].first == name) return &(anim_ids[i].second); return 0;} QVector > anim_ids; private: - QList tex_pathes; + QStringList tex_pathes; QList > anim_pathes; }; diff --git a/qglview/gltypes.cpp b/qglview/gltypes.cpp index f251d4a..a1d0ffb 100644 --- a/qglview/gltypes.cpp +++ b/qglview/gltypes.cpp @@ -24,6 +24,7 @@ GLTextureManager * currentGLTextureManager; Camera * currentCamera; QMatrix4x4 globCameraMatrix; QMutex globMutex; +QStringList GLTextureManagerBase::search_pathes("."); QString readCharsUntilNull(QDataStream & s) { @@ -38,6 +39,22 @@ QString readCharsUntilNull(QDataStream & s) { } +QString findFile(const QString & file, const QStringList & pathes) { + QFileInfo fi(QString(file).replace("\\", "/")); + //qDebug() << "search" << file << "in" << pathes; + if (fi.exists()) return fi.absoluteFilePath(); + QString fn = fi.fileName(); + if (fn.contains("/")) fn = fn.mid(fn.lastIndexOf("/")); + foreach (QString p, pathes) { + QFileInfoList fil = QDir(p).entryInfoList(QStringList(fn), QDir::Files | QDir::NoDotAndDotDot); + //qDebug() << "findFile" << fn << "in" << p << "->" << fil.size(); + if (!fil.isEmpty()) + return fil[0].absoluteFilePath(); + } + return QString(); +} + + void glDrawQuad(GLfloat x, GLfloat y, GLfloat w, GLfloat h) { glResetAllTransforms(); glSetPolygonMode(GL_FILL); @@ -61,6 +78,16 @@ QMatrix4x4 getGLMatrix(GLenum matrix) { } +void qglMultMatrix(const QMatrix4x4 & m) { + GLdouble gm[16]; + qreal qm[16]; + m.transposed().copyDataTo(qm); + for (int i = 0; i < 16; ++i) + gm[i] = qm[i]; + glMultMatrixd(gm); +} + + void createGLTexture(GLuint & tex, int width, int height, const GLenum & format, const GLenum & target) { glClearError(); if (tex == 0) { @@ -105,19 +132,27 @@ 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 = d.entryInfoList(QStringList(name + ".geom"), QDir::Files | QDir::NoDotAndDotDot); + QFileInfoList sl; + //qDebug() << "[QGLView] Shader \"" + name + "\" load shaders from" << d.absolutePath(); #if QT_VERSION >= 0x040700 - foreach (const QFileInfo & i, sl) + 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) + 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) + 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(); + //qDebug() << "[QGLView] Shader \"" + name + "\" link error: " + prog->log(); return false; } return true; @@ -204,59 +239,99 @@ void GLCubeTexture::loadPathesFromDirectory(const QString & dir) { -GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership) { - int tid = ((GLTextureManagerBase*)currentGLTextureManager)->textureID(path); +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; } - tid = currentQGLView->bindTexture(QImage(path), GL_TEXTURE_2D/*, GL_RGBA, QGLContext::MipmapBindOption*/); + 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" << path; + qDebug() << "[TextureManager] Can`t load" << p; return tid; } - qDebug() << "[TextureManager] Loaded" << path << "as" << tid; - if (ownership) ((GLTextureManagerBase*)currentGLTextureManager)->tex_ids.insert(path, tid); - /*GLenum err(0); - im = currentQGLView->convertToGLFormat(im); - glClearError(); - glGenTextures(1, &tid); - err = glGetError(); - if (err != GL_NO_ERROR) { - qDebug() << "can`t generate texture," << err; - return false; - } - //glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - glClearError(); - glBindTexture(GL_TEXTURE_2D, tid); - qDebug() << "load" << im.width() << "x" << im.height(); - glClearError(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits()); - //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - //glBindTexture(GL_TEXTURE_2D, 0); - err = glGetError(); - if (err != GL_NO_ERROR) { - glDeleteTextures(1, &tid); - qDebug() << "can`t load" << path << "," << err; - return false; - } - currentGLTextureManager->tex_ids << tid; - qDebug() << "loaded" << path << "as" << 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 & image, bool ownership) { - GLuint tid = currentQGLView->bindTexture(image); +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.insert(QString(), 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; @@ -450,7 +525,8 @@ Material::Material(): reflection(512) { transparency = reflectivity = 0.f; bump_scale = relief_scale = iof = 1.f; dispersion = 0.05f; - shine = shine_strength = 0.f; + shine = 0.5; + shine_strength = 1.f; light_model = Phong; } @@ -480,12 +556,12 @@ void Material::apply() { 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); + 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); - //qDebug() << "load" << reflection.path(0); reflection.load(); } @@ -710,10 +786,14 @@ void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & Material & mat(o.material_); 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_); + 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(); diff --git a/qglview/gltypes.h b/qglview/gltypes.h index 7548a0b..72acb38 100644 --- a/qglview/gltypes.h +++ b/qglview/gltypes.h @@ -134,10 +134,12 @@ inline double urand(const double & scale = 1.) {return ((double)rand() / RAND_MA // return [0, 1] inline double uprand(const double & scale = 1.) {return ((double)rand() / RAND_MAX) * scale;} QString readCharsUntilNull(QDataStream & s); +QString findFile(const QString & file, const QStringList & pathes); inline QColor operator *(const QColor & c, double v) {return QColor(c.red() * v, c.green() * v, c.blue() * v, c.alpha() * v);} inline QColor operator /(const QColor & c, double v) {return QColor(c.red() / v, c.green() / v, c.blue() / v, c.alpha() / v);} inline void qglColor(const QColor & c) {glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());} +void qglMultMatrix(const QMatrix4x4 & m); 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();} @@ -227,12 +229,16 @@ class GLTextureManager; class GLTextureManagerBase { public: - static GLuint loadTexture(const QString & path, bool ownership = true); - static GLuint loadTexture(const QImage & image, bool ownership = true); - int textureID(const QString & path) {return tex_ids[path];} + 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: - QMap tex_ids; + static void convertToNormal(QImage & im); + static QStringList search_pathes; + QMap tex_ids[2]; }; @@ -335,6 +341,7 @@ struct Map { 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; diff --git a/qglview/loader_3ds.cpp b/qglview/loader_3ds.cpp index 3ddbda7..45e99ce 100644 --- a/qglview/loader_3ds.cpp +++ b/qglview/loader_3ds.cpp @@ -121,6 +121,14 @@ void Loader3DS::init3DSMesh(GLObjectBase * o, const QVector & smooth) { } +Material Loader3DS::materialByName(const QVector & materials, const QString & name) { + foreach (const Material & m, materials) + if (m.name == name) + return m; + return Material(); +} + + GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { QFile f(filepath); if (!f.exists()) { @@ -129,14 +137,19 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { } f.open(QIODevice::ReadOnly); QDataStream stream(&f); - //QVector materials; + QVector materials; QVector smooth; + QVector face_mats; GLObjectBase * root = new GLObjectBase(), * co = 0; + Material mat; Loader3DS::Chunk cc; Loader3DS::Face face; Vector3d pos; QString str; ushort cnt; + QString name; + QByteArray ba; + int cur_map = 0; float fl, fl1, matrix[3][3]; uint col; root->setName(QFileInfo(f).baseName()); @@ -178,6 +191,15 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { co->faces[i].p2 = face.v2; } break; + case LOADER_3DS_CHUNK_FACEMAT: + name = readCharsUntilNull(stream); + stream.readRawData((char * )&cnt, sizeof(ushort)); + face_mats.resize(cnt); + for (int i = 0; i < cnt; ++i) + stream.readRawData((char * )&(face_mats[i]), sizeof(ushort)); + //qDebug() << " facemat name" << name << cnt; + co->material().name = name; + break; case LOADER_3DS_CHUNK_MAPLIST: stream.readRawData((char * )&cnt, sizeof(ushort)); co->puvws.resize(cnt); @@ -264,13 +286,64 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { globject_cast(co)->decay_end = fl; //qDebug() << " range end" << fl; break; + case LOADER_3DS_CHUNK_MATERIAL: + //stream.skipRawData(cc.size - 6); + if (!mat.name.isEmpty()) + materials << mat; + mat = Material(); + break; + case LOADER_3DS_CHUNK_MATERIAL_NAME: + mat.name = readCharsUntilNull(stream); + //qDebug() << "matname" << mat.name; + break; + case LOADER_3DS_CHUNK_AMBIENT_COLOR: + stream.skipRawData(cc.size - 9); + stream.readRawData((char * )&col, 3); + mat.color_self_illumination = QColor::fromRgb(((uchar * )&col)[0], ((uchar * )&col)[1], ((uchar * )&col)[2]); + //qDebug() << "mat diffuse" << mat.color_diffuse; + break; + case LOADER_3DS_CHUNK_DIFFUSE_COLOR: + stream.skipRawData(cc.size - 9); + stream.readRawData((char * )&col, 3); + mat.color_diffuse = QColor::fromRgb(((uchar * )&col)[0], ((uchar * )&col)[1], ((uchar * )&col)[2]); + //qDebug() << "mat diffuse" << mat.color_diffuse; + break; + case LOADER_3DS_CHUNK_SPECULAR_COLOR: + stream.skipRawData(cc.size - 9); + stream.readRawData((char * )&col, 3); + mat.color_specular = QColor::fromRgb(((uchar * )&col)[0], ((uchar * )&col)[1], ((uchar * )&col)[2]); + //qDebug() << "mat diffuse" << mat.color_diffuse; + break; + case LOADER_3DS_CHUNK_TEXTURE_MAP: + cur_map = LOADER_3DS_CHUNK_TEXTURE_MAP; + break; + case LOADER_3DS_CHUNK_BUMP_MAP: + cur_map = LOADER_3DS_CHUNK_BUMP_MAP; + break; + case LOADER_3DS_CHUNK_REFLECTION_MAP: + cur_map = LOADER_3DS_CHUNK_REFLECTION_MAP; + break; + case LOADER_3DS_CHUNK_MAP_FILENAME: + 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; + } + break; default: /*qDebug() << "???" << QString::number(cc.id, 16).rightJustified(4, '0') << cc.size;*/ stream.skipRawData(cc.size - 6); } } + if (!mat.name.isEmpty()) + materials << mat; + foreach (const Material & m, materials) + qDebug() << m.name; if (co != 0) { Loader3DS::init3DSMesh(co, smooth); root->addChild(co); } + for (int i = 0; i < root->childCount(); ++i) + root->child(i)->material() = Loader3DS::materialByName(materials, root->child(i)->material().name); qDebug() << "[Loader 3DS] Loaded" << root->childCount() << "objects from" << filepath; return root; } diff --git a/qglview/loader_3ds.h b/qglview/loader_3ds.h index 0133d9d..bd42aa4 100644 --- a/qglview/loader_3ds.h +++ b/qglview/loader_3ds.h @@ -46,10 +46,15 @@ #define LOADER_3DS_CHUNK_MULTIPLIER 0x465B // [+] #define LOADER_3DS_CHUNK_CAMERA 0x4700 // [+] объект-камера #define LOADER_3DS_CHUNK_MATERIAL 0xAFFF // [-] материал -#define LOADER_3DS_CHUNK_MATNAME 0xA000 // [+] название материала -#define LOADER_3DS_CHUNK_TEXTURE 0xA200 // [-] текстура материала -#define LOADER_3DS_CHUNK_MAPFILE 0xA300 // [+] имя файла текстуры - +#define LOADER_3DS_CHUNK_MATERIAL_NAME 0xA000 +#define LOADER_3DS_CHUNK_AMBIENT_COLOR 0xA010 +#define LOADER_3DS_CHUNK_DIFFUSE_COLOR 0xA020 +#define LOADER_3DS_CHUNK_SPECULAR_COLOR 0xA030 +#define LOADER_3DS_CHUNK_TEXTURE_MAP 0xA200 +#define LOADER_3DS_CHUNK_BUMP_MAP 0xA230 +#define LOADER_3DS_CHUNK_REFLECTION_MAP 0xA220 +#define LOADER_3DS_CHUNK_MAP_FILENAME 0xA300 +#define LOADER_3DS_CHUNK_MAP_PARAMETERS 0xA351 namespace Loader3DS { #pragma pack(push, 1) @@ -65,6 +70,7 @@ namespace Loader3DS { }; #pragma pack(pop) void init3DSMesh(GLObjectBase * o, const QVector & smooth); + Material materialByName(const QVector & materials, const QString & name); } GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale = 1.0); diff --git a/qglview/main.cpp b/qglview/main.cpp index b8024ff..046b7b7 100644 --- a/qglview/main.cpp +++ b/qglview/main.cpp @@ -20,10 +20,10 @@ #include #include #include -#include -//#include "mainwindow.h" -#include "unistd.h" -#include +#include "mainwindow.h" +//#include +//#include +//#include "unistd.h" /*void display () { @@ -93,7 +93,7 @@ int main(int argc, char ** argv) { glutMainLoop(); */ - return 0; + //return 0; QApplication a(argc, argv); /*QGLFormat f; f.setVersion(3, 3); @@ -101,9 +101,9 @@ int main(int argc, char ** argv) { f.setProfile(QGLFormat::CoreProfile); QGLFormat::setDefaultFormat(f);*/ //QApplication::setStyle(new QCleanlooksStyle()); - QDir::setCurrent(a.applicationDirPath()); + //QDir::setCurrent(a.applicationDirPath()); //a.setWindowIcon(QIcon(":/icons/peri4_paint.png")); - //MainWindow w; - //w.show(); + MainWindow w; + w.show(); return a.exec(); } diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index 7b3a286..cb81177 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -17,7 +17,10 @@ */ #include "mainwindow.h" +#include "loader_obj.h" +#include "loader_dae.h" #include +#include #define EARTH_H 6356863.019 // m #define EARTH_WL 6378245.000 // m @@ -39,7 +42,6 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() /*MaterialEditor * o = new MaterialEditor(); o->setWindowOpacity(.666); view->addObject(o, Qt::Window);*/ - view->start(-1); /**obj = loadFrom3DSFile("data/test.3DS", 0.15); m.reflectivity = 1; m.reflection.loadPathesFromDirectory("data/e"); @@ -59,9 +61,15 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() //obj->child("teapot")->setRenderMode(GLObjectBase::Point); //obj->child("teapot")->setLineWidth(2.); //obj->child("cone")->setRenderMode(GLObjectBase::Line); - ///view->camera().setAim(obj->child("sphere001")->pos()); - - obj = new GLPrimitiveEllipsoid(EARTH_WL / 1E+6, EARTH_WL / 1E+6, EARTH_H / 1E+6, 500, 500);//GLPrimitiveCube(); + //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 = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube(); view->addObject(obj); double al = 7.; @@ -81,13 +89,14 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() view->camera().setPos(QVector3D(10, -20, 20)); view->camera().setAim(QVector3D()); - view->camera().flyToDistance(10); + view->camera().flyToDistance(300); view->setMouseSelectionEnabled(false); view->setSelectionHaloEnabled(false); view->setHoverHaloEnabled(false); Light * l = new Light(view->camera().pos()); l->intensity = 0.8; view->addObject(l); + view->start(-1); //view->light(0)->light_type = Light::Omni; //obj = loadFrom3DSFile("34.3DS", 0.03); //view->addObject(obj); @@ -113,7 +122,7 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() box->setLineWidth(2.); view->addObject(box); box->hide();*/ - while (view->lightsCount() >= 5) view->removeLight(view->lightsCount() - 1); + //while (view->lightsCount() >= 5) view->removeLight(view->lightsCount() - 1); //view->addObject(box); //obj = obj->clone(true); @@ -158,7 +167,7 @@ void MainWindow::changeEvent(QEvent * e) { void MainWindow::timerEvent(QTimerEvent * ) { static double t = 0.; - view->light(0)->setPos(view->camera().pos()); + view->light(view->lightsCount() - 1)->setPos(view->camera().pos()); ((RendererSimple*)(view->renderer()))->mpos = view->mapFromGlobal(QCursor::pos()); /*obj->child("tor")->rotateX(0.5); obj->child("tor")->rotateZ(0.1); diff --git a/qglview/material_editor.ui b/qglview/material_editor.ui index 0eb7cc4..3390a21 100644 --- a/qglview/material_editor.ui +++ b/qglview/material_editor.ui @@ -7,7 +7,7 @@ 0 0 327 - 588 + 593 @@ -97,13 +97,16 @@ - 128.000000000000000 - - 1.000000000000000 + + 2 + + + 0.100000000000000 + - 16.000000000000000 + 0.010000000000000 diff --git a/qglview/qglview.cpp b/qglview/qglview.cpp index 4856b9b..cd62d0a 100644 --- a/qglview/qglview.cpp +++ b/qglview/qglview.cpp @@ -192,6 +192,7 @@ void QGLView::initializeGL() { void QGLView::paintGL() { //QMutexLocker ml_v(&v_mutex); glEnable(GL_CULL_FACE); + //glDisble(GL_CULL_FACE); camera_.apply(aspect); /// Selection detect @@ -383,10 +384,14 @@ void QGLView::renderSingleSelection(GLObjectBase & o) { 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.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 (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_); + } 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, diff --git a/qglview/renderer_simple.cpp b/qglview/renderer_simple.cpp index 58ef782..dfc21b3 100644 --- a/qglview/renderer_simple.cpp +++ b/qglview/renderer_simple.cpp @@ -28,10 +28,14 @@ RendererSimple::RendererSimple(QGLView * view_): GLRendererBase(view_), fbo(2) void RendererSimple::reloadShaders() { - if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context()); - loadShaders(shader_fxaa, "FXAA", "shaders"); - if (shader == 0) shader = new QGLShaderProgram(view.context()); /// WARNING - loadShaders(shader, "test", "shaders"); /// WARNING + if (shader_fxaa == 0) { + shader_fxaa = new QGLShaderProgram(view.context()); + loadShaders(shader_fxaa, "FXAA", "shaders"); + } + /*if (shader == 0) { + shader = new QGLShaderProgram(view.context()); /// WARNING + loadShaders(shader, "test", "shaders"); /// WARNING + }*/ } @@ -73,9 +77,9 @@ void RendererSimple::renderScene() { fbo_c.bind(); glClearFramebuffer(); - shader->bind(); /// WARNING + //shader->bind(); /// WARNING renderObjects(GLObjectBase::Solid, l, 0, true, view.isLightEnabled(), view.isFogEnabled()); - shader->release(); /// WARNING + //shader->release(); /// WARNING if (QRect(QPoint(), fbo_c.size()).contains(mpos)) { //qDebug() << mpos; GLfloat data[4] = {0, 0, 0, 0}; diff --git a/qglview/shaders/dsl_pass_0.frag b/qglview/shaders/dsl_pass_0.frag index 70c31d1..2ea6235 100644 --- a/qglview/shaders/dsl_pass_0.frag +++ b/qglview/shaders/dsl_pass_0.frag @@ -1,6 +1,6 @@ #version 130 -in vec3 src_normal, normal, et; +in vec3 src_normal, normal;//, et; in vec4 pos, col; in float fogCoord; @@ -19,9 +19,13 @@ void main(void) { 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); - vec3 n; - if (has_bump) n = normalize(normal - (texture2D(t1, gl_TexCoord[0].xy).rgb - vec3(0.5, 0.5, 1.)) * bump_scale); - else n = normalize(normal); + 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); if (has_diffuse) { @@ -30,7 +34,7 @@ void main(void) { dpm = gl_ModelViewProjectionMatrixInverse dpm = dpm * gl_ModelViewProjectionMatrixInverse; dpm += */ - tc += 1-et.xy * hei/10;// / et.z; + //tc += 1+et.xy * hei/10;// / et.z; dc *= texture2D(t0, tc); } diff --git a/qglview/shaders/dsl_pass_0.geom b/qglview/shaders/dsl_pass_0.geom index c64f70f..bf08c73 100644 --- a/qglview/shaders/dsl_pass_0.geom +++ b/qglview/shaders/dsl_pass_0.geom @@ -6,7 +6,7 @@ in vec3 normal[]; out vec3 tangent[]; void main() { - for (int i = 0; i < gl_in.length(); i++ ) { + for (int i = 0; i < gl_in.length(); i++) { gl_Position = gl_in[i].gl_Position; EmitVertex(); } diff --git a/qglview/shaders/dsl_pass_0.vert b/qglview/shaders/dsl_pass_0.vert index b22f104..380d322 100644 --- a/qglview/shaders/dsl_pass_0.vert +++ b/qglview/shaders/dsl_pass_0.vert @@ -1,6 +1,6 @@ #version 130 -out vec3 src_normal, normal, et; +out vec3 src_normal, normal;//, et; out vec4 pos, col; out float fogCoord, fs_gid; @@ -23,19 +23,19 @@ void main(void) { src_normal = normalize(/*gl_NormalMatrix * */vec3(pos.xy * dt * 2., 0)); //pos = gl_Position; - vec3 v = normalize(-pos.xyz); // vector to the eye + //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); + //vec3 t = normalize(gl_NormalMatrix * vec3(gl_MultiTexCoord0.yx, 1)); + //vec3 b = cross(normal, t); - mat3 tbnMatrix = mat3(t.x, b.x, normal.x, + /*mat3 tbnMatrix = mat3(t.x, b.x, normal.x, t.y, b.y, normal.y, t.z, b.z, normal.z); - et = tbnMatrix * v; + et = tbnMatrix * v;*/ pos.w = gl_Position.w; diff --git a/qglview/shaders/dsl_pass_1.frag b/qglview/shaders/dsl_pass_1.frag index 30f5f67..345e0dc 100644 --- a/qglview/shaders/dsl_pass_1.frag +++ b/qglview/shaders/dsl_pass_1.frag @@ -8,17 +8,14 @@ uniform int gid, lightsCount; uniform bool firstPass; uniform vec2 dt; uniform vec4 back_color; -//uniform vec3 eye; -//uniform vec4 lpos[8]; uniform mat4 mat; -//uniform float zNear, zFar; -float light_diffuse(int model, vec3 l, vec3 n, vec3 h, vec3 v, float shininess) {return max(0., dot(l, n));} +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));} vec4 pos, lpos; vec3 li, si, ldir, halfV; -float sh, dist, NdotL, spot, ldist; +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; @@ -34,14 +31,16 @@ void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { spot = pow(spot, (gl_LightSource[index].spotExponent + 0.001)); } halfV = normalize(ldir + v); - //i += gl_LightSource[i].diffuse.rgb * NdotL; - //si += gl_LightSource[i].specular.rgb * pow(max(dot(n, halfV), 0.), sh); 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, halfV, v, sh); - si += spot * gl_LightSource[index].specular.rgb * v2.rgb * light_specular(0, ldir, n, halfV, v, sh); + //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 = vec3(gl_LightSource[index].spotExponent); - //si = vec3(0); } void main(void) { @@ -51,7 +50,7 @@ void main(void) { gl_FragColor = back_color; return; } - vec4 v1 = texture2D(t1, gl_TexCoord[0].xy), v2 = texture2D(t2, gl_TexCoord[0].xy);//, v3 = texture2D(t3, gl_TexCoord[0].xy); + vec4 v1 = texture2D(t1, gl_TexCoord[0].xy), v2 = texture2D(t2, gl_TexCoord[0].xy);//, v3 = texture2D(t2, gl_TexCoord[0].xy); vec2 sp = gl_FragCoord.xy * dt * 2 - vec2(1, 1); vec3 dc = v0.rgb, n = v1.xyz * 2. - vec3(1.); float height = v2.w; @@ -62,9 +61,8 @@ void main(void) { pos *= v0.w; pos.rgb += n * height; vec3 v = normalize(-pos.xyz); - sh = v1.w; - //int light_model = int(v3.r * 255. + 0.5); - //li = ambient; + 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 > 1) { @@ -89,6 +87,6 @@ void main(void) { } } } - gl_FragColor.rgb = li * dc + si + texture2D(tb, gl_TexCoord[0].xy).rgb; - //gl_FragColor.rgb = v0.rgb; + gl_FragColor.rgb = li * dc + si * v2.rgb + texture2D(tb, gl_TexCoord[0].xy).rgb; + //gl_FragColor.rgb = vec3(v2.rgb); }