karlis 2023-02-28 16:48:48 +08:00
commit 50bc51a8a6
40 changed files with 956 additions and 1138 deletions

View File

@ -70,6 +70,8 @@
<LanguageStandard>stdcpp20</LanguageStandard> <LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level1</WarningLevel>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -80,7 +82,7 @@
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<MultiProcessorCompilation>true</MultiProcessorCompilation> <MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization> <Optimization>MaxSpeed</Optimization>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
@ -171,6 +173,7 @@
<None Include="res\Shaders\model_shadow.frag" /> <None Include="res\Shaders\model_shadow.frag" />
<None Include="res\Shaders\model_shadow.geom" /> <None Include="res\Shaders\model_shadow.geom" />
<None Include="res\Shaders\model_shadow.vert" /> <None Include="res\Shaders\model_shadow.vert" />
<None Include="res\Shaders\pageId_downsample.comp" />
<None Include="res\Shaders\painting.comp" /> <None Include="res\Shaders\painting.comp" />
<None Include="res\Shaders\painting.frag" /> <None Include="res\Shaders\painting.frag" />
<None Include="res\Shaders\painting.vert" /> <None Include="res\Shaders\painting.vert" />

View File

@ -201,9 +201,6 @@
<ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp"> <ClCompile Include="src\Renderer\Preview\ElementRenderer.cpp">
<Filter>Source Files\Renderer\Preview</Filter> <Filter>Source Files\Renderer\Preview</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Editor\PixelPath.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Editor\LayerStyle.cpp"> <ClCompile Include="src\Editor\LayerStyle.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -216,6 +213,9 @@
<ClCompile Include="src\gl.c"> <ClCompile Include="src\gl.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="src\Editor\PixelPath.cpp">
<Filter>Source Files\Editor</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="src\Renderer\RendererGLWidget.h"> <QtMoc Include="src\Renderer\RendererGLWidget.h">
@ -326,6 +326,9 @@
<None Include="res\Shaders\brdf_lut.comp"> <None Include="res\Shaders\brdf_lut.comp">
<Filter>Resource Files\Shaders</Filter> <Filter>Resource Files\Shaders</Filter>
</None> </None>
<None Include="res\Shaders\pageId_downsample.comp">
<Filter>Resource Files\Shaders</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtUic Include="EditorWidget.ui"> <QtUic Include="EditorWidget.ui">

View File

@ -31,6 +31,7 @@
<file>Shaders/irradiance_convolution.frag</file> <file>Shaders/irradiance_convolution.frag</file>
<file>Shaders/cubemap_prefilter.frag</file> <file>Shaders/cubemap_prefilter.frag</file>
<file>Shaders/brdf_lut.comp</file> <file>Shaders/brdf_lut.comp</file>
<file>Shaders/pageId_downsample.comp</file>
</qresource> </qresource>
<qresource prefix="/qt/etc"> <qresource prefix="/qt/etc">
<file>qt.conf</file> <file>qt.conf</file>

View File

@ -9,7 +9,7 @@ layout (location = 0) out vec4 gBaseColor;
layout (location = 1) out vec3 gNormal; layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec3 gPosition; layout (location = 2) out vec3 gPosition;
layout (location = 3) out vec2 gMetallicRoughness; layout (location = 3) out vec2 gMetallicRoughness;
layout (location = 4) out uint gPaintingIndex; layout (location = 4) out uvec2 gPaintingIndex;
in vec2 TexCoords; in vec2 TexCoords;
in vec3 WorldPos; in vec3 WorldPos;
@ -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();
gPaintingIndex = 0; 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);
} }

View File

@ -1,4 +1,5 @@
#version 450 core #version 450 core
#extension GL_ARB_sparse_texture2 : enable
uniform sampler2D texture_basecolor; uniform sampler2D texture_basecolor;
@ -6,8 +7,11 @@ in vec2 TexCoords;
void main() 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<textureQueryLevels(texture_basecolor))
lod++;
if(baseColor.a<0.4) if(baseColor.a<0.4)
discard; discard;
} }

View File

@ -0,0 +1,14 @@
#version 450 core
layout (local_size_x = 8, local_size_y = 8) in;
layout(rg16ui, binding = 3) uniform uimage2D gPageId;
layout(location = 0) uniform uvec2 dither = uvec2(0);
void main()
{
uvec2 targetLocation = gl_GlobalInvocationID.xy;
uvec2 sourceLocation = targetLocation * 8 + dither;
imageStore(gPageId, ivec2(targetLocation), uvec4(imageLoad(gPageId, ivec2(sourceLocation))));
}

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
}; };
@ -1019,8 +1010,8 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++) for ( uint contourIterator = contourIndex + 1;contourIterator < contourIndex + 1 + lineCount; contourIterator++)
{ {
uint lineIndex = elementIndexs[contourIterator]; uint lineIndex = elementIndexs[contourIterator];
uint pLocation = linesOffset + 4 * lineIndex; uint pLocation = linesOffset + 2 * lineIndex;
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]); 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; uvec4 pyIndex = uvec4(1)+pxIndex;
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
elementData[pxIndex[1]], elementData[pyIndex[1]], 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) if(contourIterator_==contourIndex + 1 + lineCount)
contourIterator = contourIndex + 1; contourIterator = contourIndex + 1;
uint lineIndex = elementIndexs[contourIterator]; uint lineIndex = elementIndexs[contourIterator];
uint pLocation = linesOffset + 4 * lineIndex; uint pLocation = linesOffset + 3 * lineIndex;
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]); 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; uvec4 pyIndex = uvec4(1)+pxIndex;
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]], 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() 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,10 +1,16 @@
#version 450 core #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 = 0) out vec4 gBaseColor;
layout(location = 1) out vec3 gNormal; layout(location = 1) out vec3 gNormal;
layout(location = 2) out vec3 gPosition; layout(location = 2) out vec3 gPosition;
layout(location = 3) out vec2 gMetallicRoughness; layout(location = 3) out vec2 gMetallicRoughness;
layout(location = 4) out uint gPaintingIndex; layout(location = 4) out uvec2 gPaintingIndex;
layout(location = 5) out vec2 gPaintingTexCoord; layout(location = 5) out vec2 gPaintingTexCoord;
in vec2 TexCoords; in vec2 TexCoords;
@ -13,635 +19,37 @@ in vec3 Normal;
void main() void main()
{ {
int lodExpect = int(textureQueryLod(texture_basecolor, TexCoords).x);
gBaseColor = vec4( vec3(1),1 ); int levels = textureQueryLevels(texture_basecolor);
// mainImage(gBaseColor, vec2(1.,1.)-TexCoords); float lod = lodExpect;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod<levels)
lod++;
if(gBaseColor.a<0.4)
discard;
//gBaseColor = vec4( vec3(1),1 );
gPosition = WorldPos; gPosition = WorldPos;
gNormal = normalize(Normal); gNormal = normalize(Normal);
// gMetallicRoughness = vec2(1, 46./255); //gMetallicRoughness = vec2(0,1);
gMetallicRoughness = vec2(0); lod = lodExpect;
gPaintingIndex = 1; vec4 mt;
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_metallic_roughness, TexCoords, lod, mt))&&lod<levels)
lod++;
gMetallicRoughness = mt.rg;
// int pageSize = textureSize(texture_basecolor, levels-1).x;
// uint pageId = 0;
// for(uint i = 0; i < lodExpect; i++)
// pageId += 1<<(2*(levels-1-i));
uint w = 1<<(levels-1-lodExpect);
ivec2 page = ivec2(TexCoords * vec2(w));
page = clamp(page, ivec2(0), ivec2(w-1));
// pageId += page.y*w+page.x;
if(lodExpect==levels-1)
gPaintingIndex = uvec2(0);
else
gPaintingIndex = uvec2((paintingId<<4)+lodExpect, (page.y<<8)+page.x);
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

