shadows basically works

This commit is contained in:
2023-02-09 17:21:59 +03:00
parent 65dd078f07
commit 3cf466e5d3
29 changed files with 293 additions and 206 deletions

View File

@@ -61,6 +61,8 @@ Renderer::Renderer(QGLView * view_)
shader_files[srFinalPass] = "ds_final.glsl";
shader_files[srTonemapPass] = "ds_tonemap.glsl";
shader_files[srShadowPass] = "shadow.glsl";
shader_defines[srGeometrySolidPass] << "SOLID";
shader_defines[srLightSpotPass] << "SPOT";
@@ -161,15 +163,16 @@ bool Renderer::bindShader(QOpenGLShaderProgram * sp) {
void Renderer::initShaders() {
if (!need_init_shaders) return;
need_init_shaders = false;
initUniformBuffer(shaders.value(srGeometrySolidPass), &buffer_materials, bpMaterials, "QGLMaterialData");
initUniformBuffer(shaders.value(srGeometryTransparentPass), &buffer_materials, bpMaterials, "QGLMaterialData");
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");
QOpenGLShaderProgram * prog = 0;
for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) {
initUniformBuffer(shaders.value(role), &buffer_materials, bpMaterials, "QGLMaterialData");
initUniformBuffer(shaders.value(role), &buffer_lights, bpLightParameters, "QGLLightParameterData");
initUniformBuffer(shaders.value(role), &buffer_lights_pos, bpLightPositions, "QGLLightPositionData");
if (!bindShader(role, &prog)) continue;
initUniformBuffer(prog, &buffer_materials, bpMaterials, "QGLMaterialData");
initUniformBuffer(prog, &buffer_lights, bpLightParameters, "QGLLightParameterData");
initUniformBuffer(prog, &buffer_lights_pos, bpLightPositions, "QGLLightPositionData");
for (int i = 0; i < 5; ++i)
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount);
@@ -182,10 +185,9 @@ void Renderer::initShaders() {
prog->setUniformValue("tex_t_0", 3);
prog->setUniformValue("tex_t_1", 4);
}
if (bindShader(srGeometrySolidPass, &prog)) {
setUniformMaps(prog);
}
if (bindShader(srGeometryTransparentPass, &prog)) {
for (ShaderRole role: {srGeometrySolidPass, srGeometryTransparentPass, srShadowPass}) {
if (!bindShader(role, &prog)) continue;
initUniformBuffer(prog, &buffer_materials, bpMaterials, "QGLMaterialData");
setUniformMaps(prog);
}
if (bindShader(srTonemapPass, &prog)) {
@@ -286,6 +288,18 @@ void Renderer::renderLight(int first_wr_buff, bool clear_only) {
back.setAlpha(0);
foreach(PassPair pass, passes) {
if (bindShader(pass.first, &prog)) {
if (pass.second == Light::Cone) {
QVector<GLint> samplers;
samplers.resize(16);
auto & cone_ll(cur_lights[pass.second]);
for (int i = 0; i < cone_ll.size(); ++i) {
Light * l = cone_ll[i];
l->shadow_map.bindDepthTexture(mtShadowCone + i);
// l->shadow_map.bindColorTexture(0, 10);
samplers[i] = mtShadowCone + i;
}
prog->setUniformValueArray("tex_shadow", samplers.data(), samplers.size());
}
fbo_out.setWriteBuffer(first_wr_buff + pass.second);
glClearFramebuffer(back, false);
if (clear_only) continue;
@@ -303,6 +317,26 @@ void Renderer::renderLight(int first_wr_buff, bool clear_only) {
}
void Renderer::renderShadow(Light * light) {
Scene & scene(*(view->scene()));
bool force_resize = false;
if (!light->shadow_map.isInit()) {
light->shadow_map.reinit(view);
force_resize = true;
}
light->shadow_map.resize(view->shadow_map_size, force_resize);
if (force_resize) {
light->shadow_map.bindDepthTexture(mtShadowCone);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
light->shadow_map.bind();
glClearFramebuffer();
renderObjects(scene, rpSolid);
light->shadow_map.release();
}
void Renderer::renderScene() {
timings.clear();
Measurer phase(&timings);
@@ -315,6 +349,7 @@ void Renderer::renderScene() {
Camera * cam = view->camera();
QOpenGLShaderProgram * prog = 0;
bool scene_changed = scene.prepare();
cur_lights = scene.lights_used;
scene.destroyUnused(f);
phase.end();
@@ -335,9 +370,36 @@ void Renderer::renderScene() {
}
phase.end();
/// shadows
phase.begin("shadows");
if (bindShader(srShadowPass, &prog)) {
glEnableDepth();
textures_empty.bind(f, tarEmpty);
textures_maps.bind(f, tarMaps);
auto cam_ivm = cam->fullViewMatrix().inverted();
auto cone_ll = cur_lights.value(Light::Cone);
QMatrix4x4 mat_vp;
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];
QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm;
om.translate(-l->worldAim());
vm.translate(0., 0., -l->distance());
// vm.rotate(-roll_, 0., 0., 1.);
QMatrix4x4 pmat = l->worldTransform();
pmat(0, 3) = pmat(1, 3) = pmat(2, 3) = 0.;
vm *= pmat.inverted();
auto vpm = pm * (vm * om);
prog->setUniformValue("qgl_ViewProjMatrix", vpm);
renderShadow(l);
l->shadow_matrix = mat_vp * vpm * cam_ivm;
}
}
phase.end();
/// lights
phase.begin("lights prepare");
cur_lights = scene.lights_used;
bool use_camlight = (camera_light_mode == QGLView::clmOn);
if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty()) {
use_camlight = true;
@@ -360,6 +422,7 @@ void Renderer::renderScene() {
}
phase.end();
/// solid geometry pass
phase.begin("geometry solid");
fbo_ds.bind();
@@ -369,7 +432,9 @@ void Renderer::renderScene() {
setUniformCamera(prog, cam);
textures_empty.bind(f, tarEmpty);
textures_maps.bind(f, tarMaps);
glPolygonMode(GL_FRONT_AND_BACK, view->renderMode());
renderObjects(scene, rpSolid);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
fbo_ds.blit(dbrNormalZ, fbo_ds.id(), dbrNormalZSolid, fbo_ds.rect(), fbo_ds.rect());
fbo_ds.blit(dbrSpecularReflect, fbo_ds.id(), dbrSpecularReflectSolid, fbo_ds.rect(), fbo_ds.rect());
@@ -392,7 +457,9 @@ void Renderer::renderScene() {
setUniformCamera(prog, cam);
textures_empty.bind(f, tarEmpty);
textures_maps.bind(f, tarMaps);
glPolygonMode(GL_FRONT_AND_BACK, view->renderMode());
renderObjects(scene, rpTransparent);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
fbo_ds.release();
phase.end();
@@ -434,7 +501,7 @@ void Renderer::renderScene() {
/// FXAA
phase.begin("fxaa");
if (view->isFeatureEnabled(QGLView::qglFXAA)) {
if (view->FXAA_) {
prog = shader_fxaa;
if (bindShader(prog)) {
auto free = getFreePlanes(0);
@@ -462,7 +529,7 @@ void Renderer::renderScene() {
rend_selection.drawSelection(fbo_out, cur_write_plane);
rend_service.renderService();
} else {
fbo_out.blit(cur_write_plane, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size() * view->devicePixelRatio()));
fbo_out.blit(cur_write_plane, 0, 0, fbo_out.rect(), QRect(QPoint(), view->pixelSize()));
}
phase.end();
@@ -474,6 +541,12 @@ void Renderer::renderScene() {
// qDebug() << last_img.size();
}
phase.end();
/*
auto cone_ll = cur_lights.value(Light::Cone);
if (!cone_ll.isEmpty()) {
Light * l = cone_ll[0];
l->shadow_map.blit(0, 0, 0, l->shadow_map.rect(), l->shadow_map.rect());
}*/
}