terrain

Real-time terrain generation using marching cubes
git clone git://git.christianermann.dev/terrain
Log | Files | Refs | README | LICENSE

shader.c (4697B)


      1 #include "shader.h"
      2 #include "logger.h"
      3 #include "memory.h"
      4 
      5 #include <stdio.h>
      6 
      7 static char* stringFromFile(const char* filename)
      8 {
      9     // Open file.
     10     FILE* fp = fopen(filename, "r");
     11     if (!fp)
     12     {
     13         LOGE("Failed to open file '%s'", filename);
     14         return NULL;
     15     }
     16 
     17     // Calculate the length of the file.
     18     fseek(fp, 0, SEEK_END);
     19     long size = ftell(fp);
     20     rewind(fp);
     21 
     22     // Read file to string.
     23     char *string = (char *)s_alloc(size + 1, MEMORY_TAG_STRING);
     24     if (string)
     25     {
     26         fread(string, 1, size, fp);
     27         string[size] = '\0';
     28     }
     29     else
     30     {
     31         LOGE("Failed to allocate string for file '%s'", filename);
     32     }
     33     fclose(fp);
     34     return string;
     35 }
     36 
     37 static GLuint createAndCompileShader(const char* shader_string,
     38         GLenum shader_type)
     39 {
     40     GLuint shader = glCreateShader(shader_type);
     41     glShaderSource(shader, 1, &shader_string, NULL);
     42     glCompileShader(shader);
     43 
     44     // Handle errors.
     45     GLint is_compiled;
     46     glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled); 
     47     if (is_compiled == GL_FALSE)
     48     {
     49         GLint size;
     50         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
     51         char *string = (char *)s_alloc(size, MEMORY_TAG_STRING);
     52         glGetShaderInfoLog(shader, size, &size, string);
     53         LOGE("Failed to compile shader: %s", string);
     54         glDeleteShader(shader);
     55         return 0;
     56     }
     57 
     58     return shader;
     59 }
     60 
     61 static GLuint createAndLinkProgram(GLuint vertex_shader,
     62         GLuint fragment_shader)
     63 {
     64     GLuint program = glCreateProgram();
     65     glAttachShader(program, vertex_shader);
     66     glAttachShader(program, fragment_shader);
     67     glLinkProgram(program);
     68 
     69     // Handle errors.
     70     GLint is_linked;
     71     glGetProgramiv(program, GL_LINK_STATUS, &is_linked);
     72     if (is_linked == GL_FALSE)
     73     {
     74         GLint size;
     75         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
     76         char *string = (char *)s_alloc(size, MEMORY_TAG_STRING);
     77         glGetProgramInfoLog(program, size, &size, string);
     78         LOGE("Failed to link program: %s", string);
     79         glDeleteProgram(program);
     80         return 0;
     81     }
     82 
     83     glDetachShader(program, vertex_shader);
     84     glDetachShader(program, fragment_shader);
     85 
     86     return program;
     87 }
     88 
     89 static GLuint createProgramFromFiles(const char* vertex_shader_filename,
     90         const char* fragment_shader_filename)
     91 {
     92     char* vertex_shader_string = stringFromFile(vertex_shader_filename);
     93     GLuint vertex_shader = createAndCompileShader(vertex_shader_string,
     94             GL_VERTEX_SHADER);
     95     if (vertex_shader == 0) return 0;
     96 
     97     char* fragment_shader_string = stringFromFile(fragment_shader_filename);
     98     GLuint fragment_shader = createAndCompileShader(fragment_shader_string,
     99             GL_FRAGMENT_SHADER);
    100     if (fragment_shader == 0) return 0;
    101 
    102     GLuint program = createAndLinkProgram(vertex_shader, fragment_shader);
    103 
    104     glDeleteShader(vertex_shader);
    105     glDeleteShader(fragment_shader);
    106 
    107     return program;
    108 }
    109 
    110 struct Shader {
    111     GLuint program;
    112     const char *vert_filename;
    113     const char *frag_filename;
    114 };
    115 
    116 Shader *Shader_make(const char* vert_filename, const char* frag_filename)
    117 {
    118     LOGI("Creating shader: %s %s", vert_filename, frag_filename);
    119 
    120     GLuint program = createProgramFromFiles(vert_filename, frag_filename);
    121 
    122     Shader *shader = s_alloc(sizeof *shader, MEMORY_TAG_RENDER);
    123     shader->program = program;
    124     shader->vert_filename = vert_filename;
    125     shader->frag_filename = frag_filename;
    126 
    127     return shader;
    128 }
    129 
    130 void Shader_free(Shader *shader)
    131 {
    132     if (shader)
    133     {
    134         s_free(shader, sizeof *shader, MEMORY_TAG_RENDER);
    135     }
    136 }
    137 
    138 void Shader_use(Shader *shader)
    139 {
    140     glUseProgram(shader->program);
    141 }
    142 
    143 void Shader_reload(Shader* shader)
    144 {
    145     GLuint reloaded_program = createProgramFromFiles(shader->vert_filename,
    146             shader->frag_filename);
    147 
    148     if (reloaded_program != 0)
    149     {
    150         glDeleteProgram(shader->program);
    151         shader->program = reloaded_program;
    152     }
    153 }
    154 
    155 void Shader_setInt(const Shader *shader, const char *name, i32 i)
    156 {
    157     GLint uniform_loc = glGetUniformLocation(shader->program, name);
    158     glUniform1i(uniform_loc, i);
    159 }
    160 
    161 void Shader_setFloat(const Shader *shader, const char *name, f32 f)
    162 {
    163     GLint uniform_loc = glGetUniformLocation(shader->program, name);
    164     glUniform1f(uniform_loc, f);
    165 }
    166 
    167 void Shader_setVec3(const Shader *shader, const char *name, Vec3 v)
    168 {
    169     GLint uniform_loc = glGetUniformLocation(shader->program, name);
    170     glUniform3fv(uniform_loc, 1, v);
    171 }
    172 
    173 void Shader_setMat4(const Shader *shader, const char *name, Mat4 m)
    174 {
    175     GLint uniform_loc = glGetUniformLocation(shader->program, name);
    176     glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, m[0]);
    177 }
    178