@ -2,9 +2,12 @@
#include <QFile> #include <QFile>
#include "../ThirdPartyLib/qquick/qquicksvgparser_p.h" #include "../ThirdPartyLib/qquick/qquicksvgparser_p.h"
#include <QPolygonF> #include <QPolygonF>
#include <iostream>
using std::map; using std::map;
using std::vector;
using std::reverse;
bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) { bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPath) {
QFile file(filePath); QFile file(filePath);
@ -46,12 +49,12 @@ bool SvgFileLoader::loadSvgFile(const QString& filePath, QPainterPath& painterPa
} }
} }
} }
qDebug() << painterPath;
file.close(); file.close();
return true; return true;
} }
QMap<QString, QString> SvgFileLoader::transformStyle(QString style) { QMap<QString, QString> SvgFileLoader::handleAttrStyle(QString style) {
QMap<QString, QString> resStyleMap; QMap<QString, QString> resStyleMap;
for (auto& attr : style.split(';')) { for (auto& attr : style.split(';')) {
if (attr.isEmpty() || attr.trimmed() == "") continue; if (attr.isEmpty() || attr.trimmed() == "") continue;
@ -62,7 +65,7 @@ QMap<QString, QString> SvgFileLoader::transformStyle(QString style) {
return resStyleMap; return resStyleMap;
} }
QPolygonF SvgFileLoader::transformPoints(QString points) { QPolygonF SvgFileLoader::handleAttrPoints(QString points) {
QPolygonF resPointVector; QPolygonF resPointVector;
QPointF point(0, 0); QPointF point(0, 0);
bool isX = true; bool isX = true;
@ -80,10 +83,58 @@ QPolygonF SvgFileLoader::transformPoints(QString points) {
return resPointVector; return resPointVector;
} }
void SvgFileLoader::handleAttrTransform(QString transformStyle, QPainterPath& painterPath) {
QTransform trans;
QStringList ops = transformStyle.split(')');
reverse(ops.begin(), ops.end());
vector<double> 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) { void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("style")) { if (attr.name().toString() == QLatin1String("style")) {
styleMap = transformStyle(attr.value().toLatin1()); styleMap = handleAttrStyle(attr.value().toLatin1());
} }
else { else {
styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1()); styleMap.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -94,22 +145,33 @@ void SvgFileLoader::handleLabelG(QPainterPath& painterPath) {
} }
void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) { void SvgFileLoader::handleLabelPath(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("d")) { 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")) { 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) { void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
QPainterPath elementPainterPath;
QString transformStyle = "";
double xBegin = 0, yBegin = 0, width = 0, height = 0;; double xBegin = 0, yBegin = 0, width = 0, height = 0;;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("x")) { if (attr.name().toString() == QLatin1String("x")) {
@ -122,17 +184,26 @@ void SvgFileLoader::handleLabelRect(QPainterPath& painterPath) {
height = attr.value().toDouble(); height = attr.value().toDouble();
} }
else if (attr.name().toString() == QLatin1String("style")) { 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; 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) { void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, r = 0; double cx = 0, cy = 0, r = 0;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
@ -144,18 +215,28 @@ void SvgFileLoader::handleLabelCircle(QPainterPath& painterPath) {
r = attr.value().toDouble(); r = attr.value().toDouble();
} }
else if (attr.name().toString() == QLatin1String("style")) { 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
elementPainterPath.addEllipse(cx, cy, r, r);
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
//addEllipse(cx, cy, r, r, painterPath); //addEllipse(cx, cy, r, r, painterPath);
painterPath.addEllipse(cx, cy, r, r);
} }
void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) { void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
double cx = 0, cy = 0, rx = 0, ry = 0; double cx = 0, cy = 0, rx = 0, ry = 0;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
@ -168,7 +249,10 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} else if (attr.name().toString() == QLatin1String("ry")) { } else if (attr.name().toString() == QLatin1String("ry")) {
rx = attr.value().toDouble(); rx = attr.value().toDouble();
} else if (attr.name().toString() == QLatin1String("style")) { } 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
@ -176,49 +260,73 @@ void SvgFileLoader::handleLabelEllipse(QPainterPath& painterPath) {
} }
qDebug() << labelStyle; qDebug() << labelStyle;
//addEllipse(cx, cy, rx, ry, painterPath); //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) { void SvgFileLoader::handleLabelPolyline(QPainterPath& painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) { if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1()); QPolygonF points = handleAttrPoints(attr.value().toLatin1());
painterPath.addPolygon(points); elementPainterPath.addPolygon(points);
} }
else if (attr.name().toString() == QLatin1String("style")) { 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) { void SvgFileLoader::handleLabelPolygon(QPainterPath & painterPath) {
QPainterPath elementPainterPath;
QString transformStyle = "";
QMap<QString, QString> labelStyle; QMap<QString, QString> labelStyle;
for (auto& attr : xmlReader->attributes()) { for (auto& attr : xmlReader->attributes()) {
if (attr.name().toString() == QLatin1String("points")) { if (attr.name().toString() == QLatin1String("points")) {
QPolygonF points = transformPoints(attr.value().toLatin1()); QPolygonF points = handleAttrPoints(attr.value().toLatin1());
//points.push_back(*points.begin()); //points.push_back(*points.begin());
painterPath.addPolygon(points); elementPainterPath.addPolygon(points);
painterPath.closeSubpath(); elementPainterPath.closeSubpath();
} }
else if (attr.name().toString() == QLatin1String("style")) { 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 { else {
labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1()); labelStyle.insert(attr.name().toLatin1(), attr.value().toLatin1());
} }
} }
qDebug() << labelStyle; qDebug() << labelStyle;
if (!transformStyle.isEmpty()) {
handleAttrTransform(transformStyle, elementPainterPath);
}
painterPath.addPath(elementPainterPath);
} }
/*
void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) { void SvgFileLoader::addEllipse(double x, double y, double w, double h, QPainterPath& painterPath) {
double k = w / 0.75; double k = w / 0.75;
painterPath.moveTo(x, y - h); 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.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(); painterPath.closeSubpath();
} }
*/

View File

