Files
qglengine/src/core/render/renderer_material.cpp

142 lines
4.4 KiB
C++

/*
QGL RendererMaterial
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define GL_GLEXT_PROTOTYPES
#include "renderer_material.h"
#include "glmesh.h"
#include "gltexture_manager.h"
#include "qglview.h"
#include "renderer.h"
#include <QOpenGLExtraFunctions>
#include <qad_types.h>
using namespace QGLEngineShaders;
RendererMaterial::RendererMaterial(Renderer * r_): r(r_), fbo_mat_thumb(r->view, 7, true, GL_RGBA16F) {
mat_sphere = Primitive::ellipsoid(16, 16);
mat_camera = new Camera();
mat_camera->setPos(QVector3D(2, 2, 2));
mat_camera->setAim(QVector3D());
mat_camera->setFOV(45.);
mat_light = new Light();
mat_light->setPos(QVector3D(50, 100, 25));
mat_light->setCastShadows(false);
last_thumb_material = 0;
}
RendererMaterial::~RendererMaterial() {
delete mat_sphere;
delete mat_camera;
delete mat_light;
}
void RendererMaterial::init(int width, int height) {
fbo_mat_thumb.reinit();
mat_sphere->reinit();
resize(width, height);
}
void RendererMaterial::resize(int width, int height) {
fbo_mat_thumb.enablePixelBuffer();
fbo_mat_thumb.resize(256, 256);
}
void RendererMaterial::renderMaterial(Material * m) {
// qDebug() << "renderMaterial" << m;
last_thumb_material = m;
QOpenGLShaderProgram * prog = 0;
QOpenGLExtraFunctions * f = r->view;
fbo_mat_thumb.bind();
glEnableDepth();
glClearFramebuffer(QColor(0, 0, 0, 0));
auto role = m->hasTransparency() ? Renderer::srGeometryTransparentPass : Renderer::srGeometrySolidPass;
if (r->bindShader(role, &prog)) {
r->setUniformMaps(prog);
r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size());
prog->setUniformValue("out_index_normal", Renderer::dbrNormalZ);
prog->setUniformValue("out_index_metal", Renderer::dbrMetalRoughReflectFlags);
// qDebug() << mat_camera->viewMatrix();
r->textures_empty.bind(f, tarEmpty);
r->textures_maps.bind(f, tarMaps);
Object o;
o.material = m->_index;
o.f_accept_light = 1;
mat_sphere->loadObject(f, o);
mat_sphere->draw(f, 1);
}
fbo_mat_thumb.bindColorTextures({Renderer::dbrDiffuse,
Renderer::dbrNormalZ,
Renderer::dbrMetalRoughReflectFlags,
Renderer::dbrEmission,
Renderer::dbrSpeedBitangXY,
Renderer::dbrGeoNormal});
fbo_mat_thumb.setWriteBuffer(6);
if (r->bindShader(Renderer::srLightOmniPass, &prog)) {
r->setUniformCamera(prog, mat_camera, true, fbo_mat_thumb.size());
r->setUniformViewCorners(prog, mat_camera, fbo_mat_thumb.size());
for (int i = 0; i <= 5; ++i)
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
prog->setUniformValue("lights_start", 0);
prog->setUniformValue("lights_count", 1);
QMap<int, QList<Light *>> mat_l;
mat_l[Light::Omni] << mat_light;
r->reloadLightsParameters(mat_l);
r->reloadLightsPositions(mat_camera);
glClearFramebuffer(Qt::black, false);
r->renderQuad(prog, r->quad, mat_camera);
r->view->scene()->setLightsChanged();
}
fbo_mat_thumb.queryImage(6);
fbo_mat_thumb.release();
}
void RendererMaterial::procQueue() {
if (last_thumb_material) {
mat_thumbnails[last_thumb_material] = fbo_mat_thumb.getImage();
emit r->view->materialThumbnailCreated(last_thumb_material);
last_thumb_material = 0;
}
if (!mat_thumb_queue.isEmpty()) renderMaterial(mat_thumb_queue.dequeue());
}
QImage RendererMaterial::materialThumbnail(Material * m) {
return mat_thumbnails.value(m);
}
void RendererMaterial::recreateMaterialThumbnails(bool force_all) {
if (force_all) {
mat_thumb_queue.clear();
// qDebug() << "recreateMaterialThumbnails" << view->scene_->materials;
foreach(Material * m, r->view->scene()->materials)
mat_thumb_queue.enqueue(m);
} else {
foreach(Material * m, r->view->scene()->changed_materials)
if (!mat_thumb_queue.contains(m)) mat_thumb_queue.enqueue(m);
}
}