shadermeh/shader.c

189 lines
3.5 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: ISC */
/*
* shader.c
*
* Copyright (C) 2022 David Oberhollenzer <goliath@infraroot.at>
*/
#include "shadermeh.h"
/* stub vertex shader */
static const char *vert_src =
"#version 140\n"
"\n"
"in vec4 V_POSITION;\n"
"in vec4 V_COLOR;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = V_POSITION;\n"
"}\n";
/* stub fragment shader */
static const char *frag_src_pre =
"#version 330\n"
"\n"
"uniform vec3 iResolution;\n"
"uniform float iTime;\n"
"uniform float iTimeDelta;\n"
"uniform float iFrame;\n"
"uniform float iChannelTime[4];\n"
"uniform vec4 iMouse;\n"
"uniform vec4 iDate;\n"
"uniform float iSampleRate;\n"
"uniform vec3 iChannelResolution[4];\n"
"uniform sampler2D iChannel0;"
"\n";
static const char *frag_src_post =
"\n"
"void main()\n"
"{\n"
" mainImage(gl_FragColor, gl_FragCoord.xy);\n"
"}\n"
"\n";
static char* load_file(const char *path)
{
size_t size, pre_len, post_len;
char *buffer;
FILE *f;
if (!path)
return NULL;
/* try to open the file */
f = fopen(path, "r");
if (!f) {
perror(path);
return NULL;
}
/* get file size */
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
pre_len = strlen(frag_src_pre);
post_len = strlen(frag_src_post);
/* try to allocate buffer for file contents */
buffer = calloc(1, pre_len + size + post_len + 1);
if (!buffer) {
fclose(f);
return NULL;
}
/* read file contents into buffer */
memcpy(buffer, frag_src_pre, pre_len);
fread(buffer + pre_len, 1, size, f);
memcpy(buffer + pre_len + size, frag_src_post, post_len);
/* cleanup */
fclose(f);
return buffer;
}
/****************************************************************************/
GLuint shader_program_load(const char *fsrc)
{
GLuint vsh = 0, fsh = 0, prog = 0;
char *fs = NULL;
if (!fsrc)
return 0;
fs = load_file(fsrc);
if (!fs)
goto done;
vsh = glCreateShader(GL_VERTEX_SHADER);
fsh = glCreateShader(GL_FRAGMENT_SHADER);
if (!vsh || !fsh)
goto done;
prog = glCreateProgram();
if (!prog)
goto done;
glShaderSource(vsh, 1, (const GLchar **)&vert_src, NULL);
glShaderSource(fsh, 1, (const GLchar **)&fs, NULL);
glCompileShader(vsh);
glCompileShader(fsh);
glAttachShader(prog, vsh);
glAttachShader(prog, fsh);
glLinkProgram(prog);
done:
if (vsh)
glDeleteShader(vsh);
if (fsh)
glDeleteShader(fsh);
free(fs);
return prog;
}
int shader_program_get_build_status(GLuint prog)
{
GLuint shaders[3];
GLsizei i, count;
GLint v;
glGetProgramiv(prog, GL_LINK_STATUS, &v);
if (!v)
return 0;
glGetAttachedShaders(prog, 3, &count, shaders);
for (i = 0; i < count; ++i) {
glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &v);
if (!v)
return 0;
}
return 1;
}
void shader_program_print_info_log(GLuint prog)
{
GLsizei i, count, len;
char *buffer = NULL;
int buffersize = 0;
GLuint shaders[3];
GLint v;
glGetAttachedShaders(prog, 3, &count, shaders);
for (i = 0; i < count; ++i) {
glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &v);
if ((v + 1) > buffersize) {
buffer = realloc(buffer, v + 1);
buffersize = v + 1;
}
glGetShaderInfoLog(shaders[i], buffersize,
&len, (GLchar *)buffer);
buffer[len] = '\0';
printf("-------------\n%s\n-------------\n", buffer);
}
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &v);
if ((v + 1) > buffersize) {
buffer = realloc(buffer, v + 1);
buffersize = v + 1;
}
glGetProgramInfoLog(prog, buffersize, &len, (GLchar *)buffer);
buffer[len] = '\0';
printf("-------------\n%s\n-------------\n", buffer);
free(buffer);
}