diff --git a/shaders/ds_light.glsl b/shaders/ds_light.glsl index 6656e02..f8c02a4 100644 --- a/shaders/ds_light.glsl +++ b/shaders/ds_light.glsl @@ -71,6 +71,14 @@ float rand(vec2 co) { return fract(sin(sn) * c) - 0.5; } +vec4 qgl_lightTexture(int index, vec2 coord, vec4 tex_shift) { + coord *= qgl_light_parameter[index].map.scale; + vec4 t = texture(qgl_texture_array[qgl_light_parameter[index].map.array_index], + vec3(coord, qgl_light_parameter[index].map.map_index)); + t += tex_shift; + t.rgb *= qgl_light_parameter[index].map.amount + qgl_light_parameter[index].map.offset; + return t; +} void calcLight(in int index, in vec3 n, in vec3 v) { lpos = qgl_light_position[index].position; @@ -82,16 +90,20 @@ void calcLight(in int index, in vec3 n, in vec3 v) { NdotL = max(dot(n, ldir), 1E-8); NdotH = max(dot(n, halfV), 1E-8); spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w; + vec3 light_color = qgl_light_parameter[index].color.rgb; #ifdef SPOT float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); spot *= scos * step(qgl_light_parameter[index].angles.w, scos); spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos); + vec4 shp = mapScreenToShadow(index, vec3(0)); + vec4 light_map_pix = qgl_lightTexture(index, shp.xy / shp.w, vec4(0)); + light_color *= light_map_pix.rgb; + spot *= light_map_pix.a; if (int(round(qgl_light_parameter[index].flags)) == 1 && bitfieldExtract(flags, 3, 1) == 1) { int layer = index - lights_start; float shadow = 0.; - vec4 shp = mapScreenToShadow(index, vec3(0)); if (soft_shadows_enabled) { @@ -168,13 +180,13 @@ void calcLight(in int index, in vec3 n, in vec3 v) { float ndlc = (1. - NdotLs) / NdotLs; diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc)); //diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r; - li += spot * diff * qgl_light_parameter[index].color.rgb; + li += spot * diff * light_color; ndlc = (1. - NdotHs) / NdotHs; float der = NdotHs * (rough_spec + ndlc); spec = rough_spec / (der*der) / PI; //spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r; - si += spot * spec * qgl_light_parameter[index].color.rgb; + si += spot * spec * light_color; } diff --git a/src/core/core/glmaterial.cpp b/src/core/core/glmaterial.cpp index 2c74c26..324aee1 100644 --- a/src/core/core/glmaterial.cpp +++ b/src/core/core/glmaterial.cpp @@ -59,10 +59,10 @@ void Map::copyToQGLMap(QGLMap & m) const { m.offset = color_offset; m.scale = QVector2D(bitmap_scale); if (loadedBitmap() && use_bitmap) { - m.array_index = tarMaps; + m.array_index = 1; m.map_index = _layer; } else { - m.array_index = tarEmpty; + m.array_index = 0; m.map_index = (_type == mtNormal ? emrBlue : emrWhite); } } diff --git a/src/core/core/glshaders_headers.h b/src/core/core/glshaders_headers.h index 1c6f3ec..1a991cf 100644 --- a/src/core/core/glshaders_headers.h +++ b/src/core/core/glshaders_headers.h @@ -99,6 +99,7 @@ const char qgl_structs[] = "#define QGL_MAPS_COUNT 6\n" " vec4 angles;\n" " float size;\n" " float flags;\n" + " QGLMap map;\n" "};\n" "struct QGLLightPosition {\n" " vec4 position;\n" diff --git a/src/core/core/glshaders_types.h b/src/core/core/glshaders_types.h index e08a067..1579692 100644 --- a/src/core/core/glshaders_types.h +++ b/src/core/core/glshaders_types.h @@ -97,18 +97,17 @@ enum BindingPoints { }; enum MapType { - mtDiffuse = 0, - mtNormal = 1, - mtMetalness = 2, - mtRoughness = 3, - mtEmission = 4, - mtRelief = 5, - mtShadowCone = 8, + mtDiffuse = 0, + mtNormal = 1, + mtMetalness = 2, + mtRoughness = 3, + mtEmission = 4, + mtRelief = 5, }; enum TextureArrayRole { - tarEmpty = 0, - tarMaps = 1, - tarShadowsCone = 10, + tarEmpty = 10, + tarMaps = 11, + tarShadowsCone = 12, }; enum EmptyMapRole { emrWhite = 0, @@ -142,6 +141,7 @@ struct QGLLightParameter { GLfloat size = 0.1f; GLfloat flags = 0; GLfloat _align[2]; + QGLMap map; }; struct QGLLightPosition { QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); } diff --git a/src/core/render/renderer.cpp b/src/core/render/renderer.cpp index f58540a..1d5395a 100644 --- a/src/core/render/renderer.cpp +++ b/src/core/render/renderer.cpp @@ -164,14 +164,10 @@ bool Renderer::bindShader(QOpenGLShaderProgram * sp) { void Renderer::initShaders() { if (!need_init_shaders) return; - need_init_shaders = false; + need_init_shaders = false; // initUniformBuffer(shaders.value(srGeometrySolidPass), &buffer_materials, bpMaterials, "QGLMaterialData"); // initUniformBuffer(shaders.value(srGeometryTransparentPass), &buffer_materials, bpMaterials, "QGLMaterialData"); // initUniformBuffer(shaders.value(srShadowPass), &buffer_materials, bpMaterials, "QGLMaterialData"); - QVector samplers; - samplers.resize(16); - for (int i = 0; i < samplers.size(); ++i) - samplers[i] = mtShadowCone + i; QOpenGLShaderProgram * prog = 0; for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) { if (!bindShader(role, &prog)) continue; @@ -182,6 +178,7 @@ void Renderer::initShaders() { prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount); prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount + 1); + setUniformMaps(prog); prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone); } if (bindShader(srFinalPass, &prog)) { @@ -386,7 +383,7 @@ void Renderer::renderScene() { } phase.end(); - /// shadows + /// shadows and shadow matrix phase.begin("shadows"); if (bindShader(srShadowPass, &prog)) { glEnableDepth(); @@ -399,8 +396,7 @@ void Renderer::renderScene() { mat_vp.scale(0.5, 0.5); mat_vp.translate(1, 1); for (int i = 0; i < cone_ll.size(); ++i) { - Light * l = cone_ll[i]; - if (!l->isCastShadows()) continue; + Light * l = cone_ll[i]; QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm; om.translate(-l->worldAim()); vm.translate(0., 0., -l->distance()); @@ -409,8 +405,10 @@ void Renderer::renderScene() { pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; vm *= pmat.inverted(); auto vpm = pm * (vm * om); - prog->setUniformValue("qgl_ViewProjMatrix", vpm); - renderShadow(i, l); + if (l->isCastShadows()) { + prog->setUniformValue("qgl_ViewProjMatrix", vpm); + renderShadow(i, l); + } l->shadow_matrix = mat_vp * vpm * cam_ivm; } } diff --git a/src/core/render/renderer_base.cpp b/src/core/render/renderer_base.cpp index 063c956..40c3c7a 100644 --- a/src/core/render/renderer_base.cpp +++ b/src/core/render/renderer_base.cpp @@ -153,6 +153,9 @@ void RendererBase::reloadMaterials(Scene & scene) { for (Material * m: scene.materials) { m->load(textures_manager); } + auto cone_ll = scene.lights_used.value(Light::Cone); + for (auto * l: cone_ll) + l->light_map.load(textures_manager); uint cur_maps_hash = textures_manager->texturesHash() ^ ((maps_size.width() << 16) | maps_size.height()); if (maps_hash != cur_maps_hash) { maps_hash = cur_maps_hash; @@ -164,6 +167,8 @@ void RendererBase::reloadMaterials(Scene & scene) { for (Material * m: scene.materials) { m->setMapsLayers(textures_manager); } + for (auto * l: cone_ll) + l->light_map.setMapLayer(textures_manager); textures_manager->loadingDone(); QGLMaterial glm; @@ -227,6 +232,7 @@ void RendererBase::reloadLightsParameters(const QMap> & ligh so.decay_intensity[3] = l->intensity; so.size = l->size; so.flags = l->cast_shadow ? 1 : 0; + if (l->light_type == Light::Cone) l->light_map.copyToQGLMap(so.map); } buffer_lights.bind(view); buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter)); diff --git a/src/core/scene/globject.cpp b/src/core/scene/globject.cpp index 1c0142f..e0e9d21 100644 --- a/src/core/scene/globject.cpp +++ b/src/core/scene/globject.cpp @@ -675,7 +675,8 @@ QDataStream & operator<<(QDataStream & s, const ObjectBase * p) { .add(108, l->decay_end) .add(109, int(l->light_type)) .add(111, l->distance()) - .add(112, l->size); + .add(112, l->size) + .add(113, l->light_map); } if (p->type_ == ObjectBase::glCamera) { // qDebug() << "place camera ..."; @@ -797,6 +798,9 @@ QDataStream & operator>>(QDataStream & s, ObjectBase *& p) { case 112: if (l) l->size = cs.getData(); break; + case 113: + if (l) l->light_map = cs.getData(); + break; case 200: if (c) c->setAim(cs.getData()); break; diff --git a/src/core/scene/globject.h b/src/core/scene/globject.h index 4794bf0..573c6f0 100644 --- a/src/core/scene/globject.h +++ b/src/core/scene/globject.h @@ -427,6 +427,7 @@ public: Type light_type; Framebuffer shadow_map; QMatrix4x4 shadow_matrix; + Map light_map; }; template diff --git a/src/widgets/material_map_editor.cpp b/src/widgets/material_map_editor.cpp index 14144df..08a2601 100644 --- a/src/widgets/material_map_editor.cpp +++ b/src/widgets/material_map_editor.cpp @@ -128,6 +128,7 @@ Map MaterialMapEditor::map() { */ void MaterialMapEditor::on_buttonSelect_clicked() { + if (!map) return; QString str = QFileDialog::getOpenFileName(this, "Select image", ui->linePath->property("GLpath").toString(), @@ -142,6 +143,7 @@ void MaterialMapEditor::on_buttonSelect_clicked() { void MaterialMapEditor::on_buttonClear_clicked() { + if (!map) return; ui->linePath->setText(""); ui->linePath->setProperty("GLpath", ""); map->clearBitmap(); diff --git a/src/widgets/material_map_editor.h b/src/widgets/material_map_editor.h index 0ec3b56..8f87aa6 100644 --- a/src/widgets/material_map_editor.h +++ b/src/widgets/material_map_editor.h @@ -45,7 +45,7 @@ protected: bool active; Ui::MaterialMapEditor * ui; - Map * map; + Map * map = nullptr; private slots: void mapChanged(); diff --git a/src/widgets/object_editor.cpp b/src/widgets/object_editor.cpp index 8761109..1e8da24 100644 --- a/src/widgets/object_editor.cpp +++ b/src/widgets/object_editor.cpp @@ -21,6 +21,7 @@ #include "qglview.h" #include "ui_object_editor.h" +#include #include #include @@ -30,6 +31,7 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { ui->setupUi(this); ui->scrollArea->viewport()->setAutoFillBackground(false); ui->scrollAreaWidgetContents->setAutoFillBackground(false); + ui->mapLight->configure(tr("Map"), false); view = 0; active = true; ignore_next = false; @@ -37,6 +39,7 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { ui->scrollArea->setEnabled(false); ui->labelAimDist->hide(); ui->spinAimDist->hide(); + ui->mapLight->hide(); QObjectList ol; ol << ui->spinPosX << ui->spinPosY << ui->spinPosZ << ui->spinRotationX << ui->spinRotationY << ui->spinRotationZ << ui->spinScaleX @@ -87,6 +90,7 @@ void ObjectEditor::changeEvent(QEvent * e) { void ObjectEditor::selectionChanged() { + int vpos = ui->scrollArea->verticalScrollBar()->value(); if (ignore_next) { ignore_next = false; return; @@ -101,6 +105,7 @@ void ObjectEditor::selectionChanged() { ui->scrollArea->setEnabled(true); if (sol.size() == 1) { setObject(sol[0]); + ui->scrollArea->verticalScrollBar()->setValue(vpos); return; } bool hl = !view->selectedLights().isEmpty(), hc = !view->selectedCameras().isEmpty(); @@ -156,6 +161,7 @@ void ObjectEditor::setObject(ObjectBase * o) { ui->spinLightSize->setValue(l->size); ui->spinAimDist->setValue(l->distance()); on_comboLightType_currentIndexChanged(ui->comboLightType->currentIndex()); + if (l->light_type == Light::Cone) ui->mapLight->setMap(&(l->light_map)); } if (is_c) { Camera * c = globject_cast(o); @@ -186,6 +192,7 @@ void ObjectEditor::on_comboLightType_currentIndexChanged(int index) { ui->labelLightAngleDash->setVisible(ang); ui->spinLightAngleStart->setVisible(ang); ui->spinLightAngleEnd->setVisible(ang); + ui->mapLight->setVisible(ang); if (!view || !active) return; QList sll = view->selectedLights(); foreach(Light * o, sll) { @@ -206,6 +213,15 @@ void ObjectEditor::on_buttonColor_colorChanged(const QColor & v) { } +void ObjectEditor::on_mapLight_changed() { + if (!view || !active) return; + QList sll = view->selectedLights(); + foreach(Light * o, sll) { + o->apply(); + } +} + + void ObjectEditor::spinChanged(double v) { if (!view || !active) return; ObjectBaseList sol = view->selectedObjects(true); diff --git a/src/widgets/object_editor.h b/src/widgets/object_editor.h index 8e3d5a5..19aa747 100644 --- a/src/widgets/object_editor.h +++ b/src/widgets/object_editor.h @@ -50,6 +50,7 @@ private slots: void on_comboLightType_currentIndexChanged(int index); void on_buttonColor_colorChanged(const QColor & v); + void on_mapLight_changed(); void spinChanged(double v); void spinTextureChanged(double v); void spinLightChanged(double v); diff --git a/src/widgets/object_editor.ui b/src/widgets/object_editor.ui index e70961a..d94335f 100644 --- a/src/widgets/object_editor.ui +++ b/src/widgets/object_editor.ui @@ -62,7 +62,7 @@ 0 -287 444 - 1081 + 1100 @@ -810,6 +810,13 @@ + + + + font:normal; + + + @@ -832,6 +839,19 @@ + + + + 5 + + + 999999999.000000000000000 + + + 0.100000000000000 + + + @@ -864,34 +884,10 @@ - - - - - - Mirror Y - - - - - - - Mirror X - - - - - - - - - 5 - - - 999999999.000000000000000 - - - 0.100000000000000 + + + + Roll: @@ -920,12 +916,23 @@ - - - - Roll: - - + + + + + + Mirror Y + + + + + + + Mirror X + + + + @@ -965,6 +972,15 @@ QWidget
scroll_spin_box.h
+ + MaterialMapEditor + QWidget +
material_map_editor.h
+ 1 + + changed() + +