diff options
Diffstat (limited to 'src/tex.c')
-rw-r--r-- | src/tex.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/tex.c b/src/tex.c new file mode 100644 index 0000000..b8254e1 --- /dev/null +++ b/src/tex.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2020 - Vito Caputo - <vcaputo@pengaru.com> + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <stdlib.h> + +#include "glad.h" +#include "m4f.h" +#include "macros.h" +#include "shader.h" +#include "tex.h" + +typedef struct tex_t { + unsigned tex; + unsigned refcnt; +} tex_t; + +static unsigned vbo, tcbo; +static shader_t *tex_shader; + +static const float vertices[] = { + +1.f, +1.f, 0.f, + +1.f, -1.f, 0.f, + -1.f, +1.f, 0.f, + +1.f, -1.f, 0.f, + -1.f, -1.f, 0.f, + -1.f, +1.f, 0.f, +}; + +static const float texcoords[] = { + 1.f, 0.f, + 1.f, 1.f, + 0.f, 0.f, + 1.f, 1.f, + 0.f, 1.f, + 0.f, 0.f, +}; + + +static const char *tex_vs = "" + "#version 120\n" + + "uniform mat4 model_x;" + + "attribute vec3 vertex;" + "attribute vec2 texcoord;" + + "void main()" + "{" + " gl_TexCoord[0].xy = texcoord;" + " gl_Position = model_x * vec4(vertex, 1.f);" + "}" +""; + + +static const char *tex_fs = "" + "#version 120\n" + + "uniform sampler2D tex0;" + "uniform float alpha;" + + "void main()" + "{" + " gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);" + " gl_FragColor.a *= alpha;" + "}" +""; + + +/* Render simply renders a texd texture onto the screen */ +void tex_render(tex_t *tex, float alpha, m4f_t *model_x) +{ + int *uniforms, *attributes; + + assert(tex); + assert(model_x); + + shader_use(tex_shader, NULL, &uniforms, NULL, &attributes); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glVertexAttribPointer(attributes[0], 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); + glEnableVertexAttribArray(attributes[0]); + + glBindBuffer(GL_ARRAY_BUFFER, tcbo); + glVertexAttribPointer(attributes[1], 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); + glEnableVertexAttribArray(attributes[1]); + + glBindTexture(GL_TEXTURE_2D, tex->tex); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glUniform1f(uniforms[0], alpha); + glUniformMatrix4fv(uniforms[1], 1, GL_FALSE, &model_x->m[0][0]); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glBindTexture(GL_TEXTURE_2D, 0); + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + + +tex_t * tex_new(int width, int height, const unsigned char *buf) +{ + tex_t *tex; + + assert(buf); + + if (!vbo) { + /* common to all tex instances */ + tex_shader = shader_pair_new(tex_vs, tex_fs, + 2, + (const char *[]) { + "alpha", + "model_x", + }, + 2, + (const char *[]) { + "vertex", + "texcoord", + }); + + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + glGenBuffers(1, &tcbo); + glBindBuffer(GL_ARRAY_BUFFER, tcbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + tex = calloc(1, sizeof(tex_t)); + fatal_if(!tex, "Unable to allocate tex_t"); + + glGenTextures(1, &tex->tex); + glBindTexture(GL_TEXTURE_2D, tex->tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); + glBindTexture(GL_TEXTURE_2D, 0); + + tex->refcnt = 1; + + return tex; +} + + +tex_t * tex_ref(tex_t *tex) +{ + assert(tex); + + tex->refcnt++; + + return tex; +} + + +tex_t * tex_free(tex_t *tex) +{ + if (!tex) + return NULL; + + assert(tex->refcnt > 0); + + tex->refcnt--; + if (!tex->refcnt) { + glDeleteTextures(1, &tex->tex); + free(tex); + } + + return NULL; +} |