c++ - Determining cascaded shadow map split ranges -
i'm doing cascaded shadow maps, , believe have problem concerning way split comparison select proper shadow map. stands, shadow mapping works overall in few cases @ angles not work.
currently lighting shader stage looks this:
"#version 420 const float depth_bias = 0.00005; layout(std140) uniform unifdirlight { mat4 mvpmatrix[4]; mat4 mcamviewmatrix; vec4 msplitdistance; vec4 mlightcolor; vec4 mlightdir; vec4 mgamma; vec2 mscreensize; } unifdirlightpass; layout (binding = 2) uniform sampler2d unifpositiontexture; layout (binding = 3) uniform sampler2d unifnormaltexture; layout (binding = 4) uniform sampler2d unifdiffusetexture; layout (binding = 6) uniform sampler2darrayshadow unifshadowtexture; out vec4 fragcolor; void main() { vec2 texcoord = gl_fragcoord.xy / unifdirlightpass.mscreensize; vec3 worldpos = texture(unifpositiontexture, texcoord).xyz; vec3 normal = normalize(texture(unifnormaltexture, texcoord).xyz); vec3 diffuse = texture(unifdiffusetexture, texcoord).xyz; vec4 campos = unifdirlightpass.mcamviewmatrix * vec4(worldpos, 1.0); // legit way of determining split? int index = 3; if (campos .z > unifdirlightpass.msplitdistance.x) index = 0; else if (campos .z > unifdirlightpass.msplitdistance.y) index = 1; else if (campos .z > unifdirlightpass.msplitdistance.z) index = 2; vec4 projcoords = unifdirlightpass.mvpmatrix[index] * vec4(worldpos, 1.0); projcoords.w = projcoords.z - depth_bias; projcoords.z = float(index); float visibilty = texture(unifshadowtexture, projcoords); float anglenormal = clamp(dot(normal, unifdirlightpass.mlightdir.xyz), 0, 1); fragcolor = vec4(diffuse, 1.0) * visibilty * anglenormal * unifdirlightpass.mlightcolor; }
and "msplitdistance", each component center fardistance of frustrum split, multiplied main cameras view matrix
vec4 camfardistcenter; camerafrustrum camerafrustrum = calculatecamerafrustrum(neardistarr[cascadeindex], fardistarr[cascadeindex], lighting.mcameraposition, lighting.mcameradirection, camfardistcenter); ..... camfardistcenter = lighting.mcameraviewmatrix * camfardistcenter; splitdistances[cascadeindex] = camfardistcenter.z;
here's how create camera frustrum each split, if of interest, believe pretty common alghorithm:
camerafrustrum calculatecamerafrustrum(const float mindist, const float maxdist, const vec3& cameraposition, const vec3& cameradirection, vec4& camfarz) { camerafrustrum ret = { vec4(-1.0f, -1.0f, 1.0f, 1.0f), vec4(-1.0f, -1.0f, -1.0f, 1.0f), vec4(-1.0f, 1.0f, 1.0f, 1.0f), vec4(-1.0f, 1.0f, -1.0f, 1.0f), vec4(1.0f, -1.0f, 1.0f, 1.0f), vec4(1.0f, -1.0f, -1.0f, 1.0f), vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(1.0f, 1.0f, -1.0f, 1.0f) }; const vec3 forwardvec = glm::normalize(cameradirection); const vec3 rightvec = glm::normalize(glm::cross(forwardvec, vec3(0.0f, 0.0f, 1.0f))); const vec3 upvec = glm::normalize(glm::cross(rightvec, forwardvec)); const vec3 nearcenter = cameraposition + forwardvec * mindist; const vec3 farcenter = cameraposition + forwardvec * maxdist; camfarz = vec4(farcenter, 1.0); const float nearheight = tan(glm::radians(70.0f) / 2.0f) * mindist; const float nearwidth = nearheight * 1920.0f / 1080.0f; const float farheight = tan(glm::radians(70.0f) / 2.0f) * maxdist; const float farwidth = farheight * 1920.0f / 1080.0f; ret[0] = vec4(nearcenter - (upvec * nearheight) - (rightvec * nearwidth), 1.0); ret[1] = vec4(nearcenter + (upvec * nearheight) - (rightvec * nearwidth), 1.0); ret[2] = vec4(nearcenter + (upvec * nearheight) + (rightvec * nearwidth), 1.0); ret[3] = vec4(nearcenter - (upvec * nearheight) + (rightvec * nearwidth), 1.0); ret[4] = vec4(farcenter - upvec * farheight - rightvec * farwidth, 1.0); ret[5] = vec4(farcenter + upvec * farheight - rightvec * farwidth, 1.0); ret[6] = vec4(farcenter + upvec * farheight + rightvec * farwidth, 1.0); ret[7] = vec4(farcenter - upvec * farheight + rightvec * farwidth, 1.0); return ret; }
is sound split comparison in camera space do? potential problem?
void calculatecamerafrustrum(glm::mat4& projectionmatrix, glm::mat4 viewmatrix, // viewmatrix = light pov glm::vec3 camera // camera = eye position + eye direction float znear, float zfar, glm::vec4 point[4]) // point[4] = shadow map boundaries glm::mat4 shadmvp = projectionmatrix * (viewmatrix * glm::translate(camera)); glm::vec3 transf; float maxx = znear, minx = zfar, maxy = znear, miny = zfar; int = -1; while (++i < 4) { transf = shadmvp * point[i]; transf.x /= transf.w; transf.y /= transf.w; if(transf.x > maxx) maxx = transf.x; if(transf.x < minx) minx = transf.x; if(transf.y > maxy) maxy = transf.y; if(transf.y < miny) miny = transf.y; } float scalex = 2.0f / (maxx - minx), scaley = 2.0f / (maxy - miny), offsetx = -0.5f * (maxx + minx) * scalex, offsety = -0.5f * (maxy + miny) * scaley; shadmvp = glm::mat4(1); // identity matrix shadmvp[0][0] = scalex; shadmvp[1][1] = scaley; shadmvp[0][3] = offsetx; shadmvp[1][3] = offsety; projectionmatrix *= shadmvp; } // no need calculate view frustum splitting, // boundaries of shadow maps levels needed (glm::ortho(...)). // :)
Comments
Post a Comment