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..95af788 100644 --- a/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters +++ b/ArchitectureColoredPainting/ArchitectureColoredPainting.vcxproj.filters @@ -201,9 +201,6 @@ Source Files\Renderer\Preview - - Source Files - Source Files @@ -216,6 +213,9 @@ Source Files + + Source Files\Editor + @@ -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/Editor/util/SvgFileLoader.cpp b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp index 30f0ae6..81d8966 100644 --- a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp +++ b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.cpp @@ -2,9 +2,12 @@ #include #include "../ThirdPartyLib/qquick/qquicksvgparser_p.h" #include +#include using std::map; +using std::vector; +using std::reverse; bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) { QFile file(filePath); @@ -46,12 +49,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa } } } - + qDebug() << painterPath; file.close(); return true; } -QMap SvgFileLoader::transformStyle(QString style) { +QMap SvgFileLoader::handleAttrStyle(QString style) { QMap resStyleMap; for (auto& attr : style.split(';')) { if (attr.isEmpty() || attr.trimmed() == "") continue; @@ -62,7 +65,7 @@ QMap SvgFileLoader::transformStyle(QString style) { return resStyleMap; } -QPolygonF SvgFileLoader::transformPoints(QString points) { +QPolygonF SvgFileLoader::handleAttrPoints(QString points) { QPolygonF resPointVector; QPointF point(0, 0); bool isX = true; @@ -80,10 +83,58 @@ QPolygonF SvgFileLoader::transformPoints(QString points) { return resPointVector; } +void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) { + QTransform trans; + QStringList ops = transformStyle.split(')'); + reverse(ops.begin(), ops.end()); + vector numbers; + for (auto op : ops) { + op = op.simplified(); + if (op.isEmpty()) continue; + QString type = (*op.split('(').begin()).trimmed(); + QString numStr = (*op.split('(').rbegin()).trimmed() + ','; + QString tmpNum = ""; + for (auto c : numStr) { + if (isdigit(c.toLatin1()) || c == '-' || c == '.') { + tmpNum += c; + } + else { + if (c == ',' && tmpNum.size() == 0) { + numbers.push_back(0); + } + else if (tmpNum.size() > 0) { + numbers.push_back(tmpNum.toDouble()); + } + tmpNum.clear(); + } + } + qDebug() << type << "///:" << numbers; + if (type == "translate") { + trans.translate(numbers[0], numbers[1]); + } + if (type == "scale") { + trans.scale(numbers[0], numbers[1]); + } + if (type == "rotate") { + trans.translate(numbers[1], numbers[2]); + trans.rotate(numbers[0]); + trans.translate(-numbers[1], -numbers[2]); + } + if (type == "skewX") { + trans.shear(numbers[0], 0); + } + if (type == "skewY") { + trans.shear(0, numbers[1]); + } + } + painterPath = trans.map(painterPath); + qDebug() << painterPath; +} + void SvgFileLoader::handleLabelG(QPainterPath& painterPath) { for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("style")) { - styleMap = transformStyle(attr.value().toLatin1()); + styleMap = handleAttrStyle(attr.value().toLatin1()); } else { styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1()); @@ -94,22 +145,33 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) { } void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("d")) { - QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), painterPath); + QQuickSvgParser::parsePathDataFast(attr.value().toLatin1(), elementPainterPath); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); + } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { QMap labelStyle; + QPainterPath elementPainterPath; + QString transformStyle = ""; double xBegin = 0, yBegin = 0, width = 0, height = 0;; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("x")) { @@ -122,17 +184,26 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { height = attr.value().toDouble(); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); + } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; - painterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height); + elementPainterPath.addRect(xBegin, yBegin, xBegin + width, yBegin + height); + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; double cx = 0, cy = 0, r = 0; for (auto& attr : xmlReader->attributes()) { @@ -144,18 +215,28 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) { r = attr.value().toDouble(); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); + } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + elementPainterPath.addEllipse(cx, cy, r, r); + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); //addEllipse(cx, cy, r, r, painterPath); - painterPath.addEllipse(cx, cy, r, r); + } void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; double cx = 0, cy = 0, rx = 0, ry = 0; for (auto& attr : xmlReader->attributes()) { @@ -168,7 +249,10 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { } else if (attr.name().toString() == QLatin1String("ry")) { rx = attr.value().toDouble(); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); + } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); @@ -176,49 +260,73 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { } qDebug() << labelStyle; //addEllipse(cx, cy, rx, ry, painterPath); - painterPath.addEllipse(cx, cy, rx, ry); + elementPainterPath.addEllipse(cx, cy, rx, ry); + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("points")) { - QPolygonF points = transformPoints(attr.value().toLatin1()); - painterPath.addPolygon(points); + QPolygonF points = handleAttrPoints(attr.value().toLatin1()); + elementPainterPath.addPolygon(points); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); + } + else if (attr.name().toString() == QLatin1String("transform")) { + transformStyle = attr.value().toLatin1(); } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) { + QPainterPath elementPainterPath; + QString transformStyle = ""; QMap labelStyle; for (auto& attr : xmlReader->attributes()) { if (attr.name().toString() == QLatin1String("points")) { - QPolygonF points = transformPoints(attr.value().toLatin1()); + QPolygonF points = handleAttrPoints(attr.value().toLatin1()); //points.push_back(*points.begin()); - painterPath.addPolygon(points); - painterPath.closeSubpath(); + elementPainterPath.addPolygon(points); + elementPainterPath.closeSubpath(); } else if (attr.name().toString() == QLatin1String("style")) { - labelStyle = transformStyle(attr.value().toLatin1()); + labelStyle = handleAttrStyle(attr.value().toLatin1()); + } + else if (attr.name().toString() == "transform") { + transformStyle = attr.value().toLatin1(); } else { labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); } } qDebug() << labelStyle; + if (!transformStyle.isEmpty()) { + handleAttrTransform(transformStyle, elementPainterPath); + } + painterPath.addPath(elementPainterPath); } +/* void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) { double k = w / 0.75; painterPath.moveTo(x, y - h); painterPath.cubicTo(QPointF(x + k, y - h), QPointF(x + k, y + h), QPointF(x, y + h)); painterPath.cubicTo(QPointF(x - k, y + h), QPointF(x - k, y - h), QPointF(x, y - h)); painterPath.closeSubpath(); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h index 352b9b0..3bdcd8a 100644 --- a/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h +++ b/ArchitectureColoredPainting/src/Editor/util/SvgFileLoader.h @@ -13,9 +13,10 @@ private: bool existFatherLabelG; QMap styleMap; std::shared_ptr xmlReader; - QPolygonF transformPoints(QString points); - QMap transformStyle(QString style); - void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); + QPolygonF handleAttrPoints(QString points); + QMap handleAttrStyle(QString style); + void handleAttrTransform(QString transformStyle, QPainterPath& painterPath); + //void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); void handleLabelG(QPainterPath& painterPath); void handleLabelPath(QPainterPath& painterPath); void handleLabelRect(QPainterPath& painterPath); 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..0304eca 100644 --- a/ArchitectureColoredPainting/src/Renderer/Model.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Model.cpp @@ -11,59 +11,38 @@ #include "Painting/ShortCutTree.h" #include "Painting/Painting.h" #include "../SvgParser.h" +#include 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 +53,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 +68,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 +91,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 +111,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); @@ -139,11 +119,11 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod aiString str; material->GetTexture(aiTextureType_BASE_COLOR, 0, &str); - if (paintingProgram != nullptr && std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0) + if (paintingProgram != nullptr && ( std::strcmp(str.C_Str(), "17876391417123941155.jpg") == 0 || std::strcmp(str.C_Str(), "11474523244911310074.jpg") == 0)) { 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 +149,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 +182,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 +218,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); @@ -242,72 +234,12 @@ GLuint Renderer::Model::loadPainting(std::string path) if (iter != paintingLoaded.end()) return iter->second; - //vector < vector > lineSet = { - // {{-0.5,0.9}, {0.1,0.3}}, - // {{0.1,0.3}, {0.0204656,0.379534}, {-0.2,0.0632573}, {-0.2,0.175736}}, - // {{-0.2,0.175736}, {-0.2,0.288215}, {-0.579534,0.220466}, {-0.5,0.3}}, - // {{-0.5,0.3}, {-0.420466,0.379534}, {-0.736743,0.6}, {-0.624264,0.6}}, - // {{-0.624264,0.6}, {-0.511785,0.6}, {-0.579534,0.979534}, {-0.5,0.9}} - //}; - - //Contour ctr = SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse(); - //ctr = Contour(ctr.begin()+1 , ctr.begin() + 4); - //qDebug() << "Contour---------------------"; - //for (auto& line : ctr) - //{ - // for (auto& p : line) - // p.show(); - // std::cout << std::endl; - //} - //qDebug() << "----------------------------"; - vector> contour = { std::make_shared(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()), - //std::make_shared(SvgParser("M292.82,107.78s0,0,0,0,0,3.59,0,7.62c0,3.85,0,5.78.06,6.43a19.94,19.94,0,0,0,2.87,7.58,15.85,15.85,0,0,0,6.61,6.23A14.75,14.75,0,0,0,310,137a11.69,11.69,0,0,0,7.59-2.92,11,11,0,0,0,3.2-6.84c.15-1.27.58-4.84-1.79-7.64a8.54,8.54,0,0,0-3.56-2.44c-1.32-.52-3.32-1.31-5.06-.33a5.41,5.41,0,0,0-2.14,3,3.48,3.48,0,0,0-.16,2.71c.78,1.86,3.36,2.14,3.47,2.15", 29.07, 30.28).parse()), std::make_shared(SvgParser("M308.49,212.25l23,28.38-82,78.31c-14.28,13.64-26.34-20.6-53.44,9.32l-30.24-13.4,63.56-51.59L190.71,215.6l-32.92,26.72L149.5,232.1l32.92-26.72L173.2,194l-32.91,26.72-7.38-9.08L165.83,185l-38.69-47.66L94.22,164,85,152.65l32.91-26.72-9.21-11.35L75.79,141.3l-5.53-6.81,32.92-26.72L94,96.42,61.05,123.14l-12-14.76L37.72,117.6l12,14.75L30.41,148,0,110.55,136.2,0l30.4,37.46L147.31,53.12l-12-14.76L124,47.58l12,14.75L103.05,89.05l9.21,11.35,32.92-26.72,5.52,6.81-32.91,26.72L127,118.56l32.92-26.72,9.21,11.35-32.91,26.72,38.69,47.67,32.91-26.72,7.37,9.08-32.91,26.72L191.49,198l32.92-26.72,8.29,10.22-32.92,26.71,38.7,47.68L302,204.3l6.45,7.95Z", 331.52, 328.26).parse()), std::make_shared(SvgParser("M377,459.61a11.26,11.26,0,0,1,11.27-11.27H696.12a11.27,11.27,0,0,0,11-8.62A359.84,359.84,0,0,0,708,280.56a11.26,11.26,0,0,0-11-8.73H388.27A11.26,11.26,0,0,1,377,260.57h0a11.26,11.26,0,0,1,11.27-11.26H683.71A11.32,11.32,0,0,0,694.28,234C649.8,113.69,542.57,23.85,412.3,4.12a11.22,11.22,0,0,0-12.76,11.17v158.9a11.26,11.26,0,0,0,11.26,11.27H583.12a11.32,11.32,0,0,0,9.26-17.75c-31.67-46.59-78.51-75.2-109.11-90.07a11.25,11.25,0,0,0-16.13,10.17V115.2a11.24,11.24,0,0,0,6.22,10.07l7.51,3.76a11.28,11.28,0,0,1,5,15.12h0a11.27,11.27,0,0,1-15.11,5l-20-10a11.27,11.27,0,0,1-6.22-10.07V54a11.27,11.27,0,0,1,14.62-10.75c5.11,1.59,125.66,40.35,172.24,149A11.27,11.27,0,0,1,621.11,208H388.27A11.26,11.26,0,0,1,377,196.73V11.36A11.32,11.32,0,0,0,365.89.08C363.34,0,360.79,0,358.22,0s-5.11,0-7.66.08a11.32,11.32,0,0,0-11.11,11.28V196.74A11.26,11.26,0,0,1,328.18,208H95.35A11.27,11.27,0,0,1,85,192.3c46.57-108.67,167.12-147.42,172.23-149A11.26,11.26,0,0,1,271.86,54v75.11a11.25,11.25,0,0,1-6.23,10.07l-20,10a11.27,11.27,0,0,1-15.11-5h0a11.26,11.26,0,0,1,5-15.11l7.52-3.76a11.27,11.27,0,0,0,6.22-10.07V87.82a11.25,11.25,0,0,0-16.14-10.16c-30.6,14.87-77.45,43.48-109.1,90.07a11.3,11.3,0,0,0,9.25,17.74H305.66a11.26,11.26,0,0,0,11.27-11.26V15.31A11.22,11.22,0,0,0,304.17,4.14C173.88,23.86,66.66,113.71,22.17,234a11.32,11.32,0,0,0,10.56,15.29H328.18a11.26,11.26,0,0,1,11.27,11.26v0a11.26,11.26,0,0,1-11.27,11.26H19.52a11.26,11.26,0,0,0-11,8.72,359.84,359.84,0,0,0,.83,159.16,11.26,11.26,0,0,0,11,8.61H328.18a11.26,11.26,0,0,1,11.27,11.27h0a11.26,11.26,0,0,1-11.27,11.26h-294a11.32,11.32,0,0,0-10.53,15.4C69,604.65,175.3,692.78,304.16,712.3a11.21,11.21,0,0,0,12.76-11.16V542.22A11.26,11.26,0,0,0,305.66,531h-166c-9.53,0-14.89,11.22-8.69,18.47,34.09,39.77,74.45,65.66,101.77,80.18a11.25,11.25,0,0,0,16.53-10V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,271.85,591v63.85A11.27,11.27,0,0,1,256.8,665.5c-4.45-1.59-109.58-40-171-139.9a11.27,11.27,0,0,1,9.59-17.17H328.18a11.26,11.26,0,0,1,11.27,11.26V705.08a11.32,11.32,0,0,0,11.11,11.28q3.82.07,7.66.08c2.57,0,5.12,0,7.67-.08A11.32,11.32,0,0,0,377,705.08V519.69a11.25,11.25,0,0,1,11.27-11.26H621.1a11.26,11.26,0,0,1,9.59,17.16c-61.46,99.87-166.59,138.3-171,139.9a11.27,11.27,0,0,1-15-10.61V591a11.26,11.26,0,0,1,11.26-11.26h0A11.26,11.26,0,0,1,467.14,591v28.6a11.25,11.25,0,0,0,16.53,10c27.33-14.53,67.68-40.42,101.77-80.19,6.2-7.23.85-18.46-8.69-18.46h-166a11.26,11.26,0,0,0-11.26,11.26V701.12a11.21,11.21,0,0,0,12.76,11.17c128.86-19.51,235.14-107.66,280.48-226a11.33,11.33,0,0,0-10.53-15.41h-294A11.25,11.25,0,0,1,377,459.61ZM35.27,399.53V316.9a11.26,11.26,0,0,1,11.27-11.26H669.92a11.25,11.25,0,0,1,11.26,11.26v82.63a11.25,11.25,0,0,1-11.26,11.26H46.54a11.27,11.27,0,0,1-11.27-11.26Z", 716.45, 716.44).parse()) }; - //vector> style = { - // std::make_shared(std::vector{ - // //strokeStyle - // //stroke - // 1, - // //strokeWidth - // 0.02, - // //strokeEndType - // 0, //圆角 - // //strokeFillType - // 0, //单色 - // //线类型 - // 0, //双侧 - // //线外描边宽度 - // 0, - // //线外描边方式 - // 0, //单色 - // //strokeFillColorMetallicRoughness - // 1,0,1, 0,0.8, - // }), - // std::make_shared(std::vector{ - // //fillStyle - // //fill - // 0, - // //fillType - // 0, //单色 - // //fillColorMetallicRoughness - // 240 / 255., 220 / 255., 160 / 255., 0.996, 0.18, - // }), - // std::make_shared(std::vector{ - // //fillStyle - // //fill - // 0, - // //fillType - // 0, //单色 - // //fillColorMetallicRoughness - // 24 / 255., 220 / 255., 16 / 255., 0., 0.18, - // }), - //}; - vector> style = { std::make_shared(), std::make_shared(0.02), @@ -320,161 +252,27 @@ 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); - //} - 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 }); + + if (path == "17876391417123941155.jpg") + { + 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 }); + } + else + { + for (int i = 0; i < 1000; i++) + { + float x = (float)rand() / RAND_MAX * 2 - 1; + float y = (float)rand() / RAND_MAX * 2 - 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], QVector4D(-0.8, -0.8, -0.2, -0.1), 0, 0); - //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(glFunc); - painting.generateBuffers(); - ///////////////////////////////////////////////////////////////////////////////////////////////// - std::vector bvhChildren0 = { - //root - 1,2, - 3,4, 5,6, - encodeChild(2),0, encodeChild(1),GLuint(30. / 360 * 65536 + 1 * 65536) /*右儿子用来表示旋转角度和zIndex*/, encodeChild(3),0, encodeChild(0),0, - //elememt0 - 1,2, - encodeChild(20)/*contour索引,由于contour不定长,这里需要给到contour在elementIndex中位置*/,0/*封闭图形*/, encodeChild(24), 0, - //elememt1 - encodeChild(12)/*contour索引*/, 1/*线*/ - - }; - std::vector bvhBounds0 = { - //root - QVector4D(-1,-1,1,1), - QVector4D(-0.9,-0.9,-0.1,0.9), QVector4D(0.1, -0.9,0.9,0.9), - QVector4D(-0.8,-0.8,-0.2,-0.1), QVector4D(-0.7,0.2,-0.2,0.7), QVector4D(0.2,-0.8,0.8,-0.1), QVector4D(0.3,0.2,0.7,0.7), - //elememt0 - QVector4D(-1,-1,1,1), - QVector4D(-1,-1,-0.2,1), QVector4D(-0.2,-1,1,1), - //elememt1 - QVector4D(-1,-1,1,1) - }; - - /** - * @[0] elementBvhRoot - * @[1] styleOffset - * @[2] pointsOffset - * @[3] linesOffset - */ - std::vector elementOffset0 = { - //element0 - glm::uvec4(7, 14, 0, 0), - //element1 - glm::uvec4(10, 39, 21, 28), - //element2 - glm::uvec4(10, 51, 21, 28), - //element3 - glm::uvec4(10, 63, 21, 28), - }; - - std::vector elementIndex0 = { - //element0 - //lines, 全部当作三阶贝塞尔, 每条线四个点索引 - 0,1,1,2, - 0,0,3,3, - 3,4,4,5, - 2,2,5,5, - 5,5,6,6, - //contours, 第一个元素为线数,后面为轮廓线索引 - 3, 1,2,4, - 3, 0,2,3, - //element1 - //lines - 0,7,8,1, - 1,1,4,4, - 5,5,6,6, - //contours - 3, 0,1,2 - }; - - std::vector elementData0 = { - //element0 - //points - -0.2,1, -0.2,-0.2, 1,-0.2, -1,1, -1,-1, 1,-1, 1,1, - //fillStyle - //fill - 0, - //fillType - 0, //单色 - //fillColorMetallicRoughness - 1,1,0, 0,0.8, - - //element1 - //points - 0.5,-0.5, 0.5,0.5, -0.2,0.5, -0.5,0.2, -0.5,-0.5, -0.8,-0.5, -0.8,0.5, 0.5,-0.4, 0.5,0.4, - //strokeStyle - //stroke - 1, - //strokeWidth - 0.1, - //strokeEndType - 0, //圆角 - //strokeFillType - 0, //单色 - //线类型 - 2, //左侧 - //线外描边宽度 - 0, - //线外描边方式 - 0, //单色 - //strokeFillColorMetallicRoughness - 1,0,1, 0,0.8, - //strokeStyle - //stroke - 1, - //strokeWidth - 0.1, - //strokeEndType - 0, //圆角 - //strokeFillType - 2, //单色 - //线类型 - 1, //左侧 - //线外描边宽度 - 0, - //线外描边方式 - 0, //单色 - //strokeFillColorMetallicRoughness - 1,0,1, 0,0.8, - //strokeStyle - //stroke - 1, - //strokeWidth - 0.1, - //strokeEndType - 0, //圆角 - //strokeFillType - 1, //单色 - //线类型 - 0, //左侧 - //线外描边宽度 - 0, - //线外描边方式 - 0, //单色 - //strokeFillColorMetallicRoughness - 1,0,1, 0,0.8, - }; - - - //m_mesh->paintingIndex = paintingHelper->addPainting(bounds.size(), std::vector(children.begin()+2, children.end()), bounds, - // elementOffset, elementIndex, elementData); - /*GLuint index = paintingHelper->addPainting(bvhChildren0, bvhBounds0, - elementOffset0, elementIndex0, elementData0);*/ - 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/CubicBezier.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp index 5c01eb8..442a6d2 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.cpp @@ -22,6 +22,12 @@ Point CubicBezier::calculateControlPoint(Point a, Point b) { }; } +double CubicBezier::ValueOfFunctionS(double t) { + double dxt = -3 * vX[0] * (1 - t) * (1 - t) + 3 * vX[1] * (1 - t) * (1 - 3 * t) + 3 * vX[2] * t * (2 - 3 * t) + 3 * vX[3] * t * t; + double dyt = -3 * vY[0] * (1 - t) * (1 - t) + 3 * vY[1] * (1 - t) * (1 - 3 * t) + 3 * vY[2] * t * (2 - 3 * t) + 3 * vY[3] * t * t; + return sqrt(dxt * dxt + dyt * dyt); +} + void CubicBezier::findPointsOfDivison(vector &p, vector& res) { double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]); if (fabs(a) > eps) { @@ -55,20 +61,26 @@ void CubicBezier::transformToCubic() { } void CubicBezier::splitBezierCubic(double t, vector& res) { - LinePtr Lf(new CubicBezier()); - float pt = 1 - t; Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) }; Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t); Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t); Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t); - Lf->push_back(getPointByIndex(0)); - Lf->push_back(pointF); - Lf->push_back(getPointByT(pointF, pointG, t)); - Lf->push_back(pointE); - res.push_back(Lf); + vector vP; vP.clear(); + vP.push_back(getPointByIndex(0)); + vP.push_back(pointF); + vP.push_back(getPointByT(pointF, pointG, t)); + vP.push_back(pointE); + LinePtr lf(new CubicBezier(vP)); + double totalLen = getIntegralByT(1), len = getIntegralByT(t); + if (totalLen <= eps) return; + double ratePoint = (1 - len / totalLen) * rate.first + len / totalLen * rate.second; + lf->setRate({ rate.first, ratePoint }); + res.push_back(lf); setPointByIndex(0, pointE); setPointByIndex(1, getPointByT(pointG, pointH, t)); setPointByIndex(2, pointH); + updateLeftType(); + setRate({ ratePoint, rate.second }); } void CubicBezier::monotonization(vector & res) { @@ -120,4 +132,4 @@ int CubicBezier::judgeOneSideIntersection(double xy, double l, double r, bool is double CubicBezier::getMinDistanceFromPoint(Point p) { return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd()); -} \ No newline at end of file +} diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h index 81f9d5d..e479f67 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/CubicBezier.h @@ -11,12 +11,14 @@ namespace Renderer static Point calculateControlPoint(Point a, Point b); static void findPointsOfDivison(std::vector& p, std::vector& res); void splitBezierCubic(double t, std::vector& res); + public: virtual double findTByValue(double value, bool isY); virtual void monotonization(std::vector & res); virtual double getLineValueByT(double t, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual double getMinDistanceFromPoint(Point p); + virtual double ValueOfFunctionS(double t); void transformToCubic(); }; } diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Element.h b/ArchitectureColoredPainting/src/Renderer/Painting/Element.h index bb869ff..3ff1d85 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Element.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Element.h @@ -1,6 +1,7 @@ #pragma once #include -#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/Line.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp index f26afd7..dbd6c0f 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.cpp @@ -1,4 +1,5 @@ #include "Line.h" +#include using namespace Renderer; using std::vector; using std::pair; @@ -14,14 +15,29 @@ Line::Line(vector Vp) { vX.push_back(now.x); vY.push_back(now.y); } + updateLeftType(); + rate = { 0, 1 }; +} + +bool Line::updateLeftType() { if (*vY.rbegin() < vY[0]) leftType = 0; else leftType = 1; + return true; } int Line::size() { return siz; } +bool Line::setRate(std::pair inRate) { + rate = inRate; + return true; +} + +uint Line::getRate() { + return glm::packUnorm2x16(glm::vec2(rate.first, rate.second)); +} + vector Line::toPointVector() const { vector vL; for (int i = 0; i < siz; i++) { @@ -151,4 +167,27 @@ bool Line::judgeIntersectionWithWidth(QVector4D bound, double width, int type) { || judgeOneSideIntersectionWithWidth(bound.w(), bound.x(), bound.z(), true, width, type) || judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type) || judgeOneSideIntersectionWithWidth(bound.z(), bound.y(), bound.w(), false, width, type); +} + +double Line::getIntegralByT(double t) { + double T[12][12], err = 1, S = 0, tmpPow4 = 1; + T[1][1] = t * (ValueOfFunctionS(t) + ValueOfFunctionS(0)) / 2; + int n = 1, k = 0; + while (err > eps) { + ++k; S = 0; + for (int i = 1; i <= n; i++) { + double x = t * (2 * i - 1) / 2; + S = S + ValueOfFunctionS(x); + } + tmpPow4 = 1; + T[k + 1][1] = (T[k][1] + t * S) / 2; + for (int m = 1; m <= k; m++) { + tmpPow4 *= 4; + T[k + 1][m + 1] = (tmpPow4 * T[k + 1][m] - T[k][m]) / (tmpPow4 - 1); + } + err = fabs(T[k + 1][k + 1] - T[k + 1][k]); + n <<= 1; t = t / 2; + if (k >= 8) break; + } + return T[k + 1][k + 1]; } \ No newline at end of file diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h index e9accc4..2198f8c 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/Line.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/Line.h @@ -49,21 +49,28 @@ namespace Renderer protected: std::vector vX, vY; int siz, leftType; + std::pair rate; public: typedef std::shared_ptr LinePtr; - Line() :siz(0) {} + Line() : siz(0), leftType(0), rate({0, 1}) {} Line(std::vector Vp); int size(); + bool setRate(std::pair inRate); + uint getRate(); void clear(); Point getBegin(); Point getEnd(); int direction(bool isY); + bool updateLeftType(); virtual double getLineValueByT(double t, bool isY) = 0; + // s = sqrt(x^2+y^2); + virtual double ValueOfFunctionS(double t) = 0; virtual void monotonization(std::vector & res) = 0; virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0; virtual double getMinDistanceFromPoint(Point p) = 0; bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type); virtual double findTByValue(double value, bool isY) = 0; + double getIntegralByT(double t); bool judgeIntersectionWithWidth(QVector4D bound, double width, int type); bool judgeIntersection(QVector4D bound); int getPointSideOfLine(Point p); diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp index 736b55e..2b4cd56 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/LineTree.cpp @@ -108,15 +108,30 @@ void LineTree::monotonization(vector& inLines, vectortoPointVector(); + canPut = false; + index = 0; for (Point& p : pointVector) { int pointIndex = getPointIndex(p); - lineIndexs.push_back(pointIndex); - if (pointVector.size() == 2) - lineIndexs.push_back(pointIndex); + if (pointVector.size() == 2) { + index = (pointIndex << 16) + pointIndex; + lineIndexs.push_back(index); + } + else { + index <<= 16; + index += pointIndex; + if (canPut) { + lineIndexs.push_back(index); + index = 0; + } + canPut = !canPut; + } } + lineIndexs.push_back(nowLine->getRate()); } } @@ -237,15 +252,15 @@ vector LineTree::getPointLineAndBvhTree(vector& resPoints, v for (auto& vectorIter : tmpPoints) { resPoints.push_back(vectorIter.second.x); resPoints.push_back(vectorIter.second.y); - vectorIter.second.show(); - std::cout << '\n'; + //vectorIter.second.show(); + //std::cout << '\n'; } // 线集 for (auto& nowLineIndex : lineIndexs) { resLines.push_back(nowLineIndex); - std::cout << nowLineIndex << ' '; + //std::cout << nowLineIndex << ' '; } - std::cout << '\n'; + //std::cout << '\n'; // 返回构造BvhTree数据 vector resBvhTreeData; for (auto& nowTreeNode : restOfTreeNodes) { @@ -253,13 +268,13 @@ vector LineTree::getPointLineAndBvhTree(vector& resPoints, v oneData.leftSon = resLines.size(); oneData.rightSon = 0; oneData.bound = nowTreeNode.bound; - std::cout << nowTreeNode.lineSet.size() << ' '; + //std::cout << nowTreeNode.lineSet.size() << ' '; resLines.push_back(nowTreeNode.lineSet.size()); for (auto& lineIndex : nowTreeNode.lineSet) { resLines.push_back(lineIndex); - std::cout << lineIndex << ' '; + //std::cout << lineIndex << ' '; } - std::cout << '\n'; + //std::cout << '\n'; resBvhTreeData.push_back(oneData); } return resBvhTreeData; 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..8821dc6 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,12 @@ 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; @@ -79,6 +80,8 @@ namespace Renderer std::unordered_map, GLuint> stylePool; std::map elementPool; std::vector elements; + + void addElement(ElementWithTransform element); void insertContourBuffer(std::shared_ptr buffer); BvhTreeData encodeElementLeaf(ElementWithTransform e); }; diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp index 7308c33..df50a92 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/ShortCutTree.cpp @@ -112,10 +112,8 @@ void ShortCutTree::generateShortCutSegment(ShortCutNode& nowTreeNode) { } for (auto& iter : pointSet) { nowTreeNode.lineSet.push_back(numLine); - lineIndexs.push_back(iter.first); - lineIndexs.push_back(iter.first); - lineIndexs.push_back(iter.second); - lineIndexs.push_back(iter.second); + lineIndexs.push_back((iter.first << 16) + iter.first); + lineIndexs.push_back((iter.second << 16) + iter.second); numLine++; } } @@ -149,14 +147,28 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod } void ShortCutTree::simplifyLineVector() { + bool canPut = false; + GLuint index = 0; numLine = allLines.size(); for (auto& nowLine : allLines) { PointVector pointVector = nowLine->toPointVector(); + canPut = false; + index = 0; for (Point& p : pointVector) { int pointIndex = getPointIndex(p); - lineIndexs.push_back(pointIndex); - if (pointVector.size() == 2) - lineIndexs.push_back(pointIndex); + if (pointVector.size() == 2) { + index = (pointIndex << 16) + pointIndex; + lineIndexs.push_back(index); + } + else { + index <<= 16; + index += pointIndex; + if (canPut) { + lineIndexs.push_back(index); + index = 0; + } + canPut = !canPut; + } } } for (auto& nowTreeNode : restOfTreeNodes) { diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp index 5351c22..101b5f8 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.cpp @@ -14,6 +14,10 @@ double StraightLine::getLineValueByT(double t, bool isY) { return t * (valueEnd - valueBegin) + valueBegin; } +double StraightLine::ValueOfFunctionS(double t) { + return sqrt((vX[1] - vX[0]) * (vX[1] - vX[0]) + (vY[1] - vY[0]) * (vY[1] - vY[0])); +} + double StraightLine::findTByValue(double value, bool isY) { Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1); if (!isY) { diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h index f2101d4..73625c0 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h +++ b/ArchitectureColoredPainting/src/Renderer/Painting/StraightLine.h @@ -11,5 +11,6 @@ namespace Renderer virtual double findTByValue(double value, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual double getMinDistanceFromPoint(Point p); + virtual double ValueOfFunctionS(double t); }; } \ No newline at end of file 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..b9f4a80 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,15 @@ 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(); + gl->BeginQuery(GL_TIME_ELAPSED, timeQuery); + gl->Enable(GL_CULL_FACE); light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); @@ -285,6 +313,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 +343,7 @@ void RendererGLWidget::paintGL() paintingProgramPtr->release(); if (model != nullptr) model->draw(); - + plainProgramPtr->bind(); plainProgramPtr->setUniformValue("projection", projection); plainProgramPtr->setUniformValue("view", view); @@ -328,11 +357,11 @@ 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); @@ -340,40 +369,40 @@ void RendererGLWidget::paintGL() } plainProgramPtr->release(); + pageIdDownsampleProgramPtr->bind(); + gl->BindImageTexture(3, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16UI); + gl->Uniform2ui(0, rand() % 8, rand() % 8); + 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); + 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: {:.2f}ms Pos: {:.2f},{:.2f},{:.2f}\r", frameCnt / accTime, averageDuration / 1e6 / frameCnt, vtManager->pageLoadDuration / 1e6 / frameCnt, 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 fcb086a..e6afb0c 100644 --- a/UnitTest/ElementRendererTest.cpp +++ b/UnitTest/ElementRendererTest.cpp @@ -4,6 +4,7 @@ #include "ElementRendererTest.h" #include "Renderer/Painting/ElementStyle.h" + using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Renderer; @@ -14,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); @@ -197,4 +196,5 @@ namespace UnitTest a.exec(); } }; + } diff --git a/UnitTest/UnitTest.cpp b/UnitTest/UnitTest.cpp index a03f793..d24ce02 100644 --- a/UnitTest/UnitTest.cpp +++ b/UnitTest/UnitTest.cpp @@ -3,12 +3,43 @@ #include #include #include +#include +#include "Renderer/Painting/CubicBezier.h" +#include using namespace Microsoft::VisualStudio::CppUnitTestFramework; namespace UnitTest { + void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) + { + switch (type) + { + case QtInfoMsg: + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY); + break; + case QtDebugMsg: + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + break; + case QtWarningMsg: + 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; + + } + Logger::WriteMessage(std::format("{}({},{}) {}\n", + QString(context.file).splitRef("\\").back().toLocal8Bit().data(), + context.line, + QString(context.function).splitRef("(").first().split(" ").back().split(":").back().toLocal8Bit().data(), + msg.toStdString()).c_str()); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + } TEST_CLASS(UnitTest) { public: @@ -31,4 +62,37 @@ namespace UnitTest a.exec(); } }; + + TEST_CLASS(SvgLoaderTest) + { + public: + TEST_METHOD(LoadSvg) + { + qInstallMessageHandler(messageHandler); + QPainterPath painterPath; + SvgFileLoader svgloader; + svgloader.loadSvgFile("D:\\BigC\\Project\\ArchitectureColoredPainting\\svg\\test.svg", painterPath); + } + }; + + TEST_CLASS(CubicBezierTest) + { + public: + TEST_METHOD(CubicIntegral) + { + qInstallMessageHandler(messageHandler); + std::shared_ptr line(new Renderer::CubicBezier()); + line->push_back({ -1, -1 }); + line->push_back({ -1, 1 }); + line->push_back({ 1, 1 }); + line->push_back({ 1, -1 }); + vector> outLines; + line->monotonization(outLines); + for (auto line : outLines) { + qDebug() << line->getRate(); + } + + } + }; + } diff --git a/svg/test.svg b/svg/test.svg new file mode 100644 index 0000000..1424018 --- /dev/null +++ b/svg/test.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file