aboutsummaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2021-09-11 21:10:02 +0000
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2021-09-11 21:10:02 +0000
commit6035757b5ce0a795c9a96895721dbe621f379387 (patch)
treebbb578a7ca83aad5996e16414b038161ec45ac9c
parent0198478d81c9cc1d4a27f718982b748b2261b657 (diff)
tessellation, moves widget, smooth animation, wip
-rw-r--r--data/chess.blendbin9294348 -> 9299940 bytes
-rw-r--r--shaders/GBuffPbrInstanced.vert48
-rw-r--r--shaders/GBuffPbrTexArray.frag278
-rw-r--r--shaders/pntriangles.tesc92
-rw-r--r--shaders/pntriangles.tese97
-rw-r--r--shaders/shadow.geom20
-rw-r--r--src/Animation/AngleAnimation.cs41
-rw-r--r--src/Animation/Animation.cs39
-rw-r--r--src/Animation/AnimationTemplate.cs22
-rw-r--r--src/Animation/BezierPath.cs22
-rw-r--r--src/Animation/FloatAnimation.cs24
-rw-r--r--src/Animation/FloatAnimation2.cs60
-rw-r--r--src/Animation/MathHelper.cs32
-rw-r--r--src/Animation/Path.cs5
-rw-r--r--src/Animation/PathAnimation.cs36
-rw-r--r--src/Animation/ShakeAnimation.cs30
-rw-r--r--src/MoveHistoryWidget.cs201
-rw-r--r--src/Piece.cs12
-rw-r--r--src/VkChess.cs422
-rw-r--r--src/deferredPbrRendererBase.cs13
-rw-r--r--ui/chess.crow4
-rw-r--r--ui/winMoves.crow7
-rw-r--r--ui/winOptions.crow10
-rw-r--r--vkChess.net.csproj4
24 files changed, 983 insertions, 536 deletions
diff --git a/data/chess.blend b/data/chess.blend
index 7f2f5f5..7238e77 100644
--- a/data/chess.blend
+++ b/data/chess.blend
Binary files differ
diff --git a/shaders/GBuffPbrInstanced.vert b/shaders/GBuffPbrInstanced.vert
index 1095beb..12d2bd9 100644
--- a/shaders/GBuffPbrInstanced.vert
+++ b/shaders/GBuffPbrInstanced.vert
@@ -9,30 +9,36 @@ layout (location = 4) in vec4 inColor;
layout (location = 5) in mat4 inModel;
layout (set = 0, binding = 0) uniform UBO {
- mat4 projection;
- mat4 model;
- mat4 view;
+ mat4 projection;
+ mat4 model;
+ mat4 view;
} ubo;
-layout (location = 0) out vec3 outWorldPos;
-layout (location = 1) out vec3 outNormal;
-layout (location = 2) out vec2 outUV0;
-layout (location = 3) out vec2 outUV1;
-layout (location = 4) out vec4 outColor;
+layout (location = 0) out vec3 outNormal;
+layout (location = 1) out vec2 outUV0;
+layout (location = 2) out vec2 outUV1;
+layout (location = 3) out vec4 outColor;
-out gl_PerVertex
+/*out gl_PerVertex
{
- vec4 gl_Position;
-};
+ vec4 gl_Position;
+};*/
-void main()
-{
- vec4 locPos = ubo.model * inModel * vec4(inPos, 1.0);
- //locPos.y = -locPos.y;
- outNormal = normalize(transpose(inverse(mat3(ubo.model * inModel))) * inNormal);
- outColor = inColor;
- outWorldPos = locPos.xyz;
- outUV0 = inUV0;
- outUV1 = inUV1;
- gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);
+void main()
+{
+ /*vec4 locPos = ubo.model * inModel * vec4(inPos, 1.0);
+
+ outNormal = normalize(transpose(inverse(mat3(ubo.model * inModel))) * inNormal);
+ outColor = inColor;
+ outWorldPos = locPos.xyz;
+ outUV0 = inUV0;
+ outUV1 = inUV1;
+ gl_Position = ubo.projection * ubo.view * vec4(outWorldPos, 1.0);*/
+
+ outNormal = normalize(transpose(inverse(mat3(ubo.model * inModel))) * inNormal);
+ outUV0 = inUV0;
+ outUV1 = inUV1;
+ outColor = inColor;
+
+ gl_Position = ubo.model * inModel * vec4(inPos, 1.0);
}
diff --git a/shaders/GBuffPbrTexArray.frag b/shaders/GBuffPbrTexArray.frag
index e0d9f4f..c99e0d7 100644
--- a/shaders/GBuffPbrTexArray.frag
+++ b/shaders/GBuffPbrTexArray.frag
@@ -9,25 +9,25 @@ layout (constant_id = 1) const float FAR_PLANE = 256.0f;
layout (constant_id = 2) const int MAT_COUNT = 1;
struct Material {
- vec4 baseColorFactor;
- vec4 emissiveFactor;
- vec4 diffuseFactor;
- vec4 specularFactor;
-
- float workflow;
- uint tex0;
- uint tex1;
- int baseColorTex;
-
- int physicalDescTex;
- int normalTex;
- int occlusionTex;
- int emissiveTex;
-
- float metallicFactor;
- float roughnessFactor;
- float alphaMask;
- float alphaMaskCutoff;
+ vec4 baseColorFactor;
+ vec4 emissiveFactor;
+ vec4 diffuseFactor;
+ vec4 specularFactor;
+
+ float workflow;
+ uint tex0;
+ uint tex1;
+ int baseColorTex;
+
+ int physicalDescTex;
+ int normalTex;
+ int occlusionTex;
+ int emissiveTex;
+
+ float metallicFactor;
+ float roughnessFactor;
+ float alphaMask;
+ float alphaMaskCutoff;
};
const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.04;
@@ -50,13 +50,13 @@ layout (location = 3) in vec2 inUV1;
layout (location = 4) in vec4 inColor;
layout (set = 0, binding = 5) uniform UBOMaterials {
- Material materials[MAT_COUNT];
+ Material materials[MAT_COUNT];
};
layout (set = 0, binding = 7) uniform sampler2DArray texArray;
layout (push_constant) uniform PushCsts {
- layout(offset = 64)
- int materialIdx;
+ layout(offset = 64)
+ int materialIdx;
};
@@ -67,147 +67,147 @@ layout (location = 3) out vec4 outPos;
vec4 SRGBtoLINEAR(vec4 srgbIn)
{
- #ifdef MANUAL_SRGB
- #ifdef SRGB_FAST_APPROXIMATION
- vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
- #else //SRGB_FAST_APPROXIMATION
- vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
- vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
- #endif //SRGB_FAST_APPROXIMATION
- return vec4(linOut,srgbIn.w);;
- #else //MANUAL_SRGB
- return srgbIn;
- #endif //MANUAL_SRGB
+ #ifdef MANUAL_SRGB
+ #ifdef SRGB_FAST_APPROXIMATION
+ vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
+ #else //SRGB_FAST_APPROXIMATION
+ vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
+ vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
+ #endif //SRGB_FAST_APPROXIMATION
+ return vec4(linOut,srgbIn.w);;
+ #else //MANUAL_SRGB
+ return srgbIn;
+ #endif //MANUAL_SRGB
}
// Find the normal for this fragment, pulling either from a predefined normal map
// or from the interpolated mesh normal and tangent attributes.
vec3 getNormal()
{
- vec3 tangentNormal;
- // Perturb normal, see http://www.thetenthplanet.de/archives/1180
- if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL)
- tangentNormal = texture(texArray, vec3(inUV0, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
- else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL)
- tangentNormal = texture(texArray, vec3(inUV1, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
- else
- return normalize(inNormal);
-
- vec3 q1 = dFdx(inWorldPos);
- vec3 q2 = dFdy(inWorldPos);
- vec2 st1 = dFdx(inUV0);
- vec2 st2 = dFdy(inUV0);
+ vec3 tangentNormal;
+ // Perturb normal, see http://www.thetenthplanet.de/archives/1180
+ if ((materials[materialIdx].tex0 & MAP_NORMAL) == MAP_NORMAL)
+ tangentNormal = texture(texArray, vec3(inUV0, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
+ else if ((materials[materialIdx].tex1 & MAP_NORMAL) == MAP_NORMAL)
+ tangentNormal = texture(texArray, vec3(inUV1, materials[materialIdx].normalTex)).xyz * 2.0 - 1.0;
+ else
+ return normalize(inNormal);
+
+ vec3 q1 = dFdx(inWorldPos);
+ vec3 q2 = dFdy(inWorldPos);
+ vec2 st1 = dFdx(inUV0);
+ vec2 st2 = dFdy(inUV0);
- vec3 N = normalize(inNormal);
- vec3 T = normalize(q1 * st2.t - q2 * st1.t);
- vec3 B = -normalize(cross(N, T));
- mat3 TBN = mat3(T, B, N);
+ vec3 N = normalize(inNormal);
+ vec3 T = normalize(q1 * st2.t - q2 * st1.t);
+ vec3 B = -normalize(cross(N, T));
+ mat3 TBN = mat3(T, B, N);
- return normalize(TBN * tangentNormal);
+ return normalize(TBN * tangentNormal);
}
-// Gets metallic factor from specular glossiness workflow inputs
+// Gets metallic factor from specular glossiness workflow inputs
float convertMetallic(vec3 diffuse, vec3 specular, float maxSpecular) {
- float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b);
- float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b);
- if (perceivedSpecular < c_MinRoughness) {
- return 0.0;
- }
- float a = c_MinRoughness;
- float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness;
- float c = c_MinRoughness - perceivedSpecular;
- float D = max(b * b - 4.0 * a * c, 0.0);
- return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
+ float perceivedDiffuse = sqrt(0.299 * diffuse.r * diffuse.r + 0.587 * diffuse.g * diffuse.g + 0.114 * diffuse.b * diffuse.b);
+ float perceivedSpecular = sqrt(0.299 * specular.r * specular.r + 0.587 * specular.g * specular.g + 0.114 * specular.b * specular.b);
+ if (perceivedSpecular < c_MinRoughness) {
+ return 0.0;
+ }
+ float a = c_MinRoughness;
+ float b = perceivedDiffuse * (1.0 - maxSpecular) / (1.0 - c_MinRoughness) + perceivedSpecular - 2.0 * c_MinRoughness;
+ float c = c_MinRoughness - perceivedSpecular;
+ float D = max(b * b - 4.0 * a * c, 0.0);
+ return clamp((-b + sqrt(D)) / (2.0 * a), 0.0, 1.0);
}
float linearDepth(float depth)
{
- float z = depth * 2.0f - 1.0f;
- return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
+ float z = depth * 2.0f - 1.0f;
+ return (2.0f * NEAR_PLANE * FAR_PLANE) / (FAR_PLANE + NEAR_PLANE - z * (FAR_PLANE - NEAR_PLANE));
}
-void main()
+void main()
{
- float perceptualRoughness;
- float metallic;
- vec4 baseColor;
- vec3 emissive = vec3(0);
-
- baseColor = materials[materialIdx].baseColorFactor;
-
- if (materials[materialIdx].workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) {
- perceptualRoughness = materials[materialIdx].roughnessFactor;
- metallic = materials[materialIdx].metallicFactor;
- // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
- // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
- if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
- perceptualRoughness *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).g;
- metallic *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).b;
- }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
- perceptualRoughness *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).g;
- metallic *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).b;
- }
- perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
- metallic = clamp(metallic, 0.0, 1.0);
+ float perceptualRoughness;
+ float metallic;
+ vec4 baseColor;
+ vec3 emissive = vec3(0);
+
+ baseColor = materials[materialIdx].baseColorFactor;
+
+ if (materials[materialIdx].workflow == PBR_WORKFLOW_METALLIC_ROUGHNESS) {
+ perceptualRoughness = materials[materialIdx].roughnessFactor;
+ metallic = materials[materialIdx].metallicFactor;
+ // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
+ // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
+ if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
+ perceptualRoughness *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).g;
+ metallic *= texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).b;
+ }else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS){
+ perceptualRoughness *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).g;
+ metallic *= texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).b;
+ }
+ perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
+ metallic = clamp(metallic, 0.0, 1.0);
+
+ // The albedo may be defined from a base texture or a flat color
+ if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR)
+ baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
+ else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR)
+ baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].baseColorTex)));
+ }
+
+ if (materials[materialIdx].alphaMask == 1.0f) {
+ if (baseColor.a < materials[materialIdx].alphaMaskCutoff)
+ discard;
+ }
+
+ if (materials[materialIdx].workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) {
+ // Values from specular glossiness workflow are converted to metallic roughness
+ if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
+ perceptualRoughness = 1.0 - texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).a;
+ else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
+ perceptualRoughness = 1.0 - texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).a;
+ else
+ perceptualRoughness = 0.0;
+
+ const float epsilon = 1e-6;
+
+ vec4 diffuse = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
+ vec3 specular = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex))).rgb;
+
+ float maxSpecular = max(max(specular.r, specular.g), specular.b);
+
+ // Convert metallic value from specular glossiness inputs
+ metallic = convertMetallic(diffuse.rgb, specular, maxSpecular);
- // The albedo may be defined from a base texture or a flat color
- if ((materials[materialIdx].tex0 & MAP_COLOR) == MAP_COLOR)
- baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
- else if ((materials[materialIdx].tex1 & MAP_COLOR) == MAP_COLOR)
- baseColor *= SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].baseColorTex)));
- }
-
- if (materials[materialIdx].alphaMask == 1.0f) {
- if (baseColor.a < materials[materialIdx].alphaMaskCutoff)
- discard;
- }
+ vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * materials[materialIdx].diffuseFactor.rgb;
+ vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * materials[materialIdx].specularFactor.rgb;
+ baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a);
- if (materials[materialIdx].workflow == PBR_WORKFLOW_SPECULAR_GLOSINESS) {
- // Values from specular glossiness workflow are converted to metallic roughness
- if ((materials[materialIdx].tex0 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
- perceptualRoughness = 1.0 - texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex)).a;
- else if ((materials[materialIdx].tex1 & MAP_METALROUGHNESS) == MAP_METALROUGHNESS)
- perceptualRoughness = 1.0 - texture(texArray, vec3(inUV1, materials[materialIdx].physicalDescTex)).a;
- else
- perceptualRoughness = 0.0;
+ }
- const float epsilon = 1e-6;
+ baseColor *= inColor;
- vec4 diffuse = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].baseColorTex)));
- vec3 specular = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].physicalDescTex))).rgb;
+ const float u_OcclusionStrength = 1.0f;
+ const float u_EmissiveFactor = 1.0f;
+ float ao = 1.0f;
- float maxSpecular = max(max(specular.r, specular.g), specular.b);
+ if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE)
+ emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
+ else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE)
+ emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
- // Convert metallic value from specular glossiness inputs
- metallic = convertMetallic(diffuse.rgb, specular, maxSpecular);
+ if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO)
+ ao = texture(texArray, vec3(inUV0, materials[materialIdx].occlusionTex)).r;
+ else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO)
+ ao = texture(texArray, vec3(inUV1, materials[materialIdx].occlusionTex)).r;
- vec3 baseColorDiffusePart = diffuse.rgb * ((1.0 - maxSpecular) / (1 - c_MinRoughness) / max(1 - metallic, epsilon)) * materials[materialIdx].diffuseFactor.rgb;
- vec3 baseColorSpecularPart = specular - (vec3(c_MinRoughness) * (1 - metallic) * (1 / max(metallic, epsilon))) * materials[materialIdx].specularFactor.rgb;
- baseColor = vec4(mix(baseColorDiffusePart, baseColorSpecularPart, metallic * metallic), diffuse.a);
+ vec3 n = getNormal();
+ vec3 p = inWorldPos;
- }
-
- baseColor *= inColor;
-
- const float u_OcclusionStrength = 1.0f;
- const float u_EmissiveFactor = 1.0f;
- float ao = 1.0f;
-
- if ((materials[materialIdx].tex0 & MAP_EMISSIVE) == MAP_EMISSIVE)
- emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV0, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
- else if ((materials[materialIdx].tex1 & MAP_EMISSIVE) == MAP_EMISSIVE)
- emissive = SRGBtoLINEAR(texture(texArray, vec3(inUV1, materials[materialIdx].emissiveTex))).rgb * u_EmissiveFactor;
-
- if ((materials[materialIdx].tex0 & MAP_AO) == MAP_AO)
- ao = texture(texArray, vec3(inUV0, materials[materialIdx].occlusionTex)).r;
- else if ((materials[materialIdx].tex1 & MAP_AO) == MAP_AO)
- ao = texture(texArray, vec3(inUV1, materials[materialIdx].occlusionTex)).r;
-
- vec3 n = getNormal();
- vec3 p = inWorldPos;
-
- outColorRough = vec4 (baseColor.rgb, perceptualRoughness);
- outEmitMetal = vec4 (emissive, metallic);
- outN_AO = vec4 (n, ao);
- outPos = vec4 (p, linearDepth(gl_FragCoord.z));
+ outColorRough = vec4 (baseColor.rgb, perceptualRoughness);
+ outEmitMetal = vec4 (emissive, metallic);
+ outN_AO = vec4 (n, ao);
+ outPos = vec4 (p, linearDepth(gl_FragCoord.z));
} \ No newline at end of file
diff --git a/shaders/pntriangles.tesc b/shaders/pntriangles.tesc
new file mode 100644
index 0000000..21fd448
--- /dev/null
+++ b/shaders/pntriangles.tesc
@@ -0,0 +1,92 @@
+#version 450
+
+// PN patch data
+struct PnPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+};
+
+/*layout (set = 0, binding = 0) uniform UBO {
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+} ubo;*/
+
+const float tessLevel = 3.0;
+
+layout (vertices=3) out;
+
+layout (location = 0) in vec3 inNormal[];
+layout (location = 1) in vec2 inUV0[];
+layout (location = 2) in vec2 inUV1[];
+layout (location = 3) in vec4 inColor[];
+
+layout(location = 0) out vec3 outNormal[3];
+layout(location = 3) out vec2 outUV0[3];
+layout(location = 6) out vec2 outUV1[3];
+layout(location = 9) patch out vec4 outColor;
+layout(location = 10) out PnPatch outPatch[3];
+
+
+float wij(int i, int j)
+{
+ return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, inNormal[i]);
+}
+
+float vij(int i, int j)
+{
+ vec3 Pj_minus_Pi = gl_in[j].gl_Position.xyz
+ - gl_in[i].gl_Position.xyz;
+ vec3 Ni_plus_Nj = inNormal[i]+inNormal[j];
+ return 2.0*dot(Pj_minus_Pi, Ni_plus_Nj)/dot(Pj_minus_Pi, Pj_minus_Pi);
+}
+
+void main()
+{
+ // get data
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ outNormal[gl_InvocationID] = inNormal[gl_InvocationID];
+ outUV0[gl_InvocationID] = inUV0[gl_InvocationID];
+ outUV1[gl_InvocationID] = inUV1[gl_InvocationID];
+ outColor = inColor[gl_InvocationID];
+
+ // set base
+ float P0 = gl_in[0].gl_Position[gl_InvocationID];
+ float P1 = gl_in[1].gl_Position[gl_InvocationID];
+ float P2 = gl_in[2].gl_Position[gl_InvocationID];
+ float N0 = inNormal[0][gl_InvocationID];
+ float N1 = inNormal[1][gl_InvocationID];
+ float N2 = inNormal[2][gl_InvocationID];
+
+ // compute control points
+ outPatch[gl_InvocationID].b210 = (2.0*P0 + P1 - wij(0,1)*N0)/3.0;
+ outPatch[gl_InvocationID].b120 = (2.0*P1 + P0 - wij(1,0)*N1)/3.0;
+ outPatch[gl_InvocationID].b021 = (2.0*P1 + P2 - wij(1,2)*N1)/3.0;
+ outPatch[gl_InvocationID].b012 = (2.0*P2 + P1 - wij(2,1)*N2)/3.0;
+ outPatch[gl_InvocationID].b102 = (2.0*P2 + P0 - wij(2,0)*N2)/3.0;
+ outPatch[gl_InvocationID].b201 = (2.0*P0 + P2 - wij(0,2)*N0)/3.0;
+ float E = ( outPatch[gl_InvocationID].b210
+ + outPatch[gl_InvocationID].b120
+ + outPatch[gl_InvocationID].b021
+ + outPatch[gl_InvocationID].b012
+ + outPatch[gl_InvocationID].b102
+ + outPatch[gl_InvocationID].b201 ) / 6.0;
+ float V = (P0 + P1 + P2)/3.0;
+ outPatch[gl_InvocationID].b111 = E + (E - V)*0.5;
+ outPatch[gl_InvocationID].n110 = N0+N1-vij(0,1)*(P1-P0);
+ outPatch[gl_InvocationID].n011 = N1+N2-vij(1,2)*(P2-P1);
+ outPatch[gl_InvocationID].n101 = N2+N0-vij(2,0)*(P0-P2);
+
+ // set tess levels
+ gl_TessLevelOuter[gl_InvocationID] = tessLevel;
+ gl_TessLevelInner[0] = tessLevel;
+} \ No newline at end of file
diff --git a/shaders/pntriangles.tese b/shaders/pntriangles.tese
new file mode 100644
index 0000000..e8af9d8
--- /dev/null
+++ b/shaders/pntriangles.tese
@@ -0,0 +1,97 @@
+#version 450
+
+// PN patch data
+struct PnPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+};
+
+layout (set = 0, binding = 0) uniform UBO {
+ mat4 projection;
+ mat4 model;
+ mat4 view;
+} ubo;
+
+const float tessAlpha = 1.0;
+
+layout(triangles, fractional_odd_spacing, ccw) in;
+
+layout(location = 0) in vec3 inNormal[];
+layout(location = 3) in vec2 inUV0[];
+layout(location = 6) in vec2 inUV1[];
+layout(location = 9) patch in vec4 inColor;
+layout(location = 10) in PnPatch inPnPatch[];
+
+layout (location = 0) out vec3 outWorldPos;
+layout (location = 1) out vec3 outNormal;
+layout (location = 2) out vec2 outUV0;
+layout (location = 3) out vec2 outUV1;
+layout (location = 4) out vec4 outColor;
+
+#define uvw gl_TessCoord
+
+void main()
+{
+ vec3 uvwSquared = uvw * uvw;
+ vec3 uvwCubed = uvwSquared * uvw;
+
+ // extract control points
+ vec3 b210 = vec3(inPnPatch[0].b210, inPnPatch[1].b210, inPnPatch[2].b210);
+ vec3 b120 = vec3(inPnPatch[0].b120, inPnPatch[1].b120, inPnPatch[2].b120);
+ vec3 b021 = vec3(inPnPatch[0].b021, inPnPatch[1].b021, inPnPatch[2].b021);
+ vec3 b012 = vec3(inPnPatch[0].b012, inPnPatch[1].b012, inPnPatch[2].b012);
+ vec3 b102 = vec3(inPnPatch[0].b102, inPnPatch[1].b102, inPnPatch[2].b102);
+ vec3 b201 = vec3(inPnPatch[0].b201, inPnPatch[1].b201, inPnPatch[2].b201);
+ vec3 b111 = vec3(inPnPatch[0].b111, inPnPatch[1].b111, inPnPatch[2].b111);
+
+ // extract control normals
+ vec3 n110 = normalize(vec3(inPnPatch[0].n110, inPnPatch[1].n110, inPnPatch[2].n110));
+ vec3 n011 = normalize(vec3(inPnPatch[0].n011, inPnPatch[1].n011, inPnPatch[2].n011));
+ vec3 n101 = normalize(vec3(inPnPatch[0].n101, inPnPatch[1].n101, inPnPatch[2].n101));
+
+ // compute texcoords
+ outUV0 = gl_TessCoord[2]*inUV0[0] + gl_TessCoord[0]*inUV0[1] + gl_TessCoord[1]*inUV0[2];
+ outUV1 = gl_TessCoord[2]*inUV1[0] + gl_TessCoord[0]*inUV1[1] + gl_TessCoord[1]*inUV1[2];
+
+ // normal
+ // Barycentric normal
+ 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]
+ + n110*uvw[2]*uvw[0] + n011*uvw[0]*uvw[1]+ n101*uvw[2]*uvw[1];
+ outNormal = tessAlpha * pnNormal + (1.0 - tessAlpha) * barNormal;
+
+ // compute interpolated pos
+ 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;
+
+ // save some computations
+ uvwSquared *= 3.0;
+
+ // compute PN position
+ 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]
+ + b210*uvwSquared[2]*uvw[0]
+ + b120*uvwSquared[0]*uvw[2]
+ + b201*uvwSquared[2]*uvw[1]
+ + b021*uvwSquared[0]*uvw[1]
+ + b102*uvwSquared[1]*uvw[2]
+ + b012*uvwSquared[1]*uvw[0]
+ + b111*6.0*uvw[0]*uvw[1]*uvw[2];
+
+ outColor = inColor;
+ // final position and normal
+ outWorldPos = (1.0 - tessAlpha) * barPos + tessAlpha * pnPos;
+
+ gl_Position = ubo.projection * ubo.view * vec4 (outWorldPos, 1.0);
+} \ No newline at end of file
diff --git a/shaders/shadow.geom b/shaders/shadow.geom
index b3d66fc..c38bc4a 100644
--- a/shaders/shadow.geom
+++ b/shaders/shadow.geom
@@ -6,27 +6,27 @@ layout (triangles, invocations = NUM_LIGHTS) in;
layout (triangle_strip, max_vertices = 3) out;
struct Light {
- vec4 position;
- vec4 color;
- mat4 mvp;
+ vec4 position;
+ vec4 color;
+ mat4 mvp;
};
layout (set = 0, binding = 0) uniform UBO {
- mat4 projection;
- mat4 model;
- mat4 view;
+ mat4 projection;
+ mat4 model;
+ mat4 view;
};
layout (set = 0, binding = 1) uniform UBOLights {
- Light lights[NUM_LIGHTS];
+ Light lights[NUM_LIGHTS];
};
//layout (location = 0) in int inInstanceIndex[];
-void main()
+void main()
{
for (int i = 0; i < gl_in.length(); i++)
{
- gl_Layer = gl_InvocationID;
- gl_Position = lights[gl_InvocationID].mvp * model * gl_in[i].gl_Position;
+ gl_Layer = gl_InvocationID;
+ gl_Position = lights[gl_InvocationID].mvp * model * gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
diff --git a/src/Animation/AngleAnimation.cs b/src/Animation/AngleAnimation.cs
index 543fe13..02faef7 100644
--- a/src/Animation/AngleAnimation.cs
+++ b/src/Animation/AngleAnimation.cs
@@ -1,44 +1,19 @@
-//
-// AngleAnimation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
namespace vke
{
- public class AngleAnimation : FloatAnimation
+ public class AngleAnimation : FloatAnimation2
{
#region CTOR
- public AngleAnimation(Object instance, string PropertyName, float Target, float step = 0.1f) :
- base(instance,PropertyName,Target,step){}
+ public AngleAnimation(Object instance, string PropertyName, float Target, int stepCount = 20) :
+ base (instance,PropertyName,MathHelper.NormalizeAngle(Target),stepCount) {
+ initialValue = MathHelper.NormalizeAngle (initialValue);
+ }
#endregion
-
- public override void Process()
- {
- base.Process();
-
- float value = getValue();
- if (value < -MathHelper.TwoPi)
- setValue(value + MathHelper.TwoPi);
- else if (value >= MathHelper.TwoPi)
- setValue(value - MathHelper.TwoPi);
- }
}
}
diff --git a/src/Animation/Animation.cs b/src/Animation/Animation.cs
index 21b141a..6ca7af8 100644
--- a/src/Animation/Animation.cs
+++ b/src/Animation/Animation.cs
@@ -1,23 +1,6 @@
-//
-// Animation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
using System.Collections.Generic;
@@ -86,7 +69,7 @@ namespace vke
if (a.delayStartMs > 0)
a.timer.Start ();
-
+
AnimationList.Add (a);
}
@@ -102,14 +85,14 @@ namespace vke
// if (frame % 20 == 0){
// foreach (Player p in MagicEngine.CurrentEngine.Players) {
// foreach (CardInstance c in p.InPlay.Cards.Where(ci => ci.HasAbility(AbilityEnum.Flying) && ci.z < 0.4f)) {
-//
+//
// }
// }
// }
// #endregion
//Stopwatch animationTime = new Stopwatch();
//animationTime.Start();
-
+
const int maxAnim = 200000;
int count = 0;
@@ -118,9 +101,9 @@ namespace vke
if (anims.Count == 0)
anims = new Stack<Animation> (AnimationList);
}
-
+
while (anims.Count > 0 && count < maxAnim) {
- Animation a = anims.Pop ();
+ Animation a = anims.Pop ();
if (a == null)
continue;
if (a.timer.IsRunning) {
@@ -133,7 +116,7 @@ namespace vke
a.Process ();
count++;
}
-
+
//animationTime.Stop();
//Debug.WriteLine("animation: {0} ticks \t {1} ms ", animationTime.ElapsedTicks,animationTime.ElapsedMilliseconds);
}
@@ -141,7 +124,7 @@ namespace vke
{
for (int i = 0; i < AnimationList.Count; i++) {
Animation anim = AnimationList [i];
- if (anim == null) {
+ if (anim == null) {
continue;
}
if (anim.AnimatedInstance == instance && anim.propertyName == PropertyName) {
@@ -155,7 +138,7 @@ namespace vke
public virtual void Process () {}
public void CancelAnimation()
{
- //Debug.WriteLine("Cancel anim: " + this.ToString());
+ //Debug.WriteLine("Cancel anim: " + this.ToString());
AnimationList.Remove(this);
}
public void RaiseAnimationFinishedEvent()
@@ -168,7 +151,5 @@ namespace vke
{
Debug.WriteLine ("\t\tAnimation finished: " + a.ToString ());
}
-
-
}
}
diff --git a/src/Animation/AnimationTemplate.cs b/src/Animation/AnimationTemplate.cs
index 995eb0a..d5c784c 100644
--- a/src/Animation/AnimationTemplate.cs
+++ b/src/Animation/AnimationTemplate.cs
@@ -1,23 +1,7 @@
-//
-// FloatAnimation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
using MiscUtil;
using System.Reflection;
diff --git a/src/Animation/BezierPath.cs b/src/Animation/BezierPath.cs
index 5e381c4..a3126e3 100644
--- a/src/Animation/BezierPath.cs
+++ b/src/Animation/BezierPath.cs
@@ -1,23 +1,7 @@
-//
-// BezierPath.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2016 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
using System.Numerics;
diff --git a/src/Animation/FloatAnimation.cs b/src/Animation/FloatAnimation.cs
index d0d1fd9..a7e4bf7 100644
--- a/src/Animation/FloatAnimation.cs
+++ b/src/Animation/FloatAnimation.cs
@@ -1,23 +1,7 @@
-//
-// FloatAnimation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
namespace vke
@@ -48,7 +32,7 @@ namespace vke
Step = -Step;
}
else if (Step > 0)
- Step = -Step;
+ Step = -Step;
}
#endregion
diff --git a/src/Animation/FloatAnimation2.cs b/src/Animation/FloatAnimation2.cs
new file mode 100644
index 0000000..1d5c919
--- /dev/null
+++ b/src/Animation/FloatAnimation2.cs
@@ -0,0 +1,60 @@
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+
+namespace vke
+{
+ public class FloatAnimation2 : Animation
+ {
+
+ public float TargetValue;
+ protected float initialValue;
+ int stepCount, currentStep;
+
+ #region CTOR
+ public FloatAnimation2(Object instance, string _propertyName, float Target, int _stepCount = 20)
+ : base(instance, _propertyName)
+ {
+
+ TargetValue = Target;
+
+ float value = getValue();
+ initialValue = value;
+
+ stepCount = _stepCount;
+ }
+ #endregion
+
+ bool smooth = true;
+
+ float smoothedStep (float step) => (-MathF.Cos (step * MathF.PI) + 1)/2.0f;
+
+ public override void Process()
+ {
+
+ currentStep++;
+
+ float t = (float)currentStep / (float)stepCount;
+ if (smooth)
+ t = smoothedStep (t);
+
+ setValue (initialValue + t * (TargetValue - initialValue));
+
+ if (currentStep < stepCount)
+ return;
+
+ setValue(TargetValue);
+ AnimationList.Remove(this);
+ RaiseAnimationFinishedEvent ();
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}:->{1}:{2}",base.ToString(),TargetValue,stepCount);
+ }
+ }
+
+}
+
diff --git a/src/Animation/MathHelper.cs b/src/Animation/MathHelper.cs
index 6a066b6..35a3009 100644
--- a/src/Animation/MathHelper.cs
+++ b/src/Animation/MathHelper.cs
@@ -1,32 +1,16 @@
-//
-// MathHelper.cs
+// Copyright (c) 2019-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
-//
-// Copyright (c) 2019
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
using System;
namespace vke {
public static class MathHelper {
public const float Pi = (float)Math.PI;
public const float TwoPi = (float)Math.PI * 2;
+ public static float NormalizeAngle (float a) {
+ float tmp = a % MathHelper.TwoPi;
+ if (tmp < 0)
+ tmp += MathHelper.TwoPi;
+ return tmp;
+ }
}
}
diff --git a/src/Animation/Path.cs b/src/Animation/Path.cs
index 6847e99..1f04e09 100644
--- a/src/Animation/Path.cs
+++ b/src/Animation/Path.cs
@@ -1,4 +1,7 @@
-using System.Numerics;
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+using System.Numerics;
namespace vke {
public class Path
diff --git a/src/Animation/PathAnimation.cs b/src/Animation/PathAnimation.cs
index 60b00a3..54c30e9 100644
--- a/src/Animation/PathAnimation.cs
+++ b/src/Animation/PathAnimation.cs
@@ -1,33 +1,16 @@
-//
-// FloatAnimation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
using System.Numerics;
namespace vke
{
public class PathAnimation : Animation<Vector3>
- {
+ {
Path path;
- int stepCount;
- int currentStep;
+ int stepCount, currentStep;
#region CTOR
public PathAnimation(Object instance, string _propertyName, Path _path, int _stepCount = 20)
@@ -39,17 +22,24 @@ namespace vke
#endregion
+ bool smooth = true;
+
+ float smoothedStep (float step) => (-MathF.Cos (step * MathF.PI) + 1)/2.0f;
+
public override void Process()
{
currentStep++;
float t = (float)currentStep / (float)stepCount;
+ if (smooth)
+ t = smoothedStep (t);
+
Vector3 pos = path.GetStep (t);
setValue(pos);
if (currentStep < stepCount)
return;
-
+
AnimationList.Remove(this);
RaiseAnimationFinishedEvent ();
}
diff --git a/src/Animation/ShakeAnimation.cs b/src/Animation/ShakeAnimation.cs
index 26172b5..37a089b 100644
--- a/src/Animation/ShakeAnimation.cs
+++ b/src/Animation/ShakeAnimation.cs
@@ -1,23 +1,7 @@
-//
-// ShakeAnimation.cs
+// Copyright (c) 2015-2021 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2015 jp
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
using System;
namespace vke
@@ -32,8 +16,8 @@ namespace vke
#region CTOR
public ShakeAnimation(
- Object instance,
- string _propertyName,
+ Object instance,
+ string _propertyName,
float lowBound, float highBound)
: base(instance, _propertyName)
{
@@ -50,10 +34,10 @@ namespace vke
public override void Process ()
{
- float value = getValue ();
+ float value = getValue ();
float step = stepMin + (float)random.NextDouble () * stepMax;
- if (rising) {
+ if (rising) {
value += step;
if (value > HighBound) {
value = HighBound;
diff --git a/src/MoveHistoryWidget.cs b/src/MoveHistoryWidget.cs
new file mode 100644
index 0000000..963a89c
--- /dev/null
+++ b/src/MoveHistoryWidget.cs
@@ -0,0 +1,201 @@
+// Copyright (c) 2020 Jean-Philippe Bruyère <jp_bruyere@hotmail.com>
+//
+// This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
+
+using System;
+using System.Xml.Serialization;
+using System.ComponentModel;
+using System.Collections;
+using Crow.Drawing;
+using Crow;
+using System.Collections.Generic;
+
+namespace vkChess
+{
+ public class MoveHistoryWidget : ScrollingObject
+ {
+ IList<string> moves;
+ int visibleLines = 1;
+ FontExtents fe;
+
+ public virtual IList<string> Moves {
+ get => moves;
+ set {
+ if (moves == value)
+ return;
+ if (moves is ObservableList<string> ol) {
+ ol.ListAdd -= Lines_ListAdd;
+ ol.ListRemove -= Lines_ListRemove;
+ ol.ListClear -= Lines_ListClear;
+ }
+ moves = value;
+ if (moves is ObservableList<string> olNew) {
+ olNew.ListAdd += Lines_ListAdd;
+ olNew.ListRemove += Lines_ListRemove;
+ olNew.ListClear += Lines_ListClear;
+
+ updateMaxScrollAndFocusedIndices ();
+ } else
+ ScrollY = MaxScrollY = CurrentMoveIndex = hoverMoveIdx = 0;
+ NotifyValueChanged ("Moves", moves);
+ RegisterForGraphicUpdate ();
+ }
+ }
+ void updateMaxScrollAndFocusedIndices () {
+ MaxScrollY = moves.Count - visibleLines;
+ ScrollY = 0;
+ CurrentMoveIndex = 0;
+ hoverMoveIdx = - 1;
+ }
+ void Lines_ListAdd (object sender, ListChangedEventArg e)
+ {
+ updateMaxScrollAndFocusedIndices ();
+ RegisterForRedraw ();
+ }
+
+ void Lines_ListRemove (object sender, ListChangedEventArg e)
+ {
+ updateMaxScrollAndFocusedIndices ();
+ RegisterForRedraw ();
+ }
+ void Lines_ListClear (object sender, ListClearEventArg e)
+ {
+ ScrollY = MaxScrollY = CurrentMoveIndex = 0;
+ hoverMoveIdx = -1;
+ RegisterForRedraw ();
+ }
+
+
+
+ public override void OnLayoutChanges (LayoutingType layoutType)
+ {
+ base.OnLayoutChanges (layoutType);
+
+ if (layoutType == LayoutingType.Height) {
+ using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) {
+ using (Context gr = new Context (img)) {
+ //Cairo.FontFace cf = gr.GetContextFontFace ();
+ this.setFontForContext (gr);
+ fe = gr.FontExtents;
+ }
+ }
+ lineHeight = fe.Height + 2 * moveMargin + moveSpacing;
+ visibleLines = (int)Math.Floor ((double)ClientRectangle.Height / lineHeight);
+ MaxScrollY = moves == null ? 0 : moves.Count - visibleLines;
+ }
+ }
+ double lineHeight = 1;
+
+ int moveMargin = 3, moveSpacing = 2;
+
+ int hoverMoveIdx = -1, currentMoveIndex;
+
+ public int CurrentMoveIndex {
+ get => currentMoveIndex;
+ set {
+ if (currentMoveIndex == value)
+ return;
+ currentMoveIndex = value;
+ NotifyValueChangedAuto (currentMoveIndex);
+ RegisterForRedraw ();
+ }
+ }
+
+ protected override void onDraw (Context gr)
+ {
+ base.onDraw (gr);
+
+ if (moves == null)
+ return;
+
+ gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight);
+ gr.SetFontSize (Font.Size);
+
+ Rectangle r = ClientRectangle;
+
+
+ double y = ClientRectangle.Y;
+ double x = ClientRectangle.X - ScrollX;
+
+ string[] movesCopy;
+ lock (moves) {
+ movesCopy = new string[moves.Count];
+ moves.CopyTo (movesCopy, 0);
+ }
+
+
+ for (int i = 0; i < visibleLines; i++) {
+ int idx = i + ScrollY;
+ int mi = movesCopy.Length - (1 + idx);
+ if (mi < 0)
+ break;
+ string m = movesCopy[mi];
+ Color bg;
+ Color fg;
+ if (mi % 2 > 0) {
+ if (idx == currentMoveIndex) {
+ bg = Colors.DarkBlue;
+ fg = Colors.White;
+ } else if (idx == hoverMoveIdx) {
+ bg = Colors.Black;
+ fg = Colors.White;
+ } else {
+ bg = Colors.Black;
+ fg = Colors.DimGrey;
+ }
+ } else {
+ if (idx == currentMoveIndex) {
+ bg = Colors.Blue;
+ fg = Colors.White;
+ } else if (idx == hoverMoveIdx) {
+ bg = Colors.White;
+ fg = Colors.Black;
+ } else {
+ bg = Colors.Grey;
+ fg = Colors.DarkGrey;
+ }
+ }
+
+ gr.SetSource (bg);
+ gr.Rectangle (x, y, (double)r.Width, lineHeight - moveSpacing);
+ gr.Fill ();
+
+ y += moveMargin;
+
+ gr.SetSource (fg);
+ TextExtents te = gr.TextExtents(m);
+ gr.MoveTo (x + 0.5 * (r.Width - te.Width), y + fe.Ascent);
+ gr.ShowText (m);
+ y += fe.Height + moveMargin + moveSpacing;
+ }
+ }
+ public override void onMouseMove(object sender, MouseMoveEventArgs e)
+ {
+ base.onMouseMove(sender, e);
+
+ if (Moves == null) {
+ hoverMoveIdx = -1;
+ return;
+ }
+
+ PointD mouseLocalPos = ScreenPointToLocal (e.Position);
+
+ hoverMoveIdx = ScrollY + (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / lineHeight)), moves.Count - 1);
+ RegisterForRedraw ();
+ }
+ public override void onMouseClick(object sender, MouseButtonEventArgs e)
+ {
+ if (e.Button == Glfw.MouseButton.Left) {
+ CurrentMoveIndex = hoverMoveIdx;
+ e.Handled = true;
+ }
+ base.onMouseClick(sender, e);
+ }
+ public override void onMouseLeave(object sender, MouseMoveEventArgs e)
+ {
+ hoverMoveIdx = -1;
+ base.onMouseLeave(sender, e);
+ }
+ }
+}
+
diff --git a/src/Piece.cs b/src/Piece.cs
index cc10324..f56a8c0 100644
--- a/src/Piece.cs
+++ b/src/Piece.cs
@@ -80,7 +80,7 @@ namespace vkChess {
public Crow.Point BoardCell;
public Vector3 Position {
- get { return position; }
+ get => position;
set {
if (value == position)
return;
@@ -90,7 +90,7 @@ namespace vkChess {
}
public float X {
- get { return position.X; }
+ get => position.X;
set {
if (position.X == value)
return;
@@ -99,7 +99,7 @@ namespace vkChess {
}
}
public float Y {
- get { return position.Y; }
+ get => position.Y;
set {
if (position.Y == value)
return;
@@ -108,7 +108,7 @@ namespace vkChess {
}
}
public float Z {
- get { return position.Z; }
+ get => position.Z;
set {
if (position.Z == value)
return;
@@ -117,7 +117,7 @@ namespace vkChess {
}
}
public float XAngle {
- get { return xAngle; }
+ get => xAngle;
set {
if (xAngle == value)
return;
@@ -126,7 +126,7 @@ namespace vkChess {
}
}
public float ZAngle {
- get { return zAngle; }
+ get => zAngle;
set {
if (zAngle == value)
return;
diff --git a/src/VkChess.cs b/src/VkChess.cs
index ef7039b..f83b1d6 100644
--- a/src/VkChess.cs
+++ b/src/VkChess.cs
@@ -10,6 +10,8 @@ using vke.glTF;
using Glfw;
using Vulkan;
using System.Reflection;
+using System.Net;
+using System.Runtime.InteropServices;
namespace vkChess
{
@@ -50,6 +52,24 @@ namespace vkChess
using (VkChess app = new VkChess ())
app.Run ();
}
+
+ public CommandGroup Commands => new CommandGroup (
+ new CommandGroup ("Menu",
+ new Command ("New Game", () => loadWindow ("ui/newGame.crow", this)),
+ new Command ("Save", () => loadWindow ("ui/newGame.crow", this)),
+ new Command ("Load", () => loadWindow ("ui/newGame.crow", this)),
+ new Command ("Options", () => loadWindow ("ui/winOptions.crow", this)),
+ new Command ("Moves", () => loadWindow ("ui/winMoves.crow", this)),
+#if DEBUG
+ new Command ("Log", () => loadWindow ("ui/winLog.crow", this)),
+#endif
+ new Command ("Quit", () => Close())
+ ),
+ new Command ("Undo", () => undo())
+ //new Command ("Redo", () => Close())
+ );
+
+
public override string [] EnabledInstanceExtensions => new string [] {
#if DEBUG
//Ext.I.VK_EXT_debug_utils,
@@ -70,7 +90,9 @@ namespace vkChess
#if PIPELINE_STATS
enabled_features.pipelineStatisticsQuery = available_features.pipelineStatisticsQuery;
#endif
+ enabled_features.tessellationShader = available_features.tessellationShader;
}
+
#if PIPELINE_STATS
PipelineStatisticsQueryPool statPool;
TimestampQueryPool timestampQPool;
@@ -84,79 +106,37 @@ namespace vkChess
#if DEBUG
//vke.DebugUtils.Messenger dbgmsg;
#endif
- protected override void CreateRenderPass () {
- renderPass = new RenderPass (dev, swapChain.ColorFormat, DeferredPbrRendererBase.NUM_SAMPLES);
- }
+
+ Queue transferQ;
GraphicPipeline plToneMap;
DescriptorSetLayout dslToneMap;
- protected override void CreateDescriptors () {
- dsPool = EnableReflections ?
- new DescriptorPool (dev, 1,
- new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 4),
- new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 1)) :
- new DescriptorPool (dev, 1,
- new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 2));
- descSet = dsPool.Allocate (dslToneMap);
- }
- protected override void CreatePipeline () {
- using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, DeferredPbrRendererBase.NUM_SAMPLES)) {
- if (DeferredPbrRendererBase.NUM_SAMPLES != VkSampleCountFlags.SampleCount1) {
- cfg.multisampleState.sampleShadingEnable = true;
- cfg.multisampleState.minSampleShading = 0.5f;
- }
- dslToneMap = new DescriptorSetLayout (dev, 0,
- new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
- new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)
- );
- if (EnableReflections) {
- dslToneMap.Bindings.AddRange ( new VkDescriptorSetLayoutBinding[] {
- new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
- new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
- new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)
- });
- cfg.Layout = new PipelineLayout (dev,
- new VkPushConstantRange (VkShaderStageFlags.Fragment, 20u), dslToneMap);
- } else
- cfg.Layout = new PipelineLayout (dev,
- new VkPushConstantRange (VkShaderStageFlags.Fragment, 8u), dslToneMap);
-
- cfg.RenderPass = renderPass;
- cfg.AddShaders (
- new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"),
- new ShaderInfo (dev, VkShaderStageFlags.Fragment,
- EnableReflections ?
- "#vkChess.net.tone_mapping_ssr.frag.spv" : "#vkChess.net.tone_mapping.frag.spv")
- );
-
- plToneMap = new GraphicPipeline (cfg);
-
+ bool updateRendererDescriptors;
+ public VkSampleCountFlags AvailableSampleCount => ~phy.Limits.framebufferColorSampleCounts;
+ public VkSampleCountFlags maxSampleCount {
+ get {
+ int sampleMask = (int)phy.Limits.framebufferColorSampleCounts;
+ for (int i = 6; i > 0; i--)
+ if ((sampleMask >> i) > 0)
+ return (VkSampleCountFlags)Math.Pow(2, i);
+ return VkSampleCountFlags.SampleCount1;
}
}
- protected override void recordUICmd (PrimaryCommandBuffer cmd, int imageIndex) {
- renderPass.Begin(cmd, frameBuffers[imageIndex]);
-
- cmd.SetViewport (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height);
- cmd.SetScissor (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height);
-
- if (EnableReflections) {
- cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 16, new float[] { Exposure, Gamma, SSRStep, SSRThreshold }, 0);
- cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 4, SSRMaxStepCount, 16);
- } else
- cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 16, new float[] { Exposure, Gamma}, 0);
-
- plToneMap.BindDescriptorSet (cmd, descSet);
- plToneMap.Bind (cmd);
- cmd.Draw (3, 1, 0, 0);
-
- renderPass.End (cmd);
+ protected override void createQueues () {
+ base.createQueues ();
+ transferQ = new Queue (dev, VkQueueFlags.Transfer);
}
protected override void initVulkan () {
- DeferredPbrRendererBase.NUM_SAMPLES = SampleCount;
-
initLog ();
base.initVulkan ();
+ iFace.SetWindowIcon ("#Crow.Icons.crow.png");
+
+ VkSampleCountFlags maxSamples = maxSampleCount;
+ if (SampleCount > maxSamples)
+ SampleCount = maxSamples;
+ DeferredPbrRendererBase.NUM_SAMPLES = SampleCount;
+
#if DEBUG
/*dbgmsg = new vke.DebugUtils.Messenger (instance, VkDebugUtilsMessageTypeFlagsEXT.PerformanceEXT | VkDebugUtilsMessageTypeFlagsEXT.ValidationEXT | VkDebugUtilsMessageTypeFlagsEXT.GeneralEXT,
VkDebugUtilsMessageSeverityFlagsEXT.InfoEXT |
@@ -174,7 +154,6 @@ namespace vkChess
timestampQPool = new TimestampQueryPool (dev);
#endif
- //Configuration.Global.Set ("StockfishPath", "/usr/games/stockfish");
cmds = cmdPool.AllocateCommandBuffer (swapChain.ImageCount);
@@ -189,7 +168,7 @@ namespace vkChess
// Matrix4x4.CreateScale(1f / Math.Max(Math.Max(renderer.modelAABB.Width, renderer.modelAABB.Height), renderer.modelAABB.Depth));
if (EnableReflections) {
- DescriptorSetWrites dsw = new DescriptorSetWrites (descSet,
+ DescriptorSetWrites dsw = new DescriptorSetWrites (descriptorSet,
dslToneMap.Bindings[4]);
dsw.Write (dev, renderer.uboMatrices.Descriptor);
}
@@ -214,11 +193,89 @@ namespace vkChess
camera.AspectRatio = Width / Height;
camera.Model = Matrix4x4.CreateScale (0.5f);
}
- Queue transferQ;
- protected override void createQueues () {
- base.createQueues ();
- transferQ = new Queue (dev, VkQueueFlags.Transfer);
+
+ #region VKCrowWindow pipeline overrides
+ protected override void CreateRenderPass () {
+ renderPass = new RenderPass (dev, swapChain.ColorFormat, DeferredPbrRendererBase.NUM_SAMPLES);
+ }
+ protected override void CreateAndAllocateDescriptors () {
+ descriptorPool = EnableReflections ?
+ new DescriptorPool (dev, 1,
+ new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 4),
+ new VkDescriptorPoolSize (VkDescriptorType.UniformBuffer, 1)) :
+ new DescriptorPool (dev, 1,
+ new VkDescriptorPoolSize (VkDescriptorType.CombinedImageSampler, 2));
+ descriptorSet = descriptorPool.Allocate (dslToneMap);
}
+ protected override void CreatePipeline () {
+ using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault (VkPrimitiveTopology.TriangleList, DeferredPbrRendererBase.NUM_SAMPLES)) {
+ if (DeferredPbrRendererBase.NUM_SAMPLES != VkSampleCountFlags.SampleCount1) {
+ cfg.multisampleState.sampleShadingEnable = true;
+ cfg.multisampleState.minSampleShading = 0.5f;
+ }
+ dslToneMap = new DescriptorSetLayout (dev, 0,
+ new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
+ new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler)
+ );
+ if (EnableReflections) {
+ dslToneMap.Bindings.AddRange ( new VkDescriptorSetLayoutBinding[] {
+ new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
+ new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),
+ new VkDescriptorSetLayoutBinding (4, VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer)
+ });
+ cfg.Layout = new PipelineLayout (dev,
+ new VkPushConstantRange (VkShaderStageFlags.Fragment, 20u), dslToneMap);
+ } else
+ cfg.Layout = new PipelineLayout (dev,
+ new VkPushConstantRange (VkShaderStageFlags.Fragment, 8u), dslToneMap);
+
+ cfg.RenderPass = renderPass;
+ cfg.AddShaders (
+ new ShaderInfo (dev, VkShaderStageFlags.Vertex, "#vke.FullScreenQuad.vert.spv"),
+ new ShaderInfo (dev, VkShaderStageFlags.Fragment,
+ EnableReflections ?
+ "#vkChess.net.tone_mapping_ssr.frag.spv" : "#vkChess.net.tone_mapping.frag.spv")
+ );
+
+ plToneMap = new GraphicPipeline (cfg);
+
+ }
+ }
+ protected override void buildCommandBuffer (PrimaryCommandBuffer cmd, int imageIndex) {
+ if (updateRendererDescriptors) {
+ if (EnableReflections) {
+ DescriptorSetWrites dsw = new DescriptorSetWrites (descriptorSet,
+ dslToneMap.Bindings[1], dslToneMap.Bindings[2], dslToneMap.Bindings[3]);
+ dsw.Write (dev, renderer.HDROutput.Descriptor, renderer.GBuffPosDepthOutput.Descriptor, renderer.GBuffN_AO.Descriptor);
+ } else {
+ DescriptorSetWrites dsw = new DescriptorSetWrites (descriptorSet, dslToneMap.Bindings[1]);
+ dsw.Write (dev, renderer.HDROutput.Descriptor);
+ }
+ updateRendererDescriptors = false;
+ }
+
+ renderer?.recordDraw (cmd, imageIndex, instanceBuff, instancedCmds?.ToArray ());
+
+
+ renderPass.Begin(cmd, frameBuffers[imageIndex]);
+
+ cmd.SetViewport (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height);
+ cmd.SetScissor (frameBuffers[imageIndex].Width, frameBuffers[imageIndex].Height);
+
+ if (EnableReflections) {
+ cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 16, new float[] { Exposure, Gamma, SSRStep, SSRThreshold }, 0);
+ cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 4, SSRMaxStepCount, 16);
+ } else
+ cmd.PushConstant (plToneMap.Layout, VkShaderStageFlags.Fragment, 16, new float[] { Exposure, Gamma}, 0);
+
+ plToneMap.BindDescriptorSet (cmd, descriptorSet);
+ plToneMap.Bind (cmd);
+ cmd.Draw (3, 1, 0, 0);
+
+ renderPass.End (cmd);
+ }
+ #endregion
+
string [] cubemapPathes = {
"data/textures/papermill.ktx",
@@ -258,27 +315,6 @@ namespace vkChess
public PbrModelTexArray.Material[] Materials =>
(renderer.model as PbrModelTexArray).materials;
-
- void buildCommandBuffers () {
- dev.WaitIdle ();
-
- cmdPool.Reset (); //VkCommandPoolResetFlags.ReleaseResources);
-
- for (int i = 0; i < swapChain.ImageCount; ++i) {
- cmds [i].Start ();
-#if PIPELINE_STATS
- statPool.Begin (cmds[i]);
- renderer.recordDraw (cmds[i], i, instanceBuff, instancedCmds?.ToArray ());
- statPool.End (cmds[i]);
-#else
- renderer?.recordDraw (cmds [i], i, instanceBuff, instancedCmds?.ToArray ());
-
- recordUICmd (cmds[i], i);
-#endif
- cmds [i].End ();
- }
- }
-
public override void UpdateView () {
dev.WaitIdle ();
if (updateViewRequested) {
@@ -296,7 +332,6 @@ namespace vkChess
const int fpsAccumLimit = 20;
-
public override void Update () {
base.Update ();
@@ -342,19 +377,11 @@ namespace vkChess
}
protected override void OnResize () {
- base.OnResize ();
renderer.Resize ();
- if (EnableReflections) {
- DescriptorSetWrites dsw = new DescriptorSetWrites (descSet,
- dslToneMap.Bindings[1], dslToneMap.Bindings[2], dslToneMap.Bindings[3]);
- dsw.Write (dev, renderer.HDROutput.Descriptor, renderer.GBuffPosDepthOutput.Descriptor, renderer.GBuffN_AO.Descriptor);
- } else {
- DescriptorSetWrites dsw = new DescriptorSetWrites (descSet, dslToneMap.Bindings[1]);
- dsw.Write (dev, renderer.HDROutput.Descriptor);
- }
+ updateRendererDescriptors = true;
+ base.OnResize ();
- buildCommandBuffers ();
updateViewRequested = true;
}
@@ -412,9 +439,7 @@ namespace vkChess
CameraPosition = new Vector3 (camera.Position.X, camera.Position.Y, -camera.Position.Z);
}
protected override void onMouseMove (double xPos, double yPos) {
- base.onMouseMove (xPos, yPos);
-
- if (MouseIsInInterface)
+ if (iFace.OnMouseMove ((int)xPos, (int)yPos))
return;
double diffX = lastMouseX - xPos;
@@ -454,9 +479,9 @@ namespace vkChess
NotifyValueChanged ("DebugCurCellPos", p?.BoardCell);
if (p != null) {
- NotifyValueChanged ("DebugCurCell", getChessCell (p.BoardCell.X, p.BoardCell.Y));
+ NotifyValueChanged ("DebugCurCell", (object)getChessCell (p.BoardCell.X, p.BoardCell.Y));
}else
- NotifyValueChanged ("DebugCurCell", "");
+ NotifyValueChanged ("DebugCurCell", (object)"");
}
protected override void onMouseButtonDown (MouseButton button) {
base.onMouseButtonDown (button);
@@ -619,13 +644,15 @@ namespace vkChess
EnableHint = false;
//if (currentState != GameState.Pad && currentState != GameState.Checkmate && !playerIsAi (CurrentPlayer) && playerIsAi (Opponent))//undo ai move
- if (!playerIsAi (CurrentPlayer) && playerIsAi (Opponent))
+ if (currentState < GameState.Pad || (!playerIsAi (CurrentPlayer) && playerIsAi (Opponent)))
undoLastMove ();
undoLastMove ();
startTurn ();
NotifyValueChanged ("board", board);
+ NotifyValueChanged ("CurrentState", currentState);
+ NotifyValueChanged ("CurrentStateColor", CurrentStateColor);
EnableHint = hintIsEnabled;
}
@@ -645,20 +672,6 @@ namespace vkChess
};
}
- public CommandGroup Commands => new CommandGroup (
- new CommandGroup ("Menu",
- new Command ("New Game", () => loadWindow ("ui/newGame.crow", this)),
- new Command ("Save", () => loadWindow ("ui/newGame.crow", this)),
- new Command ("Load", () => loadWindow ("ui/newGame.crow", this)),
- new Command ("Options", () => loadWindow ("ui/winOptions.crow", this)),
-#if DEBUG
- new Command ("Log", () => loadWindow ("ui/winLog.crow", this)),
-#endif
- new Command ("Quit", () => Close())
- ),
- new Command ("Undo", () => undo())
- //new Command ("Redo", () => Close())
- );
void terminateCurrentGame () {
if (CurrentState < GameState.Play)
return;
@@ -671,10 +684,6 @@ namespace vkChess
System.Threading.Thread.Sleep (10);
}
}
- public float CameraAngleY {
- get => CameraRotation.Y;
- set => CameraRotation = new Vector3(CameraRotation.X, value, CameraRotation.Z);
- }
void onNewWhiteGame (object sender, MouseButtonEventArgs e) {
closeWindow ("ui/newGame.crow");
if (CurrentState < GameState.Play)
@@ -696,7 +705,7 @@ namespace vkChess
if (enableHint)
sendToStockfish ("go infinite");
- Animation.StartAnimation (new AngleAnimation (this, "CameraAngleY", 0, 0.15f));
+ Animation.StartAnimation (new AngleAnimation (this, "CameraAngleY", 0, 50));
}
void onNewBlackGame (object sender, MouseButtonEventArgs e) {
closeWindow ("ui/newGame.crow");
@@ -721,7 +730,7 @@ namespace vkChess
else
sendToStockfish ("go depth 1");
- Animation.StartAnimation (new AngleAnimation (this, "CameraAngleY", MathHelper.Pi, 0.15f));
+ Animation.StartAnimation (new AngleAnimation (this, "CameraAngleY", MathHelper.Pi, 50));
}
void onPromoteToQueenClick (object sender, MouseButtonEventArgs e) {
closeWindow ("ui/promote.crow");
@@ -867,7 +876,6 @@ namespace vkChess
}
}
- float normalizeAngle (float a) => a - (int)(a / MathHelper.TwoPi);
public Vector3 CameraRotation {
get => ExtensionMethods.ParseVec3 (Configuration.Global.Get<string> ("CameraRotation", "<0.6,0,0>"));
set {
@@ -875,9 +883,9 @@ namespace vkChess
return;
Vector3 tmp = new Vector3 (
- normalizeAngle (value.X),
- normalizeAngle (value.Y),
- normalizeAngle (value.Z)
+ MathHelper.NormalizeAngle (value.X),
+ MathHelper.NormalizeAngle (value.Y),
+ MathHelper.NormalizeAngle (value.Z)
);
Configuration.Global.Set ("CameraRotation", tmp.ToString());
NotifyValueChanged ("CameraRotation", tmp);
@@ -885,6 +893,10 @@ namespace vkChess
updateViewRequested = true;
}
}
+ public float CameraAngleY {
+ get => CameraRotation.Y;
+ set => CameraRotation = new Vector3(CameraRotation.X, value, CameraRotation.Z);
+ }
public Vector3 CameraPosition {
get => ExtensionMethods.ParseVec3 (Configuration.Global.Get<string> ("CameraPosition", "<0,0,12>"));
set {
@@ -942,6 +954,39 @@ namespace vkChess
p.SetColor (value);
}
}
+ public bool OptColorIsExpanded {
+ get => Configuration.Global.Get ("OptColorIsExpanded", false);
+ set {
+ if (OptColorIsExpanded == value)
+ return;
+ Configuration.Global.Set ("OptColorIsExpanded", value);
+ }
+ }
+ public bool OptRenderingIsExpanded {
+ get => Configuration.Global.Get ("OptRenderingIsExpanded", false);
+ set {
+ if (OptRenderingIsExpanded == value)
+ return;
+ Configuration.Global.Set ("OptRenderingIsExpanded", value);
+ }
+ }
+ public bool OptCameraIsExpanded {
+ get => Configuration.Global.Get ("OptCameraIsExpanded", false);
+ set {
+ if (OptCameraIsExpanded == value)
+ return;
+ Configuration.Global.Set ("OptCameraIsExpanded", value);
+ }
+ }
+ public bool OptGameIsExpanded {
+ get => Configuration.Global.Get ("OptGameIsExpanded", true);
+ set {
+ if (OptGameIsExpanded == value)
+ return;
+ Configuration.Global.Set ("OptGameIsExpanded", value);
+ }
+ }
+
#endregion
@@ -964,12 +1009,46 @@ namespace vkChess
}
#endregion
+ #region move history show
+ int historyIdx = 0;
+ public int HistoryMoveIndex {
+ get => historyIdx;
+ set {
+ if (historyIdx == value)
+ return;
+
+ if (historyIdx == 0) {
+ //save current positions
+ savedMoves = StockfishMoves;
+ }
+
+ historyIdx = value;
+ NotifyValueChanged (historyIdx);
+
+ if (historyIdx == 0) {
+ //restore current saved positions
+ StockfishMoves = savedMoves;
+ savedMoves = null;
+ resync3DScene ();
+ startTurn ();
+ } else {
+ StockfishMoves = savedMoves.Take (savedMoves.Count - historyIdx).ToList();
+ resync3DScene ();
+ }
+ }
+ }
+
+ IList<string> savedMoves;
+
+
+ #endregion
+
#region Stockfish
object movesMutex = new object ();
Process stockfish;
volatile bool waitAnimationFinished;
//Queue<string> stockfishCmdQueue = new Queue<string> ();
- List<String> stockfishMoves = new List<string> ();
+ IList<String> stockfishMoves = new ObservableList<string> ();
bool enableHint;
public bool EnableHint {
@@ -1004,7 +1083,7 @@ namespace vkChess
if (value == StockfishPath)
return;
Configuration.Global.Set ("StockfishPath", value);
- NotifyValueChanged ("StockfishPath", value);
+ NotifyValueChanged (value);
initStockfish ();
}
@@ -1086,11 +1165,13 @@ namespace vkChess
}
}
- public List<String> StockfishMoves {
+ public IList<String> StockfishMoves {
get => stockfishMoves;
set { stockfishMoves = value; }
}
void saveCurrentGame() {
+ if (historyIdx > 0)
+ StockfishMoves = savedMoves;
Configuration.Global.Set ("CurrentGame", stockfishPositionCommand);
}
void loadCurrentGame() {
@@ -1100,7 +1181,7 @@ namespace vkChess
string curGame = Configuration.Global.Get<string> ("CurrentGame");
if (string.IsNullOrEmpty (curGame))
return;
- stockfishMoves = curGame.Split (' ').ToList();
+ stockfishMoves = new ObservableList<string> (curGame.Split (' '));
if (currentState < GameState.Play)
return;
@@ -1116,7 +1197,6 @@ namespace vkChess
syncStockfish();
}
-
void initStockfish () {
if (currentState == GameState.Init)
throw new Exception ("init stockfish impossible: 3d scene must be initialized first.");
@@ -1133,6 +1213,17 @@ namespace vkChess
stockfish = null;
}
+ if (string.IsNullOrEmpty (StockfishPath)) {
+ if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux))
+ StockfishPath = "./stockfish_14_x64";
+ else if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
+ if (RuntimeInformation.OSArchitecture == Architecture.X64)
+ StockfishPath = "stockfish_14_x64.exe";
+ else if (RuntimeInformation.OSArchitecture == Architecture.X86)
+ StockfishPath = "stockfish_14_32bit.exe";
+ }
+ }
+
if (!File.Exists (StockfishPath)) {
NotifyValueChanged ("StockfishNotFound", true);
return;
@@ -1159,7 +1250,6 @@ namespace vkChess
void syncStockfish () {
if (currentState < GameState.Play)
return;
- NotifyValueChanged ("StockfishMoves", StockfishMoves);
sendToStockfish ("setoption name Skill Level value " + (CurrentPlayer == ChessColor.White ? WhitesLevel.ToString() : BlacksLevel.ToString()));
//sendToStockfish ($"setoption name nodestime value 10");
sendToStockfish ($"position startpos moves {stockfishPositionCommand}");
@@ -1243,7 +1333,7 @@ namespace vkChess
case "Stockfish":
//stockfish starting
CurrentState = GameState.StockFishStarted;
- NotifyValueChanged("StockfishVersion", tmp[1]);
+ NotifyValueChanged("StockfishVersion", (object)tmp[1]);
sendToStockfish ("uci");
break;
}
@@ -1316,18 +1406,34 @@ namespace vkChess
currentState = value;
- if (currentState > GameState.Play) {
+ if (currentState > GameState.Pad) {
Point kPos = CurrentPlayerPieces.First (p => p.Type == PieceType.King).BoardCell;
Piece.UpdateCase (kPos.X, kPos.Y, kingCheckedColor);
if (currentState == GameState.Checkmate) {
Piece king = CurrentPlayerPieces.First (p => p.Type == PieceType.King);
- Animation.StartAnimation (new FloatAnimation (king, "Z", 0.4f, 0.04f));
- Animation.StartAnimation (new AngleAnimation (king, "XAngle", MathHelper.Pi * 0.55f, 0.09f));
- Animation.StartAnimation (new AngleAnimation (king, "ZAngle", king.ZAngle + 0.3f, 0.5f));
+ Animation.StartAnimation (new FloatAnimation2 (king, "Z", 0.4f, 20));
+ Animation.StartAnimation (new AngleAnimation (king, "XAngle", MathHelper.Pi * 0.55f));
+ Animation.StartAnimation (new AngleAnimation (king, "ZAngle", king.ZAngle + 0.3f));
}
}
NotifyValueChanged ("CurrentState", currentState);
+ NotifyValueChanged ("CurrentStateColor", CurrentStateColor);
+ }
+ }
+ Color CurrentStateColor {
+ get {
+ switch (currentState) {
+ case GameState.Play:
+ return Colors.DarkGrey;
+ case GameState.Pad:
+ return Colors.DarkMagenta;
+ case GameState.Checked:
+ return Colors.DarkOrange;
+ case GameState.Checkmate:
+ return Colors.DarkRed;
+ }
+ return Colors.DarkSlateGrey;
}
}
ChessColor currentPlayer;
@@ -1343,15 +1449,12 @@ namespace vkChess
}
}
- public ChessColor Opponent {
- get { return CurrentPlayer == ChessColor.White ? ChessColor.Black : ChessColor.White; }
- }
- public Piece [] OpponentPieces {
- get { return CurrentPlayer == ChessColor.White ? blackPieces : whitePieces; }
- }
- public Piece [] CurrentPlayerPieces {
- get { return CurrentPlayer == ChessColor.White ? whitePieces : blackPieces; }
- }
+ public ChessColor Opponent =>
+ CurrentPlayer == ChessColor.White ? ChessColor.Black : ChessColor.White;
+ public Piece [] OpponentPieces =>
+ CurrentPlayer == ChessColor.White ? blackPieces : whitePieces;
+ public Piece [] CurrentPlayerPieces
+ => CurrentPlayer == ChessColor.White ? whitePieces : blackPieces;
public int GetPawnPromotionY (ChessColor color) => color == ChessColor.White ? 7 : 0;
Point Active {
@@ -1374,11 +1477,11 @@ namespace vkChess
}
if (active < 0) {
- NotifyValueChanged ("ActCell", "");
+ NotifyValueChanged ("ActCell", (object)"");
return;
}
- NotifyValueChanged ("ActCell", getChessCell (active.X, active.Y));
+ NotifyValueChanged ("ActCell", (object)getChessCell (active.X, active.Y));
Piece.UpdateCase (active.X, active.Y, activeColor);
ValidPositionsForActivePce = new List<Point> ();
@@ -1429,7 +1532,7 @@ namespace vkChess
if (selection >= 0)
Piece.UpdateCase (selection.X, selection.Y, selectionPosColor);
- NotifyValueChanged ("SelCell", getChessCell (selection.X, selection.Y));
+ NotifyValueChanged ("SelCell", (object)getChessCell (selection.X, selection.Y));
}
}
int[] mesheIndexes;
@@ -1441,7 +1544,6 @@ namespace vkChess
cptWhiteOut = 0;
cptBlackOut = 0;
StockfishMoves.Clear ();
- NotifyValueChanged ("StockfishMoves", StockfishMoves);
Active = -1;
@@ -1554,7 +1656,6 @@ namespace vkChess
cptWhiteOut = 0;
cptBlackOut = 0;
StockfishMoves.Clear ();
- NotifyValueChanged ("StockfishMoves", StockfishMoves);
Active = -1;
board = new Piece [8, 8];
@@ -1985,7 +2086,6 @@ namespace vkChess
enPassant = true;
StockfishMoves.Add (move);
- NotifyValueChanged ("StockfishMoves", StockfishMoves);
board [pStart.X, pStart.Y] = null;
Point pTarget = pEnd;
@@ -2035,6 +2135,12 @@ namespace vkChess
if (currentState == GameState.Checked || currentState == GameState.Checkmate) {
Point kPos = CurrentPlayerPieces.First (p => p.Type == PieceType.King).BoardCell;
Piece.UpdateCase (kPos.X, kPos.Y, -kingCheckedColor);
+ if (currentState == GameState.Checkmate) {
+ Piece king = CurrentPlayerPieces.First (p => p.Type == PieceType.King);
+ Animation.StartAnimation (new FloatAnimation2 (king, "Z", 0, 20));
+ Animation.StartAnimation (new AngleAnimation (king, "XAngle", 0));
+ Animation.StartAnimation (new AngleAnimation (king, "ZAngle", 0));
+ }
}
string move = StockfishMoves [StockfishMoves.Count - 1];
@@ -2079,7 +2185,7 @@ namespace vkChess
resetBoard (false);
foreach (string m in moves) {
processMove (m, false);
- CurrentPlayer = Opponent;
+ currentPlayer = Opponent;
}
}
diff --git a/src/deferredPbrRendererBase.cs b/src/deferredPbrRendererBase.cs
index a647179..9e18607 100644
--- a/src/deferredPbrRendererBase.cs
+++ b/src/deferredPbrRendererBase.cs
@@ -213,7 +213,8 @@ namespace vkChess
init_renderpass ();
descLayoutMain = new DescriptorSetLayout (dev,
- new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer),//matrices and params
+ new VkDescriptorSetLayoutBinding (0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment |
+ VkShaderStageFlags.TessellationControl | VkShaderStageFlags.TessellationEvaluation, VkDescriptorType.UniformBuffer),//matrices and params
new VkDescriptorSetLayoutBinding (1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//irradiance
new VkDescriptorSetLayoutBinding (2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//prefil
new VkDescriptorSetLayoutBinding (3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler),//lut brdf
@@ -265,9 +266,16 @@ namespace vkChess
new SpecializationConstant<float> (0, nearPlane),
new SpecializationConstant<float> (1, farPlane),
new SpecializationConstant<int> (2, MAX_MATERIAL_COUNT))) {
+ cfg.inputAssemblyState.topology = VkPrimitiveTopology.PatchList;
+
+ cfg.AddShader (dev, VkShaderStageFlags.TessellationControl, "#vkChess.net.pntriangles.tesc.spv");
+ cfg.AddShader (dev, VkShaderStageFlags.TessellationEvaluation, "#vkChess.net.pntriangles.tese.spv");
cfg.AddShader (dev, VkShaderStageFlags.Vertex, "#vkChess.net.GBuffPbrInstanced.vert.spv");
+ cfg.TessellationPatchControlPoints = 3;
+
cfg.SubpassIndex = SP_DEPTH_PREPASS;
+
depthPrepassPipeline = new GraphicPipeline (cfg, "Depth prepass");
cfg.depthStencilState.depthCompareOp = VkCompareOp.Equal;
@@ -276,11 +284,12 @@ namespace vkChess
cfg.blendAttachments.Add (new VkPipelineColorBlendAttachmentState (false));
cfg.SubpassIndex = SP_MODELS;
-
cfg.AddShader (dev, VkShaderStageFlags.Fragment, "#vkChess.net.GBuffPbrTexArray.frag.spv", constants);
+
gBuffPipeline = new GraphicPipeline (cfg, "GBuff");
}
+ cfg.inputAssemblyState.topology = VkPrimitiveTopology.TriangleList;
cfg.rasterizationState.cullMode = VkCullModeFlags.Front;
//COMPOSE PIPELINE
cfg.blendAttachments.Clear ();
diff --git a/ui/chess.crow b/ui/chess.crow
index 4227d4d..6657492 100644
--- a/ui/chess.crow
+++ b/ui/chess.crow
@@ -16,9 +16,9 @@
Background="Transparent" Foreground="White"
Unchecked = "{Background=Transparent}"/>
<Widget Width="Stretched"/>
- <VerticalStack Style="hsStatus">
+ <VerticalStack Style="hsStatus" Width="160">
<Label Style="labStatus" Text="State:" />
- <Label Style="labStatus2" Text="{CurrentState}" />
+ <Label Style="labStatus2" Text="{CurrentState}" Background="{CurrentStateColor}"/>
</VerticalStack>
<VerticalStack Style="hsStatus">
<Label Style="labStatus" Text="Hover:" />
diff --git a/ui/winMoves.crow b/ui/winMoves.crow
new file mode 100644
index 0000000..5a80573
--- /dev/null
+++ b/ui/winMoves.crow
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<Window Caption="Moves" Top="10" Left="10" Width="100" Height="50%" >
+ <VerticalStack>
+ <MoveHistoryWidget Margin="10" Moves="{StockfishMoves}" CurrentMoveIndex="{²HistoryMoveIndex}"/>
+ </VerticalStack>
+</Window>
+
diff --git a/ui/winOptions.crow b/ui/winOptions.crow
index 050aa98..5d58924 100644
--- a/ui/winOptions.crow
+++ b/ui/winOptions.crow
@@ -12,7 +12,7 @@
</HorizontalStack>
</VerticalStack>
<!--<HorizontalStack Height="Fit">-->
- <Expandable Caption="Game" IsExpanded="false">
+ <Expandable Caption="Game" IsExpanded="{²OptGameIsExpanded}">
<VerticalStack Height="Fit" Spacing="3" Margin="10">
<HorizontalStack Height="Fit">
<Label Width="Stretched" Text="Whites Level:"/>
@@ -50,7 +50,7 @@
</HorizontalStack>
</VerticalStack>
</HorizontalStack>-->
- <Expandable Caption="Camera" IsExpanded="false">
+ <Expandable Caption="Camera" IsExpanded="{²OptCameraIsExpanded}">
<VerticalStack Height="Fit" Margin="10">
<Vector3Widget Caption="Rotation" Value="{²CameraRotation}" SmallIncrement="0.01" LargeIncrement="0.1" Minimum="-7.0" Maximum="7.0" Decimals="2"/>
<Vector3Widget Caption="Position" Value="{²CameraPosition}" SmallIncrement="0.1" LargeIncrement="1.0" Minimum="-20.0" Maximum="20.0" Decimals="1"/>
@@ -60,7 +60,7 @@
</HorizontalStack>
</VerticalStack>
</Expandable>
- <Expandable Caption="Rendering" IsExpanded="false">
+ <Expandable Caption="Rendering" IsExpanded="{²OptRenderingIsExpanded}">
<VerticalStack Height="Fit" Margin="10">
<HorizontalStack Style="Slid" >
<Label Text="Exposure:" Width="100"/>
@@ -75,7 +75,7 @@
<Slider Style="LightingSlider" Value="{²IBLAmbient}" Maximum="50.0" SmallIncrement="0.01" LargeIncrement="0.1"/>
</HorizontalStack>
<CheckBox Caption="Enable Reflections" IsChecked="{²EnableReflections}" />
- <EnumSelector Caption="Sample count" EnumValue="{²SampleCount}" Height="Fit" Width="Stretched">
+ <EnumSelector Caption="Sample count" ForceRadioButton="true" BitFieldExcludeMask="{AvailableSampleCount}" EnumValue="{²SampleCount}" Height="Fit" Width="Stretched">
<Template>
<GroupBox Caption="{./Caption}" CornerRadius="{./CornerRadius}" Foreground="{./Foreground}" Background="{./Background}">
<Wrapper Margin="5" Orientation="Vertical" Height="Fit" Width="Stretched" Name="Content"/>
@@ -84,7 +84,7 @@
</EnumSelector>
</VerticalStack>
</Expandable>
- <Expandable Caption="Colors" IsExpanded="false">
+ <Expandable Caption="Colors" IsExpanded="{²OptColorIsExpanded}">
<VerticalStack Height="Fit" Margin="10">
<Vector3Widget Caption="Black color" Value="{²BlackColor}" SmallIncrement="0.01" LargeIncrement="0.1" Maximum="1.0" Decimals="2"/>
<Vector3Widget Caption="White color" Value="{²WhiteColor}" SmallIncrement="0.01" LargeIncrement="0.1" Maximum="1.0" Decimals="2"/>
diff --git a/vkChess.net.csproj b/vkChess.net.csproj
index d030901..a79c014 100644
--- a/vkChess.net.csproj
+++ b/vkChess.net.csproj
@@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
- <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom" />
+ <GLSLShader Include="shaders\**\*.frag;shaders\**\*.vert;shaders\**\*.comp;shaders\**\*.geom;shaders\**\*.tesc;shaders\**\*.tese" />
<None Include="data\**\*.*;ui\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -19,7 +19,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="VkCrowWindow" Version="0.3.4-beta" />
- <PackageReference Include="vke" Version="0.2.2-beta" />
+ <PackageReference Include="vke" Version="0.2.4-beta" />
<PackageReference Include="SpirVTasks" Version="0.1.44" />
<PackageReference Include="vke.EnvironmentPipeline" Version="0.2.0-beta" />
<PackageReference Include="vke.gltfLoader" Version="0.2.0-beta" />