cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

renderer.cpp (11513B)


      1/*
      2 * Gearboy - Nintendo Game Boy Emulator
      3 * Copyright (C) 2012  Ignacio Sanchez
      4
      5 * This program is free software: you can redistribute it and/or modify
      6 * it under the terms of the GNU General Public License as published by
      7 * the Free Software Foundation, either version 3 of the License, or
      8 * any later version.
      9
     10 * This program is distributed in the hope that it will be useful,
     11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     13 * GNU General Public License for more details.
     14
     15 * You should have received a copy of the GNU General Public License
     16 * along with this program.  If not, see http://www.gnu.org/licenses/
     17 *
     18 */
     19
     20#ifdef __APPLE__
     21#define GL_SILENCE_DEPRECATION
     22#include <OpenGL/gl.h>
     23#else
     24#include <GL/glew.h>
     25#include <SDL_opengl.h>
     26#endif
     27
     28#include "imgui/imgui.h"
     29#include "imgui/imgui_impl_opengl2.h"
     30#include "emu.h"
     31#include "config.h"
     32#include "../../src/gearboy.h"
     33
     34#define RENDERER_IMPORT
     35#include "renderer.h"
     36
     37static uint32_t gameboy_texture;
     38static uint32_t matrix_texture;
     39static uint32_t frame_buffer_object;
     40static bool first_frame;
     41static u32 matrix[16] = {0x00000000, 0x00000000, 0x00000000, 0x000000FF, 0x00000000, 0x00000000, 0x00000000, 0x000000FF, 0x00000000, 0x00000000, 0x00000000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF};
     42static const int FRAME_BUFFER_SCALE = 4;
     43
     44static void init_ogl_gui(void);
     45static void init_ogl_emu(void);
     46static void init_ogl_debug(void);
     47static void init_matrix_textures(void);
     48static void render_gui(void);
     49static void render_emu_normal(void);
     50static void render_emu_mix(void);
     51static void render_emu_bilinear(void);
     52static void render_quad(int viewportWidth, int viewportHeight);
     53static void update_system_texture(void);
     54static void update_debug_textures(void);
     55static void render_matrix(void);
     56
     57void renderer_init(void)
     58{
     59    #ifndef __APPLE__
     60    GLenum err = glewInit();
     61    if (GLEW_OK != err)
     62    {
     63        /* Problem: glewInit failed, something is seriously wrong. */
     64        Log("GLEW Error: %s\n", glewGetErrorString(err));
     65    }
     66
     67    renderer_glew_version = (const char*)glewGetString(GLEW_VERSION);
     68    renderer_opengl_version = (const char*)glGetString(GL_VERSION);
     69
     70    Log("Using GLEW %s\n", renderer_glew_version);
     71    
     72    #endif
     73
     74    init_ogl_gui();
     75    init_ogl_emu();
     76    init_ogl_debug();
     77
     78    first_frame = true;
     79}
     80
     81void renderer_destroy(void)
     82{
     83    glDeleteFramebuffers(1, &frame_buffer_object); 
     84    glDeleteTextures(1, &renderer_emu_texture);
     85    glDeleteTextures(1, &gameboy_texture);
     86    glDeleteTextures(1, &matrix_texture);
     87    glDeleteTextures(1, &renderer_emu_debug_vram_background);
     88    glDeleteTextures(2, renderer_emu_debug_vram_tiles);
     89    glDeleteTextures(40, renderer_emu_debug_vram_oam);
     90    ImGui_ImplOpenGL2_Shutdown();
     91}
     92
     93void renderer_begin_render(void)
     94{
     95    ImGui_ImplOpenGL2_NewFrame();
     96}
     97
     98void renderer_render(void)
     99{
    100    if (config_debug.debug)
    101    {
    102        update_debug_textures();
    103    }
    104
    105    if (config_video.mix_frames)
    106        render_emu_mix();
    107    else
    108        render_emu_normal();
    109
    110    if (config_video.matrix)
    111        render_matrix();
    112
    113    render_emu_bilinear();
    114
    115    ImVec4 clear_color = ImVec4(0.1f, 0.1f, 0.1f, 1.00f);
    116
    117    glViewport(0, 0, (int)ImGui::GetIO().DisplaySize.x, (int)ImGui::GetIO().DisplaySize.y);
    118    glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
    119    glClear(GL_COLOR_BUFFER_BIT);
    120
    121    render_gui();
    122}
    123
    124void renderer_end_render(void)
    125{
    126
    127}
    128
    129static void init_ogl_gui(void)
    130{
    131    ImGui_ImplOpenGL2_Init();
    132}
    133
    134static void init_ogl_emu(void)
    135{
    136    glEnable(GL_TEXTURE_2D);
    137
    138    glGenFramebuffers(1, &frame_buffer_object);
    139    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_object);
    140
    141    glGenTextures(1, &renderer_emu_texture);
    142    glBindTexture(GL_TEXTURE_2D, renderer_emu_texture);
    143    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAMEBOY_WIDTH * FRAME_BUFFER_SCALE, GAMEBOY_HEIGHT * FRAME_BUFFER_SCALE, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    144    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    145    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    146
    147    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderer_emu_texture, 0);
    148
    149    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    150
    151    glGenTextures(1, &gameboy_texture);  
    152    glBindTexture(GL_TEXTURE_2D, gameboy_texture);
    153    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GAMEBOY_WIDTH, GAMEBOY_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) emu_frame_buffer);
    154    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    155    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    156
    157    init_matrix_textures();
    158}
    159
    160static void init_ogl_debug(void)
    161{
    162    glGenTextures(1, &renderer_emu_debug_vram_background);
    163    glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_background);
    164    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)emu_debug_background_buffer);
    165    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    166    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    167
    168    for (int b = 0; b < 2; b++)
    169    {
    170        glGenTextures(1, &renderer_emu_debug_vram_tiles[b]);
    171        glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_tiles[b]);
    172        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 16 * 8, 24 * 8, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)emu_debug_tile_buffers[b]);
    173        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    174        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    175    }
    176
    177    for (int s = 0; s < 40; s++)
    178    {
    179        glGenTextures(1, &renderer_emu_debug_vram_oam[s]);
    180        glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_oam[s]);
    181        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 16, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)emu_debug_oam_buffers[s]);
    182        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    183        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    184    }
    185}
    186
    187static void init_matrix_textures(void)
    188{
    189    glGenTextures(1, &matrix_texture);
    190
    191    glBindTexture(GL_TEXTURE_2D, matrix_texture);
    192    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (GLvoid*) matrix);
    193    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    194    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    195    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    196    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    197}
    198
    199static void render_gui(void)
    200{
    201    ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
    202}
    203
    204static void render_emu_normal(void)
    205{
    206    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_object);
    207
    208    glDisable(GL_BLEND);
    209
    210    update_system_texture();
    211
    212    render_quad(GAMEBOY_WIDTH * FRAME_BUFFER_SCALE, GAMEBOY_HEIGHT * FRAME_BUFFER_SCALE);
    213
    214    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    215}
    216
    217static void render_emu_mix(void)
    218{
    219    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_object);
    220
    221    float alpha = 0.15f + (0.20f * (1.0f - config_video.mix_frames_intensity));
    222
    223    if (first_frame)
    224    {
    225        first_frame = false;
    226        alpha = 1.0f;
    227        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    228        glClear(GL_COLOR_BUFFER_BIT);
    229    }
    230
    231    static bool round_error = false; 
    232    float round_color = 1.0f - (round_error ? 0.03f : 0.0f);
    233    round_error = !round_error;
    234
    235    glEnable(GL_BLEND);
    236    glColor4f(round_color, round_color, round_color, alpha);
    237    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    238
    239    update_system_texture();
    240
    241    render_quad(GAMEBOY_WIDTH * FRAME_BUFFER_SCALE, GAMEBOY_HEIGHT * FRAME_BUFFER_SCALE);
    242
    243    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    244    glDisable(GL_BLEND);
    245
    246    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    247}
    248
    249static void update_system_texture(void)
    250{
    251    glBindTexture(GL_TEXTURE_2D, gameboy_texture);
    252    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GAMEBOY_WIDTH, GAMEBOY_HEIGHT,
    253            GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) emu_frame_buffer);
    254
    255    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    256    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    257
    258    if (config_video.bilinear)
    259    {
    260        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    261        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    262    }
    263    else
    264    {
    265        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    266        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    267    }
    268}
    269
    270static void update_debug_textures(void)
    271{
    272    glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_background);
    273    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 256,
    274            GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) emu_debug_background_buffer);
    275
    276    for (int b = 0; b < 2; b++)
    277    {
    278        glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_tiles[b]);
    279        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16 * 8, 24 * 8,
    280                GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) emu_debug_tile_buffers[b]);
    281    }
    282
    283    for (int s = 0; s < 40; s++)
    284    {
    285        glBindTexture(GL_TEXTURE_2D, renderer_emu_debug_vram_oam[s]);
    286        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 8, 16,
    287                GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*) emu_debug_oam_buffers[s]);
    288    }
    289}
    290
    291static void render_emu_bilinear(void)
    292{
    293    glBindTexture(GL_TEXTURE_2D, renderer_emu_texture);
    294
    295    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    296    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    297
    298    if (config_video.matrix)
    299    {
    300        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    301        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    302    }
    303    else
    304    {
    305        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    306        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    307    }
    308}
    309
    310static void render_quad(int viewportWidth, int viewportHeight)
    311{
    312    glMatrixMode(GL_PROJECTION);
    313    glLoadIdentity();
    314
    315    glOrtho(0, viewportWidth, 0, viewportHeight, -1, 1);
    316
    317    glMatrixMode(GL_MODELVIEW);
    318    glViewport(0, 0, viewportWidth, viewportHeight);
    319
    320    glBegin(GL_QUADS);
    321    glTexCoord2d(0.0, 0.0);
    322    glVertex2d(0.0, 0.0);
    323    glTexCoord2d(1.0, 0.0);
    324    glVertex2d(viewportWidth, 0.0);
    325    glTexCoord2d(1.0, 1.0);
    326    glVertex2d(viewportWidth, viewportHeight);
    327    glTexCoord2d(0.0, 1.0);
    328    glVertex2d(0.0, viewportHeight);
    329    glEnd();
    330}
    331
    332static void render_matrix(void)
    333{
    334    glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_object);
    335    glEnable(GL_BLEND);
    336
    337    glColor4f(1.0f, 1.0f, 1.0f, config_video.matrix_intensity / 4.0f);
    338    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    339
    340    glBindTexture(GL_TEXTURE_2D, matrix_texture);
    341
    342    int viewportWidth = GAMEBOY_WIDTH * FRAME_BUFFER_SCALE;
    343    int viewportHeight = GAMEBOY_HEIGHT * FRAME_BUFFER_SCALE;
    344
    345    glMatrixMode(GL_PROJECTION);
    346    glLoadIdentity();
    347
    348    glOrtho(0, viewportWidth, 0, viewportHeight, -1, 1);
    349
    350    glMatrixMode(GL_MODELVIEW);
    351    glViewport(0, 0, viewportWidth, viewportHeight);
    352
    353    glBegin(GL_QUADS);
    354    glTexCoord2d(0.0, 0.0);
    355    glVertex2d(0.0, 0.0);
    356    glTexCoord2d(GAMEBOY_WIDTH, 0.0);
    357    glVertex2d(viewportWidth, 0.0);
    358    glTexCoord2d(GAMEBOY_WIDTH, GAMEBOY_HEIGHT);
    359    glVertex2d(viewportWidth, viewportHeight);
    360    glTexCoord2d(0.0, GAMEBOY_HEIGHT);
    361    glVertex2d(0.0, viewportHeight);
    362    glEnd();
    363
    364    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
    365
    366    glDisable(GL_BLEND);
    367    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    368}