PSLLQ ! because why not go for 64 while you're at it...byuu wrote:Please. What self-respecting programmer hasn't memorized up to at least 2^20 in their head? :)way less intimidating
Invaluable for those bit-shift operations ...
The unofficial BSNES pixel shader thread
-
- ZSNES Shake Shake Prinny
- Posts: 5632
- Joined: Wed Jul 28, 2004 4:15 pm
- Location: PAL50, dood !
皆黙って俺について来い!!
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
Code: Select all
<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
I just remember being really excited when I was in middle school replaying the original Dragon Warrior and suddenly understood why the limits for gold and exp were 65535...grinvader wrote:PSLLQ ! because why not go for 64 while you're at it...byuu wrote:Please. What self-respecting programmer hasn't memorized up to at least 2^20 in their head?way less intimidating
Invaluable for those bit-shift operations ...
Why yes, my shift key *IS* broken.
-
- Seen it all
- Posts: 2302
- Joined: Mon Jan 03, 2005 5:04 pm
- Location: Germany
- Contact:
I wrote it like that at first, but someone might read it as 64 KB.grinvader wrote:64kcreaothceann wrote:2^16
way less intimidating
vSNES | Delphi 10 BPLs
bsnes launcher with recent files list
bsnes launcher with recent files list
Thanks. Though that was a little test to see how the rendering code worked (you can see how I messed up the tex coords in the sample though ) . And it now works fine. Thanks again VG.mudlord I like what you have done with mario and a cube!
Hmmmz, true. Although, it works fine enough though at the moment (though I have a C2D 4500, so speed isn't really a problem. My only concern is the pressure my emulator will put on the video card in older PCs, since it uses dynamic plasma effects, wave/water effects and other things that involve changing textures every single frame. And it all does this without shaders. But we will see when I release it.)You could use a buffer of 2^16 items to store the final 24-bit values.
Dude, there is a bug in your code. I fixed it:I upgraded ubuntu to 8.04 and tried running my bsnes opengl 2.0 driver with visual effects set to normal and extra, and it did not work, It just showed me a white screen!
Code: Select all
glCreateProgram = (PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram");
glUseProgram = (PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram");
glCreateShader = (PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader");
glAttachShader = (PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader");
glLinkProgram = (PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram");
glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation");
glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
// Create our fragment shader...
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
FILE *fp = fopen("shader.frag", "rb");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buffer = new char[size + 1];
fread(buffer, 1, size, fp);
buffer[size] = 0;
fclose(fp);
const char *fbuffer = buffer;
glShaderSource(fragmentshader, 1, &fbuffer, 0);
glCompileShader(fragmentshader);
delete[] buffer;
// Create a program object and attach our compiled fragment shader to it...
program = glCreateProgram();
glAttachShader(program, fragmentshader);
// Link the program object...
glLinkProgram(program);
// Locate some parameters by name so we can set them later...
glGetUniformLocation(program, "texture");
Thats the fixed version. Works for me in my MuNES. Thanks again for porting my pixel shaders!
Bug in my bsnes shader code
Cheers man, I have updated my sources =DDude, there is a bug in your code. I fixed it
No probs!Works for me in my MuNES. Thanks again for porting my pixel shaders!
Code: Select all
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
void initShader(char *filename, char* filename2) {
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
// Create our fragment shader...
fragmentshader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
vertexshader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
//for the frag shader
FILE *fp = fopen(filename, "rb");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buffer = new char[size + 1];
fread(buffer, 1, size, fp);
buffer[size] = 0;
fclose(fp);
const char *fbuffer = buffer;
glShaderSourceARB(fragmentshader, 1, &fbuffer, 0);
glCompileShaderARB(fragmentshader);
delete[] buffer;
//for the vertex shader
FILE *fp2 = fopen(filename2, "rb");
fseek(fp2, 0, SEEK_END);
int size2 = ftell(fp2);
fseek(fp2, 0, SEEK_SET);
char *buffer2 = new char[size2 + 1];
fread(buffer2, 1, size2, fp2);
buffer2[size2] = 0;
fclose(fp2);
const char *vbuffer = buffer2;
glShaderSourceARB(vertexshader, 1, &vbuffer, 0);
glCompileShaderARB(vertexshader);
delete[] buffer2;
// Create a program object and attach our compiled fragment shader to it...
program = glCreateProgramObjectARB();
glAttachObjectARB(program, fragmentshader);
glAttachObjectARB(program, vertexshader);
// Link the program object...
glLinkProgramARB(program);
// Locate some parameters by name so we can set them later...
glGetUniformLocationARB(program, "texture");
}
Code: Select all
if (useShaders == 1)
glUseProgramObjectARB(program);
*render textured quad here*
if (useShaders == 1)
glUseProgramObjectARB(NULL);
-
- ZNES Developer
- Posts: 215
- Joined: Mon Aug 02, 2004 11:22 pm
During my previous efforts with cubic kernels I realised that the methods were probably overkill for the kind of images they would be subjected to, rather, I opted to construct a quadratic kernel with a small radius, one that requires 4 texture fetches, making it readily PS v2.0 compliant. It was constructed with sharpness in mind, so everyone that enjoys the pixelated look, but can't cope with the artifacts of non-uniform box filtering, rejoice.
At the time the shader ignores any extra information provided by the pseudo-hires modes (it only maps to a 256x224 or 256x239 texture), figures for the highest resolution modes in NTSC and PAL are welcome, so that I may implement this later.
Pixel shader: Quadratic interpolation.
v0.1 - Release
v0.11 - Fixed resolution detection.
NOT tested with any hardware besides mine.
Usage:
Patch bsnes and copy/paste the following code into a "shader.fx" file inside the main folder.
Launch bsnes and make sure to check "Point" and "None" in the "Filter" menu.
Test and provide feedback.
Examples:
1x with NTSC aspect ratio compensation:
3x with NTSC aspect ratio compensation:
Source:
At the time the shader ignores any extra information provided by the pseudo-hires modes (it only maps to a 256x224 or 256x239 texture), figures for the highest resolution modes in NTSC and PAL are welcome, so that I may implement this later.
Pixel shader: Quadratic interpolation.
v0.1 - Release
v0.11 - Fixed resolution detection.
NOT tested with any hardware besides mine.
Usage:
Patch bsnes and copy/paste the following code into a "shader.fx" file inside the main folder.
Launch bsnes and make sure to check "Point" and "None" in the "Filter" menu.
Test and provide feedback.
Examples:
1x with NTSC aspect ratio compensation:
3x with NTSC aspect ratio compensation:
Source:
Code: Select all
/* Quadratic Resampler v0.11
* By DOLLS
* Do not distribute a modified version without permission.
*/
texture tex1, tex2;
float2 rcpres;
sampler s0 = sampler_state {
texture = <tex1>;
AddressU = mirror;
AddressV = mirror;
};
sampler s1 = sampler_state {
texture = <tex2>;
AddressU = mirror;
AddressV = mirror;
};
int2 res;
float4 Normalize(in float2 coord : TEXCOORD0): COLOR0
{
res = int2(256, (frac(1 / (224 * rcpres.y)) < 0.05)? 224 : 239);
float2 loc = coord * float2(rcpres.y * res.y / (rcpres.x * res.x), 1.0) / (res.y * rcpres.y);
return tex2D(s0, loc);
}
float pow2(float x)
{
return x * x;
}
float getWeight(float x)
{
if (x == 0.0) return 1.0;
else if (x < 0.5) return 1 - 2 * pow2(x);
else if (x < 1.0) return 2 * pow2(1 - x);
else return 0.0;
}
float4 Resample(in float2 coord : TEXCOORD0) : COLOR0
{
res = int2(256, (frac(1 / (224 * rcpres.y)) < 0.05)? 224 : 239);
float2 pos = coord * res - 0.5;
float2 tex = (floor(pos) + 0.5) * rcpres;
float2 next_tex = tex + rcpres;
float2 delta = frac(pos);
float2 w0 = float2(getWeight(delta.x), getWeight(delta.y));
float2 w1 = float2(getWeight(1 - delta.x), getWeight(1 - delta.y));
float4 value = w0.x * w0.y * tex2D(s1, tex);
value += w1.x * w0.y * tex2D(s1, float2(next_tex.x, tex.y));
value += w0.x * w1.y * tex2D(s1, float2(tex.x, next_tex.y));
value += w1.x * w1.y * tex2D(s1, next_tex);
return value;
}
Technique T0
{
pass p0 {
PixelShader = compile ps_2_0 Normalize();
}
pass p1 {
PixelShader = compile ps_2_0 Resample();
}
}
-
- ZNES Developer
- Posts: 215
- Joined: Mon Aug 02, 2004 11:22 pm
mudlord: Sure, go ahead!
New shaders:
Cubic spline & Lanczos2 based resamplers, normal & gamma corrected, gamma corrected variation of the Quadratic resampler added as well.
Lanczos3 (the common one) was avoided as it introduces unnecessary ringing artifacts, it's better suited for captured media (photo, video).
If your display operates in sRGB color space (gamma 2.2 calibrated), you might want to check out the gamma corrected variations of the shaders ("_sRGB" appended in the filename, remove that part).
PS v2.0a required.
Download link:
http://www.megaupload.com/?d=MDEU3IYZ
(Sorry, my FTP is currently offline)
New shaders:
Cubic spline & Lanczos2 based resamplers, normal & gamma corrected, gamma corrected variation of the Quadratic resampler added as well.
Lanczos3 (the common one) was avoided as it introduces unnecessary ringing artifacts, it's better suited for captured media (photo, video).
If your display operates in sRGB color space (gamma 2.2 calibrated), you might want to check out the gamma corrected variations of the shaders ("_sRGB" appended in the filename, remove that part).
PS v2.0a required.
Download link:
http://www.megaupload.com/?d=MDEU3IYZ
(Sorry, my FTP is currently offline)
I'm still requesting this information.DOLLS wrote:At the time the shader ignores any extra information provided by the pseudo-hires modes (it only maps to a 256x224 or 256x239 texture), figures for the highest resolution modes in NTSC and PAL are welcome, so that I may implement this later.
Cheers mudlord
Sorry for the late reply mudlord,krom, found some more issues with your code using glIntercept. I will post some patched code ASAP. IIRC, ATI cards need vertex shaders, as well as fragment shaders, for some retarded reason. As such, I will be posting some code that should add vertex shader support, too.
Thanks a lot for the new code, I have updated my sources and I am very appreciative of your help =D
btw how is the nes emu going?
No probs!Sorry for the late reply mudlord,
Thanks a lot for the new code, I have updated my sources and I am very appreciative of your help =D
btw how is the nes emu going?
And its going excellent. I need to replace SDL as a sound server, though I have very little experience with DirectSound or WinMM. If anyone can help, I would be so grateful.
All I need is some code that
* has a init function that sets the samplerate
* a closing function that is a void()
* a writing function that has a parameter, that sets the amount of samples processed, as well as a parameter that contains the raw audio data.
Currently my code is based of Sound_Queue by blargg, so that should give ideas in how to do the WinMM/DSound sound server. (I know byuu was wanting to do something for me...maybe this can be it).
All of that is in src/lib/ruby/audio/directsound.cpp :D
Only 5kb in size.
Init:
Term:
Write:
Link with -ldsound or dsound.lib.
I'll be happy to go over any section that is unclear in detail, if you like.
You're free to use all of src/lib directly as public domain, as well.
Only 5kb in size.
Init:
Code: Select all
DirectSoundCreate(0, &ds, 0);
ds->SetCooperativeLevel((HWND)settings.handle, DSSCL_PRIORITY);
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = 0;
ds->CreateSoundBuffer(&dsbd, &dsb_p, 0);
memset(&wfx, 0, sizeof(wfx));
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = settings.frequency;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
dsb_p->SetFormat(&wfx);
memset(&dsbd, 0, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY |
DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCSOFTWARE;
dsbd.dwBufferBytes = data.ring_size * 3;
dsbd.guid3DAlgorithm = GUID_NULL;
dsbd.lpwfxFormat = &wfx;
ds->CreateSoundBuffer(&dsbd, &dsb_b, 0);
dsb_b->SetFrequency(settings.frequency);
dsb_b->SetCurrentPosition(0);
Code: Select all
if(dsb_b) { dsb_b->Stop(); dsb_b->Release(); dsb_b = 0; }
if(dsb_p) { dsb_p->Stop(); dsb_p->Release(); dsb_p = 0; }
if(ds) { ds->Release(); ds = 0; }
Code: Select all
data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16);
if(data.buffer_pos < settings.frequency / 40) return;
DWORD ring_pos, pos, size;
for(;;) {
dsb_b->GetCurrentPosition(&pos, 0);
ring_pos = pos / data.ring_size;
if(settings.synchronize == false || ring_pos != data.ring_pos) break;
Sleep(1);
}
data.ring_pos = ring_pos;
void *output;
if(dsb_b->Lock(((data.ring_pos + 2) % 3) * data.ring_size, data.ring_size,
&output, &size, 0, 0, 0) == DS_OK) {
memcpy(output, data.buffer, data.ring_size);
dsb_b->Unlock(output, size, 0, 0);
}
data.buffer_pos = 0;
I'll be happy to go over any section that is unclear in detail, if you like.
You're free to use all of src/lib directly as public domain, as well.
Strange, tried out the code, failed to work.
Not a single bit of sound, apart from a close to inaudible buzz.
Here's the main callback function for sound if you are interested.....
I changed the "sample" function of your class, to make "temp" write to it, unfortunately it done nothing...
sync_audio_write() was the SDL related function that I was talking about before...
Not a single bit of sound, apart from a close to inaudible buzz.
Here's the main callback function for sound if you are interested.....
Code: Select all
void NESCore_Callback_OutputSample(int nSamples, byte *channel1, byte *channel2,
byte *channel3, byte *channel4, byte *channel5)
{
short temp [1024];
int i;
for ( i = 0; i < nSamples; i++ )
temp [i] = (channel1 [i] + channel2 [i] + channel3 [i] + channel4 [i] + channel5 [i]) * 32;
// sync_audio_write( temp, nSamples );
sample((int16_t)temp);
}
sync_audio_write() was the SDL related function that I was talking about before...
Hheehehe, found a workaround to the problem.
Instead of adding DirectSound, I completely regutted SDL.
Everything not relating to threads, mutexes, or raw DirectSound audio has been completely stripped. Result? Managed to shrink the entire library from a mammoth ~150KB to a petite 24.5KB. Which is perfect for what I am using it for.
Instead of adding DirectSound, I completely regutted SDL.
Everything not relating to threads, mutexes, or raw DirectSound audio has been completely stripped. Result? Managed to shrink the entire library from a mammoth ~150KB to a petite 24.5KB. Which is perfect for what I am using it for.
Ah, I believe someone else did that with one of the driver classes ... I want to say it was input related, but i can't be sure. You guys are truly brave to gut such a massive program like that, heh.mudlord wrote:Hheehehe, found a workaround to the problem.
Instead of adding DirectSound, I completely regutted SDL.
Everything not relating to threads, mutexes, or raw DirectSound audio has been completely stripped. Result? Managed to shrink the entire library from a mammoth ~150KB to a petite 24.5KB. Which is perfect for what I am using it for. :lol:
Anyway, sounds neat! If you change your mind, let me know. I'd need you to send me your source code, though, so I can get it working on my side. That, or perhaps I could make the DSound lib into its own app with nothing else in the way that just plays a quick WAV file or something using an API similar to yours.
I dare say raw DSound is a bit better (love the ability to query the play cursor position), but it hinders portability, so your single API solution is probably best.
That would be so cool Even a sample showing a sine wave will be enough, since we are dealing with raw audio data.That, or perhaps I could make the DSound lib into its own app with nothing else in the way that just plays a quick WAV file or something using an API similar to yours.
I admit, I am kinda very ashamed to show you my GUI/IO source code. It is super messy, with some global variables, as well as using the Windows message pump to process core events, instead of using a seperate thread (OpenGL is extremely picky on which threads rendering contexts are made), though I do plan on fixing that.
Though, the emu does run extremely fast on a 1.3 Celeron M. The render code is quite weird too, since I do plan on adding some extra rendering features at a later date....
Here's one that outputs static at 22khz / 16-bit stereo. You can easily change things via audio.settings.frequency, audio.settings.synchronize, etc before-hand.mudlord wrote:That would be so cool :) Even a sample showing a sine wave will be enough, since we are dealing with raw audio data.
To set it up, you call audio.init(), write samples with audio.sample(left, right), and finish with audio.term().
Compile with kernel32.lib, user32.lib, dsound.lib and uuid.lib.
Binary and source included. My example has synchronization on, meaning it will put the process to sleep when too much data is in the sound buffer. It's a purely sync-to-audio setup, the same as with bsnes. Hopefully that's appropriate for MuNES, because I don't know how to do it any other way.
http://www.geocities.com/byuu64/directsound.zip
Eh, it looks pretty good to me. Not 100% abstracted, but so long as it's Windows-only, that's not really a problem.It is super messy, with some global variables, as well as using the Windows message pump to process core events, instead of using a seperate thread
I do wish you'd drop VC6, though. That compiler is evil :P
Thank you! Much appreciated!Here's one that outputs static at 22khz / 16-bit stereo. You can easily change things via audio.settings.frequency, audio.settings.synchronize, etc before-hand.
To set it up, you call audio.init(), write samples with audio.sample(left, right), and finish with audio.term().
Compile with kernel32.lib, user32.lib, dsound.lib and uuid.lib.
MuNES without SDL.dll as dependancy:
http://vba-m.ngemu.com/munes_vc6.rar
Thanks, I honestly think though some parts can still be improved. Its quite hackish. Though, it does the job :/Eh, it looks pretty good to me. Not 100% abstracted, but so long as it's Windows-only, that's not really a problem.
I do wish you'd drop VC6, though. That compiler is evil
I agree though about VC6, but I want to be assured that it runs with as little dependancies as possible. MSVCR71.DLL aint a option, if thats what your implying. I am trying my hardest to keep around 64KB and no over...or in the event of that, 96KB.
*curses VC6 over its DWORD_PTR support*
Hi guys
Is anyone willing/able to turn this into a shader filter?
NTSC tv phosphor simulation filter
Image is scaled(without filters) to 4800*2700
In each pixel color data is deleted so only 1 color remains
The deletion works as follows:
(width*height)
10*45 black pixels(all color data is dropped)
10*45 red pixles (blue and green are dropped)
10*45 black pixels(all color data is dropped)
10*45 green pixels(Red and blue are dropped)
10*45 black pixels(all color data is dropped)
10*45 blue pixels(red and green are dropped)
Each 10*45 block is averaged into a single color
The 6 10*45 blocks are mixed into a new single color
The single color 60*45 block is scaled down to 1 pixel
The result is a single 800*600 image which can then be displayed on screen
This image will be an accurate representation of a basic NTSC tv's phosphor map. However due to the lack of whiter than white's the image will look overly dark.
Without a working filter there is no way to see how much gamma correction is needed to fix this.
I bet this whole calculation could be simplified into a single line of code by someone good with math
Is anyone willing/able to turn this into a shader filter?
NTSC tv phosphor simulation filter
Image is scaled(without filters) to 4800*2700
In each pixel color data is deleted so only 1 color remains
The deletion works as follows:
(width*height)
10*45 black pixels(all color data is dropped)
10*45 red pixles (blue and green are dropped)
10*45 black pixels(all color data is dropped)
10*45 green pixels(Red and blue are dropped)
10*45 black pixels(all color data is dropped)
10*45 blue pixels(red and green are dropped)
Each 10*45 block is averaged into a single color
The 6 10*45 blocks are mixed into a new single color
The single color 60*45 block is scaled down to 1 pixel
The result is a single 800*600 image which can then be displayed on screen
This image will be an accurate representation of a basic NTSC tv's phosphor map. However due to the lack of whiter than white's the image will look overly dark.
Without a working filter there is no way to see how much gamma correction is needed to fix this.
I bet this whole calculation could be simplified into a single line of code by someone good with math
-
- Regular
- Posts: 347
- Joined: Tue Mar 07, 2006 10:32 am
- Location: The Netherlands
Because of the way shaders work, we cannot resize the input to a 4800*2700 image before processing (at least in the current implementation). We get a 1024x1024 image from bsnes of which only a part is in use (i.e. 256x224 for unfiltered low-res NTSC), and we output to whatever scale factor you have bsnes set to.
Anyway, that doesn't mean your idea won't work just fine, just not in the way you presented it
Anyway, that doesn't mean your idea won't work just fine, just not in the way you presented it