Compare commits

...

6 Commits

Author SHA1 Message Date
wuyize 063be364c2 采样最接近的可用mipmap 2023-02-22 12:49:46 +08:00
wuyize 6a02f68514 Merge branch 'main' into dev-VirtualTexture 2023-02-21 20:15:19 +08:00
wuyize 57b537b66b 初步改用虚拟纹理 2023-02-21 20:13:07 +08:00
wuyize ff848b1443 qDebug等输出显示来源 2023-02-20 22:26:29 +08:00
wuyize f0ab4115c3 Merge branch 'dev-VirtualTexture' 2023-02-20 22:10:22 +08:00
karlis fef7668351 style dialog 2023-02-20 13:48:39 +08:00
21 changed files with 348 additions and 762 deletions

View File

@ -36,12 +36,22 @@ vec3 getNormalFromMap()
void main() 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) if(gBaseColor.a<0.4)
discard; discard;
gPosition = WorldPos; gPosition = WorldPos;
gNormal = getNormalFromMap(); if(textureSize(texture_normal,0)!=vec2(0))
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg; 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 = 0; gPaintingIndex = 0;
} }

View File

@ -2,29 +2,20 @@
layout (local_size_x = 8, local_size_y = 8) in; layout (local_size_x = 8, local_size_y = 8) in;
uniform ivec2 pixelOffset;
layout(rgba8, binding = 0) uniform image2D gBaseColor; layout(rgba8, binding = 0) uniform image2D gBaseColor;
layout(rg8, binding = 1) uniform image2D gMetallicRoughness; layout(rg8, binding = 1) uniform image2D gMetallicRoughness;
layout(r16ui, binding = 2) uniform uimage2D gPaintingIndex;
layout(rg32f, binding = 3) uniform image2D gPaintingTexCoord;
layout(std430, binding = 1) buffer paintingOffsetBuffer layout(std430, binding = 0) buffer bvhBuffer
{
/**********************
** @x paintingBvhRoot
** @y paintingBvhLength
**********************/
uvec2 paintingOffsets[];
};
layout(std430, binding = 2) buffer bvhBuffer
{ {
uvec2 bvhChildren[]; uvec2 bvhChildren[];
}; };
layout(std430, binding = 3) buffer bvhBoundBuffer layout(std430, binding = 1) buffer bvhBoundBuffer
{ {
vec4 bvhBound[]; vec4 bvhBound[];
}; };
layout(std430, binding = 4) buffer elementOffsetBuffer layout(std430, binding = 2) buffer elementOffsetBuffer
{ {
/********************** /**********************
** @[0] elementBvhRoot ** @[0] elementBvhRoot
@ -34,11 +25,11 @@ layout(std430, binding = 4) buffer elementOffsetBuffer
**********************/ **********************/
uvec4 elementOffset[]; uvec4 elementOffset[];
}; };
layout(std430, binding = 5) buffer elementIndexBuffer layout(std430, binding = 3) buffer elementIndexBuffer
{ {
uint elementIndexs[]; //ÏߺÍÃæ uint elementIndexs[]; //ÏߺÍÃæ
}; };
layout(std430, binding = 6) buffer elementDataBuffer layout(std430, binding = 4) buffer elementDataBuffer
{ {
float elementData[]; //µãºÍStyle float elementData[]; //µãºÍStyle
}; };
@ -1182,13 +1173,13 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
void main() void main()
{ {
//ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy); ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy); vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor);
uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r; //imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
if(paintingIndex==0) //imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
return; //return;
uv = vec2(1)-uv*2;
vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg; //vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
vec3 debugBVH = vec3(0); vec3 debugBVH = vec3(0);
//bool debugHit = false; //bool debugHit = false;

View File

@ -1,4 +1,8 @@
#version 450 core #version 450 core
#extension GL_ARB_sparse_texture2 : enable
uniform sampler2D texture_basecolor;
uniform sampler2D texture_metallic_roughness;
layout(location = 0) out vec4 gBaseColor; layout(location = 0) out vec4 gBaseColor;
layout(location = 1) out vec3 gNormal; layout(location = 1) out vec3 gNormal;
@ -13,635 +17,25 @@ in vec3 Normal;
void main() void main()
{ {
float lod = textureQueryLod(texture_basecolor, TexCoords).x;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod<textureQueryLevels(texture_basecolor))
lod++;
gBaseColor = vec4( vec3(1),1 ); if(gBaseColor.a<0.4)
discard;
//gBaseColor = vec4( vec3(1),1 );
// mainImage(gBaseColor, vec2(1.,1.)-TexCoords); // mainImage(gBaseColor, vec2(1.,1.)-TexCoords);
gPosition = WorldPos; gPosition = WorldPos;
gNormal = normalize(Normal); gNormal = normalize(Normal);
// gMetallicRoughness = vec2(1, 46./255); //gMetallicRoughness = vec2(0,1);
gMetallicRoughness = vec2(0); lod = textureQueryLod(texture_metallic_roughness, TexCoords).x;
gPaintingIndex = 1; vec4 mt;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_metallic_roughness, TexCoords, lod, mt))&&lod<textureQueryLevels(texture_metallic_roughness))
lod++;
gMetallicRoughness = mt.rg;
//gPaintingIndex = 1;
gPaintingIndex = 0;
gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2; gPaintingTexCoord = vec2(1., 1.) - TexCoords * 2;
return; return;
} }
layout(std430, binding = 1) buffer bvhBuffer
{
uint bvhLength;
uvec2 bvhChildren[];
};
layout(std430, binding = 2) buffer bvhBoundBuffer
{
vec4 bvhBound[];
};
layout(std430, binding = 3) buffer elementOffsetBuffer
{
/**********************
** @x elementBvhRoot
** @y elementBvhLength
** @z pointsOffset
** @w linesOffset
**********************/
uvec4 elementOffset[];
};
layout(std430, binding = 4) buffer elementIndexBuffer
{
uint elementIndexs[]; //ÏߺÍÃæ
};
layout(std430, binding = 5) buffer elementDataBuffer
{
float elementData[]; //µãºÍStyle
};
const float PI = 3.14159265358979;
////////////////////////////////////////////////////////////////////////////
float border = 0;
mat2 inv(mat2 m)
{
return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / (m[0][0] * m[1][1] - m[1][0] * m[0][1]);
}
float abs_min(float a, float b)
{
if (abs(a) < abs(b))
{
return a;
}
else
{
return b;
}
}
int i_mod(int a, int m)
{
return int(mod(float(a), float(m)));
}
float line_dist(vec2 uv, const vec2 p0, vec2 p1)
{
vec2 tang = p1 - p0;
vec2 nor = normalize(vec2(tang.y, -tang.x));
if (dot(tang, uv) < dot(tang, p0))
{
return distance(p0, uv);
}
else if (dot(tang, uv) > 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;
}

View File

@ -3,6 +3,8 @@
#include <QTextBlock> #include <QTextBlock>
#include <QListWidget> #include <QListWidget>
#include <QPushButton> #include <QPushButton>
#include <QDialog>
#include <QDialogButtonBox>
void InfoDisplayWidget::setLayer(LayerWrapper *layer) void InfoDisplayWidget::setLayer(LayerWrapper *layer)
{ {
@ -88,19 +90,35 @@ void InfoDisplayWidget::generateLayerForm()
QWidget* w = new QWidget; QWidget* w = new QWidget;
item->setSizeHint(QSize(50, 40)); item->setSizeHint(QSize(50, 40));
QHBoxLayout* layout = new QHBoxLayout; QHBoxLayout* layout = new QHBoxLayout;
QPushButton* pushButton = new QPushButton(w); QPushButton* deleteButton = new QPushButton(w);
QPushButton* detailButton = new QPushButton(w);
QLabel* name = new QLabel(w); QLabel* name = new QLabel(w);
name->setText(styleNames[index]); name->setText(styleNames[index]);
pushButton->setText("×"); detailButton->setText("...");
pushButton->setFixedSize(QSize(20, 20)); detailButton->setFixedSize(QSize(20, 20));
connect(pushButton, &QPushButton::clicked, [styleList,item,this]() { deleteButton->setText("×");
deleteButton->setFixedSize(QSize(20, 20));
connect(detailButton, &QPushButton::clicked, [styleList, item, this]() {
QDialog dlg(this);
dlg.setWindowTitle("样式详情");
dlg.resize(400, 200);
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel, &dlg);
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
bool updateStyle = dlg.exec();
if (updateStyle) {
// 在此处修改新样式信息至内存
}
});
connect(deleteButton, &QPushButton::clicked, [styleList,item,this]() {
styleList->removeItemWidget(item); styleList->removeItemWidget(item);
delete item; delete item;
// delete data in layer // 删除layer对应样式
emit requireRefreshPreview(); emit requireRefreshPreview();
}); });
layout->addWidget(name); layout->addWidget(name);
layout->addWidget(pushButton); layout->addWidget(detailButton);
layout->addWidget(deleteButton);
w->setLayout(layout); w->setLayout(layout);
styleList->addItem(item); styleList->addItem(item);
styleList->setItemWidget(item, w); styleList->setItemWidget(item, w);

View File

@ -3,8 +3,11 @@
#include <QDebug> #include <QDebug>
#include <array> #include <array>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#ifndef STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h> #include <stb_image.h>
#endif
void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc) void Renderer::IblUtils::renderCube(QOpenGLFunctions_4_5_Core* glFunc)
{ {
@ -262,7 +265,7 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL
glFunc->glViewport(0, 0, cubemapSize, cubemapSize); glFunc->glViewport(0, 0, cubemapSize, cubemapSize);
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
for (unsigned int i = 0; i < 6; ++i) for (unsigned int i = 0; i < 6; ++i)
{ {
shader.setUniformValue("view", captureViews[i]); shader.setUniformValue("view", captureViews[i]);
@ -337,7 +340,7 @@ GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFun
constexpr int prefilterMapSize = 128; constexpr int prefilterMapSize = 128;
// pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale. // pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale.
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
unsigned int prefilterMap; unsigned int prefilterMap;
glFunc->glGenTextures(1, &prefilterMap); glFunc->glGenTextures(1, &prefilterMap);
glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap); glFunc->glBindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap);
@ -399,7 +402,7 @@ GLuint Renderer::IblUtils::gererateBrdfLut(QOpenGLFunctions_4_5_Core* glFunc)
constexpr int lutSize = 512; constexpr int lutSize = 512;
// pbr: generate a 2D LUT from the BRDF equations used. // pbr: generate a 2D LUT from the BRDF equations used.
// ---------------------------------------------------- // ----------------------------------------------------
unsigned int brdfLUTTexture; unsigned int brdfLUTTexture;
glFunc->glGenTextures(1, &brdfLUTTexture); glFunc->glGenTextures(1, &brdfLUTTexture);

View File

@ -41,9 +41,9 @@ namespace Renderer
QVector<Vertex> vertices; QVector<Vertex> vertices;
QVector<unsigned int> indices; QVector<unsigned int> indices;
//QVector<Texture*> textures; //QVector<Texture*> textures;
GLuint textureBasecolor; GLuint textureBasecolor = 0;
GLuint textureMetallicRoughness; GLuint textureMetallicRoughness = 0;
GLuint textureNormal; GLuint textureNormal = 0;
QMatrix4x4 model; QMatrix4x4 model;
QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLFunctions_4_5_Compatibility* glFunc;

View File

@ -14,56 +14,34 @@
using namespace Renderer; using namespace Renderer;
using std::vector; using std::vector;
Model::Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
: context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram)
, directory(path)
{
Assimp::Importer importer; Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs); QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram,
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) PaintingHelper* paintingHelper, VirtualTextureManager* vtManager)
{
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)
: context(context) : context(context)
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>()) , glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
, shaderProgram(shaderProgram) , shaderProgram(shaderProgram)
, paintingProgram(paintingProgram) , paintingProgram(paintingProgram)
, shadowProgram(shadowProgram) , shadowProgram(shadowProgram)
, paintingHelper(paintingHelper) , paintingHelper(paintingHelper)
, vtManager(vtManager)
{ {
} }
Model::~Model() //销毁对象 Model::~Model() //销毁对象
{ {
for (auto& it : meshes) {
delete it;
}
} }
void Model::draw() { void Model::draw() {
//shaderProgram->bind(); //shaderProgram->bind();
for (Drawable* mesh : meshes) { for (auto& mesh : meshes) {
mesh->draw(); mesh->draw();
} }
} }
void Model::drawShadow() { void Model::drawShadow() {
//shaderProgram->bind(); //shaderProgram->bind();
for (Drawable* mesh : meshes) { for (auto& mesh : meshes) {
mesh->drawShadow(); mesh->drawShadow();
} }
} }
@ -74,11 +52,6 @@ void Model::destroy()
delete this; delete this;
} }
Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
{
return new Model(path, context, shaderProgram);
}
void Renderer::Model::loadModel(QString path) void Renderer::Model::loadModel(QString path)
{ {
directory = path; directory = path;
@ -94,6 +67,12 @@ void Renderer::Model::loadModel(QString path)
qDebug() << "NumMaterials: " << scene->mNumMaterials; qDebug() << "NumMaterials: " << scene->mNumMaterials;
qDebug() << "NumTextures: " << scene->mNumTextures; qDebug() << "NumTextures: " << scene->mNumTextures;
directory.cdUp(); directory.cdUp();
minX = std::numeric_limits<float>::max();
maxX = std::numeric_limits<float>::min();
minY = std::numeric_limits<float>::max();
maxY = std::numeric_limits<float>::min();
minZ = std::numeric_limits<float>::max();
maxZ = std::numeric_limits<float>::min();
processNode(scene->mRootNode, scene); processNode(scene->mRootNode, scene);
AABB.push_back(QVector3D(minX, minY, minZ)); AABB.push_back(QVector3D(minX, minY, minZ));
AABB.push_back(QVector3D(minX, minY, maxZ)); AABB.push_back(QVector3D(minX, minY, maxZ));
@ -111,8 +90,8 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
// 处理节点所有的网格(如果有的话) // 处理节点所有的网格(如果有的话)
for (unsigned int i = 0; i < node->mNumMeshes; i++) for (unsigned int i = 0; i < node->mNumMeshes; i++)
{ {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4))
meshes.push_back(processMesh(mesh, scene, mat4)); meshes.emplace_back(std::move(mesh));
} }
// 接下来对它的子节点重复这一过程 // 接下来对它的子节点重复这一过程
@ -131,7 +110,7 @@ GLuint encodeZIndexAngle(GLuint zIndex, float angle)
return GLuint(angle / 360 * 65536 + zIndex * 65536); return GLuint(angle / 360 * 65536 + zIndex * 65536);
} }
Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model) std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
{ {
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
QMatrix4x4 modelQ((float*)&model); QMatrix4x4 modelQ((float*)&model);
@ -143,7 +122,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
{ {
qDebug() << str.C_Str() << "Replaced"; qDebug() << str.C_Str() << "Replaced";
// 初始化网格 // 初始化网格
PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, modelQ); auto m_mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
// 遍历网格的每个顶点 // 遍历网格的每个顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++) for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{ {
@ -170,13 +149,16 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
} }
m_mesh->paintingIndex = loadPainting(std::string(str.C_Str())); m_mesh->paintingIndex = loadPainting(std::string(str.C_Str()));
auto& handle = vtManager->paintings[m_mesh->paintingIndex];
m_mesh->textureBasecolor = handle.baseColor;
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
m_mesh->setupMesh(); m_mesh->setupMesh();
return m_mesh; return m_mesh;
} }
else else
{ {
// 初始化网格 // 初始化网格
Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, modelQ); auto m_mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
// 遍历网格的每个顶点 // 遍历网格的每个顶点
for (unsigned int i = 0; i < mesh->mNumVertices; i++) for (unsigned int i = 0; i < mesh->mNumVertices; i++)
{ {
@ -199,12 +181,21 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
m_mesh->indices.push_back(*indice); m_mesh->indices.push_back(*indice);
// 处理材质 // 处理材质
m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR); if (!(m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS); qWarning() << "Basecolor Texture Loading Failed!";
m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS); if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS)))
qWarning() << "MetallicRoughness Texture Loading Failed!";
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
qWarning() << "Normal Texture Loading Failed!";
if (m_mesh->textureBasecolor && m_mesh->textureMetallicRoughness && m_mesh->textureNormal)
{
m_mesh->setupMesh();
return m_mesh;
}
else
return nullptr;
m_mesh->setupMesh();
return m_mesh;
} }
} }
@ -226,7 +217,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
return 0; return 0;
//qDebug() << "Loading" << path.c_str(); //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; auto& texture = it->second;
texture.create(); texture.create();
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
@ -338,7 +329,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
//painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0); //painting.addElement(element[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.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0);
painting.generateBuffers(); painting.generateBuffers(glFunc);
///////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<GLuint> bvhChildren0 = { std::vector<GLuint> bvhChildren0 = {
//root //root
@ -474,7 +465,10 @@ GLuint Renderer::Model::loadPainting(std::string path)
// elementOffset, elementIndex, elementData); // elementOffset, elementIndex, elementData);
/*GLuint index = paintingHelper->addPainting(bvhChildren0, bvhBounds0, /*GLuint index = paintingHelper->addPainting(bvhChildren0, bvhBounds0,
elementOffset0, elementIndex0, elementData0);*/ elementOffset0, elementIndex0, elementData0);*/
GLuint index = paintingHelper->addPainting(painting); //GLuint index = paintingHelper->addPainting(painting);
paintingLoaded.insert({ path, index }); //paintingLoaded.insert({ path, index });
auto index = vtManager->createVirtualTexture(painting);
paintingLoaded.emplace(path, index);
return index; return index;
} }

View File

@ -2,6 +2,7 @@
#include "Mesh.h" #include "Mesh.h"
#include "Drawable.h" #include "Drawable.h"
#include "Painting/PaintingHelper.h" #include "Painting/PaintingHelper.h"
#include "VirtualTextureManager.h"
#include <QDir> #include <QDir>
#include <assimp/scene.h> #include <assimp/scene.h>
@ -15,39 +16,33 @@ namespace Renderer
void draw(); void draw();
void drawShadow(); void drawShadow();
void destroy(); void destroy();
static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
void loadModel(QString path); 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: private:
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
~Model(); ~Model();
QOpenGLContext* context; //opengl函数入口 QOpenGLContext* context;
QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLFunctions_4_5_Compatibility* glFunc = nullptr;
QOpenGLShaderProgram* shaderProgram = nullptr; QOpenGLShaderProgram* shaderProgram = nullptr;
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序 QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
QOpenGLShaderProgram* shadowProgram = nullptr; QOpenGLShaderProgram* shadowProgram = nullptr;
PaintingHelper* paintingHelper = nullptr; PaintingHelper* paintingHelper = nullptr;
VirtualTextureManager* vtManager = nullptr;
/* 模型数据 */ /* 模型数据 */
std::unordered_map<std::string, GLuint> paintingLoaded; std::unordered_map<std::string, GLuint> paintingLoaded;
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded; std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
//std::vector<Texture*> textures_loaded; //纹理 std::vector<std::unique_ptr<Drawable>> meshes;
QVector<Drawable*> meshes; //网格
QDir directory; //模型所在路径
float minX = std::numeric_limits<float>::max(); /// Ä£ÐÍËùÔÚ·¾¶
float maxX = std::numeric_limits<float>::min(); QDir directory;
float minY = std::numeric_limits<float>::max();
float maxY = std::numeric_limits<float>::min(); float minX, maxX, minY, maxY, minZ, maxZ;
float minZ = std::numeric_limits<float>::max();
float maxZ = std::numeric_limits<float>::min();
//递归遍历结点 //递归遍历结点
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4()); void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
//加载网格 //加载网格
Drawable* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model); std::unique_ptr<Drawable> processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
//加载材质纹理 //加载材质纹理
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type); GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <QOpenGLFunctions_4_5_Compatibility> #include <qopengl.h>
#include <vector> #include <vector>
#include <memory>
#include <QColor> #include <QColor>
#include <glm/glm.hpp> #include <glm/glm.hpp>

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <QOpenGLFunctions_4_5_Compatibility> #include <qopengl.h>
#include "Line.h" #include "Line.h"
#include "ElementStyle.h" #include "ElementStyle.h"

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <QOpenGLFunctions_4_5_Compatibility>
#include "BaseStyle.h" #include "BaseStyle.h"
namespace Renderer namespace Renderer

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "BaseStyle.h" #include "BaseStyle.h"
#include <map>
namespace Renderer namespace Renderer
{ {

View File

@ -105,13 +105,12 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
return BvhTreeData(bound, elementPool[e.element], rightSon); return BvhTreeData(bound, elementPool[e.element], rightSon);
} }
void Painting::generateBuffers() void Painting::generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc)
{ {
qDebug() << "Element Count: " << elementPool.size(); qDebug() << "Element Count: " << elementPool.size();
qDebug() << "Coutour Count: " << contourPool.size(); qDebug() << "Coutour Count: " << contourPool.size();
qDebug() << " Style Count: " << stylePool.size(); qDebug() << " Style Count: " << stylePool.size();
bvhChildren.clear(); bvhChildren.clear();
bvhBounds.clear(); bvhBounds.clear();
elementOffset.clear(); elementOffset.clear();
@ -161,6 +160,19 @@ void Painting::generateBuffers()
elementOffset.push_back({ contourBuffer->bvhOffset, stylePool[i.first.style], contourBuffer->pointsOffset, contourBuffer->linesOffset }); 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); //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() GLuint Renderer::Painting::getElementCount()

View File

@ -1,12 +1,13 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <array>
#include <set> #include <set>
#include <QOpenGLFunctions_4_5_Compatibility>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include "Line.h" #include "Line.h"
#include "BvhTree.h" #include "BvhTree.h"
#include "ElementStyle.h" #include "ElementStyle.h"
#include "Element.h" #include "Element.h"
#include <QOpenGLFunctions_4_5_Compatibility>
namespace Renderer namespace Renderer
{ {
@ -65,12 +66,13 @@ namespace Renderer
std::vector<GLuint> elementIndex; std::vector<GLuint> elementIndex;
std::vector<GLfloat> elementData; std::vector<GLfloat> elementData;
int paintingId = 0; int paintingId = 0;
std::array<GLuint, 5> buffers;
Painting(); Painting();
void addElement(ElementWithTransform element); void addElement(ElementWithTransform element);
void addElement(const Element& element, const ElementTransform& transform); void addElement(const Element& element, const ElementTransform& transform);
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex); void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
void generateBuffers(); void generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc);
GLuint getElementCount(); GLuint getElementCount();
private: private:
std::unordered_map<std::shared_ptr<Contour>, std::pair<std::shared_ptr<ContourBuffer>/*Ãæ*/, std::shared_ptr<ContourBuffer>/*Ïß*/>> contourPool; std::unordered_map<std::shared_ptr<Contour>, std::pair<std::shared_ptr<ContourBuffer>/*Ãæ*/, std::shared_ptr<ContourBuffer>/*Ïß*/>> contourPool;

View File

@ -13,6 +13,13 @@ void PaintingMesh::draw()
{ {
if (shaderProgram->bind()) if (shaderProgram->bind())
{ {
glFunc->glActiveTexture(GL_TEXTURE0);
glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor);
glFunc->glActiveTexture(GL_TEXTURE1);
glFunc->glBindTexture(GL_TEXTURE_2D, textureMetallicRoughness);
shaderProgram->setUniformValue("texture_basecolor", 0);
shaderProgram->setUniformValue("texture_metallic_roughness", 1);
QOpenGLVertexArrayObject::Binder bind(&VAO); QOpenGLVertexArrayObject::Binder bind(&VAO);
shaderProgram->setUniformValue("model", model); shaderProgram->setUniformValue("model", model);
EBO.bind(); EBO.bind();

View File

@ -37,15 +37,15 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
switch (element.type) switch (element.type)
{ {
case QPainterPath::MoveToElement: case QPainterPath::MoveToElement:
qDebug() << "MoveToElement"; //qDebug() << "MoveToElement";
qDebug() << element; //qDebug() << element;
pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity())); pathBuffer.push_back(glm::vec2(std::numeric_limits<float>::infinity()));
pathBuffer.push_back(glm::vec2(element.x, element.y)); pathBuffer.push_back(glm::vec2(element.x, element.y));
break; break;
case QPainterPath::LineToElement: case QPainterPath::LineToElement:
{ {
qDebug() << "LineToElement"; //qDebug() << "LineToElement";
qDebug() << element; //qDebug() << element;
glm::vec2 end = glm::vec2(element.x, element.y); glm::vec2 end = glm::vec2(element.x, element.y);
glm::vec2 mid = (pathBuffer.back() + end) / 2.f; glm::vec2 mid = (pathBuffer.back() + end) / 2.f;
pathBuffer.push_back(mid); pathBuffer.push_back(mid);
@ -55,14 +55,14 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
} }
case QPainterPath::CurveToElement: case QPainterPath::CurveToElement:
{ {
qDebug() << "CurveToElement"; //qDebug() << "CurveToElement";
qDebug() << element; //qDebug() << element;
glm::vec2 p1 = glm::vec2(element.x, element.y); glm::vec2 p1 = glm::vec2(element.x, element.y);
element = path.elementAt(++i); element = path.elementAt(++i);
qDebug() << element; //qDebug() << element;
glm::vec2 p2 = glm::vec2(element.x, element.y); glm::vec2 p2 = glm::vec2(element.x, element.y);
element = path.elementAt(++i); element = path.elementAt(++i);
qDebug() << element; //qDebug() << element;
glm::vec2 p3 = glm::vec2(element.x, element.y); glm::vec2 p3 = glm::vec2(element.x, element.y);
if (p3 != pathBuffer.back()) if (p3 != pathBuffer.back())
{ {

View File

@ -9,6 +9,7 @@
#include <random> #include <random>
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
#include "IblUtils.h" #include "IblUtils.h"
#include "VirtualTextureManager.h"
using namespace Renderer; using namespace Renderer;
@ -74,10 +75,10 @@ void RendererGLWidget::setModel()
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper); //model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
light.model = model; light.model = model;
qDebug() << model->AABB; qDebug() << model->AABB;
paintingHelper->allocateBuffers(); //paintingHelper->allocateBuffers();
paintingCompProgramPtr->bind(); //paintingCompProgramPtr->bind();
paintingHelper->bindPaintingBuffers(); //paintingHelper->bindPaintingBuffers();
paintingCompProgramPtr->release(); //paintingCompProgramPtr->release();
doneCurrent(); doneCurrent();
} }
@ -231,8 +232,9 @@ void RendererGLWidget::initializeGL()
finalProgramPtr->setUniformValue("gBaseColor", 0); finalProgramPtr->setUniformValue("gBaseColor", 0);
finalProgramPtr->release(); finalProgramPtr->release();
vtManager = std::make_unique<VirtualTextureManager>(gl.get());
paintingHelper = new PaintingHelper(glFunc); 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->bind();
skyBoxProgramPtr->setUniformValue("environmentMap", 0); skyBoxProgramPtr->setUniformValue("environmentMap", 0);
@ -353,7 +355,7 @@ void RendererGLWidget::paintGL()
gl->BindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI); 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->BindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); //gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
paintingCompProgramPtr->release(); paintingCompProgramPtr->release();
gl->EndQuery(GL_TIME_ELAPSED); gl->EndQuery(GL_TIME_ELAPSED);

View File

@ -15,6 +15,8 @@ struct GladGLContext;
namespace Renderer namespace Renderer
{ {
class VirtualTextureManager;
class RendererGLWidget : public QOpenGLWidget class RendererGLWidget : public QOpenGLWidget
{ {
Q_OBJECT Q_OBJECT
@ -77,5 +79,6 @@ namespace Renderer
QOpenGLVertexArrayObject quadVAO; QOpenGLVertexArrayObject quadVAO;
Model* model = nullptr; Model* model = nullptr;
PaintingHelper* paintingHelper; PaintingHelper* paintingHelper;
std::unique_ptr<VirtualTextureManager> vtManager;
}; };
} }

View File

@ -1,7 +1,108 @@
#include "VirtualTextureManager.h"
#include <glad/gl.h> #include <glad/gl.h>
#include "VirtualTextureManager.h"
#include <array>
#include <QDebug>
#include <stb_image.h>
#include <glm/gtc/integer.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/component_wise.hpp>
Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl) Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl)
:gl(gl) :gl(gl)
{ {
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<GLint> pageSizesX(numPageSizes);
std::vector<GLint> pageSizesY(numPageSizes);
std::vector<GLint> 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<GLint> pageSizesRG8X(numPageSizes);
std::vector<GLint> pageSizesRG8Y(numPageSizes);
std::vector<GLint> 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();
}
GLuint Renderer::VirtualTextureManager::createVirtualTexture(Painting painting)
{
const GLsizei levels = glm::log2(textureSize / pageSize) + 1;
qDebug() << "levels:" << levels;
GLuint textures[2];
gl->CreateTextures(GL_TEXTURE_2D, 2, textures);
GLuint& baseColor = textures[0];
GLuint& metallicRoughness = textures[1];
gl->TextureParameteri(baseColor, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
gl->TextureParameteri(baseColor, GL_TEXTURE_BASE_LEVEL, 0);
gl->TextureParameteri(baseColor, GL_TEXTURE_MAX_LEVEL, levels - 1);
gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl->TextureParameteri(baseColor, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl->TextureParameteri(baseColor, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gl->TextureParameteri(baseColor, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TextureStorage2D(baseColor, levels, GL_RGBA8, GLsizei(textureSize), GLsizei(textureSize));
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_SPARSE_ARB, GL_TRUE);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_BASE_LEVEL, 0);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MAX_LEVEL, levels - 1);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gl->TextureParameteri(metallicRoughness, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TextureStorage2D(metallicRoughness, levels, GL_RG8, GLsizei(textureSize), GLsizei(textureSize));
for (int i = 0; i < 5; i++)
gl->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)
{
gl->TexturePageCommitmentEXT(baseColor, static_cast<GLint>(level),
static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j, 0,
static_cast<GLsizei>(pageSize), static_cast<GLsizei>(pageSize), 1,
GL_TRUE);
gl->TexturePageCommitmentEXT(metallicRoughness, static_cast<GLint>(level),
static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j, 0,
static_cast<GLsizei>(pageSize), static_cast<GLsizei>(pageSize), 1,
GL_TRUE);
program.bind();
gl->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j);
gl->BindImageTexture(0, baseColor, level, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
gl->BindImageTexture(1, metallicRoughness, level, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
gl->DispatchCompute(pageSize / 8, pageSize / 8, 1);
program.release();
}
}
paintings.emplace_back(baseColor, metallicRoughness, painting.buffers);
return paintings.size() - 1;
} }

View File

@ -1,17 +1,37 @@
#pragma once #pragma once
#include "Painting/Painting.h"
#include <QOpenGLShaderProgram>
struct GladGLContext; struct GladGLContext;
namespace Renderer namespace Renderer
{ {
struct PaintingHandle
{
GLuint baseColor;
GLuint metallicRoughness;
std::array<GLuint, 5> buffers;
};
class VirtualTextureManager class VirtualTextureManager
{ {
public: public:
static constexpr GLsizei textureSize = 16384;
std::vector<PaintingHandle> paintings;
VirtualTextureManager(GladGLContext* gl); VirtualTextureManager(GladGLContext* gl);
/**
* @brief
* @param painting
* @return ÔÚpaintingsÖÐË÷Òý
*/
GLuint createVirtualTexture(Painting painting);
private: private:
GladGLContext* gl; GladGLContext* gl;
GLint pageSize;
QOpenGLShaderProgram program;
}; };
} }

View File

@ -2,26 +2,59 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <FramelessHelper/Core/private/framelessconfig_p.h> #include <FramelessHelper/Core/private/framelessconfig_p.h>
#include <iostream>
#include <format>
#include "consoleapi2.h"
extern "C" extern "C"
{ {
_declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001; _declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
} }
FRAMELESSHELPER_USE_NAMESPACE FRAMELESSHELPER_USE_NAMESPACE
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;
}
std::cout << 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());
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
//FramelessHelper::Widgets::initialize(); qInstallMessageHandler(messageHandler);
FramelessHelper::Core::initialize(); //FramelessHelper::Widgets::initialize();
//QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); FramelessHelper::Core::initialize();
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication a(argc, argv); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
//FramelessHelper::Core::setApplicationOSThemeAware(); QApplication a(argc, argv);
FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur); //FramelessHelper::Core::setApplicationOSThemeAware();
FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::ForceNonNativeBackgroundBlur);
FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow);
MainWindow w; FramelessConfig::instance()->set(Global::Option::CenterWindowBeforeShow);
w.show(); MainWindow w;
return a.exec(); w.show();
return a.exec();
} }