Update to v091 release.

byuu says:

A few issues crept up in the last release, this should take care of
them.

First, it seems that the 32-bit runtime on 64-bit versions of Windows
have 64-bit time functions; whereas true 32-bit Windows does not. This
was causing a DLL error when attempting to load bsnes v090.

Second, when there were more than 2,000 files in the same folder on
Windows, it was lagging the file browser. With OV2's help, I've fixed
that and it'll now load the list instantly.

Lastly, I've included the missing video shaders this time.
This commit is contained in:
Tim Allen 2012-08-11 12:18:19 +10:00
parent 47dffcae85
commit 7f404e6edb
18 changed files with 487 additions and 769 deletions

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
namespace Emulator {
static const char Name[] = "bsnes";
static const char Version[] = "090";
static const char Version[] = "091";
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}

View File

@ -24,6 +24,14 @@ struct image {
uint64_t mask;
unsigned depth;
unsigned shift;
inline bool operator==(const Channel &source) {
return mask == source.mask && depth == source.depth && shift == source.shift;
}
inline bool operator!=(const Channel &source) {
return !operator==(source);
}
} alpha, red, green, blue;
typedef double (*interpolation)(double, double, double, double, double);
@ -31,6 +39,9 @@ struct image {
static inline unsigned bitShift(uint64_t color);
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
inline bool operator==(const image &source);
inline bool operator!=(const image &source);
inline image& operator=(const image &source);
inline image& operator=(image &&source);
inline image(const image &source);
@ -89,6 +100,26 @@ uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetD
//public
bool image::operator==(const image &source) {
if(width != source.width) return false;
if(height != source.height) return false;
if(pitch != source.pitch) return false;
if(endian != source.endian) return false;
if(stride != source.stride) return false;
if(alpha != source.alpha) return false;
if(red != source.red) return false;
if(green != source.green) return false;
if(blue != source.blue) return false;
return memcmp(data, source.data, width * height * stride) == 0;
}
bool image::operator!=(const image &source) {
return !operator==(source);
}
image& image::operator=(const image &source) {
free();
@ -110,6 +141,8 @@ image& image::operator=(const image &source) {
}
image& image::operator=(image &&source) {
free();
width = source.width;
height = source.height;
pitch = source.pitch;

View File

@ -8,11 +8,21 @@
#include <sys/time.h>
#include <nds/nds.hpp>
#if defined(__amd64__) || defined(_M_AMD64)
struct timeval {
int64_t tv_sec, tv_usec;
};
#define timegm(tm) _mkgmtime64(tm)
#define gmtime(tv) _gmtime64(tv)
#else
//Windows 32-bit run-time doesn't have 64-bit time functions
struct timeval {
time_t tv_sec, tv_usec;
};
#define timegm(tm) mktime(tm)
#define gmtime(tv) localtime(tv)
#endif
#define gettimeofday(tv,tz) gettimeofday64(tv,tz)
int gettimeofday64(struct timeval *tv, struct timezone *tz) {

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp'
**
** Created: Sun Jul 22 02:20:29 2012
** Created: Thu Aug 9 18:10:14 2012
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
**
** WARNING! All changes made in this file will be lost!

View File

@ -69,6 +69,8 @@ struct pTimer : public pObject {
struct pWindow : public pObject {
Window &window;
static Window& none();
void append(Layout &layout);
void append(Menu &menu);
void append(Widget &widget);

View File

@ -1,3 +1,9 @@
Window& pWindow::none() {
static Window *window = nullptr;
if(window == nullptr) window = new Window;
return *window;
}
void pWindow::append(Layout &layout) {
}

View File

@ -56,16 +56,26 @@ string pDialogWindow::fileSave(Window &parent, const string &path, const lstring
return FileDialog(true, parent, path, filter);
}
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT msg, LPARAM lparam, LPARAM lpdata) {
if(msg == BFFM_INITIALIZED) {
if(lpdata) SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpdata);
}
return 0;
}
string pDialogWindow::folderSelect(Window &parent, const string &path) {
wchar_t wfilename[PATH_MAX + 1] = L"";
utf16_t wpath(string{path}.transform("/", "\\"));
BROWSEINFO bi;
bi.hwndOwner = &parent != &Window::none() ? parent.p.hwnd : 0;
bi.pidlRoot = NULL;
bi.pszDisplayName = wfilename;
bi.lpszTitle = L"";
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)(wchar_t*)wpath;
bi.iImage = 0;
bool result = false;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);

View File

@ -373,6 +373,8 @@ struct pLineEdit : public pWidget {
struct pListView : public pWidget {
ListView &listView;
HIMAGELIST imageList;
vector<vector<unsigned>> imageMap;
vector<image> images;
bool lostFocus;
void append(const lstring &text);
@ -396,7 +398,7 @@ struct pListView : public pWidget {
void destructor();
void orphan();
void setGeometry(const Geometry &geometry);
void setImageList();
void buildImageList();
};
struct pProgressBar : public pWidget {

View File

@ -6,6 +6,34 @@ unsigned ListView_GetColumnCount(HWND hwnd) {
return --count;
}
void ListView_SetImage(HWND hwnd, HIMAGELIST imageList, unsigned row, unsigned column, unsigned imageID) {
//if this is the first image assigned, set image list now
//do not set sooner, or image blocks will appear in a list with no images
if(ListView_GetImageList(hwnd, LVSIL_SMALL) != imageList) {
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
}
LVITEM item;
item.mask = LVIF_IMAGE;
item.iItem = row;
item.iSubItem = column;
item.iImage = imageID;
ListView_SetItem(hwnd, &item);
}
void ImageList_Append(HIMAGELIST imageList, const nall::image &source) {
auto image = source;
if(image.empty()) {
image.allocate(15, 15);
image.clear(GetSysColor(COLOR_WINDOW));
}
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
image.scale(15, 15, Interpolation::Linear);
HBITMAP bitmap = CreateBitmap(image);
ImageList_Add(imageList, bitmap, NULL);
DeleteObject(bitmap);
}
void pListView::append(const lstring &list) {
wchar_t empty[] = L"";
unsigned row = ListView_GetItemCount(hwnd);
@ -43,11 +71,11 @@ void pListView::modify(unsigned row, const lstring &list) {
void pListView::remove(unsigned row) {
ListView_DeleteItem(hwnd, row);
setImageList();
}
void pListView::reset() {
ListView_DeleteAllItems(hwnd);
buildImageList(); //free previously allocated images
}
bool pListView::selected() {
@ -103,7 +131,19 @@ void pListView::setHeaderVisible(bool visible) {
}
void pListView::setImage(unsigned row, unsigned column, const image &image) {
setImageList();
//assign existing image
for(unsigned n = 0; n < images.size(); n++) {
if(images[n] == image) {
imageMap(row)(column) = n;
return ListView_SetImage(hwnd, imageList, row, column, n);
}
}
//append and assign new image
imageMap(row)(column) = images.size();
images.append(image);
ImageList_Append(imageList, image);
ListView_SetImage(hwnd, imageList, row, column, imageMap(row)(column));
}
void pListView::setSelected(bool selected) {
@ -138,7 +178,7 @@ void pListView::constructor() {
setCheckable(listView.state.checkable);
for(auto &text : listView.state.text) append(text);
for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]);
setImageList();
buildImageList();
if(listView.state.selected) setSelection(listView.state.selection);
autoSizeColumns();
synchronize();
@ -158,53 +198,46 @@ void pListView::setGeometry(const Geometry &geometry) {
autoSizeColumns();
}
void pListView::setImageList() {
void pListView::buildImageList() {
auto &list = listView.state.image;
unsigned columns = listView.state.text.size();
unsigned rows = max(1u, listView.state.headerText.size());
if(imageList) {
ImageList_Destroy(imageList);
imageList = nullptr;
}
ListView_SetImageList(hwnd, NULL, LVSIL_SMALL);
if(imageList) ImageList_Destroy(imageList);
imageList = ImageList_Create(15, 15, ILC_COLOR32, 1, 0);
imageMap.reset();
images.reset();
images.append(nall::image()); //empty icon for cells without an image assigned (I_IMAGENONE does not work)
//create a vector of unique images from all images used (many cells may use the same image)
for(unsigned y = 0; y < list.size(); y++) {
for(unsigned x = 0; x < list[y].size(); x++) {
bool found = false;
for(auto &row : listView.state.image) {
for(auto &column : row) {
if(column.empty() == false) {
for(unsigned z = 0; z < images.size(); z++) {
if(list[y][x] == images[z]) {
found = true;
imageMap(y)(x) = z;
break;
}
}
if(found == false) {
imageMap(y)(x) = images.size();
images.append(list[y][x]);
}
if(found == false) return;
imageList = ImageList_Create(15, 15, ILC_COLOR32, 1, 0);
nall::image image;
image.allocate(15, 15);
image.clear(GetSysColor(COLOR_WINDOW));
ImageList_Add(imageList, CreateBitmap(image), NULL);
for(unsigned row = 0; row < list.size(); row++) {
for(unsigned column = 0; column < list(row).size(); column++) {
nall::image image = list(row)(column);
if(image.empty()) continue;
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
image.scale(15, 15, Interpolation::Linear);
ImageList_Add(imageList, CreateBitmap(image), NULL);
}
}
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
//build image list
for(auto &imageItem : images) ImageList_Append(imageList, imageItem);
if(images.size() <= 1) return;
unsigned ID = 1;
for(unsigned row = 0; row < list.size(); row++) {
for(unsigned column = 0; column < list(row).size(); column++) {
if(list(row)(column).empty()) continue; //I_IMAGENONE does not work properly
LVITEM item;
item.mask = LVIF_IMAGE;
item.iItem = row;
item.iSubItem = column;
item.iImage = ID++;
ListView_SetItem(hwnd, &item);
//set images for all cells
for(unsigned y = 0; y < columns; y++) {
for(unsigned x = 0; x < rows; x++) {
ListView_SetImage(hwnd, imageList, y, x, imageMap(y)(x));
}
}
}

View File

@ -0,0 +1,17 @@
shader language=GLSL
vertex~
void main(void) {
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
}
fragment~ filter=linear
uniform sampler2D rubyTexture;
void main(void) {
vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);
vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));
if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8;
gl_FragColor = intens;
}

View File

@ -0,0 +1,61 @@
shader language=GLSL
vertex~
uniform vec2 rubyTextureSize;
void main()
{
float x = 0.5 * (1.0 / rubyTextureSize.x);
float y = 0.5 * (1.0 / rubyTextureSize.y);
vec2 dg1 = vec2( x, y);
vec2 dg2 = vec2(-x, y);
vec2 dx = vec2(x, 0.0);
vec2 dy = vec2(0.0, y);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
}
fragment~ filter=linear
vec4 compress(vec4 in_color, float threshold, float ratio)
{
vec4 diff = in_color - vec4(threshold);
diff = clamp(diff, 0.0, 100.0);
return in_color - (diff * (1.0 - 1.0/ratio));
}
uniform sampler2D rubyTexture;
uniform vec2 rubyTextureSize;
void main()
{
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
vec2 tex = gl_TexCoord[0].xy;
vec2 texsize = rubyTextureSize;
vec3 first = mix(c00, c20, fract(tex.x * texsize.x + 0.5));
vec3 second = mix(c02, c22, fract(tex.x * texsize.x + 0.5));
vec3 mid_horiz = mix(c01, c21, fract(tex.x * texsize.x + 0.5));
vec3 mid_vert = mix(c10, c12, fract(tex.y * texsize.y + 0.5));
vec3 res = mix(first, second, fract(tex.y * texsize.y + 0.5));
vec4 final = vec4(0.26 * (res + mid_horiz + mid_vert) + 3.5 * abs(res - mix(mid_horiz, mid_vert, 0.5)), 1.0);
gl_FragColor = compress(final, 0.8, 5.0);
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader language="GLSL">
<fragment filter="linear"><![CDATA[
uniform sampler2D rubyTexture;
uniform vec2 rubyInputSize;
uniform vec2 rubyTextureSize;
#define distortion 0.2
vec2 barrelDistortion(vec2 coord) {
vec2 cc = coord - 0.5;
float dist = dot(cc, cc);
return coord + cc * (dist + distortion * dist * dist) * distortion;
}
void main(void) {
vec2 coord = barrelDistortion (gl_TexCoord[0] * rubyTextureSize / rubyInputSize) * rubyInputSize / rubyTextureSize;
gl_FragColor = texture2D(rubyTexture, coord);
}
]]></fragment>
</shader>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader language="GLSL">
<vertex><![CDATA[
uniform vec2 rubyTextureSize;
void main() {
float x = 0.5 * (1.0 / rubyTextureSize.x);
float y = 0.5 * (1.0 / rubyTextureSize.y);
vec2 dg1 = vec2( x, y);
vec2 dg2 = vec2(-x, y);
vec2 dx = vec2(x, 0.0);
vec2 dy = vec2(0.0, y);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
}
]]></vertex>
<fragment filter="nearest"><![CDATA[
uniform sampler2D rubyTexture;
const float mx = 0.325; // start smoothing wt.
const float k = -0.250; // wt. decrease factor
const float max_w = 0.25; // max filter weigth
const float min_w =-0.05; // min filter weigth
const float lum_add = 0.25; // effects smoothing
void main() {
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
vec3 dt = vec3(1.0, 1.0, 1.0);
float md1 = dot(abs(c00 - c22), dt);
float md2 = dot(abs(c02 - c20), dt);
float w1 = dot(abs(c22 - c11), dt) * md2;
float w2 = dot(abs(c02 - c11), dt) * md1;
float w3 = dot(abs(c00 - c11), dt) * md2;
float w4 = dot(abs(c20 - c11), dt) * md1;
float t1 = w1 + w3;
float t2 = w2 + w4;
float ww = max(t1, t2) + 0.0001;
c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);
float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);
float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);
w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);
w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);
w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);
w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);
gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11;
}
]]></fragment>
</shader>

4
shaders/Makefile Normal file
View File

@ -0,0 +1,4 @@
install:
mkdir -p ~/.config/bsnes/shaders
chmod 777 ~/.config/bsnes/shaders
cp *.shader ~/.config/bsnes/shaders

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader language="GLSL">
<vertex><![CDATA[
void main() {
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
}
]]></vertex>
<fragment filter="nearest"><![CDATA[
uniform sampler2D rubyTexture;
uniform vec2 rubyTextureSize;
void main() {
vec2 texelSize = 1.0 / rubyTextureSize;
vec2 range;
range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99;
range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99;
float left = gl_TexCoord[0].x - range.x;
float top = gl_TexCoord[0].y + range.y;
float right = gl_TexCoord[0].x + range.x;
float bottom = gl_TexCoord[0].y - range.y;
vec4 topLeftColor = texture2D(rubyTexture, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize);
vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize);
vec4 bottomLeftColor = texture2D(rubyTexture, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize);
vec4 topRightColor = texture2D(rubyTexture, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize);
vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));
float totalArea = 4.0 * range.x * range.y;
vec4 averageColor;
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
gl_FragColor = averageColor;
}
]]></fragment>
</shader>

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader language="GLSL">
<vertex><![CDATA[
uniform vec2 rubyTextureSize;
void main() {
vec4 offsetx;
vec4 offsety;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
offsetx.x = 1.0 / rubyTextureSize.x;
offsetx.y = 0.0;
offsetx.w = 0.0;
offsetx.z = 0.0;
offsety.y = 1.0 / rubyTextureSize.y;
offsety.x = 0.0;
offsety.w = 0.0;
offsety.z = 0.0;
gl_TexCoord[0] = gl_MultiTexCoord0; //center
gl_TexCoord[1] = gl_TexCoord[0] - offsetx; //left
gl_TexCoord[2] = gl_TexCoord[0] + offsetx; //right
gl_TexCoord[3] = gl_TexCoord[0] - offsety; //top
gl_TexCoord[4] = gl_TexCoord[0] + offsety; //bottom
}
]]></vertex>
<fragment filter="nearest"><![CDATA[
uniform sampler2D rubyTexture;
uniform vec2 rubyTextureSize;
void main() {
vec4 colD, colF, colB, colH, col, tmp;
vec2 sel;
col = texture2DProj(rubyTexture, gl_TexCoord[0]); //central (can be E0-E3)
colD = texture2DProj(rubyTexture, gl_TexCoord[1]); //D (left)
colF = texture2DProj(rubyTexture, gl_TexCoord[2]); //F (right)
colB = texture2DProj(rubyTexture, gl_TexCoord[3]); //B (top)
colH = texture2DProj(rubyTexture, gl_TexCoord[4]); //H (bottom)
sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy); //where are we (E0-E3)? E0 is default
if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; } //E1 (or E3): swap B and H
if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; } //E2 (or E3): swap D and F
if(colB == colD && colB != colF && colD != colH) { //do the Scale2x rule
col = colD;
}
gl_FragColor = col;
}
]]></fragment>
</shader>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader language="HLSL">
<source><![CDATA[
texture rubyTexture;
float4 vec;
sampler s0 = sampler_state { texture = <rubyTexture>; };
float3 LightColor = { 1.0, 0.7, 0.5 };
float3 DarkColor = { 0.2, 0.05, 0.0 };
float4 DiffColorPass(in float2 Tex : TEXCOORD0) : COLOR0
{
vec.x = 0.5;
vec.y = 1.0;
float3 scnColor = LightColor * tex2D(s0, Tex).xyz;
float3 grayXfer = float3(0.3, 0.59, 0.11);
float gray = dot(grayXfer, scnColor);
float3 muted = lerp(scnColor, gray.xxx, vec.x);
float3 sepia = lerp(DarkColor, LightColor, gray);
float3 result = lerp(muted, sepia, vec.y);
return float4(result, 1);
}
Technique T0
{
pass p0 { PixelShader = compile ps_2_0 DiffColorPass(); }
}
]]></source>
</shader>