diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj index 6fa540b..a1bbcba 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj @@ -70,6 +70,8 @@ stdcpp20 $(ProjectDir)include;$(SolutionDir)ArchitectureColoredPainting\src\Editor\RightBar;$(SolutionDir)ArchitectureColoredPainting\src\Editor\;$(SolutionDir)FramelessHelper\include;$(SolutionDir)FramelessHelper\qmake\inc\core;$(SolutionDir)FramelessHelper\include\FramelessHelper\Core;%(AdditionalIncludeDirectories) FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions) + Level1 + Speed opengl32.lib;%(AdditionalDependencies) @@ -80,7 +82,7 @@ true true ProgramDatabase - Disabled + MaxSpeed MultiThreadedDebugDLL @@ -171,6 +173,7 @@ + diff --git a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters index aa91db3..6a72e52 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -326,6 +326,9 @@ Resource Files\Shaders + + Resource Files\Shaders + diff --git a/ArchitectureColoredPainting/res/MainWindow.qrc b/ArchitectureColoredPainting/res/MainWindow.qrc index 5fb0bed..05dcdbb 100644 --- a/ArchitectureColoredPainting/res/MainWindow.qrc +++ b/ArchitectureColoredPainting/res/MainWindow.qrc @@ -31,6 +31,7 @@ Shaders/irradiance_convolution.frag Shaders/cubemap_prefilter.frag Shaders/brdf_lut.comp + Shaders/pageId_downsample.comp qt.conf diff --git a/ArchitectureColoredPainting/res/Shaders/model.frag b/ArchitectureColoredPainting/res/Shaders/model.frag index e2cd1ec..97e724a 100644 --- a/ArchitectureColoredPainting/res/Shaders/model.frag +++ b/ArchitectureColoredPainting/res/Shaders/model.frag @@ -9,7 +9,7 @@ layout (location = 0) out vec4 gBaseColor; layout (location = 1) out vec3 gNormal; layout (location = 2) out vec3 gPosition; layout (location = 3) out vec2 gMetallicRoughness; -layout (location = 4) out uint gPaintingIndex; +layout (location = 4) out uvec2 gPaintingIndex; in vec2 TexCoords; in vec3 WorldPos; @@ -36,12 +36,22 @@ vec3 getNormalFromMap() void main() { - gBaseColor = texture(texture_basecolor, TexCoords); + if(textureSize(texture_basecolor,0)!=vec2(0)) + gBaseColor = texture(texture_basecolor, TexCoords); + else + gBaseColor = vec4(1); if(gBaseColor.a<0.4) discard; gPosition = WorldPos; - gNormal = getNormalFromMap(); - gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; - gPaintingIndex = 0; + if(textureSize(texture_normal,0)!=vec2(0)) + gNormal = getNormalFromMap(); + else + gNormal = Normal; + if(textureSize(texture_metallic_roughness,0)!=vec2(0)) + gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; + else + gMetallicRoughness = vec2(0,1); + + gPaintingIndex = uvec2(0); } \ No newline at end of file diff --git a/ArchitectureColoredPainting/res/Shaders/model_shadow.frag b/ArchitectureColoredPainting/res/Shaders/model_shadow.frag index 391e444..308e92b 100644 --- a/ArchitectureColoredPainting/res/Shaders/model_shadow.frag +++ b/ArchitectureColoredPainting/res/Shaders/model_shadow.frag @@ -1,4 +1,5 @@ #version 450 core +#extension GL_ARB_sparse_texture2 : enable uniform sampler2D texture_basecolor; @@ -6,8 +7,11 @@ in vec2 TexCoords; void main() { - //gBaseColor = vec4(1,0,0,1); - vec4 baseColor = texture(texture_basecolor, TexCoords); + vec4 baseColor;// = texture(texture_basecolor, TexCoords); + float lod = textureQueryLod(texture_basecolor, TexCoords).x; + while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, baseColor))&&lod>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF); uvec4 pyIndex = uvec4(1)+pxIndex; mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], elementData[pxIndex[1]], elementData[pyIndex[1]], @@ -1078,8 +1069,8 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal if(contourIterator_==contourIndex + 1 + lineCount) contourIterator = contourIndex + 1; uint lineIndex = elementIndexs[contourIterator]; - uint pLocation = linesOffset + 4 * lineIndex; - uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]); + uint pLocation = linesOffset + 3 * lineIndex; + uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF); uvec4 pyIndex = uvec4(1)+pxIndex; mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], @@ -1182,13 +1173,13 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal void main() { - //ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); - ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); - uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r; - if(paintingIndex==0) - return; - - vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; + ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy); + vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor); + //imageStore(gBaseColor, pixelLocation, vec4(uv,1,1)); + //imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1)); + //return; + uv = vec2(1)-uv*2; + //vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; vec3 debugBVH = vec3(0); //bool debugHit = false; diff --git a/ArchitectureColoredPainting/res/Shaders/painting.frag b/ArchitectureColoredPainting/res/Shaders/painting.frag index 0c2f200..5fed343 100644 --- a/ArchitectureColoredPainting/res/Shaders/painting.frag +++ b/ArchitectureColoredPainting/res/Shaders/painting.frag @@ -1,10 +1,16 @@ #version 450 core +#extension GL_ARB_sparse_texture2 : enable + +uniform sampler2D texture_basecolor; +uniform sampler2D texture_metallic_roughness; + +uniform uint paintingId; layout(location = 0) out vec4 gBaseColor; layout(location = 1) out vec3 gNormal; layout(location = 2) out vec3 gPosition; layout(location = 3) out vec2 gMetallicRoughness; -layout(location = 4) out uint gPaintingIndex; +layout(location = 4) out uvec2 gPaintingIndex; layout(location = 5) out vec2 gPaintingTexCoord; in vec2 TexCoords; @@ -13,635 +19,37 @@ in vec3 Normal; void main() { - - gBaseColor = vec4( vec3(1),1 ); - // mainImage(gBaseColor, vec2(1.,1.)-TexCoords); + int lodExpect = int(textureQueryLod(texture_basecolor, TexCoords).x); + int levels = textureQueryLevels(texture_basecolor); + float lod = lodExpect; + while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod dot(tang, p1)) - { - return distance(p1, uv); - } - else - { - return dot(nor, uv) - dot(nor, p0); - } -} - -bool int_test(vec2 uv, vec2 last_point, vec2 p0, vec2 p1) -{ - last_point -= uv; - p0 -= uv; - p1 -= uv; - - bool ret; - if (p0.y == 0.) - { - ret = (p0.x >= 0. && p1.y * last_point.y < 0.); - } - else if (p1.y == 0.) - { - ret = false; - } - else if (p0.y * p1.y < 0.) - { - if (p0.x >= 0. && p1.x >= 0.) - { - ret = true; - } - else if (p0.x < 0. && p1.x < 0.) - { - ret = false; - } - else - { - vec2 nor; - if (p0.y > p1.y) - { - nor = p0 - p1; - } - else - { - nor = p1 - p0; - } - - nor = vec2(nor.y, -nor.x); - if (dot(nor, p0) < 0.) - { - ret = false; - } - else - { - ret = true; - } - } - } - else - { - ret = false; - } - - return ret; -} - -bool tri_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, bool inside) -{ - vec2 nor1 = normalize(p0 - p1); - nor1 = vec2(nor1.y, -nor1.x); - vec2 nor2 = normalize(p1 - p2); - nor2 = vec2(nor2.y, -nor2.x); - vec2 tan3 = normalize(p2 - p0); - vec2 nor3 = vec2(tan3.y, -tan3.x); - - if (inside) - { - if (dot(tan3, p0) >= dot(tan3, uv) || dot(tan3, p2) <= dot(tan3, uv)) - { - return false; - } - - float brd = max(dot(nor3, nor1), dot(nor3, nor2)) * border; - return (dot(uv, nor1) >= dot(p0, nor1) && dot(uv, nor2) >= dot(p1, nor2) && - dot(uv, nor3) >= dot(p2, nor3) + brd) || - (dot(uv, nor1) <= dot(p0, nor1) && dot(uv, nor2) <= dot(p1, nor2) && - dot(uv, nor3) <= dot(p2, nor3) - brd); - } - else - { - float brd1 = dot(nor1, tan3) * border; - float brd2 = dot(nor2, tan3) * border; - - if (dot(tan3, p0) >= dot(tan3, uv) - brd1 || dot(tan3, p2) <= dot(tan3, uv) - brd2) - { - return false; - } - return (dot(uv, nor1) >= dot(p0, nor1) - border && dot(uv, nor2) >= dot(p1, nor2) - border && - dot(uv, nor3) >= dot(p2, nor3)) || - (dot(uv, nor1) <= dot(p0, nor1) + border && dot(uv, nor2) <= dot(p1, nor2) + border && - dot(uv, nor3) <= dot(p2, nor3)); - } -} - -float bezier_sd(vec2 uv, vec2 p0, vec2 p1, vec2 p2) -{ - - const mat2 trf1 = mat2(-1, 2, 1, 2); - mat2 trf2 = inv(mat2(p0 - p1, p2 - p1)); - mat2 trf = trf1 * trf2; - - uv -= p1; - vec2 xy = trf * uv; - xy.y -= 1.; - - vec2 gradient; - gradient.x = 2. * trf[0][0] * (trf[0][0] * uv.x + trf[1][0] * uv.y) - trf[0][1]; - gradient.y = 2. * trf[1][0] * (trf[0][0] * uv.x + trf[1][0] * uv.y) - trf[1][1]; - - return (xy.x * xy.x - xy.y) / length(gradient); -} - -//////////////////////////////// - -// Modified from http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c -// Credits to Doublefresh for hinting there -int solve_quadric(vec2 coeffs, inout vec2 roots) -{ - - // normal form: x^2 + px + q = 0 - float p = coeffs[1] / 2.; - float q = coeffs[0]; - - float D = p * p - q; - - if (D < 0.) - { - return 0; - } - else - { - roots[0] = -sqrt(D) - p; - roots[1] = sqrt(D) - p; - - return 2; - } -} - -// From Trisomie21 -// But instead of his cancellation fix i'm using a newton iteration -int solve_cubic(vec3 coeffs, inout vec3 r) -{ - - float a = coeffs[2]; - float b = coeffs[1]; - float c = coeffs[0]; - - float p = b - a * a / 3.0; - float q = a * (2.0 * a * a - 9.0 * b) / 27.0 + c; - float p3 = p * p * p; - float d = q * q + 4.0 * p3 / 27.0; - float offset = -a / 3.0; - if (d >= 0.0) - { // Single solution - float z = sqrt(d); - float u = (-q + z) / 2.0; - float v = (-q - z) / 2.0; - u = sign(u) * pow(abs(u), 1.0 / 3.0); - v = sign(v) * pow(abs(v), 1.0 / 3.0); - r[0] = offset + u + v; - - // Single newton iteration to account for cancellation - float f = ((r[0] + a) * r[0] + b) * r[0] + c; - float f1 = (3. * r[0] + 2. * a) * r[0] + b; - - r[0] -= f / f1; - - return 1; - } - float u = sqrt(-p / 3.0); - float v = acos(-sqrt(-27.0 / p3) * q / 2.0) / 3.0; - float m = cos(v), n = sin(v) * 1.732050808; - - // Single newton iteration to account for cancellation - //(once for every root) - r[0] = offset + u * (m + m); - r[1] = offset - u * (n + m); - r[2] = offset + u * (n - m); - - vec3 f = ((r + a) * r + b) * r + c; - vec3 f1 = (3. * r + 2. * a) * r + b; - - r -= f / f1; - - return 3; -} - -float cubic_bezier_normal_iteration(float t, vec2 a0, vec2 a1, vec2 a2, vec2 a3) -{ - // horner's method - vec2 a_2 = a2 + t * a3; - vec2 a_1 = a1 + t * a_2; - vec2 b_2 = a_2 + t * a3; - - vec2 uv_to_p = a0 + t * a_1; - vec2 tang = a_1 + t * b_2; - - float l_tang = dot(tang, tang); - return t - dot(tang, uv_to_p) / l_tang; -} - -float cubic_bezier_dis_approx_sq(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3) -{ - vec2 a3 = (-p0 + 3. * p1 - 3. * p2 + p3); - vec2 a2 = (3. * p0 - 6. * p1 + 3. * p2); - vec2 a1 = (-3. * p0 + 3. * p1); - vec2 a0 = p0 - uv; - - float d0 = 1e38; - - float t; - vec3 params = vec3(0, .5, 1); - - for (int i = 0; i < 3; i++) - { - t = params[i]; - for (int j = 0; j < 3; j++) - { - t = cubic_bezier_normal_iteration(t, a0, a1, a2, a3); - } - t = clamp(t, 0., 1.); - vec2 uv_to_p = ((a3 * t + a2) * t + a1) * t + a0; - d0 = min(d0, dot(uv_to_p, uv_to_p)); - } - - return d0; -} - -// segment_dis_sq by iq -float length2(vec2 v) -{ - return dot(v, v); -} - -float segment_dis_sq(vec2 p, vec2 a, vec2 b) -{ - vec2 pa = p - a, ba = b - a; - float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); - return length2(pa - ba * h); -} - -int segment_int_test(vec2 uv, vec2 p0, vec2 p1) -{ - p0 -= uv; - p1 -= uv; - - int ret; - - if (p0.y * p1.y < 0.) - { - vec2 nor = p0 - p1; - nor = vec2(nor.y, -nor.x); - - float sgn; - - if (p0.y > p1.y) - { - sgn = 1.; - } - else - { - sgn = -1.; - } - - if (dot(nor, p0) * sgn < 0.) - { - ret = 0; - } - else - { - ret = 1; - } - } - else - { - ret = 0; - } - - return ret; -} - -int cubic_bezier_int_test(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3) -{ - - float cu = (-p0.y + 3. * p1.y - 3. * p2.y + p3.y); - float qu = (3. * p0.y - 6. * p1.y + 3. * p2.y); - float li = (-3. * p0.y + 3. * p1.y); - float co = p0.y - uv.y; - - vec3 roots = vec3(1e38); - int n_roots; - - int n_ints = 0; - - if (uv.x < min(min(p0.x, p1.x), min(p2.x, p3.x))) - { - if (uv.y >= min(p0.y, p3.y) && uv.y <= max(p0.y, p3.y)) - { - n_ints = 1; - } - } - else - { - - if (abs(cu) < .0001) - { - n_roots = solve_quadric(vec2(co / qu, li / qu), roots.xy); - } - else - { - n_roots = solve_cubic(vec3(co / cu, li / cu, qu / cu), roots); - } - - for (int i = 0; i < n_roots; i++) - { - if (roots[i] >= 0. && roots[i] <= 1.) - { - float x_pos = -p0.x + 3. * p1.x - 3. * p2.x + p3.x; - x_pos = x_pos * roots[i] + 3. * p0.x - 6. * p1.x + 3. * p2.x; - x_pos = x_pos * roots[i] + -3. * p0.x + 3. * p1.x; - x_pos = x_pos * roots[i] + p0.x; - - if (x_pos > uv.x) - { - n_ints++; - } - } - } - } - - return n_ints; -} - -float path2_dis_sq(vec2 uv) -{ - float dis_sq = 1e38; - - int num_its = 0; - - vec2[45] p = vec2[](vec2(-0.124919, 0.0496896), vec2(-0.127105, 0.0391554), vec2(-0.127105, 0.0405467), - vec2(-0.127105, 0.0463107), vec2(-0.131876, 0.0506833), vec2(-0.143205, 0.0506833), - vec2(-0.177789, 0.0506833), vec2(-0.194286, 0.00795032), vec2(-0.194286, -0.018882), - vec2(-0.194286, -0.0425342), vec2(-0.181366, -0.0508821), vec2(-0.167851, -0.0508821), - vec2(-0.153739, -0.0508821), vec2(-0.144397, -0.0417392), vec2(-0.138236, -0.0325963), - vec2(-0.137043, -0.0445217), vec2(-0.129888, -0.0508821), vec2(-0.118758, -0.0508821), - vec2(-0.108025, -0.0508821), vec2(-0.0901364, -0.0465093), vec2(-0.0788071, -0.0141118), - vec2(-0.087155, -0.0141118), vec2(-0.0901364, -0.0240497), vec2(-0.0955028, -0.0327951), - vec2(-0.103254, -0.0327951), vec2(-0.10882, -0.0327951), vec2(-0.111403, -0.0298137), - vec2(-0.111403, -0.0242485), vec2(-0.111403, -0.0224597), vec2(-0.111205, -0.0204721), - vec2(-0.110609, -0.0178882), vec2(-0.0962985, 0.0496896), vec2(-0.137043, 0.0383603), - vec2(-0.130683, 0.0383603), vec2(-0.128894, 0.0331926), vec2(-0.128894, 0.0308075), - vec2(-0.138435, -0.0141118), vec2(-0.14082, -0.0256398), vec2(-0.149168, -0.0316026), - vec2(-0.154931, -0.0316026), vec2(-0.158509, -0.0316026), vec2(-0.164869, -0.0314042), - vec2(-0.164869, -0.0160994), vec2(-0.164869, 0.00258385), vec2(-0.153938, 0.0383603)); - - ivec2[6] seg = ivec2[](ivec2(0, 1), ivec2(1, 2), ivec2(20, 21), ivec2(30, 31), ivec2(31, 0), ivec2(35, 36)); - - ivec4[13] c_bez = - ivec4[](ivec4(2, 3, 4, 5), ivec4(5, 6, 7, 8), ivec4(8, 9, 10, 11), ivec4(11, 12, 13, 14), ivec4(14, 15, 16, 17), - ivec4(17, 18, 19, 20), ivec4(21, 22, 23, 24), ivec4(24, 25, 26, 27), ivec4(27, 28, 29, 30), - ivec4(32, 33, 34, 35), ivec4(36, 37, 38, 39), ivec4(39, 40, 41, 42), ivec4(42, 43, 44, 32)); - - if (all(lessThan(uv, vec2(-0.0788071, 0.0506833) + border)) && - all(greaterThan(uv, vec2(-0.194286, -0.0508821) - border))) - { - for (int i = 0; i < 6; i++) - { - dis_sq = min(dis_sq, segment_dis_sq(uv, p[seg[i][0]], p[seg[i][1]])); - num_its += segment_int_test(uv, p[seg[i][0]], p[seg[i][1]]); - } - for (int i = 0; i < 13; i++) - { - dis_sq = min( - dis_sq, cubic_bezier_dis_approx_sq(uv, p[c_bez[i][0]], p[c_bez[i][1]], p[c_bez[i][2]], p[c_bez[i][3]])); - num_its += cubic_bezier_int_test(uv, p[c_bez[i][0]], p[c_bez[i][1]], p[c_bez[i][2]], p[c_bez[i][3]]); - } - } - - float sgn = 1.; - - if (num_its % 2 == 1) - { - sgn = -1.; - } - - return sgn * dis_sq; -} - -void mainImage(out vec3 fragColor, in vec2 fragCoord) -{ - border = 0.01; - vec2 uv = fragCoord; - uv -= .5; - - float dis_sq = 1e38; - - if (all(lessThan(uv, vec2(0.4, 0.0993791) + border)) && all(greaterThan(uv, vec2(-0.4, -0.0993791) - border))) - { - dis_sq = min(dis_sq, path2_dis_sq(uv)); - } - - float dis = sign(dis_sq) * sqrt(abs(dis_sq)); - - fragColor = vec3(smoothstep(0., border, dis)); - if (dis > 0 && dis <= border) - fragColor = vec3(1, 1, 0); -} -/////////////////////////////// - -const uint STACK_SIZE = 40; - -struct Stack -{ - uint top; - uint data[STACK_SIZE]; - - bool empty() - { - return top == 0; - } - bool full() - { - return top == STACK_SIZE; - } - bool getTop(out uint x) - { - if (empty()) - return false; - x = data[top - 1]; - return true; - } - bool pop() - { - if (empty()) - return false; - top--; - return true; - } - bool push(in uint x) - { - if (full()) - return false; - data[top] = x; - top++; - return true; - } -} stack, elementStack; - -vec3 drawElement(uint elementIndex, vec2 localUV, inout vec3 debugBVH = vec3(0)) -{ - vec4 elementColor = vec4(0); - - uvec4 currentOffset = elementOffset[elementIndex]; - uint elementBvhRoot = currentOffset.x; - uint elementBvhLength = currentOffset.y; - uint pointsOffset = currentOffset.z; - uint linesOffset = currentOffset.w; - - elementStack.top = 0; - uint elementBvhIndex = 0; - while (elementBvhIndex < elementBvhLength || !elementStack.empty()) - { - - while (elementBvhIndex < elementBvhLength) - { - vec4 bound = bvhBound[elementBvhRoot + elementBvhIndex]; - uint leftChild = bvhChildren[elementBvhRoot + elementBvhIndex].x; - - if (all(lessThan(bound.xy, localUV)) && all(lessThan(localUV, bound.zw))) - { - if (leftChild >= elementBvhLength) - { - debugBVH.g += 0.5; - - uint styleIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y - elementBvhLength; - // for(int i = 0; i<200;i++) - if (elementData[styleIndex] == 0.) //面 - { - - uint lineCount = elementIndexs[leftChild - elementBvhLength]; - uint num_its = 0; - - for (uint contourIterator = leftChild - elementBvhLength + 1; - contourIterator <= leftChild - elementBvhLength + lineCount; contourIterator++) - { - uint lineIndex = elementIndexs[contourIterator]; - uint p0Index = elementIndexs[linesOffset + 4 * lineIndex]; - uint p1Index = elementIndexs[linesOffset + 4 * lineIndex + 1]; - uint p2Index = elementIndexs[linesOffset + 4 * lineIndex + 2]; - uint p3Index = elementIndexs[linesOffset + 4 * lineIndex + 3]; - - vec2 p0 = vec2(elementData[pointsOffset + 2 * p0Index], - elementData[pointsOffset + 2 * p0Index + 1]); - vec2 p1 = vec2(elementData[pointsOffset + 2 * p1Index], - elementData[pointsOffset + 2 * p1Index + 1]); - vec2 p2 = vec2(elementData[pointsOffset + 2 * p2Index], - elementData[pointsOffset + 2 * p2Index + 1]); - vec2 p3 = vec2(elementData[pointsOffset + 2 * p3Index], - elementData[pointsOffset + 2 * p3Index + 1]); - - if (p0 == p1 && p2 == p3) - { - num_its += segment_int_test(localUV, p0, p3); - } - - else - num_its += cubic_bezier_int_test(localUV, p0, p1, p2, p3); - } - - if (num_its % 2 == 1) - { - elementColor = vec4(1); - //debugHit = true; - } - } - else if (elementData[styleIndex] == 1) //线 - { - } - - elementBvhIndex = elementBvhLength; - } - else - { - // debugBVH.b += 0.2; - elementStack.push(elementBvhIndex); - elementBvhIndex = leftChild; - } - } - else - elementBvhIndex = elementBvhLength; - } - if (!elementStack.empty()) - { - elementStack.getTop(elementBvhIndex); - elementStack.pop(); - elementBvhIndex = bvhChildren[elementBvhRoot + elementBvhIndex].y; - } - } - return elementColor.xyz; -} - - - +} \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp index f464c20..ab3c879 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.cpp @@ -3,8 +3,11 @@ #include #include #include +#ifndef STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION #include +#endif + void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc) { @@ -179,8 +182,8 @@ std::tuple Renderer::IblUtils::precomputeCubemap // ---------------------- unsigned int captureFBO; unsigned int captureRBO; - glFunc->glGenFramebuffers(1, &captureFBO); - glFunc->glGenRenderbuffers(1, &captureRBO); + glFunc->glCreateFramebuffers(1, &captureFBO); + glFunc->glCreateRenderbuffers(1, &captureRBO); glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); @@ -259,10 +262,12 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL glFunc->glActiveTexture(GL_TEXTURE0); glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture); + glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO); + glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize); glFunc->glViewport(0, 0, cubemapSize, cubemapSize); glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); - + for (unsigned int i = 0; i < 6; ++i) { shader.setUniformValue("view", captureViews[i]); @@ -282,8 +287,6 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) { - constexpr int irradianceMapSize = 32; - // pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale. // -------------------------------------------------------------------------------- unsigned int irradianceMap; @@ -334,10 +337,8 @@ GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFu GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array& captureViews, GLuint envCubemap) { - constexpr int prefilterMapSize = 128; - // pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale. - // -------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------- unsigned int prefilterMap; glFunc->glGenTextures(1, &prefilterMap); glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); @@ -399,7 +400,7 @@ GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc) constexpr int lutSize = 512; // pbr: generate a 2D LUT from the BRDF equations used. - // ---------------------------------------------------- + // ---------------------------------------------------- unsigned int brdfLUTTexture; glFunc->glGenTextures(1, &brdfLUTTexture); diff --git a/ArchitectureColoredPainting/src/Renderer/IblUtils.h b/ArchitectureColoredPainting/src/Renderer/IblUtils.h index 2305976..1f292fc 100644 --- a/ArchitectureColoredPainting/src/Renderer/IblUtils.h +++ b/ArchitectureColoredPainting/src/Renderer/IblUtils.h @@ -7,6 +7,8 @@ namespace Renderer { public: static constexpr int cubemapSize = 1024; + static constexpr int irradianceMapSize = 32; + static constexpr int prefilterMapSize = 128; static void renderCube(QOpenGLFunctions_4_5_Core* glFunc); static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc); /** diff --git a/ArchitectureColoredPainting/src/Renderer/Mesh.cpp b/ArchitectureColoredPainting/src/Renderer/Mesh.cpp index a9a0dee..d382834 100644 --- a/ArchitectureColoredPainting/src/Renderer/Mesh.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Mesh.cpp @@ -22,12 +22,9 @@ void Mesh::draw() { if (shaderProgram->bind()) { - glFunc->glActiveTexture(GL_TEXTURE0); - glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor); - glFunc->glActiveTexture(GL_TEXTURE1); - glFunc->glBindTexture(GL_TEXTURE_2D, textureMetallicRoughness); - glFunc->glActiveTexture(GL_TEXTURE2); - glFunc->glBindTexture(GL_TEXTURE_2D, textureNormal); + glFunc->glBindTextureUnit(0, textureBasecolor); + glFunc->glBindTextureUnit(1, textureMetallicRoughness); + glFunc->glBindTextureUnit(2, textureNormal); shaderProgram->setUniformValue("texture_basecolor", 0); shaderProgram->setUniformValue("texture_metallic_roughness", 1); shaderProgram->setUniformValue("texture_normal", 2); @@ -44,8 +41,7 @@ void Mesh::drawShadow() { if (shadowProgram->bind()) { - glFunc->glActiveTexture(GL_TEXTURE0); - glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor); + glFunc->glBindTextureUnit(0, textureBasecolor); shadowProgram->setUniformValue("texture_basecolor", 0); QOpenGLVertexArrayObject::Binder bind(&VAO); diff --git a/ArchitectureColoredPainting/src/Renderer/Mesh.h b/ArchitectureColoredPainting/src/Renderer/Mesh.h index 8033441..fa98a33 100644 --- a/ArchitectureColoredPainting/src/Renderer/Mesh.h +++ b/ArchitectureColoredPainting/src/Renderer/Mesh.h @@ -41,9 +41,9 @@ namespace Renderer QVector vertices; QVector indices; //QVector textures; - GLuint textureBasecolor; - GLuint textureMetallicRoughness; - GLuint textureNormal; + GLuint textureBasecolor = 0; + GLuint textureMetallicRoughness = 0; + GLuint textureNormal = 0; QMatrix4x4 model; QOpenGLFunctions_4_5_Compatibility* glFunc; diff --git a/ArchitectureColoredPainting/src/Renderer/Model.cpp b/ArchitectureColoredPainting/src/Renderer/Model.cpp index 5b833b4..ee419f2 100644 --- a/ArchitectureColoredPainting/src/Renderer/Model.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Model.cpp @@ -14,56 +14,34 @@ using namespace Renderer; using std::vector; -Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram) - : context(context) - , glFunc(context->versionFunctions()) - , shaderProgram(shaderProgram) - , directory(path) -{ - Assimp::Importer importer; - const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl; - return; - } - qDebug() << directory.absolutePath() << "Loaded Successfully"; - qDebug() << "NumMeshes: " << scene->mNumMeshes; - qDebug() << "NumMaterials: " << scene->mNumMaterials; - qDebug() << "NumTextures: " << scene->mNumTextures; - directory.cdUp(); - processNode(scene->mRootNode, scene); -} - -Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper) +Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, + QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, + PaintingHelper* paintingHelper, VirtualTextureManager* vtManager) : context(context) , glFunc(context->versionFunctions()) , shaderProgram(shaderProgram) , paintingProgram(paintingProgram) , shadowProgram(shadowProgram) , paintingHelper(paintingHelper) + , vtManager(vtManager) { - } Model::~Model() //销毁对象 { - for (auto& it : meshes) { - delete it; - } } void Model::draw() { //shaderProgram->bind(); - for (Drawable* mesh : meshes) { + for (auto& mesh : meshes) { mesh->draw(); } } void Model::drawShadow() { //shaderProgram->bind(); - for (Drawable* mesh : meshes) { + for (auto& mesh : meshes) { mesh->drawShadow(); } } @@ -74,11 +52,6 @@ void Model::destroy() delete this; } -Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram) -{ - return new Model(path, context, shaderProgram); -} - void Renderer::Model::loadModel(QString path) { directory = path; @@ -94,6 +67,12 @@ void Renderer::Model::loadModel(QString path) qDebug() << "NumMaterials: " << scene->mNumMaterials; qDebug() << "NumTextures: " << scene->mNumTextures; directory.cdUp(); + minX = std::numeric_limits::max(); + maxX = std::numeric_limits::min(); + minY = std::numeric_limits::max(); + maxY = std::numeric_limits::min(); + minZ = std::numeric_limits::max(); + maxZ = std::numeric_limits::min(); processNode(scene->mRootNode, scene); AABB.push_back(QVector3D(minX, minY, minZ)); AABB.push_back(QVector3D(minX, minY, maxZ)); @@ -111,8 +90,8 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4) // 处理节点所有的网格(如果有的话) for (unsigned int i = 0; i < node->mNumMeshes; i++) { - aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; - meshes.push_back(processMesh(mesh, scene, mat4)); + if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4)) + meshes.emplace_back(std::move(mesh)); } // 接下来对它的子节点重复这一过程 @@ -131,7 +110,7 @@ GLuint encodeZIndexAngle(GLuint zIndex, float angle) return GLuint(angle / 360 * 65536 + zIndex * 65536); } -Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) +std::unique_ptr Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; QMatrix4x4 modelQ((float*)&model); @@ -143,7 +122,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod { qDebug() << str.C_Str() << "Replaced"; // 初始化网格 - PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, modelQ); + auto m_mesh = std::make_unique(glFunc, paintingProgram, shadowProgram, modelQ); // 遍历网格的每个顶点 for (unsigned int i = 0; i < mesh->mNumVertices; i++) { @@ -169,14 +148,17 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod } } - m_mesh->paintingIndex = loadPainting(std::string(str.C_Str())); + m_mesh->paintingId = loadPainting(std::string(str.C_Str())); + auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId); + m_mesh->textureBasecolor = handle.baseColor; + m_mesh->textureMetallicRoughness = handle.metallicRoughness; m_mesh->setupMesh(); return m_mesh; } else { // 初始化网格 - Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, modelQ); + auto m_mesh = std::make_unique(glFunc, shaderProgram, shadowProgram, modelQ); // 遍历网格的每个顶点 for (unsigned int i = 0; i < mesh->mNumVertices; i++) { @@ -199,12 +181,21 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod m_mesh->indices.push_back(*indice); // 处理材质 - m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR); - m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS); - m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS); + if (!(m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR))) + qWarning() << "Basecolor Texture Loading Failed!"; + if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS))) + qWarning() << "MetallicRoughness Texture Loading Failed!"; + if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS))) + qWarning() << "Normal Texture Loading Failed!"; + + if (m_mesh->textureBasecolor && m_mesh->textureMetallicRoughness && m_mesh->textureNormal) + { + m_mesh->setupMesh(); + return m_mesh; + } + else + return nullptr; - m_mesh->setupMesh(); - return m_mesh; } } @@ -226,7 +217,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type) return 0; //qDebug() << "Loading" << path.c_str(); - auto [it, _] = texturesLoaded.emplace(std::piecewise_construct, std::make_tuple(path), std::make_tuple(QOpenGLTexture::Target2D)); + auto [it, _] = texturesLoaded.emplace(path, QOpenGLTexture::Target2D); auto& texture = it->second; texture.create(); texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); @@ -320,15 +311,17 @@ GLuint Renderer::Model::loadPainting(std::string path) std::make_shared(Element{ contour[2], style[0]}), }; Painting painting; - //for (int i = 0; i < 3; i++) - //{ - // float x = (float)rand() / RAND_MAX * 2 - 1; - // float y = (float)rand() / RAND_MAX * 2 - 1; - // float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x; - // float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y; - // //rootBvhTreeData.push_back(BvhTreeData(QVector4D(x, y, z, w), 0, encodeZIndexAngle(1, (float)rand() / RAND_MAX * 360))); - // painting.addElement(element[i%3], QVector4D(x, y, z, w), (float)rand() / RAND_MAX * 360, 1); - //} + for (int i = 0; i < 1000; i++) + { + float x = (float)rand() / RAND_MAX * 2 - 1; + float y = (float)rand() / RAND_MAX * 2 - 1; + float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x; + float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y; + //rootBvhTreeData.push_back(BvhTreeData(QVector4D(x, y, z, w), 0, encodeZIndexAngle(1, (float)rand() / RAND_MAX * 360))); + //painting.addElement(element[i%3], QVector4D(x, y, z, w), (float)rand() / RAND_MAX * 360, 1); + //painting.addElement(*element[i%3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.05), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 }); + + } painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.5,-0.45), glm::vec2(0.6,0.7), 45, glm::bvec2(true, false), 0 }); painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.5,0.5), 0, glm::bvec2(false), 0 }); painting.addElement(*element[2], ElementTransform{ glm::vec2(0.5,-0.45), glm::vec2(0.6,0.7), 0, glm::bvec2(false), 0 }); @@ -338,7 +331,7 @@ GLuint Renderer::Model::loadPainting(std::string path) //painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0); //painting.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0); - painting.generateBuffers(); + painting.generateBuffers(glFunc); ///////////////////////////////////////////////////////////////////////////////////////////////// std::vector bvhChildren0 = { //root @@ -474,7 +467,10 @@ GLuint Renderer::Model::loadPainting(std::string path) // elementOffset, elementIndex, elementData); /*GLuint index = paintingHelper->addPainting(bvhChildren0, bvhBounds0, elementOffset0, elementIndex0, elementData0);*/ - GLuint index = paintingHelper->addPainting(painting); - paintingLoaded.insert({ path, index }); + //GLuint index = paintingHelper->addPainting(painting); + //paintingLoaded.insert({ path, index }); + + auto index = vtManager->createVirtualTexture(painting); + paintingLoaded.emplace(path, index); return index; } diff --git a/ArchitectureColoredPainting/src/Renderer/Model.h b/ArchitectureColoredPainting/src/Renderer/Model.h index ffff1f4..3883a08 100644 --- a/ArchitectureColoredPainting/src/Renderer/Model.h +++ b/ArchitectureColoredPainting/src/Renderer/Model.h @@ -2,6 +2,7 @@ #include "Mesh.h" #include "Drawable.h" #include "Painting/PaintingHelper.h" +#include "VirtualTextureManager.h" #include #include @@ -15,39 +16,33 @@ namespace Renderer void draw(); void drawShadow(); void destroy(); - static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); void loadModel(QString path); - Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper); + Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper, VirtualTextureManager* vtManager); private: - Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram); - ~Model(); - QOpenGLContext* context; //opengl函数入口 - QOpenGLFunctions_4_5_Compatibility* glFunc; + QOpenGLContext* context; + QOpenGLFunctions_4_5_Compatibility* glFunc = nullptr; QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 QOpenGLShaderProgram* shadowProgram = nullptr; PaintingHelper* paintingHelper = nullptr; + VirtualTextureManager* vtManager = nullptr; /* 模型数据 */ std::unordered_map paintingLoaded; std::unordered_map texturesLoaded; - //std::vector textures_loaded; //纹理 - QVector meshes; //网格 - QDir directory; //模型所在路径 + std::vector> meshes; - float minX = std::numeric_limits::max(); - float maxX = std::numeric_limits::min(); - float minY = std::numeric_limits::max(); - float maxY = std::numeric_limits::min(); - float minZ = std::numeric_limits::max(); - float maxZ = std::numeric_limits::min(); + /// 模型所在路径 + QDir directory; + + float minX, maxX, minY, maxY, minZ, maxZ; //递归遍历结点 void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4()); //加载网格 - Drawable* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); + std::unique_ptr processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); //加载材质纹理 GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type); diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h index e478faf..d32f4dc 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.h @@ -1,6 +1,7 @@ #pragma once -#include +#include #include +#include #include #include diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Element.h b/ArchitectureColoredPainting/src/Renderer/Painting/Element.h index bb869ff..58a3b25 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Element.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Element.h @@ -1,6 +1,6 @@ #pragma once #include -#include +#include #include "Line.h" #include "ElementStyle.h" diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/ElementStyle.h b/ArchitectureColoredPainting/src/Renderer/Painting/ElementStyle.h index 8b81e85..8b1e3e1 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/ElementStyle.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/ElementStyle.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "BaseStyle.h" namespace Renderer diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.h b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.h index 120fa3d..e7008c5 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/MaterialStyleStroke.h @@ -1,5 +1,6 @@ #pragma once #include "BaseStyle.h" +#include namespace Renderer { diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Painting.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/Painting.cpp index e78a81a..18fc638 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Painting.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Painting.cpp @@ -105,13 +105,12 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e) return BvhTreeData(bound, elementPool[e.element], rightSon); } -void Painting::generateBuffers() +void Painting::generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc) { qDebug() << "Element Count: " << elementPool.size(); qDebug() << "Coutour Count: " << contourPool.size(); qDebug() << " Style Count: " << stylePool.size(); - bvhChildren.clear(); bvhBounds.clear(); elementOffset.clear(); @@ -161,6 +160,19 @@ void Painting::generateBuffers() elementOffset.push_back({ contourBuffer->bvhOffset, stylePool[i.first.style], contourBuffer->pointsOffset, contourBuffer->linesOffset }); //std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset); } + + glFunc->glCreateBuffers(5, buffers.data()); + GLuint& bvhSSBO = buffers[0]; + GLuint& bvhBoundSSBO = buffers[1]; + GLuint& elementOffsetSSBO = buffers[2]; + GLuint& elementIndexSSBO = buffers[3]; + GLuint& elementDataSSBO = buffers[4]; + + glFunc->glNamedBufferData(bvhSSBO, bvhChildren.size() * sizeof(GLuint), bvhChildren.data(), GL_STATIC_READ); + glFunc->glNamedBufferData(bvhBoundSSBO, bvhBounds.size() * sizeof(QVector4D), bvhBounds.data(), GL_STATIC_READ); + glFunc->glNamedBufferData(elementOffsetSSBO, elementOffset.size() * sizeof(glm::uvec4), elementOffset.data(), GL_STATIC_READ); + glFunc->glNamedBufferData(elementIndexSSBO, elementIndex.size() * sizeof(GLuint), elementIndex.data(), GL_STATIC_READ); + glFunc->glNamedBufferData(elementDataSSBO, elementData.size() * sizeof(GLfloat), elementData.data(), GL_STATIC_READ); } GLuint Renderer::Painting::getElementCount() diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Painting.h b/ArchitectureColoredPainting/src/Renderer/Painting/Painting.h index 496d879..fe29c1d 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Painting.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Painting.h @@ -1,12 +1,13 @@ #pragma once #include +#include #include -#include #include #include "Line.h" #include "BvhTree.h" #include "ElementStyle.h" #include "Element.h" +#include namespace Renderer { @@ -65,12 +66,13 @@ namespace Renderer std::vector elementIndex; std::vector elementData; int paintingId = 0; + std::array buffers; Painting(); void addElement(ElementWithTransform element); void addElement(const Element& element, const ElementTransform& transform); void addElement(std::shared_ptr element, QVector4D bound, float rotation, int zIndex); - void generateBuffers(); + void generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc); GLuint getElementCount(); private: std::unordered_map, std::pair/*面*/, std::shared_ptr/*线*/>> contourPool; diff --git a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp index 2bb7f4d..4449a96 100644 --- a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp +++ b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.cpp @@ -13,8 +13,14 @@ void PaintingMesh::draw() { if (shaderProgram->bind()) { + glFunc->glBindTextureUnit(0, textureBasecolor); + glFunc->glBindTextureUnit(1, textureMetallicRoughness); + shaderProgram->setUniformValue("texture_basecolor", 0); + shaderProgram->setUniformValue("texture_metallic_roughness", 1); + QOpenGLVertexArrayObject::Binder bind(&VAO); shaderProgram->setUniformValue("model", model); + glFunc->glUniform1ui(glFunc->glGetUniformLocation(shaderProgram->programId(), "paintingId"), paintingId); EBO.bind(); glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); shaderProgram->release(); @@ -24,6 +30,8 @@ void PaintingMesh::drawShadow() { if (shadowProgram->bind()) { + glFunc->glBindTextureUnit(0, textureBasecolor); + shadowProgram->setUniformValue("texture_basecolor", 0); QOpenGLVertexArrayObject::Binder bind(&VAO); shadowProgram->setUniformValue("model", model); EBO.bind(); diff --git a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h index 3d55d0a..8c22c21 100644 --- a/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h +++ b/ArchitectureColoredPainting/src/Renderer/PaintingMesh.h @@ -25,7 +25,7 @@ namespace Renderer QMatrix4x4 model; QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLShaderProgram* shaderProgram, * shadowProgram; - GLuint paintingIndex; + GLuint paintingId; PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model); void draw() override; diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp index bc4c71b..90f675e 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.cpp @@ -9,6 +9,8 @@ #include #include #include "IblUtils.h" +#include "VirtualTextureManager.h" +#include using namespace Renderer; @@ -24,8 +26,9 @@ RendererGLWidget::RendererGLWidget(QWidget* parent) //startTimer(); lastFrame = std::clock(); setFocusPolicy(Qt::StrongFocus); - QSurfaceFormat format; - format.setSwapInterval(0); + //QSurfaceFormat format; + //format.setProfile(QSurfaceFormat::CoreProfile); + ////format.setSwapInterval(0); //setFormat(format); } @@ -58,7 +61,10 @@ void RendererGLWidget::startTimer() { //startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate()); if (timerId == -1) + { timerId = QObject::startTimer(1); + + } } void RendererGLWidget::stopTimer() @@ -74,10 +80,10 @@ void RendererGLWidget::setModel() //model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); light.model = model; qDebug() << model->AABB; - paintingHelper->allocateBuffers(); - paintingCompProgramPtr->bind(); - paintingHelper->bindPaintingBuffers(); - paintingCompProgramPtr->release(); + //paintingHelper->allocateBuffers(); + //paintingCompProgramPtr->bind(); + //paintingHelper->bindPaintingBuffers(); + //paintingCompProgramPtr->release(); doneCurrent(); } @@ -100,16 +106,35 @@ void Renderer::RendererGLWidget::setExposure(float exposure) QOpenGLTexture randomMap(QOpenGLTexture::Target2D); +void GLAPIENTRY messageCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam) +{ + //fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", + // (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""), + // type, severity, message); + if (type == GL_DEBUG_TYPE_ERROR) + qCritical() << QString::fromStdString(std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}", + type, severity, message)); +} void RendererGLWidget::initializeGL() { gl = std::make_unique(); if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)QOpenGLContext::currentContext()->getProcAddress(name); })) - qDebug() << "Failed to initialize GLAD"; - + qCritical() << "Failed to initialize GLAD"; + QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions(); qDebug() << "GL_VERSION" << (char*)gl->GetString(GL_VERSION); + gl->Enable(GL_DEBUG_OUTPUT); + //gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + gl->DebugMessageCallback(messageCallback, 0); + gl->Enable(GL_DEPTH_TEST); gl->DepthFunc(GL_LEQUAL); gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); @@ -117,83 +142,83 @@ void RendererGLWidget::initializeGL() shadowProgramPtr = new QOpenGLShaderProgram; if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert")) - qDebug() << "ERROR:" << shadowProgramPtr->log(); + qCritical() << "ERROR:" << shadowProgramPtr->log(); if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Geometry, ":/Shaders/model_shadow.geom")) - qDebug() << "ERROR:" << shadowProgramPtr->log(); + qCritical() << "ERROR:" << shadowProgramPtr->log(); if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model_shadow.frag")) - qDebug() << "ERROR:" << shadowProgramPtr->log(); + qCritical() << "ERROR:" << shadowProgramPtr->log(); if (!shadowProgramPtr->link()) - qDebug() << "ERROR:" << shadowProgramPtr->log(); + qCritical() << "ERROR:" << shadowProgramPtr->log(); plainProgramPtr = new QOpenGLShaderProgram; if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert")) - qDebug() << "ERROR:" << plainProgramPtr->log(); + qCritical() << "ERROR:" << plainProgramPtr->log(); if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag")) - qDebug() << "ERROR:" << plainProgramPtr->log(); + qCritical() << "ERROR:" << plainProgramPtr->log(); if (!plainProgramPtr->link()) - qDebug() << "ERROR:" << plainProgramPtr->log(); + qCritical() << "ERROR:" << plainProgramPtr->log(); modelProgramPtr = new QOpenGLShaderProgram; if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) - qDebug() << "ERROR:" << modelProgramPtr->log(); + qCritical() << "ERROR:" << modelProgramPtr->log(); if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag")) - qDebug() << "ERROR:" << modelProgramPtr->log(); + qCritical() << "ERROR:" << modelProgramPtr->log(); if (!modelProgramPtr->link()) - qDebug() << "ERROR:" << modelProgramPtr->log(); + qCritical() << "ERROR:" << modelProgramPtr->log(); paintingProgramPtr = new QOpenGLShaderProgram; if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert")) - qDebug() << "ERROR:" << paintingProgramPtr->log(); + qCritical() << "ERROR:" << paintingProgramPtr->log(); if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag")) - qDebug() << "ERROR:" << paintingProgramPtr->log(); + qCritical() << "ERROR:" << paintingProgramPtr->log(); if (!paintingProgramPtr->link()) - qDebug() << "ERROR:" << paintingProgramPtr->log(); + qCritical() << "ERROR:" << paintingProgramPtr->log(); - paintingCompProgramPtr = new QOpenGLShaderProgram; - if (!paintingCompProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/painting.comp")) - qDebug() << "ERROR:" << paintingCompProgramPtr->log(); - if (!paintingCompProgramPtr->link()) - qDebug() << "ERROR:" << paintingCompProgramPtr->log(); + pageIdDownsampleProgramPtr = new QOpenGLShaderProgram; + if (!pageIdDownsampleProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/pageId_downsample.comp")) + qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log(); + if (!pageIdDownsampleProgramPtr->link()) + qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log(); depthInitProgramPtr = new QOpenGLShaderProgram; if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp")) - qDebug() << "ERROR:" << depthInitProgramPtr->log(); + qCritical() << "ERROR:" << depthInitProgramPtr->log(); if (!depthInitProgramPtr->link()) - qDebug() << "ERROR:" << depthInitProgramPtr->log(); + qCritical() << "ERROR:" << depthInitProgramPtr->log(); depthMipmapProgramPtr = new QOpenGLShaderProgram; if (!depthMipmapProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_mipmap.comp")) - qDebug() << "ERROR:" << depthMipmapProgramPtr->log(); + qCritical() << "ERROR:" << depthMipmapProgramPtr->log(); if (!depthMipmapProgramPtr->link()) - qDebug() << "ERROR:" << depthMipmapProgramPtr->log(); + qCritical() << "ERROR:" << depthMipmapProgramPtr->log(); shadowMappingProgramPtr = new QOpenGLShaderProgram; if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp")) - qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); + qCritical() << "ERROR:" << shadowMappingProgramPtr->log(); if (!shadowMappingProgramPtr->link()) - qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); + qCritical() << "ERROR:" << shadowMappingProgramPtr->log(); ssgiProgramPtr = new QOpenGLShaderProgram; if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp")) - qDebug() << "ERROR:" << ssgiProgramPtr->log(); + qCritical() << "ERROR:" << ssgiProgramPtr->log(); if (!ssgiProgramPtr->link()) - qDebug() << "ERROR:" << ssgiProgramPtr->log(); + qCritical() << "ERROR:" << ssgiProgramPtr->log(); finalProgramPtr = new QOpenGLShaderProgram; if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) - qDebug() << "ERROR:" << finalProgramPtr->log(); + qCritical() << "ERROR:" << finalProgramPtr->log(); if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag")) - qDebug() << "ERROR:" << finalProgramPtr->log(); + qCritical() << "ERROR:" << finalProgramPtr->log(); if (!finalProgramPtr->link()) - qDebug() << "ERROR:" << finalProgramPtr->log(); + qCritical() << "ERROR:" << finalProgramPtr->log(); skyBoxProgramPtr = new QOpenGLShaderProgram; if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert")) - qDebug() << "ERROR:" << skyBoxProgramPtr->log(); + qCritical() << "ERROR:" << skyBoxProgramPtr->log(); if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag")) - qDebug() << "ERROR:" << skyBoxProgramPtr->log(); + qCritical() << "ERROR:" << skyBoxProgramPtr->log(); if (!skyBoxProgramPtr->link()) - qDebug() << "ERROR:" << skyBoxProgramPtr->log(); + qCritical() << "ERROR:" << skyBoxProgramPtr->log(); shadowProgramPtr->bind(); gl->GenBuffers(1, &lightSpaceMatricesUBO); @@ -231,8 +256,10 @@ void RendererGLWidget::initializeGL() finalProgramPtr->setUniformValue("gBaseColor", 0); finalProgramPtr->release(); + vtManager = std::make_unique(gl.get()); + paintingHelper = new PaintingHelper(glFunc); - model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); + model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper, vtManager.get()); skyBoxProgramPtr->bind(); skyBoxProgramPtr->setUniformValue("environmentMap", 0); @@ -262,14 +289,30 @@ void RendererGLWidget::initializeGL() reinterpret_cast(3 * sizeof(GLfloat))); quadVBO.release(); - - + gl->GenQueries(1, &timeQuery); } void RendererGLWidget::paintGL() { QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions(); + pageIdDownsampleProgramPtr->bind(); + gl->BindImageTexture(3, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16UI); + gl->DispatchCompute(ceil(frameWidth / 8. / 8.), ceil(frameWidth / 8. / 8.), 1); + pageIdDownsampleProgramPtr->release(); + std::vector pixels; + pixels.resize(ceil(frameWidth / 8.) * ceil(frameHeight / 8.)); + fboPtr->bind(); + gl->ReadBuffer(GL_COLOR_ATTACHMENT4); + gl->ReadnPixels(0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); + //gl->GetTextureSubImage(gbuffers[4], 0, 0, 0, 0, ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1, GL_RG_INTEGER, GL_UNSIGNED_SHORT, pixels.size() * sizeof(glm::u16vec2), pixels.data()); + fboPtr->release(); + vtManager->tryUpdatePages(pixels); + + + gl->BeginQuery(GL_TIME_ELAPSED, timeQuery); + + gl->Enable(GL_CULL_FACE); light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); @@ -285,6 +328,7 @@ void RendererGLWidget::paintGL() } gl->BindBuffer(GL_UNIFORM_BUFFER, 0); + vtManager->commitMutex.lock(); { gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution); @@ -314,7 +358,7 @@ void RendererGLWidget::paintGL() paintingProgramPtr->release(); if (model != nullptr) model->draw(); - + plainProgramPtr->bind(); plainProgramPtr->setUniformValue("projection", projection); plainProgramPtr->setUniformValue("view", view); @@ -328,52 +372,37 @@ void RendererGLWidget::paintGL() for (int col = 0; col < nrColumns; ++col) { plainProgramPtr->setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); - + model.setToIdentity(); model.scale(10); model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing, - (float)(row - (nrRows / 2)) * spacing+20, + (float)(row - (nrRows / 2)) * spacing + 20, -2.0f)); plainProgramPtr->setUniformValue("model", model); IblUtils::renderSphere(glFunc); } } plainProgramPtr->release(); - fboPtr->release(); } + gl->Finish(); + vtManager->commitMutex.unlock(); - GLuint paintingCompQuery; - gl->GenQueries(1, &paintingCompQuery); - gl->BeginQuery(GL_TIME_ELAPSED, paintingCompQuery); + //depthInitProgramPtr->bind(); + //gl->ActiveTexture(GL_TEXTURE0); + //gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]); + //gl->BindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); + //gl->DispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1); + //depthInitProgramPtr->release(); - paintingCompProgramPtr->bind(); - gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); - gl->BindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); - gl->BindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI); - gl->BindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F); - - gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); - paintingCompProgramPtr->release(); - - gl->EndQuery(GL_TIME_ELAPSED); - - - depthInitProgramPtr->bind(); - gl->ActiveTexture(GL_TEXTURE0); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]); - gl->BindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - gl->DispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1); - depthInitProgramPtr->release(); - - depthMipmapProgramPtr->bind(); - for (int i = 0; i <= 3; i++) - gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1); - for (int i = 0; i <= 3; i++) - gl->BindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); - gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1); - depthMipmapProgramPtr->release(); + //depthMipmapProgramPtr->bind(); + //for (int i = 0; i <= 3; i++) + // gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); + //gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1); + //for (int i = 0; i <= 3; i++) + // gl->BindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F); + //gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1); + //depthMipmapProgramPtr->release(); shadowMappingProgramPtr->bind(); shadowMappingProgramPtr->setUniformValue("view", view); @@ -386,22 +415,15 @@ void RendererGLWidget::paintGL() shadowMappingProgramPtr->setUniformValue("camPos", camera.Position); shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); shadowMappingProgramPtr->setUniformValue("mainLightRadiance", mainLightRadiance); - /*gl->ActiveTexture(GL_TEXTURE0); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);*/ - gl->ActiveTexture(GL_TEXTURE1); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]); - gl->ActiveTexture(GL_TEXTURE2); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]); - gl->ActiveTexture(GL_TEXTURE3); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]); - gl->ActiveTexture(GL_TEXTURE4); - gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer); - gl->ActiveTexture(GL_TEXTURE5); - gl->BindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap); - gl->ActiveTexture(GL_TEXTURE6); - gl->BindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); - gl->ActiveTexture(GL_TEXTURE7); - gl->BindTexture(GL_TEXTURE_2D, brdfLUTTexture); + + gl->BindTextureUnit(1, gbuffers[1]); + gl->BindTextureUnit(2, gbuffers[2]); + gl->BindTextureUnit(3, gbuffers[3]); + gl->BindTextureUnit(4, shadowGbuffer); + gl->BindTextureUnit(5, irradianceMap); + gl->BindTextureUnit(6, prefilterMap); + gl->BindTextureUnit(7, brdfLUTTexture); + gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); gl->BindImageTexture(1, gbuffers[8], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F); gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); @@ -433,11 +455,9 @@ void RendererGLWidget::paintGL() gl->Viewport(0, 0, frameWidth, frameHeight); gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO); finalProgramPtr->bind(); finalProgramPtr->setUniformValue("exposure", exposure); - gl->ActiveTexture(GL_TEXTURE0); - gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]); + gl->BindTextureUnit(0, gbuffers[0]); quadVAO.bind(); gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); quadVAO.release(); @@ -446,30 +466,32 @@ void RendererGLWidget::paintGL() skyBoxProgramPtr->bind(); gl->Disable(GL_CULL_FACE); skyBoxProgramPtr->setUniformValue("view", view); - skyBoxProgramPtr->setUniformValue("projection", projection); + skyBoxProgramPtr->setUniformValue("projection", projection); skyBoxProgramPtr->setUniformValue("exposure", exposure); - gl->ActiveTexture(GL_TEXTURE0); - gl->BindTexture(GL_TEXTURE_CUBE_MAP, skyCubemap); + gl->BindTextureUnit(0, skyCubemap); IblUtils::renderCube(glFunc); skyBoxProgramPtr->release(); - GLuint paintingCompDuration; - gl->GetQueryObjectuiv(paintingCompQuery, GL_QUERY_RESULT, &paintingCompDuration); + gl->EndQuery(GL_TIME_ELAPSED); + GLuint frameDuration; + gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration); clock_t currentFrame = std::clock(); deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC; lastFrame = currentFrame; - static float accTime = 0, frameCnt = 0; + static float accTime = 0, frameCnt = 0, averageDuration = 0; accTime += deltaTime; frameCnt++; + averageDuration += frameDuration; if (accTime > 1.) { std::cout << std::format("{:20}\r", ""); - std::cout << std::format("FPS: {:.2f} Painting: {}ms Pos: {},{},{}\r", frameCnt / accTime, paintingCompDuration / 1e6, camera.Position.x(), camera.Position.y(), camera.Position.z()); - //std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r"; + std::cout << std::format("FPS: {:.2f}({:.2f}ms) Page: {:}ms Pos: {:.2f},{:.2f},{:.2f}\r", frameCnt / accTime, averageDuration / 1e6 / frameCnt, vtManager->pageLoadDuration / 1e6, camera.Position.x(), camera.Position.y(), camera.Position.z()); + vtManager->pageLoadDuration = 0; accTime = 0; frameCnt = 0; + averageDuration = 0; } if (pressedKeys.contains(Qt::Key_W)) { @@ -534,7 +556,7 @@ void RendererGLWidget::resizeGL(int width, int height) gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0); //gPaintingIndex gl->BindTexture(GL_TEXTURE_2D, gbuffers[4]); - gl->TexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, frameWidth, frameHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG16UI, frameWidth, frameHeight, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0); @@ -570,8 +592,8 @@ void RendererGLWidget::resizeGL(int width, int height) gl->TexImage2D(GL_TEXTURE_2D, i, GL_R32F, depthWidth / pow(2, i), depthHeight / pow(2, i), 0, GL_RED, GL_FLOAT, NULL); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); gl->TexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f })); diff --git a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h index 66ec814..f6e9195 100644 --- a/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h +++ b/ArchitectureColoredPainting/src/Renderer/RendererGLWidget.h @@ -15,6 +15,8 @@ struct GladGLContext; namespace Renderer { + class VirtualTextureManager; + class RendererGLWidget : public QOpenGLWidget { Q_OBJECT @@ -57,7 +59,7 @@ namespace Renderer QOpenGLShaderProgram* plainProgramPtr = nullptr; QOpenGLShaderProgram* modelProgramPtr = nullptr; QOpenGLShaderProgram* paintingProgramPtr = nullptr; - QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; + QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr; QOpenGLShaderProgram* depthInitProgramPtr = nullptr; QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr; QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr; @@ -77,5 +79,8 @@ namespace Renderer QOpenGLVertexArrayObject quadVAO; Model* model = nullptr; PaintingHelper* paintingHelper; + std::unique_ptr vtManager; + + GLuint timeQuery; }; } diff --git a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp index 4a1580d..0dc53c4 100644 --- a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp +++ b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.cpp @@ -1,7 +1,229 @@ -#include "VirtualTextureManager.h" #include +#include "VirtualTextureManager.h" +#include +#include +#include +#include +#define GLM_ENABLE_EXPERIMENTAL +#include -Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl) - :gl(gl) +std::mutex pageIdBufferMutex; + +Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain) + :glMain(glMain) { + auto mainContext = QOpenGLContext::currentContext(); + auto mainSurface = mainContext->surface(); + surface.setFormat(mainContext->format()); + surface.create(); + mainContext->doneCurrent(); + + thread = std::jthread([&] { + QOpenGLContext context; + context.setFormat(mainContext->format()); + context.setShareContext(mainContext); + context.create(); + context.makeCurrent(&surface); + + gl = std::make_unique(); + if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)QOpenGLContext::currentContext()->getProcAddress(name); })) + qCritical() << "Failed to initialize GLAD"; + + GLint numPageSizes; + + // Figure out how many page sizes are available for a 2D texture + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, sizeof(GLint), &numPageSizes); + std::vector pageSizesX(numPageSizes); + std::vector pageSizesY(numPageSizes); + std::vector pageSizesZ(numPageSizes); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_X_ARB, numPageSizes * sizeof(GLint), pageSizesX.data()); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_Y_ARB, numPageSizes * sizeof(GLint), pageSizesY.data()); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RGBA8, GL_VIRTUAL_PAGE_SIZE_Z_ARB, numPageSizes * sizeof(GLint), pageSizesZ.data()); + qDebug() << "RGBA8" << numPageSizes; + for (int i = 0; i < numPageSizes; i++) + qDebug() << pageSizesX[i] << pageSizesY[i] << pageSizesZ[i]; + + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RG8, GL_NUM_VIRTUAL_PAGE_SIZES_ARB, sizeof(GLint), &numPageSizes); + std::vector pageSizesRG8X(numPageSizes); + std::vector pageSizesRG8Y(numPageSizes); + std::vector pageSizesRG8Z(numPageSizes); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RG8, GL_VIRTUAL_PAGE_SIZE_X_ARB, numPageSizes * sizeof(GLint), pageSizesRG8X.data()); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RG8, GL_VIRTUAL_PAGE_SIZE_Y_ARB, numPageSizes * sizeof(GLint), pageSizesRG8Y.data()); + gl->GetInternalformativ(GL_TEXTURE_2D, GL_RG8, GL_VIRTUAL_PAGE_SIZE_Z_ARB, numPageSizes * sizeof(GLint), pageSizesRG8Z.data()); + qDebug() << "RG8" << numPageSizes; + for (int i = 0; i < numPageSizes; i++) + qDebug() << pageSizesRG8X[i] << pageSizesRG8Y[i] << pageSizesRG8Z[i]; + + pageSize = std::max(pageSizesRG8X[0], pageSizesRG8Y[0]); + qDebug() << "pageSize:" << pageSize; + + if (!program.addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/painting.comp")) + qDebug() << "ERROR:" << program.log(); + if (!program.link()) + qDebug() << "ERROR:" << program.log(); + + initialized = true; + + GLuint pageLoadTimeQuery; + gl->GenQueries(1, &pageLoadTimeQuery); + + while (true) + { + if (needUpdate) + { + needUpdate = false; + auto& pageIds = pageIdsBuffer[currentBuffer]; + pageIdBufferMutex.lock(); + currentBuffer = 1 - currentBuffer; + pageIdBufferMutex.unlock(); + + gl->BeginQuery(GL_TIME_ELAPSED, pageLoadTimeQuery); + updatePages(pageIds); + gl->EndQuery(GL_TIME_ELAPSED); + GLuint duration; + gl->GetQueryObjectuiv(pageLoadTimeQuery, GL_QUERY_RESULT, &duration); + //qDebug() << duration; + pageLoadDuration += duration; + } + } + }); + + while (!initialized) + std::this_thread::yield(); + + mainContext->makeCurrent(mainSurface); + +} + +std::uint16_t Renderer::VirtualTextureManager::createVirtualTexture(Painting painting) +{ + const GLsizei levels = glm::log2(textureSize / pageSize) + 1; + qDebug() << "levels:" << levels; + + GLuint textures[2]; + glMain->CreateTextures(GL_TEXTURE_2D, 2, textures); + GLuint& baseColor = textures[0]; + GLuint& metallicRoughness = textures[1]; + + glMain->TextureParameteri(baseColor, GL_TEXTURE_SPARSE_ARB, GL_TRUE); + glMain->TextureParameteri(baseColor, GL_TEXTURE_BASE_LEVEL, 0); + glMain->TextureParameteri(baseColor, GL_TEXTURE_MAX_LEVEL, levels - 1); + glMain->TextureParameteri(baseColor, GL_TEXTURE_WRAP_S, GL_REPEAT); + glMain->TextureParameteri(baseColor, GL_TEXTURE_WRAP_T, GL_REPEAT); + glMain->TextureParameteri(baseColor, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glMain->TextureParameteri(baseColor, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glMain->TextureStorage2D(baseColor, levels, GL_RGBA8, GLsizei(textureSize), GLsizei(textureSize)); + + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_SPARSE_ARB, GL_TRUE); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_BASE_LEVEL, 0); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAX_LEVEL, levels - 1); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_S, GL_REPEAT); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_T, GL_REPEAT); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glMain->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glMain->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize)); + + for (int i = 0; i < 5; i++) + glMain->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]); + + for (auto level = levels - 1; level < levels; ++level) + { + GLsizei levelSize = (textureSize >> level); + for (GLsizei j = 0; j < levelSize / pageSize; ++j) + for (GLsizei i = 0; i < levelSize / pageSize; ++i) + { + glMain->TexturePageCommitmentEXT(baseColor, static_cast(level), + static_cast(pageSize) * i, static_cast(pageSize) * j, 0, + static_cast(pageSize), static_cast(pageSize), 1, + GL_TRUE); + glMain->TexturePageCommitmentEXT(metallicRoughness, static_cast(level), + static_cast(pageSize) * i, static_cast(pageSize) * j, 0, + static_cast(pageSize), static_cast(pageSize), 1, + GL_TRUE); + + program.bind(); + glMain->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast(pageSize) * i, static_cast(pageSize) * j); + glMain->BindImageTexture(0, baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); + glMain->BindImageTexture(1, metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); + glMain->DispatchCompute(pageSize / 8, pageSize / 8, 1); + program.release(); + + } + } + paintings.emplace_back(baseColor, metallicRoughness, painting.buffers); + return paintings.size(); +} + +Renderer::PaintingHandle& Renderer::VirtualTextureManager::getPaintingHandle(std::uint16_t id) +{ + return paintings[id - 1]; +} + +void Renderer::VirtualTextureManager::tryUpdatePages(const std::vector& pageIds) +{ + pageIdBufferMutex.lock(); + pageIdsBuffer[currentBuffer] = pageIds; + pageIdBufferMutex.unlock(); + needUpdate = true; +} + +void Renderer::VirtualTextureManager::pageCommitmentById(const glm::u16vec2& pageId, GLboolean commit) +{ + auto& painting = getPaintingHandle(pageId.x >> 4); + GLint level = pageId.x & 0b1111; + glm::ivec2 page(pageId.y & 0b11111111, pageId.y >> 8); + //qDebug() << commit << level << page.x << page.y; + commitMutex.lock(); + + gl->TexturePageCommitmentEXT(painting.baseColor, level, + static_cast(pageSize) * page.x, static_cast(pageSize) * page.y, 0, + static_cast(pageSize), static_cast(pageSize), 1, + commit); + gl->TexturePageCommitmentEXT(painting.metallicRoughness, level, + static_cast(pageSize) * page.x, static_cast(pageSize) * page.y, 0, + static_cast(pageSize), static_cast(pageSize), 1, + commit); + + if (commit) + { + program.bind(); + for (int i = 0; i < 5; i++) + gl->BindBufferBase(GL_SHADER_STORAGE_BUFFER, i, painting.buffers[i]); + gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast(pageSize) * page.x, static_cast(pageSize) * page.y); + gl->BindImageTexture(0, painting.baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); + gl->BindImageTexture(1, painting.metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); + gl->DispatchCompute(pageSize / 8, pageSize / 8, 1); + program.release(); + } + gl->Finish(); + commitMutex.unlock(); +} + +void Renderer::VirtualTextureManager::updatePages(const std::vector& pageIds) +{ + for (auto iter = loadedPages.begin(); iter != loadedPages.end();) + { + iter->second--; + if (iter->second == 0) + { + pageCommitmentById(iter->first, GL_FALSE); + iter = loadedPages.erase(iter); + } + else + iter++; + } + for (auto& pageId : pageIds) + { + if (pageId.x) + { + auto [iter, success] = loadedPages.emplace(pageId, lifeTime); + if (success) + { + pageCommitmentById(pageId, GL_TRUE); + } + else + iter->second = lifeTime; + } + } + } diff --git a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.h b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.h index 81d4b31..e1d3a03 100644 --- a/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.h +++ b/ArchitectureColoredPainting/src/Renderer/VirtualTextureManager.h @@ -1,17 +1,65 @@ #pragma once - +#include "Painting/Painting.h" +#include +#include +#include +#include +#include +#include struct GladGLContext; namespace Renderer { + struct PaintingHandle + { + GLuint baseColor; + GLuint metallicRoughness; + std::array buffers; + }; + class VirtualTextureManager { public: - VirtualTextureManager(GladGLContext* gl); + VirtualTextureManager(GladGLContext* glMain); + /** + * @brief + * @param painting + * @return 虚拟纹理id + */ + std::uint16_t createVirtualTexture(Painting painting); + PaintingHandle& getPaintingHandle(std::uint16_t id); + void tryUpdatePages(const std::vector& pageIds); + + std::atomic initialized = false; + std::atomic needUpdate = false; + std::atomic pageLoadDuration = 0; + std::mutex commitMutex; private: - GladGLContext* gl; + std::jthread thread; + QOffscreenSurface surface; + std::unique_ptr gl; + GladGLContext* glMain; + static constexpr GLsizei textureSize = 16384; + static constexpr int lifeTime = 64; + GLint pageSize; + QOpenGLShaderProgram program; + std::vector paintings; + + struct u16vec2Hash + { + std::size_t operator()(glm::u16vec2 const& v) const + { + return ((std::size_t)v.y << 16) + v.x; + } + }; + std::unordered_map loadedPages; + std::vector pageIdsBuffer[2]; + int currentBuffer = 0; + + void updatePages(const std::vector& pageIds); + void pageCommitmentById(const glm::u16vec2& pageId, GLboolean commit); }; } diff --git a/ArchitectureColoredPainting/src/main.cpp b/ArchitectureColoredPainting/src/main.cpp index 0d8791b..6cd3b6b 100644 --- a/ArchitectureColoredPainting/src/main.cpp +++ b/ArchitectureColoredPainting/src/main.cpp @@ -27,12 +27,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); break; case QtCriticalMsg: - SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE); - break; - case QtFatalMsg: SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED); break; - + case QtFatalMsg: + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_RED); + break; } std::cout << std::format("{}({},{}) {}\n", QString(context.file).splitRef("\\").back().toLocal8Bit().data(), diff --git a/UnitTest/ElementRendererTest.cpp b/UnitTest/ElementRendererTest.cpp index 88aed8d..e6afb0c 100644 --- a/UnitTest/ElementRendererTest.cpp +++ b/UnitTest/ElementRendererTest.cpp @@ -3,7 +3,7 @@ #include #include "ElementRendererTest.h" #include "Renderer/Painting/ElementStyle.h" -#include + using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Renderer; @@ -15,8 +15,6 @@ namespace UnitTest public: TEST_METHOD(TestBothSidesRound) { - Logger::WriteMessage("In Class1"); - Assert::AreEqual(1 ,2); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);