diff --git a/data/shaders/alpha_mask.frag b/data/shaders/alpha_mask.frag new file mode 100644 index 0000000..d8fc3a2 --- /dev/null +++ b/data/shaders/alpha_mask.frag @@ -0,0 +1,22 @@ + +in vec4 color; +in vec2 texCoord; +out vec4 fragColor; + +uniform sampler2D tex; +uniform sampler2D mask_tex; + +uniform float offset_x; +uniform float offset_y; +uniform float resolution_x; +uniform float resolution_y; +uniform float mask_resolution_x; +uniform float mask_resolution_y; + +void main(void) +{ + vec4 col = texture2D(tex, texCoord); + vec2 mask_coords = vec2((texCoord.x*resolution_x + offset_x)/mask_resolution_x, (texCoord.y*resolution_y + offset_y)/mask_resolution_y); + vec4 mask = texture2D(mask_tex, mask_coords); + fragColor = vec4(col.rgb, col.a*mask.a); +} \ No newline at end of file diff --git a/data/shaders/color.frag b/data/shaders/color.frag new file mode 100644 index 0000000..d6b589f --- /dev/null +++ b/data/shaders/color.frag @@ -0,0 +1,11 @@ +varying vec4 color; +varying vec2 texCoord; + +uniform sampler2D tex; +uniform vec4 myColor; + +void main(void) +{ + vec4 c = myColor * color; + gl_FragColor = texture2D(tex, texCoord) * c; +} \ No newline at end of file diff --git a/data/shaders/common.frag b/data/shaders/common.frag new file mode 100644 index 0000000..289cb44 --- /dev/null +++ b/data/shaders/common.frag @@ -0,0 +1,11 @@ + +in vec4 color; +in vec2 texCoord; +out vec4 fragColor; + +uniform sampler2D tex; + +void main(void) +{ + fragColor = texture2D(tex, texCoord) * color; +} \ No newline at end of file diff --git a/data/shaders/common.vert b/data/shaders/common.vert new file mode 100644 index 0000000..8fcb0f0 --- /dev/null +++ b/data/shaders/common.vert @@ -0,0 +1,14 @@ +attribute vec3 gpu_Vertex; +attribute vec2 gpu_TexCoord; +attribute vec4 gpu_Color; +uniform mat4 gpu_ModelViewProjectionMatrix; + +varying vec4 color; +varying vec2 texCoord; + +void main(void) +{ + color = gpu_Color; + texCoord = vec2(gpu_TexCoord); + gl_Position = gpu_ModelViewProjectionMatrix * vec4(gpu_Vertex, 1.0); +} \ No newline at end of file diff --git a/data/shaders/marching_ants.frag b/data/shaders/marching_ants.frag new file mode 100644 index 0000000..d36186c --- /dev/null +++ b/data/shaders/marching_ants.frag @@ -0,0 +1,51 @@ + +in vec4 color; +in vec2 texCoord; +out vec4 fragColor; + +uniform sampler2D tex; + +uniform float resolution_x; +uniform float resolution_y; + +uniform float screen_w; +uniform float screen_h; + +uniform float time; +uniform float zoom; + +void main(void) +{ + float x_offset = 1.0/(screen_w*zoom) + 1.0/(resolution_x*zoom); + float y_offset = 1.0/(screen_h*zoom) + 1.0/(resolution_y*zoom); + + vec4 center = texture2D(tex, texCoord); + vec4 left = texture2D(tex, vec2(texCoord.s - x_offset, texCoord.t)); + vec4 right = texture2D(tex, vec2(texCoord.s + x_offset, texCoord.t)); + vec4 up = texture2D(tex, vec2(texCoord.s, texCoord.t - y_offset)); + vec4 down = texture2D(tex, vec2(texCoord.s, texCoord.t + y_offset)); + + bool is_image_edge = (texCoord.s - x_offset < 0 || texCoord.s + x_offset > 1 || texCoord.t - y_offset < 0 || texCoord.t + y_offset > 1); + + if(left.a != right.a || left.a != up.a || left.a != down.a || (center.a > 0.5 && is_image_edge)) + { + if(center.a > 0.5) + { + float speed = 0.6; + float ant_size = 10; + float black_to_white_ratio = 0.5; + float ant_position = (gl_FragCoord.x + gl_FragCoord.y); + float t = step(black_to_white_ratio, mod(time*speed + ant_position/ant_size, 1.0)); + + fragColor = vec4(t, t, t, 1); + } + else + fragColor = vec4(1, 1, 1, 1); + } + else if(center.a < 0.5) + { + fragColor = vec4(0, 0, 0, 0.1); + } + else + discard; +} \ No newline at end of file diff --git a/data/shaders/untextured.frag b/data/shaders/untextured.frag new file mode 100644 index 0000000..40ffe59 --- /dev/null +++ b/data/shaders/untextured.frag @@ -0,0 +1,8 @@ +#version 120 + +varying vec4 color; + +void main(void) +{ + gl_FragColor = color; +} \ No newline at end of file diff --git a/data/shaders/untextured.vert b/data/shaders/untextured.vert new file mode 100644 index 0000000..54aae53 --- /dev/null +++ b/data/shaders/untextured.vert @@ -0,0 +1,13 @@ +#version 120 + +attribute vec3 gpu_Vertex; +attribute vec4 gpu_Color; +uniform mat4 gpu_ModelViewProjectionMatrix; + +varying vec4 color; + +void main(void) +{ + color = gpu_Color; + gl_Position = gpu_ModelViewProjectionMatrix * vec4(gpu_Vertex, 1.0); +} \ No newline at end of file diff --git a/src/system.c b/src/system.c index 48174ba..823ad5d 100644 --- a/src/system.c +++ b/src/system.c @@ -207,7 +207,10 @@ static void initTouchGamepad() static void calcTextureRect(SDL_Rect* rect) { - SDL_GetWindowSize(platform.window, &rect->w, &rect->h); + // SDL_GetWindowSize(platform.window, &rect->w, &rect->h); + + rect->w = TIC80_FULLWIDTH * STUDIO_UI_SCALE; + rect->h = TIC80_FULLHEIGHT * STUDIO_UI_SCALE; if (rect->w * TIC80_HEIGHT < rect->h * TIC80_WIDTH) { @@ -889,7 +892,8 @@ static u64 getPerformanceFrequency() static void goFullscreen() { - SDL_SetWindowFullscreen(platform.window, SDL_GetWindowFlags(platform.window) & SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); + GPU_SetFullscreen(GPU_GetFullscreen() ? false : true, true); + // SDL_SetWindowFullscreen(platform.window, SDL_GetWindowFlags(platform.window) & SDL_WINDOW_FULLSCREEN_DESKTOP ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); } static void showMessageBox(const char* title, const char* message) @@ -1000,8 +1004,107 @@ static void emstick() #endif +Uint32 load_shader(GPU_ShaderEnum shader_type, const char* filename) +{ + SDL_RWops* rwops; + Uint32 shader; + char* source; + int header_size, file_size; + const char* header = ""; + GPU_Renderer* renderer = GPU_GetCurrentRenderer(); + + // Open file + rwops = SDL_RWFromFile(filename, "rb"); + if(rwops == NULL) + { + GPU_PushErrorCode("load_shader", GPU_ERROR_FILE_NOT_FOUND, "Shader file \"%s\" not found", filename); + return 0; + } + + // Get file size + file_size = SDL_RWseek(rwops, 0, SEEK_END); + SDL_RWseek(rwops, 0, SEEK_SET); + + // Get size from header + if(renderer->shader_language == GPU_LANGUAGE_GLSL) + { + if(renderer->max_shader_version >= 120) + header = "#version 120\n"; + else + header = "#version 110\n"; // Maybe this is good enough? + } + else if(renderer->shader_language == GPU_LANGUAGE_GLSLES) + header = "#version 100\nprecision mediump int;\nprecision mediump float;\n"; + + header_size = strlen(header); + + // Allocate source buffer + source = (char*)malloc(sizeof(char)*(header_size + file_size + 1)); + + // Prepend header + strcpy(source, header); + + // Read in source code + SDL_RWread(rwops, source + strlen(source), 1, file_size); + source[header_size + file_size] = '\0'; + + // Compile the shader + shader = GPU_CompileShader(shader_type, source); + + // Clean up + free(source); + SDL_RWclose(rwops); + + return shader; +} + +GPU_ShaderBlock load_shader_program(Uint32* p, const char* vertex_shader_file, const char* fragment_shader_file) +{ + Uint32 v, f; + v = load_shader(GPU_VERTEX_SHADER, vertex_shader_file); + + if(!v) + GPU_LogError("Failed to load vertex shader (%s): %s\n", vertex_shader_file, GPU_GetShaderMessage()); + + f = load_shader(GPU_PIXEL_SHADER, fragment_shader_file); + + if(!f) + GPU_LogError("Failed to load fragment shader (%s): %s\n", fragment_shader_file, GPU_GetShaderMessage()); + + *p = GPU_LinkShaders(v, f); + + if(!*p) + { + GPU_ShaderBlock b = {-1, -1, -1, -1}; + GPU_LogError("Failed to link shader program (%s + %s): %s\n", vertex_shader_file, fragment_shader_file, GPU_GetShaderMessage()); + return b; + } + + { + GPU_ShaderBlock block = GPU_LoadShaderBlock(*p, "gpu_Vertex", "gpu_TexCoord", "gpu_Color", "gpu_ModelViewProjectionMatrix"); + GPU_ActivateShaderProgram(*p, &block); + + return block; + } +} + +void free_shader(Uint32 p) +{ + GPU_FreeShaderProgram(p); +} + +void update_color_shader(float r, float g, float b, float a, int color_loc) +{ + float fcolor[4] = {r, g, b, a}; + GPU_SetUniformfv(color_loc, 4, 1, fcolor); +} + +#include + static s32 start(s32 argc, char **argv, const char* folder) { + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); + initSound(); platform.net = createNet(); @@ -1016,49 +1119,54 @@ static s32 start(s32 argc, char **argv, const char* folder) GPU_Target* screen = GPU_Init(TIC80_FULLWIDTH * STUDIO_UI_SCALE, TIC80_FULLHEIGHT * STUDIO_UI_SCALE, GPU_INIT_DISABLE_VSYNC); GPU_Image* texture = GPU_CreateImage(TIC80_FULLWIDTH, TIC80_FULLHEIGHT, GPU_FORMAT_BGRA); + s32 color_shader = 0; + GPU_ShaderBlock color_block = load_shader_program(&color_shader, "data/shaders/common.vert", "data/shaders/color.frag"); + int color_loc = GPU_GetUniformLocation(color_shader, "myColor"); + { + u64 nextTick = SDL_GetPerformanceCounter(); + const u64 Delta = SDL_GetPerformanceFrequency() / TIC_FRAMERATE; + + while (!platform.studio->quit) { - u64 nextTick = SDL_GetPerformanceCounter(); - const u64 Delta = SDL_GetPerformanceFrequency() / TIC_FRAMERATE; + platform.missedFrame = false; - while (!platform.studio->quit) + nextTick += Delta; + { - platform.missedFrame = false; + pollEvent(); - nextTick += Delta; + float t = SDL_GetTicks()/1000.0f; - + GPU_Clear(screen); + { - pollEvent(); - - GPU_Clear(screen); - - { - platform.studio->tick(); - GPU_UpdateImageBytes(texture, NULL, tic->screen, TIC80_FULLWIDTH * sizeof(u32)); - } - - GPU_BlitScale(texture, NULL, screen, TIC80_FULLWIDTH/2*STUDIO_UI_SCALE, TIC80_FULLHEIGHT/2*STUDIO_UI_SCALE, STUDIO_UI_SCALE, STUDIO_UI_SCALE); - - GPU_Flip(screen); - - blitSound(); + platform.studio->tick(); + GPU_UpdateImageBytes(texture, NULL, (const u8*)tic->screen, TIC80_FULLWIDTH * sizeof(u32)); } + GPU_ActivateShaderProgram(color_shader, &color_block); + update_color_shader((1+sin(t))/2, (1+sin(t+1))/2, (1+sin(t+2))/2, 1.0f, color_loc); + // GPU_BlitScale(texture, NULL, screen, TIC80_FULLWIDTH/2*STUDIO_UI_SCALE, TIC80_FULLHEIGHT/2*STUDIO_UI_SCALE, STUDIO_UI_SCALE, STUDIO_UI_SCALE); + GPU_Blit(texture, NULL, screen, TIC80_FULLWIDTH/2*STUDIO_UI_SCALE, TIC80_FULLHEIGHT/2*STUDIO_UI_SCALE); + + GPU_Flip(screen); + + blitSound(); + } + + { + s64 delay = nextTick - SDL_GetPerformanceCounter(); + + if(delay < 0) { - s64 delay = nextTick - SDL_GetPerformanceCounter(); - - if(delay < 0) - { - nextTick -= delay; - platform.missedFrame = true; - } - else SDL_Delay((u32)(delay * 1000 / SDL_GetPerformanceFrequency())); + nextTick -= delay; + platform.missedFrame = true; } + else SDL_Delay((u32)(delay * 1000 / SDL_GetPerformanceFrequency())); } } - } platform.studio->close(); @@ -1081,7 +1189,6 @@ static s32 start2(s32 argc, char **argv, const char* folder) SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); - initSound(); platform.net = createNet();