cone shadows done

This commit is contained in:
2023-02-12 21:27:04 +03:00
parent 728c4a85ed
commit e3389bcc20
11 changed files with 142 additions and 88 deletions

View File

@@ -95,6 +95,7 @@ const char qgl_structs[] = "#define QGL_MAPS_COUNT 6\n"
" vec4 color;\n"
" vec4 decay_intensity;\n"
" vec4 angles;\n"
" uint flags;\n"
"};\n"
"struct QGLLightPosition {\n"
" vec4 position;\n"

View File

@@ -98,8 +98,9 @@ enum MapType {
mtShadowCone = 8,
};
enum TextureArrayRole {
tarEmpty = 0,
tarMaps = 1,
tarEmpty = 0,
tarMaps = 1,
tarShadowsCone = 2,
};
enum EmptyMapRole {
emrWhite = 0,
@@ -130,6 +131,8 @@ struct QGLLightParameter {
QVector4D color;
QVector4D decay_intensity; // [^0, ^1, ^2, intensity]
QVector4D angles; // [start, cos(start), end, cos(end)]
GLuint flags = 0;
GLuint _align[3];
};
struct QGLLightPosition {
QGLLightPosition() { QMatrix4x4().copyDataTo(shadowmatrix); }

View File

@@ -82,7 +82,13 @@ bool Texture2DArray::resize(QOpenGLExtraFunctions * f, QSize new_size, int layer
f->glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
f->glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
f->glTexImage3D(target_, 0, GL_RGBA8, size_.width(), size_.height(), layers_, 0, format_, GL_UNSIGNED_BYTE, nullptr);
GLenum bformat = format_;
GLenum btype = GL_UNSIGNED_BYTE;
if (format_ == GL_R16F || format_ == GL_R32F) {
bformat = GL_RED;
btype = GL_FLOAT;
}
f->glTexImage3D(target_, 0, format_, size_.width(), size_.height(), layers_, 0, bformat, btype, nullptr);
return true;
}

View File

@@ -88,6 +88,7 @@ void Renderer::init(int width, int height) {
buffer_lights_pos.reinit();
textures_maps.reinit();
textures_empty.reinit();
shadow_maps_cone.reinit();
resize(width, height);
rend_mat.init(width, height);
rend_service.init(width, height);
@@ -163,10 +164,14 @@ 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<GLuint> 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;
@@ -177,6 +182,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);
prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone);
}
if (bindShader(srFinalPass, &prog)) {
prog->setUniformValue("tex_g1", 0);
@@ -288,18 +294,14 @@ 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);
/*if (pass.second == Light::Cone) {
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;
// l->shadow_map.bindDepthTexture(mtShadowCone + i);
l->shadow_map.bindColorTexture(0, 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;
@@ -311,13 +313,14 @@ void Renderer::renderLight(int first_wr_buff, bool clear_only) {
prog->setUniformValue("fog_decay", qMax(view->fogDecay(), 0.001f));
prog->setUniformValue("fog_density", view->fogDensity());
prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3, 3>());
prog->setUniformValue("shadow_size", view->shadow_map_size);
renderQuad(prog, quad, cam);
}
}
}
void Renderer::renderShadow(Light * light) {
void Renderer::renderShadow(int index, Light * light) {
Scene & scene(*(view->scene()));
bool force_resize = false;
if (!light->shadow_map.isInit()) {
@@ -325,12 +328,16 @@ void Renderer::renderShadow(Light * light) {
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();
if (!framebufferTextureLayer) {
framebufferTextureLayer = view->context()->getProcAddress("glFramebufferTextureLayer");
}
if (framebufferTextureLayer) {
((PFNGLFRAMEBUFFERTEXTURELAYERPROC)framebufferTextureLayer)(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, shadow_maps_cone.ID(), 0, index);
// glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadow_maps_cone.ID(), 0, index);
}
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glClearFramebuffer();
renderObjects(scene, rpSolid);
light->shadow_map.release();
@@ -378,11 +385,13 @@ void Renderer::renderScene() {
textures_maps.bind(f, tarMaps);
auto cam_ivm = cam->fullViewMatrix().inverted();
auto cone_ll = cur_lights.value(Light::Cone);
shadow_maps_cone.resize(f, view->shadow_map_size, cone_ll.size());
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];
Light * l = cone_ll[i];
if (!l->isCastShadows()) continue;
QMatrix4x4 pm = glMatrixPerspective(l->angle_end, 1., 0.1), om, vm;
om.translate(-l->worldAim());
vm.translate(0., 0., -l->distance());
@@ -392,7 +401,7 @@ void Renderer::renderScene() {
vm *= pmat.inverted();
auto vpm = pm * (vm * om);
prog->setUniformValue("qgl_ViewProjMatrix", vpm);
renderShadow(l);
renderShadow(i, l);
l->shadow_matrix = mat_vp * vpm * cam_ivm;
}
}
@@ -432,12 +441,13 @@ void Renderer::renderScene() {
setUniformCamera(prog, cam);
textures_empty.bind(f, tarEmpty);
textures_maps.bind(f, tarMaps);
shadow_maps_cone.bind(f, tarShadowsCone);
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());
fbo_ds.blit(dbrMetalRoughReflectFlags, fbo_ds.id(), dbrMetalRoughReflectFlagsSolid, fbo_ds.rect(), fbo_ds.rect());
fbo_ds.release();
phase.end();

View File

@@ -81,12 +81,12 @@ public:
enum DeferredBufferRole {
dbrDiffuse,
dbrNormalZ,
dbrSpecularReflect,
dbrEmissionRough,
dbrMetalRoughReflectFlags,
dbrEmission,
dbrSpeedBitangXY,
dbrNormalZSolid,
dbrSpecularReflectSolid,
dbrMetalRoughReflectFlagsSolid,
dbrBuffersCount,
};
@@ -113,7 +113,7 @@ protected:
void reloadObjects();
void renderObjects(Scene & scene, RenderPass pass);
void renderLight(int first_wr_buff, bool clear_only);
void renderShadow(Light * light);
void renderShadow(int index, Light * light);
bool bindShader(ShaderRole role, QOpenGLShaderProgram ** ret = 0);
bool bindShader(QOpenGLShaderProgram * sp);
@@ -151,7 +151,8 @@ private:
QVector<FramebufferEffectBase *> fb_effects;
QImage last_img;
QString timings;
bool is_grabbing = false;
bool is_grabbing = false;
QFunctionPointer framebufferTextureLayer = nullptr;
};
#endif // RENDERER_H

View File

@@ -36,7 +36,8 @@ RendererBase::RendererBase(QGLView * view_)
, buffer_lights(GL_UNIFORM_BUFFER, GL_STREAM_DRAW)
, buffer_lights_pos(GL_UNIFORM_BUFFER, GL_STREAM_DRAW)
, textures_empty(GL_RGBA, false)
, textures_maps(GL_RGBA, true) {
, textures_maps(GL_RGBA, true)
, shadow_maps_cone(GL_R32F, false) {
textures_manager = new TextureManager(view);
maps_size = QSize(1024, 1024);
maps_hash = 0;
@@ -60,6 +61,7 @@ void RendererBase::initTextureArrays() {
textures_empty.load(f, im, emrWhite);
im.fill(0xFF8080);
textures_empty.load(f, im, emrBlue);
shadow_maps_cone.init(f);
}
@@ -223,6 +225,7 @@ void RendererBase::reloadLightsParameters(const QMap<int, QList<Light *>> & ligh
so.decay_intensity[1] = l->decay_linear;
so.decay_intensity[2] = l->decay_quadratic;
so.decay_intensity[3] = l->intensity;
so.flags = l->cast_shadow ? 1 : 0;
}
buffer_lights.bind(view);
buffer_lights.resize(view, cur_lights_params_.size() * sizeof(QGLLightParameter));

View File

@@ -57,7 +57,7 @@ protected:
QVector<QGLEngineShaders::QGLLightPosition> cur_lights_pos_;
Buffer buffer_materials;
Buffer buffer_lights, buffer_lights_pos;
Texture2DArray textures_empty, textures_maps;
Texture2DArray textures_empty, textures_maps, shadow_maps_cone;
QSize maps_size;
uint maps_hash;
GLuint tex_coeff[2];

View File

@@ -223,6 +223,12 @@ void ObjectBase::setVisible(bool v) {
}
void ObjectBase::setCastShadows(bool on) {
cast_shadow = on;
if (type_ == glLight) ((Light *)this)->apply();
}
void ObjectBase::rotateZ(GLfloat a) {
raw_matrix = false;
trans.setRotationZ(trans.rotationZ() + a);
@@ -587,23 +593,12 @@ void AimedObject::orbitXY(const float & a) {
void AimedObject::transformChanged() {}
Light::Light(): AimedObject(), shadow_map(nullptr, 1, true) {
type_ = glLight;
light_type = Omni;
intensity = 1.;
angle_start = angle_end = 180.;
decay_linear = decay_quadratic = decay_start = 0.;
decay_const = decay_end = 1.;
setDirection(0, 0, -1.);
}
Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(nullptr, 1, true) {
Light::Light(const QVector3D & p, const QColor & c, float i): AimedObject(), shadow_map(nullptr, 0, true, GL_R32F) {
type_ = glLight;
light_type = Omni;
intensity = i;
color_ = c;
angle_start = angle_end = 180.;
angle_start = angle_end = 90.;
decay_linear = decay_quadratic = decay_start = 0.;
decay_const = decay_end = 1.;
setPos(p);

View File

@@ -85,7 +85,7 @@ public:
bool isReceiveShadows() const { return rec_shadow; }
bool isCastShadows() const { return cast_shadow; }
void setReceiveShadows(bool on) { rec_shadow = on; }
void setCastShadows(bool on) { cast_shadow = on; }
void setCastShadows(bool on);
void move(const QVector3D & dv) {
trans.setTranslation(pos() + dv);
@@ -398,8 +398,7 @@ public:
Directional
};
Light();
Light(const QVector3D & p, const QColor & c = Qt::white, float i = 1.);
Light(const QVector3D & p = QVector3D(), const QColor & c = Qt::white, float i = 1.);
virtual ObjectBase * clone(bool withChildren = true);
virtual void init() {
shadow_map.resize(512, 512);