of slightly overkill Image objects.undefined
@@ -119,7 +119,7 @@ liblolcore_sources = \ | |||||
image/dither/random.cpp image/dither/ediff.cpp \ | image/dither/random.cpp image/dither/ediff.cpp \ | ||||
image/dither/ostromoukhov.cpp \ | image/dither/ostromoukhov.cpp \ | ||||
image/filter/autocontrast.cpp image/filter/convolution.cpp \ | image/filter/autocontrast.cpp image/filter/convolution.cpp \ | ||||
image/render/noise.cpp image/render/screen.cpp \ | |||||
image/render/noise.cpp \ | |||||
\ | \ | ||||
loldebug.h \ | loldebug.h \ | ||||
debug/fps.cpp debug/fps.h debug/lines.cpp \ | debug/fps.cpp debug/fps.h debug/lines.cpp \ | ||||
@@ -27,54 +27,48 @@ namespace lol | |||||
* Making the matrix generic is not terribly slower: the performance | * Making the matrix generic is not terribly slower: the performance | ||||
* hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the | * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the | ||||
* benefit of a lot less code. */ | * benefit of a lot less code. */ | ||||
Image Image::DitherEdiff(Image &kernel, ScanMode scan) const | |||||
Image Image::DitherEdiff(Array2D<float> const &kernel, ScanMode scan) const | |||||
{ | { | ||||
Image dst = *this; | Image dst = *this; | ||||
float *pixels = dst.Lock<PixelFormat::Y_F32>(); | |||||
int w = dst.GetSize().x; | |||||
int h = dst.GetSize().y; | |||||
float *kerdata = kernel.Lock<PixelFormat::Y_F32>(); | |||||
int kw = kernel.GetSize().x; | |||||
int kh = kernel.GetSize().y; | |||||
ivec2 size = dst.GetSize(); | |||||
ivec2 ksize = kernel.GetSize(); | |||||
int kx; | int kx; | ||||
for (kx = 0; kx < kw; kx++) | |||||
if (kerdata[kx] > 0.f) | |||||
for (kx = 0; kx < ksize.x; kx++) | |||||
if (kernel[kx][0] > 0.f) | |||||
break; | break; | ||||
for (int y = 0; y < h; y++) | |||||
float *pixels = dst.Lock<PixelFormat::Y_F32>(); | |||||
for (int y = 0; y < size.y; y++) | |||||
{ | { | ||||
bool reverse = (y & 1) && (scan == ScanMode::Serpentine); | bool reverse = (y & 1) && (scan == ScanMode::Serpentine); | ||||
for (int x = 0; x < w; x++) | |||||
for (int x = 0; x < size.x; x++) | |||||
{ | { | ||||
int x2 = reverse ? w - 1 - x : x; | |||||
int x2 = reverse ? size.x - 1 - x : x; | |||||
int s = reverse ? -1 : 1; | int s = reverse ? -1 : 1; | ||||
float p = pixels[y * w + x2]; | |||||
float p = pixels[y * size.x + x2]; | |||||
float q = p < 0.5f ? 0.f : 1.f; | float q = p < 0.5f ? 0.f : 1.f; | ||||
pixels[y * w + x2] = q; | |||||
pixels[y * size.x + x2] = q; | |||||
float e = (p - q); | float e = (p - q); | ||||
for (int j = 0; j < kh && y < h - j; j++) | |||||
for (int i = 0; i < kw; i++) | |||||
for (int j = 0; j < ksize.y && y < size.y - j; j++) | |||||
for (int i = 0; i < ksize.x; i++) | |||||
{ | { | ||||
if (j == 0 && i <= kx) | if (j == 0 && i <= kx) | ||||
continue; | continue; | ||||
if (x + i - kx < 0 || x + i - kx >= w) | |||||
if (x + i - kx < 0 || x + i - kx >= size.x) | |||||
continue; | continue; | ||||
pixels[(y + j) * w + x2 + (i - kx) * s] | |||||
+= e * kerdata[j * kw + i]; | |||||
pixels[(y + j) * size.x + x2 + (i - kx) * s] | |||||
+= e * kernel[i][j]; | |||||
} | } | ||||
} | } | ||||
} | } | ||||
kernel.Unlock(kerdata); | |||||
dst.Unlock(pixels); | dst.Unlock(pixels); | ||||
return dst; | return dst; | ||||
@@ -1,110 +0,0 @@ | |||||
// | |||||
// Lol Engine | |||||
// | |||||
// Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// | |||||
#if defined HAVE_CONFIG_H | |||||
# include "config.h" | |||||
#endif | |||||
#include "core.h" | |||||
/* | |||||
* Halftoning screen functions | |||||
*/ | |||||
namespace lol | |||||
{ | |||||
bool Image::RenderBayer(ivec2 size) | |||||
{ | |||||
if (size.x <= 0 || size.y <= 0) | |||||
return false; | |||||
int n = 1; | |||||
while (n < size.x || n < size.y) | |||||
n *= 2; | |||||
SetSize(size); | |||||
float *pixels = Lock<PixelFormat::Y_F32>(); | |||||
for (int j = 0; j < size.y; j++) | |||||
for (int i = 0; i < size.x; i++) | |||||
{ | |||||
int x = 0; | |||||
for (int k = 1, l = n * n / 4; k < n; k *= 2, l /= 4) | |||||
{ | |||||
if ((i & k) && (j & k)) | |||||
x += l; | |||||
else if (i & k) | |||||
x += 3 * l; | |||||
else if (j & k) | |||||
x += 2 * l; | |||||
} | |||||
pixels[j * size.x + i] = (float)(x + 1) / (n * n + 1); | |||||
} | |||||
Unlock(pixels); | |||||
return true; | |||||
} | |||||
typedef struct | |||||
{ | |||||
int x, y; | |||||
float dist; | |||||
} | |||||
dot_t; | |||||
static int cmpdot(const void *p1, const void *p2) | |||||
{ | |||||
return ((dot_t const *)p1)->dist > ((dot_t const *)p2)->dist; | |||||
} | |||||
bool Image::RenderHalftone(ivec2 size) | |||||
{ | |||||
if (size.x <= 0 || size.y <= 0) | |||||
return false; | |||||
Array<dot_t> circle; | |||||
circle.Resize(size.x * size.y); | |||||
for (int y = 0; y < size.y; y++) | |||||
for (int x = 0; x < size.x; x++) | |||||
{ | |||||
float dy = ((float)y + 0.07f) / size.y - 0.5f; | |||||
float dx = (float)x / size.x - 0.5f; | |||||
/* Using dx²+dy² here creates another interesting halftone. */ | |||||
float r = - lol::cos(F_PI * (dx - dy)) - lol::cos(F_PI * (dx + dy)); | |||||
circle[y * size.x + x].x = x; | |||||
circle[y * size.x + x].y = y; | |||||
circle[y * size.x + x].dist = r; | |||||
} | |||||
std::qsort(circle.Data(), size.x * size.y, sizeof(dot_t), cmpdot); | |||||
SetSize(2 * size); | |||||
float *pixels = Lock<PixelFormat::Y_F32>(); | |||||
float mul = 1.f / (size.x * size.y * 4 + 1); | |||||
for (int n = 0; n < size.x * size.y; n++) | |||||
{ | |||||
int x = circle[n].x; | |||||
int y = circle[n].y; | |||||
pixels[y * (2 * size.x) + x] = (float)(2 * n + 1) * mul; | |||||
pixels[(y + size.y) * (2 * size.x) + x + size.x] = (float)(2 * n + 2) * mul; | |||||
pixels[(y + size.y) * (2 * size.x) + x] = 1.0f - (float)(2 * n + 1) * mul; | |||||
pixels[y * (2 * size.x) + x + size.x] = 1.0f - (float)(2 * n + 2) * mul; | |||||
} | |||||
Unlock(pixels); | |||||
return true; | |||||
} | |||||
} /* namespace lol */ | |||||
@@ -15,7 +15,7 @@ | |||||
#include "core.h" | #include "core.h" | ||||
/* | /* | ||||
* Stock images | |||||
* Stock images and kernels | |||||
*/ | */ | ||||
namespace lol | namespace lol | ||||
@@ -23,50 +23,136 @@ namespace lol | |||||
bool Image::Stock(char const *name) | bool Image::Stock(char const *name) | ||||
{ | { | ||||
/* Generate a Bayer dithering pattern. */ | |||||
if (!strncmp(name, "bayer:", 6)) | |||||
/* Generate an error diffusion matrix. */ | |||||
if (!strncmp(name, "ediff:", 6)) | |||||
{ | { | ||||
float const *ker = nullptr; | |||||
ivec2 size(0); | ivec2 size(0); | ||||
size.x = atoi(name + 6); | |||||
name = strchr(name + 6, 'x'); | |||||
if (name) | |||||
size.y = atoi(name + 1); | |||||
if (!size.y) | |||||
size.y = size.x; | |||||
return RenderBayer(size); | |||||
SetSize(size); | |||||
float *pixels = Lock<PixelFormat::Y_F32>(); | |||||
memcpy(pixels, ker, size.x * size.y * sizeof(float)); | |||||
Unlock(pixels); | |||||
return true; | |||||
} | } | ||||
/* Generate a clustered dithering pattern. */ | |||||
if (!strncmp(name, "halftone:", 9)) | |||||
/* Generate a completely random image. */ | |||||
if (!strncmp(name, "random:", 7)) | |||||
{ | { | ||||
ivec2 size(0); | ivec2 size(0); | ||||
size.x = atoi(name + 9); | |||||
name = strchr(name + 9, 'x'); | |||||
size.x = atoi(name + 7); | |||||
name = strchr(name + 7, 'x'); | |||||
if (name) | if (name) | ||||
size.y = atoi(name + 1); | size.y = atoi(name + 1); | ||||
if (!size.y) | if (!size.y) | ||||
size.y = size.x; | size.y = size.x; | ||||
if (size.x <= 0 || size.y <= 0) | |||||
return false; | |||||
return RenderHalftone(size); | |||||
return RenderRandom(size); | |||||
} | } | ||||
/* Generate an error diffusion matrix. */ | |||||
if (!strncmp(name, "ediff:", 6)) | |||||
return false; | |||||
} | |||||
Array2D<float> Image::BayerKernel(ivec2 size) | |||||
{ | |||||
Array2D<float> ret(size); | |||||
int n = 1; | |||||
while (n < size.x || n < size.y) | |||||
n *= 2; | |||||
for (int j = 0; j < size.y; j++) | |||||
for (int i = 0; i < size.x; i++) | |||||
{ | |||||
int x = 0; | |||||
for (int k = 1, l = n * n / 4; k < n; k *= 2, l /= 4) | |||||
{ | |||||
if ((i & k) && (j & k)) | |||||
x += l; | |||||
else if (i & k) | |||||
x += 3 * l; | |||||
else if (j & k) | |||||
x += 2 * l; | |||||
} | |||||
ret[i][j] = (float)(x + 1) / (n * n + 1); | |||||
} | |||||
return ret; | |||||
} | |||||
struct Dot | |||||
{ | |||||
int x, y; | |||||
float dist; | |||||
}; | |||||
static int cmpdot(const void *p1, const void *p2) | |||||
{ | |||||
return ((Dot const *)p1)->dist > ((Dot const *)p2)->dist; | |||||
} | |||||
Array2D<float> Image::HalftoneKernel(ivec2 size) | |||||
{ | |||||
Array2D<float> ret(size); | |||||
ivec2 csize = (size + ivec2(1)) / 2; | |||||
Array<Dot> circle; | |||||
circle.Resize(csize.x * csize.y); | |||||
for (int y = 0; y < csize.y; y++) | |||||
for (int x = 0; x < csize.x; x++) | |||||
{ | |||||
float dy = ((float)y + 0.07f) / csize.y - 0.5f; | |||||
float dx = (float)x / csize.x - 0.5f; | |||||
/* Using dx²+dy² here creates another interesting halftone. */ | |||||
float r = - lol::cos(F_PI * (dx - dy)) - lol::cos(F_PI * (dx + dy)); | |||||
circle[y * csize.x + x].x = x; | |||||
circle[y * csize.x + x].y = y; | |||||
circle[y * csize.x + x].dist = r; | |||||
} | |||||
/* FIXME: use std::sort here */ | |||||
std::qsort(circle.Data(), csize.x * csize.y, sizeof(Dot), cmpdot); | |||||
float mul = 1.f / (csize.x * csize.y * 4 + 1); | |||||
for (int n = 0; n < csize.x * csize.y; n++) | |||||
{ | { | ||||
float const *ker = nullptr; | |||||
ivec2 size(0); | |||||
int x = circle[n].x; | |||||
int y = circle[n].y; | |||||
ret[x][y] = (float)(2 * n + 1) * mul; | |||||
ret[x + csize.x][y + csize.y] = (float)(2 * n + 2) * mul; | |||||
ret[x][y + csize.y] = 1.0f - (float)(2 * n + 1) * mul; | |||||
ret[x + csize.x][y] = 1.0f - (float)(2 * n + 2) * mul; | |||||
} | |||||
if (!strcmp(name + 6, "fs")) | |||||
return ret; | |||||
} | |||||
Array2D<float> EdiffKernel(EdiffAlgorithm algorithm) | |||||
{ | |||||
Array2D<float> ret; | |||||
switch(algorithm) | |||||
{ | |||||
case EdiffAlgorithm::FloydSteinberg: | |||||
ret.SetSize(ivec2(3, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 1., 7./16, | 0., 1., 7./16, | ||||
3./16, 5./16, 1./16, | 3./16, 5./16, 1./16, | ||||
}; | }; | ||||
ker = myker; size = ivec2(3, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "jajuni")) | |||||
return ret; | |||||
case EdiffAlgorithm::JaJuNi: | |||||
ret.SetSize(ivec2(5, 3)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
@@ -74,9 +160,11 @@ bool Image::Stock(char const *name) | |||||
3./48, 5./48, 7./48, 5./48, 3./48, | 3./48, 5./48, 7./48, 5./48, 3./48, | ||||
1./48, 3./48, 5./48, 3./48, 1./48, | 1./48, 3./48, 5./48, 3./48, 1./48, | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 3); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "atkinson")) | |||||
return ret; | |||||
case EdiffAlgorithm::Atkinson: | |||||
ret.SetSize(ivec2(4, 3)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
@@ -84,36 +172,44 @@ bool Image::Stock(char const *name) | |||||
1./8, 1./8, 1./8, 0., | 1./8, 1./8, 1./8, 0., | ||||
0., 1./8, 0., 0., | 0., 1./8, 0., 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(4, 3); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "fan")) | |||||
return ret; | |||||
case EdiffAlgorithm::Fan: | |||||
ret.SetSize(ivec2(4, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 0., 1., 7./16, | 0., 0., 1., 7./16, | ||||
1./16, 3./16, 5./16, 0., | 1./16, 3./16, 5./16, 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(4, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "shiaufan")) | |||||
return ret; | |||||
case EdiffAlgorithm::ShiauFan: | |||||
ret.SetSize(ivec2(4, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 0., 1., 1./2, | 0., 0., 1., 1./2, | ||||
1./8, 1./8, 1./4, 0., | 1./8, 1./8, 1./4, 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(4, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "shiaufan2")) | |||||
return ret; | |||||
case EdiffAlgorithm::ShiauFan2: | |||||
ret.SetSize(ivec2(5, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 0., 0., 1., 1./2, | 0., 0., 0., 1., 1./2, | ||||
1./16, 1./16, 1./8, 1./4, 0., | 1./16, 1./16, 1./8, 1./4, 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "stucki")) | |||||
return ret; | |||||
case EdiffAlgorithm::Stucki: | |||||
ret.SetSize(ivec2(5, 3)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
@@ -121,18 +217,22 @@ bool Image::Stock(char const *name) | |||||
2./42, 4./42, 8./42, 4./42, 2./42, | 2./42, 4./42, 8./42, 4./42, 2./42, | ||||
1./42, 2./42, 4./42, 2./42, 1./42, | 1./42, 2./42, 4./42, 2./42, 1./42, | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 3); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "burkes")) | |||||
return ret; | |||||
case EdiffAlgorithm::Burkes: | |||||
ret.SetSize(ivec2(5, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 0., 1., 4./16, 2./16, | 0., 0., 1., 4./16, 2./16, | ||||
1./16, 2./16, 4./16, 2./16, 1./16, | 1./16, 2./16, 4./16, 2./16, 1./16, | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "sierra")) | |||||
return ret; | |||||
case EdiffAlgorithm::Sierra: | |||||
ret.SetSize(ivec2(5, 3)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
@@ -140,53 +240,34 @@ bool Image::Stock(char const *name) | |||||
2./32, 4./32, 5./32, 4./32, 2./32, | 2./32, 4./32, 5./32, 4./32, 2./32, | ||||
0., 2./32, 3./32, 2./32, 0., | 0., 2./32, 3./32, 2./32, 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 3); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "sierra2")) | |||||
return ret; | |||||
case EdiffAlgorithm::Sierra2: | |||||
ret.SetSize(ivec2(5, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 0., 1., 4./16, 3./16, | 0., 0., 1., 4./16, 3./16, | ||||
1./16, 2./16, 3./16, 2./16, 1./16, | 1./16, 2./16, 3./16, 2./16, 1./16, | ||||
}; | }; | ||||
ker = myker; size = ivec2(5, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
else if (!strcmp(name + 6, "lite")) | |||||
return ret; | |||||
case EdiffAlgorithm::Lite: | |||||
ret.SetSize(ivec2(3, 2)); | |||||
{ | { | ||||
static float const myker[] = | static float const myker[] = | ||||
{ | { | ||||
0., 1., 1./2, | 0., 1., 1./2, | ||||
1./4, 1./4, 0., | 1./4, 1./4, 0., | ||||
}; | }; | ||||
ker = myker; size = ivec2(3, 2); | |||||
memcpy(&ret[0][0], myker, sizeof(myker)); | |||||
} | } | ||||
SetSize(size); | |||||
float *pixels = Lock<PixelFormat::Y_F32>(); | |||||
memcpy(pixels, ker, size.x * size.y * sizeof(float)); | |||||
Unlock(pixels); | |||||
return true; | |||||
} | |||||
/* Generate a completely random image. */ | |||||
if (!strncmp(name, "random:", 7)) | |||||
{ | |||||
ivec2 size(0); | |||||
size.x = atoi(name + 7); | |||||
name = strchr(name + 7, 'x'); | |||||
if (name) | |||||
size.y = atoi(name + 1); | |||||
if (!size.y) | |||||
size.y = size.x; | |||||
if (size.x <= 0 || size.y <= 0) | |||||
return false; | |||||
return RenderRandom(size); | |||||
return ret; | |||||
} | } | ||||
return false; | |||||
return ret; | |||||
} | } | ||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -41,6 +41,21 @@ enum class ScanMode : uint8_t | |||||
Serpentine, | Serpentine, | ||||
}; | }; | ||||
enum class EdiffAlgorithm : uint8_t | |||||
{ | |||||
FloydSteinberg, | |||||
JaJuNi, | |||||
Atkinson, | |||||
Fan, | |||||
ShiauFan, | |||||
ShiauFan2, | |||||
Stucki, | |||||
Burkes, | |||||
Sierra, | |||||
Sierra2, | |||||
Lite, | |||||
}; | |||||
class Image | class Image | ||||
{ | { | ||||
public: | public: | ||||
@@ -75,10 +90,13 @@ public: | |||||
bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const; | bool RetrieveTiles(Array<ivec2, ivec2>& tiles) const; | ||||
/* Image processing kernels */ | |||||
static Array2D<float> BayerKernel(ivec2 size); | |||||
static Array2D<float> HalftoneKernel(ivec2 size); | |||||
static Array2D<float> EdiffKernel(EdiffAlgorithm algorithm); | |||||
/* Rendering */ | /* Rendering */ | ||||
bool Stock(char const *desc); | bool Stock(char const *desc); | ||||
bool RenderBayer(ivec2 size); | |||||
bool RenderHalftone(ivec2 size); | |||||
bool RenderRandom(ivec2 size); | bool RenderRandom(ivec2 size); | ||||
/* Image processing */ | /* Image processing */ | ||||
@@ -86,7 +104,8 @@ public: | |||||
Image Convolution(Array2D<float> const &kernel); | Image Convolution(Array2D<float> const &kernel); | ||||
Image DitherRandom() const; | Image DitherRandom() const; | ||||
Image DitherEdiff(Image &kernel, ScanMode scan = ScanMode::Raster) const; | |||||
Image DitherEdiff(Array2D<float> const &kernel, | |||||
ScanMode scan = ScanMode::Raster) const; | |||||
Image DitherOstromoukhov(ScanMode scan = ScanMode::Raster) const; | Image DitherOstromoukhov(ScanMode scan = ScanMode::Raster) const; | ||||
private: | private: | ||||
@@ -157,7 +157,6 @@ | |||||
<ClCompile Include="image\image.cpp" /> | <ClCompile Include="image\image.cpp" /> | ||||
<ClCompile Include="image\pixels.cpp" /> | <ClCompile Include="image\pixels.cpp" /> | ||||
<ClCompile Include="image\render\noise.cpp" /> | <ClCompile Include="image\render\noise.cpp" /> | ||||
<ClCompile Include="image\render\screen.cpp" /> | |||||
<ClCompile Include="input\controller.cpp" /> | <ClCompile Include="input\controller.cpp" /> | ||||
<ClCompile Include="input\input.cpp" /> | <ClCompile Include="input\input.cpp" /> | ||||
<ClCompile Include="layer.cpp" /> | <ClCompile Include="layer.cpp" /> | ||||
@@ -373,9 +373,6 @@ | |||||
<ClCompile Include="image\render\noise.cpp"> | <ClCompile Include="image\render\noise.cpp"> | ||||
<Filter>image\render</Filter> | <Filter>image\render</Filter> | ||||
</ClCompile> | </ClCompile> | ||||
<ClCompile Include="image\render\screen.cpp"> | |||||
<Filter>image\render</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="image\pixels.cpp"> | <ClCompile Include="image\pixels.cpp"> | ||||
<Filter>image</Filter> | <Filter>image</Filter> | ||||
</ClCompile> | </ClCompile> | ||||
@@ -784,4 +781,4 @@ | |||||
</None> | </None> | ||||
<None Include="Makefile.am" /> | <None Include="Makefile.am" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | |||||
</Project> |