diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-04-19 16:07:21 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-04-19 16:07:21 -0700 |
commit | 308d0ee789659778210662ca9156981944452ccc (patch) | |
tree | 1e2021b57e96c25f0f69326e9f1cfac73dc1a347 /src/tex.c | |
parent | c068006e340c83fe7099b0e63daf33dbd94b9432 (diff) |
src: implement a game for Blender 2020
The theme of this Blender was:
Monkeys / Rescuing / Between Realities
With all the COVID-19 stuff going on, it seemed like a fun way
to lighten things up a bit to make something where a monkey runs
around trying to rescue child monkeys from coronaviruses moving
across the playfield. In keeping with the theme, to rescue the
helpless monkeys you take them to a different reality by carrying
them off the window/screen. As infections increase the field
becomes crowded with viruses until your player becomes infected
through contact, ending your game.
This was written quickly kamikaze style overnight. Some
scaffolding bits came from past projects of mine like the vector
headers, shader and texture node building blocks, and the plasma
effect has been used a few times now and originally was derived
from some gpu programming tutorial if memory serves. I just
wanted to put something in the background for this strange
reality.
This is the first time I've used libplay, in fact, it was
basically slapped together last night at the start of this to
avoid having to do all that SDL initialization all over again.
The unique meat of this work is in game.c, there isn't really all
that much to this game though. It's not pretty code, but it
works well enough and this task served as a useful exercise of
trying to get some quick game dev done using this collection of
facilities.
Most the heavy lifting comes from my reused libraries which are
slowly evolving into something somewhat effective for simple game
development.
Enjoy, and happy hacking!
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; +} |