@ -13,9 +13,10 @@ private:
bool existFatherLabelG; bool existFatherLabelG;
QMap<QString, QString> styleMap; QMap<QString, QString> styleMap;
std::shared_ptr<QXmlStreamReader> xmlReader; std::shared_ptr<QXmlStreamReader> xmlReader;
QPolygonF transformPoints(QString points); QPolygonF handleAttrPoints(QString points);
QMap<QString, QString> transformStyle(QString style); QMap<QString, QString> handleAttrStyle(QString style);
void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath); void handleAttrTransform(QString transformStyle, QPainterPath& painterPath);
//void addEllipse(double cx, double cy, double h, double w, QPainterPath& painterPath);
void handleLabelG(QPainterPath& painterPath); void handleLabelG(QPainterPath& painterPath);
void handleLabelPath(QPainterPath& painterPath); void handleLabelPath(QPainterPath& painterPath);
void handleLabelRect(QPainterPath& painterPath); void handleLabelRect(QPainterPath& painterPath);

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)
{ {
@ -179,8 +182,8 @@ std::tuple<GLuint, GLuint, GLuint, GLuint> Renderer::IblUtils::precomputeCubemap
// ---------------------- // ----------------------
unsigned int captureFBO; unsigned int captureFBO;
unsigned int captureRBO; unsigned int captureRBO;
glFunc->glGenFramebuffers(1, &captureFBO); glFunc->glCreateFramebuffers(1, &captureFBO);
glFunc->glGenRenderbuffers(1, &captureRBO); glFunc->glCreateRenderbuffers(1, &captureRBO);
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO); glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO); 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->glActiveTexture(GL_TEXTURE0);
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture); 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->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]);
@ -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<QMatrix4x4, 6>& captureViews, GLuint envCubemap) GLuint Renderer::IblUtils::generateIrradianceMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
{ {
constexpr int irradianceMapSize = 32;
// pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale. // pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale.
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
unsigned int irradianceMap; 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<QMatrix4x4, 6>& captureViews, GLuint envCubemap) GLuint Renderer::IblUtils::generatePrefilterMap(QOpenGLFunctions_4_5_Core* glFunc, GLuint captureFBO, GLuint captureRBO, const QMatrix4x4& captureProjection, const std::array<QMatrix4x4, 6>& captureViews, GLuint envCubemap)
{ {
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 +400,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

@ -7,6 +7,8 @@ namespace Renderer
{ {
public: public:
static constexpr int cubemapSize = 1024; 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 renderCube(QOpenGLFunctions_4_5_Core* glFunc);
static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc); static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc);
/** /**

View File

@ -22,12 +22,9 @@ void Mesh::draw()
{ {
if (shaderProgram->bind()) if (shaderProgram->bind())
{ {
glFunc->glActiveTexture(GL_TEXTURE0); glFunc->glBindTextureUnit(0, textureBasecolor);
glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor); glFunc->glBindTextureUnit(1, textureMetallicRoughness);
glFunc->glActiveTexture(GL_TEXTURE1); glFunc->glBindTextureUnit(2, textureNormal);
glFunc->glBindTexture(GL_TEXTURE_2D, textureMetallicRoughness);
glFunc->glActiveTexture(GL_TEXTURE2);
glFunc->glBindTexture(GL_TEXTURE_2D, textureNormal);
shaderProgram->setUniformValue("texture_basecolor", 0); shaderProgram->setUniformValue("texture_basecolor", 0);
shaderProgram->setUniformValue("texture_metallic_roughness", 1); shaderProgram->setUniformValue("texture_metallic_roughness", 1);
shaderProgram->setUniformValue("texture_normal", 2); shaderProgram->setUniformValue("texture_normal", 2);
@ -44,8 +41,7 @@ void Mesh::drawShadow()
{ {
if (shadowProgram->bind()) if (shadowProgram->bind())
{ {
glFunc->glActiveTexture(GL_TEXTURE0); glFunc->glBindTextureUnit(0, textureBasecolor);
glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor);
shadowProgram->setUniformValue("texture_basecolor", 0); shadowProgram->setUniformValue("texture_basecolor", 0);
QOpenGLVertexArrayObject::Binder bind(&VAO); QOpenGLVertexArrayObject::Binder bind(&VAO);

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

@ -11,59 +11,38 @@
#include "Painting/ShortCutTree.h" #include "Painting/ShortCutTree.h"
#include "Painting/Painting.h" #include "Painting/Painting.h"
#include "../SvgParser.h" #include "../SvgParser.h"
#include <ThirdPartyLib/qquick/qquicksvgparser_p.h>
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 +53,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 +68,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 +91,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 +111,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);
@ -139,11 +119,11 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
aiString str; aiString str;
material->GetTexture(aiTextureType_BASE_COLOR, 0, &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"; 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++)
{ {
@ -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(); 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 +182,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 +218,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);
@ -242,72 +234,12 @@ GLuint Renderer::Model::loadPainting(std::string path)
if (iter != paintingLoaded.end()) if (iter != paintingLoaded.end())
return iter->second; return iter->second;
//vector < vector <Point>> 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<std::shared_ptr<Contour>> contour = { vector<std::shared_ptr<Contour>> contour = {
std::make_shared<Contour>(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()), std::make_shared<Contour>(SvgParser("M100,100C-.5,100,0,100.5,0,0L40,.07C40,59.5,39.5,60,100,60Z", 100, 100).parse()),
//std::make_shared<Contour>(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<Contour>(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<Contour>(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<Contour>(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()) std::make_shared<Contour>(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<std::shared_ptr<ElementStyle>> style = {
// std::make_shared<ElementStyle>(std::vector<GLfloat>{
// //strokeStyle
// //stroke
// 1,
// //strokeWidth
// 0.02,
// //strokeEndType
// 0, //圆角
// //strokeFillType
// 0, //单色
// //线类型
// 0, //双侧
// //线外描边宽度
// 0,
// //线外描边方式
// 0, //单色
// //strokeFillColorMetallicRoughness
// 1,0,1, 0,0.8,
// }),
// std::make_shared<ElementStyle>(std::vector<GLfloat>{
// //fillStyle
// //fill
// 0,
// //fillType
// 0, //单色
// //fillColorMetallicRoughness
// 240 / 255., 220 / 255., 160 / 255., 0.996, 0.18,
// }),
// std::make_shared<ElementStyle>(std::vector<GLfloat>{
// //fillStyle
// //fill
// 0,
// //fillType
// 0, //单色
// //fillColorMetallicRoughness
// 24 / 255., 220 / 255., 16 / 255., 0., 0.18,
// }),
//};
vector<std::shared_ptr<ElementStyle>> style = { vector<std::shared_ptr<ElementStyle>> style = {
std::make_shared<ElementStyleFillDemo>(), std::make_shared<ElementStyleFillDemo>(),
std::make_shared<ElementStyleStrokeDemo>(0.02), std::make_shared<ElementStyleStrokeDemo>(0.02),
@ -320,161 +252,27 @@ GLuint Renderer::Model::loadPainting(std::string path)
std::make_shared<Element>(Element{ contour[2], style[0]}), std::make_shared<Element>(Element{ contour[2], style[0]}),
}; };
Painting painting; Painting painting;
//for (int i = 0; i < 3; i++)
//{ if (path == "17876391417123941155.jpg")
// float x = (float)rand() / RAND_MAX * 2 - 1; {
// float y = (float)rand() / RAND_MAX * 2 - 1; painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.5,-0.45), glm::vec2(0.6,0.7), 45, glm::bvec2(true, false), 0 });
// float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x; painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.5,0.5), 0, glm::bvec2(false), 0 });
// float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y; painting.addElement(*element[2], ElementTransform{ glm::vec2(0.5,-0.45), glm::vec2(0.6,0.7), 0, glm::bvec2(false), 0 });
// //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); else
//} {
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.5,-0.45), glm::vec2(0.6,0.7), 45, glm::bvec2(true, false), 0 }); for (int i = 0; i < 1000; i++)
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 }); 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.generateBuffers(glFunc);
//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(); auto index = vtManager->createVirtualTexture(painting);
///////////////////////////////////////////////////////////////////////////////////////////////// paintingLoaded.emplace(path, index);
std::vector<GLuint> 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<QVector4D> 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<glm::uvec4> 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<GLuint> 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<GLfloat> 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<GLuint>(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 });
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

@ -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<double> &p, vector<double>& res) { void CubicBezier::findPointsOfDivison(vector<double> &p, vector<double>& res) {
double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]); double a = (-p[0] + 3 * p[1] - 3 * p[2] + p[3]);
if (fabs(a) > eps) { if (fabs(a) > eps) {
@ -55,20 +61,26 @@ void CubicBezier::transformToCubic() {
} }
void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) { void CubicBezier::splitBezierCubic(double t, vector<LinePtr>& res) {
LinePtr Lf(new CubicBezier());
float pt = 1 - t;
Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) }; Point pointE = { getLineValueByT(t, false), getLineValueByT(t, true) };
Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t); Point pointF = getPointByT(getPointByIndex(0), getPointByIndex(1), t);
Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t); Point pointG = getPointByT(getPointByIndex(1), getPointByIndex(2), t);
Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t); Point pointH = getPointByT(getPointByIndex(2), getPointByIndex(3), t);
Lf->push_back(getPointByIndex(0)); vector<Point> vP; vP.clear();
Lf->push_back(pointF); vP.push_back(getPointByIndex(0));
Lf->push_back(getPointByT(pointF, pointG, t)); vP.push_back(pointF);
Lf->push_back(pointE); vP.push_back(getPointByT(pointF, pointG, t));
res.push_back(Lf); 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(0, pointE);
setPointByIndex(1, getPointByT(pointG, pointH, t)); setPointByIndex(1, getPointByT(pointG, pointH, t));
setPointByIndex(2, pointH); setPointByIndex(2, pointH);
updateLeftType();
setRate({ ratePoint, rate.second });
} }
void CubicBezier::monotonization(vector <LinePtr>& res) { void CubicBezier::monotonization(vector <LinePtr>& res) {
@ -120,4 +132,4 @@ int CubicBezier::judgeOneSideIntersection(double xy, double l, double r, bool is
double CubicBezier::getMinDistanceFromPoint(Point p) { double CubicBezier::getMinDistanceFromPoint(Point p) {
return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd()); return CubicBezierSignedDistance::cubic_bezier_dis(p, getBegin(), getPointByIndex(1), getPointByIndex(2), getEnd());
} }

View File

@ -11,12 +11,14 @@ namespace Renderer
static Point calculateControlPoint(Point a, Point b); static Point calculateControlPoint(Point a, Point b);
static void findPointsOfDivison(std::vector<double>& p, std::vector<double>& res); static void findPointsOfDivison(std::vector<double>& p, std::vector<double>& res);
void splitBezierCubic(double t, std::vector<LinePtr>& res); void splitBezierCubic(double t, std::vector<LinePtr>& res);
public: public:
virtual double findTByValue(double value, bool isY); virtual double findTByValue(double value, bool isY);
virtual void monotonization(std::vector <LinePtr>& res); virtual void monotonization(std::vector <LinePtr>& res);
virtual double getLineValueByT(double t, bool isY); virtual double getLineValueByT(double t, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getMinDistanceFromPoint(Point p); virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t);
void transformToCubic(); void transformToCubic();
}; };
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <QOpenGLFunctions_4_5_Compatibility> #include <qopengl.h>
#include <QPainterPath>
#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,4 +1,5 @@
#include "Line.h" #include "Line.h"
#include <glm/detail/func_packing.hpp>
using namespace Renderer; using namespace Renderer;
using std::vector; using std::vector;
using std::pair; using std::pair;
@ -14,14 +15,29 @@ Line::Line(vector<Point> Vp) {
vX.push_back(now.x); vX.push_back(now.x);
vY.push_back(now.y); vY.push_back(now.y);
} }
updateLeftType();
rate = { 0, 1 };
}
bool Line::updateLeftType() {
if (*vY.rbegin() < vY[0]) leftType = 0; if (*vY.rbegin() < vY[0]) leftType = 0;
else leftType = 1; else leftType = 1;
return true;
} }
int Line::size() { int Line::size() {
return siz; return siz;
} }
bool Line::setRate(std::pair<double, double> inRate) {
rate = inRate;
return true;
}
uint Line::getRate() {
return glm::packUnorm2x16(glm::vec2(rate.first, rate.second));
}
vector<Point> Line::toPointVector() const { vector<Point> Line::toPointVector() const {
vector<Point> vL; vector<Point> vL;
for (int i = 0; i < siz; i++) { 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.w(), bound.x(), bound.z(), true, width, type)
|| judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type) || judgeOneSideIntersectionWithWidth(bound.x(), bound.y(), bound.w(), false, width, type)
|| judgeOneSideIntersectionWithWidth(bound.z(), 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];
} }

View File

@ -49,21 +49,28 @@ namespace Renderer
protected: protected:
std::vector<double> vX, vY; std::vector<double> vX, vY;
int siz, leftType; int siz, leftType;
std::pair<double, double> rate;
public: public:
typedef std::shared_ptr<Line> LinePtr; typedef std::shared_ptr<Line> LinePtr;
Line() :siz(0) {} Line() : siz(0), leftType(0), rate({0, 1}) {}
Line(std::vector<Point> Vp); Line(std::vector<Point> Vp);
int size(); int size();
bool setRate(std::pair<double, double> inRate);
uint getRate();
void clear(); void clear();
Point getBegin(); Point getBegin();
Point getEnd(); Point getEnd();
int direction(bool isY); int direction(bool isY);
bool updateLeftType();
virtual double getLineValueByT(double t, bool isY) = 0; 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 <LinePtr>& res) = 0; virtual void monotonization(std::vector <LinePtr>& res) = 0;
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0; virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY) = 0;
virtual double getMinDistanceFromPoint(Point p) = 0; virtual double getMinDistanceFromPoint(Point p) = 0;
bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type); bool judgeOneSideIntersectionWithWidth(double xy, double l, double r, bool isY, double width, int type);
virtual double findTByValue(double value, bool isY) = 0; virtual double findTByValue(double value, bool isY) = 0;
double getIntegralByT(double t);
bool judgeIntersectionWithWidth(QVector4D bound, double width, int type); bool judgeIntersectionWithWidth(QVector4D bound, double width, int type);
bool judgeIntersection(QVector4D bound); bool judgeIntersection(QVector4D bound);
int getPointSideOfLine(Point p); int getPointSideOfLine(Point p);

View File

@ -108,15 +108,30 @@ void LineTree::monotonization(vector<PointVector>& inLines, vector<std::shared_p
} }
void LineTree::simplifyLineVector() { void LineTree::simplifyLineVector() {
bool canPut = false;
GLuint index = 0;
numLine = allLines.size(); numLine = allLines.size();
for (auto& nowLine : allLines) { for (auto& nowLine : allLines) {
PointVector pointVector = nowLine->toPointVector(); PointVector pointVector = nowLine->toPointVector();
canPut = false;
index = 0;
for (Point& p : pointVector) { for (Point& p : pointVector) {
int pointIndex = getPointIndex(p); int pointIndex = getPointIndex(p);
lineIndexs.push_back(pointIndex); if (pointVector.size() == 2) {
if (pointVector.size() == 2) index = (pointIndex << 16) + pointIndex;
lineIndexs.push_back(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<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
for (auto& vectorIter : tmpPoints) { for (auto& vectorIter : tmpPoints) {
resPoints.push_back(vectorIter.second.x); resPoints.push_back(vectorIter.second.x);
resPoints.push_back(vectorIter.second.y); resPoints.push_back(vectorIter.second.y);
vectorIter.second.show(); //vectorIter.second.show();
std::cout << '\n'; //std::cout << '\n';
} }
// Ïß¼¯ // Ïß¼¯
for (auto& nowLineIndex : lineIndexs) { for (auto& nowLineIndex : lineIndexs) {
resLines.push_back(nowLineIndex); resLines.push_back(nowLineIndex);
std::cout << nowLineIndex << ' '; //std::cout << nowLineIndex << ' ';
} }
std::cout << '\n'; //std::cout << '\n';
// ·µ»Ø¹¹ÔìBvhTreeÊý¾Ý // ·µ»Ø¹¹ÔìBvhTreeÊý¾Ý
vector<BvhTreeData> resBvhTreeData; vector<BvhTreeData> resBvhTreeData;
for (auto& nowTreeNode : restOfTreeNodes) { for (auto& nowTreeNode : restOfTreeNodes) {
@ -253,13 +268,13 @@ vector<BvhTreeData> LineTree::getPointLineAndBvhTree(vector<float>& resPoints, v
oneData.leftSon = resLines.size(); oneData.leftSon = resLines.size();
oneData.rightSon = 0; oneData.rightSon = 0;
oneData.bound = nowTreeNode.bound; oneData.bound = nowTreeNode.bound;
std::cout << nowTreeNode.lineSet.size() << ' '; //std::cout << nowTreeNode.lineSet.size() << ' ';
resLines.push_back(nowTreeNode.lineSet.size()); resLines.push_back(nowTreeNode.lineSet.size());
for (auto& lineIndex : nowTreeNode.lineSet) { for (auto& lineIndex : nowTreeNode.lineSet) {
resLines.push_back(lineIndex); resLines.push_back(lineIndex);
std::cout << lineIndex << ' '; //std::cout << lineIndex << ' ';
} }
std::cout << '\n'; //std::cout << '\n';
resBvhTreeData.push_back(oneData); resBvhTreeData.push_back(oneData);
} }
return resBvhTreeData; return resBvhTreeData;

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,12 @@ 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(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;
@ -79,6 +80,8 @@ namespace Renderer
std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool; std::unordered_map<std::shared_ptr<MaterialStyle>, GLuint> stylePool;
std::map<BaseElement, GLuint> elementPool; std::map<BaseElement, GLuint> elementPool;
std::vector<ElementWithTransform> elements; std::vector<ElementWithTransform> elements;
void addElement(ElementWithTransform element);
void insertContourBuffer(std::shared_ptr<ContourBuffer> buffer); void insertContourBuffer(std::shared_ptr<ContourBuffer> buffer);
BvhTreeData encodeElementLeaf(ElementWithTransform e); BvhTreeData encodeElementLeaf(ElementWithTransform e);
}; };

View File

@ -112,10 +112,8 @@ void ShortCutTree::generateShortCutSegment(ShortCutNode& nowTreeNode) {
} }
for (auto& iter : pointSet) { for (auto& iter : pointSet) {
nowTreeNode.lineSet.push_back(numLine); nowTreeNode.lineSet.push_back(numLine);
lineIndexs.push_back(iter.first); lineIndexs.push_back((iter.first << 16) + iter.first);
lineIndexs.push_back(iter.first); lineIndexs.push_back((iter.second << 16) + iter.second);
lineIndexs.push_back(iter.second);
lineIndexs.push_back(iter.second);
numLine++; numLine++;
} }
} }
@ -149,14 +147,28 @@ bool ShortCutTree::handleShortCutNode(ShortCutNode& fa, ShortCutNode& nowTreeNod
} }
void ShortCutTree::simplifyLineVector() { void ShortCutTree::simplifyLineVector() {
bool canPut = false;
GLuint index = 0;
numLine = allLines.size(); numLine = allLines.size();
for (auto& nowLine : allLines) { for (auto& nowLine : allLines) {
PointVector pointVector = nowLine->toPointVector(); PointVector pointVector = nowLine->toPointVector();
canPut = false;
index = 0;
for (Point& p : pointVector) { for (Point& p : pointVector) {
int pointIndex = getPointIndex(p); int pointIndex = getPointIndex(p);
lineIndexs.push_back(pointIndex); if (pointVector.size() == 2) {
if (pointVector.size() == 2) index = (pointIndex << 16) + pointIndex;
lineIndexs.push_back(pointIndex); lineIndexs.push_back(index);
}
else {
index <<= 16;
index += pointIndex;
if (canPut) {
lineIndexs.push_back(index);
index = 0;
}
canPut = !canPut;
}
} }
} }
for (auto& nowTreeNode : restOfTreeNodes) { for (auto& nowTreeNode : restOfTreeNodes) {

View File

@ -14,6 +14,10 @@ double StraightLine::getLineValueByT(double t, bool isY) {
return t * (valueEnd - valueBegin) + valueBegin; 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) { double StraightLine::findTByValue(double value, bool isY) {
Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1); Point pointBegin = getPointByIndex(0), pointEnd = getPointByIndex(1);
if (!isY) { if (!isY) {

View File

@ -11,5 +11,6 @@ namespace Renderer
virtual double findTByValue(double value, bool isY); virtual double findTByValue(double value, bool isY);
virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY); virtual int judgeOneSideIntersection(double xy, double l, double r, bool isY);
virtual double getMinDistanceFromPoint(Point p); virtual double getMinDistanceFromPoint(Point p);
virtual double ValueOfFunctionS(double t);
}; };
} }

View File

@ -13,8 +13,14 @@ void PaintingMesh::draw()
{ {
if (shaderProgram->bind()) 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); QOpenGLVertexArrayObject::Binder bind(&VAO);
shaderProgram->setUniformValue("model", model); shaderProgram->setUniformValue("model", model);
glFunc->glUniform1ui(glFunc->glGetUniformLocation(shaderProgram->programId(), "paintingId"), paintingId);
EBO.bind(); EBO.bind();
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
shaderProgram->release(); shaderProgram->release();
@ -24,6 +30,8 @@ void PaintingMesh::drawShadow()
{ {
if (shadowProgram->bind()) if (shadowProgram->bind())
{ {
glFunc->glBindTextureUnit(0, textureBasecolor);
shadowProgram->setUniformValue("texture_basecolor", 0);
QOpenGLVertexArrayObject::Binder bind(&VAO); QOpenGLVertexArrayObject::Binder bind(&VAO);
shadowProgram->setUniformValue("model", model); shadowProgram->setUniformValue("model", model);
EBO.bind(); EBO.bind();

View File

@ -25,7 +25,7 @@ namespace Renderer
QMatrix4x4 model; QMatrix4x4 model;
QOpenGLFunctions_4_5_Compatibility* glFunc; QOpenGLFunctions_4_5_Compatibility* glFunc;
QOpenGLShaderProgram* shaderProgram, * shadowProgram; QOpenGLShaderProgram* shaderProgram, * shadowProgram;
GLuint paintingIndex; GLuint paintingId;
PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model); PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
void draw() override; void draw() override;

View File

@ -9,6 +9,8 @@
#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"
#include <QDebug>
using namespace Renderer; using namespace Renderer;
@ -24,8 +26,9 @@ RendererGLWidget::RendererGLWidget(QWidget* parent)
//startTimer(); //startTimer();
lastFrame = std::clock(); lastFrame = std::clock();
setFocusPolicy(Qt::StrongFocus); setFocusPolicy(Qt::StrongFocus);
QSurfaceFormat format; //QSurfaceFormat format;
format.setSwapInterval(0); //format.setProfile(QSurfaceFormat::CoreProfile);
////format.setSwapInterval(0);
//setFormat(format); //setFormat(format);
} }
@ -58,7 +61,10 @@ void RendererGLWidget::startTimer()
{ {
//startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate()); //startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate());
if (timerId == -1) if (timerId == -1)
{
timerId = QObject::startTimer(1); timerId = QObject::startTimer(1);
}
} }
void RendererGLWidget::stopTimer() 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); //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();
} }
@ -100,16 +106,35 @@ void Renderer::RendererGLWidget::setExposure(float exposure)
QOpenGLTexture randomMap(QOpenGLTexture::Target2D); 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() void RendererGLWidget::initializeGL()
{ {
gl = std::make_unique<GladGLContext>(); gl = std::make_unique<GladGLContext>();
if (!gladLoadGLContext(gl.get(), [](const char* name) { return (GLADapiproc)QOpenGLContext::currentContext()->getProcAddress(name); })) 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<QOpenGLFunctions_4_5_Core>(); QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
qDebug() << "GL_VERSION" << (char*)gl->GetString(GL_VERSION); 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->Enable(GL_DEPTH_TEST);
gl->DepthFunc(GL_LEQUAL); gl->DepthFunc(GL_LEQUAL);
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS); gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
@ -117,83 +142,83 @@ void RendererGLWidget::initializeGL()
shadowProgramPtr = new QOpenGLShaderProgram; shadowProgramPtr = new QOpenGLShaderProgram;
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert")) 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")) 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")) if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model_shadow.frag"))
qDebug() << "ERROR:" << shadowProgramPtr->log(); qCritical() << "ERROR:" << shadowProgramPtr->log();
if (!shadowProgramPtr->link()) if (!shadowProgramPtr->link())
qDebug() << "ERROR:" << shadowProgramPtr->log(); qCritical() << "ERROR:" << shadowProgramPtr->log();
plainProgramPtr = new QOpenGLShaderProgram; plainProgramPtr = new QOpenGLShaderProgram;
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert")) if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert"))
qDebug() << "ERROR:" << plainProgramPtr->log(); qCritical() << "ERROR:" << plainProgramPtr->log();
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag")) if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag"))
qDebug() << "ERROR:" << plainProgramPtr->log(); qCritical() << "ERROR:" << plainProgramPtr->log();
if (!plainProgramPtr->link()) if (!plainProgramPtr->link())
qDebug() << "ERROR:" << plainProgramPtr->log(); qCritical() << "ERROR:" << plainProgramPtr->log();
modelProgramPtr = new QOpenGLShaderProgram; modelProgramPtr = new QOpenGLShaderProgram;
if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert")) if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert"))
qDebug() << "ERROR:" << modelProgramPtr->log(); qCritical() << "ERROR:" << modelProgramPtr->log();
if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag")) if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag"))
qDebug() << "ERROR:" << modelProgramPtr->log(); qCritical() << "ERROR:" << modelProgramPtr->log();
if (!modelProgramPtr->link()) if (!modelProgramPtr->link())
qDebug() << "ERROR:" << modelProgramPtr->log(); qCritical() << "ERROR:" << modelProgramPtr->log();
paintingProgramPtr = new QOpenGLShaderProgram; paintingProgramPtr = new QOpenGLShaderProgram;
if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert")) if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert"))
qDebug() << "ERROR:" << paintingProgramPtr->log(); qCritical() << "ERROR:" << paintingProgramPtr->log();
if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag")) if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag"))
qDebug() << "ERROR:" << paintingProgramPtr->log(); qCritical() << "ERROR:" << paintingProgramPtr->log();
if (!paintingProgramPtr->link()) if (!paintingProgramPtr->link())
qDebug() << "ERROR:" << paintingProgramPtr->log(); qCritical() << "ERROR:" << paintingProgramPtr->log();
paintingCompProgramPtr = new QOpenGLShaderProgram; pageIdDownsampleProgramPtr = new QOpenGLShaderProgram;
if (!paintingCompProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/painting.comp")) if (!pageIdDownsampleProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/pageId_downsample.comp"))
qDebug() << "ERROR:" << paintingCompProgramPtr->log(); qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log();
if (!paintingCompProgramPtr->link()) if (!pageIdDownsampleProgramPtr->link())
qDebug() << "ERROR:" << paintingCompProgramPtr->log(); qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log();
depthInitProgramPtr = new QOpenGLShaderProgram; depthInitProgramPtr = new QOpenGLShaderProgram;
if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp")) if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp"))
qDebug() << "ERROR:" << depthInitProgramPtr->log(); qCritical() << "ERROR:" << depthInitProgramPtr->log();
if (!depthInitProgramPtr->link()) if (!depthInitProgramPtr->link())
qDebug() << "ERROR:" << depthInitProgramPtr->log(); qCritical() << "ERROR:" << depthInitProgramPtr->log();
depthMipmapProgramPtr = new QOpenGLShaderProgram; depthMipmapProgramPtr = new QOpenGLShaderProgram;
if (!depthMipmapProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_mipmap.comp")) if (!depthMipmapProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_mipmap.comp"))
qDebug() << "ERROR:" << depthMipmapProgramPtr->log(); qCritical() << "ERROR:" << depthMipmapProgramPtr->log();
if (!depthMipmapProgramPtr->link()) if (!depthMipmapProgramPtr->link())
qDebug() << "ERROR:" << depthMipmapProgramPtr->log(); qCritical() << "ERROR:" << depthMipmapProgramPtr->log();
shadowMappingProgramPtr = new QOpenGLShaderProgram; shadowMappingProgramPtr = new QOpenGLShaderProgram;
if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp")) if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp"))
qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); qCritical() << "ERROR:" << shadowMappingProgramPtr->log();
if (!shadowMappingProgramPtr->link()) if (!shadowMappingProgramPtr->link())
qDebug() << "ERROR:" << shadowMappingProgramPtr->log(); qCritical() << "ERROR:" << shadowMappingProgramPtr->log();
ssgiProgramPtr = new QOpenGLShaderProgram; ssgiProgramPtr = new QOpenGLShaderProgram;
if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp")) if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp"))
qDebug() << "ERROR:" << ssgiProgramPtr->log(); qCritical() << "ERROR:" << ssgiProgramPtr->log();
if (!ssgiProgramPtr->link()) if (!ssgiProgramPtr->link())
qDebug() << "ERROR:" << ssgiProgramPtr->log(); qCritical() << "ERROR:" << ssgiProgramPtr->log();
finalProgramPtr = new QOpenGLShaderProgram; finalProgramPtr = new QOpenGLShaderProgram;
if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert")) if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert"))
qDebug() << "ERROR:" << finalProgramPtr->log(); qCritical() << "ERROR:" << finalProgramPtr->log();
if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag")) if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag"))
qDebug() << "ERROR:" << finalProgramPtr->log(); qCritical() << "ERROR:" << finalProgramPtr->log();
if (!finalProgramPtr->link()) if (!finalProgramPtr->link())
qDebug() << "ERROR:" << finalProgramPtr->log(); qCritical() << "ERROR:" << finalProgramPtr->log();
skyBoxProgramPtr = new QOpenGLShaderProgram; skyBoxProgramPtr = new QOpenGLShaderProgram;
if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert")) if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert"))
qDebug() << "ERROR:" << skyBoxProgramPtr->log(); qCritical() << "ERROR:" << skyBoxProgramPtr->log();
if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag")) if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag"))
qDebug() << "ERROR:" << skyBoxProgramPtr->log(); qCritical() << "ERROR:" << skyBoxProgramPtr->log();
if (!skyBoxProgramPtr->link()) if (!skyBoxProgramPtr->link())
qDebug() << "ERROR:" << skyBoxProgramPtr->log(); qCritical() << "ERROR:" << skyBoxProgramPtr->log();
shadowProgramPtr->bind(); shadowProgramPtr->bind();
gl->GenBuffers(1, &lightSpaceMatricesUBO); gl->GenBuffers(1, &lightSpaceMatricesUBO);
@ -231,8 +256,10 @@ 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);
@ -262,14 +289,15 @@ void RendererGLWidget::initializeGL()
reinterpret_cast<void*>(3 * sizeof(GLfloat))); reinterpret_cast<void*>(3 * sizeof(GLfloat)));
quadVBO.release(); quadVBO.release();
gl->GenQueries(1, &timeQuery);
} }
void RendererGLWidget::paintGL() void RendererGLWidget::paintGL()
{ {
QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>(); QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
gl->BeginQuery(GL_TIME_ELAPSED, timeQuery);
gl->Enable(GL_CULL_FACE); gl->Enable(GL_CULL_FACE);
light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw))); light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw)));
@ -285,6 +313,7 @@ void RendererGLWidget::paintGL()
} }
gl->BindBuffer(GL_UNIFORM_BUFFER, 0); gl->BindBuffer(GL_UNIFORM_BUFFER, 0);
vtManager->commitMutex.lock();
{ {
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle); gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution); gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution);
@ -314,7 +343,7 @@ void RendererGLWidget::paintGL()
paintingProgramPtr->release(); paintingProgramPtr->release();
if (model != nullptr) if (model != nullptr)
model->draw(); model->draw();
plainProgramPtr->bind(); plainProgramPtr->bind();
plainProgramPtr->setUniformValue("projection", projection); plainProgramPtr->setUniformValue("projection", projection);
plainProgramPtr->setUniformValue("view", view); plainProgramPtr->setUniformValue("view", view);
@ -328,11 +357,11 @@ void RendererGLWidget::paintGL()
for (int col = 0; col < nrColumns; ++col) for (int col = 0; col < nrColumns; ++col)
{ {
plainProgramPtr->setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f)); plainProgramPtr->setUniformValue("roughness", glm::clamp((float)col / (float)nrColumns, 0.05f, 1.0f));
model.setToIdentity(); model.setToIdentity();
model.scale(10); model.scale(10);
model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing, model.translate(QVector3D((float)(col - (nrColumns / 2)) * spacing,
(float)(row - (nrRows / 2)) * spacing+20, (float)(row - (nrRows / 2)) * spacing + 20,
-2.0f)); -2.0f));
plainProgramPtr->setUniformValue("model", model); plainProgramPtr->setUniformValue("model", model);
IblUtils::renderSphere(glFunc); IblUtils::renderSphere(glFunc);
@ -340,40 +369,40 @@ void RendererGLWidget::paintGL()
} }
plainProgramPtr->release(); 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<glm::u16vec2> 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(); fboPtr->release();
} }
gl->Finish();
vtManager->commitMutex.unlock();
GLuint paintingCompQuery; //depthInitProgramPtr->bind();
gl->GenQueries(1, &paintingCompQuery); //gl->ActiveTexture(GL_TEXTURE0);
gl->BeginQuery(GL_TIME_ELAPSED, paintingCompQuery); //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(); //depthMipmapProgramPtr->bind();
gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); //for (int i = 0; i <= 3; i++)
gl->BindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8); // gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
gl->BindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI); //gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1);
gl->BindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F); //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(frameWidth / 8.), ceil(frameHeight / 8.), 1); //gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1);
paintingCompProgramPtr->release(); //depthMipmapProgramPtr->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();
shadowMappingProgramPtr->bind(); shadowMappingProgramPtr->bind();
shadowMappingProgramPtr->setUniformValue("view", view); shadowMappingProgramPtr->setUniformValue("view", view);
@ -386,22 +415,15 @@ void RendererGLWidget::paintGL()
shadowMappingProgramPtr->setUniformValue("camPos", camera.Position); shadowMappingProgramPtr->setUniformValue("camPos", camera.Position);
shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection); shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection);
shadowMappingProgramPtr->setUniformValue("mainLightRadiance", mainLightRadiance); shadowMappingProgramPtr->setUniformValue("mainLightRadiance", mainLightRadiance);
/*gl->ActiveTexture(GL_TEXTURE0);
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);*/ gl->BindTextureUnit(1, gbuffers[1]);
gl->ActiveTexture(GL_TEXTURE1); gl->BindTextureUnit(2, gbuffers[2]);
gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]); gl->BindTextureUnit(3, gbuffers[3]);
gl->ActiveTexture(GL_TEXTURE2); gl->BindTextureUnit(4, shadowGbuffer);
gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]); gl->BindTextureUnit(5, irradianceMap);
gl->ActiveTexture(GL_TEXTURE3); gl->BindTextureUnit(6, prefilterMap);
gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]); gl->BindTextureUnit(7, brdfLUTTexture);
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->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8); 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->BindImageTexture(1, gbuffers[8], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F);
gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1); gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
@ -433,11 +455,9 @@ void RendererGLWidget::paintGL()
gl->Viewport(0, 0, frameWidth, frameHeight); gl->Viewport(0, 0, frameWidth, frameHeight);
gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO);
finalProgramPtr->bind(); finalProgramPtr->bind();
finalProgramPtr->setUniformValue("exposure", exposure); finalProgramPtr->setUniformValue("exposure", exposure);
gl->ActiveTexture(GL_TEXTURE0); gl->BindTextureUnit(0, gbuffers[0]);
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);
quadVAO.bind(); quadVAO.bind();
gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4); gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
quadVAO.release(); quadVAO.release();
@ -446,30 +466,32 @@ void RendererGLWidget::paintGL()
skyBoxProgramPtr->bind(); skyBoxProgramPtr->bind();
gl->Disable(GL_CULL_FACE); gl->Disable(GL_CULL_FACE);
skyBoxProgramPtr->setUniformValue("view", view); skyBoxProgramPtr->setUniformValue("view", view);
skyBoxProgramPtr->setUniformValue("projection", projection); skyBoxProgramPtr->setUniformValue("projection", projection);
skyBoxProgramPtr->setUniformValue("exposure", exposure); skyBoxProgramPtr->setUniformValue("exposure", exposure);
gl->ActiveTexture(GL_TEXTURE0); gl->BindTextureUnit(0, skyCubemap);
gl->BindTexture(GL_TEXTURE_CUBE_MAP, skyCubemap);
IblUtils::renderCube(glFunc); IblUtils::renderCube(glFunc);
skyBoxProgramPtr->release(); skyBoxProgramPtr->release();
GLuint paintingCompDuration; gl->EndQuery(GL_TIME_ELAPSED);
gl->GetQueryObjectuiv(paintingCompQuery, GL_QUERY_RESULT, &paintingCompDuration); GLuint frameDuration;
gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration);
clock_t currentFrame = std::clock(); clock_t currentFrame = std::clock();
deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC; deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC;
lastFrame = currentFrame; lastFrame = currentFrame;
static float accTime = 0, frameCnt = 0; static float accTime = 0, frameCnt = 0, averageDuration = 0;
accTime += deltaTime; accTime += deltaTime;
frameCnt++; frameCnt++;
averageDuration += frameDuration;
if (accTime > 1.) if (accTime > 1.)
{ {
std::cout << std::format("{:20}\r", ""); 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 << 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());
//std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r"; vtManager->pageLoadDuration = 0;
accTime = 0; accTime = 0;
frameCnt = 0; frameCnt = 0;
averageDuration = 0;
} }
if (pressedKeys.contains(Qt::Key_W)) { 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); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
//gPaintingIndex //gPaintingIndex
gl->BindTexture(GL_TEXTURE_2D, gbuffers[4]); 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_MIN_FILTER, GL_NEAREST);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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); 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->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_BASE_LEVEL, 0);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6); 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_MIN_FILTER, GL_NEAREST);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_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_S, GL_CLAMP_TO_BORDER);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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 })); gl->TexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));

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
@ -57,7 +59,7 @@ namespace Renderer
QOpenGLShaderProgram* plainProgramPtr = nullptr; QOpenGLShaderProgram* plainProgramPtr = nullptr;
QOpenGLShaderProgram* modelProgramPtr = nullptr; QOpenGLShaderProgram* modelProgramPtr = nullptr;
QOpenGLShaderProgram* paintingProgramPtr = nullptr; QOpenGLShaderProgram* paintingProgramPtr = nullptr;
QOpenGLShaderProgram* paintingCompProgramPtr = nullptr; QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr;
QOpenGLShaderProgram* depthInitProgramPtr = nullptr; QOpenGLShaderProgram* depthInitProgramPtr = nullptr;
QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr; QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr;
QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr; QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr;
@ -77,5 +79,8 @@ namespace Renderer
QOpenGLVertexArrayObject quadVAO; QOpenGLVertexArrayObject quadVAO;
Model* model = nullptr; Model* model = nullptr;
PaintingHelper* paintingHelper; PaintingHelper* paintingHelper;
std::unique_ptr<VirtualTextureManager> vtManager;
GLuint timeQuery;
}; };
} }

