oculus2_psprite
changeset 21:dc7af0f549b2
VR point sprite shooting test
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 22 Jan 2015 06:19:52 +0200 |
parents | 6a3a9840c303 |
children | fdfb911879df |
files | Makefile sdr/psprite.p.glsl sdr/psprite.v.glsl src/main.c src/projectile.c src/projectile.h src/sdr.c src/sdr.h |
diffstat | 8 files changed, 866 insertions(+), 39 deletions(-) [+] |
line diff
1.1 --- a/Makefile Wed Jan 21 11:29:30 2015 +0200 1.2 +++ b/Makefile Thu Jan 22 06:19:52 2015 +0200 1.3 @@ -2,11 +2,14 @@ 1.4 obj = $(src:.c=.o) 1.5 bin = oculus2 1.6 1.7 -CFLAGS = -pedantic -Wall -g `pkg-config --cflags sdl2` 1.8 -LDFLAGS = $(libgl) `pkg-config --libs sdl2` -lovr $(libsys) 1.9 +warn = -pedantic -Wall 1.10 + 1.11 +CFLAGS = $(warn) -g `pkg-config --cflags sdl2` 1.12 +LDFLAGS = $(libgl) `pkg-config --libs sdl2` -lovr $(libsys) -lvmath 1.13 1.14 ifeq ($(shell uname -s), Darwin) 1.15 libgl = -framework OpenGL -lGLEW 1.16 + warn += -Wno-deprecated-declarations 1.17 else 1.18 libgl = -lGL -lGLU -lGLEW 1.19 libsys = -lX11
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/sdr/psprite.p.glsl Thu Jan 22 06:19:52 2015 +0200 2.3 @@ -0,0 +1,12 @@ 2.4 +#version 120 2.5 + 2.6 +void main() 2.7 +{ 2.8 + vec2 pt = gl_PointCoord.xy * 2.0 - 1.0; 2.9 + float len = length(pt); 2.10 + vec2 dir = pt / len; 2.11 + float angle = atan(dir.y, dir.x); 2.12 + 2.13 + float alpha = 1.0 - smoothstep(0.8, 0.9, len + abs(sin(angle * 8.0)) * 0.1); 2.14 + gl_FragColor = vec4(1.0, 1.0, 1.0, alpha); 2.15 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr/psprite.v.glsl Thu Jan 22 06:19:52 2015 +0200 3.3 @@ -0,0 +1,22 @@ 3.4 +uniform vec2 viewport; 3.5 + 3.6 +void main() 3.7 +{ 3.8 + const float psize = 1.0; 3.9 + 3.10 + vec4 ppos = gl_ModelViewProjectionMatrix * gl_Vertex; 3.11 + gl_Position = ppos; 3.12 + 3.13 + float vs_z = (gl_ModelViewMatrix * gl_Vertex).z; 3.14 + vec4 p0 = gl_ProjectionMatrix * vec4(0.0, 0.0, vs_z, 1.0); 3.15 + vec4 p1 = gl_ProjectionMatrix * vec4(psize, 0.0, vs_z, 1.0); 3.16 + 3.17 + p0.xyz /= p0.w; 3.18 + p1.xyz /= p1.w; 3.19 + 3.20 + p0.xy = (p0.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5)) * viewport; 3.21 + p1.xy = (p1.xy * vec2(0.5, 0.5) + vec2(0.5, 0.5)) * viewport; 3.22 + 3.23 + float sz = length(p1.xy - p0.xy); 3.24 + gl_PointSize = sz; 3.25 +}
4.1 --- a/src/main.c Wed Jan 21 11:29:30 2015 +0200 4.2 +++ b/src/main.c Thu Jan 22 06:19:52 2015 +0200 4.3 @@ -1,11 +1,3 @@ 4.4 -/* Very simple OculusSDK OpenGL usage example. 4.5 - * 4.6 - * Uses SDL2 (www.libsdl.org) for event handling and OpenGL context management. 4.7 - * Uses GLEW (glew.sourceforge.net) for OpenGL extension wrangling. 4.8 - * 4.9 - * Author: John Tsiombikas <nuclear@member.fsf.org> 4.10 - * This code is in the public domain. Do whatever you like with it. 4.11 - */ 4.12 #include <stdio.h> 4.13 #include <stdlib.h> 4.14 #include <assert.h> 4.15 @@ -24,11 +16,16 @@ 4.16 4.17 #include <OVR_CAPI.h> 4.18 #include <OVR_CAPI_GL.h> 4.19 +#include "projectile.h" 4.20 + 4.21 +#define GUN_Y 1.5 4.22 4.23 int init(void); 4.24 +int init_rift(void); 4.25 void cleanup(void); 4.26 void toggle_hmd_fullscreen(void); 4.27 void display(void); 4.28 +void display_rift(void); 4.29 void draw_scene(void); 4.30 void draw_box(float xsz, float ysz, float zsz, float norm_sign); 4.31 void update_rtarg(int width, int height); 4.32 @@ -38,6 +35,7 @@ 4.33 unsigned int next_pow2(unsigned int x); 4.34 void quat_to_matrix(const float *quat, float *mat); 4.35 unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1); 4.36 +int parse_args(int argc, char **argv); 4.37 4.38 /* forward declaration to avoid including non-public headers of libovr */ 4.39 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enable); 4.40 @@ -50,6 +48,7 @@ 4.41 static int fb_width, fb_height; 4.42 static int fb_tex_width, fb_tex_height; 4.43 4.44 +static int use_rift = 1; 4.45 static ovrHmd hmd; 4.46 static ovrSizei eyeres[2]; 4.47 static ovrEyeRenderDesc eye_rdesc[2]; 4.48 @@ -60,9 +59,16 @@ 4.49 4.50 static unsigned int chess_tex; 4.51 4.52 +static float cam_theta, cam_phi; 4.53 + 4.54 4.55 int main(int argc, char **argv) 4.56 { 4.57 + unsigned int msec, prev_frame_msec; 4.58 + 4.59 + if(parse_args(argc, argv) == -1) { 4.60 + return 1; 4.61 + } 4.62 if(init() == -1) { 4.63 return 1; 4.64 } 4.65 @@ -74,7 +80,16 @@ 4.66 goto done; 4.67 } 4.68 } 4.69 - display(); 4.70 + 4.71 + msec = SDL_GetTicks(); 4.72 + update_shots((msec - prev_frame_msec) / 1000.0); 4.73 + prev_frame_msec = msec; 4.74 + 4.75 + if(use_rift) { 4.76 + display_rift(); 4.77 + } else { 4.78 + display(); 4.79 + } 4.80 } 4.81 4.82 done: 4.83 @@ -85,11 +100,13 @@ 4.84 4.85 int init(void) 4.86 { 4.87 - int i, x, y; 4.88 + int x, y; 4.89 unsigned int flags; 4.90 4.91 - /* libovr must be initialized before we create the OpenGL context */ 4.92 - ovr_Initialize(); 4.93 + if(use_rift) { 4.94 + /* libovr must be initialized before we create the OpenGL context */ 4.95 + ovr_Initialize(); 4.96 + } 4.97 4.98 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); 4.99 4.100 @@ -106,6 +123,31 @@ 4.101 4.102 glewInit(); 4.103 4.104 + if(use_rift && init_rift() == -1) { 4.105 + return -1; 4.106 + } 4.107 + 4.108 + if(init_shots() == -1) { 4.109 + return -1; 4.110 + } 4.111 + 4.112 + glEnable(GL_DEPTH_TEST); 4.113 + glEnable(GL_CULL_FACE); 4.114 + glEnable(GL_LIGHTING); 4.115 + glEnable(GL_LIGHT0); 4.116 + glEnable(GL_LIGHT1); 4.117 + glEnable(GL_NORMALIZE); 4.118 + 4.119 + glClearColor(0.1, 0.1, 0.1, 1); 4.120 + 4.121 + chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0); 4.122 + return 0; 4.123 +} 4.124 + 4.125 +int init_rift(void) 4.126 +{ 4.127 + int i; 4.128 + 4.129 if(!(hmd = ovrHmd_Create(0))) { 4.130 fprintf(stderr, "failed to open Oculus HMD, falling back to virtual debug HMD\n"); 4.131 if(!(hmd = ovrHmd_CreateDebug(ovrHmd_DK2))) { 4.132 @@ -192,26 +234,17 @@ 4.133 4.134 /* disable the retarded "health and safety warning" */ 4.135 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); 4.136 - 4.137 - glEnable(GL_DEPTH_TEST); 4.138 - glEnable(GL_CULL_FACE); 4.139 - glEnable(GL_LIGHTING); 4.140 - glEnable(GL_LIGHT0); 4.141 - glEnable(GL_LIGHT1); 4.142 - glEnable(GL_NORMALIZE); 4.143 - 4.144 - glClearColor(0.1, 0.1, 0.1, 1); 4.145 - 4.146 - chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0); 4.147 return 0; 4.148 } 4.149 4.150 void cleanup(void) 4.151 { 4.152 - if(hmd) { 4.153 - ovrHmd_Destroy(hmd); 4.154 + if(use_rift) { 4.155 + if(hmd) { 4.156 + ovrHmd_Destroy(hmd); 4.157 + } 4.158 + ovr_Shutdown(); 4.159 } 4.160 - ovr_Shutdown(); 4.161 4.162 SDL_Quit(); 4.163 } 4.164 @@ -226,18 +259,22 @@ 4.165 * to the rift's part of the desktop before going fullscreen 4.166 */ 4.167 SDL_GetWindowPosition(win, &prev_x, &prev_y); 4.168 - SDL_SetWindowPosition(win, hmd->WindowsPos.x, hmd->WindowsPos.y); 4.169 + if(use_rift) { 4.170 + SDL_SetWindowPosition(win, hmd->WindowsPos.x, hmd->WindowsPos.y); 4.171 + } 4.172 SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP); 4.173 4.174 #ifdef OVR_OS_LINUX 4.175 - /* on linux for now we have to deal with screen rotation during rendering. The docs are promoting 4.176 - * not rotating the DK2 screen globally 4.177 - */ 4.178 - glcfg.OGL.Header.BackBufferSize.w = hmd->Resolution.h; 4.179 - glcfg.OGL.Header.BackBufferSize.h = hmd->Resolution.w; 4.180 + if(use_rift) { 4.181 + /* on linux for now we have to deal with screen rotation during rendering. The docs are promoting 4.182 + * not rotating the DK2 screen globally 4.183 + */ 4.184 + glcfg.OGL.Header.BackBufferSize.w = hmd->Resolution.h; 4.185 + glcfg.OGL.Header.BackBufferSize.h = hmd->Resolution.w; 4.186 4.187 - distort_caps |= ovrDistortionCap_LinuxDevFullscreen; 4.188 - ovrHmd_ConfigureRendering(hmd, &glcfg.Config, distort_caps, hmd->DefaultEyeFov, eye_rdesc); 4.189 + distort_caps |= ovrDistortionCap_LinuxDevFullscreen; 4.190 + ovrHmd_ConfigureRendering(hmd, &glcfg.Config, distort_caps, hmd->DefaultEyeFov, eye_rdesc); 4.191 + } 4.192 #endif 4.193 } else { 4.194 /* return to windowed mode and move the window back to its original position */ 4.195 @@ -245,16 +282,38 @@ 4.196 SDL_SetWindowPosition(win, prev_x, prev_y); 4.197 4.198 #ifdef OVR_OS_LINUX 4.199 - glcfg.OGL.Header.BackBufferSize = hmd->Resolution; 4.200 + if(use_rift) { 4.201 + glcfg.OGL.Header.BackBufferSize = hmd->Resolution; 4.202 4.203 - distort_caps &= ~ovrDistortionCap_LinuxDevFullscreen; 4.204 - ovrHmd_ConfigureRendering(hmd, &glcfg.Config, distort_caps, hmd->DefaultEyeFov, eye_rdesc); 4.205 + distort_caps &= ~ovrDistortionCap_LinuxDevFullscreen; 4.206 + ovrHmd_ConfigureRendering(hmd, &glcfg.Config, distort_caps, hmd->DefaultEyeFov, eye_rdesc); 4.207 + } 4.208 #endif 4.209 } 4.210 } 4.211 4.212 void display(void) 4.213 { 4.214 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4.215 + 4.216 + glMatrixMode(GL_PROJECTION); 4.217 + glLoadIdentity(); 4.218 + gluPerspective(50.0, (float)win_width / (float)win_height, 0.5, 500.0); 4.219 + 4.220 + glMatrixMode(GL_MODELVIEW); 4.221 + glLoadIdentity(); 4.222 + glRotatef(cam_phi, 1, 0, 0); 4.223 + glRotatef(cam_theta, 0, 1, 0); 4.224 + glTranslatef(0, -1.6, 0); /* player height */ 4.225 + 4.226 + draw_scene(); 4.227 + 4.228 + SDL_GL_SwapWindow(win); 4.229 + assert(glGetError() == GL_NO_ERROR); 4.230 +} 4.231 + 4.232 +void display_rift(void) 4.233 +{ 4.234 int i; 4.235 ovrMatrix4f proj; 4.236 ovrPosef pose[2]; 4.237 @@ -330,6 +389,8 @@ 4.238 { 4.239 win_width = x; 4.240 win_height = y; 4.241 + 4.242 + glViewport(0, 0, x, y); 4.243 } 4.244 4.245 void draw_scene(void) 4.246 @@ -390,6 +451,33 @@ 4.247 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 4.248 draw_box(0.05, 1.2, 6, 1.0); 4.249 draw_box(6, 1.2, 0.05, 1.0); 4.250 + 4.251 + /* draw laser sight */ 4.252 + glPushMatrix(); 4.253 + glTranslatef(0, GUN_Y, 0); 4.254 + glRotatef(-cam_theta, 0, 1, 0); 4.255 + glRotatef(-cam_phi, 1, 0, 0); 4.256 + 4.257 + glPushAttrib(GL_ENABLE_BIT); 4.258 + glDisable(GL_LIGHTING); 4.259 + glEnable(GL_BLEND); 4.260 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 4.261 + 4.262 + glDepthMask(0); 4.263 + glLineWidth(3.0); 4.264 + 4.265 + glBegin(GL_LINES); 4.266 + glColor4f(1.0, 0.2, 0.15, 0.4); 4.267 + glVertex3f(0, 0, 0); 4.268 + glVertex3f(0, 0, -100.0); 4.269 + glEnd(); 4.270 + glLineWidth(1.0); 4.271 + 4.272 + glPopAttrib(); 4.273 + 4.274 + glPopMatrix(); 4.275 + 4.276 + draw_shots(); 4.277 } 4.278 4.279 void draw_box(float xsz, float ysz, float zsz, float norm_sign) 4.280 @@ -486,6 +574,20 @@ 4.281 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height); 4.282 } 4.283 4.284 +void fire(void) 4.285 +{ 4.286 + vec3_t pos = {0, GUN_Y, 0}; 4.287 + vec3_t dir; 4.288 + float theta = DEG_TO_RAD(cam_theta); 4.289 + float phi = DEG_TO_RAD(cam_phi); 4.290 + 4.291 + dir.x = -sin(-theta) * cos(phi); 4.292 + dir.y = -sin(phi); 4.293 + dir.z = -cos(-theta) * cos(phi); 4.294 + 4.295 + shoot(pos, v3_scale(dir, 10.0)); 4.296 +} 4.297 + 4.298 int handle_event(SDL_Event *ev) 4.299 { 4.300 switch(ev->type) { 4.301 @@ -502,6 +604,34 @@ 4.302 case SDL_WINDOWEVENT: 4.303 if(ev->window.event == SDL_WINDOWEVENT_RESIZED) { 4.304 reshape(ev->window.data1, ev->window.data2); 4.305 + } else if(ev->window.event == SDL_WINDOWEVENT_SHOWN) { 4.306 + int xsz, ysz; 4.307 + SDL_GetWindowSize(win, &xsz, &ysz); 4.308 + reshape(xsz, ysz); 4.309 + } 4.310 + break; 4.311 + 4.312 + case SDL_MOUSEBUTTONDOWN: 4.313 + if(ev->button.button == SDL_BUTTON_LEFT) { 4.314 + fire(); 4.315 + } 4.316 + break; 4.317 + 4.318 + case SDL_MOUSEMOTION: 4.319 + { 4.320 + static int prev_x, prev_y; 4.321 + int dx = ev->motion.x - prev_x; 4.322 + int dy = ev->motion.y - prev_y; 4.323 + prev_x = ev->motion.x; 4.324 + prev_y = ev->motion.y; 4.325 + 4.326 + if(ev->motion.state & SDL_BUTTON_RMASK) { 4.327 + cam_theta += dx * 0.5; 4.328 + cam_phi += dy * 0.5; 4.329 + 4.330 + if(cam_phi < -90) cam_phi = -90; 4.331 + if(cam_phi > 90) cam_phi = 90; 4.332 + } 4.333 } 4.334 break; 4.335 4.336 @@ -628,3 +758,23 @@ 4.337 4.338 return tex; 4.339 } 4.340 + 4.341 +int parse_args(int argc, char **argv) 4.342 +{ 4.343 + int i; 4.344 + 4.345 + for(i=1; i<argc; i++) { 4.346 + if(argv[i][0] == '-') { 4.347 + if(strcmp(argv[i], "-novr") == 0) { 4.348 + use_rift = 0; 4.349 + } else { 4.350 + fprintf(stderr, "invalid option: %s\n", argv[i]); 4.351 + return -1; 4.352 + } 4.353 + } else { 4.354 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 4.355 + return -1; 4.356 + } 4.357 + } 4.358 + return 0; 4.359 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/projectile.c Thu Jan 22 06:19:52 2015 +0200 5.3 @@ -0,0 +1,124 @@ 5.4 +#include <stdlib.h> 5.5 +#include <GL/glew.h> 5.6 +#include "projectile.h" 5.7 +#include "sdr.h" 5.8 + 5.9 +#define MAX_DIST_SQ (100.0 * 100.0) 5.10 + 5.11 +struct projectile { 5.12 + vec3_t pos, vel; 5.13 + struct projectile *next; 5.14 +}; 5.15 + 5.16 +static struct projectile *plist, *ptail; 5.17 +static unsigned int prog; 5.18 + 5.19 +int init_shots(void) 5.20 +{ 5.21 + if(!(prog = create_program_load("sdr/psprite.v.glsl", "sdr/psprite.p.glsl"))) { 5.22 + return -1; 5.23 + } 5.24 + return 0; 5.25 +} 5.26 + 5.27 +void shoot(vec3_t orig, vec3_t dir) 5.28 +{ 5.29 + struct projectile *p; 5.30 + 5.31 + if(!(p = malloc(sizeof *p))) { 5.32 + return; 5.33 + } 5.34 + p->pos = orig; 5.35 + p->vel = dir; 5.36 + p->next = 0; 5.37 + 5.38 + if(plist) { 5.39 + ptail->next = p; 5.40 + ptail = p; 5.41 + } else { 5.42 + plist = ptail = p; 5.43 + } 5.44 +} 5.45 + 5.46 +void update_shots(float dt) 5.47 +{ 5.48 + struct projectile dummy, *pp; 5.49 + 5.50 + dummy.next = plist; 5.51 + pp = &dummy; 5.52 + 5.53 + while(pp->next) { 5.54 + struct projectile *p = pp->next; 5.55 + 5.56 + p->pos = v3_add(p->pos, v3_scale(p->vel, dt)); 5.57 + 5.58 + if(v3_length_sq(p->pos) > MAX_DIST_SQ) { 5.59 + void *tmp = p; 5.60 + pp->next = p->next; 5.61 + free(tmp); 5.62 + } else { 5.63 + pp = pp->next; 5.64 + } 5.65 + } 5.66 + 5.67 + plist = dummy.next; 5.68 +} 5.69 + 5.70 +void draw_shots(void) 5.71 +{ 5.72 + int vp[4]; 5.73 + struct projectile *p = plist; 5.74 + 5.75 + glPushAttrib(GL_ENABLE_BIT); 5.76 + 5.77 + glEnable(GL_BLEND); 5.78 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 5.79 + 5.80 + glDepthMask(0); 5.81 + 5.82 + glEnable(GL_POINT_SPRITE); 5.83 + glEnable(GL_PROGRAM_POINT_SIZE); 5.84 + glUseProgram(prog); 5.85 + 5.86 + glGetIntegerv(GL_VIEWPORT, vp); 5.87 + if(set_uniform_float2(prog, "viewport", vp[2], vp[3]) == -1) { 5.88 + fprintf(stderr, "failed to set viewport\n"); 5.89 + } 5.90 + 5.91 + glBegin(GL_POINTS); 5.92 + 5.93 + while(p) { 5.94 + glVertex3f(p->pos.x, p->pos.y, p->pos.z); 5.95 + p = p->next; 5.96 + } 5.97 + 5.98 + glEnd(); 5.99 + 5.100 + glDepthMask(1); 5.101 + 5.102 + glUseProgram(0); 5.103 + glPopAttrib(); 5.104 + 5.105 + 5.106 + glDisable(GL_LIGHTING); 5.107 + glBegin(GL_LINES); 5.108 + glColor3f(0, 1, 0); 5.109 + p = plist; 5.110 + while(p) { 5.111 + float x0 = p->pos.x - 0.5; 5.112 + float y0 = p->pos.y - 0.5; 5.113 + float x1 = p->pos.x + 0.5; 5.114 + float y1 = p->pos.y + 0.5; 5.115 + glVertex3f(x0, y0, p->pos.z); 5.116 + glVertex3f(x1, y0, p->pos.z); 5.117 + glVertex3f(x1, y0, p->pos.z); 5.118 + glVertex3f(x1, y1, p->pos.z); 5.119 + glVertex3f(x1, y1, p->pos.z); 5.120 + glVertex3f(x0, y1, p->pos.z); 5.121 + glVertex3f(x0, y1, p->pos.z); 5.122 + glVertex3f(x0, y0, p->pos.z); 5.123 + p = p->next; 5.124 + } 5.125 + glEnd(); 5.126 + glEnable(GL_LIGHTING); 5.127 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/projectile.h Thu Jan 22 06:19:52 2015 +0200 6.3 @@ -0,0 +1,13 @@ 6.4 +#ifndef PROJECTILE_H_ 6.5 +#define PROJECTILE_H_ 6.6 + 6.7 +#include <vmath/vmath.h> 6.8 + 6.9 +int init_shots(void); 6.10 + 6.11 +void shoot(vec3_t orig, vec3_t dir); 6.12 + 6.13 +void update_shots(float dt); 6.14 +void draw_shots(void); 6.15 + 6.16 +#endif /* PROJECTILE_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/sdr.c Thu Jan 22 06:19:52 2015 +0200 7.3 @@ -0,0 +1,427 @@ 7.4 +/* 7.5 +Printblobs - halftoning display hack 7.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 7.7 + 7.8 +This program is free software: you can redistribute it and/or modify 7.9 +it under the terms of the GNU General Public License as published by 7.10 +the Free Software Foundation, either version 3 of the License, or 7.11 +(at your option) any later version. 7.12 + 7.13 +This program is distributed in the hope that it will be useful, 7.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 7.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 7.16 +GNU General Public License for more details. 7.17 + 7.18 +You should have received a copy of the GNU General Public License 7.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 7.20 +*/ 7.21 +#include <stdio.h> 7.22 +#include <stdlib.h> 7.23 +#include <string.h> 7.24 +#include <errno.h> 7.25 +#include <stdarg.h> 7.26 +#include <assert.h> 7.27 +#include <GL/glew.h> 7.28 + 7.29 +#if defined(unix) || defined(__unix__) 7.30 +#include <unistd.h> 7.31 +#include <sys/stat.h> 7.32 +#endif /* unix */ 7.33 + 7.34 +#include "sdr.h" 7.35 + 7.36 +static const char *sdrtypestr(unsigned int sdrtype); 7.37 + 7.38 +unsigned int create_vertex_shader(const char *src) 7.39 +{ 7.40 + return create_shader(src, GL_VERTEX_SHADER); 7.41 +} 7.42 + 7.43 +unsigned int create_pixel_shader(const char *src) 7.44 +{ 7.45 + return create_shader(src, GL_FRAGMENT_SHADER); 7.46 +} 7.47 + 7.48 +unsigned int create_tessctl_shader(const char *src) 7.49 +{ 7.50 + return create_shader(src, GL_TESS_CONTROL_SHADER); 7.51 +} 7.52 + 7.53 +unsigned int create_tesseval_shader(const char *src) 7.54 +{ 7.55 + return create_shader(src, GL_TESS_EVALUATION_SHADER); 7.56 +} 7.57 + 7.58 +unsigned int create_geometry_shader(const char *src) 7.59 +{ 7.60 + return create_shader(src, GL_GEOMETRY_SHADER); 7.61 +} 7.62 + 7.63 +unsigned int create_shader(const char *src, unsigned int sdr_type) 7.64 +{ 7.65 + unsigned int sdr; 7.66 + int success, info_len; 7.67 + char *info_str = 0; 7.68 + GLenum err; 7.69 + 7.70 + sdr = glCreateShader(sdr_type); 7.71 + assert(glGetError() == GL_NO_ERROR); 7.72 + glShaderSource(sdr, 1, &src, 0); 7.73 + err = glGetError(); 7.74 + assert(err == GL_NO_ERROR); 7.75 + glCompileShader(sdr); 7.76 + assert(glGetError() == GL_NO_ERROR); 7.77 + 7.78 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 7.79 + assert(glGetError() == GL_NO_ERROR); 7.80 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 7.81 + assert(glGetError() == GL_NO_ERROR); 7.82 + 7.83 + if(info_len) { 7.84 + if((info_str = malloc(info_len + 1))) { 7.85 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 7.86 + assert(glGetError() == GL_NO_ERROR); 7.87 + } 7.88 + } 7.89 + 7.90 + if(success) { 7.91 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 7.92 + } else { 7.93 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 7.94 + glDeleteShader(sdr); 7.95 + sdr = 0; 7.96 + } 7.97 + 7.98 + free(info_str); 7.99 + return sdr; 7.100 +} 7.101 + 7.102 +void free_shader(unsigned int sdr) 7.103 +{ 7.104 + glDeleteShader(sdr); 7.105 +} 7.106 + 7.107 +unsigned int load_vertex_shader(const char *fname) 7.108 +{ 7.109 + return load_shader(fname, GL_VERTEX_SHADER); 7.110 +} 7.111 + 7.112 +unsigned int load_pixel_shader(const char *fname) 7.113 +{ 7.114 + return load_shader(fname, GL_FRAGMENT_SHADER); 7.115 +} 7.116 + 7.117 +unsigned int load_tessctl_shader(const char *fname) 7.118 +{ 7.119 + return load_shader(fname, GL_TESS_CONTROL_SHADER); 7.120 +} 7.121 + 7.122 +unsigned int load_tesseval_shader(const char *fname) 7.123 +{ 7.124 + return load_shader(fname, GL_TESS_EVALUATION_SHADER); 7.125 +} 7.126 + 7.127 +unsigned int load_geometry_shader(const char *fname) 7.128 +{ 7.129 + return load_shader(fname, GL_GEOMETRY_SHADER); 7.130 +} 7.131 + 7.132 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 7.133 +{ 7.134 +#if defined(unix) || defined(__unix__) 7.135 + struct stat st; 7.136 +#endif 7.137 + unsigned int sdr; 7.138 + size_t filesize; 7.139 + FILE *fp; 7.140 + char *src; 7.141 + 7.142 + if(!(fp = fopen(fname, "r"))) { 7.143 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 7.144 + return 0; 7.145 + } 7.146 + 7.147 +#if defined(unix) || defined(__unix__) 7.148 + fstat(fileno(fp), &st); 7.149 + filesize = st.st_size; 7.150 +#else 7.151 + fseek(fp, 0, SEEK_END); 7.152 + filesize = ftell(fp); 7.153 + fseek(fp, 0, SEEK_SET); 7.154 +#endif /* unix */ 7.155 + 7.156 + if(!(src = malloc(filesize + 1))) { 7.157 + fclose(fp); 7.158 + return 0; 7.159 + } 7.160 + fread(src, 1, filesize, fp); 7.161 + src[filesize] = 0; 7.162 + fclose(fp); 7.163 + 7.164 + fprintf(stderr, "compiling %s shader: %s... ", sdrtypestr(sdr_type), fname); 7.165 + sdr = create_shader(src, sdr_type); 7.166 + 7.167 + free(src); 7.168 + return sdr; 7.169 +} 7.170 + 7.171 + 7.172 +unsigned int get_vertex_shader(const char *fname) 7.173 +{ 7.174 + return get_shader(fname, GL_VERTEX_SHADER); 7.175 +} 7.176 + 7.177 +unsigned int get_pixel_shader(const char *fname) 7.178 +{ 7.179 + return get_shader(fname, GL_FRAGMENT_SHADER); 7.180 +} 7.181 + 7.182 +unsigned int get_tessctl_shader(const char *fname) 7.183 +{ 7.184 + return get_shader(fname, GL_TESS_CONTROL_SHADER); 7.185 +} 7.186 + 7.187 +unsigned int get_tesseval_shader(const char *fname) 7.188 +{ 7.189 + return get_shader(fname, GL_TESS_EVALUATION_SHADER); 7.190 +} 7.191 + 7.192 +unsigned int get_geometry_shader(const char *fname) 7.193 +{ 7.194 + return get_shader(fname, GL_GEOMETRY_SHADER); 7.195 +} 7.196 + 7.197 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 7.198 +{ 7.199 + unsigned int sdr; 7.200 + if(!(sdr = load_shader(fname, sdr_type))) { 7.201 + return 0; 7.202 + } 7.203 + return sdr; 7.204 +} 7.205 + 7.206 + 7.207 +/* ---- gpu programs ---- */ 7.208 + 7.209 +unsigned int create_program(void) 7.210 +{ 7.211 + unsigned int prog = glCreateProgram(); 7.212 + assert(glGetError() == GL_NO_ERROR); 7.213 + return prog; 7.214 +} 7.215 + 7.216 +unsigned int create_program_link(unsigned int sdr0, ...) 7.217 +{ 7.218 + unsigned int prog, sdr; 7.219 + va_list ap; 7.220 + 7.221 + if(!(prog = create_program())) { 7.222 + return 0; 7.223 + } 7.224 + 7.225 + attach_shader(prog, sdr0); 7.226 + if(glGetError()) { 7.227 + return 0; 7.228 + } 7.229 + 7.230 + va_start(ap, sdr0); 7.231 + while((sdr = va_arg(ap, unsigned int))) { 7.232 + attach_shader(prog, sdr); 7.233 + if(glGetError()) { 7.234 + return 0; 7.235 + } 7.236 + } 7.237 + va_end(ap); 7.238 + 7.239 + if(link_program(prog) == -1) { 7.240 + free_program(prog); 7.241 + return 0; 7.242 + } 7.243 + return prog; 7.244 +} 7.245 + 7.246 +unsigned int create_program_load(const char *vfile, const char *pfile) 7.247 +{ 7.248 + unsigned int vs = 0, ps = 0; 7.249 + 7.250 + if(vfile && *vfile && !(vs = get_vertex_shader(vfile))) { 7.251 + return 0; 7.252 + } 7.253 + if(pfile && *pfile && !(ps = get_pixel_shader(pfile))) { 7.254 + return 0; 7.255 + } 7.256 + return create_program_link(vs, ps, 0); 7.257 +} 7.258 + 7.259 +void free_program(unsigned int sdr) 7.260 +{ 7.261 + glDeleteProgram(sdr); 7.262 +} 7.263 + 7.264 +void attach_shader(unsigned int prog, unsigned int sdr) 7.265 +{ 7.266 + glAttachShader(prog, sdr); 7.267 + assert(glGetError() == GL_NO_ERROR); 7.268 +} 7.269 + 7.270 +int link_program(unsigned int prog) 7.271 +{ 7.272 + int linked, info_len, retval = 0; 7.273 + char *info_str = 0; 7.274 + 7.275 + glLinkProgram(prog); 7.276 + assert(glGetError() == GL_NO_ERROR); 7.277 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 7.278 + assert(glGetError() == GL_NO_ERROR); 7.279 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 7.280 + assert(glGetError() == GL_NO_ERROR); 7.281 + 7.282 + if(info_len) { 7.283 + if((info_str = malloc(info_len + 1))) { 7.284 + glGetProgramInfoLog(prog, info_len, 0, info_str); 7.285 + assert(glGetError() == GL_NO_ERROR); 7.286 + } 7.287 + } 7.288 + 7.289 + if(linked) { 7.290 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 7.291 + } else { 7.292 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 7.293 + retval = -1; 7.294 + } 7.295 + 7.296 + free(info_str); 7.297 + return retval; 7.298 +} 7.299 + 7.300 +int bind_program(unsigned int prog) 7.301 +{ 7.302 + GLenum err; 7.303 + 7.304 + glUseProgram(prog); 7.305 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 7.306 + /* maybe the program is not linked, try linking first */ 7.307 + if(err == GL_INVALID_OPERATION) { 7.308 + if(link_program(prog) == -1) { 7.309 + return -1; 7.310 + } 7.311 + glUseProgram(prog); 7.312 + return glGetError() == GL_NO_ERROR ? 0 : -1; 7.313 + } 7.314 + return -1; 7.315 + } 7.316 + return 0; 7.317 +} 7.318 + 7.319 +/* ugly but I'm not going to write the same bloody code over and over */ 7.320 +#define BEGIN_UNIFORM_CODE \ 7.321 + int loc, curr_prog; \ 7.322 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 7.323 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { \ 7.324 + return -1; \ 7.325 + } \ 7.326 + if((loc = glGetUniformLocation(prog, name)) != -1) 7.327 + 7.328 +#define END_UNIFORM_CODE \ 7.329 + if((unsigned int)curr_prog != prog) { \ 7.330 + bind_program(curr_prog); \ 7.331 + } \ 7.332 + return loc == -1 ? -1 : 0 7.333 + 7.334 +int set_uniform_int(unsigned int prog, const char *name, int val) 7.335 +{ 7.336 + BEGIN_UNIFORM_CODE { 7.337 + glUniform1i(loc, val); 7.338 + } 7.339 + END_UNIFORM_CODE; 7.340 +} 7.341 + 7.342 +int set_uniform_float(unsigned int prog, const char *name, float val) 7.343 +{ 7.344 + BEGIN_UNIFORM_CODE { 7.345 + glUniform1f(loc, val); 7.346 + } 7.347 + END_UNIFORM_CODE; 7.348 +} 7.349 + 7.350 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y) 7.351 +{ 7.352 + BEGIN_UNIFORM_CODE { 7.353 + glUniform2f(loc, x, y); 7.354 + } 7.355 + END_UNIFORM_CODE; 7.356 +} 7.357 + 7.358 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 7.359 +{ 7.360 + BEGIN_UNIFORM_CODE { 7.361 + glUniform3f(loc, x, y, z); 7.362 + } 7.363 + END_UNIFORM_CODE; 7.364 +} 7.365 + 7.366 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 7.367 +{ 7.368 + BEGIN_UNIFORM_CODE { 7.369 + glUniform4f(loc, x, y, z, w); 7.370 + } 7.371 + END_UNIFORM_CODE; 7.372 +} 7.373 + 7.374 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 7.375 +{ 7.376 + BEGIN_UNIFORM_CODE { 7.377 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 7.378 + } 7.379 + END_UNIFORM_CODE; 7.380 +} 7.381 + 7.382 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 7.383 +{ 7.384 + BEGIN_UNIFORM_CODE { 7.385 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 7.386 + } 7.387 + END_UNIFORM_CODE; 7.388 +} 7.389 + 7.390 +int get_attrib_loc(unsigned int prog, const char *name) 7.391 +{ 7.392 + int loc, curr_prog; 7.393 + 7.394 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 7.395 + if((unsigned int)curr_prog != prog && bind_program(prog) == -1) { 7.396 + return -1; 7.397 + } 7.398 + 7.399 + loc = glGetAttribLocation(prog, (char*)name); 7.400 + 7.401 + if((unsigned int)curr_prog != prog) { 7.402 + bind_program(curr_prog); 7.403 + } 7.404 + return loc; 7.405 +} 7.406 + 7.407 +void set_attrib_float3(int attr_loc, float x, float y, float z) 7.408 +{ 7.409 + glVertexAttrib3f(attr_loc, x, y, z); 7.410 +} 7.411 + 7.412 +static const char *sdrtypestr(unsigned int sdrtype) 7.413 +{ 7.414 + switch(sdrtype) { 7.415 + case GL_VERTEX_SHADER: 7.416 + return "vertex"; 7.417 + case GL_FRAGMENT_SHADER: 7.418 + return "pixel"; 7.419 + case GL_TESS_CONTROL_SHADER: 7.420 + return "tessellation control"; 7.421 + case GL_TESS_EVALUATION_SHADER: 7.422 + return "tessellation evaluation"; 7.423 + case GL_GEOMETRY_SHADER: 7.424 + return "geometry"; 7.425 + 7.426 + default: 7.427 + break; 7.428 + } 7.429 + return "<unknown>"; 7.430 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/sdr.h Thu Jan 22 06:19:52 2015 +0200 8.3 @@ -0,0 +1,76 @@ 8.4 +/* 8.5 +Printblobs - halftoning display hack 8.6 +Copyright (C) 2013 John Tsiombikas <nuclear@member.fsf.org> 8.7 + 8.8 +This program is free software: you can redistribute it and/or modify 8.9 +it under the terms of the GNU General Public License as published by 8.10 +the Free Software Foundation, either version 3 of the License, or 8.11 +(at your option) any later version. 8.12 + 8.13 +This program is distributed in the hope that it will be useful, 8.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 8.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8.16 +GNU General Public License for more details. 8.17 + 8.18 +You should have received a copy of the GNU General Public License 8.19 +along with this program. If not, see <http://www.gnu.org/licenses/>. 8.20 +*/ 8.21 +#ifndef SDR_H_ 8.22 +#define SDR_H_ 8.23 + 8.24 +#ifdef __cplusplus 8.25 +extern "C" { 8.26 +#endif /* __cplusplus */ 8.27 + 8.28 +/* ---- shaders ---- */ 8.29 +unsigned int create_vertex_shader(const char *src); 8.30 +unsigned int create_pixel_shader(const char *src); 8.31 +unsigned int create_tessctl_shader(const char *src); 8.32 +unsigned int create_tesseval_shader(const char *src); 8.33 +unsigned int create_geometry_shader(const char *src); 8.34 +unsigned int create_shader(const char *src, unsigned int sdr_type); 8.35 +void free_shader(unsigned int sdr); 8.36 + 8.37 +unsigned int load_vertex_shader(const char *fname); 8.38 +unsigned int load_pixel_shader(const char *fname); 8.39 +unsigned int load_tessctl_shader(const char *fname); 8.40 +unsigned int load_tesseval_shader(const char *fname); 8.41 +unsigned int load_geometry_shader(const char *fname); 8.42 +unsigned int load_shader(const char *src, unsigned int sdr_type); 8.43 + 8.44 +unsigned int get_vertex_shader(const char *fname); 8.45 +unsigned int get_pixel_shader(const char *fname); 8.46 +unsigned int get_tessctl_shader(const char *fname); 8.47 +unsigned int get_tesseval_shader(const char *fname); 8.48 +unsigned int get_geometry_shader(const char *fname); 8.49 +unsigned int get_shader(const char *fname, unsigned int sdr_type); 8.50 + 8.51 +int add_shader(const char *fname, unsigned int sdr); 8.52 +int remove_shader(const char *fname); 8.53 + 8.54 +/* ---- gpu programs ---- */ 8.55 +unsigned int create_program(void); 8.56 +unsigned int create_program_link(unsigned int sdr0, ...); 8.57 +unsigned int create_program_load(const char *vfile, const char *pfile); 8.58 +void free_program(unsigned int sdr); 8.59 + 8.60 +void attach_shader(unsigned int prog, unsigned int sdr); 8.61 +int link_program(unsigned int prog); 8.62 +int bind_program(unsigned int prog); 8.63 + 8.64 +int set_uniform_int(unsigned int prog, const char *name, int val); 8.65 +int set_uniform_float(unsigned int prog, const char *name, float val); 8.66 +int set_uniform_float2(unsigned int prog, const char *name, float x, float y); 8.67 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 8.68 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 8.69 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); 8.70 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); 8.71 + 8.72 +int get_attrib_loc(unsigned int prog, const char *name); 8.73 +void set_attrib_float3(int attr_loc, float x, float y, float z); 8.74 + 8.75 +#ifdef __cplusplus 8.76 +} 8.77 +#endif /* __cplusplus */ 8.78 + 8.79 +#endif /* SDR_H_ */