Merge branch 'shader_setup' into sdl-gpu_test
This commit is contained in:
commit
a46d0b5f1c
2
Makefile
2
Makefile
|
@ -249,7 +249,7 @@ bin/menu.o: src/menu.c $(TIC80_H) $(TIC_H)
|
|||
bin/surf.o: src/surf.c $(TIC80_H) $(TIC_H)
|
||||
$(CC) $< $(OPT) $(INCLUDES) -c -o $@
|
||||
|
||||
bin/system.o: src/system.c src/keycodes.c $(TIC80_H) $(TIC_H)
|
||||
bin/system.o: src/system.c src/keycodes.c src/ext/shader/* $(TIC80_H) $(TIC_H)
|
||||
$(CC) $< $(OPT) $(INCLUDES) -c -o $@
|
||||
|
||||
SDL_NET = \
|
||||
|
|
|
@ -4,12 +4,15 @@ precision highp float;
|
|||
|
||||
varying vec2 texCoord;
|
||||
uniform sampler2D source;
|
||||
uniform float trg_x;
|
||||
uniform float trg_y;
|
||||
uniform float trg_w;
|
||||
uniform float trg_h;
|
||||
uniform float scr_w;
|
||||
uniform float scr_h;
|
||||
|
||||
// Emulated input resolution.
|
||||
vec2 res=vec2(256.0,144.0);
|
||||
vec2 trg=vec2(trg_w, trg_h);
|
||||
|
||||
// Hardness of scanline.
|
||||
// -8.0 = soft
|
||||
|
@ -45,83 +48,86 @@ vec3 ToSrgb(vec3 c){return vec3(ToSrgb1(c.r),ToSrgb1(c.g),ToSrgb1(c.b));}
|
|||
// Nearest emulated sample given floating point position and texel offset.
|
||||
// Also zero's off screen.
|
||||
vec3 Fetch(vec2 pos,vec2 off){
|
||||
pos=(floor(pos*res+off)+vec2(0.5,0.5))/res;
|
||||
return ToLinear(1.2 * texture2D(source,pos.xy,-16.0).rgb);}
|
||||
pos=(floor(pos*res+off)+vec2(0.5,0.5))/res;
|
||||
return ToLinear(1.2 * texture2D(source,pos.xy,-16.0).rgb);}
|
||||
|
||||
// Distance in emulated pixels to nearest texel.
|
||||
vec2 Dist(vec2 pos){pos=pos*res;return -((pos-floor(pos))-vec2(0.5));}
|
||||
|
||||
|
||||
// 1D Gaussian.
|
||||
float Gaus(float pos,float scale){return exp2(scale*pos*pos);}
|
||||
|
||||
// 3-tap Gaussian filter along horz line.
|
||||
vec3 Horz3(vec2 pos,float off){
|
||||
vec3 b=Fetch(pos,vec2(-1.0,off));
|
||||
vec3 c=Fetch(pos,vec2( 0.0,off));
|
||||
vec3 d=Fetch(pos,vec2( 1.0,off));
|
||||
float dst=Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale=hardPix;
|
||||
float wb=Gaus(dst-1.0,scale);
|
||||
float wc=Gaus(dst+0.0,scale);
|
||||
float wd=Gaus(dst+1.0,scale);
|
||||
// Return filtered sample.
|
||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
|
||||
vec3 b=Fetch(pos,vec2(-1.0,off));
|
||||
vec3 c=Fetch(pos,vec2( 0.0,off));
|
||||
vec3 d=Fetch(pos,vec2( 1.0,off));
|
||||
float dst=Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale=hardPix;
|
||||
float wb=Gaus(dst-1.0,scale);
|
||||
float wc=Gaus(dst+0.0,scale);
|
||||
float wd=Gaus(dst+1.0,scale);
|
||||
// Return filtered sample.
|
||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);}
|
||||
|
||||
// 5-tap Gaussian filter along horz line.
|
||||
vec3 Horz5(vec2 pos,float off){
|
||||
vec3 a=Fetch(pos,vec2(-2.0,off));
|
||||
vec3 b=Fetch(pos,vec2(-1.0,off));
|
||||
vec3 c=Fetch(pos,vec2( 0.0,off));
|
||||
vec3 d=Fetch(pos,vec2( 1.0,off));
|
||||
vec3 e=Fetch(pos,vec2( 2.0,off));
|
||||
float dst=Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale=hardPix;
|
||||
float wa=Gaus(dst-2.0,scale);
|
||||
float wb=Gaus(dst-1.0,scale);
|
||||
float wc=Gaus(dst+0.0,scale);
|
||||
float wd=Gaus(dst+1.0,scale);
|
||||
float we=Gaus(dst+2.0,scale);
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
|
||||
vec3 a=Fetch(pos,vec2(-2.0,off));
|
||||
vec3 b=Fetch(pos,vec2(-1.0,off));
|
||||
vec3 c=Fetch(pos,vec2( 0.0,off));
|
||||
vec3 d=Fetch(pos,vec2( 1.0,off));
|
||||
vec3 e=Fetch(pos,vec2( 2.0,off));
|
||||
float dst=Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale=hardPix;
|
||||
float wa=Gaus(dst-2.0,scale);
|
||||
float wb=Gaus(dst-1.0,scale);
|
||||
float wc=Gaus(dst+0.0,scale);
|
||||
float wd=Gaus(dst+1.0,scale);
|
||||
float we=Gaus(dst+2.0,scale);
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);}
|
||||
|
||||
// Return scanline weight.
|
||||
float Scan(vec2 pos,float off){
|
||||
float dst=Dist(pos).y;
|
||||
return Gaus(dst+off,hardScan);}
|
||||
float dst=Dist(pos).y;
|
||||
return Gaus(dst+off,hardScan);}
|
||||
|
||||
// Allow nearest three lines to effect pixel.
|
||||
vec3 Tri(vec2 pos){
|
||||
vec3 a=Horz3(pos,-1.0);
|
||||
vec3 b=Horz5(pos, 0.0);
|
||||
vec3 c=Horz3(pos, 1.0);
|
||||
float wa=Scan(pos,-1.0);
|
||||
float wb=Scan(pos, 0.0);
|
||||
float wc=Scan(pos, 1.0);
|
||||
return a*wa+b*wb+c*wc;}
|
||||
vec3 a=Horz3(pos,-1.0);
|
||||
vec3 b=Horz5(pos, 0.0);
|
||||
vec3 c=Horz3(pos, 1.0);
|
||||
float wa=Scan(pos,-1.0);
|
||||
float wb=Scan(pos, 0.0);
|
||||
float wc=Scan(pos, 1.0);
|
||||
return a*wa+b*wb+c*wc;}
|
||||
|
||||
// Distortion of scanlines, and end of screen alpha.
|
||||
vec2 Warp(vec2 pos){
|
||||
pos=pos*2.0-1.0;
|
||||
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
|
||||
return pos*0.5+0.5;}
|
||||
pos=pos*2.0-1.0;
|
||||
pos*=vec2(1.0+(pos.y*pos.y)*warp.x,1.0+(pos.x*pos.x)*warp.y);
|
||||
return pos*0.5+0.5;}
|
||||
|
||||
// Shadow mask.
|
||||
vec3 Mask(vec2 pos){
|
||||
pos.x+=pos.y*3.0;
|
||||
vec3 mask=vec3(maskDark,maskDark,maskDark);
|
||||
pos.x=fract(pos.x/6.0);
|
||||
if(pos.x<0.333)mask.r=maskLight;
|
||||
else if(pos.x<0.666)mask.g=maskLight;
|
||||
else mask.b=maskLight;
|
||||
return mask;}
|
||||
pos.x+=pos.y*3.0;
|
||||
vec3 mask=vec3(maskDark,maskDark,maskDark);
|
||||
pos.x=fract(pos.x/6.0);
|
||||
if(pos.x<0.333)mask.r=maskLight;
|
||||
else if(pos.x<0.666)mask.g=maskLight;
|
||||
else mask.b=maskLight;
|
||||
return mask;}
|
||||
|
||||
void main() {
|
||||
vec2 pos = gl_FragCoord.xy/trg.xy;
|
||||
hardScan=-12.0;
|
||||
// maskDark=maskLight;
|
||||
pos=Warp(gl_FragCoord.xy/trg.xy);
|
||||
gl_FragColor.rgb=Tri(vec2(pos.s, 1.0 - pos.t))*Mask(gl_FragCoord.xy);
|
||||
gl_FragColor = vec4(ToSrgb(gl_FragColor.rgb), 1.0);
|
||||
hardScan=-12.0;
|
||||
// maskDark=maskLight;
|
||||
vec2 start=gl_FragCoord.xy-vec2(trg_x, trg_y);
|
||||
start.y=scr_h-start.y;
|
||||
|
||||
vec2 pos=Warp(start/vec2(trg_w, trg_h));
|
||||
|
||||
gl_FragColor.rgb=Tri(pos)*Mask(gl_FragCoord.xy);
|
||||
gl_FragColor = vec4(ToSrgb(gl_FragColor.rgb), 1.0);
|
||||
})
|
128
src/system.c
128
src/system.c
|
@ -23,6 +23,8 @@ static struct
|
|||
{
|
||||
Studio* studio;
|
||||
|
||||
bool useShader;
|
||||
|
||||
SDL_Window* window;
|
||||
SDL_Renderer* renderer;
|
||||
SDL_Texture* texture;
|
||||
|
@ -213,45 +215,60 @@ static void initTouchGamepad()
|
|||
}
|
||||
|
||||
static void calcTextureRect(SDL_Rect* rect)
|
||||
{
|
||||
s32 w, h;
|
||||
SDL_GetWindowSize(platform.window, &w, &h);
|
||||
|
||||
rect->x = OFFSET_LEFT * w / TIC80_FULLWIDTH;
|
||||
rect->y = OFFSET_TOP * h / TIC80_FULLHEIGHT;
|
||||
rect->w = TIC80_WIDTH * w / TIC80_FULLWIDTH;
|
||||
rect->h = TIC80_HEIGHT * h / TIC80_FULLHEIGHT;
|
||||
}
|
||||
|
||||
static void calcTextureRect2(SDL_Rect* rect)
|
||||
{
|
||||
SDL_GetWindowSize(platform.window, &rect->w, &rect->h);
|
||||
|
||||
if (rect->w * TIC80_HEIGHT < rect->h * TIC80_WIDTH)
|
||||
if(platform.useShader)
|
||||
{
|
||||
s32 discreteWidth = rect->w - rect->w % TIC80_WIDTH;
|
||||
s32 discreteHeight = TIC80_HEIGHT * discreteWidth / TIC80_WIDTH;
|
||||
enum{Width = TIC80_FULLWIDTH, Height = TIC80_FULLHEIGHT};
|
||||
|
||||
rect->x = (rect->w - discreteWidth) / 2;
|
||||
if (rect->w * Height < rect->h * Width)
|
||||
{
|
||||
rect->x = 0;
|
||||
rect->y = 0;
|
||||
|
||||
rect->y = rect->w > rect->h
|
||||
? (rect->h - discreteHeight) / 2
|
||||
: OFFSET_LEFT*discreteWidth/TIC80_WIDTH;
|
||||
rect->h = Height * rect->w / Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 width = Width * rect->h / Height;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
rect->x = (rect->w - width) / 2;
|
||||
rect->y = 0;
|
||||
|
||||
rect->w = width;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 discreteHeight = rect->h - rect->h % TIC80_HEIGHT;
|
||||
s32 discreteWidth = TIC80_WIDTH * discreteHeight / TIC80_HEIGHT;
|
||||
enum{Width = TIC80_WIDTH, Height = TIC80_HEIGHT};
|
||||
|
||||
rect->x = (rect->w - discreteWidth) / 2;
|
||||
rect->y = (rect->h - discreteHeight) / 2;
|
||||
if (rect->w * Height < rect->h * Width)
|
||||
{
|
||||
s32 discreteWidth = rect->w - rect->w % Width;
|
||||
s32 discreteHeight = Height * discreteWidth / Width;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
rect->x = (rect->w - discreteWidth) / 2;
|
||||
|
||||
rect->y = rect->w > rect->h
|
||||
? (rect->h - discreteHeight) / 2
|
||||
: OFFSET_TOP*discreteWidth/Width;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
s32 discreteHeight = rect->h - rect->h % Height;
|
||||
s32 discreteWidth = Width * discreteHeight / Height;
|
||||
|
||||
rect->x = (rect->w - discreteWidth) / 2;
|
||||
rect->y = (rect->h - discreteHeight) / 2;
|
||||
|
||||
rect->w = discreteWidth;
|
||||
rect->h = discreteHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,8 +285,16 @@ static void processMouse()
|
|||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
|
||||
if(rect.w) input->mouse.x = (mx - rect.x) * TIC80_WIDTH / rect.w;
|
||||
if(rect.h) input->mouse.y = (my - rect.y) * TIC80_HEIGHT / rect.h;
|
||||
if(platform.useShader)
|
||||
{
|
||||
if(rect.w) input->mouse.x = (mx - rect.x) * TIC80_FULLWIDTH / rect.w - OFFSET_LEFT;
|
||||
if(rect.h) input->mouse.y = (my - rect.y) * TIC80_FULLHEIGHT / rect.h - OFFSET_TOP;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rect.w) input->mouse.x = (mx - rect.x) * TIC80_WIDTH / rect.w;
|
||||
if(rect.h) input->mouse.y = (my - rect.y) * TIC80_HEIGHT / rect.h;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -659,6 +684,14 @@ static void blitTexture()
|
|||
}
|
||||
}
|
||||
|
||||
// static void blitGpuTexture(GPU_Target* screen, GPU_Image* texture)
|
||||
// {
|
||||
// SDL_Rect rect = {0, 0, 0, 0};
|
||||
// calcTextureRect(&rect);
|
||||
|
||||
// GPU_BlitScale(texture, NULL, platform.gpu.screen, rect.x, rect.y, (float)rect.w / TIC80_FULLWIDTH, (float)rect.h / TIC80_FULLHEIGHT);
|
||||
// }
|
||||
|
||||
static void blitGpuTexture(GPU_Target* screen, GPU_Image* texture)
|
||||
{
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
|
@ -1057,13 +1090,31 @@ static void gpuTick()
|
|||
GPU_UpdateImageBytes(platform.gpu.texture, NULL, (const u8*)tic->screen, TIC80_FULLWIDTH * sizeof(u32));
|
||||
|
||||
{
|
||||
s32 w, h;
|
||||
SDL_GetWindowSize(platform.window, &w, &h);
|
||||
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_w"), w);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_h"), h);
|
||||
if(platform.useShader)
|
||||
{
|
||||
SDL_Rect rect = {0, 0, 0, 0};
|
||||
calcTextureRect(&rect);
|
||||
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_x"), rect.x);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_y"), rect.y);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_w"), rect.w);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "trg_h"), rect.h);
|
||||
|
||||
{
|
||||
s32 w, h;
|
||||
SDL_GetWindowSize(platform.window, &w, &h);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "scr_w"), w);
|
||||
GPU_SetUniformf(GPU_GetUniformLocation(platform.gpu.crt_shader, "scr_h"), h);
|
||||
}
|
||||
|
||||
GPU_BlitScale(platform.gpu.texture, NULL, platform.gpu.screen, rect.x, rect.y, (float)rect.w / TIC80_FULLWIDTH, (float)rect.h / TIC80_FULLHEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
blitGpuTexture(platform.gpu.screen, platform.gpu.texture);
|
||||
}
|
||||
|
||||
GPU_BlitScale(platform.gpu.texture, NULL, platform.gpu.screen, 0, 0, (float)w / TIC80_FULLWIDTH, (float)h / TIC80_FULLHEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1124,13 +1175,11 @@ static void emsGpuTick()
|
|||
|
||||
u32 load_shader_program()
|
||||
{
|
||||
Uint32 v, f;
|
||||
|
||||
static const char* VertexShader =
|
||||
#include "ext/shader/common.vert"
|
||||
;
|
||||
|
||||
v = GPU_CompileShader(GPU_VERTEX_SHADER, VertexShader);
|
||||
u32 v = GPU_CompileShader(GPU_VERTEX_SHADER, VertexShader);
|
||||
|
||||
if(!v)
|
||||
GPU_LogError("Failed to load vertex shader: %s\n", GPU_GetShaderMessage());
|
||||
|
@ -1139,7 +1188,7 @@ u32 load_shader_program()
|
|||
#include "ext/shader/crt-lottes.frag"
|
||||
;
|
||||
|
||||
f = GPU_CompileShader(GPU_PIXEL_SHADER, PixelShader);
|
||||
u32 f = GPU_CompileShader(GPU_PIXEL_SHADER, PixelShader);
|
||||
|
||||
if(!f)
|
||||
GPU_LogError("Failed to load fragment shader: %s\n", GPU_GetShaderMessage());
|
||||
|
@ -1189,7 +1238,10 @@ static s32 start(s32 argc, char **argv, const char* folder)
|
|||
GPU_SetAnchor(platform.gpu.texture, 0, 0);
|
||||
GPU_SetImageFilter(platform.gpu.texture, GPU_FILTER_NEAREST);
|
||||
|
||||
platform.gpu.crt_shader = load_shader_program();
|
||||
platform.useShader = true;
|
||||
|
||||
if(platform.useShader)
|
||||
platform.gpu.crt_shader = load_shader_program();
|
||||
|
||||
#if defined(__EMSCRIPTEN__)
|
||||
|
||||
|
|
Loading…
Reference in New Issue