cone shadows done
This commit is contained in:
@@ -16,11 +16,12 @@ void main(void) {
|
||||
|
||||
in vec3 view_dir, world_dir;
|
||||
|
||||
uniform vec2 dt;
|
||||
uniform vec2 dt, shadow_size;
|
||||
uniform float z_near;
|
||||
uniform sampler2D tex_coeffs[2];
|
||||
uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4, tex_sh;
|
||||
uniform sampler2DShadow tex_shadow[16];
|
||||
//uniform sampler2DShadow tex_shadow[16];
|
||||
uniform sampler2DArray tex_shadows_cone;
|
||||
uniform samplerCube tex_env;
|
||||
uniform int lights_start, lights_count;
|
||||
|
||||
@@ -34,16 +35,30 @@ const float PI = 3.1416;
|
||||
|
||||
vec4 pos, lpos, shp;
|
||||
vec3 li, si, ldir, halfV, bn, bn2, lwdir;
|
||||
//vec3 vds, vds2;
|
||||
vec3 vds, vds2;
|
||||
float rough_diff, rough_spec, dist, NdotL, NdotH, spot, ldist, diff, spec, sdist, shadow;
|
||||
|
||||
vec4 mapScreenToShadow(in int light_index) {
|
||||
vec4 shp = qgl_light_position[light_index].shadow_matrix * pos;
|
||||
shp.z += 0.095;
|
||||
|
||||
vec4 mapScreenToShadow(in int light_index, in vec3 offset) {
|
||||
vec4 shp = qgl_light_position[light_index].shadow_matrix * (pos + vec4(offset, 0));
|
||||
shp.z -= 0.05;
|
||||
return shp;
|
||||
}
|
||||
|
||||
|
||||
float getShadow(in vec3 uvz, in int layer) {
|
||||
vec2 uvpix = uvz.xy * shadow_size + vec2(0.5f);
|
||||
vec2 uvp = fract(uvpix), iuvp = vec2(1.f) - uvp;
|
||||
vec4 gt = textureGather(tex_shadows_cone, vec3(floor(uvpix.xy) / shadow_size, layer), 0);
|
||||
vec4 uvv;
|
||||
uvv[0] = iuvp.x * uvp.y;
|
||||
uvv[1] = uvp.x * uvp.y;
|
||||
uvv[2] = uvp.x * iuvp.y;
|
||||
uvv[3] = iuvp.x * iuvp.y;
|
||||
return dot(step(vec4(uvz.z), gt), uvv);
|
||||
}
|
||||
|
||||
|
||||
void calcLight(in int index, in vec3 n, in vec3 v) {
|
||||
lpos = qgl_light_position[index].position;
|
||||
ldir = lpos.xyz - (pos.xyz * lpos.w);
|
||||
@@ -59,8 +74,28 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
|
||||
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);
|
||||
spot *= textureProj(tex_shadow[index - lights_start], shp);
|
||||
if (qgl_light_parameter[index].flags == 1) {
|
||||
|
||||
float ds = ldist/300.;
|
||||
//float bias = ldist * 0.05;
|
||||
vds = ds * bn.xyz;
|
||||
vds2 = ds * bn2.xyz;
|
||||
|
||||
int layer = index - lights_start;
|
||||
float shadow = 0.;
|
||||
vec4 shp = mapScreenToShadow(index, vec3(0));
|
||||
shp.xy /= shp.w;
|
||||
//shp.z -= bias;
|
||||
//for (int xi = -2; xi <= 2; ++xi) {
|
||||
// for (int yi = -2; yi <= 2; ++yi) {
|
||||
//shadow += step(shp.z, texture(tex_shadows_cone, vec3(shp.xy, layer), ivec2(0, 0)).r);
|
||||
shadow = getShadow(shp.xyz, layer);
|
||||
// }
|
||||
//}
|
||||
spot *= shadow;// / 25.f;
|
||||
|
||||
//spot = texture(tex_shadows_cone, shp.xyz).r/20;
|
||||
//spot = sz;
|
||||
|
||||
/*//lwdir = mat3(mat_viewi) * qgl_Light[index].direction.xyz;
|
||||
//bn = normalize(cross(lwdir, vec3(1, 0, 0)));
|
||||
@@ -92,6 +127,7 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
|
||||
//shadow += getShadow(index, pos.xyz, - vds + vds2 + vds2);
|
||||
//shadow += shadow += getShadow(index, pos.xyz, vds+vds2)*10;
|
||||
spot *= mix(1., shadow / 11., shadow_on);*/
|
||||
}
|
||||
#endif
|
||||
vec3 dist_decay = vec3(1, ldist, ldist*ldist);
|
||||
spot /= dot(qgl_light_parameter[index].decay_intensity.xyz, dist_decay);
|
||||
@@ -156,8 +192,8 @@ void main(void) {
|
||||
float reflectivity = v2.b;
|
||||
float NdotV = dot(normal, v);
|
||||
float roughness3 = roughness*roughness*roughness;
|
||||
//bn = normalize(vec3(v3.w, v4.zw));
|
||||
//bn2 = normalize(cross(n, bn));
|
||||
bn = normalize(cross(normal, view_dir));
|
||||
bn2 = normalize(cross(normal, bn));
|
||||
rough_diff = max(roughness, _min_rough);
|
||||
rough_spec = max(roughness3, _min_rough);
|
||||
float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1);
|
||||
@@ -185,6 +221,7 @@ void main(void) {
|
||||
res_col = mix(res_col, fog_color.rgb, fog);
|
||||
|
||||
qgl_FragColor = vec4(res_col, alpha);
|
||||
//qgl_FragColor.rgb = view_dir;
|
||||
/*
|
||||
#ifdef SPOT
|
||||
vec4 wpos = vec4(world_dir * z, 1);
|
||||
|
||||
@@ -18,7 +18,6 @@ void main(void) {
|
||||
discard;
|
||||
|
||||
float z = gl_FragCoord.z;
|
||||
z = z + z - 1;
|
||||
z = ((_pe - 2.) * z_near) / (z + _pe - 1.); // infinite depth
|
||||
qgl_FragData[0] = vec4(z / 20);
|
||||
z = ((_pe - 2.) * z_near) / (z + z + _pe - 2.); // infinite depth
|
||||
qgl_FragData[0].r = z;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -100,6 +100,7 @@ enum MapType {
|
||||
enum TextureArrayRole {
|
||||
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); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -167,6 +168,10 @@ void Renderer::initShaders() {
|
||||
// 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;
|
||||
}
|
||||
prog->setUniformValueArray("tex_shadow", samplers.data(), samplers.size());
|
||||
// l->shadow_map.bindDepthTexture(mtShadowCone + i);
|
||||
l->shadow_map.bindColorTexture(0, mtShadowCone + i);
|
||||
}
|
||||
}*/
|
||||
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];
|
||||
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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -152,6 +152,7 @@ private:
|
||||
QImage last_img;
|
||||
QString timings;
|
||||
bool is_grabbing = false;
|
||||
QFunctionPointer framebufferTextureLayer = nullptr;
|
||||
};
|
||||
|
||||
#endif // RENDERER_H
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user