git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

SDL/shader.c

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include "shader.h"
      4 #include "utils.h"
      5 
      6 static const char *vertex_shader = "\n\
      7 #version 150 \n\
      8 in vec4 aPosition;\n\
      9 void main(void) {\n\
     10 gl_Position = aPosition;\n\
     11 }\n\
     12 ";
     13 
     14 static GLuint create_shader(const char *source, GLenum type)
     15 {
     16     // Create the shader object
     17     GLuint shader = glCreateShader(type);
     18     // Load the shader source
     19     glShaderSource(shader, 1, &source, 0);
     20     // Compile the shader
     21     glCompileShader(shader);
     22     // Check for errors
     23     GLint status = 0;
     24     glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
     25     if (status == GL_FALSE) {
     26         GLchar messages[1024];
     27         glGetShaderInfoLog(shader, sizeof(messages), 0, &messages[0]);
     28         fprintf(stderr, "GLSL Shader Error: %s", messages);
     29     }
     30     return shader;
     31 }
     32 
     33 static GLuint create_program(const char *vsh, const char *fsh)
     34 {
     35     // Build shaders
     36     GLuint vertex_shader = create_shader(vsh, GL_VERTEX_SHADER);
     37     GLuint fragment_shader = create_shader(fsh, GL_FRAGMENT_SHADER);
     38     
     39     // Create program
     40     GLuint program = glCreateProgram();
     41     
     42     // Attach shaders
     43     glAttachShader(program, vertex_shader);
     44     glAttachShader(program, fragment_shader);
     45     
     46     // Link program
     47     glLinkProgram(program);
     48     // Check for errors
     49     GLint status;
     50     glGetProgramiv(program, GL_LINK_STATUS, &status);
     51     
     52     if (status == GL_FALSE) {
     53         GLchar messages[1024];
     54         glGetProgramInfoLog(program, sizeof(messages), 0, &messages[0]);
     55         fprintf(stderr, "GLSL Program Error: %s", messages);
     56     }
     57     
     58     // Delete shaders
     59     glDeleteShader(vertex_shader);
     60     glDeleteShader(fragment_shader);
     61     
     62     return program;
     63 }
     64 
     65 extern bool uses_gl(void);
     66 bool init_shader_with_name(shader_t *shader, const char *name)
     67 {
     68     if (!uses_gl()) return false;
     69     
     70     GLint major = 0, minor = 0;
     71     glGetIntegerv(GL_MAJOR_VERSION, &major);
     72     glGetIntegerv(GL_MINOR_VERSION, &minor);
     73     
     74     if (major * 0x100 + minor < 0x302) {
     75         return false;
     76     }
     77     
     78     static char master_shader_code[0x801] = {0,};
     79     static char shader_code[0x10001] = {0,};
     80     static char final_shader_code[0x10801] = {0,};
     81     static ssize_t filter_token_location = 0;
     82     
     83     if (!master_shader_code[0]) {
     84         FILE *master_shader_f = fopen(resource_path("Shaders/MasterShader.fsh"), "r");
     85         if (!master_shader_f) return false;
     86         fread(master_shader_code, 1, sizeof(master_shader_code) - 1, master_shader_f);
     87         fclose(master_shader_f);
     88         filter_token_location = strstr(master_shader_code, "{filter}") - master_shader_code;
     89         if (filter_token_location < 0) {
     90             master_shader_code[0] = 0;
     91             return false;
     92         }
     93     }
     94     
     95     char shader_path[1024];
     96     sprintf(shader_path, "Shaders/%s.fsh", name);
     97     
     98     FILE *shader_f = fopen(resource_path(shader_path), "r");
     99     if (!shader_f) return false;
    100     memset(shader_code, 0, sizeof(shader_code));
    101     fread(shader_code, 1, sizeof(shader_code) - 1, shader_f);
    102     fclose(shader_f);
    103     
    104     memset(final_shader_code, 0, sizeof(final_shader_code));
    105     memcpy(final_shader_code, master_shader_code, filter_token_location);
    106     strcpy(final_shader_code + filter_token_location, shader_code);
    107     strcat(final_shader_code + filter_token_location,
    108            master_shader_code + filter_token_location + sizeof("{filter}") - 1);
    109     
    110     shader->program = create_program(vertex_shader, final_shader_code);
    111     
    112     // Attributes
    113     shader->position_attribute = glGetAttribLocation(shader->program, "aPosition");
    114     // Uniforms
    115     shader->resolution_uniform = glGetUniformLocation(shader->program, "output_resolution");
    116     shader->origin_uniform = glGetUniformLocation(shader->program, "origin");
    117 
    118     glGenTextures(1, &shader->texture);
    119     glBindTexture(GL_TEXTURE_2D, shader->texture);
    120     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    121     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    122     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    123     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    124     glBindTexture(GL_TEXTURE_2D, 0);
    125     shader->texture_uniform = glGetUniformLocation(shader->program, "image");
    126     
    127     glGenTextures(1, &shader->previous_texture);
    128     glBindTexture(GL_TEXTURE_2D, shader->previous_texture);
    129     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    130     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    131     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    132     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    133     glBindTexture(GL_TEXTURE_2D, 0);
    134     shader->previous_texture_uniform = glGetUniformLocation(shader->program, "previous_image");
    135     
    136     shader->blending_mode_uniform = glGetUniformLocation(shader->program, "frame_blending_mode");
    137     
    138     // Program
    139     
    140     glUseProgram(shader->program);
    141     
    142     GLuint vao;
    143     glGenVertexArrays(1, &vao);
    144     glBindVertexArray(vao);
    145     
    146     GLuint vbo;
    147     glGenBuffers(1, &vbo);
    148     
    149     // Attributes
    150     
    151     
    152     static GLfloat const quad[16] = {
    153         -1.f, -1.f, 0, 1,
    154         -1.f, +1.f, 0, 1,
    155         +1.f, -1.f, 0, 1,
    156         +1.f, +1.f, 0, 1,
    157     };
    158     
    159     
    160     glBindBuffer(GL_ARRAY_BUFFER, vbo);
    161     glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
    162     glEnableVertexAttribArray(shader->position_attribute);
    163     glVertexAttribPointer(shader->position_attribute, 4, GL_FLOAT, GL_FALSE, 0, 0);
    164     
    165     return true;
    166 }
    167 
    168 void render_bitmap_with_shader(shader_t *shader, void *bitmap, void *previous,
    169                                unsigned source_width, unsigned source_height,
    170                                unsigned x, unsigned y, unsigned w, unsigned h,
    171                                GB_frame_blending_mode_t blending_mode)
    172 {
    173     glUseProgram(shader->program);
    174     glUniform2f(shader->origin_uniform, x, y);
    175     glUniform2f(shader->resolution_uniform, w, h);
    176     glActiveTexture(GL_TEXTURE0);
    177     glBindTexture(GL_TEXTURE_2D, shader->texture);
    178     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap);
    179     glUniform1i(shader->texture_uniform, 0);
    180     glUniform1i(shader->blending_mode_uniform, previous? blending_mode : GB_FRAME_BLENDING_MODE_DISABLED);
    181     if (previous) {
    182         glActiveTexture(GL_TEXTURE1);
    183         glBindTexture(GL_TEXTURE_2D, shader->previous_texture);
    184         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, source_width, source_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, previous);
    185         glUniform1i(shader->previous_texture_uniform, 1);
    186     }
    187     glBindFragDataLocation(shader->program, 0, "frag_color");
    188     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    189 }
    190 
    191 void free_shader(shader_t *shader)
    192 {
    193     if (!uses_gl()) return;
    194     GLint major = 0, minor = 0;
    195     glGetIntegerv(GL_MAJOR_VERSION, &major);
    196     glGetIntegerv(GL_MINOR_VERSION, &minor);
    197     
    198     if (major * 0x100 + minor < 0x302) {
    199         return;
    200     }
    201     
    202     glDeleteProgram(shader->program);
    203     glDeleteTextures(1, &shader->texture);
    204     glDeleteTextures(1, &shader->previous_texture);
    205 
    206 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.