git-svn-id: svn://db.shs.com.ru/libs@586 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
266
test/qglview/glmaterial.cpp
Normal file
266
test/qglview/glmaterial.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gltypes.h"
|
||||
#include "qglview.h"
|
||||
|
||||
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, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, format_, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
//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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
QString GLTextureManagerBase::findFile(const QString & path) {
|
||||
return ::findFile(path, search_pathes);
|
||||
}
|
||||
|
||||
|
||||
GLuint GLTextureManagerBase::loadTexture(const QString & path, bool ownership, bool bump) {
|
||||
QString p = findFile(path);
|
||||
if (p.isEmpty()) return 0;
|
||||
int tid = 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, __GLContext__::MipmapBindOption*/);
|
||||
//GLuint tid = 0;
|
||||
GLuint _tid = tid;
|
||||
createGLTexture(_tid, image);///currentQGLView->bindTexture(image, GL_TEXTURE_2D);
|
||||
tid = _tid;
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load" << p;
|
||||
return tid;
|
||||
}
|
||||
qDebug() << "[TextureManager] Loaded" << p << "as" << tid;
|
||||
if (ownership) 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 = 0;
|
||||
createGLTexture(tid, im);///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) tex_ids[bump ? 1 : 0].insert(QString(), tid);
|
||||
return tid;
|
||||
}
|
||||
|
||||
|
||||
void GLTextureManagerBase::reloadTexture(GLuint tid, const QString & path) {
|
||||
QString p = findFile(path);
|
||||
if (p.isEmpty() || (tid == 0)) return;
|
||||
QImage image(p);
|
||||
createGLTexture(tid, image);
|
||||
if (tid == 0) {
|
||||
qDebug() << "[TextureManager] Can`t load" << p;
|
||||
return;
|
||||
}
|
||||
qDebug() << "[TextureManager] Reloaded" << p << "as" << tid;
|
||||
}
|
||||
|
||||
|
||||
void GLTextureManagerBase::reloadTexture(GLuint tid, const QImage & im) {
|
||||
if (im.isNull() || (tid == 0)) return;
|
||||
QImage image(im);
|
||||
createGLTexture(tid, image);
|
||||
qDebug() << "[TextureManager] Reloaded" << 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);
|
||||
float 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] += sd[a] / 255.f - 0.5f; ++a;
|
||||
sum[1] += sd[a] / 255.f - 0.5f; ++a;
|
||||
sum[0] += sd[a] / 255.f - 0.5f; ++a;
|
||||
++a;
|
||||
}
|
||||
}
|
||||
float 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.05f) && (qAbs(sum[1]) <= 0.05f) && (sum[2] >= 0.25f)) /// 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.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f);
|
||||
res.x = piClamp(0.5f + (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f);
|
||||
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.5f + (p[0].length() - p[1].length()) / 2.f, 0.f, 1.f);
|
||||
res.x = piClamp(0.5f + (p[0].length() - p[2].length()) / 2.f, 0.f, 1.f);
|
||||
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;
|
||||
map_specularity.color_amount = 0.5f;
|
||||
map_specular.color_amount = 1.f;
|
||||
iof = 1.f;
|
||||
dispersion = 0.05f;
|
||||
}
|
||||
|
||||
|
||||
void Material::apply(QOpenGLShaderProgram * 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] = map_diffuse.color_amount * color_diffuse.redF();
|
||||
mat_diffuse[1] = map_diffuse.color_amount * color_diffuse.greenF();
|
||||
mat_diffuse[2] = map_diffuse.color_amount * color_diffuse.blueF();
|
||||
mat_diffuse[3] = map_diffuse.color_amount * color_diffuse.alphaF() * (1.f - transparency);
|
||||
mat_specular[0] = map_specular.color_amount * color_specular.redF();
|
||||
mat_specular[1] = map_specular.color_amount * color_specular.greenF();
|
||||
mat_specular[2] = map_specular.color_amount * color_specular.blueF();
|
||||
mat_emission[0] = map_self_illumination.color_amount * color_self_illumination.redF();
|
||||
mat_emission[1] = map_self_illumination.color_amount * color_self_illumination.greenF();
|
||||
mat_emission[2] = map_self_illumination.color_amount * 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);
|
||||
//qDebug() << (map_specularity.color_amount)*128.;
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, (map_specularity.color_amount)*128.f);
|
||||
glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_diffuse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Material::loadTextures(GLTextureManagerBase * tm) {
|
||||
//qDebug() << "load textures";
|
||||
if (!tm) return;
|
||||
if (!map_diffuse.bitmap_path.isEmpty()) map_diffuse.bitmap_id = tm->loadTexture(map_diffuse.bitmap_path);
|
||||
if (!map_normal.bitmap_path.isEmpty()) map_normal.bitmap_id = tm->loadTexture(map_normal.bitmap_path, true, true);
|
||||
if (!map_relief.bitmap_path.isEmpty()) map_relief.bitmap_id = tm->loadTexture(map_relief.bitmap_path);
|
||||
if (!map_specularity.bitmap_path.isEmpty()) map_specularity.bitmap_id = tm->loadTexture(map_specularity.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();
|
||||
}
|
||||
Reference in New Issue
Block a user