spot light map

This commit is contained in:
2023-02-14 10:43:51 +03:00
parent 36540468dc
commit 12695983d2
13 changed files with 119 additions and 62 deletions

View File

@@ -71,6 +71,14 @@ float rand(vec2 co) {
return fract(sin(sn) * c) - 0.5; 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) { void calcLight(in int index, in vec3 n, in vec3 v) {
lpos = qgl_light_position[index].position; 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); NdotL = max(dot(n, ldir), 1E-8);
NdotH = max(dot(n, halfV), 1E-8); NdotH = max(dot(n, halfV), 1E-8);
spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w; spot = step(1.001E-8, NdotL) * qgl_light_parameter[index].decay_intensity.w;
vec3 light_color = qgl_light_parameter[index].color.rgb;
#ifdef SPOT #ifdef SPOT
float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.); float scos = max(dot(-ldir, qgl_light_position[index].direction.xyz), 0.);
spot *= scos * step(qgl_light_parameter[index].angles.w, scos); 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); 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) { if (int(round(qgl_light_parameter[index].flags)) == 1 && bitfieldExtract(flags, 3, 1) == 1) {
int layer = index - lights_start; int layer = index - lights_start;
float shadow = 0.; float shadow = 0.;
vec4 shp = mapScreenToShadow(index, vec3(0));
if (soft_shadows_enabled) { if (soft_shadows_enabled) {
@@ -168,13 +180,13 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
float ndlc = (1. - NdotLs) / NdotLs; float ndlc = (1. - NdotLs) / NdotLs;
diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc)); diff = 2. / (1. + sqrt(1. + (1. - rough_diff) * ndlc));
//diff = texture(tex_coeffs[0], vec2(roughness, (NdotLs))).r; //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; ndlc = (1. - NdotHs) / NdotHs;
float der = NdotHs * (rough_spec + ndlc); float der = NdotHs * (rough_spec + ndlc);
spec = rough_spec / (der*der) / PI; spec = rough_spec / (der*der) / PI;
//spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r; //spec = texture(tex_coeffs[1], vec2(roughness, (NdotHs))).r;
si += spot * spec * qgl_light_parameter[index].color.rgb; si += spot * spec * light_color;
} }

View File

@@ -59,10 +59,10 @@ void Map::copyToQGLMap(QGLMap & m) const {
m.offset = color_offset; m.offset = color_offset;
m.scale = QVector2D(bitmap_scale); m.scale = QVector2D(bitmap_scale);
if (loadedBitmap() && use_bitmap) { if (loadedBitmap() && use_bitmap) {
m.array_index = tarMaps; m.array_index = 1;
m.map_index = _layer; m.map_index = _layer;
} else { } else {
m.array_index = tarEmpty; m.array_index = 0;
m.map_index = (_type == mtNormal ? emrBlue : emrWhite); m.map_index = (_type == mtNormal ? emrBlue : emrWhite);
} }
} }

View File

@@ -99,6 +99,7 @@ const char qgl_structs[] = "#define QGL_MAPS_COUNT 6\n"
" vec4 angles;\n" " vec4 angles;\n"
" float size;\n" " float size;\n"
" float flags;\n" " float flags;\n"
" QGLMap map;\n"
"};\n" "};\n"
"struct QGLLightPosition {\n" "struct QGLLightPosition {\n"
" vec4 position;\n" " vec4 position;\n"

View File

@@ -103,12 +103,11 @@ enum MapType {
mtRoughness = 3, mtRoughness = 3,
mtEmission = 4, mtEmission = 4,
mtRelief = 5, mtRelief = 5,
mtShadowCone = 8,
}; };
enum TextureArrayRole { enum TextureArrayRole {
tarEmpty = 0, tarEmpty = 10,
tarMaps = 1, tarMaps = 11,
tarShadowsCone = 10, tarShadowsCone = 12,
}; };
enum EmptyMapRole { enum EmptyMapRole {
emrWhite = 0, emrWhite = 0,
@@ -142,6 +141,7 @@ struct QGLLightParameter {
GLfloat size = 0.1f; GLfloat size = 0.1f;
GLfloat flags = 0; GLfloat flags = 0;
GLfloat _align[2]; GLfloat _align[2];
QGLMap map;
}; };
struct QGLLightPosition { struct QGLLightPosition {
QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); } QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); }

View File