View File

@ -1,7 +1,229 @@
#include "VirtualTextureManager.h"
#include <glad/gl.h> #include <glad/gl.h>
#include "VirtualTextureManager.h"
#include <QOffscreenSurface>
#include <array>
#include <QDebug>
#include <glm/gtc/integer.hpp>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/component_wise.hpp>
Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* gl) std::mutex pageIdBufferMutex;
:gl(gl)
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<GladGLContext>();
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<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();
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<GLint>(level),
static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(pageSize) * j, 0,
static_cast<GLsizei>(pageSize), static_cast<GLsizei>(pageSize), 1,
GL_TRUE);
glMain->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();
glMain->Uniform2i(gl->GetUniformLocation(program.programId(), "pixelOffset"), static_cast<GLsizei>(pageSize) * i, static_cast<GLsizei>(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<glm::u16vec2>& 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<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y, 0,
static_cast<GLsizei>(pageSize), static_cast<GLsizei>(pageSize), 1,
commit);
gl->TexturePageCommitmentEXT(painting.metallicRoughness, level,
static_cast<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(pageSize) * page.y, 0,
static_cast<GLsizei>(pageSize), static_cast<GLsizei>(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<GLsizei>(pageSize) * page.x, static_cast<GLsizei>(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<glm::u16vec2>& 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;
}
}
} }

