Merge branch 'main' of http://101.34.228.45:3000/BigC/ArchitectureColoredPainting
commit
de0f8f6009
|
@ -70,6 +70,8 @@
|
|||
<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>
|
||||
<PreprocessorDefinitions>FRAMELESSHELPER_WIDGETS_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level1</WarningLevel>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
@ -80,7 +82,7 @@
|
|||
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -171,6 +173,7 @@
|
|||
<None Include="res\Shaders\model_shadow.frag" />
|
||||
<None Include="res\Shaders\model_shadow.geom" />
|
||||
<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.frag" />
|
||||
<None Include="res\Shaders\painting.vert" />
|
||||
|
|
|
@ -326,6 +326,9 @@
|
|||
<None Include="res\Shaders\brdf_lut.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
<None Include="res\Shaders\pageId_downsample.comp">
|
||||
<Filter>Resource Files\Shaders</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="EditorWidget.ui">
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
<file>Shaders/irradiance_convolution.frag</file>
|
||||
<file>Shaders/cubemap_prefilter.frag</file>
|
||||
<file>Shaders/brdf_lut.comp</file>
|
||||
<file>Shaders/pageId_downsample.comp</file>
|
||||
</qresource>
|
||||
<qresource prefix="/qt/etc">
|
||||
<file>qt.conf</file>
|
||||
|
|
|
@ -9,7 +9,7 @@ layout (location = 0) out vec4 gBaseColor;
|
|||
layout (location = 1) out vec3 gNormal;
|
||||
layout (location = 2) out vec3 gPosition;
|
||||
layout (location = 3) out vec2 gMetallicRoughness;
|
||||
layout (location = 4) out uint gPaintingIndex;
|
||||
layout (location = 4) out uvec2 gPaintingIndex;
|
||||
|
||||
in vec2 TexCoords;
|
||||
in vec3 WorldPos;
|
||||
|
@ -36,12 +36,22 @@ vec3 getNormalFromMap()
|
|||
|
||||
void main()
|
||||
{
|
||||
if(textureSize(texture_basecolor,0)!=vec2(0))
|
||||
gBaseColor = texture(texture_basecolor, TexCoords);
|
||||
else
|
||||
gBaseColor = vec4(1);
|
||||
if(gBaseColor.a<0.4)
|
||||
discard;
|
||||
gPosition = WorldPos;
|
||||
if(textureSize(texture_normal,0)!=vec2(0))
|
||||
gNormal = getNormalFromMap();
|
||||
else
|
||||
gNormal = Normal;
|
||||
if(textureSize(texture_metallic_roughness,0)!=vec2(0))
|
||||
gMetallicRoughness = texture(texture_metallic_roughness, TexCoords).bg;
|
||||
gPaintingIndex = 0;
|
||||
else
|
||||
gMetallicRoughness = vec2(0,1);
|
||||
|
||||
gPaintingIndex = uvec2(0);
|
||||
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_sparse_texture2 : enable
|
||||
|
||||
uniform sampler2D texture_basecolor;
|
||||
|
||||
|
@ -6,8 +7,11 @@ in vec2 TexCoords;
|
|||
|
||||
void main()
|
||||
{
|
||||
//gBaseColor = vec4(1,0,0,1);
|
||||
vec4 baseColor = texture(texture_basecolor, TexCoords);
|
||||
vec4 baseColor;// = texture(texture_basecolor, TexCoords);
|
||||
float lod = textureQueryLod(texture_basecolor, TexCoords).x;
|
||||
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, baseColor))&&lod<textureQueryLevels(texture_basecolor))
|
||||
lod++;
|
||||
|
||||
if(baseColor.a<0.4)
|
||||
discard;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#version 450 core
|
||||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
layout(rg16ui, binding = 3) uniform uimage2D gPageId;
|
||||
|
||||
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))));
|
||||
}
|
|
@ -2,29 +2,20 @@
|
|||
|
||||
layout (local_size_x = 8, local_size_y = 8) in;
|
||||
|
||||
uniform ivec2 pixelOffset;
|
||||
|
||||
layout(rgba8, binding = 0) uniform image2D gBaseColor;
|
||||
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
|
||||
{
|
||||
/**********************
|
||||
** @x paintingBvhRoot
|
||||
** @y paintingBvhLength
|
||||
**********************/
|
||||
uvec2 paintingOffsets[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 2) buffer bvhBuffer
|
||||
layout(std430, binding = 0) buffer bvhBuffer
|
||||
{
|
||||
uvec2 bvhChildren[];
|
||||
};
|
||||
layout(std430, binding = 3) buffer bvhBoundBuffer
|
||||
layout(std430, binding = 1) buffer bvhBoundBuffer
|
||||
{
|
||||
vec4 bvhBound[];
|
||||
};
|
||||
layout(std430, binding = 4) buffer elementOffsetBuffer
|
||||
layout(std430, binding = 2) buffer elementOffsetBuffer
|
||||
{
|
||||
/**********************
|
||||
** @[0] elementBvhRoot
|
||||
|
@ -34,11 +25,11 @@ layout(std430, binding = 4) buffer elementOffsetBuffer
|
|||
**********************/
|
||||
uvec4 elementOffset[];
|
||||
};
|
||||
layout(std430, binding = 5) buffer elementIndexBuffer
|
||||
layout(std430, binding = 3) buffer elementIndexBuffer
|
||||
{
|
||||
uint elementIndexs[]; //ÏߺÍÃæ
|
||||
};
|
||||
layout(std430, binding = 6) buffer elementDataBuffer
|
||||
layout(std430, binding = 4) buffer elementDataBuffer
|
||||
{
|
||||
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++)
|
||||
{
|
||||
uint lineIndex = elementIndexs[contourIterator];
|
||||
uint pLocation = linesOffset + 4 * lineIndex;
|
||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]);
|
||||
uint pLocation = linesOffset + 2 * lineIndex;
|
||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
||||
uvec4 pyIndex = uvec4(1)+pxIndex;
|
||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
||||
elementData[pxIndex[1]], elementData[pyIndex[1]],
|
||||
|
@ -1078,8 +1069,8 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
|
|||
if(contourIterator_==contourIndex + 1 + lineCount)
|
||||
contourIterator = contourIndex + 1;
|
||||
uint lineIndex = elementIndexs[contourIterator];
|
||||
uint pLocation = linesOffset + 4 * lineIndex;
|
||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation], elementIndexs[pLocation+1], elementIndexs[pLocation+2], elementIndexs[pLocation+3]);
|
||||
uint pLocation = linesOffset + 3 * lineIndex;
|
||||
uvec4 pxIndex = uvec4(pointsOffset)+2*uvec4(elementIndexs[pLocation]>>16, elementIndexs[pLocation]&0xFFFF, elementIndexs[pLocation+1]>>16, elementIndexs[pLocation+1]&0xFFFF);
|
||||
uvec4 pyIndex = uvec4(1)+pxIndex;
|
||||
|
||||
mat4x2 p = mat4x2(elementData[pxIndex[0]], elementData[pyIndex[0]],
|
||||
|
@ -1182,13 +1173,13 @@ bool drawElement(uint elementIndex, vec2 localUV, out vec3 color, out vec2 metal
|
|||
|
||||
void main()
|
||||
{
|
||||
//ivec2 pixelLocation = ivec2(((gl_LocalInvocationID.xy)*imageSize(gPaintingIndex)/gl_WorkGroupSize.xy + gl_WorkGroupID.xy).xy);
|
||||
ivec2 pixelLocation = ivec2(gl_GlobalInvocationID.xy);
|
||||
uint paintingIndex = imageLoad(gPaintingIndex, pixelLocation).r;
|
||||
if(paintingIndex==0)
|
||||
return;
|
||||
|
||||
vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
|
||||
ivec2 pixelLocation = ivec2(pixelOffset + gl_GlobalInvocationID.xy);
|
||||
vec2 uv = (pixelLocation + vec2(0.5)) / imageSize(gBaseColor);
|
||||
//imageStore(gBaseColor, pixelLocation, vec4(uv,1,1));
|
||||
//imageStore(gMetallicRoughness, pixelLocation, vec4(uv,1,1));
|
||||
//return;
|
||||
uv = vec2(1)-uv*2;
|
||||
//vec2 uv = imageLoad(gPaintingTexCoord, pixelLocation).rg;
|
||||
|
||||
vec3 debugBVH = vec3(0);
|
||||
//bool debugHit = false;
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
#version 450 core
|
||||
#extension GL_ARB_sparse_texture2 : enable
|
||||
|
||||
uniform sampler2D texture_basecolor;
|
||||
uniform sampler2D texture_metallic_roughness;
|
||||
|
||||
uniform uint paintingId;
|
||||
|
||||
layout(location = 0) out vec4 gBaseColor;
|
||||
layout(location = 1) out vec3 gNormal;
|
||||
layout(location = 2) out vec3 gPosition;
|
||||
layout(location = 3) out vec2 gMetallicRoughness;
|
||||
layout(location = 4) out uint gPaintingIndex;
|
||||
layout(location = 4) out uvec2 gPaintingIndex;
|
||||
layout(location = 5) out vec2 gPaintingTexCoord;
|
||||
|
||||
in vec2 TexCoords;
|
||||
|
@ -13,635 +19,37 @@ in vec3 Normal;
|
|||
|
||||
void main()
|
||||
{
|
||||
|
||||
gBaseColor = vec4( vec3(1),1 );
|
||||
// mainImage(gBaseColor, vec2(1.,1.)-TexCoords);
|
||||
int lodExpect = int(textureQueryLod(texture_basecolor, TexCoords).x);
|
||||
int levels = textureQueryLevels(texture_basecolor);
|
||||
float lod = lodExpect;
|
||||
while(!sparseTexelsResidentARB(sparseTextureLodARB(texture_basecolor, TexCoords, lod, gBaseColor))&&lod<levels)
|
||||
lod++;
|
||||
if(gBaseColor.a<0.4)
|
||||
discard;
|
||||
//gBaseColor = vec4( vec3(1),1 );
|
||||
gPosition = WorldPos;
|
||||
gNormal = normalize(Normal);
|
||||
// gMetallicRoughness = vec2(1, 46./255);
|
||||
gMetallicRoughness = vec2(0);
|
||||
gPaintingIndex = 1;
|
||||
//gMetallicRoughness = vec2(0,1);
|
||||
lod = lodExpect;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
#include <QDebug>
|
||||
#include <array>
|
||||
#include <glm/glm.hpp>
|
||||
#ifndef STB_IMAGE_IMPLEMENTATION
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#endif
|
||||
|
||||
|
||||
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 captureRBO;
|
||||
glFunc->glGenFramebuffers(1, &captureFBO);
|
||||
glFunc->glGenRenderbuffers(1, &captureRBO);
|
||||
glFunc->glCreateFramebuffers(1, &captureFBO);
|
||||
glFunc->glCreateRenderbuffers(1, &captureRBO);
|
||||
|
||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||
glFunc->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, captureRBO);
|
||||
|
@ -259,6 +262,8 @@ GLuint Renderer::IblUtils::generateCubemap(QOpenGLFunctions_4_5_Core* glFunc, GL
|
|||
glFunc->glActiveTexture(GL_TEXTURE0);
|
||||
glFunc->glBindTexture(GL_TEXTURE_2D, hdrTexture);
|
||||
|
||||
glFunc->glBindRenderbuffer(GL_RENDERBUFFER, captureRBO);
|
||||
glFunc->glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, cubemapSize, cubemapSize);
|
||||
glFunc->glViewport(0, 0, cubemapSize, cubemapSize);
|
||||
glFunc->glBindFramebuffer(GL_FRAMEBUFFER, captureFBO);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
constexpr int irradianceMapSize = 32;
|
||||
|
||||
// pbr: create an irradiance cubemap, and re-scale capture FBO to irradiance scale.
|
||||
// --------------------------------------------------------------------------------
|
||||
unsigned int irradianceMap;
|
||||
|
@ -334,8 +337,6 @@ 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)
|
||||
{
|
||||
constexpr int prefilterMapSize = 128;
|
||||
|
||||
// pbr: create a pre-filter cubemap, and re-scale capture FBO to pre-filter scale.
|
||||
// --------------------------------------------------------------------------------
|
||||
unsigned int prefilterMap;
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace Renderer
|
|||
{
|
||||
public:
|
||||
static constexpr int cubemapSize = 1024;
|
||||
static constexpr int irradianceMapSize = 32;
|
||||
static constexpr int prefilterMapSize = 128;
|
||||
static void renderCube(QOpenGLFunctions_4_5_Core* glFunc);
|
||||
static void renderSphere(QOpenGLFunctions_4_5_Core* glFunc);
|
||||
/**
|
||||
|
|
|
@ -22,12 +22,9 @@ void Mesh::draw()
|
|||
{
|
||||
if (shaderProgram->bind())
|
||||
{
|
||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
||||
glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor);
|
||||
glFunc->glActiveTexture(GL_TEXTURE1);
|
||||
glFunc->glBindTexture(GL_TEXTURE_2D, textureMetallicRoughness);
|
||||
glFunc->glActiveTexture(GL_TEXTURE2);
|
||||
glFunc->glBindTexture(GL_TEXTURE_2D, textureNormal);
|
||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
||||
glFunc->glBindTextureUnit(1, textureMetallicRoughness);
|
||||
glFunc->glBindTextureUnit(2, textureNormal);
|
||||
shaderProgram->setUniformValue("texture_basecolor", 0);
|
||||
shaderProgram->setUniformValue("texture_metallic_roughness", 1);
|
||||
shaderProgram->setUniformValue("texture_normal", 2);
|
||||
|
@ -44,8 +41,7 @@ void Mesh::drawShadow()
|
|||
{
|
||||
if (shadowProgram->bind())
|
||||
{
|
||||
glFunc->glActiveTexture(GL_TEXTURE0);
|
||||
glFunc->glBindTexture(GL_TEXTURE_2D, textureBasecolor);
|
||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
||||
shadowProgram->setUniformValue("texture_basecolor", 0);
|
||||
|
||||
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
||||
|
|
|
@ -41,9 +41,9 @@ namespace Renderer
|
|||
QVector<Vertex> vertices;
|
||||
QVector<unsigned int> indices;
|
||||
//QVector<Texture*> textures;
|
||||
GLuint textureBasecolor;
|
||||
GLuint textureMetallicRoughness;
|
||||
GLuint textureNormal;
|
||||
GLuint textureBasecolor = 0;
|
||||
GLuint textureMetallicRoughness = 0;
|
||||
GLuint textureNormal = 0;
|
||||
|
||||
QMatrix4x4 model;
|
||||
QOpenGLFunctions_4_5_Compatibility* glFunc;
|
||||
|
|
|
@ -14,56 +14,34 @@
|
|||
|
||||
using namespace Renderer;
|
||||
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;
|
||||
const aiScene* scene = importer.ReadFile(directory.absolutePath().toUtf8(), aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode)
|
||||
{
|
||||
qDebug() << "ERROR::ASSIMP::" << importer.GetErrorString() << endl;
|
||||
return;
|
||||
}
|
||||
qDebug() << directory.absolutePath() << "Loaded Successfully";
|
||||
qDebug() << "NumMeshes: " << scene->mNumMeshes;
|
||||
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||
directory.cdUp();
|
||||
processNode(scene->mRootNode, scene);
|
||||
}
|
||||
|
||||
Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper)
|
||||
Model::Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram,
|
||||
QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram,
|
||||
PaintingHelper* paintingHelper, VirtualTextureManager* vtManager)
|
||||
: context(context)
|
||||
, glFunc(context->versionFunctions<QOpenGLFunctions_4_5_Compatibility>())
|
||||
, shaderProgram(shaderProgram)
|
||||
, paintingProgram(paintingProgram)
|
||||
, shadowProgram(shadowProgram)
|
||||
, paintingHelper(paintingHelper)
|
||||
, vtManager(vtManager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Model::~Model() //销毁对象
|
||||
{
|
||||
for (auto& it : meshes) {
|
||||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
void Model::draw() {
|
||||
//shaderProgram->bind();
|
||||
for (Drawable* mesh : meshes) {
|
||||
for (auto& mesh : meshes) {
|
||||
mesh->draw();
|
||||
}
|
||||
}
|
||||
|
||||
void Model::drawShadow() {
|
||||
//shaderProgram->bind();
|
||||
for (Drawable* mesh : meshes) {
|
||||
for (auto& mesh : meshes) {
|
||||
mesh->drawShadow();
|
||||
}
|
||||
}
|
||||
|
@ -74,11 +52,6 @@ void Model::destroy()
|
|||
delete this;
|
||||
}
|
||||
|
||||
Model* Model::createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram)
|
||||
{
|
||||
return new Model(path, context, shaderProgram);
|
||||
}
|
||||
|
||||
void Renderer::Model::loadModel(QString path)
|
||||
{
|
||||
directory = path;
|
||||
|
@ -94,6 +67,12 @@ void Renderer::Model::loadModel(QString path)
|
|||
qDebug() << "NumMaterials: " << scene->mNumMaterials;
|
||||
qDebug() << "NumTextures: " << scene->mNumTextures;
|
||||
directory.cdUp();
|
||||
minX = std::numeric_limits<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);
|
||||
AABB.push_back(QVector3D(minX, minY, minZ));
|
||||
AABB.push_back(QVector3D(minX, minY, maxZ));
|
||||
|
@ -111,8 +90,8 @@ void Model::processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4)
|
|||
// 处理节点所有的网格(如果有的话)
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes.push_back(processMesh(mesh, scene, mat4));
|
||||
if (auto mesh = processMesh(scene->mMeshes[node->mMeshes[i]], scene, mat4))
|
||||
meshes.emplace_back(std::move(mesh));
|
||||
|
||||
}
|
||||
// 接下来对它的子节点重复这一过程
|
||||
|
@ -131,7 +110,7 @@ GLuint encodeZIndexAngle(GLuint zIndex, float angle)
|
|||
return GLuint(angle / 360 * 65536 + zIndex * 65536);
|
||||
}
|
||||
|
||||
Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
|
||||
std::unique_ptr<Drawable> Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model)
|
||||
{
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
QMatrix4x4 modelQ((float*)&model);
|
||||
|
@ -143,7 +122,7 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
|
|||
{
|
||||
qDebug() << str.C_Str() << "Replaced";
|
||||
// 初始化网格
|
||||
PaintingMesh* m_mesh = new PaintingMesh(glFunc, paintingProgram, shadowProgram, modelQ);
|
||||
auto m_mesh = std::make_unique<PaintingMesh>(glFunc, paintingProgram, shadowProgram, modelQ);
|
||||
// 遍历网格的每个顶点
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
|
@ -169,14 +148,17 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
|
|||
}
|
||||
}
|
||||
|
||||
m_mesh->paintingIndex = loadPainting(std::string(str.C_Str()));
|
||||
m_mesh->paintingId = loadPainting(std::string(str.C_Str()));
|
||||
auto& handle = vtManager->getPaintingHandle(m_mesh->paintingId);
|
||||
m_mesh->textureBasecolor = handle.baseColor;
|
||||
m_mesh->textureMetallicRoughness = handle.metallicRoughness;
|
||||
m_mesh->setupMesh();
|
||||
return m_mesh;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 初始化网格
|
||||
Mesh* m_mesh = new Mesh(glFunc, shaderProgram, shadowProgram, modelQ);
|
||||
auto m_mesh = std::make_unique<Mesh>(glFunc, shaderProgram, shadowProgram, modelQ);
|
||||
// 遍历网格的每个顶点
|
||||
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||
{
|
||||
|
@ -199,13 +181,22 @@ Drawable* Model::processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 mod
|
|||
m_mesh->indices.push_back(*indice);
|
||||
|
||||
// 处理材质
|
||||
m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR);
|
||||
m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS);
|
||||
m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS);
|
||||
if (!(m_mesh->textureBasecolor = loadMaterialTextures(material, aiTextureType_BASE_COLOR)))
|
||||
qWarning() << "Basecolor Texture Loading Failed!";
|
||||
if (!(m_mesh->textureMetallicRoughness = loadMaterialTextures(material, aiTextureType_METALNESS)))
|
||||
qWarning() << "MetallicRoughness Texture Loading Failed!";
|
||||
if (!(m_mesh->textureNormal = loadMaterialTextures(material, aiTextureType_NORMALS)))
|
||||
qWarning() << "Normal Texture Loading Failed!";
|
||||
|
||||
if (m_mesh->textureBasecolor && m_mesh->textureMetallicRoughness && m_mesh->textureNormal)
|
||||
{
|
||||
m_mesh->setupMesh();
|
||||
return m_mesh;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
|
||||
|
@ -226,7 +217,7 @@ GLuint Model::loadMaterialTextures(aiMaterial* mat, aiTextureType type)
|
|||
return 0;
|
||||
|
||||
//qDebug() << "Loading" << path.c_str();
|
||||
auto [it, _] = texturesLoaded.emplace(std::piecewise_construct, std::make_tuple(path), std::make_tuple(QOpenGLTexture::Target2D));
|
||||
auto [it, _] = texturesLoaded.emplace(path, QOpenGLTexture::Target2D);
|
||||
auto& texture = it->second;
|
||||
texture.create();
|
||||
texture.setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
|
||||
|
@ -320,15 +311,17 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
|||
std::make_shared<Element>(Element{ contour[2], style[0]}),
|
||||
};
|
||||
Painting painting;
|
||||
//for (int i = 0; i < 3; i++)
|
||||
//{
|
||||
// float x = (float)rand() / RAND_MAX * 2 - 1;
|
||||
// float y = (float)rand() / RAND_MAX * 2 - 1;
|
||||
// float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x;
|
||||
// float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y;
|
||||
// //rootBvhTreeData.push_back(BvhTreeData(QVector4D(x, y, z, w), 0, encodeZIndexAngle(1, (float)rand() / RAND_MAX * 360)));
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
float x = (float)rand() / RAND_MAX * 2 - 1;
|
||||
float y = (float)rand() / RAND_MAX * 2 - 1;
|
||||
float z = 0.05 + x;//(float)rand() / RAND_MAX * (0.1) + x;
|
||||
float w = 0.05 + y;//(float)rand() / RAND_MAX * (0.1) + y;
|
||||
//rootBvhTreeData.push_back(BvhTreeData(QVector4D(x, y, z, w), 0, encodeZIndexAngle(1, (float)rand() / RAND_MAX * 360)));
|
||||
//painting.addElement(element[i%3], QVector4D(x, y, z, w), (float)rand() / RAND_MAX * 360, 1);
|
||||
//}
|
||||
//painting.addElement(*element[i%3], ElementTransform{ glm::vec2(x,y), glm::vec2(0.05), (float)rand() / RAND_MAX * 360, glm::bvec2(false), 0 });
|
||||
|
||||
}
|
||||
painting.addElement(*element[0], ElementTransform{ glm::vec2(-0.5,-0.45), glm::vec2(0.6,0.7), 45, glm::bvec2(true, false), 0 });
|
||||
painting.addElement(*element[1], ElementTransform{ glm::vec2(-0.45,0.45), glm::vec2(0.5,0.5), 0, glm::bvec2(false), 0 });
|
||||
painting.addElement(*element[2], ElementTransform{ glm::vec2(0.5,-0.45), glm::vec2(0.6,0.7), 0, glm::bvec2(false), 0 });
|
||||
|
@ -338,7 +331,7 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
|||
//painting.addElement(element[1], QVector4D(-0.7, 0.2, -0.2, 0.7), 0, 0);
|
||||
//painting.addElement(element[2], QVector4D(0.2, -0.8, 0.8, -0.1), 0, 0);
|
||||
|
||||
painting.generateBuffers();
|
||||
painting.generateBuffers(glFunc);
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
std::vector<GLuint> bvhChildren0 = {
|
||||
//root
|
||||
|
@ -474,7 +467,10 @@ GLuint Renderer::Model::loadPainting(std::string path)
|
|||
// elementOffset, elementIndex, elementData);
|
||||
/*GLuint index = paintingHelper->addPainting(bvhChildren0, bvhBounds0,
|
||||
elementOffset0, elementIndex0, elementData0);*/
|
||||
GLuint index = paintingHelper->addPainting(painting);
|
||||
paintingLoaded.insert({ path, index });
|
||||
//GLuint index = paintingHelper->addPainting(painting);
|
||||
//paintingLoaded.insert({ path, index });
|
||||
|
||||
auto index = vtManager->createVirtualTexture(painting);
|
||||
paintingLoaded.emplace(path, index);
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "Mesh.h"
|
||||
#include "Drawable.h"
|
||||
#include "Painting/PaintingHelper.h"
|
||||
#include "VirtualTextureManager.h"
|
||||
#include <QDir>
|
||||
#include <assimp/scene.h>
|
||||
|
||||
|
@ -15,39 +16,33 @@ namespace Renderer
|
|||
void draw();
|
||||
void drawShadow();
|
||||
void destroy();
|
||||
static Model* createModel(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
|
||||
void loadModel(QString path);
|
||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper);
|
||||
Model(QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* paintingProgram, QOpenGLShaderProgram* shadowProgram, PaintingHelper* paintingHelper, VirtualTextureManager* vtManager);
|
||||
private:
|
||||
Model(QString path, QOpenGLContext* context, QOpenGLShaderProgram* shaderProgram);
|
||||
|
||||
~Model();
|
||||
QOpenGLContext* context; //opengl函数入口
|
||||
QOpenGLFunctions_4_5_Compatibility* glFunc;
|
||||
QOpenGLContext* context;
|
||||
QOpenGLFunctions_4_5_Compatibility* glFunc = nullptr;
|
||||
QOpenGLShaderProgram* shaderProgram = nullptr;
|
||||
QOpenGLShaderProgram* paintingProgram = nullptr; //彩绘着色器程序
|
||||
QOpenGLShaderProgram* shadowProgram = nullptr;
|
||||
PaintingHelper* paintingHelper = nullptr;
|
||||
VirtualTextureManager* vtManager = nullptr;
|
||||
|
||||
/* 模型数据 */
|
||||
std::unordered_map<std::string, GLuint> paintingLoaded;
|
||||
std::unordered_map<std::string, QOpenGLTexture> texturesLoaded;
|
||||
//std::vector<Texture*> textures_loaded; //纹理
|
||||
QVector<Drawable*> meshes; //网格
|
||||
QDir directory; //模型所在路径
|
||||
std::vector<std::unique_ptr<Drawable>> meshes;
|
||||
|
||||
float minX = std::numeric_limits<float>::max();
|
||||
float maxX = std::numeric_limits<float>::min();
|
||||
float minY = std::numeric_limits<float>::max();
|
||||
float maxY = std::numeric_limits<float>::min();
|
||||
float minZ = std::numeric_limits<float>::max();
|
||||
float maxZ = std::numeric_limits<float>::min();
|
||||
/// Ä£ÐÍËùÔÚ·¾¶
|
||||
QDir directory;
|
||||
|
||||
float minX, maxX, minY, maxY, minZ, maxZ;
|
||||
|
||||
//递归遍历结点
|
||||
void processNode(aiNode* node, const aiScene* scene, aiMatrix4x4 mat4 = aiMatrix4x4());
|
||||
|
||||
//加载网格
|
||||
Drawable* processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
|
||||
std::unique_ptr<Drawable> processMesh(aiMesh* mesh, const aiScene* scene, aiMatrix4x4 model);
|
||||
|
||||
//加载材质纹理
|
||||
GLuint loadMaterialTextures(aiMaterial* mat, aiTextureType type);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
#include <qopengl.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <QColor>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
#include <qopengl.h>
|
||||
#include "Line.h"
|
||||
#include "ElementStyle.h"
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
#include "BaseStyle.h"
|
||||
|
||||
namespace Renderer
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "BaseStyle.h"
|
||||
#include <map>
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
|
|
@ -105,13 +105,12 @@ BvhTreeData Painting::encodeElementLeaf(ElementWithTransform e)
|
|||
return BvhTreeData(bound, elementPool[e.element], rightSon);
|
||||
}
|
||||
|
||||
void Painting::generateBuffers()
|
||||
void Painting::generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc)
|
||||
{
|
||||
qDebug() << "Element Count: " << elementPool.size();
|
||||
qDebug() << "Coutour Count: " << contourPool.size();
|
||||
qDebug() << " Style Count: " << stylePool.size();
|
||||
|
||||
|
||||
bvhChildren.clear();
|
||||
bvhBounds.clear();
|
||||
elementOffset.clear();
|
||||
|
@ -161,6 +160,19 @@ void Painting::generateBuffers()
|
|||
elementOffset.push_back({ contourBuffer->bvhOffset, stylePool[i.first.style], contourBuffer->pointsOffset, contourBuffer->linesOffset });
|
||||
//std::cout << std::format("{} {} {} {}\n", contourBuffer->bvhOffset, stylePool[i.first->style], contourBuffer->pointsOffset, contourBuffer->linesOffset);
|
||||
}
|
||||
|
||||
glFunc->glCreateBuffers(5, buffers.data());
|
||||
GLuint& bvhSSBO = buffers[0];
|
||||
GLuint& bvhBoundSSBO = buffers[1];
|
||||
GLuint& elementOffsetSSBO = buffers[2];
|
||||
GLuint& elementIndexSSBO = buffers[3];
|
||||
GLuint& elementDataSSBO = buffers[4];
|
||||
|
||||
glFunc->glNamedBufferData(bvhSSBO, bvhChildren.size() * sizeof(GLuint), bvhChildren.data(), GL_STATIC_READ);
|
||||
glFunc->glNamedBufferData(bvhBoundSSBO, bvhBounds.size() * sizeof(QVector4D), bvhBounds.data(), GL_STATIC_READ);
|
||||
glFunc->glNamedBufferData(elementOffsetSSBO, elementOffset.size() * sizeof(glm::uvec4), elementOffset.data(), GL_STATIC_READ);
|
||||
glFunc->glNamedBufferData(elementIndexSSBO, elementIndex.size() * sizeof(GLuint), elementIndex.data(), GL_STATIC_READ);
|
||||
glFunc->glNamedBufferData(elementDataSSBO, elementData.size() * sizeof(GLfloat), elementData.data(), GL_STATIC_READ);
|
||||
}
|
||||
|
||||
GLuint Renderer::Painting::getElementCount()
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
#include <glm/glm.hpp>
|
||||
#include "Line.h"
|
||||
#include "BvhTree.h"
|
||||
#include "ElementStyle.h"
|
||||
#include "Element.h"
|
||||
#include <QOpenGLFunctions_4_5_Compatibility>
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
|
@ -65,12 +66,13 @@ namespace Renderer
|
|||
std::vector<GLuint> elementIndex;
|
||||
std::vector<GLfloat> elementData;
|
||||
int paintingId = 0;
|
||||
std::array<GLuint, 5> buffers;
|
||||
|
||||
Painting();
|
||||
void addElement(ElementWithTransform element);
|
||||
void addElement(const Element& element, const ElementTransform& transform);
|
||||
void addElement(std::shared_ptr<Element> element, QVector4D bound, float rotation, int zIndex);
|
||||
void generateBuffers();
|
||||
void generateBuffers(QOpenGLFunctions_4_5_Compatibility* glFunc);
|
||||
GLuint getElementCount();
|
||||
private:
|
||||
std::unordered_map<std::shared_ptr<Contour>, std::pair<std::shared_ptr<ContourBuffer>/*Ãæ*/, std::shared_ptr<ContourBuffer>/*Ïß*/>> contourPool;
|
||||
|
|
|
@ -13,8 +13,14 @@ void PaintingMesh::draw()
|
|||
{
|
||||
if (shaderProgram->bind())
|
||||
{
|
||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
||||
glFunc->glBindTextureUnit(1, textureMetallicRoughness);
|
||||
shaderProgram->setUniformValue("texture_basecolor", 0);
|
||||
shaderProgram->setUniformValue("texture_metallic_roughness", 1);
|
||||
|
||||
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
||||
shaderProgram->setUniformValue("model", model);
|
||||
glFunc->glUniform1ui(glFunc->glGetUniformLocation(shaderProgram->programId(), "paintingId"), paintingId);
|
||||
EBO.bind();
|
||||
glFunc->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
|
||||
shaderProgram->release();
|
||||
|
@ -24,6 +30,8 @@ void PaintingMesh::drawShadow()
|
|||
{
|
||||
if (shadowProgram->bind())
|
||||
{
|
||||
glFunc->glBindTextureUnit(0, textureBasecolor);
|
||||
shadowProgram->setUniformValue("texture_basecolor", 0);
|
||||
QOpenGLVertexArrayObject::Binder bind(&VAO);
|
||||
shadowProgram->setUniformValue("model", model);
|
||||
EBO.bind();
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Renderer
|
|||
QMatrix4x4 model;
|
||||
QOpenGLFunctions_4_5_Compatibility* glFunc;
|
||||
QOpenGLShaderProgram* shaderProgram, * shadowProgram;
|
||||
GLuint paintingIndex;
|
||||
GLuint paintingId;
|
||||
|
||||
PaintingMesh(QOpenGLFunctions_4_5_Compatibility* glFunc, QOpenGLShaderProgram* shaderProgram, QOpenGLShaderProgram* shadowProgram, const QMatrix4x4& model);
|
||||
void draw() override;
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <random>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include "IblUtils.h"
|
||||
#include "VirtualTextureManager.h"
|
||||
#include <QDebug>
|
||||
|
||||
using namespace Renderer;
|
||||
|
||||
|
@ -24,8 +26,9 @@ RendererGLWidget::RendererGLWidget(QWidget* parent)
|
|||
//startTimer();
|
||||
lastFrame = std::clock();
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
QSurfaceFormat format;
|
||||
format.setSwapInterval(0);
|
||||
//QSurfaceFormat format;
|
||||
//format.setProfile(QSurfaceFormat::CoreProfile);
|
||||
////format.setSwapInterval(0);
|
||||
//setFormat(format);
|
||||
}
|
||||
|
||||
|
@ -58,7 +61,10 @@ void RendererGLWidget::startTimer()
|
|||
{
|
||||
//startTimer(1000 / QGuiApplication::primaryScreen()->refreshRate());
|
||||
if (timerId == -1)
|
||||
{
|
||||
timerId = QObject::startTimer(1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void RendererGLWidget::stopTimer()
|
||||
|
@ -74,10 +80,10 @@ void RendererGLWidget::setModel()
|
|||
//model = new Model("E:\\3D Objects\\gallery_gltf\\gallery_gltf.gltf", context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
|
||||
light.model = model;
|
||||
qDebug() << model->AABB;
|
||||
paintingHelper->allocateBuffers();
|
||||
paintingCompProgramPtr->bind();
|
||||
paintingHelper->bindPaintingBuffers();
|
||||
paintingCompProgramPtr->release();
|
||||
//paintingHelper->allocateBuffers();
|
||||
//paintingCompProgramPtr->bind();
|
||||
//paintingHelper->bindPaintingBuffers();
|
||||
//paintingCompProgramPtr->release();
|
||||
doneCurrent();
|
||||
}
|
||||
|
||||
|
@ -100,16 +106,35 @@ void Renderer::RendererGLWidget::setExposure(float exposure)
|
|||
|
||||
QOpenGLTexture randomMap(QOpenGLTexture::Target2D);
|
||||
|
||||
void GLAPIENTRY messageCallback(GLenum source,
|
||||
GLenum type,
|
||||
GLuint id,
|
||||
GLenum severity,
|
||||
GLsizei length,
|
||||
const GLchar* message,
|
||||
const void* userParam)
|
||||
{
|
||||
//fprintf(stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
|
||||
// (type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
|
||||
// type, severity, message);
|
||||
if (type == GL_DEBUG_TYPE_ERROR)
|
||||
qCritical() << QString::fromStdString(std::format("GL_ERROR: type = {:#x}, severity = {:#x}, message = {}",
|
||||
type, severity, message));
|
||||
}
|
||||
|
||||
void RendererGLWidget::initializeGL()
|
||||
{
|
||||
gl = std::make_unique<GladGLContext>();
|
||||
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>();
|
||||
qDebug() << "GL_VERSION" << (char*)gl->GetString(GL_VERSION);
|
||||
|
||||
gl->Enable(GL_DEBUG_OUTPUT);
|
||||
//gl->Enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
gl->DebugMessageCallback(messageCallback, 0);
|
||||
|
||||
gl->Enable(GL_DEPTH_TEST);
|
||||
gl->DepthFunc(GL_LEQUAL);
|
||||
gl->Enable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
|
@ -117,83 +142,83 @@ void RendererGLWidget::initializeGL()
|
|||
|
||||
shadowProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model_shadow.vert"))
|
||||
qDebug() << "ERROR:" << shadowProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowProgramPtr->log();
|
||||
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Geometry, ":/Shaders/model_shadow.geom"))
|
||||
qDebug() << "ERROR:" << shadowProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowProgramPtr->log();
|
||||
if (!shadowProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model_shadow.frag"))
|
||||
qDebug() << "ERROR:" << shadowProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowProgramPtr->log();
|
||||
if (!shadowProgramPtr->link())
|
||||
qDebug() << "ERROR:" << shadowProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowProgramPtr->log();
|
||||
|
||||
plainProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/shader.vert"))
|
||||
qDebug() << "ERROR:" << plainProgramPtr->log();
|
||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
||||
if (!plainProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/shader.frag"))
|
||||
qDebug() << "ERROR:" << plainProgramPtr->log();
|
||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
||||
if (!plainProgramPtr->link())
|
||||
qDebug() << "ERROR:" << plainProgramPtr->log();
|
||||
qCritical() << "ERROR:" << plainProgramPtr->log();
|
||||
|
||||
modelProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/model.vert"))
|
||||
qDebug() << "ERROR:" << modelProgramPtr->log();
|
||||
qCritical() << "ERROR:" << modelProgramPtr->log();
|
||||
if (!modelProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/model.frag"))
|
||||
qDebug() << "ERROR:" << modelProgramPtr->log();
|
||||
qCritical() << "ERROR:" << modelProgramPtr->log();
|
||||
if (!modelProgramPtr->link())
|
||||
qDebug() << "ERROR:" << modelProgramPtr->log();
|
||||
qCritical() << "ERROR:" << modelProgramPtr->log();
|
||||
|
||||
paintingProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/painting.vert"))
|
||||
qDebug() << "ERROR:" << paintingProgramPtr->log();
|
||||
qCritical() << "ERROR:" << paintingProgramPtr->log();
|
||||
if (!paintingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/painting.frag"))
|
||||
qDebug() << "ERROR:" << paintingProgramPtr->log();
|
||||
qCritical() << "ERROR:" << paintingProgramPtr->log();
|
||||
if (!paintingProgramPtr->link())
|
||||
qDebug() << "ERROR:" << paintingProgramPtr->log();
|
||||
qCritical() << "ERROR:" << paintingProgramPtr->log();
|
||||
|
||||
paintingCompProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!paintingCompProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/painting.comp"))
|
||||
qDebug() << "ERROR:" << paintingCompProgramPtr->log();
|
||||
if (!paintingCompProgramPtr->link())
|
||||
qDebug() << "ERROR:" << paintingCompProgramPtr->log();
|
||||
pageIdDownsampleProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!pageIdDownsampleProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/pageId_downsample.comp"))
|
||||
qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log();
|
||||
if (!pageIdDownsampleProgramPtr->link())
|
||||
qCritical() << "ERROR:" << pageIdDownsampleProgramPtr->log();
|
||||
|
||||
depthInitProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!depthInitProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_init.comp"))
|
||||
qDebug() << "ERROR:" << depthInitProgramPtr->log();
|
||||
qCritical() << "ERROR:" << depthInitProgramPtr->log();
|
||||
if (!depthInitProgramPtr->link())
|
||||
qDebug() << "ERROR:" << depthInitProgramPtr->log();
|
||||
qCritical() << "ERROR:" << depthInitProgramPtr->log();
|
||||
|
||||
depthMipmapProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!depthMipmapProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/depth_mipmap.comp"))
|
||||
qDebug() << "ERROR:" << depthMipmapProgramPtr->log();
|
||||
qCritical() << "ERROR:" << depthMipmapProgramPtr->log();
|
||||
if (!depthMipmapProgramPtr->link())
|
||||
qDebug() << "ERROR:" << depthMipmapProgramPtr->log();
|
||||
qCritical() << "ERROR:" << depthMipmapProgramPtr->log();
|
||||
|
||||
shadowMappingProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!shadowMappingProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/shadow_mapping.comp"))
|
||||
qDebug() << "ERROR:" << shadowMappingProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowMappingProgramPtr->log();
|
||||
if (!shadowMappingProgramPtr->link())
|
||||
qDebug() << "ERROR:" << shadowMappingProgramPtr->log();
|
||||
qCritical() << "ERROR:" << shadowMappingProgramPtr->log();
|
||||
|
||||
ssgiProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!ssgiProgramPtr->addShaderFromSourceFile(QOpenGLShader::Compute, ":/Shaders/ssgi.comp"))
|
||||
qDebug() << "ERROR:" << ssgiProgramPtr->log();
|
||||
qCritical() << "ERROR:" << ssgiProgramPtr->log();
|
||||
if (!ssgiProgramPtr->link())
|
||||
qDebug() << "ERROR:" << ssgiProgramPtr->log();
|
||||
qCritical() << "ERROR:" << ssgiProgramPtr->log();
|
||||
|
||||
finalProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/final.vert"))
|
||||
qDebug() << "ERROR:" << finalProgramPtr->log();
|
||||
qCritical() << "ERROR:" << finalProgramPtr->log();
|
||||
if (!finalProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/final.frag"))
|
||||
qDebug() << "ERROR:" << finalProgramPtr->log();
|
||||
qCritical() << "ERROR:" << finalProgramPtr->log();
|
||||
if (!finalProgramPtr->link())
|
||||
qDebug() << "ERROR:" << finalProgramPtr->log();
|
||||
qCritical() << "ERROR:" << finalProgramPtr->log();
|
||||
|
||||
skyBoxProgramPtr = new QOpenGLShaderProgram;
|
||||
if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Shaders/skybox.vert"))
|
||||
qDebug() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
qCritical() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
if (!skyBoxProgramPtr->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Shaders/skybox.frag"))
|
||||
qDebug() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
qCritical() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
if (!skyBoxProgramPtr->link())
|
||||
qDebug() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
qCritical() << "ERROR:" << skyBoxProgramPtr->log();
|
||||
|
||||
shadowProgramPtr->bind();
|
||||
gl->GenBuffers(1, &lightSpaceMatricesUBO);
|
||||
|
@ -231,8 +256,10 @@ void RendererGLWidget::initializeGL()
|
|||
finalProgramPtr->setUniformValue("gBaseColor", 0);
|
||||
finalProgramPtr->release();
|
||||
|
||||
vtManager = std::make_unique<VirtualTextureManager>(gl.get());
|
||||
|
||||
paintingHelper = new PaintingHelper(glFunc);
|
||||
model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper);
|
||||
model = new Model(context(), modelProgramPtr, paintingProgramPtr, shadowProgramPtr, paintingHelper, vtManager.get());
|
||||
|
||||
skyBoxProgramPtr->bind();
|
||||
skyBoxProgramPtr->setUniformValue("environmentMap", 0);
|
||||
|
@ -262,14 +289,30 @@ void RendererGLWidget::initializeGL()
|
|||
reinterpret_cast<void*>(3 * sizeof(GLfloat)));
|
||||
quadVBO.release();
|
||||
|
||||
|
||||
|
||||
gl->GenQueries(1, &timeQuery);
|
||||
}
|
||||
|
||||
void RendererGLWidget::paintGL()
|
||||
{
|
||||
QOpenGLFunctions_4_5_Core* glFunc = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_5_Core>();
|
||||
|
||||
pageIdDownsampleProgramPtr->bind();
|
||||
gl->BindImageTexture(3, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG16UI);
|
||||
gl->DispatchCompute(ceil(frameWidth / 8. / 8.), ceil(frameWidth / 8. / 8.), 1);
|
||||
pageIdDownsampleProgramPtr->release();
|
||||
std::vector<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);
|
||||
|
||||
|
||||
gl->BeginQuery(GL_TIME_ELAPSED, timeQuery);
|
||||
|
||||
|
||||
gl->Enable(GL_CULL_FACE);
|
||||
|
||||
light.lightDirection.setX(cos(qDegreesToRadians(sunPitch)) * cos(qDegreesToRadians(sunYaw)));
|
||||
|
@ -285,6 +328,7 @@ void RendererGLWidget::paintGL()
|
|||
}
|
||||
gl->BindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
|
||||
vtManager->commitMutex.lock();
|
||||
{
|
||||
gl->BindFramebuffer(GL_FRAMEBUFFER, shadowFboHandle);
|
||||
gl->Viewport(0, 0, shadowMapResolution, shadowMapResolution);
|
||||
|
@ -339,41 +383,26 @@ void RendererGLWidget::paintGL()
|
|||
}
|
||||
}
|
||||
plainProgramPtr->release();
|
||||
|
||||
fboPtr->release();
|
||||
}
|
||||
gl->Finish();
|
||||
vtManager->commitMutex.unlock();
|
||||
|
||||
GLuint paintingCompQuery;
|
||||
gl->GenQueries(1, &paintingCompQuery);
|
||||
gl->BeginQuery(GL_TIME_ELAPSED, paintingCompQuery);
|
||||
//depthInitProgramPtr->bind();
|
||||
//gl->ActiveTexture(GL_TEXTURE0);
|
||||
//gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]);
|
||||
//gl->BindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
//gl->DispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1);
|
||||
//depthInitProgramPtr->release();
|
||||
|
||||
paintingCompProgramPtr->bind();
|
||||
gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||
gl->BindImageTexture(1, gbuffers[3], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG8);
|
||||
gl->BindImageTexture(2, gbuffers[4], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R16UI);
|
||||
gl->BindImageTexture(3, gbuffers[5], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RG32F);
|
||||
|
||||
gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
|
||||
paintingCompProgramPtr->release();
|
||||
|
||||
gl->EndQuery(GL_TIME_ELAPSED);
|
||||
|
||||
|
||||
depthInitProgramPtr->bind();
|
||||
gl->ActiveTexture(GL_TEXTURE0);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[6]);
|
||||
gl->BindImageTexture(0, gbuffers[7], 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
gl->DispatchCompute(ceil(depthWidth / 8.), ceil(depthHeight / 8.), 1);
|
||||
depthInitProgramPtr->release();
|
||||
|
||||
depthMipmapProgramPtr->bind();
|
||||
for (int i = 0; i <= 3; i++)
|
||||
gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1);
|
||||
for (int i = 0; i <= 3; i++)
|
||||
gl->BindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1);
|
||||
depthMipmapProgramPtr->release();
|
||||
//depthMipmapProgramPtr->bind();
|
||||
//for (int i = 0; i <= 3; i++)
|
||||
// gl->BindImageTexture(i, gbuffers[7], i, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
//gl->DispatchCompute(ceil(depthWidth / 2. / 8.), ceil(depthHeight / 2. / 8.), 1);
|
||||
//for (int i = 0; i <= 3; i++)
|
||||
// gl->BindImageTexture(i, gbuffers[7], i + 3, GL_FALSE, 0, GL_READ_WRITE, GL_R32F);
|
||||
//gl->DispatchCompute(ceil(depthWidth / 2. / 8. / 8.), ceil(depthHeight / 2. / 8. / 8.), 1);
|
||||
//depthMipmapProgramPtr->release();
|
||||
|
||||
shadowMappingProgramPtr->bind();
|
||||
shadowMappingProgramPtr->setUniformValue("view", view);
|
||||
|
@ -386,22 +415,15 @@ void RendererGLWidget::paintGL()
|
|||
shadowMappingProgramPtr->setUniformValue("camPos", camera.Position);
|
||||
shadowMappingProgramPtr->setUniformValue("mainLightDirection", light.lightDirection);
|
||||
shadowMappingProgramPtr->setUniformValue("mainLightRadiance", mainLightRadiance);
|
||||
/*gl->ActiveTexture(GL_TEXTURE0);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);*/
|
||||
gl->ActiveTexture(GL_TEXTURE1);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[1]);
|
||||
gl->ActiveTexture(GL_TEXTURE2);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[2]);
|
||||
gl->ActiveTexture(GL_TEXTURE3);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[3]);
|
||||
gl->ActiveTexture(GL_TEXTURE4);
|
||||
gl->BindTexture(GL_TEXTURE_2D_ARRAY, shadowGbuffer);
|
||||
gl->ActiveTexture(GL_TEXTURE5);
|
||||
gl->BindTexture(GL_TEXTURE_CUBE_MAP, irradianceMap);
|
||||
gl->ActiveTexture(GL_TEXTURE6);
|
||||
gl->BindTexture(GL_TEXTURE_CUBE_MAP, prefilterMap);
|
||||
gl->ActiveTexture(GL_TEXTURE7);
|
||||
gl->BindTexture(GL_TEXTURE_2D, brdfLUTTexture);
|
||||
|
||||
gl->BindTextureUnit(1, gbuffers[1]);
|
||||
gl->BindTextureUnit(2, gbuffers[2]);
|
||||
gl->BindTextureUnit(3, gbuffers[3]);
|
||||
gl->BindTextureUnit(4, shadowGbuffer);
|
||||
gl->BindTextureUnit(5, irradianceMap);
|
||||
gl->BindTextureUnit(6, prefilterMap);
|
||||
gl->BindTextureUnit(7, brdfLUTTexture);
|
||||
|
||||
gl->BindImageTexture(0, gbuffers[0], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
||||
gl->BindImageTexture(1, gbuffers[8], 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16F);
|
||||
gl->DispatchCompute(ceil(frameWidth / 8.), ceil(frameHeight / 8.), 1);
|
||||
|
@ -433,11 +455,9 @@ void RendererGLWidget::paintGL()
|
|||
|
||||
gl->Viewport(0, 0, frameWidth, frameHeight);
|
||||
gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
//QOpenGLVertexArrayObject::Binder vaoBinder(&quadVAO);
|
||||
finalProgramPtr->bind();
|
||||
finalProgramPtr->setUniformValue("exposure", exposure);
|
||||
gl->ActiveTexture(GL_TEXTURE0);
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[0]);
|
||||
gl->BindTextureUnit(0, gbuffers[0]);
|
||||
quadVAO.bind();
|
||||
gl->DrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
quadVAO.release();
|
||||
|
@ -448,28 +468,30 @@ void RendererGLWidget::paintGL()
|
|||
skyBoxProgramPtr->setUniformValue("view", view);
|
||||
skyBoxProgramPtr->setUniformValue("projection", projection);
|
||||
skyBoxProgramPtr->setUniformValue("exposure", exposure);
|
||||
gl->ActiveTexture(GL_TEXTURE0);
|
||||
gl->BindTexture(GL_TEXTURE_CUBE_MAP, skyCubemap);
|
||||
gl->BindTextureUnit(0, skyCubemap);
|
||||
IblUtils::renderCube(glFunc);
|
||||
skyBoxProgramPtr->release();
|
||||
|
||||
GLuint paintingCompDuration;
|
||||
gl->GetQueryObjectuiv(paintingCompQuery, GL_QUERY_RESULT, &paintingCompDuration);
|
||||
gl->EndQuery(GL_TIME_ELAPSED);
|
||||
GLuint frameDuration;
|
||||
gl->GetQueryObjectuiv(timeQuery, GL_QUERY_RESULT, &frameDuration);
|
||||
|
||||
clock_t currentFrame = std::clock();
|
||||
deltaTime = (float)(currentFrame - lastFrame) / CLOCKS_PER_SEC;
|
||||
lastFrame = currentFrame;
|
||||
|
||||
static float accTime = 0, frameCnt = 0;
|
||||
static float accTime = 0, frameCnt = 0, averageDuration = 0;
|
||||
accTime += deltaTime;
|
||||
frameCnt++;
|
||||
averageDuration += frameDuration;
|
||||
if (accTime > 1.)
|
||||
{
|
||||
std::cout << std::format("{:20}\r", "");
|
||||
std::cout << std::format("FPS: {:.2f} Painting: {}ms Pos: {},{},{}\r", frameCnt / accTime, paintingCompDuration / 1e6, camera.Position.x(), camera.Position.y(), camera.Position.z());
|
||||
//std::cout << "FPS: " << frameCnt / accTime << " " << camera.Position.x() << " " << camera.Position.y() << " " << camera.Position.z() << "\r";
|
||||
std::cout << std::format("FPS: {:.2f}({:.2f}ms) Page: {:}ms Pos: {:.2f},{:.2f},{:.2f}\r", frameCnt / accTime, averageDuration / 1e6 / frameCnt, vtManager->pageLoadDuration / 1e6, camera.Position.x(), camera.Position.y(), camera.Position.z());
|
||||
vtManager->pageLoadDuration = 0;
|
||||
accTime = 0;
|
||||
frameCnt = 0;
|
||||
averageDuration = 0;
|
||||
}
|
||||
|
||||
if (pressedKeys.contains(Qt::Key_W)) {
|
||||
|
@ -534,7 +556,7 @@ void RendererGLWidget::resizeGL(int width, int height)
|
|||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, gbuffers[3], 0);
|
||||
//gPaintingIndex
|
||||
gl->BindTexture(GL_TEXTURE_2D, gbuffers[4]);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, frameWidth, frameHeight, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
|
||||
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RG16UI, frameWidth, frameHeight, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, gbuffers[4], 0);
|
||||
|
@ -570,8 +592,8 @@ void RendererGLWidget::resizeGL(int width, int height)
|
|||
gl->TexImage2D(GL_TEXTURE_2D, i, GL_R32F, depthWidth / pow(2, i), depthHeight / pow(2, i), 0, GL_RED, GL_FLOAT, NULL);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 6);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||
gl->TexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, std::begin({ 1.0f, 1.0f, 1.0f, 1.0f }));
|
||||
|
|
|
@ -15,6 +15,8 @@ struct GladGLContext;
|
|||
|
||||
namespace Renderer
|
||||
{
|
||||
class VirtualTextureManager;
|
||||
|
||||
class RendererGLWidget : public QOpenGLWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -57,7 +59,7 @@ namespace Renderer
|
|||
QOpenGLShaderProgram* plainProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* modelProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* paintingProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* paintingCompProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* pageIdDownsampleProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* depthInitProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* depthMipmapProgramPtr = nullptr;
|
||||
QOpenGLShaderProgram* shadowMappingProgramPtr = nullptr;
|
||||
|
@ -77,5 +79,8 @@ namespace Renderer
|
|||
QOpenGLVertexArrayObject quadVAO;
|
||||
Model* model = nullptr;
|
||||
PaintingHelper* paintingHelper;
|
||||
std::unique_ptr<VirtualTextureManager> vtManager;
|
||||
|
||||
GLuint timeQuery;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,229 @@
|
|||
#include "VirtualTextureManager.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)
|
||||
:gl(gl)
|
||||
std::mutex pageIdBufferMutex;
|
||||
|
||||
Renderer::VirtualTextureManager::VirtualTextureManager(GladGLContext* glMain)
|
||||
:glMain(glMain)
|
||||
{
|
||||
auto mainContext = QOpenGLContext::currentContext();
|
||||
auto mainSurface = mainContext->surface();
|
||||
surface.setFormat(mainContext->format());
|
||||
surface.create();
|
||||
mainContext->doneCurrent();
|
||||
|
||||
thread = std::jthread([&] {
|
||||
QOpenGLContext context;
|
||||
context.setFormat(mainContext->format());
|
||||
context.setShareContext(mainContext);
|
||||
context.create();
|
||||
context.makeCurrent(&surface);
|
||||
|
||||
gl = std::make_unique<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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,17 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include "Painting/Painting.h"
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <QOffscreenSurface>
|
||||
|
||||
struct GladGLContext;
|
||||
|
||||
namespace Renderer
|
||||
{
|
||||
struct PaintingHandle
|
||||
{
|
||||
GLuint baseColor;
|
||||
GLuint metallicRoughness;
|
||||
std::array<GLuint, 5> buffers;
|
||||
};
|
||||
|
||||
class VirtualTextureManager
|
||||
{
|
||||
public:
|
||||
VirtualTextureManager(GladGLContext* gl);
|
||||
VirtualTextureManager(GladGLContext* glMain);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param painting
|
||||
* @return ÐéÄâÎÆÀíid
|
||||
*/
|
||||
std::uint16_t createVirtualTexture(Painting painting);
|
||||
PaintingHandle& getPaintingHandle(std::uint16_t id);
|
||||
void tryUpdatePages(const std::vector<glm::u16vec2>& pageIds);
|
||||
|
||||
std::atomic<bool> initialized = false;
|
||||
std::atomic<bool> needUpdate = false;
|
||||
std::atomic<GLuint> pageLoadDuration = 0;
|
||||
std::mutex commitMutex;
|
||||
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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -27,12 +27,11 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt
|
|||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
|
||||
break;
|
||||
|
||||
case QtFatalMsg:
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | BACKGROUND_RED);
|
||||
break;
|
||||
}
|
||||
std::cout << std::format("{}({},{}) {}\n",
|
||||
QString(context.file).splitRef("\\").back().toLocal8Bit().data(),
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <QtWidgets/QApplication>
|
||||
#include "ElementRendererTest.h"
|
||||
#include "Renderer/Painting/ElementStyle.h"
|
||||
#include <util/SvgFileLoader.h>
|
||||
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
using namespace Renderer;
|
||||
|
@ -15,8 +15,6 @@ namespace UnitTest
|
|||
public:
|
||||
TEST_METHOD(TestBothSidesRound)
|
||||
{
|
||||
Logger::WriteMessage("In Class1");
|
||||
Assert::AreEqual(1 ,2);
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
|
|
Loading…
Reference in New Issue