Tue, 23 Jan 2024 21:34:12 +0100
bring first scene graph to live
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * Copyright 2023 Mike Becker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "ascension/shader.h" #include "ascension/files.h" #include "ascension/error.h" #include <GL/glew.h> #include <string.h> AscShaderFont ASC_SHADER_FONT; AscShader asc_shader_compile(unsigned int type, char const *code, int length) { GLuint id = glCreateShader(type); if (id == 0) { asc_error("glCreateShader failed"); return (AscShader) {0}; } GLint success; glShaderSource(id, 1, &code, &length); glCompileShader(id); glGetShaderiv(id, GL_COMPILE_STATUS, &success); if (success) { asc_dprintf("Shader %u compiled", id); return (AscShader) {id}; } else { char *log = malloc(1024); glGetShaderInfoLog(id, 1024, NULL, log); glDeleteShader(id); asc_error(log); free(log); return (AscShader) {0}; } } AscShader asc_shader_compilef(unsigned int type, char const *filename) { asc_file code = asc_file_mmap_rdonly(filename); if (code.ptr == NULL) { asc_error("Mapping shader file into memory failed"); return (AscShader) {0}; } AscShader ret = asc_shader_compile(type, code.ptr, code.length); asc_file_unmap(code); return ret; } AscShaderProgram asc_shader_link(AscShader vertex, AscShader fragment) { if (vertex.id == 0 || fragment.id == 0) { asc_dprintf("Skip linking shader program - shaders have not been loaded correctly."); return (AscShaderProgram) {0}; } GLint success; GLint id = glCreateProgram(); if (id <= 0) { asc_error("glCreateProgram failed"); return (AscShaderProgram) {0}; } glAttachShader(id, vertex.id); glAttachShader(id, fragment.id); glLinkProgram(id); glGetProgramiv(id, GL_LINK_STATUS, &success); glDetachShader(id, vertex.id); glDetachShader(id, fragment.id); if (success) { asc_dprintf("Shader Program %u linked (vtf: %u, frag: %u)", id, vertex.id, fragment.id); AscShaderProgram prog; prog.id = id; prog.model = glGetUniformLocation(id, "model"); prog.view = glGetUniformLocation(id, "view"); prog.projection = glGetUniformLocation(id, "projection"); return prog; } else { char *log = malloc(1024); glGetProgramInfoLog(id, 1024, NULL, log); glDeleteShader(id); asc_error(log); free(log); return (AscShaderProgram) {0}; } } void asc_shader_destroy(AscShader shader) { if (shader.id > 0) { asc_dprintf("Delete Shader %u", shader.id); glDeleteShader(shader.id); } shader.id = 0; } void asc_shader_program_destroy(AscShaderProgram program) { if (program.id > 0) { asc_dprintf("Delete Shader Program %u", program.id); glDeleteProgram(program.id); } program.id = 0; } static AscShaderProgram asc_shader_compile_link_discard( char const *vtxName, char const *fragName) { AscShader font_vtx = asc_shader_compilef(GL_VERTEX_SHADER, vtxName); AscShader font_frag = asc_shader_compilef(GL_FRAGMENT_SHADER, fragName); AscShaderProgram prog = asc_shader_link(font_vtx, font_frag); asc_shader_destroy(font_vtx); asc_shader_destroy(font_frag); return prog; } void asc_shader_initialize_predefined(void) { ASC_SHADER_FONT.base = asc_shader_compile_link_discard("shader/font_vtx.glsl", "shader/font_frag.glsl"); ASC_SHADER_FONT.surface = glGetUniformLocation(ASC_SHADER_FONT.base.id, "surface"); } void asc_shader_destroy_predefined(void) { asc_shader_program_destroy(ASC_SHADER_FONT.base); }