View File

@ -1,17 +1,65 @@
#pragma once #pragma once
#include "Painting/Painting.h"
#include <QOpenGLShaderProgram>
#include <unordered_map>
#include <thread>
#include <atomic>
#include <mutex>
#include <QOffscreenSurface>
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:
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<glm::u16vec2>& pageIds);
std::atomic<bool> initialized = false;
std::atomic<bool> needUpdate = false;
std::atomic<GLuint> pageLoadDuration = 0;
std::mutex commitMutex;
private: private:
GladGLContext* gl; std::jthread thread;
QOffscreenSurface surface;
std::unique_ptr<GladGLContext> gl;
GladGLContext* glMain;
static constexpr GLsizei textureSize = 16384;
static constexpr int lifeTime = 64;
GLint pageSize;
QOpenGLShaderProgram program;
std::vector<PaintingHandle> paintings;
struct u16vec2Hash
{
std::size_t operator()(glm::u16vec2 const& v) const
{
return ((std::size_t)v.y << 16) + v.x;
}
};
std::unordered_map<glm::u16vec2, int, u16vec2Hash> loadedPages;
std::vector<glm::u16vec2> pageIdsBuffer[2];
int currentBuffer = 0;
void updatePages(const std::vector<glm::u16vec2>& pageIds);
void pageCommitmentById(const glm::u16vec2& pageId, GLboolean commit);
}; };
} }

