glstuff

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 6377884c65418b193716b320c274f489ca5a69ef
Author: Brian Swetland <swetland@frotz.net>
Date:   Sun, 13 Jan 2013 18:32:16 -0800

initial commit

Diffstat:
A.gitignore | 2++
AMakefile | 26++++++++++++++++++++++++++
Acube-texture.png | 0
Acube-texture.xcf | 0
Aextensions.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aglue.h | 35+++++++++++++++++++++++++++++++++++
Aloadfile.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aloadpng.c | 107+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asdlglue.c | 146+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest1.c | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest1.fragment.glsl | 6++++++
Atest1.vertex.glsl | 10++++++++++
Atest2.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atexture1.png | 0
Autil.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autil.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 files changed, 911 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,2 @@ +*.o +.*.swp diff --git a/Makefile b/Makefile @@ -0,0 +1,26 @@ + +SDLCFG := sdl-config +#SDLCFG := /work/sdl/bin/sdl2-config + +SDLFLAGS := $(shell $(SDLCFG) --cflags) +SDLLIBS := $(shell $(SDLCFG) --libs) + +CFLAGS := $(SDLFLAGS) -DWITH_SDL2=0 -Wall +LIBS := $(SDLLIBS) -lGL -lm -lpng + +COMMONOBJS := util.o sdlglue.o loadpng.o loadfile.o + +all: test1 test2 + +TEST1OBJS := test1.o $(COMMONOBJS) + +test1: $(TEST1OBJS) + $(CC) -o test1 $(TEST1OBJS) $(LIBS) + +TEST2OBJS := test2.o $(COMMONOBJS) + +test2: $(TEST2OBJS) + $(CC) -o test2 $(TEST2OBJS) $(LIBS) + +clean:: + rm -f test1 test2 *.o diff --git a/cube-texture.png b/cube-texture.png Binary files differ. diff --git a/cube-texture.xcf b/cube-texture.xcf Binary files differ. diff --git a/extensions.c b/extensions.c @@ -0,0 +1,58 @@ + +/* not needed for linux */ + +static PFNGLATTACHOBJECTARBPROC glAttachObjectARB; +static PFNGLCOMPILESHADERARBPROC glCompileShaderARB; +static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB; +static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB; +static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB; +static PFNGLGETINFOLOGARBPROC glGetInfoLogARB; +static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB; +static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB; +static PFNGLLINKPROGRAMARBPROC glLinkProgramARB; +static PFNGLSHADERSOURCEARBPROC glShaderSourceARB; +static PFNGLUNIFORM1IARBPROC glUniform1iARB; +static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB; + +#define EFUNC(n) { (void**) &n, #n } + +#if !WITH_SDL2 +int SDL_GL_ExtensionSupported(const char *name) { + if (strstr((char*)glGetString(GL_EXTENSIONS), name)) + return 1; + else + return 0; +} +#endif + +struct { + void **func; + const char *name; +} fntb[] = { + EFUNC(glAttachObjectARB), + EFUNC(glCompileShaderARB), + EFUNC(glCreateProgramObjectARB), + EFUNC(glCreateShaderObjectARB), + EFUNC(glDeleteObjectARB), + EFUNC(glGetInfoLogARB), + EFUNC(glGetObjectParameterivARB), + EFUNC(glGetUniformLocationARB), + EFUNC(glLinkProgramARB), + EFUNC(glShaderSourceARB), + EFUNC(glUniform1iARB), + EFUNC(glUseProgramObjectARB), +}; + +void glsl_init(void) { + int n; + if (!SDL_GL_ExtensionSupported("GL_ARB_shader_objects") || + !SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") || + !SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") || + !SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) + die("missing glsl extensions"); + for (n = 0; n < sizeof(fntb)/sizeof(fntb[0]); n++) { + *fntb[n].func = SDL_GL_GetProcAddress(fntb[n].name); + if (!(*fntb[n].func)) + die("cannot find func '%s'", fntb[n].name); + } +} diff --git a/glue.h b/glue.h @@ -0,0 +1,35 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SDL_GLUE_H_ +#define _SDL_GLUE_H_ + +#define GL_GLEXT_PROTOTYPES 1 + +#include <SDL_opengl.h> + +struct ctxt { + unsigned width; + unsigned height; + void *data; +}; + +int scene_init(struct ctxt *c); +int scene_draw(struct ctxt *c); + +int shader_compile(const char *vshader, const char *fshader, + GLuint *pgm, GLuint *vshd, GLuint *fshd); + +#endif diff --git a/loadfile.c b/loadfile.c @@ -0,0 +1,57 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "util.h" + +void *load_file(const char *fn, unsigned *_sz) { + void *data = 0; + long sz; + FILE *fp; + + if(!(fp = fopen(fn, "rb"))) + goto exit; + + if (fseek(fp, 0, SEEK_END)) + goto close_and_exit; + + if ((sz = ftell(fp)) < 0) + goto close_and_exit; + + if (fseek(fp, 0, SEEK_SET)) + goto close_and_exit; + + if (!(data = malloc(sz + 1))) + goto close_and_exit; + + if (fread(data, sz, 1, fp) != 1) { + free(data); + data = 0; + } else { + ((char*) data)[sz] = 0; + if (_sz) + *_sz = sz; + } + +close_and_exit: + fclose(fp); +exit: + if (!data) + fprintf(stderr, "failed to load '%s'\n", fn); + return data; +} diff --git a/loadpng.c b/loadpng.c @@ -0,0 +1,107 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <png.h> + +#include "util.h" + +void *load_png_rgba(const char *fn, unsigned *_width, unsigned *_height) { + png_structp png; + png_infop info; + png_uint_32 w, h; + int depth, ctype, itype, i; + png_byte *data = 0; + png_byte **rows = 0; + FILE *fp; + + if ((fp = fopen(fn, "rb")) == NULL) + goto exit; + + if (!(png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0))) + goto close_and_exit; + + if (!(info = png_create_info_struct(png))) { + png_destroy_read_struct(&png, NULL, NULL); + goto destroy_and_exit; + } + + if (setjmp(png->jmpbuf)) { + if (data) { + free(data); + data = 0; + } + goto destroy_and_exit; + } + + png_init_io(png, fp); + + png_read_info(png, info); + + png_get_IHDR(png, info, &w, &h, &depth, &ctype, &itype, NULL, NULL); + + if (depth < 8) + png_set_packing(png); + + if (depth > 8) + png_set_strip_16(png); + + if (ctype == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png); + + if ((ctype == PNG_COLOR_TYPE_GRAY) && (depth < 8)) + png_set_expand(png); + + if (png_get_valid(png, info, PNG_INFO_tRNS)) + png_set_expand(png); + + if ((ctype == PNG_COLOR_TYPE_RGB) || + (ctype == PNG_COLOR_TYPE_GRAY)) + png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER); + + if ((ctype == PNG_COLOR_TYPE_GRAY) || + (ctype == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_set_gray_to_rgb(png); + + + data = malloc(w * h * 4); + rows = malloc(h * sizeof(png_byte*)); + + if (!data || !rows) + png_error(png, "cannot allocate image buffer"); + + for (i = 0; i < h; i++) + rows[h-i-1] = data + (i * w * 4); + + png_read_image(png, rows); + + *_width = w; + *_height = h; + +destroy_and_exit: + if (rows) + free(rows); + png_destroy_read_struct(&png, &info, NULL); + +close_and_exit: + fclose(fp); +exit: + if (!data) + fprintf(stderr,"failed to load '%s'\n", fn); + return data; +} diff --git a/sdlglue.c b/sdlglue.c @@ -0,0 +1,146 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <SDL.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "util.h" +#include "glue.h" + +void die(const char *fmt, ...) { + fprintf(stderr,"ERROR: %s\n", fmt); + exit(-1); +} + +int shader_compile(const char *vshader, const char *fshader, + GLuint *_pgm, GLuint *_vshd, GLuint *_fshd) { + GLint r; + GLuint pgm, vshd, fshd; + + pgm = glCreateProgram(); + vshd = glCreateShader(GL_VERTEX_SHADER); + fshd = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(vshd, 1, &vshader, NULL); + glShaderSource(fshd, 1, &fshader, NULL); + glCompileShader(vshd); + glCompileShader(fshd); + glAttachShader(pgm, vshd); + glAttachShader(pgm, fshd); +// glBindAttribLocation(pgm, 0, "vPosition"); + glLinkProgram(pgm); + + glGetProgramiv(pgm, GL_LINK_STATUS, &r); + + if (!r) { + GLint len; + char *buf; + glGetProgramiv(pgm, GL_INFO_LOG_LENGTH, &len); + buf = malloc(len + 1); + memset(buf, 0, len); + if (buf != 0) { + glGetProgramInfoLog(pgm, len, &len, buf); + buf[len] = 0; + fprintf(stderr,"<< Shader Compiler Error >>\n%s\n",buf); + free(buf); + } + return -1; + } else { + *_pgm = pgm; + *_vshd = vshd; + *_fshd = fshd; + return 0; + } +} + +void handle_events(void) { + SDL_Event ev; + + while (SDL_PollEvent(&ev)) { + switch (ev.type) { + case SDL_KEYDOWN: + case SDL_QUIT: + SDL_Quit(); + exit(0); + } + } +} + +int main(int argc, char **argv) { + struct ctxt c; +#if WITH_SDL2 + SDL_Window *w; + SDL_GLContext gc; +#endif + + c.width = 640; + c.height = 480; + c.data = 0; + + if (SDL_Init(SDL_INIT_VIDEO)) + die("sdl video init failed"); + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); + SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32); + +#if 0 + SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8); + + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 2); +#endif + +#if WITH_SDL2 + if (!(w = SDL_CreateWindow("Test", 0, 0, c.width, c.height, + SDL_WINDOW_OPENGL))) + die("sdl cannot create window"); + + if (!(gc = SDL_GL_CreateContext(w))) + die("sdl cannot create gl context"); +#else + if (SDL_SetVideoMode(c.width, c.height, 32, + SDL_HWSURFACE | SDL_GL_DOUBLEBUFFER | SDL_OPENGL) == NULL) + die("sdl cannot set mode"); +#endif + + if (scene_init(&c)) + return -1; + + for (;;) { + handle_events(); + + if (scene_draw(&c)) + return -1; + +#if WITH_SDL2 + SDL_GL_SwapWindow(w); +#else + SDL_GL_SwapBuffers(); +#endif + } + + return 0; +} + diff --git a/test1.c b/test1.c @@ -0,0 +1,109 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "util.h" +#include "glue.h" + +void *texdata; +unsigned texw, texh; + +const char *vert_src, *frag_src; + +GLuint pgm, vshd, fshd, tex0; +GLuint _vPosition, _vUV; +GLuint _uMVP, _uSampler; + +mat4 MVP; + +GLfloat verts[] = { + -0.5f, -0.5f, 0.0f, + -0.5f, 0.5f, 0.0f, + 0.5f, -0.5f, 0.0f, + 0.5f, 0.5f, 0.0f, +}; + +GLfloat texcoords[] = { + 0.0, 0.0, + 0.0, 1.0, + 1.0, 0.0, + 1.0, 1.0, +}; + +int scene_init(struct ctxt *c) { + if (!(texdata = load_png_rgba("texture1.png", &texw, &texh))) + return -1; + if (!(vert_src = load_file("test1.vertex.glsl", 0))) + return -1; + if (!(frag_src = load_file("test1.fragment.glsl", 0))) + return -1; + + mtx_identity(MVP); + mtx_ortho(MVP, -2.66, 2.66, -2, 2, 1, -1); + + glViewport(0, 0, c->width, c->height); + glClearColor(0, 0, 0, 0); + glClearDepth(1.0f); + + if (shader_compile(vert_src, frag_src, &pgm, &vshd, &fshd)) + return -1; + + _vPosition = glGetAttribLocation(pgm, "vPosition"); + _vUV = glGetAttribLocation(pgm, "vUV"); + _uMVP = glGetUniformLocation(pgm, "uMVP"); + _uSampler = glGetUniformLocation(pgm, "uSampler"); + + if(glGetError() != GL_NO_ERROR) fprintf(stderr,"OOPS!\n"); + + glEnable(GL_TEXTURE_2D); +// glEnable(GL_BLEND); +// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glGenTextures(1, &tex0); + + glBindTexture(GL_TEXTURE_2D, tex0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, + GL_UNSIGNED_BYTE, texdata); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + return 0; +} + +int scene_draw(struct ctxt *c) { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glLoadIdentity(); + glUseProgram(pgm); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex0); + + glUniformMatrix4fv(_uMVP, 1, GL_FALSE, (void*) MVP); + glUniform1i(_uSampler, 0); + + glVertexAttribPointer(_vPosition, 3, GL_FLOAT, GL_FALSE, 0, verts); + glEnableVertexAttribArray(_vPosition); + + glVertexAttribPointer(_vUV, 2, GL_FLOAT, GL_FALSE, 0, texcoords); + glEnableVertexAttribArray(_vUV); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + return 0; +} + diff --git a/test1.fragment.glsl b/test1.fragment.glsl @@ -0,0 +1,6 @@ +uniform sampler2D uSampler; +varying vec2 fUV; + +void main() { + gl_FragColor = texture2D(uSampler, fUV); +} diff --git a/test1.vertex.glsl b/test1.vertex.glsl @@ -0,0 +1,10 @@ +uniform mat4 uMVP; +attribute vec4 vPosition; +attribute vec2 vUV; +varying vec2 fUV; + +void main() { + gl_Position = uMVP * vPosition; + fUV = vUV; +} + diff --git a/test2.c b/test2.c @@ -0,0 +1,158 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "util.h" +#include "glue.h" + +#include <math.h> + +void *texdata; +unsigned texw, texh; + +const char *vert_src, *frag_src; + +GLuint pgm, vshd, fshd, tex0; +GLuint _vPosition, _vUV; +GLuint _uMVP, _uSampler; + +mat4 perspective; +mat4 MVP; + +float a = 0.0; + +GLfloat data[] = { + -0.5f, 0.5f, 0.5f, 0.25, 0.75, + -0.5f, -0.5f, 0.5f, 0.25, 0.50, + 0.5f, -0.5f, 0.5f, 0.50, 0.50, + 0.5f, 0.5f, 0.5f, 0.50, 0.75, + + 0.5f, 0.5f, 0.5f, 0.50, 0.75, + 0.5f, -0.5f, 0.5f, 0.50, 0.50, + 0.5f, -0.5f, -0.5f, 0.75, 0.50, + 0.5f, 0.5f, -0.5f, 0.75, 0.75, + + 0.5f, 0.5f, -0.5f, 0.75, 0.75, + 0.5f, -0.5f, -0.5f, 0.75, 0.50, + -0.5f, -0.5f, -0.5f, 1.00, 0.50, + -0.5f, 0.5f, -0.5f, 1.00, 0.75, + + -0.5f, 0.5f, -0.5f, 0.00, 0.75, + -0.5f, -0.5f, -0.5f, 0.00, 0.50, + -0.5f, -0.5f, 0.5f, 0.25, 0.50, + -0.5f, 0.5f, 0.5f, 0.25, 0.75, + + -0.5f, 0.5f, -0.5f, 0.25, 1.00, + -0.5f, 0.5f, 0.5f, 0.25, 0.75, + 0.5f, 0.5f, 0.5f, 0.50, 0.75, + 0.5f, 0.5f, -0.5f, 0.50, 1.00, + + -0.5f, -0.5f, 0.5f, 0.25, 0.50, + -0.5f, -0.5f, -0.5f, 0.25, 0.25, + 0.5f, -0.5f, -0.5f, 0.50, 0.25, + 0.5f, -0.5f, 0.5f, 0.50, 0.50, +}; + +GLubyte indices[] = { + 0, 1, 2, 3, 0, 2, + 4, 5, 6, 7, 4, 6, + 8, 9, 10, 11, 8, 10, + 12, 13, 14, 15, 12, 14, + 16, 17, 18, 19, 16, 18, + 20, 21, 22, 23, 20, 22, +}; + +int scene_init(struct ctxt *c) { + float aspect = ((float) c->width) / ((float) c->height); + + if (!(texdata = load_png_rgba("cube-texture.png", &texw, &texh))) + return -1; + if (!(vert_src = load_file("test1.vertex.glsl", 0))) + return -1; + if (!(frag_src = load_file("test1.fragment.glsl", 0))) + return -1; + + mtx_identity(MVP); + mtx_perspective(perspective, 60.0, aspect, 1.0, 10.0); + + glViewport(0, 0, c->width, c->height); + glClearColor(0, 0, 0, 0); + glClearDepth(1.0f); + + if (shader_compile(vert_src, frag_src, &pgm, &vshd, &fshd)) + return -1; + + _vPosition = glGetAttribLocation(pgm, "vPosition"); + _vUV = glGetAttribLocation(pgm, "vUV"); + _uMVP = glGetUniformLocation(pgm, "uMVP"); + _uSampler = glGetUniformLocation(pgm, "uSampler"); + + if(glGetError() != GL_NO_ERROR) fprintf(stderr,"OOPS!\n"); + + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); +// glEnable(GL_BLEND); +// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + glGenTextures(1, &tex0); + + glBindTexture(GL_TEXTURE_2D, tex0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texw, texh, 0, GL_RGBA, + GL_UNSIGNED_BYTE, texdata); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + return 0; +} + +int scene_draw(struct ctxt *c) { + mat4 camera; + + mtx_identity(camera); + mtx_translate(camera, 0, 0, -3.0); + mtx_rotate_y(camera, a); + mtx_rotate_x(camera, 25.0); + + mtx_mul_unsafe(MVP, camera, perspective); + + a += 1.0; + if (a > 360.0) a = 0.0; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glUseProgram(pgm); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex0); + + glUniformMatrix4fv(_uMVP, 1, GL_FALSE, (void*) MVP); + glUniform1i(_uSampler, 0); + + glVertexAttribPointer(_vPosition, 3, GL_FLOAT, GL_FALSE, 5*4, data); + glEnableVertexAttribArray(_vPosition); + + glVertexAttribPointer(_vUV, 2, GL_FLOAT, GL_FALSE, 5*4, data + 3); + glEnableVertexAttribArray(_vUV); + + glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices); + + return 0; +} + diff --git a/texture1.png b/texture1.png Binary files differ. diff --git a/util.c b/util.c @@ -0,0 +1,141 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <math.h> +#include <string.h> + +#include "util.h" + +void mtx_mul_unsafe(mat4 m, mat4 a, mat4 b) { + int i; + for (i = 0; i < 4; i++) { + m[i][0] = (a[i][0] * b[0][0]) + + (a[i][1] * b[1][0]) + + (a[i][2] * b[2][0]) + + (a[i][3] * b[3][0]); + m[i][1] = (a[i][0] * b[0][1]) + + (a[i][1] * b[1][1]) + + (a[i][2] * b[2][1]) + + (a[i][3] * b[3][1]); + m[i][2] = (a[i][0] * b[0][2]) + + (a[i][1] * b[1][2]) + + (a[i][2] * b[2][2]) + + (a[i][3] * b[3][2]); + m[i][3] = (a[i][0] * b[0][3]) + + (a[i][1] * b[1][3]) + + (a[i][2] * b[2][3]) + + (a[i][3] * b[3][3]); + } +} + +void mtx_mul(mat4 m, mat4 a, mat4 b) { + mat4 t; + mtx_mul_unsafe(t, a, b); + memcpy(m, t, sizeof(mat4)); +} + +void mtx_identity(mat4 m) { + memset(m, 0, sizeof(mat4)); + m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; +} + +void mtx_translate(mat4 m, float x, float y, float z) { + m[3][0] += (m[0][0] * x + m[1][0] * y + m[2][0] * z); + m[3][1] += (m[0][1] * x + m[1][1] * y + m[2][1] * z); + m[3][2] += (m[0][2] * x + m[1][2] * y + m[2][2] * z); + m[3][3] += (m[0][3] * x + m[1][3] * y + m[2][3] * z); +} + +void mtx_rotate_x(mat4 m, float angle) { + mat4 r; + float sa,ca; + angle = angle * M_PI / 180.0; + sa = sinf(angle); + ca = cosf(angle); + memset(r, 0, sizeof(mat4)); + r[0][0] = 1; + r[1][1] = ca; + r[1][2] = -sa; + r[2][1] = sa; + r[2][2] = ca; + r[3][3] = 1; + mtx_mul(m, r, m); +} + +void mtx_rotate_y(mat4 m, float angle) { + mat4 r; + float sa,ca; + angle = angle * M_PI / 180.0; + sa = sinf(angle); + ca = cosf(angle); + memset(r, 0, sizeof(mat4)); + r[0][0] = ca; + r[0][2] = sa; + r[1][1] = 1; + r[2][0] = -sa; + r[2][2] = ca; + r[3][3] = 1; + mtx_mul(m, r, m); +} + +void mtx_rotate_z(mat4 m, float angle) { + mat4 r; + float sa,ca; + angle = angle * M_PI / 180.0; + sa = sinf(angle); + ca = cosf(angle); + memset(r, 0, sizeof(mat4)); + r[0][0] = ca; + r[0][1] = -sa; + r[1][0] = sa; + r[1][1] = ca; + r[2][2] = 1; + r[3][3] = 1; + mtx_mul(m, r, m); +} + +void mtx_frustum(mat4 m, float left, float right, float bottom, float top, float znear, float zfar) { + float znear2 = 2.0 * znear; + float width = right - left; + float height = top - bottom; + float depth = zfar - znear; + memset(m, 0, sizeof(mat4)); + m[0][0] = znear2 / width; + m[1][1] = znear2 / height; + m[2][0] = (right + left) / width; + m[2][1] = (top + bottom) / height; + m[2][2] = (-zfar - znear) / depth; + m[2][3] = -1.0; + m[3][2] = (-znear2 * zfar) / depth; +} + +void mtx_perspective(mat4 m, float fov, float aspect, float znear, float zfar) { + float ymax, xmax; + ymax = znear * tanf(fov * M_PI / 360.0); + xmax = ymax * aspect; + mtx_frustum(m, -xmax, xmax, -ymax, ymax, znear, zfar); +} + +void mtx_ortho(mat4 m, float l, float r, float b, float t, float n, float f) { + memset(m, 0, sizeof(mat4)); + m[0][0] = 2.0 / (r - l); + m[1][1] = 2.0 / (t - b); + m[2][2] = -2.0 / (f - n); + m[3][0] = -((r + l) / (r - l)); + m[3][1] = -((t + b) / (t - b)); + m[3][2] = -((f + n) / (f - n)); + m[3][3] = 1.0; +} + diff --git a/util.h b/util.h @@ -0,0 +1,56 @@ +/* Copyright 2013 Brian Swetland <swetland@frotz.net> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _UTIL_H_ +#define _UTIL_H_ + +typedef float mat4[4][4]; +typedef float vec4[4]; + +/* load the identity matrix */ +void mtx_identity(mat4 out); + +/* out = left * right */ +void mtx_mul(mat4 out, mat4 left, mat4 right); + +/* avoids a copy, but out and left may not be the same */ +void mtx_mul_unsafe(mat4 out, mat4 left, mat4 right); + +/* applies the transform to out */ +void mtx_translate(mat4 out, float x, float y, float z); +void mtx_rotate_x(mat4 out, float angle); +void mtx_rotate_y(mat4 out, float angle); +void mtx_rotate_z(mat4 out, float angle); + +/* GLU-style perspective matrix helper functions */ +void mtx_ortho(mat4 out, + float left, float right, + float bottom, float top, + float near, float far); + +void mtx_frustum(mat4 out, + float left, float right, float bottom, float top, + float znear, float zfar); + +void mtx_perspective(mat4 out, + float fov_degrees, float aspect_ratio, + float znear, float zfar); + +/* file io helpers */ +void *load_png_rgba(const char *fn, unsigned *width, unsigned *height); +void *load_file(const char *fn, unsigned *sz); + +#endif +