prosperon/source/engine/shader.c

178 lines
4.3 KiB
C
Raw Normal View History

2021-11-30 21:29:18 -06:00
#include "shader.h"
2022-02-06 10:14:57 -06:00
#include "render.h"
2021-11-30 21:29:18 -06:00
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "log.h"
#include "resources.h"
2022-08-26 09:19:17 -05:00
#include "stb_ds.h"
#include "timer.h"
2021-11-30 21:29:18 -06:00
#include "time.h"
2021-11-30 21:29:18 -06:00
#define SHADER_BUF 10000
2022-11-19 17:13:57 -06:00
static struct shader *shaders;
2021-11-30 21:29:18 -06:00
2022-11-19 17:13:57 -06:00
struct shader *MakeShader(const char *vertpath, const char *fragpath)
2021-11-30 21:29:18 -06:00
{
2022-08-26 09:19:17 -05:00
if (arrcap(shaders) == 0)
arrsetcap(shaders, 20);
2022-07-02 03:40:50 -05:00
2022-11-19 17:13:57 -06:00
struct shader init = {
2022-08-26 09:19:17 -05:00
.vertpath = vertpath,
.fragpath = fragpath };
shader_compile(&init);
arrput(shaders, init);
return &arrlast(shaders);
2021-11-30 21:29:18 -06:00
}
int shader_compile_error(GLuint shader)
{
GLint success = 0;
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (success) return 0;
glGetShaderInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
2022-02-06 10:14:57 -06:00
YughLog(0, LOG_ERROR, "Shader compilation error.\nLog: %s", infoLog);
2021-11-30 21:29:18 -06:00
return 1;
}
int shader_link_error(GLuint shader)
{
GLint success = 0;
GLchar infoLog[ERROR_BUFFER] = { '\0' };
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (success) return 0;
glGetProgramInfoLog(shader, ERROR_BUFFER, NULL, infoLog);
2022-02-06 10:14:57 -06:00
YughLog(0, LOG_ERROR, "Shader link error.\nLog: %s", infoLog);
2021-11-30 21:29:18 -06:00
return 1;
}
2022-02-06 10:14:57 -06:00
GLuint load_shader_from_file(const char *path, int type)
2021-11-30 21:29:18 -06:00
{
char spath[MAXPATH] = {'\0'};
2022-01-19 16:43:21 -06:00
sprintf(spath, "%s%s", "shaders/", path);
FILE *f = fopen(make_path(spath), "r'");
2021-11-30 21:29:18 -06:00
if (!path)
perror(spath), exit(1);
2023-01-03 17:13:31 -06:00
char *buf;
2021-11-30 21:29:18 -06:00
long int fsize;
fseek(f, 0, SEEK_END);
fsize = ftell(f);
2023-01-03 17:13:31 -06:00
buf = malloc(fsize+1);
2021-11-30 21:29:18 -06:00
rewind(f);
2023-01-03 17:13:31 -06:00
size_t r = fread(buf, sizeof(char), fsize, f);
buf[r] = '\0';
2021-11-30 21:29:18 -06:00
fclose(f);
GLuint id = glCreateShader(type);
const char *code = buf;
glShaderSource(id, 1, &code, NULL);
glCompileShader(id);
2022-07-02 03:40:50 -05:00
if (shader_compile_error(id)) {
YughError("Error with shader %s.", path);
2021-11-30 21:29:18 -06:00
return 0;
2022-07-02 03:40:50 -05:00
}
2021-11-30 21:29:18 -06:00
2023-01-03 17:13:31 -06:00
free(buf);
2021-11-30 21:29:18 -06:00
return id;
}
2022-11-19 17:13:57 -06:00
void shader_compile(struct shader *shader)
2021-11-30 21:29:18 -06:00
{
YughInfo("Making shader with %s and %s.", shader->vertpath, shader->fragpath);
clock_t startt = clock();
2022-08-26 09:19:17 -05:00
2021-11-30 21:29:18 -06:00
GLuint vert = load_shader_from_file(shader->vertpath, GL_VERTEX_SHADER);
GLuint frag = load_shader_from_file(shader->fragpath, GL_FRAGMENT_SHADER);
shader->id = glCreateProgram();
glAttachShader(shader->id, vert);
glAttachShader(shader->id, frag);
glLinkProgram(shader->id);
shader_link_error(shader->id);
glDeleteShader(vert);
glDeleteShader(frag);
startt = clock() - startt;
YughInfo("Created shader in %d ticks (%f seconds).", startt, ((float)startt/CLOCKS_PER_SEC));
2021-11-30 21:29:18 -06:00
}
2022-11-19 17:13:57 -06:00
void shader_use(struct shader *shader)
2021-11-30 21:29:18 -06:00
{
glUseProgram(shader->id);
}
2022-11-19 17:13:57 -06:00
void shader_setbool(struct shader *shader, const char *name, int val)
2021-11-30 21:29:18 -06:00
{
glUniform1i(glGetUniformLocation(shader->id, name), val);
}
2022-11-19 17:13:57 -06:00
void shader_setint(struct shader *shader, const char *name, int val)
2021-11-30 21:29:18 -06:00
{
glUniform1i(glGetUniformLocation(shader->id, name), val);
}
2022-11-19 17:13:57 -06:00
void shader_setfloat(struct shader *shader, const char *name, float val)
2021-11-30 21:29:18 -06:00
{
glUniform1f(glGetUniformLocation(shader->id, name), val);
}
2022-11-19 17:13:57 -06:00
void shader_setvec2(struct shader *shader, const char *name, mfloat_t val[2])
2021-11-30 21:29:18 -06:00
{
glUniform2fv(glGetUniformLocation(shader->id, name), 1, val);
}
2022-11-19 17:13:57 -06:00
void shader_setvec3(struct shader *shader, const char *name, mfloat_t val[3])
2021-11-30 21:29:18 -06:00
{
glUniform3fv(glGetUniformLocation(shader->id, name), 1, val);
}
2022-11-19 17:13:57 -06:00
void shader_setvec4(struct shader *shader, const char *name, mfloat_t val[4])
2021-11-30 21:29:18 -06:00
{
glUniform4fv(glGetUniformLocation(shader->id, name), 1, val);
}
2022-11-19 17:13:57 -06:00
void shader_setmat2(struct shader *shader, const char *name, mfloat_t val[4])
2021-11-30 21:29:18 -06:00
{
2022-06-30 10:31:23 -05:00
glUniformMatrix2fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, val);
2021-11-30 21:29:18 -06:00
}
2022-11-19 17:13:57 -06:00
void shader_setmat3(struct shader *shader, const char *name, mfloat_t val[9])
2021-11-30 21:29:18 -06:00
{
2022-06-30 10:31:23 -05:00
glUniformMatrix3fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, val);
2021-11-30 21:29:18 -06:00
}
2022-11-19 17:13:57 -06:00
void shader_setmat4(struct shader *shader, const char *name, mfloat_t val[16])
2021-11-30 21:29:18 -06:00
{
2022-06-30 10:31:23 -05:00
glUniformMatrix4fv(glGetUniformLocation(shader->id, name), 1, GL_FALSE, val);
2021-11-30 21:29:18 -06:00
}
2022-11-19 17:13:57 -06:00
void shader_setUBO(struct shader *shader, const char *name, unsigned int index)
2021-11-30 21:29:18 -06:00
{
2022-06-30 10:31:23 -05:00
glUniformBlockBinding(shader->id, glGetUniformBlockIndex(shader->id, name), index);
2021-11-30 21:29:18 -06:00
}
void shader_compile_all()
{
2022-12-28 16:50:54 -06:00
for (int i = 0; i < arrlen(shaders); i++)
shader_compile(&shaders[i]);
2021-11-30 21:29:18 -06:00
}