View File

@ -27,12 +27,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
break; break;
case QtCriticalMsg: 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); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
break; break;
case QtFatalMsg:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_RED);
break;
} }
std::cout << std::format("{}({},{}) {}\n", std::cout << std::format("{}({},{}) {}\n",
QString(context.file).splitRef("\\").back().toLocal8Bit().data(), QString(context.file).splitRef("\\").back().toLocal8Bit().data(),

View File

@ -4,6 +4,7 @@
#include "ElementRendererTest.h" #include "ElementRendererTest.h"
#include "Renderer/Painting/ElementStyle.h" #include "Renderer/Painting/ElementStyle.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Renderer; using namespace Renderer;
@ -14,8 +15,6 @@ namespace UnitTest
public: public:
TEST_METHOD(TestBothSidesRound) TEST_METHOD(TestBothSidesRound)
{ {
Logger::WriteMessage("In Class1");
Assert::AreEqual(1 ,2);
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
@ -197,4 +196,5 @@ namespace UnitTest
a.exec(); a.exec();
} }
}; };
} }

View File

@ -3,12 +3,43 @@
#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 <util/SvgFileLoader.h>
#include "Renderer/Painting/CubicBezier.h"
#include <Renderer/Painting/StraightLine.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework; using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace UnitTest 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) TEST_CLASS(UnitTest)
{ {
public: public:
@ -31,4 +62,37 @@ namespace UnitTest
a.exec(); 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<Renderer::Line> 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<std::shared_ptr<Renderer::Line>> outLines;
line->monotonization(outLines);
for (auto line : outLines) {
qDebug() << line->getRate();
}
}
};
} }

6
svg/test.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<rect width="300" height="100"
style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)"
transform="translate(50 20)"/>
</svg>

After

Width:  |  Height:  |  Size: 191 B