oculus1
diff src/vr.cc @ 21:ef4c9d8eeca7
added shaderless distortion method
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 02 Oct 2013 04:09:37 +0300 |
parents | 899cf9ebffb4 |
children | 75ab0d4ce2bb |
line diff
1.1 --- a/src/vr.cc Tue Oct 01 12:51:20 2013 +0300 1.2 +++ b/src/vr.cc Wed Oct 02 04:09:37 2013 +0300 1.3 @@ -10,13 +10,40 @@ 1.4 #include <malloc.h> 1.5 #endif 1.6 1.7 +#define USUB 28 1.8 +#define VSUB 40 1.9 + 1.10 +/* these are just used for the shaderless precomputed distortion method */ 1.11 +struct Mesh { 1.12 + int prim; 1.13 + int num_verts, num_faces; 1.14 + unsigned int vbo; 1.15 + unsigned int ibo; 1.16 +}; 1.17 +struct Vertex { 1.18 + float x, y, z; 1.19 + float tx, ty; 1.20 +}; 1.21 + 1.22 + 1.23 static void init_ctx(); 1.24 static bool init_ovr(); 1.25 static bool init_sdr(); 1.26 1.27 +static Mesh gen_view_mesh(int usub, int vsub, float aspect, float lens_center_offset, 1.28 + float scale, const float *dist_factors, float tex_scale_x, float tex_scale_y); 1.29 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, const float *dist_factors); 1.30 +static float barrel_scale(float rad, const float *k); 1.31 + 1.32 VRContext vr_ctx; 1.33 static unsigned int sdrprog; 1.34 1.35 +static Mesh wrapmesh[2]; 1.36 +static bool mesh_valid; 1.37 + 1.38 +bool dbg_enable; 1.39 + 1.40 + 1.41 extern "C" int vr_init(enum vr_init_mode mode) 1.42 { 1.43 glewInit(); 1.44 @@ -338,49 +365,204 @@ 1.45 {-1, -1, 0, 1}, 1.46 {0, -1, 1, 1} 1.47 }; 1.48 + static const float quad_trans[3] = {0, -1, 1}; 1.49 + static const float quad_scale[3] = {1, 0.5, 0.5}; 1.50 static const float offs_scale[3] = {0.0, -1.0, 1.0}; 1.51 + static int prev_tex_scale_x, prev_tex_scale_y; 1.52 1.53 glPushAttrib(GL_ENABLE_BIT); 1.54 glDisable(GL_DEPTH_TEST); 1.55 glDisable(GL_LIGHTING); 1.56 - glEnable(GL_TEXTURE_2D); 1.57 + glDisable(GL_CULL_FACE); 1.58 + 1.59 + glMatrixMode(GL_PROJECTION); 1.60 + glPushMatrix(); 1.61 + glLoadIdentity(); 1.62 1.63 glMatrixMode(GL_MODELVIEW); 1.64 glPushMatrix(); 1.65 glLoadIdentity(); 1.66 1.67 - glMatrixMode(GL_PROJECTION); 1.68 - glPushMatrix(); 1.69 - glLoadIdentity(); 1.70 + if(!dbg_enable) { 1.71 + glUseProgram(sdrprog); 1.72 1.73 - glUseProgram(sdrprog); 1.74 + if(sdrprog) { 1.75 + int loc; 1.76 + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { 1.77 + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; 1.78 + glUniform1f(loc, offset); 1.79 + } 1.80 1.81 - if(sdrprog) { 1.82 - int loc; 1.83 - if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { 1.84 - float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; 1.85 - glUniform1f(loc, offset); 1.86 + if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { 1.87 + glUniform2f(loc, tex_scale_x, tex_scale_y); 1.88 + } 1.89 } 1.90 1.91 - if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { 1.92 - glUniform2f(loc, tex_scale_x, tex_scale_y); 1.93 + glBindTexture(GL_TEXTURE_2D, tex); 1.94 + glBegin(GL_QUADS); 1.95 + glColor4f(1, 1, 1, 1); 1.96 + glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); 1.97 + glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); 1.98 + glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); 1.99 + glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); 1.100 + glEnd(); 1.101 + 1.102 + glUseProgram(0); 1.103 + 1.104 + } else { 1.105 + 1.106 + if(!mesh_valid || tex_scale_x != prev_tex_scale_x || tex_scale_y != prev_tex_scale_y) { 1.107 + for(int i=0; i<2; i++) { 1.108 + int eye = i + VR_EYE_LEFT; 1.109 + 1.110 + if(wrapmesh[i].vbo) { 1.111 + glDeleteBuffers(1, &wrapmesh[i].vbo); 1.112 + } 1.113 + if(wrapmesh[i].ibo) { 1.114 + glDeleteBuffers(1, &wrapmesh[i].ibo); 1.115 + } 1.116 + 1.117 + float aspect = vr_ctx.info.aspect / 2.0; 1.118 + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; 1.119 + wrapmesh[i] = gen_view_mesh(USUB, VSUB, aspect, offset, vr_ctx.info.scale, vr_ctx.info.distort, 1.120 + tex_scale_x, tex_scale_y); 1.121 + } 1.122 + mesh_valid = true; 1.123 + prev_tex_scale_x = tex_scale_x; 1.124 + prev_tex_scale_y = tex_scale_y; 1.125 } 1.126 + 1.127 + glScalef(quad_scale[eye], 1.0, 1.0); 1.128 + glTranslatef(quad_trans[eye], 0, 0); 1.129 + 1.130 + glUseProgram(0); 1.131 + glBindTexture(GL_TEXTURE_2D, tex); 1.132 + glEnable(GL_TEXTURE_2D); 1.133 + 1.134 + glColor3f(1, 1, 1); 1.135 + 1.136 + glEnableClientState(GL_VERTEX_ARRAY); 1.137 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.138 + 1.139 + int meshidx = eye - VR_EYE_LEFT; 1.140 + glBindBuffer(GL_ARRAY_BUFFER, wrapmesh[meshidx].vbo); 1.141 + glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0); 1.142 + glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, tx)); 1.143 + 1.144 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wrapmesh[meshidx].ibo); 1.145 + glDrawElements(GL_TRIANGLES, wrapmesh[meshidx].num_faces * 3, GL_UNSIGNED_INT, 0); 1.146 + 1.147 + glBindBuffer(GL_ARRAY_BUFFER, 0); 1.148 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 1.149 + 1.150 + glDisableClientState(GL_VERTEX_ARRAY); 1.151 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.152 } 1.153 1.154 - glBindTexture(GL_TEXTURE_2D, tex); 1.155 - glBegin(GL_QUADS); 1.156 - glColor4f(1, 1, 1, 1); 1.157 - glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); 1.158 - glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); 1.159 - glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); 1.160 - glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); 1.161 - glEnd(); 1.162 - 1.163 - glUseProgram(0); 1.164 - 1.165 + glMatrixMode(GL_PROJECTION); 1.166 glPopMatrix(); 1.167 glMatrixMode(GL_MODELVIEW); 1.168 glPopMatrix(); 1.169 1.170 glPopAttrib(); 1.171 } 1.172 + 1.173 +static Mesh gen_view_mesh(int usub, int vsub, float aspect, float lens_center_offset, 1.174 + float scale, const float *dist_factors, float tex_scale_x, float tex_scale_y) 1.175 +{ 1.176 + int uverts = usub + 1; 1.177 + int vverts = vsub + 1; 1.178 + 1.179 + int num_verts = uverts * vverts; 1.180 + int num_quads = usub * vsub; 1.181 + int num_tris = num_quads * 2; 1.182 + 1.183 + Vertex *varr = new Vertex[num_verts]; 1.184 + unsigned int *iarr = new unsigned int[num_tris * 3]; 1.185 + 1.186 + float du = 1.0 / (float)usub; 1.187 + float dv = 1.0 / (float)vsub; 1.188 + 1.189 + Vertex *vptr = varr; 1.190 + for(int i=0; i<vverts; i++) { 1.191 + float v = (float)i * dv; 1.192 + float y = 2.0 * v - 1.0; 1.193 + 1.194 + for(int j=0; j<uverts; j++) { 1.195 + float u = (float)j * du; 1.196 + float x = 2.0 * u - 1.0; 1.197 + float tc[2] = {u, v}; 1.198 + 1.199 + distort_texcoords(tc, aspect, lens_center_offset, scale, dist_factors); 1.200 + 1.201 + vptr->x = x; 1.202 + vptr->y = y; 1.203 + vptr->z = 0; 1.204 + vptr->tx = tc[0] * tex_scale_x; 1.205 + vptr->ty = tc[1] * tex_scale_y; 1.206 + vptr++; 1.207 + } 1.208 + } 1.209 + 1.210 + unsigned int *iptr = iarr; 1.211 + for(int i=0; i<vsub; i++) { 1.212 + for(int j=0; j<usub; j++) { 1.213 + *iptr++ = i * uverts + j; 1.214 + *iptr++ = (i + 1) * uverts + j; 1.215 + *iptr++ = (i + 1) * uverts + (j + 1); 1.216 + 1.217 + *iptr++ = i * uverts + j; 1.218 + *iptr++ = (i + 1) * uverts + (j + 1); 1.219 + *iptr++ = i * uverts + (j + 1); 1.220 + } 1.221 + } 1.222 + 1.223 + unsigned int buf[2]; 1.224 + glGenBuffers(2, buf); 1.225 + glBindBuffer(GL_ARRAY_BUFFER, buf[0]); 1.226 + glBufferData(GL_ARRAY_BUFFER, num_verts * sizeof *varr, varr, GL_STATIC_DRAW); 1.227 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf[1]); 1.228 + glBufferData(GL_ELEMENT_ARRAY_BUFFER, num_tris * 3 * sizeof *iarr, iarr, GL_STATIC_DRAW); 1.229 + 1.230 + delete [] varr; 1.231 + delete [] iarr; 1.232 + 1.233 + Mesh mesh; 1.234 + mesh.prim = GL_TRIANGLES; 1.235 + mesh.num_verts = num_verts; 1.236 + mesh.num_faces = num_tris; 1.237 + mesh.vbo = buf[0]; 1.238 + mesh.ibo = buf[1]; 1.239 + return mesh; 1.240 +} 1.241 + 1.242 +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, const float *dist_factors) 1.243 +{ 1.244 + // map tc [0, 1] -> [-1, 1] 1.245 + float ptx = tc[0] * 2.0 - 1.0; 1.246 + float pty = tc[1] * 2.0 - 1.0; 1.247 + 1.248 + ptx += lens_center_offset * 2.0; 1.249 + pty /= aspect; // correct for aspect ratio 1.250 + 1.251 + float rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); 1.252 + ptx *= rad; // scale the point by the computer distortion radius 1.253 + pty *= rad; 1.254 + 1.255 + ptx /= scale; 1.256 + pty /= scale; 1.257 + 1.258 + pty *= aspect; 1.259 + ptx -= lens_center_offset * 2.0; 1.260 + 1.261 + // map back to range [0, 1] 1.262 + tc[0] = ptx * 0.5 + 0.5; 1.263 + tc[1] = pty * 0.5 + 0.5; 1.264 +} 1.265 + 1.266 +static float barrel_scale(float rad, const float *k) 1.267 +{ 1.268 + float radsq = rad * rad; 1.269 + float radquad = radsq * radsq; 1.270 + return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; 1.271 +}