Commit for 2020.10.18.7z
This commit is contained in:
parent
3fdc1820ea
commit
1393f1b77a
@ -21,20 +21,20 @@ layout (location = 1) out vec4 outNormal;
|
||||
layout (location = 2) out vec4 outPosition;
|
||||
|
||||
void main() {
|
||||
outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), inUv);
|
||||
if ( inCursor.radius.x <= 0 && inCursor.radius.y <= 0 ) {
|
||||
vec2 uv = gl_FragCoord.xy / textureSize(albedoTexture, 0);
|
||||
// uv.x = 1-uv.x;
|
||||
outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), uv);
|
||||
outNormal = texture(sampler2D(normalTexture, samp), uv);
|
||||
outPosition = texture(sampler2D(positionTexture, samp), uv);
|
||||
if ( outAlbedoSpecular.a < 0.01f ) outAlbedoSpecular = vec4(0,0,0,1);
|
||||
// if ( outAlbedoSpecular.a < 0.01f ) outAlbedoSpecular = vec4(0,0,0,1);
|
||||
return;
|
||||
}
|
||||
|
||||
outAlbedoSpecular = texture(sampler2D(albedoTexture, samp), inUv);
|
||||
float dist = pow(inUv.x - inCursor.position.x, 2) / pow(inCursor.radius.x, 2) + pow(inUv.y - inCursor.position.y, 2) / pow(inCursor.radius.y, 2);
|
||||
if ( dist <= 1 ) {
|
||||
float attenuation = dist;
|
||||
outAlbedoSpecular.rgb = mix( inCursor.color.rgb * inCursor.color.a, outAlbedoSpecular.rgb, attenuation );
|
||||
}
|
||||
if ( inAlpha < 1.0 ) outAlbedoSpecular.a = inAlpha;
|
||||
}
|
||||
@ -27,12 +27,14 @@ struct Matrices {
|
||||
layout (binding = 0) uniform UBO {
|
||||
Matrices matrices;
|
||||
Cursor cursor;
|
||||
vec2 alpha;
|
||||
// float alpha;
|
||||
// float padding;
|
||||
} ubo;
|
||||
|
||||
void main() {
|
||||
outUv = inUv;
|
||||
outCursor = ubo.cursor;
|
||||
outAlpha = 1;
|
||||
|
||||
gl_Position = ubo.matrices.model[PushConstant.pass] * vec4(inPos.xy, 0.0, 1.0);
|
||||
}
|
||||
@ -7,7 +7,11 @@ layout (input_attachment_index = 0, binding = 2) uniform subpassInput samplerNor
|
||||
layout (input_attachment_index = 0, binding = 3) uniform subpassInput samplerPosition;
|
||||
// layout (input_attachment_index = 0, binding = 4) uniform subpassInput samplerDepth;
|
||||
layout (binding = 5) uniform sampler2D samplerShadows[LIGHTS];
|
||||
|
||||
/*
|
||||
layout (std140, binding = 6) buffer Palette {
|
||||
vec4 palette[];
|
||||
};
|
||||
*/
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in flat uint inPushConstantPass;
|
||||
|
||||
@ -47,6 +51,7 @@ struct Light {
|
||||
float power;
|
||||
int type;
|
||||
float depthBias;
|
||||
vec2 padding;
|
||||
mat4 view;
|
||||
mat4 projection;
|
||||
};
|
||||
@ -62,13 +67,15 @@ struct Space {
|
||||
} position, normal, view;
|
||||
|
||||
struct Fog {
|
||||
vec2 range;
|
||||
vec4 color;
|
||||
vec2 range;
|
||||
vec2 padding;
|
||||
};
|
||||
|
||||
struct Mode {
|
||||
uint type;
|
||||
uint scalar;
|
||||
vec2 padding;
|
||||
vec4 parameters;
|
||||
};
|
||||
|
||||
@ -188,7 +195,6 @@ vec3 hslToRgb(vec3 HSL) {
|
||||
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
|
||||
return (RGB - 0.5) * C + HSL.z;
|
||||
}
|
||||
|
||||
vec3 rgbToHsl(vec3 RGB) {
|
||||
float Epsilon = 1e-10;
|
||||
vec3 HCV; {
|
||||
@ -209,7 +215,6 @@ float hueDistance(float h1, float h2) {
|
||||
}
|
||||
const float lightnessSteps = 4.0;
|
||||
float lightnessStep(float l) {
|
||||
/* Quantize the lightness to one of `lightnessSteps` values */
|
||||
return floor((0.5 + l * lightnessSteps)) / lightnessSteps;
|
||||
}
|
||||
const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255,
|
||||
@ -228,54 +233,11 @@ const int indexMatrix16x16[256] = int[](0,192, 48,240, 12,204, 60,252, 3,195, 5
|
||||
138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117,
|
||||
42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213,
|
||||
170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85);
|
||||
float indexValue16x16() {
|
||||
int x = int(mod(gl_FragCoord.x, 16));
|
||||
int y = int(mod(gl_FragCoord.y, 16));
|
||||
float indexValue16x16( float scale ) {
|
||||
int x = int(mod(gl_FragCoord.x * scale, 16));
|
||||
int y = int(mod(gl_FragCoord.y * scale, 16));
|
||||
return indexMatrix16x16[(x + y * 16)] / 256.0;
|
||||
}
|
||||
const int paletteSize = 40;
|
||||
const vec3 palette16x16[paletteSize] = vec3[](
|
||||
vec3( 0, 0, 0),
|
||||
vec3( 0, 0, 0.502),
|
||||
vec3( 0, 0, 0.753),
|
||||
vec3( 0, 0, 1),
|
||||
vec3( 0, 1, 0.251),
|
||||
vec3( 0, 1, 0.50),
|
||||
vec3( 24.0/360.0, 1, 0.251),
|
||||
vec3( 24.0/360.0, 1, 0.5),
|
||||
vec3( 24.0/360.0, 1, 0.625),
|
||||
vec3( 24.0/360.0, 1, 0.751),
|
||||
vec3( 30.0/360.0, 1, 0.251),
|
||||
vec3( 60.0/360.0, 0.333, 0.376),
|
||||
vec3( 60.0/360.0, 1, 0.251),
|
||||
vec3( 60.0/360.0, 1, 0.5),
|
||||
vec3( 60.0/360.0, 1, 0.751),
|
||||
vec3(120.0/360.0, 1, 0.251),
|
||||
vec3(120.0/360.0, 1, 0.5),
|
||||
vec3(120.0/360.0, 1, 0.751),
|
||||
vec3(150.0/360.0, 1, 0.251),
|
||||
vec3(150.0/360.0, 1, 0.5),
|
||||
vec3(150.0/360.0, 1, 0.751),
|
||||
vec3(180.0/360.0, 1, 0.125),
|
||||
vec3(180.0/360.0, 1, 0.251),
|
||||
vec3(180.0/360.0, 1, 0.5),
|
||||
vec3(180.0/360.0, 1, 0.751),
|
||||
vec3(210.0/360.0, 1, 0.251),
|
||||
vec3(210.0/360.0, 1, 0.5),
|
||||
vec3(210.0/360.0, 1, 0.751),
|
||||
vec3(240.0/360.0, 1, 0.251),
|
||||
vec3(240.0/360.0, 1, 0.5),
|
||||
vec3(240.0/360.0, 1, 0.751),
|
||||
vec3(270.0/360.0, 1, 0.251),
|
||||
vec3(270.0/360.0, 1, 0.5),
|
||||
vec3(270.0/360.0, 1, 0.751),
|
||||
vec3(300.0/360.0, 1, 0.251),
|
||||
vec3(300.0/360.0, 1, 0.5),
|
||||
vec3(300.0/360.0, 1, 0.751),
|
||||
vec3(330.0/360.0, 1, 0.251),
|
||||
vec3(330.0/360.0, 1, 0.5),
|
||||
vec3(330.0/360.0, 1, 0.751)
|
||||
);
|
||||
const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42,
|
||||
48, 16, 56, 24, 50, 18, 58, 26,
|
||||
12, 44, 4, 36, 14, 46, 6, 38,
|
||||
@ -284,90 +246,28 @@ const int indexMatrix8x8[64] = int[](0, 32, 8, 40, 2, 34, 10, 42,
|
||||
51, 19, 59, 27, 49, 17, 57, 25,
|
||||
15, 47, 7, 39, 13, 45, 5, 37,
|
||||
63, 31, 55, 23, 61, 29, 53, 21);
|
||||
float indexValue8x8() {
|
||||
int x = int(mod(gl_FragCoord.x, 8));
|
||||
int y = int(mod(gl_FragCoord.y, 8));
|
||||
float indexValue8x8( float scale ) {
|
||||
int x = int(mod(gl_FragCoord.x * scale, 8));
|
||||
int y = int(mod(gl_FragCoord.y * scale, 8));
|
||||
return indexMatrix8x8[(x + y * 8)] / 64.0;
|
||||
}
|
||||
const int palette8x8Size = 28;
|
||||
const vec3 palette8x8[28] = vec3[](
|
||||
vec3(0, 0, 0),
|
||||
vec3(0, 0, 1),
|
||||
vec3(0, 0, 0.502),
|
||||
vec3(0, 0, 0.753),
|
||||
vec3(0, 1, 0.251),
|
||||
vec3(0, 1, 0.50),
|
||||
vec3(60.0/360.0, 1, 0.251),
|
||||
vec3(60.0/360.0, 1, 0.5),
|
||||
vec3(120.0/360.0, 1, 0.251),
|
||||
vec3(120.0/360.0, 1, 0.5),
|
||||
vec3(180.0/360.0, 1, 0.251),
|
||||
vec3(180.0/360.0, 1, 0.5),
|
||||
vec3(240.0/360.0, 1, 0.251),
|
||||
vec3(240.0/360.0, 1, 0.5),
|
||||
vec3(300.0/360.0, 1, 0.251),
|
||||
vec3(300.0/360.0, 1, 0.5),
|
||||
vec3(60.0/360.0, 0.333, 0.376),
|
||||
vec3(60.0/360.0, 1, 0.751),
|
||||
vec3(180.0/360.0, 1, 0.125),
|
||||
vec3(150.0/360.0, 1, 0.5),
|
||||
vec3(210.0/360.0, 1, 0.5),
|
||||
vec3(180.0/360.0, 1, 0.751),
|
||||
vec3(210.0/360.0, 1, 0.251),
|
||||
vec3(240.0/360.0, 1, 0.751),
|
||||
vec3(270.0/360.0, 1, 0.5),
|
||||
vec3(330.0/360.0, 1, 0.5),
|
||||
vec3(30.0/360.0, 1, 0.251),
|
||||
vec3(24.0/360.0, 1, 0.625)
|
||||
);
|
||||
const int indexMatrix4x4[16] = int[](0, 8, 2, 10,
|
||||
12, 4, 14, 6,
|
||||
3, 11, 1, 9,
|
||||
15, 7, 13, 5);
|
||||
|
||||
float indexValue4x4() {
|
||||
int x = int(mod(gl_FragCoord.x, 4));
|
||||
int y = int(mod(gl_FragCoord.y, 4));
|
||||
float indexValue4x4( float scale ) {
|
||||
int x = int(mod(gl_FragCoord.x * scale, 4));
|
||||
int y = int(mod(gl_FragCoord.y * scale, 4));
|
||||
return indexMatrix4x4[(x + y * 4)] / 16.0;
|
||||
}
|
||||
const int palette4x4Size = 28;
|
||||
const vec3 palette4x4[28] = vec3[](
|
||||
vec3(0, 0, 0),
|
||||
vec3(0, 0, 1),
|
||||
vec3(0, 0, 0.502),
|
||||
vec3(0, 0, 0.753),
|
||||
vec3(0, 1, 0.251),
|
||||
vec3(0, 1, 0.50),
|
||||
vec3(60.0/360.0, 1, 0.251),
|
||||
vec3(60.0/360.0, 1, 0.5),
|
||||
vec3(120.0/360.0, 1, 0.251),
|
||||
vec3(120.0/360.0, 1, 0.5),
|
||||
vec3(180.0/360.0, 1, 0.251),
|
||||
vec3(180.0/360.0, 1, 0.5),
|
||||
vec3(240.0/360.0, 1, 0.251),
|
||||
vec3(240.0/360.0, 1, 0.5),
|
||||
vec3(300.0/360.0, 1, 0.251),
|
||||
vec3(300.0/360.0, 1, 0.5),
|
||||
vec3(60.0/360.0, 0.333, 0.376),
|
||||
vec3(60.0/360.0, 1, 0.751),
|
||||
vec3(180.0/360.0, 1, 0.125),
|
||||
vec3(150.0/360.0, 1, 0.5),
|
||||
vec3(210.0/360.0, 1, 0.5),
|
||||
vec3(180.0/360.0, 1, 0.751),
|
||||
vec3(210.0/360.0, 1, 0.251),
|
||||
vec3(240.0/360.0, 1, 0.751),
|
||||
vec3(270.0/360.0, 1, 0.5),
|
||||
vec3(330.0/360.0, 1, 0.5),
|
||||
vec3(30.0/360.0, 1, 0.251),
|
||||
vec3(24.0/360.0, 1, 0.625)
|
||||
);
|
||||
vec3[2] closestColors16x16(float hue) {
|
||||
vec3[2] closestColors(float hue) {
|
||||
vec3 ret[2];
|
||||
vec3 closest = vec3(-2, 0, 0);
|
||||
vec3 secondClosest = vec3(-2, 0, 0);
|
||||
vec3 temp;
|
||||
for (int i = 0; i < paletteSize; ++i) {
|
||||
temp = rgbToHsl(palette16x16[i]);
|
||||
/*
|
||||
for (int i = 0; i < palette.length(); ++i) {
|
||||
temp = rgbToHsl(palette[i].rgb);
|
||||
float tempDistance = hueDistance(temp.x, hue);
|
||||
if (tempDistance < hueDistance(closest.x, hue)) {
|
||||
secondClosest = closest;
|
||||
@ -378,123 +278,52 @@ vec3[2] closestColors16x16(float hue) {
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
ret[0] = closest;
|
||||
ret[1] = secondClosest;
|
||||
return ret;
|
||||
}
|
||||
vec3 dither1_16x16(vec3 color) {
|
||||
vec3 hsl = rgbToHsl(color);
|
||||
|
||||
vec3 cs[2] = closestColors16x16(hsl.x);
|
||||
vec3 c1 = cs[0];
|
||||
vec3 c2 = cs[1];
|
||||
float d = indexValue16x16();
|
||||
float hueDiff = hueDistance(hsl.x, c1.x) / hueDistance(c2.x, c1.x);
|
||||
|
||||
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
|
||||
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
|
||||
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
|
||||
|
||||
vec3 resultColor = (hueDiff < d) ? c1 : c2;
|
||||
resultColor.z = (lightnessDiff < d) ? l1 : l2;
|
||||
return hslToRgb(resultColor);
|
||||
}
|
||||
vec3[2] closestColors8x8(float hue) {
|
||||
vec3 ret[2];
|
||||
vec3 closest = vec3(-2, 0, 0);
|
||||
vec3 secondClosest = vec3(-2, 0, 0);
|
||||
vec3 temp;
|
||||
for (int i = 0; i < palette8x8Size; ++i) {
|
||||
temp = palette8x8[i];
|
||||
float tempDistance = hueDistance(temp.x, hue);
|
||||
if (tempDistance < hueDistance(closest.x, hue)) {
|
||||
secondClosest = closest;
|
||||
closest = temp;
|
||||
} else {
|
||||
if (tempDistance < hueDistance(secondClosest.x, hue)) {
|
||||
secondClosest = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret[0] = closest;
|
||||
ret[1] = secondClosest;
|
||||
return ret;
|
||||
}
|
||||
vec3 dither1_8x8(vec3 color) {
|
||||
vec3 hsl = rgbToHsl(color);
|
||||
|
||||
vec3 cs[2] = closestColors8x8(hsl.x);
|
||||
vec3 c1 = cs[0];
|
||||
vec3 c2 = cs[1];
|
||||
float d = indexValue8x8();
|
||||
float hueDiff = hueDistance(hsl.x, c1.x) / hueDistance(c2.x, c1.x);
|
||||
|
||||
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
|
||||
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
|
||||
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
|
||||
|
||||
vec3 resultColor = (hueDiff < d) ? c1 : c2;
|
||||
//resultColor.z = (lightnessDiff < d) ? l1 : l2;
|
||||
return hslToRgb(resultColor);
|
||||
}
|
||||
vec3[2] closestColors4x4(float hue) {
|
||||
vec3 ret[2];
|
||||
vec3 closest = vec3(-2, 0, 0);
|
||||
vec3 secondClosest = vec3(-2, 0, 0);
|
||||
vec3 temp;
|
||||
for (int i = 0; i < palette4x4Size; ++i) {
|
||||
temp = palette4x4[i];
|
||||
float tempDistance = hueDistance(temp.x, hue);
|
||||
if (tempDistance < hueDistance(closest.x, hue)) {
|
||||
secondClosest = closest;
|
||||
closest = temp;
|
||||
} else {
|
||||
if (tempDistance < hueDistance(secondClosest.x, hue)) {
|
||||
secondClosest = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret[0] = closest;
|
||||
ret[1] = secondClosest;
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec3 dither1_4x4(vec3 color) {
|
||||
vec3 hsl = rgbToHsl(color);
|
||||
|
||||
vec3 cs[2] = closestColors4x4(hsl.x);
|
||||
vec3 c1 = cs[0];
|
||||
vec3 c2 = cs[1];
|
||||
float d = indexValue4x4();
|
||||
float hueDiff = hueDistance(hsl.x, c1.x) / hueDistance(c2.x, c1.x);
|
||||
|
||||
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
|
||||
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
|
||||
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
|
||||
|
||||
vec3 resultColor = (hueDiff < d) ? c1 : c2;
|
||||
//resultColor.z = (lightnessDiff < d) ? l1 : l2;
|
||||
return hslToRgb(resultColor);
|
||||
}
|
||||
float dither(float color) {
|
||||
float closestColor = (color < 0.5) ? 0 : 1;
|
||||
float secondClosestColor = 1 - closestColor;
|
||||
float d;
|
||||
float d = 1; // -0.5 - fract(ubo.mode.parameters.w / 8.0);
|
||||
if ( ubo.mode.scalar == 16 ) {
|
||||
d = indexValue16x16();
|
||||
d = indexValue16x16(1);
|
||||
} else if ( ubo.mode.scalar == 8 ) {
|
||||
d = indexValue8x8();
|
||||
d = indexValue8x8(1);
|
||||
} else if ( ubo.mode.scalar == 4 ) {
|
||||
d = indexValue4x4();
|
||||
d = indexValue4x4(1);
|
||||
}
|
||||
float distance = abs(closestColor - color);
|
||||
return (distance < d) ? closestColor : secondClosestColor;
|
||||
}
|
||||
void dither(inout vec3 color) {
|
||||
vec3 hsl = rgbToHsl(color);
|
||||
hsl.y = dither(hsl.y);
|
||||
hsl.x = dither(hsl.x);
|
||||
color = hslToRgb(hsl);
|
||||
}
|
||||
void dither1(inout vec3 color) {
|
||||
vec3 hsl = rgbToHsl(color);
|
||||
|
||||
float d = 0;
|
||||
vec3 cs[2] = { hsl, hsl }; // closestColors(hsl.x);
|
||||
float scale = 1;
|
||||
if ( ubo.mode.scalar == 16 ) {
|
||||
d = indexValue16x16(scale);
|
||||
} else if ( ubo.mode.scalar == 8 ) {
|
||||
d = indexValue8x8(scale);
|
||||
} else if ( ubo.mode.scalar == 4 ) {
|
||||
d = indexValue4x4(scale);
|
||||
}
|
||||
float hueDiff = hueDistance(hsl.x, cs[0].x) / hueDistance(cs[1].x, cs[0].x);
|
||||
float l1 = lightnessStep(max((hsl.z - 0.125), 0.0));
|
||||
float l2 = lightnessStep(min((hsl.z + 0.124), 1.0));
|
||||
float lightnessDiff = (hsl.z - l1) / (l2 - l1);
|
||||
|
||||
vec3 resultColor = (hueDiff < d) ? cs[0] : cs[1];
|
||||
resultColor.z = (lightnessDiff < d) ? l1 : l2;
|
||||
color = hslToRgb(resultColor);
|
||||
}
|
||||
|
||||
float rand2(vec2 co){
|
||||
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453);
|
||||
@ -541,15 +370,12 @@ void main() {
|
||||
|
||||
fog(fragColor, litFactor);
|
||||
|
||||
if ( (ubo.mode.type & (0x1 >> 1)) == (0x1 >> 1) ) {
|
||||
dither(fragColor);
|
||||
if ( (ubo.mode.type & (0x1 << 0)) == (0x1 << 0) ) {
|
||||
dither1(fragColor);
|
||||
}
|
||||
if ( (ubo.mode.type & (0x1 >> 2)) == (0x1 >> 2) ) {
|
||||
if ( (ubo.mode.type & (0x1 << 1)) == (0x1 << 1) ) {
|
||||
whitenoise(fragColor);
|
||||
}
|
||||
if ( (ubo.mode.type & (0x1 >> 3)) == (0x1 >> 3) ) {
|
||||
dither(fragColor);
|
||||
}
|
||||
|
||||
outFragColor = vec4(fragColor,1);
|
||||
}
|
||||
@ -7,6 +7,7 @@ struct Gui {
|
||||
vec4 color;
|
||||
int mode;
|
||||
float depth;
|
||||
vec2 padding;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
@ -19,7 +20,7 @@ void main() {
|
||||
if ( inUv.x > inGui.offset.z ) discard;
|
||||
if ( inUv.y > inGui.offset.w ) discard;
|
||||
|
||||
outFragColor = texture(samplerColor, inUv);// vec4(inUv.s, inUv.t, 1.0, 1.0);
|
||||
outFragColor = texture(samplerColor, inUv);
|
||||
if ( outFragColor.a < 0.001 ) discard;
|
||||
if ( inGui.mode == 1 ) {
|
||||
outFragColor = inGui.color;
|
||||
|
||||
@ -1,38 +0,0 @@
|
||||
#version 450
|
||||
|
||||
layout (binding = 1) uniform sampler2D samplerColor;
|
||||
|
||||
struct Gui {
|
||||
vec4 offset;
|
||||
vec4 color;
|
||||
int mode;
|
||||
float depth;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in flat Gui inGui;
|
||||
layout (location = 0) out vec4 outFragColor;
|
||||
|
||||
void main() {
|
||||
if ( inUv.x < inGui.offset.x ) discard;
|
||||
if ( inUv.y < inGui.offset.y ) discard;
|
||||
if ( inUv.x > inGui.offset.z ) discard;
|
||||
if ( inUv.y > inGui.offset.w ) discard;
|
||||
|
||||
outFragColor = texture(samplerColor, inUv);// vec4(inUv.s, inUv.t, 1.0, 1.0);
|
||||
if ( outFragColor.a < 0.001 ) discard;
|
||||
|
||||
if ( inGui.mode == 1 ) {
|
||||
outFragColor = inGui.color;
|
||||
} else {
|
||||
outFragColor *= inGui.color;
|
||||
}
|
||||
|
||||
float end = 0.25;
|
||||
if ( inUv.x < end ) {
|
||||
outFragColor.a = inUv.x / end;
|
||||
} else if ( inUv.x + end >= 1 ) {
|
||||
float offset = (1 - inUv.x);
|
||||
outFragColor.a = offset / end;
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,7 @@ struct Gui {
|
||||
vec4 color;
|
||||
int mode;
|
||||
float depth;
|
||||
vec2 padding;
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
|
||||
@ -13,6 +13,7 @@ struct Gui {
|
||||
float weight;
|
||||
int spread;
|
||||
float scale;
|
||||
float padding;
|
||||
};
|
||||
|
||||
layout (location = 0) in vec2 inUv;
|
||||
|
||||
@ -21,6 +21,7 @@ struct Gui {
|
||||
float weight;
|
||||
int spread;
|
||||
float scale;
|
||||
float padding;
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
|
||||
@ -21,6 +21,7 @@ struct Gui {
|
||||
float weight;
|
||||
int spread;
|
||||
float scale;
|
||||
float padding;
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
|
||||
@ -15,6 +15,7 @@ struct Gui {
|
||||
vec4 color;
|
||||
int mode;
|
||||
float depth;
|
||||
vec2 padding;
|
||||
};
|
||||
|
||||
layout (binding = 0) uniform UBO {
|
||||
|
||||
39
bin/data/shaders/mcdonalds.frag.glsl
Normal file
39
bin/data/shaders/mcdonalds.frag.glsl
Normal file
@ -0,0 +1,39 @@
|
||||
#version 450
|
||||
|
||||
layout (constant_id = 0) const uint TEXTURES = 87;
|
||||
layout (binding = 1) uniform sampler2D samplerTextures[TEXTURES];
|
||||
struct Map {
|
||||
uint target;
|
||||
float blend;
|
||||
ivec2 padding;
|
||||
};
|
||||
layout (binding = 2) uniform UBO {
|
||||
Map map[TEXTURES];
|
||||
} ubo;
|
||||
layout (location = 0) in vec2 inUv;
|
||||
layout (location = 1) in vec4 inColor;
|
||||
layout (location = 2) in vec3 inNormal;
|
||||
layout (location = 3) in vec3 inPosition;
|
||||
layout (location = 4) flat in uint inId;
|
||||
|
||||
layout (location = 0) out vec4 outAlbedoSpecular;
|
||||
layout (location = 1) out vec4 outNormal;
|
||||
layout (location = 2) out vec4 outPosition;
|
||||
|
||||
void main() {
|
||||
uint offset = inId;
|
||||
outAlbedoSpecular = texture(samplerTextures[offset], inUv.xy);
|
||||
Map mapped = ubo.map[offset];
|
||||
if ( offset != mapped.target ) {
|
||||
outAlbedoSpecular = mix(texture(samplerTextures[offset], inUv.xy), texture(samplerTextures[mapped.target], inUv.xy), mapped.blend);
|
||||
} else {
|
||||
outAlbedoSpecular = texture(samplerTextures[offset], inUv.xy);
|
||||
}
|
||||
|
||||
if ( outAlbedoSpecular.a < 0.001 ) discard;
|
||||
outAlbedoSpecular.rgb *= inColor.rgb;
|
||||
outAlbedoSpecular.a = 1;
|
||||
|
||||
outNormal = vec4(inNormal,1);
|
||||
outPosition = vec4(inPosition,1);
|
||||
}
|
||||
@ -6,6 +6,12 @@
|
||||
#include <uf/utils/mempool/mempool.h>
|
||||
|
||||
int main(int argc, char** argv){
|
||||
for ( size_t i = 0; i < argc; ++i ) {
|
||||
char* c_str = argv[i];
|
||||
std::string string(argv[i]);
|
||||
ext::arguments.emplace_back(string);
|
||||
}
|
||||
|
||||
std::atexit([]{
|
||||
uf::iostream << "Termination via std::atexit()!" << "\n";
|
||||
client::terminated = !(client::ready = ext::ready = false);
|
||||
@ -42,13 +48,9 @@ int main(int argc, char** argv){
|
||||
ext::render();
|
||||
} catch ( std::runtime_error& e ) {
|
||||
uf::iostream << "RUNTIME ERROR: " << e.what() << "\n";
|
||||
std::abort();
|
||||
raise(SIGSEGV);
|
||||
throw e;
|
||||
break;
|
||||
} catch ( std::exception& e ) {
|
||||
uf::iostream << "EXCEPTION ERROR: " << e.what() << "\n";
|
||||
std::abort();
|
||||
raise(SIGSEGV);
|
||||
throw e;
|
||||
} catch ( bool handled ) {
|
||||
if (!handled) uf::iostream << "UNHANDLED ERROR: " << "???" << "\n";
|
||||
@ -59,8 +61,8 @@ int main(int argc, char** argv){
|
||||
|
||||
if ( !client::terminated ) {
|
||||
uf::iostream << "Natural termination!" << "\n";
|
||||
ext::terminate();
|
||||
client::terminate();
|
||||
}
|
||||
ext::terminate();
|
||||
client::terminate();
|
||||
return 0;
|
||||
}
|
||||
@ -31,9 +31,12 @@ namespace uf {
|
||||
template<typename T>
|
||||
T loadChild( const std::string&, bool = true );
|
||||
|
||||
std::string formatHookName( const std::string& name );
|
||||
void queueHook( const std::string&, const std::string& = "", double = 0 );
|
||||
std::vector<std::string> callHook( const std::string&, const std::string& = "" );
|
||||
std::size_t addHook( const std::string&, const uf::HookHandler::Readable::function_t& );
|
||||
|
||||
std::string grabURI( const std::string& filename, const std::string& root = "" );
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(EXT_STATIC)
|
||||
#if defined(UF_ENV_WINDOWS)
|
||||
@ -38,6 +39,7 @@
|
||||
#include <string>
|
||||
namespace ext {
|
||||
extern bool EXT_API ready;
|
||||
extern std::vector<std::string> EXT_API arguments;
|
||||
|
||||
extern void EXT_API initialize();
|
||||
extern bool EXT_API running();
|
||||
|
||||
@ -11,7 +11,11 @@ namespace ext {
|
||||
VkDevice device;
|
||||
VkBuffer buffer = VK_NULL_HANDLE;
|
||||
VkDeviceMemory memory = VK_NULL_HANDLE;
|
||||
VkDescriptorBufferInfo descriptor;
|
||||
VkDescriptorBufferInfo descriptor = {
|
||||
VK_NULL_HANDLE,
|
||||
0,
|
||||
0
|
||||
};
|
||||
VkDeviceSize size = 0;
|
||||
VkDeviceSize alignment = 0;
|
||||
void* mapped = nullptr;
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#include <uf/ext/vulkan.h>
|
||||
#include <uf/ext/vulkan/buffer.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
|
||||
namespace ext {
|
||||
namespace vulkan {
|
||||
@ -13,9 +14,9 @@ namespace ext {
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkDevice logicalDevice;
|
||||
struct {
|
||||
VkCommandPool graphics = VK_NULL_HANDLE;
|
||||
VkCommandPool compute = VK_NULL_HANDLE;
|
||||
VkCommandPool transfer = VK_NULL_HANDLE;
|
||||
std::unordered_map<std::thread::id, VkCommandPool> graphics;
|
||||
std::unordered_map<std::thread::id, VkCommandPool> compute;
|
||||
std::unordered_map<std::thread::id, VkCommandPool> transfer;
|
||||
} commandPool;
|
||||
|
||||
VkPhysicalDeviceProperties properties;
|
||||
@ -42,10 +43,10 @@ namespace ext {
|
||||
std::vector<VkQueueFamilyProperties> queueFamilyProperties;
|
||||
|
||||
struct {
|
||||
VkQueue graphics;
|
||||
VkQueue present;
|
||||
VkQueue compute;
|
||||
VkQueue transfer;
|
||||
std::unordered_map<std::thread::id,VkQueue> graphics;
|
||||
std::unordered_map<std::thread::id,VkQueue> present;
|
||||
std::unordered_map<std::thread::id,VkQueue> compute;
|
||||
std::unordered_map<std::thread::id,VkQueue> transfer;
|
||||
} queues;
|
||||
|
||||
uf::Window* window;
|
||||
@ -88,6 +89,15 @@ namespace ext {
|
||||
void *data = nullptr
|
||||
);
|
||||
|
||||
enum QueueEnum {
|
||||
GRAPHICS,
|
||||
PRESENT,
|
||||
COMPUTE,
|
||||
TRANSFER,
|
||||
};
|
||||
VkQueue& getQueue( QueueEnum );
|
||||
VkCommandPool& getCommandPool( QueueEnum );
|
||||
|
||||
// RAII
|
||||
void initialize();
|
||||
void destroy();
|
||||
|
||||
@ -18,7 +18,7 @@ void ext::vulkan::Graphic::initializeGeometry( uf::BaseMesh<T, U>& mesh, bool st
|
||||
updateBuffer(
|
||||
(void*) mesh.indices.data(),
|
||||
mesh.indices.size() * mesh.sizes.indices,
|
||||
0,
|
||||
1,
|
||||
stage
|
||||
);
|
||||
return;
|
||||
|
||||
@ -9,6 +9,7 @@ namespace ext {
|
||||
VkFormat format;
|
||||
VkImageLayout layout;
|
||||
VkImageUsageFlags usage;
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
bool aliased = false;
|
||||
|
||||
VkImage image;
|
||||
|
||||
@ -15,21 +15,24 @@ namespace ext {
|
||||
struct {
|
||||
VkFilter min = VK_FILTER_LINEAR;
|
||||
VkFilter mag = VK_FILTER_LINEAR;
|
||||
VkBorderColor borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
|
||||
} filter;
|
||||
struct {
|
||||
VkSamplerAddressMode u = VK_SAMPLER_ADDRESS_MODE_REPEAT, v = VK_SAMPLER_ADDRESS_MODE_REPEAT, w = VK_SAMPLER_ADDRESS_MODE_REPEAT;
|
||||
VkBool32 unnormalizedCoordinates = VK_FALSE;
|
||||
} addressMode;
|
||||
struct {
|
||||
VkBool32 compareEnable = VK_FALSE;
|
||||
VkCompareOp compareOp = VK_COMPARE_OP_ALWAYS;
|
||||
VkSamplerMipmapMode mode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
float lodBias = 0.0f;
|
||||
} mip;
|
||||
VkCompareOp compareOp = VK_COMPARE_OP_NEVER;
|
||||
struct {
|
||||
float min = 0.0f;
|
||||
float max = 0.0f;
|
||||
} lod;
|
||||
float maxAnisotropy;
|
||||
|
||||
} mip;
|
||||
struct {
|
||||
VkBool32 enabled = VK_TRUE;
|
||||
float max = 16.0f;
|
||||
} anisotropy;
|
||||
VkDescriptorImageInfo info;
|
||||
} descriptor;
|
||||
|
||||
@ -41,9 +44,10 @@ namespace ext {
|
||||
|
||||
VkImage image;
|
||||
VkImageView view;
|
||||
VkImageLayout imageLayout;
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkDeviceMemory deviceMemory;
|
||||
VkDescriptorImageInfo descriptor;
|
||||
VkFormat format;
|
||||
|
||||
Sampler sampler;
|
||||
|
||||
@ -63,9 +67,7 @@ namespace ext {
|
||||
VkImage image,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
||||
VkImageSubresourceRange subresourceRange
|
||||
);
|
||||
static void setImageLayout(
|
||||
VkCommandBuffer cmdbuffer,
|
||||
@ -73,8 +75,7 @@ namespace ext {
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
|
||||
uint32_t mipLevels
|
||||
);
|
||||
};
|
||||
struct UF_API Texture2D : public Texture {
|
||||
@ -83,31 +84,27 @@ namespace ext {
|
||||
std::string filename,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
bool forceLinear = false
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void loadFromFile(
|
||||
std::string filename,
|
||||
Device& device,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
bool forceLinear = false
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
Device& device,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
bool forceLinear = false
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void loadFromImage(
|
||||
uf::Image& image,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
bool forceLinear = false
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void fromBuffers(
|
||||
void* buffer,
|
||||
@ -119,13 +116,14 @@ namespace ext {
|
||||
VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VkImageLayout imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
|
||||
);
|
||||
void asRenderTarget(
|
||||
Device& device,
|
||||
uint32_t texWidth,
|
||||
uint32_t texHeight,
|
||||
VkFormat format = VK_FORMAT_R8G8B8A8_UNORM
|
||||
);
|
||||
void asRenderTarget( Device& device, uint32_t texWidth, uint32_t texHeight, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM );
|
||||
void aliasAttachment( const RenderTarget::Attachment& attachment, bool = true );
|
||||
void update( uf::Image& image, VkImageLayout );
|
||||
void update( void*, VkDeviceSize, VkImageLayout );
|
||||
inline void update( uf::Image& image ) { return this->update(image, this->imageLayout) ; }
|
||||
inline void update( void* data, VkDeviceSize size ) { return this->update(data, size, this->imageLayout) ; }
|
||||
|
||||
void generateMipmaps(VkCommandBuffer commandBuffer);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -41,8 +41,11 @@ namespace ext {
|
||||
|
||||
extern UF_API uint32_t width;
|
||||
extern UF_API uint32_t height;
|
||||
extern UF_API uint8_t msaa;
|
||||
|
||||
extern UF_API bool validation;
|
||||
extern UF_API bool rebuildOnTickStart;
|
||||
extern UF_API bool waitOnRenderEnd;
|
||||
extern UF_API std::vector<std::string> validationFilters;
|
||||
extern UF_API std::vector<std::string> requestedDeviceFeatures;
|
||||
extern UF_API std::vector<std::string> requestedDeviceExtensions;
|
||||
|
||||
@ -248,26 +248,4 @@ namespace uf {
|
||||
} matrices;
|
||||
alignas(16) pod::Vector4f color = { 1, 1, 1, 0 };
|
||||
};
|
||||
struct GuiMeshDescriptor {
|
||||
struct {
|
||||
alignas(16) pod::Matrix4f model;
|
||||
} matrices;
|
||||
struct {
|
||||
alignas(16) pod::Vector4f offset;
|
||||
alignas(16) pod::Vector4f color;
|
||||
alignas(4) int32_t mode = 0;
|
||||
alignas(4) float depth = 0.0f;
|
||||
} gui;
|
||||
};
|
||||
struct StereoGuiMeshDescriptor {
|
||||
struct {
|
||||
alignas(16) pod::Matrix4f model[2];
|
||||
} matrices;
|
||||
struct {
|
||||
alignas(16) pod::Vector4f offset;
|
||||
alignas(16) pod::Vector4f color;
|
||||
alignas(4) int32_t mode = 0;
|
||||
alignas(4) float depth = 0.0f;
|
||||
} gui;
|
||||
};
|
||||
}
|
||||
@ -22,6 +22,7 @@ namespace uf {
|
||||
void addImage( const uint8_t*, const pod::Vector2ui&, std::size_t, std::size_t, bool = false, bool = false );
|
||||
|
||||
void generate();
|
||||
void clear();
|
||||
|
||||
pod::Vector2f mapUv( const pod::Vector2f&, size_t );
|
||||
pod::Vector3f mapUv( const pod::Vector3f& );
|
||||
|
||||
@ -12,5 +12,6 @@ namespace uf {
|
||||
std::string UF_API lowercase( const std::string& );
|
||||
std::string UF_API uppercase( const std::string& );
|
||||
std::vector<std::string> UF_API split( const std::string&, const std::string& );
|
||||
std::string UF_API si( double value, const std::string& unit, size_t precision = 3 );
|
||||
}
|
||||
}
|
||||
@ -11,12 +11,22 @@
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
#include <uf/utils/string/hash.h>
|
||||
|
||||
UF_BEHAVIOR_REGISTER_CPP(GltfBehavior)
|
||||
#define this (&self)
|
||||
void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
metadata["textures"]["additional"] = Json::Value(Json::arrayValue);
|
||||
// Default load: GLTF model
|
||||
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
std::string filename = json["filename"].asString();
|
||||
if ( uf::io::extension(filename) != "png" ) return "false";
|
||||
auto& vector = metadata["textures"]["additional"];
|
||||
vector[vector.size()] = filename;
|
||||
return "true";
|
||||
});
|
||||
this->addHook( "asset:Load.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
std::string filename = json["filename"].asString();
|
||||
@ -28,16 +38,39 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
uf::Object* objectPointer = NULL;
|
||||
try { objectPointer = assetLoader.get<uf::Object*>(filename); } catch ( ... ) {}
|
||||
if ( !objectPointer ) return "false";
|
||||
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
objectPointer->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() || !entity->hasComponent<ext::gltf::mesh_t>() ) return;
|
||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
||||
auto& mesh = entity->getComponent<ext::gltf::mesh_t>();
|
||||
graphic.initialize();
|
||||
graphic.initializeGeometry( mesh );
|
||||
|
||||
graphic.material.attachShader("./data/shaders/gltf.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
graphic.material.attachShader("./data/shaders/gltf.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
{
|
||||
std::string filename = "/gltf.stereo.vert.spv";
|
||||
if ( metadata["system"]["renderer"]["shaders"]["vertex"].isString() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["vertex"].asString();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].asString() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_VERTEX_BIT);
|
||||
}
|
||||
{
|
||||
std::string filename = "/gltf.frag.spv";
|
||||
if ( metadata["system"]["renderer"]["shaders"]["fragment"].isString() )
|
||||
filename = metadata["system"]["renderer"]["shaders"]["fragment"].asString();
|
||||
filename = this->grabURI( filename, metadata["system"]["root"].asString() );
|
||||
graphic.material.attachShader(filename, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
|
||||
for ( int i = 0; i < metadata["textures"]["additional"].size(); ++i ) {
|
||||
std::string filename = metadata["textures"]["additional"][i].asString();
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& assetLoader = scene.getComponent<uf::Asset>();
|
||||
const uf::Image* imagePointer = NULL;
|
||||
try { imagePointer = &assetLoader.get<uf::Image>(filename); } catch ( ... ) {}
|
||||
if ( !imagePointer ) continue;
|
||||
uf::Image image = *imagePointer;
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( image );
|
||||
}
|
||||
|
||||
graphic.process = true;
|
||||
|
||||
@ -52,12 +85,15 @@ void uf::GltfBehavior::initialize( uf::Object& self ) {
|
||||
if ( binding.descriptorCount > 1 )
|
||||
binding.descriptorCount = specializationConstants->textures;
|
||||
}
|
||||
};
|
||||
objectPointer->process(filter);
|
||||
|
||||
});
|
||||
this->addChild(objectPointer->as<uf::Entity>());
|
||||
objectPointer->initialize();
|
||||
|
||||
objectPointer->process([&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() || !entity->hasComponent<ext::gltf::mesh_t>() ) return;
|
||||
auto& eMetadata = entity->getComponent<uf::Serializer>();
|
||||
eMetadata["textures"]["map"] = metadata["textures"]["map"];
|
||||
uf::instantiator::bind( "GltfBehavior", *entity );
|
||||
});
|
||||
return "true";
|
||||
});
|
||||
}
|
||||
@ -65,7 +101,50 @@ void uf::GltfBehavior::destroy( uf::Object& self ) {
|
||||
|
||||
}
|
||||
void uf::GltfBehavior::tick( uf::Object& self ) {
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
if ( !graphic.initialized ) return;
|
||||
auto& shader = graphic.material.shaders.back();
|
||||
if ( shader.uniforms.empty() ) return;
|
||||
auto& userdata = shader.uniforms.front();
|
||||
struct UniformDescriptor {
|
||||
// alignas(4) uint32_t mappings;
|
||||
struct Mapping {
|
||||
alignas(4) uint32_t target;
|
||||
alignas(4) float blend;
|
||||
uint32_t padding[2];
|
||||
} map;
|
||||
};
|
||||
size_t uniforms_len = userdata.data().len;
|
||||
uint8_t* uniforms_buffer = (uint8_t*) (void*) userdata;
|
||||
UniformDescriptor* uniforms = (UniformDescriptor*) uniforms_buffer;
|
||||
UniformDescriptor::Mapping* mappings = (UniformDescriptor::Mapping*) &uniforms_buffer[sizeof(UniformDescriptor) - sizeof(UniformDescriptor::Mapping)];
|
||||
|
||||
size_t textures = graphic.material.textures.size();
|
||||
// uniforms->mappings = textures;
|
||||
for ( size_t i = 0; i < textures; ++i ) {
|
||||
mappings[i].target = i;
|
||||
mappings[i].blend = 0.0f;
|
||||
}
|
||||
for ( auto it = metadata["textures"]["map"].begin(); it != metadata["textures"]["map"].end(); ++it ) {
|
||||
std::string key = it.key().asString();
|
||||
uint32_t from = std::stoi(key);
|
||||
uint32_t to = metadata["textures"]["map"][key][0].asUInt();
|
||||
float blend = 1.0f;
|
||||
if ( metadata["textures"]["map"][key][1].asString() == "sin(time)" ) {
|
||||
blend = sin(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( metadata["textures"]["map"][key][1].asString() == "cos(time)" ) {
|
||||
blend = cos(uf::physics::time::current)*0.5f+0.5f;
|
||||
} else if ( metadata["textures"]["map"][key][1].isNumeric() ) {
|
||||
blend = metadata["textures"]["map"][key][1].asFloat();
|
||||
}
|
||||
if ( from >= textures || to >= textures ) continue;
|
||||
mappings[from].target = to;
|
||||
mappings[from].blend = blend;
|
||||
}
|
||||
shader.updateBuffer( (void*) uniforms_buffer, uniforms_len, 0, false );
|
||||
};
|
||||
}
|
||||
void uf::GltfBehavior::render( uf::Object& self ) {
|
||||
|
||||
|
||||
@ -12,19 +12,6 @@
|
||||
uf::Timer<long long> uf::Object::timer(false);
|
||||
namespace {
|
||||
uf::Object null;
|
||||
std::string grabURI( std::string filename, std::string root = "" ) {
|
||||
if ( filename.substr(0,8) == "https://" ) return filename;
|
||||
std::string extension = uf::io::extension(filename);
|
||||
if ( filename[0] == '/' || root == "" ) {
|
||||
if ( filename.substr(0,9) == "/smtsamo/" ) root = "./data/";
|
||||
else if ( extension == "json" ) root = "./data/entities/";
|
||||
else if ( extension == "png" ) root = "./data/textures/";
|
||||
else if ( extension == "glb" ) root = "./data/models/";
|
||||
else if ( extension == "gltf" ) root = "./data/models/";
|
||||
else if ( extension == "ogg" ) root = "./data/audio/";
|
||||
}
|
||||
return uf::io::sanitize(filename, root);
|
||||
}
|
||||
}
|
||||
|
||||
UF_OBJECT_REGISTER_BEGIN(Object)
|
||||
@ -41,12 +28,22 @@ void uf::Object::queueHook( const std::string& name, const std::string& payload,
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
metadata["system"]["hooks"]["queue"].append(queue);
|
||||
}
|
||||
std::vector<std::string> uf::Object::callHook( const std::string& n, const std::string& payload ) {
|
||||
std::string name = uf::string::replace( n, "%UID%", std::to_string(this->getUid()) );
|
||||
return uf::hooks.call( name, payload );
|
||||
std::string uf::Object::formatHookName( const std::string& n ) {
|
||||
std::unordered_map<std::string, std::string> formats = {
|
||||
{"%UID%", std::to_string(this->getUid())},
|
||||
{"%P-UID%", std::to_string(this->getParent().getUid())},
|
||||
};
|
||||
std::string name = n;
|
||||
for ( auto& pair : formats ) {
|
||||
name = uf::string::replace( name, pair.first, pair.second );
|
||||
}
|
||||
return name;
|
||||
}
|
||||
std::vector<std::string> uf::Object::callHook( const std::string& name, const std::string& payload ) {
|
||||
return uf::hooks.call( this->formatHookName( name ), payload );
|
||||
}
|
||||
std::size_t uf::Object::addHook( const std::string& name, const uf::HookHandler::Readable::function_t& callback ) {
|
||||
std::string parsed = uf::string::replace( name, "%UID%", std::to_string(this->getUid()) );
|
||||
std::string parsed = this->formatHookName( name );
|
||||
std::size_t id = uf::hooks.addHook( parsed, callback );
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
metadata["system"]["hooks"]["alloc"][parsed].append(id);
|
||||
@ -76,6 +73,7 @@ bool uf::Object::reload( bool hard ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
if ( !metadata["system"]["source"].isString() ) return false;
|
||||
uf::Serializer json;
|
||||
uf::Serializer payload;
|
||||
std::string filename = metadata["system"]["source"].asString(); //grabURI( metadata["system"]["source"].asString(), metadata["system"]["root"].asString() ); // uf::io::sanitize(metadata["system"]["source"].asString(), metadata["system"]["root"].asString());
|
||||
if ( !json.readFromFile( filename ) ) {
|
||||
uf::iostream << "Error @ " << __FILE__ << ":" << __LINE__ << ": failed to open `" + filename + "`" << "\n";
|
||||
@ -83,11 +81,15 @@ bool uf::Object::reload( bool hard ) {
|
||||
return false;
|
||||
}
|
||||
if ( hard ) return this->load(filename);
|
||||
|
||||
payload["old"] = metadata;
|
||||
for ( auto it = json["metadata"].begin(); it != json["metadata"].end(); ++it ) {
|
||||
metadata[it.key().asString()] = json["metadata"][it.key().asString()];
|
||||
}
|
||||
payload["new"] = metadata;
|
||||
std::cout << "Updated metadata for " << this->getName() << ": " << this->getUid() << std::endl;
|
||||
this->queueHook("object:Reload.%UID%");
|
||||
|
||||
this->queueHook("object:Reload.%UID%", payload);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -306,6 +308,7 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
json["root"] = uf::io::directory(filename);
|
||||
json["source"] = filename; // uf::io::filename(filename)
|
||||
json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10;
|
||||
|
||||
if ( this->loadChildUid(json) == -1 ) continue;
|
||||
}
|
||||
}
|
||||
@ -411,4 +414,20 @@ std::size_t uf::Object::loadChildUid( const std::string& f, bool initialize ) {
|
||||
std::size_t uf::Object::loadChildUid( const uf::Serializer& json, bool initialize ) {
|
||||
uf::Object* pointer = this->loadChildPointer(json, initialize);
|
||||
return pointer ? pointer->getUid() : -1;
|
||||
}
|
||||
|
||||
std::string uf::Object::grabURI( const std::string& filename, const std::string& _root ) {
|
||||
std::string root = _root;
|
||||
if ( filename.substr(0,8) == "https://" ) return filename;
|
||||
std::string extension = uf::io::extension(filename);
|
||||
if ( filename[0] == '/' || root == "" ) {
|
||||
if ( filename.substr(0,9) == "/smtsamo/" ) root = "./data/";
|
||||
else if ( extension == "json" ) root = "./data/entities/";
|
||||
else if ( extension == "png" ) root = "./data/textures/";
|
||||
else if ( extension == "glb" ) root = "./data/models/";
|
||||
else if ( extension == "gltf" ) root = "./data/models/";
|
||||
else if ( extension == "ogg" ) root = "./data/audio/";
|
||||
else if ( extension == "spv" ) root = "./data/shaders/";
|
||||
}
|
||||
return uf::io::sanitize(filename, root);
|
||||
}
|
||||
@ -12,6 +12,7 @@
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/image/atlas.h>
|
||||
#include <uf/utils/string/hash.h>
|
||||
|
||||
namespace {
|
||||
|
||||
@ -224,6 +225,14 @@ void loadNode( uf::Object& entity, const tinygltf::Model& model, const tinygltf:
|
||||
auto& im = model.images[t.source];
|
||||
uf::Image& image = images.emplace_back();
|
||||
image.loadFromBuffer( &im.image[0], {im.width, im.height}, 8, im.component, true );
|
||||
/*
|
||||
{
|
||||
static int i = 0;
|
||||
auto& pixels = image.getPixels();
|
||||
std::string hash = uf::string::sha256( pixels );
|
||||
image.save("./textures/" + std::to_string(i++) + "."+hash+".png");
|
||||
}
|
||||
*/
|
||||
}
|
||||
if ( mode & ext::gltf::LoadMode::SEPARATE_MESHES ) {
|
||||
auto sampler = samplers.begin();
|
||||
|
||||
@ -468,7 +468,7 @@ void ext::openvr::submit() { bool invert = swapEyes;
|
||||
vulkanData.m_pDevice = ( VkDevice_T * ) ext::vulkan::device;
|
||||
vulkanData.m_pPhysicalDevice = ( VkPhysicalDevice_T * ) ext::vulkan::device.physicalDevice;
|
||||
vulkanData.m_pInstance = ( VkInstance_T *) ext::vulkan::device.instance;
|
||||
vulkanData.m_pQueue = ( VkQueue_T * ) ext::vulkan::device.queues.present;
|
||||
vulkanData.m_pQueue = ( VkQueue_T * ) ext::vulkan::device.getQueue( ext::vulkan::Device::QueueEnum::PRESENT );
|
||||
vulkanData.m_nQueueFamilyIndex = ext::vulkan::device.queueFamilyIndices.present;
|
||||
|
||||
vulkanData.m_nWidth = width;
|
||||
|
||||
@ -127,6 +127,15 @@ namespace {
|
||||
CHECK_FEATURE(inheritedQueries);
|
||||
}
|
||||
#undef CHECK_FEATURE
|
||||
|
||||
#define CHECK_FEATURE2( NAME )\
|
||||
if ( feature == #NAME ) {\
|
||||
if ( device.features2.NAME == VK_TRUE ) {\
|
||||
device.enabledFeatures2.NAME = true;\
|
||||
if ( ext::vulkan::validation ) std::cout << "Enabled feature: " << feature << std::endl;\
|
||||
} else if ( ext::vulkan::validation ) std::cout << "Failed to enable feature: " << feature << std::endl;\
|
||||
}
|
||||
#undef CHECK_FEATURE2
|
||||
}
|
||||
uf::Serializer retrieveDeviceFeatures( ext::vulkan::Device& device ) {
|
||||
uf::Serializer json;
|
||||
@ -192,6 +201,11 @@ namespace {
|
||||
CHECK_FEATURE(inheritedQueries);
|
||||
#undef CHECK_FEATURE
|
||||
|
||||
#define CHECK_FEATURE2( NAME )\
|
||||
json[#NAME]["supported"] = device.features2.NAME;\
|
||||
json[#NAME]["enabled"] = device.enabledFeatures2.NAME;
|
||||
#undef CHECK_FEATURE2
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
@ -295,7 +309,7 @@ int ext::vulkan::Device::rate( VkPhysicalDevice device ) {
|
||||
}
|
||||
|
||||
VkCommandBuffer ext::vulkan::Device::createCommandBuffer( VkCommandBufferLevel level, bool begin ){
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( commandPool.transfer, level, 1 );
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo( getCommandPool(QueueEnum::TRANSFER), level, 1 );
|
||||
|
||||
VkCommandBuffer commandBuffer;
|
||||
VK_CHECK_RESULT( vkAllocateCommandBuffers( logicalDevice, &cmdBufAllocateInfo, &commandBuffer ) );
|
||||
@ -322,14 +336,14 @@ void ext::vulkan::Device::flushCommandBuffer( VkCommandBuffer commandBuffer, boo
|
||||
VK_CHECK_RESULT(vkCreateFence(logicalDevice, &fenceInfo, nullptr, &fence));
|
||||
|
||||
// Submit to the queue
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device.queues.transfer, 1, &submitInfo, fence));
|
||||
VK_CHECK_RESULT(vkQueueSubmit( getQueue( QueueEnum::TRANSFER ), 1, &submitInfo, fence));
|
||||
// vkQueueSubmit(device.queues.transfer, 1, &submitInfo, fence);
|
||||
// Wait for the fence to signal that command buffer has finished executing
|
||||
VK_CHECK_RESULT(vkWaitForFences(logicalDevice, 1, &fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT));
|
||||
|
||||
vkDestroyFence(logicalDevice, fence, nullptr);
|
||||
|
||||
if ( free ) vkFreeCommandBuffers(logicalDevice, commandPool.transfer, 1, &commandBuffer);
|
||||
if ( free ) vkFreeCommandBuffers(logicalDevice, getCommandPool( QueueEnum::TRANSFER ), 1, &commandBuffer);
|
||||
}
|
||||
|
||||
VkResult ext::vulkan::Device::createBuffer( VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer* buffer, VkDeviceMemory* memory, void *data ) {
|
||||
@ -421,6 +435,71 @@ VkResult ext::vulkan::Device::createBuffer(
|
||||
// Attach the memory to the buffer object
|
||||
return buffer.bind();
|
||||
}
|
||||
VkCommandPool& ext::vulkan::Device::getCommandPool( ext::vulkan::Device::QueueEnum queueEnum ) {
|
||||
uint32_t index = 0;
|
||||
VkCommandPool* pool = NULL;
|
||||
bool exists = false;
|
||||
auto id = std::this_thread::get_id();
|
||||
switch ( queueEnum ) {
|
||||
case QueueEnum::GRAPHICS:
|
||||
index = device.queueFamilyIndices.graphics;
|
||||
if ( commandPool.graphics.count(id) > 0 ) exists = true;
|
||||
pool = &commandPool.graphics[id];
|
||||
break;
|
||||
case QueueEnum::COMPUTE:
|
||||
index = device.queueFamilyIndices.compute;
|
||||
if ( commandPool.compute.count(id) > 0 ) exists = true;
|
||||
pool = &commandPool.compute[id];
|
||||
break;
|
||||
case QueueEnum::TRANSFER:
|
||||
index = device.queueFamilyIndices.transfer;
|
||||
if ( commandPool.transfer.count(id) > 0 ) exists = true;
|
||||
pool = &commandPool.transfer[id];
|
||||
break;
|
||||
}
|
||||
if ( !exists ) {
|
||||
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmdPoolInfo.queueFamilyIndex = index;
|
||||
cmdPoolInfo.flags = createFlags;
|
||||
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, pool ) != VK_SUCCESS )
|
||||
throw std::runtime_error("failed to create command pool for graphics!");
|
||||
}
|
||||
return *pool;
|
||||
}
|
||||
VkQueue& ext::vulkan::Device::getQueue( ext::vulkan::Device::QueueEnum queueEnum ) {
|
||||
uint32_t index = 0;
|
||||
VkQueue* queue = NULL;
|
||||
bool exists = false;
|
||||
auto id = std::this_thread::get_id();
|
||||
switch ( queueEnum ) {
|
||||
case QueueEnum::GRAPHICS:
|
||||
index = device.queueFamilyIndices.graphics;
|
||||
if ( queues.graphics.count(id) > 0 ) exists = true;
|
||||
queue = &queues.graphics[id];
|
||||
break;
|
||||
case QueueEnum::PRESENT:
|
||||
index = device.queueFamilyIndices.present;
|
||||
if ( queues.present.count(id) > 0 ) exists = true;
|
||||
queue = &queues.present[id];
|
||||
break;
|
||||
case QueueEnum::COMPUTE:
|
||||
index = device.queueFamilyIndices.compute;
|
||||
if ( queues.compute.count(id) > 0 ) exists = true;
|
||||
queue = &queues.compute[id];
|
||||
break;
|
||||
case QueueEnum::TRANSFER:
|
||||
index = device.queueFamilyIndices.transfer;
|
||||
if ( queues.transfer.count(id) > 0 ) exists = true;
|
||||
queue = &queues.transfer[id];
|
||||
break;
|
||||
}
|
||||
if ( !exists ) {
|
||||
vkGetDeviceQueue( device, index, 0, queue );
|
||||
}
|
||||
return *queue;
|
||||
}
|
||||
|
||||
void ext::vulkan::Device::initialize() {
|
||||
const std::vector<const char*> validationLayers = {
|
||||
@ -540,7 +619,11 @@ void ext::vulkan::Device::initialize() {
|
||||
// Memory properties are used regularly for creating all kinds of buffers
|
||||
vkGetPhysicalDeviceMemoryProperties( this->physicalDevice, &memoryProperties );
|
||||
}
|
||||
if ( false ) {
|
||||
{
|
||||
properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
||||
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||
memoryProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
|
||||
|
||||
vkGetPhysicalDeviceProperties2( this->physicalDevice, &properties2 );
|
||||
// Features should be checked by the examples before using them
|
||||
vkGetPhysicalDeviceFeatures2( this->physicalDevice, &features2 );
|
||||
@ -553,6 +636,17 @@ void ext::vulkan::Device::initialize() {
|
||||
// assert(queueFamilyCount > 0);
|
||||
queueFamilyProperties.resize(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties( this->physicalDevice, &queueFamilyCount, queueFamilyProperties.data() );
|
||||
{
|
||||
VkSampleCountFlags counts = properties.limits.framebufferColorSampleCounts & properties.limits.framebufferDepthSampleCounts;
|
||||
uint8_t maxSamples = 1;
|
||||
if (counts & VK_SAMPLE_COUNT_64_BIT) maxSamples = 64;
|
||||
else if (counts & VK_SAMPLE_COUNT_32_BIT) maxSamples = 32;
|
||||
else if (counts & VK_SAMPLE_COUNT_16_BIT) maxSamples = 16;
|
||||
else if (counts & VK_SAMPLE_COUNT_8_BIT) maxSamples = 8;
|
||||
else if (counts & VK_SAMPLE_COUNT_4_BIT) maxSamples = 4;
|
||||
else if (counts & VK_SAMPLE_COUNT_2_BIT) maxSamples = 2;
|
||||
ext::vulkan::msaa = std::min( maxSamples, ext::vulkan::msaa );
|
||||
}
|
||||
}
|
||||
// Create logical device
|
||||
{
|
||||
@ -664,33 +758,9 @@ void ext::vulkan::Device::initialize() {
|
||||
std::cout << retrieveDeviceFeatures( *this ) << std::endl;
|
||||
}
|
||||
// Create command pool
|
||||
{
|
||||
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmdPoolInfo.queueFamilyIndex = queueFamilyIndices.graphics;
|
||||
cmdPoolInfo.flags = createFlags;
|
||||
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, &commandPool.graphics ) != VK_SUCCESS )
|
||||
throw std::runtime_error("failed to create command pool for graphics!");
|
||||
}
|
||||
{
|
||||
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmdPoolInfo.queueFamilyIndex = queueFamilyIndices.compute;
|
||||
cmdPoolInfo.flags = createFlags;
|
||||
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, &commandPool.compute ) != VK_SUCCESS )
|
||||
throw std::runtime_error("failed to create command pool for compute!");
|
||||
}
|
||||
{
|
||||
VkCommandPoolCreateFlags createFlags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
||||
VkCommandPoolCreateInfo cmdPoolInfo = {};
|
||||
cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
cmdPoolInfo.queueFamilyIndex = queueFamilyIndices.transfer;
|
||||
cmdPoolInfo.flags = createFlags;
|
||||
if ( vkCreateCommandPool( this->logicalDevice, &cmdPoolInfo, nullptr, &commandPool.transfer ) != VK_SUCCESS )
|
||||
throw std::runtime_error("failed to create command pool for transfer!");
|
||||
}
|
||||
getCommandPool( QueueEnum::GRAPHICS );
|
||||
getCommandPool( QueueEnum::COMPUTE );
|
||||
getCommandPool( QueueEnum::TRANSFER );
|
||||
// Set queue
|
||||
{
|
||||
uint32_t graphicsQueueNodeIndex = UINT32_MAX;
|
||||
@ -720,11 +790,16 @@ void ext::vulkan::Device::initialize() {
|
||||
}
|
||||
|
||||
device.queueFamilyIndices.present = presentQueueNodeIndex;
|
||||
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.graphics, 0, &queues.graphics );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.present, 0, &queues.present );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.compute, 0, &queues.compute );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.transfer, 0, &queues.transfer );
|
||||
getQueue( QueueEnum::GRAPHICS );
|
||||
getQueue( QueueEnum::PRESENT );
|
||||
getQueue( QueueEnum::COMPUTE );
|
||||
getQueue( QueueEnum::TRANSFER );
|
||||
/*
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.graphics, 0, &queues.graphics[std::this_thread::get_id()] );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.present, 0, &queues.present[std::this_thread::get_id()] );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.compute, 0, &queues.compute[std::this_thread::get_id()] );
|
||||
vkGetDeviceQueue( device, device.queueFamilyIndices.transfer, 0, &queues.transfer[std::this_thread::get_id()] );
|
||||
*/
|
||||
}
|
||||
// Set formats
|
||||
{
|
||||
@ -791,17 +866,17 @@ void ext::vulkan::Device::destroy() {
|
||||
vkDestroyPipelineCache( this->logicalDevice, this->pipelineCache, nullptr );
|
||||
this->pipelineCache = nullptr;
|
||||
}
|
||||
if ( this->commandPool.graphics ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, this->commandPool.graphics, nullptr );
|
||||
this->commandPool.graphics = nullptr;
|
||||
for ( auto& pair : this->commandPool.graphics ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, pair.second, nullptr );
|
||||
pair.second = VK_NULL_HANDLE;
|
||||
}
|
||||
if ( this->commandPool.compute ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, this->commandPool.compute, nullptr );
|
||||
this->commandPool.compute = nullptr;
|
||||
for ( auto& pair : this->commandPool.compute ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, pair.second, nullptr );
|
||||
pair.second = VK_NULL_HANDLE;
|
||||
}
|
||||
if ( this->commandPool.transfer ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, this->commandPool.transfer, nullptr );
|
||||
this->commandPool.transfer = nullptr;
|
||||
for ( auto& pair : this->commandPool.transfer ) {
|
||||
vkDestroyCommandPool( this->logicalDevice, pair.second, nullptr );
|
||||
pair.second = VK_NULL_HANDLE;
|
||||
}
|
||||
if ( this->logicalDevice ) {
|
||||
vkDestroyDevice( this->logicalDevice, nullptr );
|
||||
|
||||
@ -322,7 +322,7 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
|
||||
blendAttachmentStates.push_back(renderTarget.attachments[color.attachment].blendState);
|
||||
}
|
||||
// require blending if independentBlend is not an enabled feature
|
||||
if ( !device.enabledFeatures.independentBlend ) {
|
||||
if ( device.enabledFeatures.independentBlend == VK_FALSE ) {
|
||||
for ( size_t i = 1; i < blendAttachmentStates.size(); ++i ) {
|
||||
blendAttachmentStates[i] = blendAttachmentStates[0];
|
||||
}
|
||||
@ -365,8 +365,18 @@ void ext::vulkan::Pipeline::initialize( Graphic& graphic ) {
|
||||
VkPipelineViewportStateCreateInfo viewportState = ext::vulkan::initializers::pipelineViewportStateCreateInfo(
|
||||
1, 1, 0
|
||||
);
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
switch ( ext::vulkan::msaa ) {
|
||||
case 64: samples = VK_SAMPLE_COUNT_64_BIT; break;
|
||||
case 32: samples = VK_SAMPLE_COUNT_32_BIT; break;
|
||||
case 16: samples = VK_SAMPLE_COUNT_16_BIT; break;
|
||||
case 8: samples = VK_SAMPLE_COUNT_8_BIT; break;
|
||||
case 4: samples = VK_SAMPLE_COUNT_4_BIT; break;
|
||||
case 2: samples = VK_SAMPLE_COUNT_2_BIT; break;
|
||||
default: samples = VK_SAMPLE_COUNT_1_BIT; break;
|
||||
}
|
||||
VkPipelineMultisampleStateCreateInfo multisampleState = ext::vulkan::initializers::pipelineMultisampleStateCreateInfo(
|
||||
VK_SAMPLE_COUNT_1_BIT,
|
||||
samples,
|
||||
0
|
||||
);
|
||||
std::vector<VkDynamicState> dynamicStateEnables = {
|
||||
@ -460,7 +470,7 @@ void ext::vulkan::Pipeline::record( Graphic& graphic, VkCommandBuffer commandBuf
|
||||
}
|
||||
}
|
||||
// Bind descriptor sets describing shader binding points
|
||||
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
vkCmdBindDescriptorSets(commandBuffer, bindPoint, pipelineLayout, 0, 1, &descriptorSet, 0, nullptr);
|
||||
// Bind the rendering pipeline
|
||||
// The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time
|
||||
vkCmdBindPipeline(commandBuffer, bindPoint, pipeline);
|
||||
@ -493,11 +503,46 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
}
|
||||
{
|
||||
for ( auto& shader : graphic.material.shaders ) {
|
||||
std::vector<VkDescriptorBufferInfo> buffersStorageVector;
|
||||
std::vector<VkDescriptorBufferInfo> buffersUniformsVector;
|
||||
for ( auto& buffer : shader.buffers ) {
|
||||
if ( buffer.usageFlags & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) {
|
||||
auto& descriptor = buffersStorageVector.emplace_back(buffer.descriptor);
|
||||
if ( descriptor.offset % device->properties.limits.minStorageBufferOffsetAlignment != 0 ) {
|
||||
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl;
|
||||
descriptor.offset = 0;
|
||||
}
|
||||
}
|
||||
if ( buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) {
|
||||
auto& descriptor = buffersUniformsVector.emplace_back(buffer.descriptor);
|
||||
if ( descriptor.offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl;
|
||||
descriptor.offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( auto& buffer : graphic.buffers ) {
|
||||
if ( buffer.usageFlags & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT ) {
|
||||
auto& descriptor = buffersStorageVector.emplace_back(buffer.descriptor);
|
||||
if ( descriptor.offset % device->properties.limits.minStorageBufferOffsetAlignment != 0 ) {
|
||||
std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl;
|
||||
descriptor.offset = 0;
|
||||
}
|
||||
}
|
||||
if ( buffer.usageFlags & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ) {
|
||||
auto& descriptor = buffersUniformsVector.emplace_back(buffer.descriptor);
|
||||
if ( descriptor.offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||
std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.offset << std::endl;
|
||||
descriptor.offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto textures = graphic.material.textures.begin();
|
||||
auto samplers = graphic.material.samplers.begin();
|
||||
auto buffersUniforms = shader.buffers.begin();
|
||||
auto buffersStorage = graphic.buffers.begin();
|
||||
auto attachments = inputDescriptors.begin();
|
||||
auto buffersStorage = buffersStorageVector.begin();
|
||||
auto buffersUniforms = buffersUniformsVector.begin();
|
||||
|
||||
for ( auto& layout : shader.descriptorSetLayoutBindings ) {
|
||||
|
||||
@ -509,9 +554,6 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
size_t imageInfosStart = imageInfos.size();
|
||||
// assume we have a texture, and fill it in the slots as defaults
|
||||
size_t target = layout.descriptorCount;
|
||||
if ( target == 132 ) {
|
||||
target = graphic.material.textures.size();
|
||||
}
|
||||
for ( size_t i = 0; i < target; ++i ) {
|
||||
VkDescriptorImageInfo d = emptyTexture.descriptor;
|
||||
if ( textures != graphic.material.textures.end() ) {
|
||||
@ -558,27 +600,38 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
imageInfo = &((samplers++)->descriptor.info);
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
|
||||
if ( buffersUniforms == shader.buffers.end() ) {
|
||||
std::cout << "buffersUniforms == shader.buffers.end()" << std::endl;
|
||||
if ( buffersUniforms == buffersUniformsVector.end() ) {
|
||||
std::cout << "buffersUniforms == buffersUniformsVector.end()" << std::endl;
|
||||
break;
|
||||
}
|
||||
auto* descriptor = &(*(buffersUniforms++));
|
||||
if ( descriptor->offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||
std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor->offset << std::endl;
|
||||
descriptor->offset = 0;
|
||||
}
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
&((buffersUniforms++)->descriptor)
|
||||
descriptor
|
||||
));
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: {
|
||||
if ( buffersStorage == graphic.buffers.end() ) {
|
||||
std::cout << "buffersStorage == graphic.buffers.end()" << std::endl;
|
||||
if ( buffersStorage == buffersStorageVector.end() ) {
|
||||
std::cout << "buffersStorage == buffersStorageVector.end()" << std::endl;
|
||||
break;
|
||||
}
|
||||
auto* descriptor = &(*(buffersStorage++));
|
||||
if ( descriptor->offset % device->properties.limits.minStorageBufferOffsetAlignment != 0 ) {
|
||||
std::cout << __LINE__ << ": Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor->offset << std::endl;
|
||||
descriptor->offset = 0;
|
||||
}
|
||||
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
layout.binding,
|
||||
&((buffersStorage++)->descriptor)
|
||||
descriptor
|
||||
));
|
||||
} break;
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
|
||||
@ -591,6 +644,16 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
}
|
||||
|
||||
if ( imageInfo ) {
|
||||
if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || layout.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ) {
|
||||
if ( imageInfo->imageView == VK_NULL_HANDLE ) {
|
||||
imageInfo = &emptyTexture.descriptor;
|
||||
}
|
||||
}
|
||||
if ( layout.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || layout.descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ) {
|
||||
if ( imageInfo->sampler == VK_NULL_HANDLE ) {
|
||||
imageInfo->sampler = emptyTexture.sampler.sampler;
|
||||
}
|
||||
}
|
||||
writeDescriptorSets.push_back(ext::vulkan::initializers::writeDescriptorSet(
|
||||
descriptorSet,
|
||||
layout.descriptorType,
|
||||
@ -602,6 +665,22 @@ void ext::vulkan::Pipeline::update( Graphic& graphic ) {
|
||||
}
|
||||
}
|
||||
|
||||
for ( auto& descriptor : writeDescriptorSets ) {
|
||||
if ( descriptor.pBufferInfo ) {
|
||||
// std::cout << descriptor.pBufferInfo->offset << std::endl;
|
||||
if ( descriptor.pBufferInfo->offset % device->properties.limits.minUniformBufferOffsetAlignment != 0 ) {
|
||||
// std::cout << "Unaligned offset! Expecting " << device->properties.limits.minUniformBufferOffsetAlignment << ", got " << descriptor.pBufferInfo->offset << std::endl;
|
||||
std::cout << "Invalid descriptor for buffer: " << descriptor.pBufferInfo->buffer << " " << descriptor.pBufferInfo->offset << " " << descriptor.pBufferInfo->range << ", invalidating..." << std::endl;
|
||||
auto pointer = const_cast<VkDescriptorBufferInfo*>(descriptor.pBufferInfo);
|
||||
pointer->offset = 0;
|
||||
pointer->range = 0;
|
||||
pointer->buffer = VK_NULL_HANDLE;
|
||||
|
||||
// const_cast<VkDescriptorBufferInfo*>(descriptor.pBufferInfo)->offset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vkUpdateDescriptorSets(
|
||||
*device,
|
||||
writeDescriptorSets.size(),
|
||||
@ -667,10 +746,12 @@ void ext::vulkan::Graphic::initialize( const std::string& renderModeName ) {
|
||||
RenderMode& renderMode = ext::vulkan::getRenderMode(renderModeName, true);
|
||||
|
||||
this->descriptor.renderMode = renderModeName;
|
||||
auto* device = renderMode.device;
|
||||
if ( !device ) device = &ext::vulkan::device;
|
||||
|
||||
material.initialize( *renderMode.device );
|
||||
material.initialize( *device );
|
||||
|
||||
ext::vulkan::Buffers::initialize( *renderMode.device );
|
||||
ext::vulkan::Buffers::initialize( *device );
|
||||
}
|
||||
void ext::vulkan::Graphic::initializePipeline() {
|
||||
initializePipeline( this->descriptor, false );
|
||||
|
||||
@ -80,14 +80,14 @@ void ext::vulkan::RenderMode::render() {
|
||||
submitInfo.commandBufferCount = 1;
|
||||
|
||||
// Submit to the graphics queue passing a wait fence
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]));
|
||||
VK_CHECK_RESULT(vkQueueSubmit( device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[currentBuffer]));
|
||||
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]);
|
||||
|
||||
// Present the current buffer to the swap chain
|
||||
// Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation
|
||||
// This ensures that the image is not presented to the windowing system until all commands have been submitted
|
||||
VK_CHECK_RESULT(swapchain.queuePresent(device->queues.present, currentBuffer, renderCompleteSemaphore));
|
||||
VK_CHECK_RESULT(vkQueueWaitIdle(device->queues.present));
|
||||
VK_CHECK_RESULT(swapchain.queuePresent(device->getQueue( Device::QueueEnum::PRESENT ), currentBuffer, renderCompleteSemaphore));
|
||||
VK_CHECK_RESULT(vkQueueWaitIdle(device->getQueue( Device::QueueEnum::PRESENT )));
|
||||
}
|
||||
|
||||
void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
@ -105,7 +105,7 @@ void ext::vulkan::RenderMode::initialize( Device& device ) {
|
||||
commands.resize( swapchain.buffers );
|
||||
|
||||
VkCommandBufferAllocateInfo cmdBufAllocateInfo = ext::vulkan::initializers::commandBufferAllocateInfo(
|
||||
this->getType() == "Compute" ? device.commandPool.compute : device.commandPool.graphics,
|
||||
this->getType() == "Compute" ? device.getCommandPool(Device::QueueEnum::COMPUTE) : device.getCommandPool(Device::QueueEnum::GRAPHICS),
|
||||
VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||
static_cast<uint32_t>(commands.size())
|
||||
);
|
||||
@ -145,20 +145,23 @@ void ext::vulkan::RenderMode::destroy() {
|
||||
renderTarget.destroy();
|
||||
|
||||
if ( commands.size() > 0 ) {
|
||||
vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->commandPool.compute : device->commandPool.graphics, static_cast<uint32_t>(commands.size()), commands.data());
|
||||
vkFreeCommandBuffers( *device, this->getType() == "Compute" ? device->getCommandPool(Device::QueueEnum::COMPUTE) : device->getCommandPool(Device::QueueEnum::GRAPHICS), static_cast<uint32_t>(commands.size()), commands.data());
|
||||
}
|
||||
commands.clear();
|
||||
|
||||
if ( renderCompleteSemaphore != VK_NULL_HANDLE ) {
|
||||
vkDestroySemaphore( *device, renderCompleteSemaphore, nullptr);
|
||||
renderCompleteSemaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
for ( auto& fence : fences ) {
|
||||
vkDestroyFence( *device, fence, nullptr);
|
||||
fence = VK_NULL_HANDLE;
|
||||
}
|
||||
fences.clear();
|
||||
}
|
||||
void ext::vulkan::RenderMode::synchronize( uint64_t timeout ) {
|
||||
if ( !device ) return;
|
||||
if ( fences.empty() ) return;
|
||||
VK_CHECK_RESULT(vkWaitForFences( *device, fences.size(), fences.data(), VK_TRUE, timeout ));
|
||||
}
|
||||
void ext::vulkan::RenderMode::pipelineBarrier( VkCommandBuffer command, uint8_t stage ) {
|
||||
|
||||
@ -115,7 +115,7 @@ void ext::vulkan::ComputeRenderMode::render() {
|
||||
submitInfo.commandBufferCount = 1;
|
||||
submitInfo.pCommandBuffers = &commands[currentBuffer];
|
||||
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device->queues.compute, 1, &submitInfo, fences[currentBuffer]));
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::COMPUTE ), 1, &submitInfo, fences[currentBuffer]));
|
||||
//vkQueueSubmit(device->queues.compute, 1, &submitInfo, fences[currentBuffer]);
|
||||
}
|
||||
void ext::vulkan::ComputeRenderMode::tick() {
|
||||
|
||||
@ -103,13 +103,7 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||
/*
|
||||
struct SpecializationConstant {
|
||||
int32_t maxLights = 16;
|
||||
};
|
||||
auto& specializationConstants = shader.specializationConstants.get<SpecializationConstant>();
|
||||
specializationConstants.maxLights = metadata["system"]["config"]["engine"]["scenes"]["max lights"].asUInt64();
|
||||
*/
|
||||
|
||||
auto& shader = blitter.material.shaders.back();
|
||||
struct SpecializationConstant {
|
||||
uint32_t maxLights = 16;
|
||||
@ -120,6 +114,41 @@ void ext::vulkan::DeferredRenderMode::initialize( Device& device ) {
|
||||
if ( binding.descriptorCount > 1 )
|
||||
binding.descriptorCount = specializationConstants->maxLights;
|
||||
}
|
||||
/*
|
||||
std::vector<pod::Vector4f> palette;
|
||||
// size of palette
|
||||
if ( metadata["system"]["config"]["engine"]["scenes"]["palette"].isNumeric() ) {
|
||||
size_t size = metadata["system"]["config"]["engine"]["scenes"]["palette"].asUInt64();
|
||||
for ( size_t x = 0; x < size; ++x ) {
|
||||
palette.push_back(pod::Vector4f{
|
||||
(128.0f + 128.0f * sin(3.1415f * x / 16.0f)) / 256.0f,
|
||||
(128.0f + 128.0f * sin(3.1415f * x / 32.0f)) / 256.0f,
|
||||
(128.0f + 128.0f * sin(3.1415f * x / 64.0f)) / 256.0f,
|
||||
1.0f,
|
||||
});
|
||||
}
|
||||
// palette array
|
||||
} else if ( metadata["system"]["config"]["engine"]["scenes"]["palette"].isArray() ) {
|
||||
for ( int i = 0; i < metadata["system"]["config"]["engine"]["scenes"]["palette"].size(); ++i ) {
|
||||
auto& color = palette.emplace_back();
|
||||
palette.push_back(pod::Vector4f{
|
||||
metadata["system"]["config"]["engine"]["scenes"]["palette"][i][0].asFloat(),
|
||||
metadata["system"]["config"]["engine"]["scenes"]["palette"][i][1].asFloat(),
|
||||
metadata["system"]["config"]["engine"]["scenes"]["palette"][i][2].asFloat(),
|
||||
metadata["system"]["config"]["engine"]["scenes"]["palette"][i][3].asFloat(),
|
||||
});
|
||||
}
|
||||
}
|
||||
if ( !palette.empty() ) {
|
||||
shader.initializeBuffer(
|
||||
(void*) palette.data(),
|
||||
palette.size() * sizeof(pod::Vector4f),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
}
|
||||
*/
|
||||
}
|
||||
blitter.initializePipeline();
|
||||
}
|
||||
@ -133,6 +162,7 @@ void ext::vulkan::DeferredRenderMode::tick() {
|
||||
if ( blitter.initialized ) {
|
||||
auto& pipeline = blitter.getPipeline();
|
||||
pipeline.update( blitter );
|
||||
ext::vulkan::rebuild = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ void ext::vulkan::RenderTargetRenderMode::render() {
|
||||
submitInfo.pCommandBuffers = &commands[currentBuffer]; // Command buffers(s) to execute in this batch (submission)
|
||||
submitInfo.commandBufferCount = 1;
|
||||
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]));
|
||||
VK_CHECK_RESULT(vkQueueSubmit(device->getQueue( Device::QueueEnum::GRAPHICS ), 1, &submitInfo, fences[currentBuffer]));
|
||||
//vkQueueSubmit(device->queues.graphics, 1, &submitInfo, fences[currentBuffer]);
|
||||
/*
|
||||
VkSemaphoreWaitInfo waitInfo = {};
|
||||
|
||||
@ -48,9 +48,21 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
switch ( ext::vulkan::msaa ) {
|
||||
case 64: samples = VK_SAMPLE_COUNT_64_BIT; break;
|
||||
case 32: samples = VK_SAMPLE_COUNT_32_BIT; break;
|
||||
case 16: samples = VK_SAMPLE_COUNT_16_BIT; break;
|
||||
case 8: samples = VK_SAMPLE_COUNT_8_BIT; break;
|
||||
case 4: samples = VK_SAMPLE_COUNT_4_BIT; break;
|
||||
case 2: samples = VK_SAMPLE_COUNT_2_BIT; break;
|
||||
default: samples = VK_SAMPLE_COUNT_1_BIT; break;
|
||||
}
|
||||
|
||||
attachment->layout = layout;
|
||||
attachment->format = format;
|
||||
attachment->usage = usage;
|
||||
attachment->samples = samples;
|
||||
|
||||
VkImageCreateInfo imageCreateInfo = {};
|
||||
imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||
@ -59,7 +71,7 @@ size_t ext::vulkan::RenderTarget::attach( VkFormat format, VkImageUsageFlags usa
|
||||
imageCreateInfo.extent = { width, height, 1 };
|
||||
imageCreateInfo.mipLevels = 1;
|
||||
imageCreateInfo.arrayLayers = USEVR ? 2 : 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.samples = samples;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
imageCreateInfo.usage = usage;
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@ -151,7 +163,7 @@ void ext::vulkan::RenderTarget::initialize( Device& device ) {
|
||||
for ( auto& attachment : this->attachments ) {
|
||||
VkAttachmentDescription description;
|
||||
description.format = attachment.format;
|
||||
description.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
description.samples = attachment.samples;
|
||||
description.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
description.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
description.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
|
||||
@ -7,22 +7,29 @@ ext::vulkan::Texture2D ext::vulkan::Texture2D::empty;
|
||||
|
||||
void ext::vulkan::Sampler::initialize( Device& device ) {
|
||||
this->device = &device;
|
||||
|
||||
if ( device.enabledFeatures.samplerAnisotropy == VK_FALSE ) {
|
||||
descriptor.anisotropy.enabled = VK_FALSE;
|
||||
}
|
||||
{
|
||||
VkSamplerCreateInfo samplerCreateInfo = {};
|
||||
samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
samplerCreateInfo.minFilter = descriptor.filter.min;
|
||||
samplerCreateInfo.magFilter = descriptor.filter.mag;
|
||||
samplerCreateInfo.borderColor = descriptor.filter.borderColor;
|
||||
samplerCreateInfo.addressModeU = descriptor.addressMode.u;
|
||||
samplerCreateInfo.addressModeV = descriptor.addressMode.v;
|
||||
samplerCreateInfo.addressModeW = descriptor.addressMode.w;
|
||||
samplerCreateInfo.unnormalizedCoordinates = descriptor.addressMode.unnormalizedCoordinates;
|
||||
|
||||
samplerCreateInfo.mipmapMode = descriptor.mip.mode;
|
||||
samplerCreateInfo.mipLodBias = descriptor.mip.lodBias;
|
||||
samplerCreateInfo.compareOp = descriptor.compareOp;
|
||||
samplerCreateInfo.minLod = descriptor.lod.min;
|
||||
samplerCreateInfo.maxLod = descriptor.lod.max;
|
||||
samplerCreateInfo.maxAnisotropy = descriptor.maxAnisotropy;
|
||||
samplerCreateInfo.compareEnable = descriptor.mip.compareEnable;
|
||||
samplerCreateInfo.compareOp = descriptor.mip.compareOp;
|
||||
samplerCreateInfo.minLod = descriptor.mip.min;
|
||||
samplerCreateInfo.maxLod = descriptor.mip.max;
|
||||
|
||||
samplerCreateInfo.anisotropyEnable = descriptor.anisotropy.enabled;
|
||||
samplerCreateInfo.maxAnisotropy = descriptor.anisotropy.max;
|
||||
VK_CHECK_RESULT(vkCreateSampler(device.logicalDevice, &samplerCreateInfo, nullptr, &sampler));
|
||||
}
|
||||
{
|
||||
@ -72,9 +79,7 @@ void ext::vulkan::Texture::setImageLayout(
|
||||
VkImage image,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkImageSubresourceRange subresourceRange,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask
|
||||
VkImageSubresourceRange subresourceRange
|
||||
) {
|
||||
// Create an image barrier object
|
||||
VkImageMemoryBarrier imageMemoryBarrier = ext::vulkan::initializers::imageMemoryBarrier();
|
||||
@ -83,6 +88,9 @@ void ext::vulkan::Texture::setImageLayout(
|
||||
imageMemoryBarrier.image = image;
|
||||
imageMemoryBarrier.subresourceRange = subresourceRange;
|
||||
|
||||
VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
|
||||
// Source layouts (old)
|
||||
// Source access mask controls actions that have to be finished on the old layout
|
||||
// before it will be transitioned to the new layout
|
||||
@ -165,6 +173,20 @@ void ext::vulkan::Texture::setImageLayout(
|
||||
break;
|
||||
}
|
||||
|
||||
if ( oldImageLayout == VK_IMAGE_LAYOUT_UNDEFINED && newImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ) {
|
||||
imageMemoryBarrier.srcAccessMask = 0;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
} else if ( oldImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ) {
|
||||
imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
srcStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
}
|
||||
|
||||
// Put barrier inside setup command buffer
|
||||
vkCmdPipelineBarrier(
|
||||
cmdbuffer,
|
||||
@ -181,32 +203,29 @@ void ext::vulkan::Texture::setImageLayout(
|
||||
VkImageAspectFlags aspectMask,
|
||||
VkImageLayout oldImageLayout,
|
||||
VkImageLayout newImageLayout,
|
||||
VkPipelineStageFlags srcStageMask,
|
||||
VkPipelineStageFlags dstStageMask
|
||||
uint32_t mipLevels
|
||||
) {
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = aspectMask;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = 1;
|
||||
subresourceRange.levelCount = mipLevels;
|
||||
subresourceRange.layerCount = 1;
|
||||
setImageLayout(cmdbuffer, image, oldImageLayout, newImageLayout, subresourceRange, srcStageMask, dstStageMask);
|
||||
setImageLayout(cmdbuffer, image, oldImageLayout, newImageLayout, subresourceRange);
|
||||
}
|
||||
void ext::vulkan::Texture2D::loadFromFile(
|
||||
std::string filename,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout,
|
||||
bool forceLinear
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
return loadFromFile( filename, ext::vulkan::device, format, imageUsageFlags, imageLayout, forceLinear );
|
||||
return loadFromFile( filename, ext::vulkan::device, format, imageUsageFlags, imageLayout );
|
||||
}
|
||||
void ext::vulkan::Texture2D::loadFromFile(
|
||||
std::string filename,
|
||||
Device& device,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout,
|
||||
bool forceLinear
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
uf::Image image;
|
||||
image.open( filename );
|
||||
@ -281,18 +300,16 @@ void ext::vulkan::Texture2D::loadFromImage(
|
||||
uf::Image& image,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout,
|
||||
bool forceLinear
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
return loadFromImage( image, ext::vulkan::device, format, imageUsageFlags, imageLayout, forceLinear );
|
||||
return loadFromImage( image, ext::vulkan::device, format, imageUsageFlags, imageLayout );
|
||||
}
|
||||
void ext::vulkan::Texture2D::loadFromImage(
|
||||
uf::Image& image,
|
||||
Device& device,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsageFlags,
|
||||
VkImageLayout imageLayout,
|
||||
bool forceLinear
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
switch ( image.getChannels() ) {
|
||||
// R
|
||||
@ -358,37 +375,12 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
VkImageLayout imageLayout
|
||||
) {
|
||||
this->initialize(device, texWidth, texHeight);
|
||||
this->mips = 1;
|
||||
|
||||
// Use a separate command buffer for texture loading
|
||||
VkCommandBuffer copyCmd = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
//
|
||||
Buffer staging;
|
||||
|
||||
VK_CHECK_RESULT(device.createBuffer(
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
staging,
|
||||
bufferSize,
|
||||
data
|
||||
));
|
||||
|
||||
VkBufferImageCopy bufferCopyRegion = {};
|
||||
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
bufferCopyRegion.imageSubresource.mipLevel = 0;
|
||||
bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
|
||||
bufferCopyRegion.imageSubresource.layerCount = 1;
|
||||
bufferCopyRegion.imageExtent.width = width;
|
||||
bufferCopyRegion.imageExtent.height = height;
|
||||
bufferCopyRegion.imageExtent.depth = 1;
|
||||
bufferCopyRegion.bufferOffset = 0;
|
||||
|
||||
// Create optimal tiled target image
|
||||
VkImageCreateInfo imageCreateInfo = ext::vulkan::initializers::imageCreateInfo();
|
||||
imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||
imageCreateInfo.format = format;
|
||||
imageCreateInfo.mipLevels = this->mips;
|
||||
imageCreateInfo.format = this->format = format;
|
||||
imageCreateInfo.mipLevels = this->mips = static_cast<uint32_t>(std::floor(std::log2(std::max(texWidth, texHeight)))) + 1;
|
||||
imageCreateInfo.arrayLayers = 1;
|
||||
imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
@ -396,6 +388,10 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
imageCreateInfo.extent = { width, height, 1 };
|
||||
imageCreateInfo.usage = imageUsageFlags;
|
||||
// Ensure that the TRANSFER_SRC bit is set for mip creation
|
||||
if ( this->mips > 1 && !(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)) {
|
||||
imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
|
||||
}
|
||||
// Ensure that the TRANSFER_DST bit is set for staging
|
||||
if (!(imageCreateInfo.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
|
||||
imageCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
@ -405,62 +401,19 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &image, &allocation, &allocationInfo));
|
||||
deviceMemory = allocationInfo.deviceMemory;
|
||||
/*
|
||||
VK_CHECK_RESULT(vkCreateImage(device.logicalDevice, &imageCreateInfo, nullptr, &image));
|
||||
VkMemoryAllocateInfo memAlloc = staging.memAlloc;
|
||||
VkMemoryRequirements memReqs;
|
||||
vkGetImageMemoryRequirements(device.logicalDevice, image, &memReqs);
|
||||
memAlloc.allocationSize = staging.memReqs.size;
|
||||
memAlloc.memoryTypeIndex = device.getMemoryType(staging.memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device.logicalDevice, &memAlloc, nullptr, &deviceMemory));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device.logicalDevice, image, deviceMemory, 0));
|
||||
*/
|
||||
|
||||
// Create sampler
|
||||
sampler.descriptor.mip.min = 0;
|
||||
sampler.descriptor.mip.max = static_cast<float>(this->mips);
|
||||
sampler.initialize( device );
|
||||
|
||||
// Create image view
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = this->mips;
|
||||
subresourceRange.layerCount = 1;
|
||||
|
||||
// Image barrier for optimal image (target)
|
||||
// Optimal image will be used as destination for the copy
|
||||
setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
subresourceRange
|
||||
);
|
||||
// Copy mip levels from staging buffer
|
||||
vkCmdCopyBufferToImage(
|
||||
copyCmd,
|
||||
staging.buffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
&bufferCopyRegion
|
||||
);
|
||||
// Change texture image layout to shader read after all mip levels have been copied
|
||||
this->imageLayout = imageLayout;
|
||||
setImageLayout(
|
||||
copyCmd,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
imageLayout,
|
||||
subresourceRange
|
||||
);
|
||||
device.flushCommandBuffer(copyCmd);
|
||||
// Clean up staging resources
|
||||
/*
|
||||
vkFreeMemory(device.logicalDevice, staging.memory, nullptr);
|
||||
vkDestroyBuffer(device.logicalDevice, staging.buffer, nullptr);
|
||||
*/
|
||||
staging.destroy();
|
||||
|
||||
// Create sampler
|
||||
sampler.initialize( device );
|
||||
|
||||
// Create image view
|
||||
VkImageViewCreateInfo viewCreateInfo = {};
|
||||
viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||
viewCreateInfo.pNext = NULL;
|
||||
@ -471,7 +424,8 @@ void ext::vulkan::Texture2D::fromBuffers(
|
||||
viewCreateInfo.subresourceRange.levelCount = 1;
|
||||
viewCreateInfo.image = image;
|
||||
VK_CHECK_RESULT(vkCreateImageView(device.logicalDevice, &viewCreateInfo, nullptr, &view));
|
||||
// Update descriptor image info member that can be used for setting up descriptor sets
|
||||
|
||||
this->update( data, bufferSize, imageLayout );
|
||||
this->updateDescriptors();
|
||||
}
|
||||
|
||||
@ -505,14 +459,7 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
|
||||
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||
VK_CHECK_RESULT(vmaCreateImage(allocator, &imageCreateInfo, &allocInfo, &image, &allocation, &allocationInfo));
|
||||
deviceMemory = allocationInfo.deviceMemory;
|
||||
/*
|
||||
VK_CHECK_RESULT(vkCreateImage(device, &imageCreateInfo, nullptr, &image));
|
||||
vkGetImageMemoryRequirements(device, image, &memReqs);
|
||||
memAllocInfo.allocationSize = memReqs.size;
|
||||
memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
VK_CHECK_RESULT(vkAllocateMemory(device, &memAllocInfo, nullptr, &deviceMemory));
|
||||
VK_CHECK_RESULT(vkBindImageMemory(device, image, deviceMemory, 0));
|
||||
*/
|
||||
|
||||
VkCommandBuffer layoutCmd = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
@ -521,7 +468,8 @@ void ext::vulkan::Texture2D::asRenderTarget( Device& device, uint32_t width, uin
|
||||
image,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
imageLayout
|
||||
imageLayout,
|
||||
this->mips
|
||||
);
|
||||
|
||||
device.flushCommandBuffer(layoutCmd, true);
|
||||
@ -551,4 +499,177 @@ void ext::vulkan::Texture2D::aliasAttachment( const RenderTarget::Attachment& at
|
||||
if ( createSampler ) sampler.initialize( ext::vulkan::device );
|
||||
|
||||
this->updateDescriptors();
|
||||
}
|
||||
|
||||
void ext::vulkan::Texture2D::update( uf::Image& image, VkImageLayout targetImageLayout ) {
|
||||
if ( width != image.getDimensions()[0] || height != image.getDimensions()[1] )
|
||||
return;
|
||||
return this->update( (void*) image.getPixelsPtr(), image.getPixels().size() );
|
||||
}
|
||||
void ext::vulkan::Texture2D::update( void* data, VkDeviceSize bufferSize, VkImageLayout targetImageLayout ) {
|
||||
// Update descriptor image info member that can be used for setting up descriptor sets
|
||||
|
||||
auto& device = *this->device;
|
||||
|
||||
if ( targetImageLayout == VK_IMAGE_LAYOUT_UNDEFINED ) {
|
||||
targetImageLayout = this->imageLayout;
|
||||
}
|
||||
|
||||
// Create image view
|
||||
VkImageSubresourceRange subresourceRange = {};
|
||||
subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
subresourceRange.baseMipLevel = 0;
|
||||
subresourceRange.levelCount = this->mips;
|
||||
subresourceRange.layerCount = 1;
|
||||
|
||||
VkBufferImageCopy bufferCopyRegion = {};
|
||||
bufferCopyRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
bufferCopyRegion.imageSubresource.mipLevel = 0;
|
||||
bufferCopyRegion.imageSubresource.baseArrayLayer = 0;
|
||||
bufferCopyRegion.imageSubresource.layerCount = 1;
|
||||
bufferCopyRegion.imageExtent.width = width;
|
||||
bufferCopyRegion.imageExtent.height = height;
|
||||
bufferCopyRegion.imageExtent.depth = 1;
|
||||
bufferCopyRegion.bufferOffset = 0;
|
||||
//
|
||||
Buffer staging;
|
||||
VK_CHECK_RESULT(device.createBuffer(
|
||||
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
staging,
|
||||
bufferSize,
|
||||
data
|
||||
));
|
||||
|
||||
// Use a separate command buffer for texture loading
|
||||
VkCommandBuffer commandBuffer = device.createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
|
||||
|
||||
// Image barrier for optimal image (target)
|
||||
// Optimal image will be used as destination for the copy
|
||||
setImageLayout(
|
||||
commandBuffer,
|
||||
image,
|
||||
imageLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
subresourceRange
|
||||
);
|
||||
|
||||
// Copy mip levels from staging buffer
|
||||
vkCmdCopyBufferToImage(
|
||||
commandBuffer,
|
||||
staging.buffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1,
|
||||
&bufferCopyRegion
|
||||
);
|
||||
|
||||
this->generateMipmaps(commandBuffer);
|
||||
|
||||
setImageLayout(
|
||||
commandBuffer,
|
||||
image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
targetImageLayout,
|
||||
subresourceRange
|
||||
);
|
||||
device.flushCommandBuffer(commandBuffer);
|
||||
// Clean up staging resources
|
||||
staging.destroy();
|
||||
|
||||
this->imageLayout = targetImageLayout;
|
||||
|
||||
this->updateDescriptors();
|
||||
}
|
||||
|
||||
void ext::vulkan::Texture2D::generateMipmaps( VkCommandBuffer commandBuffer ) {
|
||||
auto& device = *this->device;
|
||||
|
||||
VkFormatProperties formatProperties;
|
||||
vkGetPhysicalDeviceFormatProperties(device.physicalDevice, format, &formatProperties);
|
||||
if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)) {
|
||||
throw std::runtime_error("texture image format does not support linear blitting!");
|
||||
}
|
||||
|
||||
|
||||
// base layer barrier
|
||||
VkImageMemoryBarrier barrier{};
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
barrier.image = image;
|
||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.subresourceRange.levelCount = 1;
|
||||
|
||||
int32_t mipWidth = width;
|
||||
int32_t mipHeight = height;
|
||||
for ( size_t i = 1; i < this->mips; ++i ) {
|
||||
|
||||
// transition previous layer to read from it
|
||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
vkCmdPipelineBarrier(commandBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
|
||||
// blit to current mip layer
|
||||
VkImageBlit blit{};
|
||||
blit.srcOffsets[0] = { 0, 0, 0 };
|
||||
blit.srcOffsets[1] = { mipWidth, mipHeight, 1 };
|
||||
blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit.srcSubresource.mipLevel = i - 1;
|
||||
blit.srcSubresource.baseArrayLayer = 0;
|
||||
blit.srcSubresource.layerCount = 1;
|
||||
blit.dstOffsets[0] = { 0, 0, 0 };
|
||||
blit.dstOffsets[1] = { mipWidth > 1 ? mipWidth / 2 : 1, mipHeight > 1 ? mipHeight / 2 : 1, 1 };
|
||||
blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
blit.dstSubresource.mipLevel = i;
|
||||
blit.dstSubresource.baseArrayLayer = 0;
|
||||
blit.dstSubresource.layerCount = 1;
|
||||
|
||||
vkCmdBlitImage(
|
||||
commandBuffer,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
1, &blit,
|
||||
VK_FILTER_LINEAR
|
||||
);
|
||||
|
||||
// transition previous layer back
|
||||
barrier.subresourceRange.baseMipLevel = i - 1;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
vkCmdPipelineBarrier(commandBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
|
||||
|
||||
if (mipWidth > 1) mipWidth /= 2;
|
||||
if (mipHeight > 1) mipHeight /= 2;
|
||||
}
|
||||
/*
|
||||
barrier.subresourceRange.baseMipLevel = this->mips - 1;
|
||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
vkCmdPipelineBarrier(commandBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
|
||||
0, nullptr,
|
||||
0, nullptr,
|
||||
1, &barrier
|
||||
);
|
||||
*/
|
||||
}
|
||||
@ -10,8 +10,11 @@
|
||||
|
||||
uint32_t ext::vulkan::width = 1280;
|
||||
uint32_t ext::vulkan::height = 720;
|
||||
uint8_t ext::vulkan::msaa = 1;
|
||||
|
||||
bool ext::vulkan::validation = true;
|
||||
bool ext::vulkan::rebuildOnTickStart = false;
|
||||
bool ext::vulkan::waitOnRenderEnd = false;
|
||||
std::vector<std::string> ext::vulkan::validationFilters;
|
||||
std::vector<std::string> ext::vulkan::requestedDeviceFeatures;
|
||||
std::vector<std::string> ext::vulkan::requestedDeviceExtensions;
|
||||
@ -49,7 +52,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL ext::vulkan::debugCallback(
|
||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
|
||||
void* pUserData
|
||||
) {
|
||||
if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE;
|
||||
// if ( messageSeverity <= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT ) return VK_FALSE;
|
||||
std::string message = pCallbackData->pMessage;
|
||||
for ( auto& filter : ext::vulkan::validationFilters ) {
|
||||
if ( message.find(filter) != std::string::npos ) return VK_FALSE;
|
||||
@ -276,15 +279,14 @@ void ext::vulkan::initialize( uint8_t stage ) {
|
||||
}
|
||||
void ext::vulkan::tick() {
|
||||
ext::vulkan::mutex.lock();
|
||||
if ( ext::vulkan::resized ) ext::vulkan::rebuild = true;
|
||||
if ( ext::vulkan::resized || ext::vulkan::rebuildOnTickStart ) {
|
||||
ext::vulkan::rebuild = true;
|
||||
}
|
||||
|
||||
std::function<void(uf::Entity*)> filter = [&]( uf::Entity* entity ) {
|
||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
||||
ext::vulkan::Graphic& graphic = entity->getComponent<uf::Graphic>();
|
||||
if ( graphic.initialized ) return;
|
||||
|
||||
if ( !graphic.process ) return;
|
||||
if ( graphic.initialized ) return;
|
||||
if ( graphic.initialized || !graphic.process || graphic.initialized ) return;
|
||||
graphic.initializePipeline();
|
||||
ext::vulkan::rebuild = true;
|
||||
};
|
||||
@ -310,7 +312,7 @@ void ext::vulkan::tick() {
|
||||
ext::vulkan::mutex.unlock();
|
||||
}
|
||||
void ext::vulkan::render() {
|
||||
// ext::vulkan::mutex.lock();
|
||||
ext::vulkan::mutex.lock();
|
||||
if ( hasRenderMode("Gui", true) ) {
|
||||
RenderMode& primary = getRenderMode("Gui", true);
|
||||
auto it = std::find( renderModes.begin(), renderModes.end(), &primary );
|
||||
@ -331,7 +333,15 @@ void ext::vulkan::render() {
|
||||
}
|
||||
|
||||
ext::vulkan::currentRenderMode = NULL;
|
||||
// ext::vulkan::mutex.unlock();
|
||||
if ( ext::vulkan::waitOnRenderEnd ) {
|
||||
for ( auto& renderMode : renderModes ) {
|
||||
if ( !renderMode ) continue;
|
||||
if ( !renderMode->execute ) continue;
|
||||
renderMode->synchronize();
|
||||
}
|
||||
vkDeviceWaitIdle( device );
|
||||
}
|
||||
ext::vulkan::mutex.unlock();
|
||||
}
|
||||
void ext::vulkan::destroy() {
|
||||
ext::vulkan::mutex.lock();
|
||||
|
||||
@ -60,10 +60,10 @@ void uf::Atlas::generate() {
|
||||
auto& dstBuffer = this->m_image.getPixels();
|
||||
|
||||
for ( size_t i = 0; i < size.x * size.y * 4; i+=4 ) {
|
||||
dstBuffer[i+0] = 255;
|
||||
dstBuffer[i+0] = 0;
|
||||
dstBuffer[i+1] = 0;
|
||||
dstBuffer[i+2] = 255;
|
||||
dstBuffer[i+3] = 255;
|
||||
dstBuffer[i+2] = 0;
|
||||
dstBuffer[i+3] = 0;
|
||||
}
|
||||
|
||||
for ( auto& it : stored.Get() ) {
|
||||
@ -84,6 +84,11 @@ void uf::Atlas::generate() {
|
||||
}
|
||||
}
|
||||
}
|
||||
void uf::Atlas::clear() {
|
||||
this->m_images.clear();
|
||||
this->m_image.clear();
|
||||
this->m_atlas = uf::Atlas::atlas_t{};
|
||||
}
|
||||
pod::Vector2f uf::Atlas::mapUv( const pod::Vector2f& uv, size_t index ) {
|
||||
BinPack2D::ContentAccumulator<uf::Atlas::identifier_t> stored;
|
||||
this->m_atlas.CollectContent( stored );
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
std::string UF_API uf::string::lowercase( const std::string& str ) {
|
||||
std::string lower = str;
|
||||
@ -27,4 +31,73 @@ std::string UF_API uf::string::replace( const std::string& string, const std::st
|
||||
if( start_pos == std::string::npos ) return result;
|
||||
result.replace(start_pos, search.length(), replace);
|
||||
return result;
|
||||
}
|
||||
std::string UF_API uf::string::si( double value, const std::string& unit, size_t precision ) {
|
||||
int power = floor(std::log10( value ));
|
||||
double base = value / std::pow( 10, power );
|
||||
|
||||
// std::cout << base << " x 10^" << power << " -> ";
|
||||
|
||||
size_t pValue = -1;
|
||||
#define REDUCE(VAL)\
|
||||
while ( pValue > power && power > VAL ) {\
|
||||
--power;\
|
||||
base *= 10;\
|
||||
}\
|
||||
pValue = VAL;
|
||||
#define INCREASE(VAL)\
|
||||
if ( pValue < power && power < VAL ) std::cout << " (increasing (" << pValue << ", " << VAL << ")) ";\
|
||||
while ( pValue < power && power < VAL ) {\
|
||||
++power;\
|
||||
base /= 10;\
|
||||
}\
|
||||
pValue = VAL;
|
||||
|
||||
REDUCE(24)
|
||||
REDUCE(21)
|
||||
REDUCE(18)
|
||||
REDUCE(15)
|
||||
REDUCE(12)
|
||||
REDUCE( 9)
|
||||
REDUCE( 6)
|
||||
REDUCE( 3)
|
||||
// REDUCE( 2)
|
||||
// REDUCE( 1)
|
||||
REDUCE( 0)
|
||||
/*
|
||||
// INCREASE(-1)
|
||||
INCREASE(-2)
|
||||
INCREASE(-3)
|
||||
INCREASE(-6)
|
||||
INCREASE(-9)
|
||||
INCREASE(-12)
|
||||
*/
|
||||
|
||||
// std::cout << base << " x 10^" << power << std::endl;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(precision) << base;
|
||||
std::string string = ss.str();
|
||||
|
||||
switch ( power ) {
|
||||
case 24: string += "Y"; break;
|
||||
case 21: string += "Z"; break;
|
||||
case 18: string += "E"; break;
|
||||
case 15: string += "P"; break;
|
||||
case 12: string += "T"; break;
|
||||
case 9: string += "G"; break;
|
||||
case 6: string += "M"; break;
|
||||
case 3: string += "k"; break;
|
||||
// case 2: string += "h"; break;
|
||||
// case 1: string += "da"; break;
|
||||
case 0: string += ""; break;
|
||||
// case -1: string += "d"; break;
|
||||
case -2: string += "c"; break;
|
||||
case -3: string += "m"; break;
|
||||
case -6: string += "μ"; break;
|
||||
case -9: string += "n"; break;
|
||||
case-12: string += "p"; break;
|
||||
}
|
||||
string += unit;
|
||||
return string;
|
||||
}
|
||||
@ -172,6 +172,7 @@ void ext::LightBehavior::destroy( uf::Object& self ){
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
uf::renderer::removeRenderMode( &renderMode, false );
|
||||
this->deleteComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
}
|
||||
}
|
||||
#undef this
|
||||
@ -158,5 +158,6 @@ void ext::PortalBehavior::render( uf::Object& self ){
|
||||
void ext::PortalBehavior::destroy( uf::Object& self ){
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
uf::renderer::removeRenderMode( &renderMode, false );
|
||||
this->deleteComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
}
|
||||
#undef this
|
||||
@ -85,7 +85,7 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
timer.reset();
|
||||
|
||||
uf::Serializer json = event;
|
||||
uf::Object* manager = (uf::Object*) this->findByName("Gui Manager");
|
||||
uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !manager ) return "false";
|
||||
uf::Serializer payload;
|
||||
// uf::Object* gui = (uf::Object*) manager->findByUid( (payload["uid"] = manager->loadChildUid("/scenes/worldscape/gui/pause/menu.json", false)).asUInt64() );
|
||||
@ -109,8 +109,10 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
return "true";
|
||||
});
|
||||
/* store viewport size */ {
|
||||
metadata["window"]["size"]["x"] = uf::renderer::width;
|
||||
metadata["window"]["size"]["y"] = uf::renderer::height;
|
||||
metadata["system"]["window"]["size"]["x"] = uf::renderer::width;
|
||||
metadata["system"]["window"]["size"]["y"] = uf::renderer::height;
|
||||
ext::gui::size.current.x = uf::renderer::width;
|
||||
ext::gui::size.current.y = uf::renderer::height;
|
||||
|
||||
this->addHook( "window:Resized", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
@ -120,7 +122,8 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
size.y = json["window"]["size"]["y"].asUInt64();
|
||||
}
|
||||
|
||||
metadata["window"] = json["window"];
|
||||
metadata["system"]["window"] = json["system"]["window"];
|
||||
ext::gui::size.current = size;
|
||||
|
||||
return "true";
|
||||
});
|
||||
@ -160,7 +163,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
|
||||
/* Regain control if nothing requests it */ {
|
||||
uf::Object* menu = (uf::Object*) this->findByName("Gui: Menu");
|
||||
uf::Object* menu = (uf::Object*) this->globalFindByName("Gui: Menu");
|
||||
if ( !menu ) {
|
||||
uf::Serializer payload;
|
||||
payload["state"] = false;
|
||||
@ -245,17 +248,20 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
alignas(16) pod::Vector4f ambient;
|
||||
struct Mode {
|
||||
alignas(8) pod::Vector2ui type;
|
||||
alignas(8) pod::Vector2ui padding;
|
||||
alignas(16) pod::Vector4f parameters;
|
||||
} mode;
|
||||
struct {
|
||||
alignas(8) pod::Vector2f range;
|
||||
alignas(16) pod::Vector4f color;
|
||||
alignas(8) pod::Vector2f range;
|
||||
alignas(8) pod::Vector2f padding;
|
||||
} fog;
|
||||
struct Light {
|
||||
alignas(16) pod::Vector4f position;
|
||||
alignas(16) pod::Vector4f color;
|
||||
alignas(4) uint32_t type;
|
||||
alignas(4) float depthBias;
|
||||
alignas(8) pod::Vector2f padding;
|
||||
alignas(16) pod::Matrix4f view;
|
||||
alignas(16) pod::Matrix4f projection;
|
||||
} lights;
|
||||
|
||||
@ -4,15 +4,15 @@
|
||||
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <uf/utils/math/transform.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <uf/engine/asset/asset.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
EXT_BEHAVIOR_REGISTER_CPP(StaticEmitterBehavior)
|
||||
#define this ((uf::Scene*) &self)
|
||||
|
||||
#define this ((uf::Object*) &self)
|
||||
void ext::StaticEmitterBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
auto* hud = this->loadChildPointer("/hud.json", true);
|
||||
metadata["hud"]["uid"] = hud->getUid();
|
||||
}
|
||||
void ext::StaticEmitterBehavior::tick( uf::Object& self ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
@ -37,9 +37,7 @@ void ext::StaticEmitterBehavior::tick( uf::Object& self ) {
|
||||
float pieces = metadata["static"]["pieces"].isNumeric() ? metadata["static"]["pieces"].asFloat() : 1000;
|
||||
|
||||
uint32_t mode = sMetadata["system"]["renderer"]["shader"]["mode"].asUInt();
|
||||
if ( !(mode & 0x2) ) {
|
||||
mode = mode | 0x2;
|
||||
}
|
||||
mode |= (0x1 << 1);
|
||||
|
||||
sMetadata["system"]["renderer"]["shader"]["mode"] = mode;
|
||||
sMetadata["system"]["renderer"]["shader"]["parameters"][0] = flicker;
|
||||
@ -47,6 +45,22 @@ void ext::StaticEmitterBehavior::tick( uf::Object& self ) {
|
||||
sMetadata["system"]["renderer"]["shader"]["parameters"][2] = staticBlend;
|
||||
sMetadata["system"]["renderer"]["shader"]["parameters"][3] = "time";
|
||||
}
|
||||
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start();
|
||||
if ( metadata["hud"]["uid"].isNumeric() && timer.elapsed().asDouble() > 0.125 ) {
|
||||
timer.reset();
|
||||
auto* hud = this->findByUid( metadata["hud"]["uid"].asUInt64() );
|
||||
auto& hMetadata = hud->getComponent<uf::Serializer>();
|
||||
double d = uf::vector::distance( cTransform.position, transform.position );
|
||||
std::string string = uf::string::si( d, "m" );
|
||||
hMetadata["text settings"]["alpha"] = 0.5f;
|
||||
if ( hMetadata["text settings"]["string"].asString() != string ) {
|
||||
uf::Serializer payload;
|
||||
payload["string"] = string;
|
||||
hud->as<uf::Object>().callHook("gui:UpdateString.%UID%", payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ext::StaticEmitterBehavior::render( uf::Object& self ){}
|
||||
|
||||
1478
ext/gui/behavior.cpp
1478
ext/gui/behavior.cpp
File diff suppressed because it is too large
Load Diff
@ -4,14 +4,35 @@
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
|
||||
#include "behavior.h"
|
||||
|
||||
namespace pod {
|
||||
struct GlyphBox {
|
||||
struct {
|
||||
float x, y, w, h;
|
||||
} box;
|
||||
uint64_t code;
|
||||
pod::Vector3f color;
|
||||
};
|
||||
}
|
||||
|
||||
namespace ext {
|
||||
class EXT_API Gui : public uf::Object {
|
||||
public:
|
||||
Gui() {
|
||||
this->addBehavior<ext::GuiBehavior>();
|
||||
}
|
||||
typedef uf::BaseMesh<pod::Vertex_3F2F3F> glyph_mesh_t;
|
||||
|
||||
Gui();
|
||||
std::vector<pod::GlyphBox> generateGlyphs( const std::string& = "" );
|
||||
void load( uf::Image& );
|
||||
};
|
||||
namespace gui {
|
||||
struct Size {
|
||||
pod::Vector2ui current = {};
|
||||
pod::Vector2ui reference = {};
|
||||
};
|
||||
extern Size size;
|
||||
}
|
||||
}
|
||||
204
ext/gui/manager/behavior.cpp
Normal file
204
ext/gui/manager/behavior.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
#include "behavior.h"
|
||||
#include "../gui.h"
|
||||
|
||||
#include <uf/utils/hook/hook.h>
|
||||
#include <uf/utils/time/time.h>
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <uf/utils/userdata/userdata.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
#include <uf/utils/text/glyph.h>
|
||||
#include <uf/engine/asset/asset.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
#include <uf/utils/http/http.h>
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <regex>
|
||||
|
||||
ext::gui::Size ext::gui::size = {
|
||||
.current = {
|
||||
uf::renderer::width,
|
||||
uf::renderer::height,
|
||||
},
|
||||
.reference = {
|
||||
1920,
|
||||
1080
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
EXT_BEHAVIOR_REGISTER_CPP(GuiManagerBehavior)
|
||||
EXT_BEHAVIOR_REGISTER_AS_OBJECT(GuiManagerBehavior, GuiManager)
|
||||
#define this (&self)
|
||||
void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
{
|
||||
ext::gui::size.current.x = uf::renderer::width;
|
||||
ext::gui::size.current.y = uf::renderer::height;
|
||||
}
|
||||
// add gui render mode
|
||||
if ( !uf::renderer::hasRenderMode( "Gui", true ) ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
std::string name = "Gui";
|
||||
uf::renderer::addRenderMode( &renderMode, name );
|
||||
renderMode.blitter.descriptor.subpass = 1;
|
||||
}
|
||||
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
uf::Asset& assetLoader = this->getComponent<uf::Asset>();
|
||||
|
||||
this->addHook( "window:Resized", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
pod::Vector2ui size; {
|
||||
size.x = json["window"]["size"]["x"].asUInt64();
|
||||
size.y = json["window"]["size"]["y"].asUInt64();
|
||||
}
|
||||
ext::gui::size.current = size;
|
||||
// ext::gui::size.reference = size;
|
||||
|
||||
return "true";
|
||||
} );
|
||||
this->addHook( "window:Mouse.Moved", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
bool down = json["mouse"]["state"].asString() == "Down";
|
||||
bool clicked = false;
|
||||
pod::Vector2ui position; {
|
||||
position.x = json["mouse"]["position"]["x"].asInt() > 0 ? json["mouse"]["position"]["x"].asUInt() : 0;
|
||||
position.y = json["mouse"]["position"]["y"].asInt() > 0 ? json["mouse"]["position"]["y"].asUInt() : 0;
|
||||
}
|
||||
pod::Vector2f click; {
|
||||
click.x = (float) position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) position.y / (float) ext::gui::size.current.y;
|
||||
click.x = (click.x * 2.0f) - 1.0f;
|
||||
click.y = (click.y * 2.0f) - 1.0f;
|
||||
float x = click.x;
|
||||
float y = click.y;
|
||||
}
|
||||
|
||||
{
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = scene.getController();
|
||||
auto& metadata = controller.getComponent<uf::Serializer>();
|
||||
|
||||
if ( metadata["overlay"]["cursor"]["type"].asString() == "mouse" ) {
|
||||
metadata["overlay"]["cursor"]["position"][0] = click.x;
|
||||
metadata["overlay"]["cursor"]["position"][1] = click.y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return "true";
|
||||
});
|
||||
}
|
||||
void ext::GuiManagerBehavior::tick( uf::Object& self ) {
|
||||
|
||||
}
|
||||
void ext::GuiManagerBehavior::render( uf::Object& self ){
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& controller = scene.getController();
|
||||
auto& camera = controller.getComponent<uf::Camera>();
|
||||
auto& metadata = controller.getComponent<uf::Serializer>();
|
||||
|
||||
uf::renderer::RenderTargetRenderMode* renderModePointer = NULL;
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
renderModePointer = this->getComponentPointer<uf::renderer::RenderTargetRenderMode>();
|
||||
} else {
|
||||
renderModePointer = (uf::renderer::RenderTargetRenderMode*) &uf::renderer::getRenderMode( "Gui", true );
|
||||
}
|
||||
auto& renderMode = *renderModePointer;
|
||||
auto& blitter = renderMode.blitter;
|
||||
struct UniformDescriptor {
|
||||
struct {
|
||||
alignas(16) pod::Matrix4f models[2];
|
||||
} matrices;
|
||||
struct {
|
||||
alignas(8) pod::Vector2f position = { 0.5f, 0.5f };
|
||||
alignas(8) pod::Vector2f radius = { 0.1f, 0.1f };
|
||||
alignas(16) pod::Vector4f color = { 1, 1, 1, 1 };
|
||||
} cursor;
|
||||
// alignas(8) pod::Vector2f alpha;
|
||||
};
|
||||
auto& shader = blitter.material.shaders.front();
|
||||
auto& uniforms = shader.uniforms.front().get<UniformDescriptor>();
|
||||
|
||||
for ( size_t i = 0; i < 2; ++i ) {
|
||||
pod::Transform<> transform;
|
||||
if ( metadata["overlay"]["position"].isArray() )
|
||||
transform.position = {
|
||||
metadata["overlay"]["position"][0].asFloat(),
|
||||
metadata["overlay"]["position"][1].asFloat(),
|
||||
metadata["overlay"]["position"][2].asFloat(),
|
||||
};
|
||||
if ( metadata["overlay"]["scale"].isArray() )
|
||||
transform.scale = {
|
||||
metadata["overlay"]["scale"][0].asFloat(),
|
||||
metadata["overlay"]["scale"][1].asFloat(),
|
||||
metadata["overlay"]["scale"][2].asFloat(),
|
||||
};
|
||||
if ( metadata["overlay"]["orientation"].isArray() )
|
||||
transform.orientation = {
|
||||
metadata["overlay"]["orientation"][0].asFloat(),
|
||||
metadata["overlay"]["orientation"][1].asFloat(),
|
||||
metadata["overlay"]["orientation"][2].asFloat(),
|
||||
metadata["overlay"]["orientation"][3].asFloat(),
|
||||
};
|
||||
if ( ext::openvr::enabled && (metadata["overlay"]["enabled"].asBool() || uf::renderer::getRenderMode("Stereoscopic Deferred", true).getType() == "Stereoscopic Deferred" )) {
|
||||
if ( metadata["overlay"]["floating"].asBool() ) {
|
||||
pod::Matrix4f model = uf::transform::model( transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * ext::openvr::hmdEyePositionMatrix( i == 0 ? vr::Eye_Left : vr::Eye_Right ) * model;
|
||||
} else {
|
||||
auto translation = uf::matrix::translate( uf::matrix::identity(), camera.getTransform().position + controller.getComponent<pod::Transform<>>().position );
|
||||
auto rotation = uf::quaternion::matrix( controller.getComponent<pod::Transform<>>().orientation * pod::Vector4f{1,1,1,-1} );
|
||||
|
||||
pod::Matrix4f model = translation * rotation * uf::transform::model( transform );
|
||||
uniforms.matrices.models[i] = camera.getProjection(i) * camera.getView(i) * model;
|
||||
}
|
||||
} else {
|
||||
pod::Matrix4t<> model = uf::matrix::translate( uf::matrix::identity(), { 0, 0, 1 } );
|
||||
uniforms.matrices.models[i] = model;
|
||||
}
|
||||
// uniforms.alpha.x = metadata["overlay"]["alpha"].asFloat();
|
||||
// uniforms.alpha.y = 0;
|
||||
|
||||
uniforms.cursor.position.x = (metadata["overlay"]["cursor"]["position"][0].asFloat() + 1.0f) * 0.5f; //(::mouse.position.x + 1.0f) * 0.5f;
|
||||
uniforms.cursor.position.y = (metadata["overlay"]["cursor"]["position"][1].asFloat() + 1.0f) * 0.5f; //(::mouse.position.y + 1.0f) * 0.5f;
|
||||
|
||||
pod::Vector3f cursorSize;
|
||||
cursorSize.x = metadata["overlay"]["cursor"]["radius"].asFloat();
|
||||
cursorSize.y = metadata["overlay"]["cursor"]["radius"].asFloat();
|
||||
cursorSize = uf::matrix::multiply<float>( uf::matrix::inverse( uf::matrix::scale( uf::matrix::identity() , transform.scale) ), cursorSize );
|
||||
|
||||
uniforms.cursor.radius.x = cursorSize.x;
|
||||
uniforms.cursor.radius.y = cursorSize.y;
|
||||
|
||||
uniforms.cursor.color.x = metadata["overlay"]["cursor"]["color"][0].asFloat();
|
||||
uniforms.cursor.color.y = metadata["overlay"]["cursor"]["color"][1].asFloat();
|
||||
uniforms.cursor.color.z = metadata["overlay"]["cursor"]["color"][2].asFloat();
|
||||
uniforms.cursor.color.w = metadata["overlay"]["cursor"]["color"][3].asFloat();
|
||||
}
|
||||
shader.updateBuffer( (void*) &uniforms, sizeof(uniforms), 0 );
|
||||
}
|
||||
void ext::GuiManagerBehavior::destroy( uf::Object& self ){
|
||||
if ( this->hasComponent<uf::renderer::RenderTargetRenderMode>() ) {
|
||||
auto& renderMode = this->getComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
uf::renderer::removeRenderMode( &renderMode, false );
|
||||
this->deleteComponent<uf::renderer::RenderTargetRenderMode>();
|
||||
}
|
||||
}
|
||||
#undef this
|
||||
17
ext/gui/manager/behavior.h
Normal file
17
ext/gui/manager/behavior.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
|
||||
namespace ext {
|
||||
class EXT_API GuiManagerBehavior {
|
||||
public:
|
||||
static void attach( uf::Object& );
|
||||
static void initialize( uf::Object& );
|
||||
static void tick( uf::Object& );
|
||||
static void render( uf::Object& );
|
||||
static void destroy( uf::Object& );
|
||||
};
|
||||
}
|
||||
41
ext/main.cpp
41
ext/main.cpp
@ -64,9 +64,38 @@ namespace {
|
||||
uf::Serializer config;
|
||||
}
|
||||
bool ext::ready = false;
|
||||
std::vector<std::string> ext::arguments;
|
||||
|
||||
void EXT_API ext::initialize() {
|
||||
/**/ {
|
||||
::config = ext::getConfig();
|
||||
/* Arguments */ {
|
||||
auto& arguments = ::config["arguments"];
|
||||
for ( auto& arg : ext::arguments ) {
|
||||
// store raw argument
|
||||
int i = arguments.size();
|
||||
arguments[i] = arg;
|
||||
// parse --key=value
|
||||
{
|
||||
std::regex regex("^--(.+?)=(.+?)$");
|
||||
std::smatch match;
|
||||
if ( std::regex_search( arg, match, regex ) ) {
|
||||
std::string keyString = match[1].str();
|
||||
std::string valueString = match[2].str();
|
||||
auto keys = uf::string::split(keyString, ".");
|
||||
uf::Serializer value; value.deserialize(valueString);
|
||||
Json::Value* traversal = &::config;
|
||||
for ( auto& key : keys ) {
|
||||
traversal = &((*traversal)[key]);
|
||||
}
|
||||
*traversal = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
uf::iostream << "Arguments: " << uf::Serializer(arguments) << "\n";
|
||||
uf::iostream << "New config: " << ::config << "\n";
|
||||
}
|
||||
|
||||
/* Seed */ {
|
||||
srand(time(NULL));
|
||||
}
|
||||
/* Open output file */ {
|
||||
@ -84,7 +113,6 @@ void EXT_API ext::initialize() {
|
||||
// #include "./inits/persistence.inl"
|
||||
}
|
||||
|
||||
::config = ext::getConfig();
|
||||
/* Parse config */ {
|
||||
// Set memory pool sizes
|
||||
{
|
||||
@ -153,6 +181,11 @@ void EXT_API ext::initialize() {
|
||||
uf::thread::workers = ::config["engine"]["threads"]["workers"].asUInt64();
|
||||
// Enable valiation layer
|
||||
uf::renderer::validation = ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].asBool();
|
||||
if ( ::config["engine"]["ext"]["vulkan"]["validation"]["enabled"].isNumeric() )
|
||||
uf::renderer::msaa = ::config["engine"]["ext"]["vulkan"]["msaa"].asUInt64();
|
||||
|
||||
uf::renderer::rebuildOnTickStart = ::config["engine"]["ext"]["vulkan"]["validation"]["rebuild on tick begin"].asBool();
|
||||
uf::renderer::waitOnRenderEnd = ::config["engine"]["ext"]["vulkan"]["validation"]["wait on render end"].asBool();
|
||||
|
||||
for ( int i = 0; i < ::config["engine"]["ext"]["vulkan"]["validation"]["filters"].size(); ++i ) {
|
||||
uf::renderer::validationFilters.push_back( ::config["engine"]["ext"]["vulkan"]["validation"]["filters"][i].asString() );
|
||||
@ -196,7 +229,6 @@ void EXT_API ext::initialize() {
|
||||
uf::renderer::addRenderMode( renderMode, "Gui" );
|
||||
renderMode->blitter.descriptor.subpass = 1;
|
||||
}
|
||||
|
||||
if ( ::config["engine"]["render modes"]["stereo deferred"].asBool() )
|
||||
uf::renderer::addRenderMode( new uf::renderer::StereoscopicDeferredRenderMode, "" );
|
||||
else if ( ::config["engine"]["render modes"]["deferred"].asBool() )
|
||||
@ -240,6 +272,9 @@ void EXT_API ext::initialize() {
|
||||
/* Add hooks */ {
|
||||
uf::hooks.addHook( "game:LoadScene", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
std::cout << "SCENE CHANGE: " << event << std::endl;
|
||||
uf::renderer::mutex.lock();
|
||||
uf::renderer::mutex.unlock();
|
||||
uf::scene::unloadScene();
|
||||
auto& scene = uf::scene::loadScene( json["scene"].asString() );
|
||||
auto& metadata = scene.getComponent<uf::Serializer>();
|
||||
|
||||
@ -68,7 +68,7 @@ void ext::RayTracingSceneBehavior::initialize( uf::Object& self ) {
|
||||
renderMode.compute.initializeBuffer(
|
||||
(void*) shapes.data(),
|
||||
shapes.size() * sizeof(Shape),
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
true
|
||||
);
|
||||
|
||||
@ -74,7 +74,7 @@ void ext::WorldScapeSceneBehavior::initialize( uf::Object& self ) {
|
||||
this->addHook( "world:Battle.Start", [&](const std::string& event)->std::string{
|
||||
if ( timer.elapsed().asDouble() < 1 ) return "false";
|
||||
timer.reset();
|
||||
uf::Object* guiManager = (uf::Object*) this->findByName("Gui Manager");
|
||||
uf::Object* guiManager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !guiManager ) return "false";
|
||||
uf::Serializer json = event;
|
||||
|
||||
@ -88,7 +88,7 @@ void ext::WorldScapeSceneBehavior::initialize( uf::Object& self ) {
|
||||
});
|
||||
this->addHook( "world:Battle.End", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
ext::HousamoBattle* battleManager = (ext::HousamoBattle*) this->findByName("Battle Manager");
|
||||
ext::HousamoBattle* battleManager = (ext::HousamoBattle*) this->globalFindByName("Battle Manager");
|
||||
if ( !battleManager ) return "false";
|
||||
|
||||
this->removeChild(*battleManager);
|
||||
@ -100,7 +100,7 @@ void ext::WorldScapeSceneBehavior::initialize( uf::Object& self ) {
|
||||
this->addHook( "menu:Dialogue.Start", [&](const std::string& event)->std::string{
|
||||
if ( timer.elapsed().asDouble() < 1 ) return "false";
|
||||
timer.reset();
|
||||
uf::Object* guiManager = (uf::Object*) this->findByName("Gui Manager");
|
||||
uf::Object* guiManager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !guiManager ) return "false";
|
||||
uf::Serializer json = event;
|
||||
|
||||
@ -112,7 +112,7 @@ void ext::WorldScapeSceneBehavior::initialize( uf::Object& self ) {
|
||||
});
|
||||
this->addHook( "menu:Dialogue.End", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
ext::DialogueManager* dialogueManager = (ext::DialogueManager*) this->findByName("Dialogue Manager");
|
||||
ext::DialogueManager* dialogueManager = (ext::DialogueManager*) this->globalFindByName("Dialogue Manager");
|
||||
if ( !dialogueManager ) return "false";
|
||||
|
||||
this->removeChild(*dialogueManager);
|
||||
|
||||
@ -206,37 +206,37 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
battleMessage = new ext::Gui;
|
||||
this->addChild(*battleMessage);
|
||||
battleMessage->load("./battle-text.json", true);
|
||||
battleMessage->as<uf::Object>().load("./battle-text.json", true);
|
||||
battleMessage->initialize();
|
||||
}
|
||||
/* Magic Circle Outter */ {
|
||||
circleOut = new ext::Gui;
|
||||
this->addChild(*circleOut);
|
||||
circleOut->load("./circle-out.json", true);
|
||||
circleOut->as<uf::Object>().load("./circle-out.json", true);
|
||||
circleOut->initialize();
|
||||
}
|
||||
/* Magic Circle Inner */ {
|
||||
circleIn = new ext::Gui;
|
||||
this->addChild(*circleIn);
|
||||
circleIn->load("./circle-in.json", true);
|
||||
circleIn->as<uf::Object>().load("./circle-in.json", true);
|
||||
circleIn->initialize();
|
||||
}
|
||||
/* Command Circle */ {
|
||||
partyMemberCommandCircle = new ext::Gui;
|
||||
this->addChild(*partyMemberCommandCircle);
|
||||
partyMemberCommandCircle->load("./partyMemberCommandCircle.json", true);
|
||||
partyMemberCommandCircle->as<uf::Object>().load("./partyMemberCommandCircle.json", true);
|
||||
partyMemberCommandCircle->initialize();
|
||||
}
|
||||
/* Command Circle */ {
|
||||
optionsBackground = new ext::Gui;
|
||||
this->addChild(*optionsBackground);
|
||||
optionsBackground->load("./optionsBackground.json", true);
|
||||
optionsBackground->as<uf::Object>().load("./optionsBackground.json", true);
|
||||
optionsBackground->initialize();
|
||||
}
|
||||
/* Turn Counter Container */ {
|
||||
turnCounters = new ext::Gui;
|
||||
this->addChild(*turnCounters);
|
||||
turnCounters->load("./turnCounters.json", true);
|
||||
turnCounters->as<uf::Object>().load("./turnCounters.json", true);
|
||||
turnCounters->initialize();
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ void ext::GuiBattle::initialize() {
|
||||
ext::Gui* particle = new ext::Gui;
|
||||
this->addChild(*particle);
|
||||
uf::Serializer& pMetadata = particle->getComponent<uf::Serializer>();
|
||||
particle->load("./damageText.json", true);
|
||||
particle->as<uf::Object>().load("./damageText.json", true);
|
||||
std::string color = json["color"].isString() ? json["color"].asString() : "FF0000";
|
||||
pMetadata["text settings"]["string"] = "%#"+color+"%" + damage;
|
||||
pod::Transform<>& transform = particle->getComponent<pod::Transform<>>();
|
||||
@ -300,7 +300,7 @@ void ext::GuiBattle::initialize() {
|
||||
battleMessage = new ext::Gui;
|
||||
this->addChild(*battleMessage);
|
||||
uf::Serializer& pMetadata = battleMessage->getComponent<uf::Serializer>();
|
||||
battleMessage->load("./battle-text.json", true);
|
||||
battleMessage->as<uf::Object>().load("./battle-text.json", true);
|
||||
pMetadata["text settings"]["string"] = message;
|
||||
battleMessage->initialize();
|
||||
|
||||
@ -340,7 +340,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
critCutInBackground = new ext::Gui;
|
||||
this->addChild(*critCutInBackground);
|
||||
critCutInBackground->load("./critCutInBackground.json", true);
|
||||
critCutInBackground->as<uf::Object>().load("./critCutInBackground.json", true);
|
||||
critCutInBackground->initialize();
|
||||
}
|
||||
{
|
||||
@ -351,7 +351,7 @@ void ext::GuiBattle::initialize() {
|
||||
uf::Serializer cardData = masterDataGet("Card", json["id"].asString());
|
||||
pMetadata["system"]["assets"][0] = "/smtsamo/ci/ci_"+ cardData["filename"].asString() +".png";
|
||||
if ( !uf::io::exists( pMetadata["system"]["assets"][0].asString() ) ) pMetadata["system"]["assets"][0] = Json::nullValue;
|
||||
critCutIn->load("./critCutIn.json", true);
|
||||
critCutIn->as<uf::Object>().load("./critCutIn.json", true);
|
||||
critCutIn->initialize();
|
||||
}
|
||||
|
||||
@ -373,7 +373,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
turnCounters = new ext::Gui;
|
||||
this->addChild(*turnCounters);
|
||||
turnCounters->load("./turnCounters.json", true);
|
||||
turnCounters->as<uf::Object>().load("./turnCounters.json", true);
|
||||
turnCounters->initialize();
|
||||
}
|
||||
// show full counters
|
||||
@ -381,7 +381,7 @@ void ext::GuiBattle::initialize() {
|
||||
while ( turns > 0 ) {
|
||||
ext::Gui* counter = new ext::Gui;
|
||||
turnCounters->addChild(*counter);
|
||||
counter->load("./turnCounter.json", true);
|
||||
counter->as<uf::Object>().load("./turnCounter.json", true);
|
||||
counter->initialize();
|
||||
pod::Transform<>& pTransform = counter->getComponent<pod::Transform<>>();
|
||||
pTransform.position.x -= 0.142716f * (i++);
|
||||
@ -465,7 +465,7 @@ void ext::GuiBattle::initialize() {
|
||||
partyMemberText = new ext::Gui;
|
||||
partyMemberButton->addChild(*partyMemberText);
|
||||
uf::Serializer& pMetadata = partyMemberText->getComponent<uf::Serializer>();
|
||||
partyMemberText->load("./partyMemberText.json", true);
|
||||
partyMemberText->as<uf::Object>().load("./partyMemberText.json", true);
|
||||
pMetadata["text settings"]["string"] = "" + colorString("00FF00") + "" + member["hp"].asString() + "\n" + colorString("0000FF") + "" + member["mp"].asString();
|
||||
pMetadata[""] = member;
|
||||
pod::Transform<>& transform = partyMemberText->getComponent<pod::Transform<>>();
|
||||
@ -499,7 +499,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
partyMemberButton = new ext::Gui;
|
||||
this->addChild(*partyMemberButton);
|
||||
partyMemberButton->load("./partyMemberButton.json", true);
|
||||
partyMemberButton->as<uf::Object>().load("./partyMemberButton.json", true);
|
||||
|
||||
pod::Transform<>& transform = partyMemberButton->getComponent<pod::Transform<>>();
|
||||
transform.position.y += (i * 0.45);
|
||||
@ -518,7 +518,7 @@ void ext::GuiBattle::initialize() {
|
||||
partyMemberButton->addChild(*partyMemberIconShadow);
|
||||
uf::Serializer& pMetadata = partyMemberIconShadow->getComponent<uf::Serializer>();
|
||||
pMetadata["system"]["assets"][0] = filename;
|
||||
partyMemberIconShadow->load("./partyMemberIconShadow.json", true);
|
||||
partyMemberIconShadow->as<uf::Object>().load("./partyMemberIconShadow.json", true);
|
||||
pMetadata[""] = member;
|
||||
pod::Transform<>& transform = partyMemberIconShadow->getComponent<pod::Transform<>>();
|
||||
transform.position = bTransform.position;
|
||||
@ -532,7 +532,7 @@ void ext::GuiBattle::initialize() {
|
||||
partyMemberButton->addChild(*partyMemberIcon);
|
||||
uf::Serializer& pMetadata = partyMemberIcon->getComponent<uf::Serializer>();
|
||||
pMetadata["system"]["assets"][0] = filename;
|
||||
partyMemberIcon->load("./partyMemberIcon.json", true);
|
||||
partyMemberIcon->as<uf::Object>().load("./partyMemberIcon.json", true);
|
||||
pMetadata[""] = member;
|
||||
pod::Transform<>& transform = partyMemberIcon->getComponent<pod::Transform<>>();
|
||||
transform.position = bTransform.position;
|
||||
@ -544,7 +544,7 @@ void ext::GuiBattle::initialize() {
|
||||
partyMemberText = new ext::Gui;
|
||||
partyMemberButton->addChild(*partyMemberText);
|
||||
uf::Serializer& pMetadata = partyMemberText->getComponent<uf::Serializer>();
|
||||
partyMemberText->load("./partyMemberText.json", true);
|
||||
partyMemberText->as<uf::Object>().load("./partyMemberText.json", true);
|
||||
pMetadata["text settings"]["string"] = "" + colorString("FF0000") + "" + member["hp"].asString() + "\n" + colorString("0000FF") + "" + member["mp"].asString();
|
||||
pMetadata[""] = member;
|
||||
pod::Transform<>& transform = partyMemberText->getComponent<pod::Transform<>>();
|
||||
@ -555,7 +555,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
ext::Gui* partyMemberBar = new ext::Gui;
|
||||
partyMemberButton->addChild(*partyMemberBar);
|
||||
partyMemberBar->load("./partyMemberBars.json", true);
|
||||
partyMemberBar->as<uf::Object>().load("./partyMemberBars.json", true);
|
||||
pod::Transform<>& transform = partyMemberBar->getComponent<pod::Transform<>>();
|
||||
transform.position = bTransform.position;
|
||||
transform.position.x = 0.742573;
|
||||
@ -565,7 +565,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
ext::Gui* partyMemberHP = new ext::Gui;
|
||||
partyMemberButton->addChild(*partyMemberHP);
|
||||
partyMemberHP->load("./partyMemberHP.json", true);
|
||||
partyMemberHP->as<uf::Object>().load("./partyMemberHP.json", true);
|
||||
pod::Transform<>& transform = partyMemberHP->getComponent<pod::Transform<>>();
|
||||
transform.position = bTransform.position;
|
||||
transform.position.x = 0.742573;
|
||||
@ -583,7 +583,7 @@ void ext::GuiBattle::initialize() {
|
||||
{
|
||||
ext::Gui* partyMemberMP = new ext::Gui;
|
||||
partyMemberButton->addChild(*partyMemberMP);
|
||||
partyMemberMP->load("./partyMemberMP.json", true);
|
||||
partyMemberMP->as<uf::Object>().load("./partyMemberMP.json", true);
|
||||
pod::Transform<>& transform = partyMemberMP->getComponent<pod::Transform<>>();
|
||||
transform.position = bTransform.position;
|
||||
transform.position.x = 0.742573;
|
||||
@ -740,7 +740,7 @@ void ext::GuiBattle::tick() {
|
||||
battleOptions = new ext::Gui;
|
||||
this->addChild(*battleOptions);
|
||||
uf::Serializer& pMetadata = battleOptions->getComponent<uf::Serializer>();
|
||||
battleOptions->load("./battle-option.json", true);
|
||||
battleOptions->as<uf::Object>().load("./battle-option.json", true);
|
||||
pMetadata["text settings"]["string"] = string;
|
||||
pod::Transform<>& pTransform = battleOptions->getComponent<pod::Transform<>>();
|
||||
battleOptions->initialize();
|
||||
@ -793,7 +793,7 @@ void ext::GuiBattle::tick() {
|
||||
commandOptions = new ext::Gui;
|
||||
this->addChild(*commandOptions);
|
||||
uf::Serializer& pMetadata = commandOptions->getComponent<uf::Serializer>();
|
||||
commandOptions->load("./battle-option.json", true);
|
||||
commandOptions->as<uf::Object>().load("./battle-option.json", true);
|
||||
pMetadata["text settings"]["string"] = string;
|
||||
pod::Transform<>& pTransform = commandOptions->getComponent<pod::Transform<>>();
|
||||
commandOptions->initialize();
|
||||
@ -845,7 +845,7 @@ void ext::GuiBattle::tick() {
|
||||
targetOptions = new ext::Gui;
|
||||
this->addChild(*targetOptions);
|
||||
uf::Serializer& pMetadata = targetOptions->getComponent<uf::Serializer>();
|
||||
targetOptions->load("./battle-option.json", true);
|
||||
targetOptions->as<uf::Object>().load("./battle-option.json", true);
|
||||
pMetadata["text settings"]["string"] = string;
|
||||
pod::Transform<>& pTransform = targetOptions->getComponent<pod::Transform<>>();
|
||||
targetOptions->initialize();
|
||||
|
||||
@ -203,7 +203,7 @@ void ext::GuiDialogue::tick() {
|
||||
dialogueMessage = new ext::Gui;
|
||||
this->addChild(*dialogueMessage);
|
||||
uf::Serializer& pMetadata = dialogueMessage->getComponent<uf::Serializer>();
|
||||
dialogueMessage->load("./dialogue-text.json", true);
|
||||
dialogueMessage->as<uf::Object>().load("./dialogue-text.json", true);
|
||||
pMetadata["text settings"]["string"] = result["message"].asString();
|
||||
dialogueMessage->initialize();
|
||||
}
|
||||
@ -251,7 +251,7 @@ void ext::GuiDialogue::tick() {
|
||||
dialogueOptions = new ext::Gui;
|
||||
this->addChild(*dialogueOptions);
|
||||
uf::Serializer& pMetadata = dialogueOptions->getComponent<uf::Serializer>();
|
||||
dialogueOptions->load("./dialogue-option.json", true);
|
||||
dialogueOptions->as<uf::Object>().load("./dialogue-option.json", true);
|
||||
pMetadata["text settings"]["string"] = string;
|
||||
pod::Transform<>& pTransform = dialogueOptions->getComponent<pod::Transform<>>();
|
||||
dialogueOptions->initialize();
|
||||
|
||||
@ -127,6 +127,7 @@ void ext::GuiWorldPauseMenuBehavior::initialize( uf::Object& self ) {
|
||||
uf::Serializer member = pMetadata[""]["transients"][id];
|
||||
uf::Serializer cardData = masterDataGet("Card", id);
|
||||
std::string name = cardData["filename"].asString();
|
||||
if ( name == "" ) continue;
|
||||
if ( member["skin"].isString() ) name += "_" + member["skin"].asString();
|
||||
std::string filename = "https://cdn..xyz//unity/Android/fg/fg_" + name + ".png";
|
||||
if ( cardData["internal"].asBool() ) {
|
||||
@ -137,7 +138,7 @@ void ext::GuiWorldPauseMenuBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
{
|
||||
std::string portrait = metadata["portraits"]["list"][0].asString();
|
||||
/* Transient shadow background */ {
|
||||
/* Transient shadow background */ if ( portrait != "" ) {
|
||||
transientSpriteShadow = new uf::Object;
|
||||
uf::Asset& assetLoader = transientSpriteShadow->getComponent<uf::Asset>();
|
||||
this->addChild(*transientSpriteShadow);
|
||||
@ -148,7 +149,7 @@ void ext::GuiWorldPauseMenuBehavior::initialize( uf::Object& self ) {
|
||||
transientSpriteShadow->initialize();
|
||||
|
||||
}
|
||||
/* Transient transientSprite */ {
|
||||
/* Transient transientSprite */ if ( portrait != "" ) {
|
||||
transientSprite = new uf::Object;
|
||||
uf::Asset& assetLoader = transientSprite->getComponent<uf::Asset>();
|
||||
this->addChild(*transientSprite);
|
||||
@ -229,7 +230,13 @@ void ext::GuiWorldPauseMenuBehavior::initialize( uf::Object& self ) {
|
||||
delete this;
|
||||
return "true";
|
||||
*/
|
||||
uf::Serializer json = event;
|
||||
|
||||
metadata["system"]["hooks"]["onClose"] = json["callback"];
|
||||
|
||||
metadata["system"]["closing"] = true;
|
||||
playSound(*this, "menu close");
|
||||
|
||||
return "true";
|
||||
});
|
||||
}
|
||||
@ -238,6 +245,7 @@ void ext::GuiWorldPauseMenuBehavior::tick( uf::Object& self ) {
|
||||
uf::Serializer& masterdata = scene.getComponent<uf::Serializer>();
|
||||
static uf::Timer<long long> timer(false);
|
||||
static uf::Audio sfx;
|
||||
// if ( !timer.running() ) timer.start( uf::Time<>(-1000000) );
|
||||
if ( !timer.running() ) timer.start();
|
||||
|
||||
static float alpha = 0.0f;
|
||||
@ -259,6 +267,21 @@ void ext::GuiWorldPauseMenuBehavior::tick( uf::Object& self ) {
|
||||
} else if ( metadata["system"]["closed"].asBool() ) {
|
||||
// kill
|
||||
timer.stop();
|
||||
|
||||
uf::Serializer callback = metadata["system"]["hooks"]["onClose"];
|
||||
uf::Serializer payload = callback["payload"];
|
||||
uf::Object* target = this;
|
||||
if ( callback["scope"].asString() == "parent" ) {
|
||||
target = &this->getParent().as<uf::Object>();
|
||||
} else if ( callback["scope"].asString() == "scene" ) {
|
||||
target = &uf::scene::getCurrentScene();
|
||||
}
|
||||
if ( callback["delay"].isNumeric() ) {
|
||||
target->queueHook( callback["name"].asString(), payload, callback["delay"].asFloat() );
|
||||
} else {
|
||||
target->callHook( callback["name"].asString(), payload );
|
||||
}
|
||||
|
||||
this->destroy();
|
||||
this->getParent().removeChild(*this);
|
||||
delete this;
|
||||
@ -495,13 +518,13 @@ void ext::GuiWorldPauseMenuBehavior::tick( uf::Object& self ) {
|
||||
delta += uf::physics::time::delta * 1.5f;
|
||||
transform.position = uf::vector::lerp( start, end, delta );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if ( metadata["clicked"].asBool() && timer.elapsed().asDouble() >= 1 ) {
|
||||
timer.reset();
|
||||
this->callHook("menu:Close.%UID%");
|
||||
playSound(*this, "menu close");
|
||||
}
|
||||
*/
|
||||
metadata["color"][3] = alpha;
|
||||
|
||||
for ( uf::Entity* pointer : closeOption->getChildren() ) {
|
||||
@ -531,17 +554,13 @@ void ext::GuiWorldPauseMenuBehavior::tick( uf::Object& self ) {
|
||||
delta += uf::physics::time::delta * 1.5f;
|
||||
transform.position = uf::vector::lerp( start, end, delta );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if ( metadata["clicked"].asBool() && timer.elapsed().asDouble() >= 1 ) {
|
||||
timer.reset();
|
||||
this->callHook("menu:Close.%UID%");
|
||||
playSound(*this, "menu close");
|
||||
/*
|
||||
uf::Scene& scene = this->getRootParent<uf::Scene>();
|
||||
scene.queueHook("system:Quit.%UID%", "", 1.0f);
|
||||
*/
|
||||
}
|
||||
*/
|
||||
metadata["color"][3] = alpha;
|
||||
|
||||
for ( uf::Entity* pointer : quitOption->getChildren() ) {
|
||||
|
||||
@ -105,7 +105,7 @@ namespace {
|
||||
void ext::HousamoBattle::initialize() {
|
||||
uf::Object::initialize();
|
||||
|
||||
gui = NULL;
|
||||
::gui = NULL;
|
||||
transients.clear();
|
||||
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
@ -283,17 +283,17 @@ void ext::HousamoBattle::initialize() {
|
||||
return payload;
|
||||
});
|
||||
this->addHook( "world:Battle.Gui.%UID%", [&](const std::string& event)->std::string{
|
||||
ext::Gui* guiManager = (ext::Gui*) this->getRootParent().findByName("Gui Manager");
|
||||
ext::Gui* guiManager = (ext::Gui*) this->globalFindByName("Gui Manager");
|
||||
ext::Gui* guiMenu = new ext::GuiBattle;
|
||||
guiManager->addChild(*guiMenu);
|
||||
guiMenu->load("./scenes/world/gui/battle/menu.json");
|
||||
guiMenu->as<uf::Object>().load("./scenes/world/gui/battle/menu.json");
|
||||
guiMenu->initialize();
|
||||
|
||||
uf::Serializer payload;
|
||||
payload["battle"] = metadata["battle"];
|
||||
guiMenu->queueHook("world:Battle.Start.%UID%", payload);
|
||||
|
||||
gui = guiMenu;
|
||||
::gui = guiMenu;
|
||||
|
||||
return "true";
|
||||
});
|
||||
@ -403,10 +403,10 @@ void ext::HousamoBattle::initialize() {
|
||||
// std::cout << metadata["battle"]["transients"] << std::endl;
|
||||
}
|
||||
|
||||
if ( gui ) {
|
||||
if ( ::gui ) {
|
||||
uf::Serializer payload;
|
||||
payload["battle"] = metadata["battle"];
|
||||
gui->queueHook("world:Battle.Update.%UID%", payload);
|
||||
::gui->queueHook("world:Battle.Update.%UID%", payload);
|
||||
}
|
||||
|
||||
if ( hookName == "" ) return payload;
|
||||
@ -657,10 +657,10 @@ void ext::HousamoBattle::initialize() {
|
||||
turnState["counter"] = counter;
|
||||
turnState["start of turn"] = true;
|
||||
|
||||
if ( gui ) {
|
||||
if ( ::gui ) {
|
||||
uf::Serializer payload;
|
||||
payload["battle"] = metadata["battle"];
|
||||
gui->queueHook("world:Battle.TurnStart.%UID%", payload);
|
||||
::gui->queueHook("world:Battle.TurnStart.%UID%", payload);
|
||||
}
|
||||
} else {
|
||||
turnState["start of turn"] = false;
|
||||
@ -791,10 +791,10 @@ void ext::HousamoBattle::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
if ( gui ) {
|
||||
if ( ::gui ) {
|
||||
uf::Serializer payload;
|
||||
payload["battle"] = metadata["battle"];
|
||||
gui->queueHook("world:Battle.Update.%UID%", payload);
|
||||
::gui->queueHook("world:Battle.Update.%UID%", payload);
|
||||
}
|
||||
|
||||
if ( skipped ) payload["skipped"] = true;
|
||||
@ -906,7 +906,7 @@ void ext::HousamoBattle::initialize() {
|
||||
payload["color"] = json["color"];
|
||||
payload["target"]["uid"] = json["uid"];
|
||||
payload["target"]["damage"] = json["message"];
|
||||
gui->queueHook("world:Battle.Damage.%UID%", payload, delays.damage);
|
||||
::gui->queueHook("world:Battle.Damage.%UID%", payload, delays.damage);
|
||||
delays.damage += 0.25f;
|
||||
};
|
||||
|
||||
@ -1062,7 +1062,7 @@ void ext::HousamoBattle::initialize() {
|
||||
uf::Serializer payload;
|
||||
payload["target"]["uid"] = target["uid"];
|
||||
payload["target"]["damage"] = "Miss";
|
||||
gui->queueHook("world:Battle.Damage.%UID%", payload);
|
||||
::gui->queueHook("world:Battle.Damage.%UID%", payload);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1337,7 +1337,7 @@ void ext::HousamoBattle::initialize() {
|
||||
uf::Serializer payload;
|
||||
payload["uid"] = json["uid"];
|
||||
payload["id"] = member["id"];
|
||||
gui->queueHook("world:Battle.OnCrit.%UID%", payload, 0.1f);
|
||||
::gui->queueHook("world:Battle.OnCrit.%UID%", payload, 0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1435,7 +1435,7 @@ void ext::HousamoBattle::initialize() {
|
||||
*/
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
scene.callHook("world:Music.LoadPrevious.%UID%");
|
||||
gui->callHook("menu:Close.%UID%");
|
||||
::gui->callHook("menu:Close.%UID%");
|
||||
|
||||
// cleanup
|
||||
for ( ext::Housamo* pointer : transients ) {
|
||||
|
||||
@ -92,7 +92,7 @@ namespace {
|
||||
void ext::DialogueManager::initialize() {
|
||||
uf::Object::initialize();
|
||||
|
||||
gui = NULL;
|
||||
::gui = NULL;
|
||||
transients.clear();
|
||||
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
@ -175,17 +175,17 @@ void ext::DialogueManager::initialize() {
|
||||
return payload;
|
||||
});
|
||||
this->addHook( "menu:Dialogue.Gui.%UID%", [&](const std::string& event)->std::string{
|
||||
ext::Gui* guiManager = (ext::Gui*) this->getRootParent().findByName("Gui Manager");
|
||||
ext::Gui* guiManager = (ext::Gui*) this->globalFindByName("Gui Manager");
|
||||
ext::Gui* guiMenu = new ext::GuiDialogue;
|
||||
guiManager->addChild(*guiMenu);
|
||||
guiMenu->load("./entities/gui/dialogue/menu.json");
|
||||
guiMenu->as<uf::Object>().load("./entities/gui/dialogue/menu.json");
|
||||
guiMenu->initialize();
|
||||
|
||||
uf::Serializer payload;
|
||||
payload["dialogue"] = metadata["dialogue"];
|
||||
guiMenu->queueHook("menu:Dialogue.Start.%UID%", payload);
|
||||
|
||||
gui = guiMenu;
|
||||
::gui = guiMenu;
|
||||
|
||||
return "true";
|
||||
});
|
||||
@ -251,7 +251,7 @@ void ext::DialogueManager::initialize() {
|
||||
// play music
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
scene.callHook("world:Music.LoadPrevious.%UID%");
|
||||
gui->callHook("menu:Close.%UID%");
|
||||
::gui->callHook("menu:Close.%UID%");
|
||||
|
||||
this->callHook("menu:Dialogue.End");
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <uf/utils/math/physics.h>
|
||||
|
||||
#include <uf/engine/object/object.h>
|
||||
#include <uf/engine/asset/asset.h>
|
||||
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/graphic/mesh.h>
|
||||
@ -77,7 +78,51 @@ void ext::TerrainBehavior::initialize( uf::Object& self ) {
|
||||
uf::thread::limiter = metadata["system"]["limiter"].asFloat();
|
||||
return "true";
|
||||
});
|
||||
this->addHook( "terrain:GenerateMesh.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
|
||||
|
||||
graphic.initializeGeometry( mesh );
|
||||
graphic.getPipeline().update( graphic );
|
||||
graphic.process = true;
|
||||
uf::renderer::rebuild = true;
|
||||
|
||||
return "true";
|
||||
});
|
||||
this->addHook( "terrain:Post-Initialize.%UID%", [&](const std::string& event)->std::string{
|
||||
if ( metadata["terrain"]["unified"].asBool() ) {
|
||||
std::string textureFilename = ""; {
|
||||
uf::Asset assetLoader;
|
||||
for ( uint i = 0; i < metadata["system"]["assets"].size(); ++i ) {
|
||||
if ( textureFilename != "" ) break;
|
||||
std::string filename = this->grabURI( metadata["system"]["assets"][i].asString(), metadata["system"]["root"].asString() );
|
||||
textureFilename = assetLoader.cache( filename );
|
||||
}
|
||||
}
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
|
||||
graphic.initialize();
|
||||
graphic.process = false;
|
||||
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.sampler.descriptor.filter.min = VK_FILTER_NEAREST;
|
||||
texture.sampler.descriptor.filter.mag = VK_FILTER_NEAREST;
|
||||
texture.loadFromFile( textureFilename );
|
||||
|
||||
std::string suffix = ""; {
|
||||
std::string _ = this->getRootParent<uf::Scene>().getComponent<uf::Serializer>()["shaders"]["region"]["suffix"].asString();
|
||||
if ( _ != "" ) suffix = _ + ".";
|
||||
}
|
||||
graphic.material.initializeShaders({
|
||||
{"./data/shaders/terrain.stereo.vert.spv", VK_SHADER_STAGE_VERTEX_BIT},
|
||||
{"./data/shaders/terrain."+suffix+"frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT}
|
||||
});
|
||||
|
||||
uf::renderer::rebuildOnTickStart = false;
|
||||
}
|
||||
|
||||
this->generate();
|
||||
/*
|
||||
auto& parent = this->getParent().as<uf::Object>();
|
||||
@ -185,15 +230,34 @@ void ext::TerrainBehavior::tick( uf::Object& self ) {
|
||||
}
|
||||
// sort by closest to farthest
|
||||
sortRegions(controller, regions);
|
||||
if ( metadata["terrain"]["unified"].asBool() ) {
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
|
||||
mesh.destroy();
|
||||
for ( uf::Object* region : regions ) {
|
||||
uf::Serializer& metadata = region->getComponent<uf::Serializer>();
|
||||
if ( !metadata["region"]["initialized"].asBool() ) region->initialize();
|
||||
if ( !metadata["region"]["generated"].asBool() ) region->callHook("region:Generate.%UID%", "");
|
||||
if ( !metadata["region"]["rasterized"].asBool() ) {
|
||||
region->queueHook("region:Finalize.%UID%", "");
|
||||
region->queueHook("region:Populate.%UID%", "");
|
||||
}
|
||||
auto& generator = region->getComponent<ext::TerrainGenerator>();
|
||||
generator.rasterize(mesh.vertices, *region, false);
|
||||
}
|
||||
this->queueHook("terrain:GenerateMesh.%UID%");
|
||||
} else {
|
||||
// initialize uninitialized regions
|
||||
for ( uf::Object* region : regions ) {
|
||||
// uf::thread::add( uf::thread::fetchWorker(), [&]() -> int {
|
||||
uf::Serializer& metadata = region->getComponent<uf::Serializer>();
|
||||
if ( !metadata["region"]["initialized"].asBool() ) region->initialize();
|
||||
if ( !metadata["region"]["generated"].asBool() ) region->callHook("region:Generate.%UID%", "");
|
||||
if ( !metadata["region"]["rasterized"].asBool() ) region->callHook("region:Rasterize.%UID%", "");
|
||||
// return 0;}, true );
|
||||
for ( uf::Object* region : regions ) {
|
||||
// uf::thread::add( uf::thread::fetchWorker(), [&]() -> int {
|
||||
uf::Serializer& metadata = region->getComponent<uf::Serializer>();
|
||||
if ( !metadata["region"]["initialized"].asBool() ) region->initialize();
|
||||
if ( !metadata["region"]["generated"].asBool() ) region->callHook("region:Generate.%UID%", "");
|
||||
if ( !metadata["region"]["rasterized"].asBool() ) region->callHook("region:Rasterize.%UID%", "");
|
||||
// return 0;}, true );
|
||||
}
|
||||
}
|
||||
|
||||
// move to next state:
|
||||
transitionState(*this, "open", !regions.empty());
|
||||
return 0;}, true );
|
||||
@ -201,7 +265,25 @@ void ext::TerrainBehavior::tick( uf::Object& self ) {
|
||||
// check if we need to relocate entities
|
||||
this->relocateChildren();
|
||||
}
|
||||
void ext::TerrainBehavior::render( uf::Object& self ){}
|
||||
void ext::TerrainBehavior::render( uf::Object& self ){
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
|
||||
if ( !metadata["terrain"]["unified"].asBool() ) return;
|
||||
/* Update uniforms */ if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
auto& camera = scene.getController().getComponent<uf::Camera>();
|
||||
if ( !graphic.initialized ) return;
|
||||
auto& uniforms = graphic.material.shaders.front().uniforms.front().get<uf::StereoMeshDescriptor>();
|
||||
uniforms.matrices.model = uf::matrix::identity();
|
||||
for ( std::size_t i = 0; i < 2; ++i ) {
|
||||
uniforms.matrices.view[i] = camera.getView( i );
|
||||
uniforms.matrices.projection[i] = camera.getProjection( i );
|
||||
}
|
||||
graphic.material.shaders.front().updateBuffer( uniforms, 0, true );
|
||||
}
|
||||
}
|
||||
void ext::TerrainBehavior::destroy( uf::Object& self ){}
|
||||
#undef this
|
||||
EXT_BEHAVIOR_ENTITY_CPP_END(Terrain)
|
||||
@ -1287,7 +1287,7 @@ void ext::TerrainGenerator::updateLight(){
|
||||
// this->wrapLight();
|
||||
// this->writeToFile();
|
||||
}
|
||||
void ext::TerrainGenerator::rasterize( std::vector<ext::TerrainGenerator::mesh_t::vertex_t>& vertices, const uf::Object& region ){
|
||||
void ext::TerrainGenerator::rasterize( std::vector<ext::TerrainGenerator::mesh_t::vertex_t>& vertices, const uf::Object& region, bool applyTransform ){
|
||||
if ( this->m_voxels.id.rle.empty() ) return;
|
||||
|
||||
this->writeToFile();
|
||||
@ -1326,6 +1326,7 @@ void ext::TerrainGenerator::rasterize( std::vector<ext::TerrainGenerator::mesh_t
|
||||
color.b *= tMetadata["region"]["light"]["ambient"][2].asFloat();
|
||||
ambientLight = colorToUint16( color );
|
||||
}
|
||||
pod::Matrix4f modelMatrix = uf::transform::model( transform );
|
||||
#define TERRAIN_SHOULD_RENDER_FACE(SIDE)\
|
||||
should.SIDE = !neighbor.SIDE.opaque();\
|
||||
if ( should.SIDE ) {\
|
||||
@ -1359,6 +1360,10 @@ void ext::TerrainGenerator::rasterize( std::vector<ext::TerrainGenerator::mesh_t
|
||||
p[2] = (p[2] << 4) | p[2];\
|
||||
p[3] = (p[3] << 4) | p[3];\
|
||||
}\
|
||||
if ( applyTransform ) {\
|
||||
pod::Vector3f& p = vertex.position;\
|
||||
p += transform.position; /*p = uf::matrix::multiply<float>( modelMatrix, p );*/\
|
||||
}\
|
||||
vertices.push_back(vertex);\
|
||||
}\
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ namespace ext {
|
||||
void updateLight();
|
||||
|
||||
void generate( uf::Object& );
|
||||
void rasterize( std::vector<TerrainGenerator::mesh_t::vertex_t>& vertices, const uf::Object& );
|
||||
void rasterize( std::vector<TerrainGenerator::mesh_t::vertex_t>& vertices, const uf::Object&, bool = false );
|
||||
// void vectorize( std::vector<uf::renderer::ComputeGraphic::Cube>&, const uf::Object& );
|
||||
|
||||
std::vector<ext::TerrainVoxel::uid_t> getRawVoxels();
|
||||
|
||||
@ -12,22 +12,9 @@
|
||||
#include <uf/utils/string/ext.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace {
|
||||
std::string grabURI( std::string filename, std::string root = "" ) {
|
||||
if ( filename.substr(0,8) == "https://" ) return filename;
|
||||
std::string extension = uf::io::extension(filename);
|
||||
if ( filename[0] == '/' || root == "" ) {
|
||||
if ( extension == "json" ) root = "./data/entities/";
|
||||
if ( extension == "png" ) root = "./data/textures/";
|
||||
if ( extension == "ogg" ) root = "./data/audio/";
|
||||
}
|
||||
return uf::io::sanitize(filename, root);
|
||||
}
|
||||
}
|
||||
|
||||
EXT_BEHAVIOR_REGISTER_CPP(RegionBehavior)
|
||||
EXT_BEHAVIOR_REGISTER_AS_OBJECT(RegionBehavior, Region)
|
||||
#define this (&self)
|
||||
#define this ((uf::Object*) &self)
|
||||
void ext::RegionBehavior::initialize( uf::Object& self ) {
|
||||
// alias Mesh types
|
||||
{
|
||||
@ -38,13 +25,13 @@ void ext::RegionBehavior::initialize( uf::Object& self ) {
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
metadata["region"]["initialized"] = true;
|
||||
|
||||
{
|
||||
if ( !metadata["terrain"]["unified"].asBool() ) {
|
||||
std::string textureFilename = ""; {
|
||||
uf::Serializer& metadata = this->getParent().getComponent<uf::Serializer>();
|
||||
uf::Asset assetLoader;
|
||||
for ( uint i = 0; i < metadata["system"]["assets"].size(); ++i ) {
|
||||
if ( textureFilename != "" ) break;
|
||||
std::string filename = grabURI( metadata["system"]["assets"][i].asString(), metadata["system"]["root"].asString() );
|
||||
std::string filename = this->grabURI( metadata["system"]["assets"][i].asString(), metadata["system"]["root"].asString() );
|
||||
textureFilename = assetLoader.cache( filename );
|
||||
}
|
||||
}
|
||||
@ -141,10 +128,10 @@ void ext::RegionBehavior::initialize( uf::Object& self ) {
|
||||
this->addHook( "region:Finalize.%UID%", [&](const std::string& event)->std::string{
|
||||
uf::Serializer json = event;
|
||||
|
||||
ext::TerrainGenerator::mesh_t& mesh = this->getComponent<ext::TerrainGenerator::mesh_t>();
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
|
||||
graphic.process = true;
|
||||
if ( this->hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = this->getComponent<uf::Graphic>();
|
||||
graphic.process = true;
|
||||
}
|
||||
metadata["region"]["rasterized"] = true;
|
||||
|
||||
return "true";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
tskill program
|
||||
cd bin
|
||||
./program.bat
|
||||
|
||||
./program.bat $@
|
||||
tskill program
|
||||
|
||||
Loading…
Reference in New Issue
Block a user