/* SPDX-License-Identifier: ISC */ /* * shader.c * * Copyright (C) 2022 David Oberhollenzer */ #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); }