Updated PN-Triangles tessellation shader demo
This commit is contained in:
parent
3f06ef81fb
commit
459dbbc5a1
16 changed files with 374 additions and 464 deletions
|
|
@ -7,15 +7,14 @@ if %ERRORLEVEL% EQU 0 (
|
||||||
mkdir "assets\shaders\base"
|
mkdir "assets\shaders\base"
|
||||||
xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y
|
xcopy "..\..\data\shaders\base\*.spv" "assets\shaders\base" /Y
|
||||||
|
|
||||||
|
|
||||||
mkdir "assets\shaders\tessellation"
|
mkdir "assets\shaders\tessellation"
|
||||||
xcopy "..\..\data\shaders\tessellation\*.spv" "assets\shaders\tessellation" /Y
|
xcopy "..\..\data\shaders\tessellation\*.spv" "assets\shaders\tessellation" /Y
|
||||||
|
|
||||||
mkdir "assets\textures"
|
mkdir "assets\textures"
|
||||||
xcopy "..\..\data\textures\bearmug.ktx" "assets\textures" /Y
|
xcopy "..\..\data\textures\deer.ktx" "assets\textures" /Y
|
||||||
|
|
||||||
mkdir "assets\models\lowpoly"
|
mkdir "assets\models\lowpoly"
|
||||||
xcopy "..\..\data\models\lowpoly\bearmug.dae" "assets\models\lowpoly" /Y
|
xcopy "..\..\data\models\lowpoly\deer.dae" "assets\models\lowpoly" /Y
|
||||||
|
|
||||||
mkdir "res\drawable"
|
mkdir "res\drawable"
|
||||||
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
|
xcopy "..\..\android\images\icon.png" "res\drawable" /Y
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
195
data/models/lowpoly/deer.dae
Normal file
195
data/models/lowpoly/deer.dae
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -14,7 +14,7 @@ layout (binding = 0, rgba8) uniform writeonly image2D resultImage;
|
||||||
#define SPHERECOUNT 3
|
#define SPHERECOUNT 3
|
||||||
#define SHADOW 0.5
|
#define SHADOW 0.5
|
||||||
#define RAYBOUNCES 1
|
#define RAYBOUNCES 1
|
||||||
#define REFLECTIONSTRENGTH 0.25
|
#define REFLECTIONSTRENGTH 0.4
|
||||||
|
|
||||||
struct Camera {
|
struct Camera {
|
||||||
vec3 pos;
|
vec3 pos;
|
||||||
|
|
@ -47,7 +47,7 @@ float lightSpecular(vec3 normal, vec3 lightDir)
|
||||||
{
|
{
|
||||||
vec3 viewVec = normalize(ubo.camera.pos);
|
vec3 viewVec = normalize(ubo.camera.pos);
|
||||||
vec3 halfVec = normalize(lightDir + viewVec);
|
vec3 halfVec = normalize(lightDir + viewVec);
|
||||||
return pow(clamp(dot(normal, halfVec), 0.0, 1.0), 16.0);
|
return pow(clamp(dot(normal, halfVec), 0.0, 1.0), 32.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primitives
|
// Primitives
|
||||||
|
|
@ -206,19 +206,19 @@ void main()
|
||||||
spheres[0].pos = vec3(-2.25, 1.0, 0.0);
|
spheres[0].pos = vec3(-2.25, 1.0, 0.0);
|
||||||
spheres[0].r = 1.0;
|
spheres[0].r = 1.0;
|
||||||
spheres[0].material.diffuse = vec3(1.0, 0.0, 0.0);
|
spheres[0].material.diffuse = vec3(1.0, 0.0, 0.0);
|
||||||
spheres[0].material.specular = vec3(1.0, 1.0, 1.0);
|
spheres[0].material.specular = vec3(2.0);
|
||||||
|
|
||||||
spheres[1].id = 3;
|
spheres[1].id = 3;
|
||||||
spheres[1].pos = vec3(0.0, 2.5, 0.0);
|
spheres[1].pos = vec3(0.0, 2.5, 0.0);
|
||||||
spheres[1].r = 1.0;
|
spheres[1].r = 1.0;
|
||||||
spheres[1].material.diffuse = vec3(0.0, 0.0, 1.0);
|
spheres[1].material.diffuse = vec3(0.0, 0.0, 1.0);
|
||||||
spheres[1].material.specular = vec3(1.0, 1.0, 1.0);
|
spheres[1].material.specular = vec3(2.0);
|
||||||
|
|
||||||
spheres[2].id = 4;
|
spheres[2].id = 4;
|
||||||
spheres[2].pos = vec3(2.25, 1.0, 0.0);
|
spheres[2].pos = vec3(2.25, 1.0, 0.0);
|
||||||
spheres[2].r = 1.0;
|
spheres[2].r = 1.0;
|
||||||
spheres[2].material.diffuse = vec3(0.0, 1.0, 0.0);
|
spheres[2].material.diffuse = vec3(0.0, 1.0, 0.0);
|
||||||
spheres[2].material.specular = vec3(1.0, 1.0, 1.0);
|
spheres[2].material.specular = vec3(2.0);
|
||||||
|
|
||||||
ivec2 dim = imageSize(resultImage);
|
ivec2 dim = imageSize(resultImage);
|
||||||
vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim;
|
vec2 uv = vec2(gl_GlobalInvocationID.xy) / dim;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -8,6 +8,11 @@ layout (location = 1) in vec2 inUV;
|
||||||
|
|
||||||
layout (location = 0) out vec2 outUV;
|
layout (location = 0) out vec2 outUV;
|
||||||
|
|
||||||
|
out gl_PerVertex
|
||||||
|
{
|
||||||
|
vec4 gl_Position;
|
||||||
|
};
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outUV = inUV;
|
outUV = inUV;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -13,8 +13,9 @@ layout (location = 0) out vec4 outFragColor;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 N = normalize(inNormal);
|
vec3 N = normalize(inNormal);
|
||||||
vec3 L = normalize(vec3(0.0, 2.0, 2.0));
|
vec3 L = normalize(vec3(0.0, -4.0, 4.0));
|
||||||
|
|
||||||
vec3 color = texture(samplerColorMap, inUV).rgb;
|
vec4 color = texture(samplerColorMap, inUV);
|
||||||
outFragColor.rgb = vec3(clamp(max(dot(N,L), 0.0), 0.15, 1.0)) * color;
|
|
||||||
|
outFragColor.rgb = vec3(clamp(max(dot(N,L), 0.0), 0.2, 1.0)) * color.rgb * 1.5;
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -10,6 +10,11 @@ layout (location = 2) in vec2 inUV;
|
||||||
layout (location = 0) out vec3 outNormal;
|
layout (location = 0) out vec3 outNormal;
|
||||||
layout (location = 1) out vec2 outUV;
|
layout (location = 1) out vec2 outUV;
|
||||||
|
|
||||||
|
out gl_PerVertex
|
||||||
|
{
|
||||||
|
vec4 gl_Position;
|
||||||
|
};
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
gl_Position = vec4(inPos.xyz, 1.0);
|
gl_Position = vec4(inPos.xyz, 1.0);
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -84,69 +84,3 @@ void main()
|
||||||
gl_TessLevelOuter[gl_InvocationID] = ubo.tessLevel;
|
gl_TessLevelOuter[gl_InvocationID] = ubo.tessLevel;
|
||||||
gl_TessLevelInner[0] = ubo.tessLevel;
|
gl_TessLevelInner[0] = ubo.tessLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
struct PnPatch
|
|
||||||
{
|
|
||||||
float barycentric[7];
|
|
||||||
float normals[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (binding = 0) uniform UBO
|
|
||||||
{
|
|
||||||
float tessLevel;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout (vertices = 3) out;
|
|
||||||
|
|
||||||
layout (location = 0) in vec3 inNormal[];
|
|
||||||
layout (location = 1) in vec2 inUV[];
|
|
||||||
|
|
||||||
layout (location = 0) out vec3 outNormal[3];
|
|
||||||
layout (location = 1) out PnPatch outPatch[3];
|
|
||||||
|
|
||||||
float dotPosNormW(int i, int j)
|
|
||||||
{
|
|
||||||
return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, inNormal[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
float dotPosNormV(int i, int j)
|
|
||||||
{
|
|
||||||
vec3 deltaPos = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
|
|
||||||
return 2.0 * dot(deltaPos, inNormal[i] + inNormal[j]) / dot(deltaPos, deltaPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
|
|
||||||
outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
|
|
||||||
|
|
||||||
float pos[3] = float[](gl_in[0].gl_Position[gl_InvocationID], gl_in[1].gl_Position[gl_InvocationID], gl_in[2].gl_Position[gl_InvocationID]);
|
|
||||||
float normal[3] = float[](inNormal[0][gl_InvocationID], inNormal[1][gl_InvocationID], inNormal[2][gl_InvocationID]);
|
|
||||||
|
|
||||||
// Calculate control points
|
|
||||||
outPatch[gl_InvocationID].barycentric[0] = (2.0 * pos[0] + pos[1] - dotPosNormW(0,1) * normal[0]) / 3.0;
|
|
||||||
outPatch[gl_InvocationID].barycentric[1] = (2.0 * pos[1] + pos[0] - dotPosNormW(1,0) * normal[1]) / 3.0;
|
|
||||||
outPatch[gl_InvocationID].barycentric[2] = (2.0 * pos[1] + pos[2] - dotPosNormW(1,2) * normal[1]) / 3.0;
|
|
||||||
outPatch[gl_InvocationID].barycentric[3] = (2.0 * pos[2] + pos[1] - dotPosNormW(2,1) * normal[2]) / 3.0;
|
|
||||||
outPatch[gl_InvocationID].barycentric[4] = (2.0 * pos[2] + pos[0] - dotPosNormW(2,0) * normal[2]) / 3.0;
|
|
||||||
outPatch[gl_InvocationID].barycentric[5] = (2.0 * pos[0] + pos[2] - dotPosNormW(0,2) * normal[0]) / 3.0;
|
|
||||||
|
|
||||||
float E = 0.0;
|
|
||||||
for (int i = 0; i < outPatch[gl_InvocationID].barycentric.length(); ++i)
|
|
||||||
{
|
|
||||||
E += outPatch[gl_InvocationID].barycentric[i];
|
|
||||||
}
|
|
||||||
E /= 6.0;
|
|
||||||
float V = (pos[0] + pos[1] + pos[2])/3.0;
|
|
||||||
|
|
||||||
outPatch[gl_InvocationID].barycentric[6] = E + (E - V) * 0.5;
|
|
||||||
outPatch[gl_InvocationID].normals[0] = normal[0] + normal[1] - dotPosNormV(0, 1) * (pos[1] - pos[0]);
|
|
||||||
outPatch[gl_InvocationID].normals[1] = normal[1] + normal[2] - dotPosNormV(1, 2) * (pos[2] - pos[1]);
|
|
||||||
outPatch[gl_InvocationID].normals[2] = normal[2] + normal[0] - dotPosNormV(2, 0) * (pos[0] - pos[2]);
|
|
||||||
|
|
||||||
gl_TessLevelOuter[gl_InvocationID] = ubo.tessLevel;
|
|
||||||
gl_TessLevelInner[0] = ubo.tessLevel;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
@ -51,31 +51,18 @@ void main()
|
||||||
vec3 b111 = vec3(iPnPatch[0].b111, iPnPatch[1].b111, iPnPatch[2].b111);
|
vec3 b111 = vec3(iPnPatch[0].b111, iPnPatch[1].b111, iPnPatch[2].b111);
|
||||||
|
|
||||||
// extract control normals
|
// extract control normals
|
||||||
vec3 n110 = normalize(vec3(iPnPatch[0].n110,
|
vec3 n110 = normalize(vec3(iPnPatch[0].n110, iPnPatch[1].n110, iPnPatch[2].n110));
|
||||||
iPnPatch[1].n110,
|
vec3 n011 = normalize(vec3(iPnPatch[0].n011, iPnPatch[1].n011, iPnPatch[2].n011));
|
||||||
iPnPatch[2].n110));
|
vec3 n101 = normalize(vec3(iPnPatch[0].n101, iPnPatch[1].n101, iPnPatch[2].n101));
|
||||||
vec3 n011 = normalize(vec3(iPnPatch[0].n011,
|
|
||||||
iPnPatch[1].n011,
|
|
||||||
iPnPatch[2].n011));
|
|
||||||
vec3 n101 = normalize(vec3(iPnPatch[0].n101,
|
|
||||||
iPnPatch[1].n101,
|
|
||||||
iPnPatch[2].n101));
|
|
||||||
|
|
||||||
// compute texcoords
|
// compute texcoords
|
||||||
oTexCoord = gl_TessCoord[2]*iTexCoord[0]
|
oTexCoord = gl_TessCoord[2]*iTexCoord[0] + gl_TessCoord[0]*iTexCoord[1] + gl_TessCoord[1]*iTexCoord[2];
|
||||||
+ gl_TessCoord[0]*iTexCoord[1]
|
|
||||||
+ gl_TessCoord[1]*iTexCoord[2];
|
|
||||||
|
|
||||||
// normal
|
// normal
|
||||||
vec3 barNormal = gl_TessCoord[2]*iNormal[0]
|
// Barycentric normal
|
||||||
+ gl_TessCoord[0]*iNormal[1]
|
vec3 barNormal = gl_TessCoord[2]*iNormal[0] + gl_TessCoord[0]*iNormal[1] + gl_TessCoord[1]*iNormal[2];
|
||||||
+ gl_TessCoord[1]*iNormal[2];
|
vec3 pnNormal = iNormal[0]*uvwSquared[2] + iNormal[1]*uvwSquared[0] + iNormal[2]*uvwSquared[1]
|
||||||
vec3 pnNormal = iNormal[0]*uvwSquared[2]
|
+ n110*uvw[2]*uvw[0] + n011*uvw[0]*uvw[1]+ n101*uvw[2]*uvw[1];
|
||||||
+ iNormal[1]*uvwSquared[0]
|
|
||||||
+ iNormal[2]*uvwSquared[1]
|
|
||||||
+ n110*uvw[2]*uvw[0]
|
|
||||||
+ n011*uvw[0]*uvw[1]
|
|
||||||
+ n101*uvw[2]*uvw[1];
|
|
||||||
oNormal = ubo.tessAlpha*pnNormal + (1.0-ubo.tessAlpha) * barNormal;
|
oNormal = ubo.tessAlpha*pnNormal + (1.0-ubo.tessAlpha) * barNormal;
|
||||||
|
|
||||||
// compute interpolated pos
|
// compute interpolated pos
|
||||||
|
|
@ -102,78 +89,3 @@ void main()
|
||||||
vec3 finalPos = (1.0-ubo.tessAlpha)*barPos + ubo.tessAlpha*pnPos;
|
vec3 finalPos = (1.0-ubo.tessAlpha)*barPos + ubo.tessAlpha*pnPos;
|
||||||
gl_Position = ubo.projection * ubo.model * vec4(finalPos,1.0);
|
gl_Position = ubo.projection * ubo.model * vec4(finalPos,1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
struct PnPatch
|
|
||||||
{
|
|
||||||
float barycentric[7];
|
|
||||||
float normals[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
layout (binding = 1) uniform UBO
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 model;
|
|
||||||
float tessAlpha;
|
|
||||||
} ubo;
|
|
||||||
|
|
||||||
layout(triangles, equal_spacing, ccw) in;
|
|
||||||
|
|
||||||
layout(location = 0) in vec3 inNormal[];
|
|
||||||
layout(location = 1) in PnPatch inPatch[];
|
|
||||||
|
|
||||||
layout(location = 0) out vec3 outNormal;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 uvwSquared = gl_TessCoord * gl_TessCoord;
|
|
||||||
vec3 uvwCubed = uvwSquared * gl_TessCoord;
|
|
||||||
|
|
||||||
// Get barycentric coordinates
|
|
||||||
vec3 barycentric[7];
|
|
||||||
for (int i = 0; i < barycentric.length(); ++i)
|
|
||||||
{
|
|
||||||
barycentric[i] = vec3(inPatch[0].barycentric[i], inPatch[1].barycentric[i], inPatch[2].barycentric[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal control points
|
|
||||||
vec3 normals[3];
|
|
||||||
for (int i = 0; i < normals.length(); ++i)
|
|
||||||
{
|
|
||||||
normals[i] = normalize(vec3(inPatch[0].normals[i], inPatch[1].normals[i], inPatch[2].normals[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate normals
|
|
||||||
vec3 barNormal = gl_TessCoord[2] * inNormal[0] + gl_TessCoord[0] * inNormal[1] + gl_TessCoord[1] * inNormal[2];
|
|
||||||
vec3 pnNormal = inNormal[0] * uvwSquared[2]
|
|
||||||
+ inNormal[1] * uvwSquared[0]
|
|
||||||
+ inNormal[2] * uvwSquared[1]
|
|
||||||
+ normals[0] * gl_TessCoord[2] * gl_TessCoord[0]
|
|
||||||
+ normals[1] * gl_TessCoord[0] * gl_TessCoord[1]
|
|
||||||
+ normals[2] * gl_TessCoord[2] * gl_TessCoord[1];
|
|
||||||
outNormal = ubo.tessAlpha * pnNormal + (1.0-ubo.tessAlpha) * barNormal;
|
|
||||||
|
|
||||||
// Interpolate position
|
|
||||||
vec3 barPos = gl_TessCoord[2] * gl_in[0].gl_Position.xyz
|
|
||||||
+ gl_TessCoord[0] * gl_in[1].gl_Position.xyz
|
|
||||||
+ gl_TessCoord[1] * gl_in[2].gl_Position.xyz;
|
|
||||||
|
|
||||||
uvwSquared *= 3.0;
|
|
||||||
|
|
||||||
// PN positions
|
|
||||||
vec3 pnPos = gl_in[0].gl_Position.xyz * uvwCubed[2]
|
|
||||||
+ gl_in[1].gl_Position.xyz * uvwCubed[0]
|
|
||||||
+ gl_in[2].gl_Position.xyz * uvwCubed[1]
|
|
||||||
+ barycentric[0] * uvwSquared[2] * gl_TessCoord[0]
|
|
||||||
+ barycentric[1] * uvwSquared[0] * gl_TessCoord[2]
|
|
||||||
+ barycentric[5] * uvwSquared[2] * gl_TessCoord[1]
|
|
||||||
+ barycentric[2] * uvwSquared[0] * gl_TessCoord[1]
|
|
||||||
+ barycentric[4] * uvwSquared[1] * gl_TessCoord[2]
|
|
||||||
+ barycentric[3] * uvwSquared[1] * gl_TessCoord[0]
|
|
||||||
+ barycentric[6] * 6.0 * gl_TessCoord[0] * gl_TessCoord[1] * gl_TessCoord[2];
|
|
||||||
|
|
||||||
vec3 finalPos = (1.0 - ubo.tessAlpha) * barPos + ubo.tessAlpha * pnPos;
|
|
||||||
gl_Position = ubo.projection * ubo.model * vec4(finalPos, 1.0);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
Binary file not shown.
BIN
data/textures/deer.ktx
Normal file
BIN
data/textures/deer.ktx
Normal file
Binary file not shown.
|
|
@ -56,13 +56,13 @@ public:
|
||||||
vkTools::UniformData uniformDataTC, uniformDataTE;
|
vkTools::UniformData uniformDataTC, uniformDataTE;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
float tessLevel = 4.0f;
|
float tessLevel = 3.0f;
|
||||||
} uboTC;
|
} uboTC;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
glm::mat4 projection;
|
glm::mat4 projection;
|
||||||
glm::mat4 model;
|
glm::mat4 model;
|
||||||
float tessAlpha = 0.9f;
|
float tessAlpha = 1.0f;
|
||||||
} uboTE;
|
} uboTE;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -71,8 +71,8 @@ public:
|
||||||
VkPipeline solidPassThrough;
|
VkPipeline solidPassThrough;
|
||||||
VkPipeline wirePassThrough;
|
VkPipeline wirePassThrough;
|
||||||
} pipelines;
|
} pipelines;
|
||||||
VkPipeline *pipelineLeft = &pipelines.solidPassThrough;
|
VkPipeline *pipelineLeft = &pipelines.wirePassThrough;
|
||||||
VkPipeline *pipelineRight = &pipelines.solid;
|
VkPipeline *pipelineRight = &pipelines.wire;
|
||||||
|
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet;
|
||||||
|
|
@ -80,9 +80,11 @@ public:
|
||||||
|
|
||||||
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
VulkanExample() : VulkanExampleBase(ENABLE_VALIDATION)
|
||||||
{
|
{
|
||||||
zoom = -1.5f;
|
zoom = -6.5f;
|
||||||
rotation = glm::vec3(-380.0f, 18.5f, 0.0f);
|
rotation = glm::vec3(-350.0f, 60.0f, 0.0f);
|
||||||
|
cameraPos = glm::vec3(-3.0f, 2.3f, 0.0f);
|
||||||
title = "Vulkan Example - Tessellation shader (PN Triangles)";
|
title = "Vulkan Example - Tessellation shader (PN Triangles)";
|
||||||
|
enableTextOverlay = true;
|
||||||
// Support for tessellation shaders is optional, so check first
|
// Support for tessellation shaders is optional, so check first
|
||||||
if (!deviceFeatures.tessellationShader)
|
if (!deviceFeatures.tessellationShader)
|
||||||
{
|
{
|
||||||
|
|
@ -128,7 +130,7 @@ public:
|
||||||
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
VkCommandBufferBeginInfo cmdBufInfo = vkTools::initializers::commandBufferBeginInfo();
|
||||||
|
|
||||||
VkClearValue clearValues[2];
|
VkClearValue clearValues[2];
|
||||||
clearValues[0].color = defaultClearColor;
|
clearValues[0].color = { {0.5f, 0.5f, 0.5f, 0.0f} };
|
||||||
clearValues[1].depthStencil = { 1.0f, 0 };
|
clearValues[1].depthStencil = { 1.0f, 0 };
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
|
VkRenderPassBeginInfo renderPassBeginInfo = vkTools::initializers::renderPassBeginInfo();
|
||||||
|
|
@ -140,32 +142,19 @@ public:
|
||||||
renderPassBeginInfo.clearValueCount = 2;
|
renderPassBeginInfo.clearValueCount = 2;
|
||||||
renderPassBeginInfo.pClearValues = clearValues;
|
renderPassBeginInfo.pClearValues = clearValues;
|
||||||
|
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
|
||||||
{
|
{
|
||||||
// Set target frame buffer
|
// Set target frame buffer
|
||||||
renderPassBeginInfo.framebuffer = frameBuffers[i];
|
renderPassBeginInfo.framebuffer = frameBuffers[i];
|
||||||
|
|
||||||
err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo);
|
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
VkViewport viewport = vkTools::initializers::viewport(
|
VkViewport viewport = vkTools::initializers::viewport(splitScreen ? (float)width / 2.0f : (float)width, (float)height, 0.0f, 1.0f);
|
||||||
splitScreen ? (float)width / 2.0f : (float)width,
|
|
||||||
(float)height,
|
|
||||||
0.0f,
|
|
||||||
1.0f
|
|
||||||
);
|
|
||||||
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
|
||||||
|
|
||||||
VkRect2D scissor = vkTools::initializers::rect2D(
|
VkRect2D scissor = vkTools::initializers::rect2D(width, height, 0, 0);
|
||||||
width,
|
|
||||||
height,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
|
||||||
|
|
||||||
vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f);
|
vkCmdSetLineWidth(drawCmdBuffers[i], 1.0f);
|
||||||
|
|
@ -190,47 +179,19 @@ public:
|
||||||
|
|
||||||
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
vkCmdEndRenderPass(drawCmdBuffers[i]);
|
||||||
|
|
||||||
err = vkEndCommandBuffer(drawCmdBuffers[i]);
|
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw()
|
|
||||||
{
|
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
// Get next image in the swap chain (back/front buffer)
|
|
||||||
err = swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer);
|
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
submitPostPresentBarrier(swapChain.buffers[currentBuffer].image);
|
|
||||||
|
|
||||||
// Command buffer to be sumitted to the queue
|
|
||||||
submitInfo.commandBufferCount = 1;
|
|
||||||
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
|
||||||
|
|
||||||
// Submit to queue
|
|
||||||
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
|
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
submitPrePresentBarrier(swapChain.buffers[currentBuffer].image);
|
|
||||||
|
|
||||||
err = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete);
|
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
err = vkQueueWaitIdle(queue);
|
|
||||||
assert(!err);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadMeshes()
|
void loadMeshes()
|
||||||
{
|
{
|
||||||
loadMesh(getAssetPath() + "models/lowpoly/bearmug.dae", &meshes.object, vertexLayout, 4.0f);
|
loadMesh(getAssetPath() + "models/lowpoly/deer.dae", &meshes.object, vertexLayout, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadTextures()
|
void loadTextures()
|
||||||
{
|
{
|
||||||
textureLoader->loadTexture(
|
textureLoader->loadTexture(
|
||||||
getAssetPath() + "textures/bearmug.ktx",
|
getAssetPath() + "textures/deer.ktx",
|
||||||
VK_FORMAT_BC3_UNORM_BLOCK,
|
VK_FORMAT_BC3_UNORM_BLOCK,
|
||||||
&textures.colorMap);
|
&textures.colorMap);
|
||||||
}
|
}
|
||||||
|
|
@ -295,8 +256,7 @@ public:
|
||||||
poolSizes.data(),
|
poolSizes.data(),
|
||||||
1);
|
1);
|
||||||
|
|
||||||
VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool);
|
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
|
||||||
assert(!vkRes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDescriptorSetLayout()
|
void setupDescriptorSetLayout()
|
||||||
|
|
@ -325,16 +285,14 @@ public:
|
||||||
setLayoutBindings.data(),
|
setLayoutBindings.data(),
|
||||||
setLayoutBindings.size());
|
setLayoutBindings.size());
|
||||||
|
|
||||||
VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout);
|
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, nullptr, &descriptorSetLayout));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo =
|
||||||
vkTools::initializers::pipelineLayoutCreateInfo(
|
vkTools::initializers::pipelineLayoutCreateInfo(
|
||||||
&descriptorSetLayout,
|
&descriptorSetLayout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout);
|
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDescriptorSet()
|
void setupDescriptorSet()
|
||||||
|
|
@ -345,8 +303,7 @@ public:
|
||||||
&descriptorSetLayout,
|
&descriptorSetLayout,
|
||||||
1);
|
1);
|
||||||
|
|
||||||
VkResult vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet);
|
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
|
||||||
assert(!vkRes);
|
|
||||||
|
|
||||||
VkDescriptorImageInfo texDescriptor =
|
VkDescriptorImageInfo texDescriptor =
|
||||||
vkTools::initializers::descriptorImageInfo(
|
vkTools::initializers::descriptorImageInfo(
|
||||||
|
|
@ -381,8 +338,6 @@ public:
|
||||||
|
|
||||||
void preparePipelines()
|
void preparePipelines()
|
||||||
{
|
{
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
|
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
|
||||||
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
|
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
|
||||||
VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
|
VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
|
||||||
|
|
@ -464,12 +419,10 @@ public:
|
||||||
|
|
||||||
// Tessellation pipelines
|
// Tessellation pipelines
|
||||||
// Solid
|
// Solid
|
||||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid);
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid));
|
||||||
assert(!err);
|
|
||||||
// Wireframe
|
// Wireframe
|
||||||
rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
|
rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
|
||||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wire);
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wire));
|
||||||
assert(!err);
|
|
||||||
|
|
||||||
// Pass through pipelines
|
// Pass through pipelines
|
||||||
// Load pass through tessellation shaders (Vert and frag are reused)
|
// Load pass through tessellation shaders (Vert and frag are reused)
|
||||||
|
|
@ -478,12 +431,10 @@ public:
|
||||||
|
|
||||||
// Solid
|
// Solid
|
||||||
rasterizationState.polygonMode = VK_POLYGON_MODE_FILL;
|
rasterizationState.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solidPassThrough);
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solidPassThrough));
|
||||||
assert(!err);
|
|
||||||
// Wireframe
|
// Wireframe
|
||||||
rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
|
rasterizationState.polygonMode = VK_POLYGON_MODE_LINE;
|
||||||
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wirePassThrough);
|
VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.wirePassThrough));
|
||||||
assert(!err);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare and initialize uniform buffer containing shader uniforms
|
// Prepare and initialize uniform buffer containing shader uniforms
|
||||||
|
|
@ -492,6 +443,7 @@ public:
|
||||||
// Tessellation evaluation shader uniform buffer
|
// Tessellation evaluation shader uniform buffer
|
||||||
createBuffer(
|
createBuffer(
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
sizeof(uboTE),
|
sizeof(uboTE),
|
||||||
&uboTE,
|
&uboTE,
|
||||||
&uniformDataTE.buffer,
|
&uniformDataTE.buffer,
|
||||||
|
|
@ -501,6 +453,7 @@ public:
|
||||||
// Tessellation control shader uniform buffer
|
// Tessellation control shader uniform buffer
|
||||||
createBuffer(
|
createBuffer(
|
||||||
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||||
sizeof(uboTC),
|
sizeof(uboTC),
|
||||||
&uboTC,
|
&uboTC,
|
||||||
&uniformDataTC.buffer,
|
&uniformDataTC.buffer,
|
||||||
|
|
@ -517,27 +470,36 @@ public:
|
||||||
uboTE.projection = glm::perspective(glm::radians(45.0f), (float)(width* ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f);
|
uboTE.projection = glm::perspective(glm::radians(45.0f), (float)(width* ((splitScreen) ? 0.5f : 1.0f)) / (float)height, 0.1f, 256.0f);
|
||||||
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, zoom));
|
viewMatrix = glm::translate(viewMatrix, glm::vec3(0.0f, 0.0f, zoom));
|
||||||
|
|
||||||
float offset = 0.5f;
|
|
||||||
int uboIndex = 1;
|
|
||||||
uboTE.model = glm::mat4();
|
uboTE.model = glm::mat4();
|
||||||
uboTE.model = viewMatrix * glm::translate(uboTE.model, glm::vec3(0, 0, 0));
|
uboTE.model = viewMatrix * glm::translate(uboTE.model, cameraPos);
|
||||||
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
|
||||||
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
uboTE.model = glm::rotate(uboTE.model, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
uint8_t *pData;
|
uint8_t *pData;
|
||||||
VkResult err = vkMapMemory(device, uniformDataTE.memory, 0, sizeof(uboTE), 0, (void **)&pData);
|
|
||||||
assert(!err);
|
// Tessellatione evaulation uniform block
|
||||||
|
VK_CHECK_RESULT(vkMapMemory(device, uniformDataTE.memory, 0, sizeof(uboTE), 0, (void **)&pData));
|
||||||
memcpy(pData, &uboTE, sizeof(uboTE));
|
memcpy(pData, &uboTE, sizeof(uboTE));
|
||||||
vkUnmapMemory(device, uniformDataTE.memory);
|
vkUnmapMemory(device, uniformDataTE.memory);
|
||||||
|
|
||||||
// Tessellation control
|
// Tessellation control uniform block
|
||||||
err = vkMapMemory(device, uniformDataTC.memory, 0, sizeof(uboTC), 0, (void **)&pData);
|
VK_CHECK_RESULT(vkMapMemory(device, uniformDataTC.memory, 0, sizeof(uboTC), 0, (void **)&pData));
|
||||||
assert(!err);
|
|
||||||
memcpy(pData, &uboTC, sizeof(uboTC));
|
memcpy(pData, &uboTC, sizeof(uboTC));
|
||||||
vkUnmapMemory(device, uniformDataTC.memory);
|
vkUnmapMemory(device, uniformDataTC.memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw()
|
||||||
|
{
|
||||||
|
VulkanExampleBase::prepareFrame();
|
||||||
|
|
||||||
|
submitInfo.commandBufferCount = 1;
|
||||||
|
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
|
||||||
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
|
||||||
|
|
||||||
|
VulkanExampleBase::submitFrame();
|
||||||
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
VulkanExampleBase::prepare();
|
VulkanExampleBase::prepare();
|
||||||
|
|
@ -567,12 +529,47 @@ public:
|
||||||
updateUniformBuffers();
|
updateUniformBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void keyPressed(uint32_t keyCode)
|
||||||
|
{
|
||||||
|
switch (keyCode)
|
||||||
|
{
|
||||||
|
case 0x6B:
|
||||||
|
case GAMEPAD_BUTTON_R1:
|
||||||
|
changeTessellationLevel(0.25);
|
||||||
|
break;
|
||||||
|
case 0x6D:
|
||||||
|
case GAMEPAD_BUTTON_L1:
|
||||||
|
changeTessellationLevel(-0.25);
|
||||||
|
break;
|
||||||
|
case 0x57:
|
||||||
|
case GAMEPAD_BUTTON_A:
|
||||||
|
togglePipelines();
|
||||||
|
break;
|
||||||
|
case 0x53:
|
||||||
|
case GAMEPAD_BUTTON_X:
|
||||||
|
toggleSplitScreen();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void getOverlayText(VulkanTextOverlay *textOverlay)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::setprecision(2) << std::fixed << uboTC.tessLevel;
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
textOverlay->addText("Tessellation level: " + ss.str() + " (Buttons L1/R1 to change)", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
|
||||||
|
#else
|
||||||
|
textOverlay->addText("Tessellation level: " + ss.str() + " (NUMPAD +/- to change)", 5.0f, 85.0f, VulkanTextOverlay::alignLeft);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void changeTessellationLevel(float delta)
|
void changeTessellationLevel(float delta)
|
||||||
{
|
{
|
||||||
uboTC.tessLevel += delta;
|
uboTC.tessLevel += delta;
|
||||||
// Clamp
|
// Clamp
|
||||||
uboTC.tessLevel = fmax(1.0f, fmin(uboTC.tessLevel, 32.0f));
|
uboTC.tessLevel = fmax(1.0f, fmin(uboTC.tessLevel, 32.0f));
|
||||||
updateUniformBuffers();
|
updateUniformBuffers();
|
||||||
|
updateTextOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void togglePipelines()
|
void togglePipelines()
|
||||||
|
|
@ -607,24 +604,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
if (vulkanExample != NULL)
|
if (vulkanExample != NULL)
|
||||||
{
|
{
|
||||||
vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam);
|
vulkanExample->handleMessages(hWnd, uMsg, wParam, lParam);
|
||||||
if (uMsg == WM_KEYDOWN)
|
|
||||||
{
|
|
||||||
switch (wParam)
|
|
||||||
{
|
|
||||||
case VK_ADD:
|
|
||||||
vulkanExample->changeTessellationLevel(0.25);
|
|
||||||
break;
|
|
||||||
case VK_SUBTRACT:
|
|
||||||
vulkanExample->changeTessellationLevel(-0.25);
|
|
||||||
break;
|
|
||||||
case 0x57:
|
|
||||||
vulkanExample->togglePipelines();
|
|
||||||
break;
|
|
||||||
case 0x53:
|
|
||||||
vulkanExample->toggleSplitScreen();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
|
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue