Переглянути джерело

misc: move more shaders to .lolfx files.

legacy
Sam Hocevar sam 12 роки тому
джерело
коміт
ee7dd6a699
8 змінених файлів з 258 додано та 222 видалено
  1. +1
    -0
      .gitignore
  2. +4
    -35
      test/tutorial/02_cube.cpp
  3. +46
    -0
      test/tutorial/02_cube.lolfx
  4. +3
    -187
      test/tutorial/03_fractal.cpp
  5. +196
    -0
      test/tutorial/03_fractal.lolfx
  6. +2
    -0
      test/tutorial/Makefile.am
  7. +3
    -0
      win32/02_cube.vcxproj
  8. +3
    -0
      win32/03_fractal.vcxproj

+ 1
- 0
.gitignore Переглянути файл

@@ -13,6 +13,7 @@
.auto
.libs
.deps
.dirstamp
Makefile
Makefile.in
aclocal.m4


+ 4
- 35
test/tutorial/02_cube.cpp Переглянути файл

@@ -27,6 +27,8 @@ using namespace lol;
# include <direct.h>
#endif

extern char const *lolfx_02_cube;

class Cube : public WorldEntity
{
public:
@@ -81,41 +83,8 @@ public:

if (!m_ready)
{
m_shader = Shader::Create(
#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
"#version 120\n"
"attribute vec3 in_Vertex;"
"attribute vec3 in_Color;"
"uniform mat4 in_Matrix;"
"varying vec3 pass_Color;"
""
"void main(void) {"
" gl_Position = in_Matrix * vec4(in_Vertex, 1.0);"
" pass_Color = in_Color;"
"}",

"#version 120\n"
"varying vec3 pass_Color;"
""
"void main(void) {"
" gl_FragColor = vec4(pass_Color, 1.0);"
"}"
#else
"void main(float3 in_Vertex : POSITION,"
" float3 in_Color : COLOR,"
" uniform float4x4 in_Matrix,"
" out float4 out_Position : POSITION,"
" out float3 pass_Color : COLOR) {"
" pass_Color = in_Color;"
" out_Position = mul(in_Matrix, float4(in_Vertex, 1.0));"
"}",

"void main(float3 pass_Color : COLOR,"
" out float4 out_FragColor : COLOR) {"
" out_FragColor = float4(pass_Color, 1.0);"
"}"
#endif
);
m_shader = Shader::Create(lolfx_02_cube);

m_mvp = m_shader->GetUniformLocation("in_Matrix");
m_coord = m_shader->GetAttribLocation("in_Vertex",
VertexUsage::Position, 0);


+ 46
- 0
test/tutorial/02_cube.lolfx Переглянути файл

@@ -0,0 +1,46 @@
-- GLSL.Vert --

#version 120\n

attribute vec3 in_Vertex;
attribute vec3 in_Color;
uniform mat4 in_Matrix;
varying vec3 pass_Color;

void main(void)
{
gl_Position = in_Matrix * vec4(in_Vertex, 1.0);
pass_Color = in_Color;
}

-- GLSL.Frag --

#version 120

varying vec3 pass_Color;

void main(void)
{
gl_FragColor = vec4(pass_Color, 1.0);
}

-- HLSL.Vert --

void main(float3 in_Vertex : POSITION,
float3 in_Color : COLOR,
uniform float4x4 in_Matrix,
out float4 out_Position : POSITION,
out float3 pass_Color : COLOR)
{
pass_Color = in_Color;
out_Position = mul(in_Matrix, float4(in_Vertex, 1.0));
}

-- HLSL.Frag --

void main(float3 pass_Color : COLOR,
out float4 out_FragColor : COLOR)
{
out_FragColor = float4(pass_Color, 1.0);
}


+ 3
- 187
test/tutorial/03_fractal.cpp Переглянути файл

@@ -37,6 +37,8 @@ using namespace lol;
# include <direct.h>
#endif

extern char const *lolfx_03_fractal;

#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
@@ -478,194 +480,8 @@ public:
D3DPOOL_SYSTEMMEM, &m_tex, NULL);
#endif

m_shader = Shader::Create(
#if !defined __CELLOS_LV2__ && !defined _XBOX && !defined USE_D3D9
# if !defined HAVE_GLES_2X
"#version 120\n"
# else
"precision highp float;"
# endif
""
"uniform mat4 u_ZoomSettings;"
"uniform vec4 u_TexelSize;"
"uniform vec4 u_ScreenSize;"
""
"attribute vec2 a_TexCoord;"
"attribute vec2 a_Vertex;"
""
"varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY;"
""
"void main(void)"
"{"
" gl_Position = vec4(a_Vertex, 0.0, 1.0);"
/* Center point in [-.5,.5], apply zoom and translation
* transformation, and go back to texture coordinates
* in [0,1]. That's the ideal point we would like to
* compute the value for. Then add or remove half the
* size of a texel: the distance from this new point to
* the final point will be our error. */
" vec4 offsets = vec4(0.5, -0.5, 0.015625, -0.015625);"
" vec4 zoomscale = vec4(u_ZoomSettings[0][2],"
" u_ZoomSettings[1][2],"
" u_ZoomSettings[2][2],"
" u_ZoomSettings[3][2]);"
" vec4 zoomtx = vec4(u_ZoomSettings[0][0],"
" u_ZoomSettings[1][0],"
" u_ZoomSettings[2][0],"
" u_ZoomSettings[3][0]);"
" vec4 zoomty = vec4(u_ZoomSettings[0][1],"
" u_ZoomSettings[1][1],"
" u_ZoomSettings[2][1],"
" u_ZoomSettings[3][1]);"
" v_CenterX = zoomscale * a_TexCoord.x + zoomtx"
" + offsets.xyxy * u_TexelSize.x;"
" v_CenterY = zoomscale * a_TexCoord.y - zoomty"
" + offsets.xyyx * u_TexelSize.y;"
/* Precompute the multiple of one texel where our ideal
* point lies. The fragment shader will call floor() on
* this value. We add or remove a slight offset to avoid
* rounding issues at the image's edges. */
" v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw;"
" v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz;"
"}",
m_shader = Shader::Create(lolfx_03_fractal);

# if !defined HAVE_GLES_2X
"#version 120\n"
# else
"precision highp float;"
# endif
""
"uniform vec4 u_TexelSize;"
"uniform sampler2D u_Texture;"
""
"varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY;"
""
"void main(void)"
"{"
" vec4 v05 = vec4(0.5, 0.5, 0.5, 0.5);"
" vec4 rx, ry, t0, dx, dy, dd;"
/* Get a pixel coordinate from each slice into rx & ry */
" rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX);"
" ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY);"
/* Compute inverse distance to expected pixel in dd,
* and put zero if we fall outside the texture. */
" t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05);"
" dx = rx - v_CenterX;"
" dy = ry - v_CenterY;"
//" vec4 dd = t0 * (abs(dx) + abs(dy));"
//" vec4 dd = t0 / (0.001 + sqrt((dx * dx) + (dy * dy)));"
" dd = t0 / (0.000001 + (dx * dx) + (dy * dy));"
/* Modify Y coordinate to select proper quarter. */
" ry = ry * 0.25 + vec4(0.0, 0.25, 0.5, 0.75);"
""
# if 1
"\n#if 0\n" /* XXX: disabled until we can autodetect i915 */
/* t1.x <-- dd.x > dd.y */
/* t1.y <-- dd.z > dd.w */
" vec2 t1 = step(dd.xz, dd.yw);"
/* ret.x <-- max(rx.x, rx.y) wrt. t1.x */
/* ret.y <-- max(rx.z, rx.w) wrt. t1.y */
/* ret.z <-- max(ry.x, ry.y) wrt. t1.x */
/* ret.w <-- max(ry.z, ry.w) wrt. t1.y */
" vec4 ret = mix(vec4(rx.xz, ry.xz),"
" vec4(rx.yw, ry.yw), t1.xyxy);"
/* dd.x <-- max(dd.x, dd.y) */
/* dd.z <-- max(dd.z, dd.w) */
" dd.xy = mix(dd.xz, dd.yw, t1);"
/* t2 <-- dd.x > dd.z */
" float t2 = step(dd.x, dd.y);"
/* ret.x <-- max(ret.x, ret.y); */
/* ret.y <-- max(ret.z, ret.w); */
" ret.xy = mix(ret.xz, ret.yw, t2);"
"\n#else\n"
/* Fallback for i915 cards -- the trick to reduce the
* number of operations is to compute both step(a,b)
* and step(b,a) and hope that their sum is 1. This is
* almost always the case, and when it isn't we can
* afford to have a few wrong pixels. However, a real
* problem is when panning the image, because half the
* screen is likely to flicker. To avoid this problem,
* we cheat a little (see m_translate comment above). */
" vec4 t1 = step(dd.xzyw, dd.ywxz);"
" vec4 ret = vec4(rx.xz, ry.xz) * t1.zwzw"
" + vec4(rx.yw, ry.yw) * t1.xyxy;"
" dd.xy = dd.xz * t1.zw + dd.yw * t1.xy;"
" vec2 t2 = step(dd.xy, dd.yx);"
" ret.xy = ret.xz * t2.yy + ret.yw * t2.xx;"
"\n#endif\n"
/* Nearest neighbour */
" gl_FragColor = texture2D(u_Texture, ret.xy);"
# else
/* Alternate version: some kind of linear interpolation */
" vec4 p0 = texture2D(u_Texture, vec2(rx.x, ry.x));"
" vec4 p1 = texture2D(u_Texture, vec2(rx.y, ry.y));"
" vec4 p2 = texture2D(u_Texture, vec2(rx.z, ry.z));"
" vec4 p3 = texture2D(u_Texture, vec2(rx.w, ry.w));"
" gl_FragColor = 1.0 / (dd.x + dd.y + dd.z + dd.w)"
" * (dd.x * p0 + dd.y * p1 + dd.z * p2 + dd.w * p3);"
# endif
"}"
#else
"void main(float2 a_Vertex : POSITION,"
" float2 a_TexCoord : TEXCOORD0,"
" uniform float4x4 u_ZoomSettings,"
" uniform float4 u_TexelSize,"
" uniform float4 u_ScreenSize,"
" out float4 out_Position : POSITION0,"
" out float4 v_CenterX : TEXCOORD0,"
" out float4 v_CenterY : TEXCOORD1,"
" out float4 v_IndexX : TEXCOORD2,"
" out float4 v_IndexY : TEXCOORD3)"
"{"
" out_Position = float4(a_Vertex, 0.0, 1.0);"
" float4 offsets = float4(0.5, -0.5, 0.015625, -0.015625);"
" float4 zoomscale = float4(u_ZoomSettings[2][0],"
" u_ZoomSettings[2][1],"
" u_ZoomSettings[2][2],"
" u_ZoomSettings[2][3]);"
" float4 zoomtx = float4(u_ZoomSettings[0][0],"
" u_ZoomSettings[0][1],"
" u_ZoomSettings[0][2],"
" u_ZoomSettings[0][3]);"
" float4 zoomty = float4(u_ZoomSettings[1][0],"
" u_ZoomSettings[1][1],"
" u_ZoomSettings[1][2],"
" u_ZoomSettings[1][3]);"
" v_CenterX = zoomscale * a_TexCoord.x + zoomtx"
" + offsets.xyxy * u_TexelSize.x;"
" v_CenterY = zoomscale * a_TexCoord.y - zoomty"
" + offsets.xyyx * u_TexelSize.y;"
" v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw;"
" v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz;"
"}",

"void main(in float4 v_CenterX : TEXCOORD0,"
" in float4 v_CenterY : TEXCOORD1,"
" in float4 v_IndexX : TEXCOORD2,"
" in float4 v_IndexY : TEXCOORD3,"
" uniform float4 u_TexelSize,"
" uniform sampler2D u_Texture,"
" out float4 out_FragColor : COLOR)"
"{"
" float4 v05 = float4(0.5, 0.5, 0.5, 0.5);"
" float4 rx, ry, t0, dx, dy, dd;"
" rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX);"
" ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY);"
" t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05);"
" dx = rx - v_CenterX;"
" dy = ry - v_CenterY;"
" dd = t0 / (0.000001 + (dx * dx) + (dy * dy));"
" ry = ry * 0.25 + float4(0.0, 0.25, 0.5, 0.75);"
" float2 t1 = step(dd.xz, dd.yw);"
" float4 ret = lerp(float4(rx.xz, ry.xz),"
" float4(rx.yw, ry.yw), t1.xyxy);"
" dd.xy = lerp(dd.xz, dd.yw, t1);"
" float t2 = step(dd.x, dd.y);"
" ret.xy = lerp(ret.xz, ret.yw, t2);"
" out_FragColor = tex2D(u_Texture, ret.xy);"
"}"
#endif
);
m_vertexattrib = m_shader->GetAttribLocation("a_Vertex", VertexUsage::Position, 0);
m_texattrib = m_shader->GetAttribLocation("a_TexCoord", VertexUsage::TexCoord, 0);
m_texeluni = m_shader->GetUniformLocation("u_TexelSize");


+ 196
- 0
test/tutorial/03_fractal.lolfx Переглянути файл

@@ -0,0 +1,196 @@
-- GLSL.Vert --

#version 120

#if defined HAVE_GLES_2X
precision highp float;
#endif

uniform mat4 u_ZoomSettings;
uniform vec4 u_TexelSize;
uniform vec4 u_ScreenSize;

attribute vec2 a_TexCoord;
attribute vec2 a_Vertex;

varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY;

void main(void)
{
gl_Position = vec4(a_Vertex, 0.0, 1.0);
/* Center point in [-.5,.5], apply zoom and translation
* transformation, and go back to texture coordinates
* in [0,1]. That's the ideal point we would like to
* compute the value for. Then add or remove half the
* size of a texel: the distance from this new point to
* the final point will be our error. */
vec4 offsets = vec4(0.5, -0.5, 0.015625, -0.015625);
vec4 zoomscale = vec4(u_ZoomSettings[0][2],
u_ZoomSettings[1][2],
u_ZoomSettings[2][2],
u_ZoomSettings[3][2]);
vec4 zoomtx = vec4(u_ZoomSettings[0][0],
u_ZoomSettings[1][0],
u_ZoomSettings[2][0],
u_ZoomSettings[3][0]);
vec4 zoomty = vec4(u_ZoomSettings[0][1],
u_ZoomSettings[1][1],
u_ZoomSettings[2][1],
u_ZoomSettings[3][1]);
v_CenterX = zoomscale * a_TexCoord.x + zoomtx
+ offsets.xyxy * u_TexelSize.x;
v_CenterY = zoomscale * a_TexCoord.y - zoomty
+ offsets.xyyx * u_TexelSize.y;
/* Precompute the multiple of one texel where our ideal
* point lies. The fragment shader will call floor() on
* this value. We add or remove a slight offset to avoid
* rounding issues at the image's edges. */
v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw;
v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz;
}

-- GLSL.Frag --

#version 120

#if defined HAVE_GLES_2X
precision highp float;
#endif

uniform vec4 u_TexelSize;
uniform sampler2D u_Texture;

varying vec4 v_CenterX, v_CenterY, v_IndexX, v_IndexY;

void main(void)
{
vec4 v05 = vec4(0.5, 0.5, 0.5, 0.5);
vec4 rx, ry, t0, dx, dy, dd;
/* Get a pixel coordinate from each slice into rx & ry */
rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX);
ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY);
/* Compute inverse distance to expected pixel in dd,
* and put zero if we fall outside the texture. */
t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05);
dx = rx - v_CenterX;
dy = ry - v_CenterY;
#if 0
vec4 dd = t0 * (abs(dx) + abs(dy));
vec4 dd = t0 / (0.001 + sqrt((dx * dx) + (dy * dy)));
#endif
dd = t0 / (0.000001 + (dx * dx) + (dy * dy));
/* Modify Y coordinate to select proper quarter. */
ry = ry * 0.25 + vec4(0.0, 0.25, 0.5, 0.75);

#if 1
# if 0
/* XXX: disabled until we can autodetect i915 */
/* t1.x <-- dd.x > dd.y */
/* t1.y <-- dd.z > dd.w */
vec2 t1 = step(dd.xz, dd.yw);
/* ret.x <-- max(rx.x, rx.y) wrt. t1.x */
/* ret.y <-- max(rx.z, rx.w) wrt. t1.y */
/* ret.z <-- max(ry.x, ry.y) wrt. t1.x */
/* ret.w <-- max(ry.z, ry.w) wrt. t1.y */
vec4 ret = mix(vec4(rx.xz, ry.xz),
vec4(rx.yw, ry.yw), t1.xyxy);
/* dd.x <-- max(dd.x, dd.y) */
/* dd.z <-- max(dd.z, dd.w) */
dd.xy = mix(dd.xz, dd.yw, t1);
/* t2 <-- dd.x > dd.z */
float t2 = step(dd.x, dd.y);
/* ret.x <-- max(ret.x, ret.y); */
/* ret.y <-- max(ret.z, ret.w); */
ret.xy = mix(ret.xz, ret.yw, t2);
# else
/* Fallback for i915 cards -- the trick to reduce the
* number of operations is to compute both step(a,b)
* and step(b,a) and hope that their sum is 1. This is
* almost always the case, and when it isn't we can
* afford to have a few wrong pixels. However, a real
* problem is when panning the image, because half the
* screen is likely to flicker. To avoid this problem,
* we cheat a little (see m_translate comment above). */
vec4 t1 = step(dd.xzyw, dd.ywxz);
vec4 ret = vec4(rx.xz, ry.xz) * t1.zwzw
+ vec4(rx.yw, ry.yw) * t1.xyxy;
dd.xy = dd.xz * t1.zw + dd.yw * t1.xy;
vec2 t2 = step(dd.xy, dd.yx);
ret.xy = ret.xz * t2.yy + ret.yw * t2.xx;
# endif
/* Nearest neighbour */
gl_FragColor = texture2D(u_Texture, ret.xy);
#else
/* Alternate version: some kind of linear interpolation */
vec4 p0 = texture2D(u_Texture, vec2(rx.x, ry.x));
vec4 p1 = texture2D(u_Texture, vec2(rx.y, ry.y));
vec4 p2 = texture2D(u_Texture, vec2(rx.z, ry.z));
vec4 p3 = texture2D(u_Texture, vec2(rx.w, ry.w));
gl_FragColor = 1.0 / (dd.x + dd.y + dd.z + dd.w)
* (dd.x * p0 + dd.y * p1 + dd.z * p2 + dd.w * p3);
#endif
}

-- HLSL.Vert --

void main(float2 a_Vertex : POSITION,
float2 a_TexCoord : TEXCOORD0,
uniform float4x4 u_ZoomSettings,
uniform float4 u_TexelSize,
uniform float4 u_ScreenSize,
out float4 out_Position : POSITION0,
out float4 v_CenterX : TEXCOORD0,
out float4 v_CenterY : TEXCOORD1,
out float4 v_IndexX : TEXCOORD2,
out float4 v_IndexY : TEXCOORD3)
{
out_Position = float4(a_Vertex, 0.0, 1.0);
float4 offsets = float4(0.5, -0.5, 0.015625, -0.015625);
float4 zoomscale = float4(u_ZoomSettings[2][0],
u_ZoomSettings[2][1],
u_ZoomSettings[2][2],
u_ZoomSettings[2][3]);
float4 zoomtx = float4(u_ZoomSettings[0][0],
u_ZoomSettings[0][1],
u_ZoomSettings[0][2],
u_ZoomSettings[0][3]);
float4 zoomty = float4(u_ZoomSettings[1][0],
u_ZoomSettings[1][1],
u_ZoomSettings[1][2],
u_ZoomSettings[1][3]);
v_CenterX = zoomscale * a_TexCoord.x + zoomtx
+ offsets.xyxy * u_TexelSize.x;
v_CenterY = zoomscale * a_TexCoord.y - zoomty
+ offsets.xyyx * u_TexelSize.y;
v_IndexX = v_CenterX * u_ScreenSize.z - offsets.zwzw;
v_IndexY = v_CenterY * u_ScreenSize.w - offsets.zwwz;
}

-- HLSL.Frag --

void main(in float4 v_CenterX : TEXCOORD0,
in float4 v_CenterY : TEXCOORD1,
in float4 v_IndexX : TEXCOORD2,
in float4 v_IndexY : TEXCOORD3,
uniform float4 u_TexelSize,
uniform sampler2D u_Texture,
out float4 out_FragColor : COLOR)
{
float4 v05 = float4(0.5, 0.5, 0.5, 0.5);
float4 rx, ry, t0, dx, dy, dd;
rx = u_TexelSize.x + u_TexelSize.z * floor(v_IndexX);
ry = u_TexelSize.y + u_TexelSize.w * floor(v_IndexY);
t0 = step(abs(rx - v05), v05) * step(abs(ry - v05), v05);
dx = rx - v_CenterX;
dy = ry - v_CenterY;
dd = t0 / (0.000001 + (dx * dx) + (dy * dy));
ry = ry * 0.25 + float4(0.0, 0.25, 0.5, 0.75);
float2 t1 = step(dd.xz, dd.yw);
float4 ret = lerp(float4(rx.xz, ry.xz),
float4(rx.yw, ry.yw), t1.xyxy);
dd.xy = lerp(dd.xz, dd.yw, t1);
float t2 = step(dd.x, dd.y);
ret.xy = lerp(ret.xz, ret.yw, t2);
out_FragColor = tex2D(u_Texture, ret.xy);
}


+ 2
- 0
test/tutorial/Makefile.am Переглянути файл

@@ -27,11 +27,13 @@ nodist_01_triangle_SOURCES = 01_triangle.lolfx.cpp
01_triangle_DEPENDENCIES = $(top_builddir)/src/liblol.a

02_cube_SOURCES = 02_cube.cpp
nodist_02_cube_SOURCES = 02_cube.lolfx.cpp
02_cube_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
02_cube_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
02_cube_DEPENDENCIES = $(top_builddir)/src/liblol.a

03_fractal_SOURCES = 03_fractal.cpp
nodist_03_fractal_SOURCES = 03_fractal.lolfx.cpp
03_fractal_CPPFLAGS = @LOL_CFLAGS@ @PIPI_CFLAGS@
03_fractal_LDFLAGS = $(top_builddir)/src/liblol.a @LOL_LIBS@ @PIPI_LIBS@
03_fractal_DEPENDENCIES = $(top_builddir)/src/liblol.a


+ 3
- 0
win32/02_cube.vcxproj Переглянути файл

@@ -29,6 +29,9 @@
<ItemGroup>
<ClCompile Include="..\test\tutorial\02_cube.cpp" />
</ItemGroup>
<ItemGroup>
<LolFxCompile Include="..\test\tutorial\02_cube.lolfx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="lolcore.vcxproj">
<Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project>


+ 3
- 0
win32/03_fractal.vcxproj Переглянути файл

@@ -29,6 +29,9 @@
<ItemGroup>
<ClCompile Include="..\test\tutorial\03_fractal.cpp" />
</ItemGroup>
<ItemGroup>
<LolFxCompile Include="..\test\tutorial\03_fractal.lolfx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="lolcore.vcxproj">
<Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project>


Завантаження…
Відмінити
Зберегти