@@ -168,10 +168,6 @@ void Renderer::initShaders() {
// initUniformBuffer(shaders.value(srGeometrySolidPass), &buffer_materials, bpMaterials, "QGLMaterialData"); // initUniformBuffer(shaders.value(srGeometrySolidPass), &buffer_materials, bpMaterials, "QGLMaterialData");
// initUniformBuffer(shaders.value(srGeometryTransparentPass), &buffer_materials, bpMaterials, "QGLMaterialData"); // initUniformBuffer(shaders.value(srGeometryTransparentPass), &buffer_materials, bpMaterials, "QGLMaterialData");
// initUniformBuffer(shaders.value(srShadowPass), &buffer_materials, bpMaterials, "QGLMaterialData"); // initUniformBuffer(shaders.value(srShadowPass), &buffer_materials, bpMaterials, "QGLMaterialData");
QVector<GLuint> samplers;
samplers.resize(16);
for (int i = 0; i < samplers.size(); ++i)
samplers[i] = mtShadowCone + i;
QOpenGLShaderProgram * prog = 0; QOpenGLShaderProgram * prog = 0;
for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) { for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) {
if (!bindShader(role, &prog)) continue; if (!bindShader(role, &prog)) continue;
@@ -182,6 +178,7 @@ void Renderer::initShaders() {
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount); prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount);
prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount + 1); prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount + 1);
setUniformMaps(prog);
prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone); prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone);
} }
if (bindShader(srFinalPass, &prog)) { if (bindShader(srFinalPass, &prog)) {
@@ -386,7 +383,7 @@ void Renderer::renderScene() {
} }
phase.end(); phase.end();
/// shadows /// shadows and shadow matrix
phase.begin("shadows"); phase.begin("shadows");
if (bindShader(srShadowPass, &prog)) { if (bindShader(srShadowPass, &prog)) {
glEnableDepth(); glEnableDepth();
@@ -400,7 +397,6 @@ void Renderer::renderScene() {
mat_vp.translate(1, 1); mat_vp.translate(1, 1);
for (int i = 0; i < cone_ll.size(); ++i) { for (int i = 0; i < cone_ll.size(); ++i) {
Light * l = cone_ll[i]; Light * l = cone_ll[i];
if (!l->isCastShadows()) continue;
QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm; QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm;
om.translate(-l->worldAim()); om.translate(-l->worldAim());
vm.translate(0., 0., -l->distance()); vm.translate(0., 0., -l->distance());
@@ -409,8 +405,10 @@ void Renderer::renderScene() {
pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.; pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.;
vm *= pmat.inverted(); vm *= pmat.inverted();
auto vpm = pm * (vm * om); auto vpm = pm * (vm * om);
if (l->isCastShadows()) {
prog->setUniformValue("qgl_ViewProjMatrix", vpm); prog->setUniformValue("qgl_ViewProjMatrix", vpm);
renderShadow(i, l); renderShadow(i, l);
}
l->shadow_matrix = mat_vp * vpm * cam_ivm; l->shadow_matrix = mat_vp * vpm * cam_ivm;
} }
} }

View File

@@ -153,6 +153,9 @@ void RendererBase::reloadMaterials(Scene & scene) {
for (Material * m: scene.materials) { for (Material * m: scene.materials) {
m->load(textures_manager); 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()); uint cur_maps_hash = textures_manager->texturesHash() ^ ((maps_size.width() << 16) | maps_size.height());
if (maps_hash != cur_maps_hash) { if (maps_hash != cur_maps_hash) {
maps_hash = cur_maps_hash; maps_hash = cur_maps_hash;
@@ -164,6 +167,8 @@ void RendererBase::reloadMaterials(Scene & scene) {
for (Material * m: scene.materials) { for (Material * m: scene.materials) {
m->setMapsLayers(textures_manager); m->setMapsLayers(textures_manager);
} }
for (auto * l: cone_ll)
l->light_map.setMapLayer(textures_manager);
textures_manager->loadingDone(); textures_manager->loadingDone();
QGLMaterial glm; QGLMaterial glm;
@@ -227,6 +232,7 @@ void RendererBase::reloadLightsParameters(const QMap<int, QList<Light *>> & ligh
so.decay_intensity[3] = l->intensity; so.decay_intensity[3] = l->intensity;
so.size = l->size; so.size = l->size;
so.flags = l->cast_shadow ? 1 : 0; 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.bind(view);
buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter)); buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter));

View File

@@ -675,7 +675,8 @@ QDataStream & operator<<(QDataStream & s, const ObjectBase * p) {
.add(108, l->decay_end) .add(108, l->decay_end)
.add(109, int(l->light_type)) .add(109, int(l->light_type))
.add(111, l->distance()) .add(111, l->distance())
.add(112, l->size); .add(112, l->size)
.add(113, l->light_map);
} }
if (p->type_ == ObjectBase::glCamera) { if (p->type_ == ObjectBase::glCamera) {
// qDebug() << "place camera ..."; // qDebug() << "place camera ...";
@@ -797,6 +798,9 @@ QDataStream & operator>>(QDataStream & s, ObjectBase *& p) {
case 112: case 112:
if (l) l->size = cs.getData<double>(); if (l) l->size = cs.getData<double>();
break; break;
case 113:
if (l) l->light_map = cs.getData<Map>();
break;
case 200: case 200:
if (c) c->setAim(cs.getData<QVector3D>()); if (c) c->setAim(cs.getData<QVector3D>());
break; break;

View File

@@ -427,6 +427,7 @@ public:
Type light_type; Type light_type;
Framebuffer shadow_map; Framebuffer shadow_map;
QMatrix4x4 shadow_matrix; QMatrix4x4 shadow_matrix;
Map light_map;
}; };
template<class T> template<class T>

View File

@@ -128,6 +128,7 @@ Map MaterialMapEditor::map() {
*/ */
void MaterialMapEditor::on_buttonSelect_clicked() { void MaterialMapEditor::on_buttonSelect_clicked() {
if (!map) return;
QString str = QFileDialog::getOpenFileName(this, QString str = QFileDialog::getOpenFileName(this,
"Select image", "Select image",
ui->linePath->property("GLpath").toString(), ui->linePath->property("GLpath").toString(),
@@ -142,6 +143,7 @@ void MaterialMapEditor::on_buttonSelect_clicked() {
void MaterialMapEditor::on_buttonClear_clicked() { void MaterialMapEditor::on_buttonClear_clicked() {
if (!map) return;
ui->linePath->setText(""); ui->linePath->setText("");
ui->linePath->setProperty("GLpath", ""); ui->linePath->setProperty("GLpath", "");
map->clearBitmap(); map->clearBitmap();

View File

@@ -45,7 +45,7 @@ protected:
bool active; bool active;
Ui::MaterialMapEditor * ui; Ui::MaterialMapEditor * ui;
Map * map; Map * map = nullptr;
private slots: private slots:
void mapChanged(); void mapChanged();

View File

@@ -21,6 +21,7 @@
#include "qglview.h" #include "qglview.h"
#include "ui_object_editor.h" #include "ui_object_editor.h"
#include <QScrollBar>
#include <scroll_spin_box.h> #include <scroll_spin_box.h>
#include <spinslider.h> #include <spinslider.h>
@@ -30,6 +31,7 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) {
ui->setupUi(this); ui->setupUi(this);
ui->scrollArea->viewport()->setAutoFillBackground(false); ui->scrollArea->viewport()->setAutoFillBackground(false);
ui->scrollAreaWidgetContents->setAutoFillBackground(false); ui->scrollAreaWidgetContents->setAutoFillBackground(false);
ui->mapLight->configure(tr("Map"), false);
view = 0; view = 0;
active = true; active = true;
ignore_next = false; ignore_next = false;
@@ -37,6 +39,7 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) {
ui->scrollArea->setEnabled(false); ui->scrollArea->setEnabled(false);
ui->labelAimDist->hide(); ui->labelAimDist->hide();
ui->spinAimDist->hide(); ui->spinAimDist->hide();
ui->mapLight->hide();
QObjectList ol; QObjectList ol;
ol << ui->spinPosX << ui->spinPosY << ui->spinPosZ << ui->spinRotationX << ui->spinRotationY << ui->spinRotationZ << ui->spinScaleX 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() { void ObjectEditor::selectionChanged() {
int vpos = ui->scrollArea->verticalScrollBar()->value();
if (ignore_next) { if (ignore_next) {
ignore_next = false; ignore_next = false;
return; return;
@@ -101,6 +105,7 @@ void ObjectEditor::selectionChanged() {
ui->scrollArea->setEnabled(true); ui->scrollArea->setEnabled(true);
if (sol.size() == 1) { if (sol.size() == 1) {
setObject(sol[0]); setObject(sol[0]);
ui->scrollArea->verticalScrollBar()->setValue(vpos);
return; return;
} }
bool hl = !view->selectedLights().isEmpty(), hc = !view->selectedCameras().isEmpty(); bool hl = !view->selectedLights().isEmpty(), hc = !view->selectedCameras().isEmpty();
@@ -156,6 +161,7 @@ void ObjectEditor::setObject(ObjectBase * o) {
ui->spinLightSize->setValue(l->size); ui->spinLightSize->setValue(l->size);
ui->spinAimDist->setValue(l->distance()); ui->spinAimDist->setValue(l->distance());
on_comboLightType_currentIndexChanged(ui->comboLightType->currentIndex()); on_comboLightType_currentIndexChanged(ui->comboLightType->currentIndex());
if (l->light_type == Light::Cone) ui->mapLight->setMap(&(l->light_map));
} }
if (is_c) { if (is_c) {
Camera * c = globject_cast<Camera *>(o); Camera * c = globject_cast<Camera *>(o);
@@ -186,6 +192,7 @@ void ObjectEditor::on_comboLightType_currentIndexChanged(int index) {
ui->labelLightAngleDash->setVisible(ang); ui->labelLightAngleDash->setVisible(ang);
ui->spinLightAngleStart->setVisible(ang); ui->spinLightAngleStart->setVisible(ang);
ui->spinLightAngleEnd->setVisible(ang); ui->spinLightAngleEnd->setVisible(ang);
ui->mapLight->setVisible(ang);
if (!view || !active) return; if (!view || !active) return;
QList<Light *> sll = view->selectedLights(); QList<Light *> sll = view->selectedLights();
foreach(Light * o, sll) { 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<Light *> sll = view->selectedLights();
foreach(Light * o, sll) {
o->apply();
}
}
void ObjectEditor::spinChanged(double v) { void ObjectEditor::spinChanged(double v) {
if (!view || !active) return; if (!view || !active) return;
ObjectBaseList sol = view->selectedObjects(true); ObjectBaseList sol = view->selectedObjects(true);

View File

@@ -50,6 +50,7 @@ private slots:
void on_comboLightType_currentIndexChanged(int index); void on_comboLightType_currentIndexChanged(int index);
void on_buttonColor_colorChanged(const QColor & v); void on_buttonColor_colorChanged(const QColor & v);
void on_mapLight_changed();
void spinChanged(double v); void spinChanged(double v);
void spinTextureChanged(double v); void spinTextureChanged(double v);
void spinLightChanged(double v); void spinLightChanged(double v);

View File

@@ -62,7 +62,7 @@
<x>0</x> <x>0</x>
<y>-287</y> <y>-287</y>
<width>444</width> <width>444</width>
<height>1081</height> <height>1100</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
@@ -810,6 +810,13 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="7" column="0" colspan="2">
<widget class="MaterialMapEditor" name="mapLight" native="true">
<property name="styleSheet">
<string notr="true">font:normal;</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@@ -832,6 +839,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="spinCameraDepthStart">
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_45"> <widget class="QLabel" name="label_45">
<property name="text"> <property name="text">
@@ -864,34 +884,10 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout"> <widget class="QLabel" name="label_47">
<item>
<widget class="QCheckBox" name="checkCameraMirrorY">
<property name="text"> <property name="text">
<string>Mirror Y</string> <string>Roll:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkCameraMirrorX">
<property name="text">
<string>Mirror X</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="spinCameraDepthStart">
<property name="decimals">
<number>5</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
<property name="value">
<double>0.100000000000000</double>
</property> </property>
</widget> </widget>
</item> </item>
@@ -920,13 +916,24 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="3" column="1">
<widget class="QLabel" name="label_47"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="checkCameraMirrorY">
<property name="text"> <property name="text">
<string>Roll:</string> <string>Mirror Y</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="checkCameraMirrorX">
<property name="text">
<string>Mirror X</string>
</property>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@@ -965,6 +972,15 @@
<extends>QWidget</extends> <extends>QWidget</extends>
<header>scroll_spin_box.h</header> <header>scroll_spin_box.h</header>
</customwidget> </customwidget>
<customwidget>
<class>MaterialMapEditor</class>
<extends>QWidget</extends>
<header>material_map_editor.h</header>
<container>1</container>
<slots>
<signal>changed()</signal>
</slots>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>