├── LICENSE.md ├── README.md ├── doc └── config.ld ├── init.lua ├── logo.svg ├── opengl.lua ├── opengles2.lua └── ovr.lua /LICENSE.md: -------------------------------------------------------------------------------- 1 | # LÖVE3D 2 | 3 | This code is licensed under the [**MIT Open Source License**][MIT]. 4 | 5 | Copyright (c) 2015 Landon Manning - LManning17@gmail.com - [LandonManning.com][LM] 6 | Copyright (c) 2015 Colby Klein - shakesoda@gmail.com - [excessive.moe][exmoe] 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | 27 | [MIT]: http://www.opensource.org/licenses/mit-license.html 28 | [LM]: http://LandonManning.com 29 | [exmoe]: http://excessive.moe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LÖVE3D 2 | 3 | This library will be obsolete after LÖVE 0.11 is released, and will no longer be maintained (or will perhaps change just to a utility library). LÖVE 0.11 includes *all* the features this provided (and more!) 4 | 5 | Extensions to the LÖVE 0.10 API for 3D rendering - depth testing, depth buffers on canvases, etc. Works on desktop OpenGL and OpenGL ES (tested on Raspberry Pi, should work for Android with some tweaking). 6 | 7 | Two ways to use the API are provided. You can either use it as a regular module or tell it to inject itself into love.graphics using `l3d.import(true)`. The latter is more user-friendly, but must be more carefully maintained with love versions (on our end). 8 | 9 | While this can be used to make fully 3D games (and, in fact, we have), it's most reasonable to use it to lift art restrictions so you can make 2.5D games (or put 3D elements in otherwise 2D games). This is not intended to compete with the likes of any big 3D engine like Unreal Engine or Unity. 10 | 11 | Depends on LÖVE 0.10 and [CPML](https://github.com/excessive/cpml) 12 | 13 | You can load models using [IQM](https://github.com/excessive/iqm). 14 | 15 | Online documentation can be found [here](http://excessive.github.io/love3d/) or you can generate them yourself using `ldoc -c doc/config.ld -o index .` 16 | 17 | ## Usage 18 | 19 | Examples can be found here: https://github.com/excessive/love3d-demos 20 | -------------------------------------------------------------------------------- /doc/config.ld: -------------------------------------------------------------------------------- 1 | project="LÖVE3D" 2 | title="LÖVE3D documentation" 3 | description="Utilities for working in 3D with LÖVE" 4 | format="markdown" 5 | backtick_references=false 6 | file = { 7 | "../init.lua", 8 | "../ovr.lua" 9 | } 10 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | --- LÖVE3D. 2 | -- Utilities for working in 3D with LÖVE. 3 | -- @module l3d 4 | 5 | local current_folder = (...):gsub('%.init$', '') .. "." 6 | local cpml = require "cpml" 7 | local ffi = require "ffi" 8 | 9 | local use_gles = false 10 | 11 | local l3d = { 12 | _LICENSE = "Love3D is distributed under the terms of the MIT license. See LICENSE.md.", 13 | _URL = "https://github.com/excessive/love3d", 14 | _VERSION = "0.0.2", 15 | _DESCRIPTION = "A 3D extension for LÖVE." 16 | } 17 | 18 | -- hang onto the original in case we patch over it, we need it! 19 | local new_canvas = love.graphics.newCanvas 20 | 21 | -- from rxi/lume 22 | local function iscallable(x) 23 | if type(x) == "function" then return true end 24 | local mt = getmetatable(x) 25 | return mt and mt.__call ~= nil 26 | end 27 | 28 | local function combine(...) 29 | local n = select('#', ...) 30 | if n == 0 then return noop end 31 | if n == 1 then 32 | local fn = select(1, ...) 33 | if not fn then return noop end 34 | assert(iscallable(fn), "expected a function or nil") 35 | return fn 36 | end 37 | local funcs = {} 38 | for i = 1, n do 39 | local fn = select(i, ...) 40 | if fn ~= nil then 41 | assert(iscallable(fn), "expected a function or nil") 42 | funcs[#funcs + 1] = fn 43 | end 44 | end 45 | return function(...) 46 | for _, f in ipairs(funcs) do f(...) end 47 | end 48 | end 49 | 50 | --- Load OpenGL functions for use by LÖVE3D. 51 | -- Loads extra functions that LÖVE does not provide and optionally adds/updates 52 | -- functions in love.graphics for 3D. 53 | -- 54 | -- This must be called before anything else. 55 | -- @param use_monkeypatching patch the LOVE API with LOVE3D functions 56 | function l3d.import() 57 | local already_loaded = pcall(function() return ffi.C.SDL_GL_DEPTH_SIZE end) 58 | if not already_loaded then 59 | ffi.cdef([[ 60 | typedef enum { 61 | SDL_GL_DEPTH_SIZE = 6 62 | } SDL_GLattr; 63 | void *SDL_GL_GetProcAddress(const char *proc); 64 | int SDL_GL_GetAttribute(SDL_GLattr attr, int* value); 65 | ]]) 66 | end 67 | 68 | -- Windows needs to use an external SDL 69 | local sdl 70 | if love.system.getOS() == "Windows" then 71 | if not love.filesystem.isFused() and love.filesystem.isFile("bin/SDL2.dll") then 72 | sdl = ffi.load("bin/SDL2") 73 | else 74 | sdl = ffi.load("SDL2") 75 | end 76 | else 77 | -- On other systems, we get the symbols for free. 78 | sdl = ffi.C 79 | end 80 | 81 | -- Get handles for OpenGL 82 | local opengl 83 | if select(1, love.graphics.getRendererInfo()) == "OpenGL ES" then 84 | use_gles = true 85 | opengl = require(current_folder .. "opengles2") 86 | else 87 | opengl = require(current_folder .. "opengl") 88 | end 89 | opengl.loader = function(fn) 90 | return sdl.SDL_GL_GetProcAddress(fn) 91 | end 92 | opengl:import() 93 | 94 | local out = ffi.new("int[?]", 1) 95 | sdl.SDL_GL_GetAttribute(sdl.SDL_GL_DEPTH_SIZE, out) 96 | end 97 | 98 | --- Clear color/depth buffers. 99 | -- Must pass false (not nil!) to disable clearing. Defaults to depth only. 100 | -- @param color clear color buffer (bool) 101 | -- @param depth clear depth buffer (bool) 102 | function l3d.clear(color, depth) 103 | local to_clear = 0 104 | if color then 105 | to_clear = bit.bor(to_clear, tonumber(GL.COLOR_BUFFER_BIT)) 106 | end 107 | if depth or depth == nil then 108 | to_clear = bit.bor(to_clear, tonumber(GL.DEPTH_BUFFER_BIT)) 109 | end 110 | gl.Clear(to_clear) 111 | end 112 | 113 | --- Reset LOVE3D state. 114 | -- Disables depth testing, enables depth writing, disables culling and resets 115 | -- front face. 116 | function l3d.reset() 117 | l3d.set_depth_test() 118 | l3d.set_depth_write() 119 | l3d.set_culling() 120 | l3d.set_front_face() 121 | end 122 | 123 | -- FXAA helpers 124 | --- Get FXAA alpha value for a given color 125 | function l3d.get_fxaa_alpha(color) 126 | local c_vec = cpml.vec3.isvector(color) and color or cpml.vec3(color) 127 | return c_vec:dot(cpml.vec3(0.299, 0.587, 0.114)) 128 | end 129 | 130 | function l3d.set_fxaa_background(color) 131 | local c_vec = cpml.vec3.isvector(color) and color or cpml.vec3(color) 132 | love.graphics.setBackgroundColor(c_vec.x, c_vec.y, c_vec.z, l3d.get_fxaa_alpha(c_vec)) 133 | end 134 | 135 | --- Set depth writing. 136 | -- Enable or disable writing to the depth buffer. 137 | -- @param mask 138 | function l3d.set_depth_write(mask) 139 | if mask then 140 | assert(type(mask) == "boolean", "set_depth_write expects one parameter of type 'boolean'") 141 | end 142 | if mask == nil then 143 | mask = true 144 | end 145 | gl.DepthMask(mask and 1 or 0) 146 | end 147 | 148 | --- Set depth test method. 149 | -- Can be "greater", "equal", "less" or unspecified to disable depth testing. 150 | -- Usually you want to use "less". 151 | -- @param method 152 | function l3d.set_depth_test(method) 153 | if method then 154 | local methods = { 155 | greater = GL.GEQUAL, 156 | equal = GL.EQUAL, 157 | less = GL.LEQUAL 158 | } 159 | assert(methods[method], "Invalid depth test method.") 160 | gl.Enable(GL.DEPTH_TEST) 161 | gl.DepthFunc(methods[method]) 162 | if use_gles then 163 | gl.DepthRangef(0, 1) 164 | gl.ClearDepthf(1.0) 165 | else 166 | gl.DepthRange(0, 1) 167 | gl.ClearDepth(1.0) 168 | end 169 | else 170 | gl.Disable(GL.DEPTH_TEST) 171 | end 172 | end 173 | 174 | --- Set front face winding. 175 | -- Can be "cw", "ccw" or unspecified to reset to ccw. 176 | -- @param facing 177 | function l3d.set_front_face(facing) 178 | if not facing or facing == "ccw" then 179 | gl.FrontFace(GL.CCW) 180 | return 181 | elseif facing == "cw" then 182 | gl.FrontFace(GL.CW) 183 | return 184 | end 185 | 186 | error("Invalid face winding. Parameter must be one of: 'cw', 'ccw' or unspecified.") 187 | end 188 | 189 | --- Set culling method. 190 | -- Can be "front", "back" or unspecified to reset to none. 191 | -- @param method 192 | function l3d.set_culling(method) 193 | if not method then 194 | gl.Disable(GL.CULL_FACE) 195 | return 196 | end 197 | 198 | gl.Enable(GL.CULL_FACE) 199 | 200 | if method == "back" then 201 | gl.CullFace(GL.BACK) 202 | return 203 | elseif method == "front" then 204 | gl.CullFace(GL.FRONT) 205 | return 206 | end 207 | 208 | error("Invalid culling method: Parameter must be one of: 'front', 'back' or unspecified") 209 | end 210 | 211 | --- Create a shader without LOVE's preprocessing. 212 | -- Useful if you need different shader outputs or a later GLSL version. 213 | -- The shader is still preprocessed for things such as VERTEX and PIXEL, but 214 | -- you will have to write your own main() function, attributes, etc. 215 | -- 216 | -- *Warning: This will very likely do bad things for your shader compatibility.* 217 | -- @param gl_version 218 | -- @param vc vertex shader code or filename 219 | -- @param pc pixel shader code or filename 220 | -- @return shader 221 | function l3d.new_shader_raw(gl_version, vc, pc) 222 | local function is_vc(code) 223 | return code:match("#ifdef%s+VERTEX") ~= nil 224 | end 225 | local function is_pc(code) 226 | return code:match("#ifdef%s+PIXEL") ~= nil 227 | end 228 | local function mk_shader_code(arg1, arg2) 229 | -- local lang = "glsl" 230 | if (love.graphics.getRendererInfo()) == "OpenGL ES" then 231 | error("NYI: Can't into GLES") 232 | -- lang = "glsles" 233 | end 234 | local vc, pc 235 | -- as love does 236 | if arg1 then 237 | -- first arg contains vertex shader code 238 | if is_vc(arg1) then vc = arg1 end 239 | local ispixel = is_pc(arg1) 240 | -- first arg contains pixel shader code 241 | if ispixel then pc = arg1 end 242 | end 243 | if arg2 then 244 | -- second arg contains vertex shader code 245 | if is_vc(arg2) then vc = arg2 end 246 | local ispixel = is_pc(arg2) 247 | -- second arg contains pixel shader code 248 | if ispixel then pc = arg2 end 249 | end 250 | -- Later versions of GLSL do this anyways - so let's use GL version. 251 | local versions = { 252 | ["2.1"] = "120", ["3.0"] = "130", ["3.1"] = "140", ["3.2"] = "150", 253 | ["3.3"] = "330", ["4.0"] = "400", ["4.1"] = "410", ["4.2"] = "420", 254 | ["4.3"] = "430", ["4.4"] = "440", ["4.5"] = "450", 255 | } 256 | local fmt = [[%s 257 | #ifndef GL_ES 258 | #define lowp 259 | #define mediump 260 | #define highp 261 | #endif 262 | #pragma optionNV(strict on) 263 | #define %s 264 | #line 0 265 | %s]] 266 | local vs = arg1 and string.format(fmt, "#version " .. versions[gl_version], "VERTEX", vc) or nil 267 | local ps = arg2 and string.format(fmt, "#version " .. versions[gl_version], "PIXEL", pc) or nil 268 | return vs, ps 269 | end 270 | local orig = love.graphics._shaderCodeToGLSL 271 | love.graphics._shaderCodeToGLSL = mk_shader_code 272 | local shader = love.graphics.newShader(vc, pc) 273 | love.graphics._shaderCodeToGLSL = orig 274 | return shader 275 | end 276 | 277 | --- Create a buffer from a list of vertices (cpml.vec3's). 278 | -- Offset will offset every vertex by the specified amount, useful for preventing z-fighting. 279 | -- Optional mesh argument will update the mesh instead of creating a new one. 280 | -- Specify usage as "dynamic" if you intend to update it frequently. 281 | -- @param t vertex data 282 | -- @param offset 283 | -- @param mesh used when updating 284 | -- @param usage 285 | function l3d.new_triangles(t, offset, mesh, usage) 286 | offset = offset or cpml.vec3(0, 0, 0) 287 | local data, indices = {}, {} 288 | for k, v in ipairs(t) do 289 | local current = {} 290 | table.insert(current, v.x + offset.x) 291 | table.insert(current, v.y + offset.y) 292 | table.insert(current, v.z + offset.z) 293 | table.insert(data, current) 294 | if not mesh then 295 | table.insert(indices, k) 296 | end 297 | end 298 | 299 | if not mesh then 300 | local layout = { 301 | { "VertexPosition", "float", 3 } 302 | } 303 | 304 | local m = love.graphics.newMesh(layout, data, "triangles", usage or "static") 305 | m:setVertexMap(indices) 306 | return m 307 | else 308 | if mesh.setVertices then 309 | mesh:setVertices(data) 310 | end 311 | return mesh 312 | end 313 | end 314 | 315 | --- Create a canvas with a depth buffer. 316 | -- @param width 317 | -- @param height 318 | -- @param format 319 | -- @param msaa 320 | -- @param gen_depth 321 | function l3d.new_canvas(width, height, format, msaa, gen_depth) 322 | -- TODO: Test this to make sure things are properly freed. 323 | if use_gles then 324 | error() 325 | return 326 | end 327 | local w, h = width or love.graphics.getWidth(), height or love.graphics.getHeight() 328 | local canvas = new_canvas(w, h, format, msaa) 329 | if gen_depth and canvas then 330 | love.graphics.setCanvas(canvas) 331 | 332 | local depth = ffi.new("unsigned int[1]", 1) 333 | gl.GenRenderbuffers(1, depth); 334 | gl.BindRenderbuffer(GL.RENDERBUFFER, depth[0]); 335 | if not use_gles and (type(msaa) == "number" and msaa > 1) then 336 | gl.RenderbufferStorageMultisample(GL.RENDERBUFFER, msaa, use_gles and GL.DEPTH_COMPONENT16 or GL.DEPTH_COMPONENT24, w, h) 337 | else 338 | gl.RenderbufferStorage(GL.RENDERBUFFER, use_gles and GL.DEPTH_COMPONENT16 or GL.DEPTH_COMPONENT24, w, h) 339 | end 340 | gl.FramebufferRenderbuffer(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, depth[0]) 341 | local status = gl.CheckFramebufferStatus(GL.FRAMEBUFFER) 342 | if status ~= GL.FRAMEBUFFER_COMPLETE then 343 | error(string.format("Framebuffer is borked :( (%d)", status)) 344 | end 345 | if gl.GetError() ~= GL.NO_ERROR then 346 | error("You fucking broke GL you asshole.") 347 | end 348 | l3d.clear() 349 | love.graphics.setCanvas() 350 | end 351 | 352 | return canvas 353 | end 354 | 355 | --- Bind a shadow map. 356 | -- Sets up drawing to a shadow map texture created with l3d.new_shadow_map. 357 | -- @param map 358 | function l3d.bind_shadow_map(map) 359 | if map then 360 | assert(map.shadow_map) 361 | gl.DrawBuffer(GL.NONE) 362 | gl.ReadBuffer(GL.NONE) 363 | love.graphics.setCanvas(map.dummy_canvas) 364 | gl.BindFramebuffer(GL.FRAMEBUFFER, map.buffers[0]) 365 | gl.Viewport(0, 0, map.width, map.height) 366 | else 367 | --- XXX: This is not a good assumption on ES! 368 | -- gl.BindFramebuffer(0) 369 | love.graphics.setCanvas() 370 | gl.DrawBuffer(GL.BACK) 371 | gl.ReadBuffer(GL.BACK) 372 | end 373 | end 374 | 375 | --- Bind shadow map to a texture sampler. 376 | -- @param map 377 | -- @param shader 378 | function l3d.bind_shadow_texture(map, shader) 379 | -- Throw me a bone here, slime, this sucks. 380 | local current = ffi.new("GLuint[1]") 381 | gl.GetIntegerv(GL.CURRENT_PROGRAM, current) 382 | local loc = gl.GetUniformLocation(current[0], "shadow_texture") 383 | gl.ActiveTexture(GL.TEXTURE7) 384 | gl.BindTexture(GL.TEXTURE_2D, map.buffers[1]) 385 | gl.Uniform1i(loc, 7) 386 | gl.ActiveTexture(GL.TEXTURE0) 387 | end 388 | 389 | --- Create a new shadow map. 390 | -- Creates a depth texture and framebuffer to draw to. 391 | -- @param w shadow map width 392 | -- @param h shadow map height 393 | -- @return shadow_map 394 | function l3d.new_shadow_map(w, h) 395 | -- Use a dummy canvas so that we can make LOVE reset the canvas for us. 396 | -- ...sneaky sneaky 397 | local dummy = love.graphics.newCanvas(1, 1) 398 | love.graphics.setCanvas(dummy) 399 | 400 | local buffers = ffi.gc(ffi.new("GLuint[2]"), function(ptr) 401 | gl.DeleteFramebuffers(1, ptr) 402 | gl.DeleteTextures(1, ptr+1) 403 | end) 404 | 405 | gl.GenTextures(1, buffers+1) 406 | gl.BindTexture(GL.TEXTURE_2D, buffers[1]) 407 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR) 408 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR) 409 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE) 410 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE) 411 | gl.TexImage2D(GL.TEXTURE_2D, 0, GL.DEPTH_COMPONENT24, w, h, 0, GL.DEPTH_COMPONENT, GL.FLOAT, nil) 412 | 413 | gl.GenFramebuffers(1, buffers) 414 | gl.BindFramebuffer(GL.FRAMEBUFFER, buffers[0]) 415 | 416 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_COMPARE_MODE, GL.COMPARE_REF_TO_TEXTURE); 417 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_COMPARE_FUNC, GL.LEQUAL); 418 | gl.FramebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, buffers[1], 0) 419 | 420 | gl.DrawBuffer(GL.NONE) 421 | gl.ReadBuffer(GL.NONE) 422 | 423 | if gl.CheckFramebufferStatus(GL.FRAMEBUFFER) ~= GL.FRAMEBUFFER_COMPLETE then 424 | l3d.bind_shadow_map() 425 | return false 426 | end 427 | 428 | l3d.bind_shadow_map() 429 | 430 | return { 431 | shadow_map = true, 432 | buffers = buffers, 433 | dummy_canvas = dummy, 434 | width = w, 435 | height = h 436 | } 437 | end 438 | 439 | return l3d 440 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /opengl.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | local glheader = [[ 4 | typedef float GLfloat; 5 | typedef unsigned int GLbitfield; 6 | typedef unsigned int GLuint; 7 | typedef double GLdouble; 8 | typedef unsigned int GLenum; 9 | typedef unsigned char GLboolean; 10 | typedef int GLsizei; 11 | typedef int GLint; 12 | typedef char GLchar; 13 | 14 | #define GL_NO_ERROR 0 15 | #define GL_NONE 0 16 | #define GL_EQUAL 0x0202 17 | #define GL_LEQUAL 0x0203 18 | #define GL_GEQUAL 0x0206 19 | #define GL_FRONT 0x0404 20 | #define GL_BACK 0x0405 21 | #define GL_CW 0x0900 22 | #define GL_CCW 0x0901 23 | #define GL_CULL_FACE 0x0B44 24 | #define GL_DEPTH_TEST 0x0B71 25 | #define GL_TEXTURE_2D 0x0DE1 26 | #define GL_FLOAT 0x1406 27 | #define GL_DEPTH_COMPONENT 0x1902 28 | #define GL_NEAREST 0x2600 29 | #define GL_LINEAR 0x2601 30 | #define GL_TEXTURE_MAG_FILTER 0x2800 31 | #define GL_TEXTURE_MIN_FILTER 0x2801 32 | #define GL_TEXTURE_WRAP_S 0x2802 33 | #define GL_TEXTURE_WRAP_T 0x2803 34 | #define GL_CLAMP_TO_EDGE 0x812F 35 | #define GL_TEXTURE0 0x84C0 36 | #define GL_TEXTURE7 0x84C7 37 | #define GL_TEXTURE_COMPARE_MODE 0x884C 38 | #define GL_TEXTURE_COMPARE_FUNC 0x884D 39 | #define GL_COMPARE_REF_TO_TEXTURE 0x884E 40 | #define GL_CURRENT_PROGRAM 0x8B8D 41 | #define GL_FRAMEBUFFER_COMPLETE 0x8CD5 42 | #define GL_DEPTH_ATTACHMENT 0x8D00 43 | #define GL_FRAMEBUFFER 0x8D40 44 | #define GL_RENDERBUFFER 0x8D41 45 | 46 | #define GL_DEPTH_COMPONENT16 0x81A5 47 | #define GL_DEPTH_COMPONENT24 0x81A6 48 | 49 | #define GL_DEPTH_BUFFER_BIT 0x00000100 50 | #define GL_COLOR_BUFFER_BIT 0x00004000 51 | 52 | typedef void (APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); 53 | typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); 54 | typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); 55 | typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); 56 | typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); 57 | typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); 58 | typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); 59 | typedef void (APIENTRYP PFNGLREADBUFFERPROC) (GLenum mode); 60 | typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); 61 | typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); 62 | typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); 63 | typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); 64 | typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); 65 | typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); 66 | typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); 67 | typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); 68 | typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); 69 | typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); 70 | typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); 71 | typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); 72 | typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); 73 | typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); 74 | typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); 75 | typedef void (APIENTRYP PFNGLDRAWBUFFERPROC) (GLenum mode); 76 | typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); 77 | typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); 78 | typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); 79 | typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth); 80 | typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); 81 | typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); 82 | typedef void (APIENTRYP PFNGLDEPTHRANGEPROC) (GLdouble near, GLdouble far); 83 | typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); 84 | typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); 85 | typedef void (APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode); 86 | ]] 87 | 88 | local openGL = { 89 | GL = {}, 90 | gl = {}, 91 | loader = nil, 92 | 93 | import = function(self) 94 | rawset(_G, "GL", self.GL) 95 | rawset(_G, "gl", self.gl) 96 | end 97 | } 98 | 99 | if ffi.os == "Windows" then 100 | glheader = glheader:gsub("APIENTRYP", "__stdcall *") 101 | glheader = glheader:gsub("APIENTRY", "__stdcall") 102 | else 103 | glheader = glheader:gsub("APIENTRYP", "*") 104 | glheader = glheader:gsub("APIENTRY", "") 105 | end 106 | 107 | local type_glenum = ffi.typeof("unsigned int") 108 | local type_uint64 = ffi.typeof("uint64_t") 109 | 110 | local function constant_replace(name, value) 111 | local ctype = type_glenum 112 | local GL = openGL.GL 113 | 114 | local num = tonumber(value) 115 | if (not num) then 116 | if (value:match("ull$")) then 117 | --Potentially reevaluate this for LuaJIT 2.1 118 | GL[name] = loadstring("return " .. value)() 119 | elseif (value:match("u$")) then 120 | value = value:gsub("u$", "") 121 | num = tonumber(value) 122 | end 123 | end 124 | 125 | GL[name] = GL[name] or ctype(num) 126 | 127 | return "" 128 | end 129 | 130 | glheader = glheader:gsub("#define GL_(%S+)%s+(%S+)\n", constant_replace) 131 | 132 | ffi.cdef(glheader) 133 | 134 | --ffi.load(ffi.os == 'OSX' and 'OpenGL.framework/OpenGL' or ffi.os == 'Windows' and 'opengl32' or 'GL') 135 | if ffi.os == "Windows" then 136 | ffi.load('opengl32') 137 | end 138 | 139 | local gl_mt = { 140 | __index = function(self, name) 141 | local glname = "gl" .. name 142 | local procname = "PFNGL" .. name:upper() .. "PROC" 143 | local func = ffi.cast(procname, openGL.loader(glname)) 144 | rawset(self, name, func) 145 | return func 146 | end 147 | } 148 | 149 | setmetatable(openGL.gl, gl_mt) 150 | 151 | return openGL 152 | -------------------------------------------------------------------------------- /opengles2.lua: -------------------------------------------------------------------------------- 1 | local ffi = require("ffi") 2 | 3 | -- gl2.h 4 | local glheader = [[ 5 | /* 6 | ** Copyright (c) 2013 The Khronos Group Inc. 7 | ** 8 | ** Permission is hereby granted, free of charge, to any person obtaining a 9 | ** copy of this software and/or associated documentation files (the 10 | ** "Materials"), to deal in the Materials without restriction, including 11 | ** without limitation the rights to use, copy, modify, merge, publish, 12 | ** distribute, sublicense, and/or sell copies of the Materials, and to 13 | ** permit persons to whom the Materials are furnished to do so, subject to 14 | ** the following conditions: 15 | ** 16 | ** The above copyright notice and this permission notice shall be included 17 | ** in all copies or substantial portions of the Materials. 18 | ** 19 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 26 | */ 27 | /* 28 | ** This header is generated from the Khronos OpenGL / OpenGL ES XML 29 | ** API Registry. The current version of the Registry, generator scripts 30 | ** used to make the header, and the header can be found at 31 | ** http://www.opengl.org/registry/ 32 | ** 33 | ** Khronos $Revision: 24614 $ on $Date: 2013-12-30 04:44:46 -0800 (Mon, 30 Dec 2013) $ 34 | */ 35 | 36 | /* Generated on date 20131230 */ 37 | 38 | /* Generated C header for: 39 | * API: gles2 40 | * Profile: common 41 | * Versions considered: 2\.[0-9] 42 | * Versions emitted: .* 43 | * Default extensions included: None 44 | * Additional extensions included: _nomatch_^ 45 | * Extensions removed: _nomatch_^ 46 | */ 47 | 48 | typedef int8_t GLbyte; 49 | typedef float GLclampf; 50 | typedef int32_t GLfixed; 51 | typedef short GLshort; 52 | typedef unsigned short GLushort; 53 | typedef void GLvoid; 54 | typedef struct __GLsync *GLsync; 55 | typedef int64_t GLint64; 56 | typedef uint64_t GLuint64; 57 | typedef unsigned int GLenum; 58 | typedef unsigned int GLuint; 59 | typedef char GLchar; 60 | typedef float GLfloat; 61 | typedef size_t GLsizeiptr; 62 | typedef intptr_t GLintptr; 63 | typedef unsigned int GLbitfield; 64 | typedef int GLint; 65 | typedef unsigned char GLboolean; 66 | typedef int GLsizei; 67 | typedef uint8_t GLubyte; 68 | #define GL_DEPTH_BUFFER_BIT 0x00000100 69 | #define GL_STENCIL_BUFFER_BIT 0x00000400 70 | #define GL_COLOR_BUFFER_BIT 0x00004000 71 | #define GL_FALSE 0 72 | #define GL_TRUE 1 73 | #define GL_POINTS 0x0000 74 | #define GL_LINES 0x0001 75 | #define GL_LINE_LOOP 0x0002 76 | #define GL_LINE_STRIP 0x0003 77 | #define GL_TRIANGLES 0x0004 78 | #define GL_TRIANGLE_STRIP 0x0005 79 | #define GL_TRIANGLE_FAN 0x0006 80 | #define GL_ZERO 0 81 | #define GL_ONE 1 82 | #define GL_SRC_COLOR 0x0300 83 | #define GL_ONE_MINUS_SRC_COLOR 0x0301 84 | #define GL_SRC_ALPHA 0x0302 85 | #define GL_ONE_MINUS_SRC_ALPHA 0x0303 86 | #define GL_DST_ALPHA 0x0304 87 | #define GL_ONE_MINUS_DST_ALPHA 0x0305 88 | #define GL_DST_COLOR 0x0306 89 | #define GL_ONE_MINUS_DST_COLOR 0x0307 90 | #define GL_SRC_ALPHA_SATURATE 0x0308 91 | #define GL_FUNC_ADD 0x8006 92 | #define GL_BLEND_EQUATION 0x8009 93 | #define GL_BLEND_EQUATION_RGB 0x8009 94 | #define GL_BLEND_EQUATION_ALPHA 0x883D 95 | #define GL_FUNC_SUBTRACT 0x800A 96 | #define GL_FUNC_REVERSE_SUBTRACT 0x800B 97 | #define GL_BLEND_DST_RGB 0x80C8 98 | #define GL_BLEND_SRC_RGB 0x80C9 99 | #define GL_BLEND_DST_ALPHA 0x80CA 100 | #define GL_BLEND_SRC_ALPHA 0x80CB 101 | #define GL_CONSTANT_COLOR 0x8001 102 | #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 103 | #define GL_CONSTANT_ALPHA 0x8003 104 | #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 105 | #define GL_BLEND_COLOR 0x8005 106 | #define GL_ARRAY_BUFFER 0x8892 107 | #define GL_ELEMENT_ARRAY_BUFFER 0x8893 108 | #define GL_ARRAY_BUFFER_BINDING 0x8894 109 | #define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 110 | #define GL_STREAM_DRAW 0x88E0 111 | #define GL_STATIC_DRAW 0x88E4 112 | #define GL_DYNAMIC_DRAW 0x88E8 113 | #define GL_BUFFER_SIZE 0x8764 114 | #define GL_BUFFER_USAGE 0x8765 115 | #define GL_CURRENT_VERTEX_ATTRIB 0x8626 116 | #define GL_FRONT 0x0404 117 | #define GL_BACK 0x0405 118 | #define GL_FRONT_AND_BACK 0x0408 119 | #define GL_TEXTURE_2D 0x0DE1 120 | #define GL_CULL_FACE 0x0B44 121 | #define GL_BLEND 0x0BE2 122 | #define GL_DITHER 0x0BD0 123 | #define GL_STENCIL_TEST 0x0B90 124 | #define GL_DEPTH_TEST 0x0B71 125 | #define GL_SCISSOR_TEST 0x0C11 126 | #define GL_POLYGON_OFFSET_FILL 0x8037 127 | #define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E 128 | #define GL_SAMPLE_COVERAGE 0x80A0 129 | #define GL_NO_ERROR 0 130 | #define GL_INVALID_ENUM 0x0500 131 | #define GL_INVALID_VALUE 0x0501 132 | #define GL_INVALID_OPERATION 0x0502 133 | #define GL_OUT_OF_MEMORY 0x0505 134 | #define GL_CW 0x0900 135 | #define GL_CCW 0x0901 136 | #define GL_LINE_WIDTH 0x0B21 137 | #define GL_ALIASED_POINT_SIZE_RANGE 0x846D 138 | #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E 139 | #define GL_CULL_FACE_MODE 0x0B45 140 | #define GL_FRONT_FACE 0x0B46 141 | #define GL_DEPTH_RANGE 0x0B70 142 | #define GL_DEPTH_WRITEMASK 0x0B72 143 | #define GL_DEPTH_CLEAR_VALUE 0x0B73 144 | #define GL_DEPTH_FUNC 0x0B74 145 | #define GL_STENCIL_CLEAR_VALUE 0x0B91 146 | #define GL_STENCIL_FUNC 0x0B92 147 | #define GL_STENCIL_FAIL 0x0B94 148 | #define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 149 | #define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 150 | #define GL_STENCIL_REF 0x0B97 151 | #define GL_STENCIL_VALUE_MASK 0x0B93 152 | #define GL_STENCIL_WRITEMASK 0x0B98 153 | #define GL_STENCIL_BACK_FUNC 0x8800 154 | #define GL_STENCIL_BACK_FAIL 0x8801 155 | #define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 156 | #define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 157 | #define GL_STENCIL_BACK_REF 0x8CA3 158 | #define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 159 | #define GL_STENCIL_BACK_WRITEMASK 0x8CA5 160 | #define GL_VIEWPORT 0x0BA2 161 | #define GL_SCISSOR_BOX 0x0C10 162 | #define GL_COLOR_CLEAR_VALUE 0x0C22 163 | #define GL_COLOR_WRITEMASK 0x0C23 164 | #define GL_UNPACK_ALIGNMENT 0x0CF5 165 | #define GL_PACK_ALIGNMENT 0x0D05 166 | #define GL_MAX_TEXTURE_SIZE 0x0D33 167 | #define GL_MAX_VIEWPORT_DIMS 0x0D3A 168 | #define GL_SUBPIXEL_BITS 0x0D50 169 | #define GL_RED_BITS 0x0D52 170 | #define GL_GREEN_BITS 0x0D53 171 | #define GL_BLUE_BITS 0x0D54 172 | #define GL_ALPHA_BITS 0x0D55 173 | #define GL_DEPTH_BITS 0x0D56 174 | #define GL_STENCIL_BITS 0x0D57 175 | #define GL_POLYGON_OFFSET_UNITS 0x2A00 176 | #define GL_POLYGON_OFFSET_FACTOR 0x8038 177 | #define GL_TEXTURE_BINDING_2D 0x8069 178 | #define GL_SAMPLE_BUFFERS 0x80A8 179 | #define GL_SAMPLES 0x80A9 180 | #define GL_SAMPLE_COVERAGE_VALUE 0x80AA 181 | #define GL_SAMPLE_COVERAGE_INVERT 0x80AB 182 | #define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 183 | #define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 184 | #define GL_DONT_CARE 0x1100 185 | #define GL_FASTEST 0x1101 186 | #define GL_NICEST 0x1102 187 | #define GL_GENERATE_MIPMAP_HINT 0x8192 188 | #define GL_BYTE 0x1400 189 | #define GL_UNSIGNED_BYTE 0x1401 190 | #define GL_SHORT 0x1402 191 | #define GL_UNSIGNED_SHORT 0x1403 192 | #define GL_INT 0x1404 193 | #define GL_UNSIGNED_INT 0x1405 194 | #define GL_FLOAT 0x1406 195 | #define GL_FIXED 0x140C 196 | #define GL_DEPTH_COMPONENT 0x1902 197 | #define GL_ALPHA 0x1906 198 | #define GL_RGB 0x1907 199 | #define GL_RGBA 0x1908 200 | #define GL_LUMINANCE 0x1909 201 | #define GL_LUMINANCE_ALPHA 0x190A 202 | #define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 203 | #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 204 | #define GL_UNSIGNED_SHORT_5_6_5 0x8363 205 | #define GL_FRAGMENT_SHADER 0x8B30 206 | #define GL_VERTEX_SHADER 0x8B31 207 | #define GL_MAX_VERTEX_ATTRIBS 0x8869 208 | #define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB 209 | #define GL_MAX_VARYING_VECTORS 0x8DFC 210 | #define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D 211 | #define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C 212 | #define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 213 | #define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD 214 | #define GL_SHADER_TYPE 0x8B4F 215 | #define GL_DELETE_STATUS 0x8B80 216 | #define GL_LINK_STATUS 0x8B82 217 | #define GL_VALIDATE_STATUS 0x8B83 218 | #define GL_ATTACHED_SHADERS 0x8B85 219 | #define GL_ACTIVE_UNIFORMS 0x8B86 220 | #define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 221 | #define GL_ACTIVE_ATTRIBUTES 0x8B89 222 | #define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A 223 | #define GL_SHADING_LANGUAGE_VERSION 0x8B8C 224 | #define GL_CURRENT_PROGRAM 0x8B8D 225 | #define GL_NEVER 0x0200 226 | #define GL_LESS 0x0201 227 | #define GL_EQUAL 0x0202 228 | #define GL_LEQUAL 0x0203 229 | #define GL_GREATER 0x0204 230 | #define GL_NOTEQUAL 0x0205 231 | #define GL_GEQUAL 0x0206 232 | #define GL_ALWAYS 0x0207 233 | #define GL_KEEP 0x1E00 234 | #define GL_REPLACE 0x1E01 235 | #define GL_INCR 0x1E02 236 | #define GL_DECR 0x1E03 237 | #define GL_INVERT 0x150A 238 | #define GL_INCR_WRAP 0x8507 239 | #define GL_DECR_WRAP 0x8508 240 | #define GL_VENDOR 0x1F00 241 | #define GL_RENDERER 0x1F01 242 | #define GL_VERSION 0x1F02 243 | #define GL_EXTENSIONS 0x1F03 244 | #define GL_NEAREST 0x2600 245 | #define GL_LINEAR 0x2601 246 | #define GL_NEAREST_MIPMAP_NEAREST 0x2700 247 | #define GL_LINEAR_MIPMAP_NEAREST 0x2701 248 | #define GL_NEAREST_MIPMAP_LINEAR 0x2702 249 | #define GL_LINEAR_MIPMAP_LINEAR 0x2703 250 | #define GL_TEXTURE_MAG_FILTER 0x2800 251 | #define GL_TEXTURE_MIN_FILTER 0x2801 252 | #define GL_TEXTURE_WRAP_S 0x2802 253 | #define GL_TEXTURE_WRAP_T 0x2803 254 | #define GL_TEXTURE 0x1702 255 | #define GL_TEXTURE_CUBE_MAP 0x8513 256 | #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 257 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 258 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 259 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 260 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 261 | #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 262 | #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A 263 | #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C 264 | #define GL_TEXTURE0 0x84C0 265 | #define GL_TEXTURE1 0x84C1 266 | #define GL_TEXTURE2 0x84C2 267 | #define GL_TEXTURE3 0x84C3 268 | #define GL_TEXTURE4 0x84C4 269 | #define GL_TEXTURE5 0x84C5 270 | #define GL_TEXTURE6 0x84C6 271 | #define GL_TEXTURE7 0x84C7 272 | #define GL_TEXTURE8 0x84C8 273 | #define GL_TEXTURE9 0x84C9 274 | #define GL_TEXTURE10 0x84CA 275 | #define GL_TEXTURE11 0x84CB 276 | #define GL_TEXTURE12 0x84CC 277 | #define GL_TEXTURE13 0x84CD 278 | #define GL_TEXTURE14 0x84CE 279 | #define GL_TEXTURE15 0x84CF 280 | #define GL_TEXTURE16 0x84D0 281 | #define GL_TEXTURE17 0x84D1 282 | #define GL_TEXTURE18 0x84D2 283 | #define GL_TEXTURE19 0x84D3 284 | #define GL_TEXTURE20 0x84D4 285 | #define GL_TEXTURE21 0x84D5 286 | #define GL_TEXTURE22 0x84D6 287 | #define GL_TEXTURE23 0x84D7 288 | #define GL_TEXTURE24 0x84D8 289 | #define GL_TEXTURE25 0x84D9 290 | #define GL_TEXTURE26 0x84DA 291 | #define GL_TEXTURE27 0x84DB 292 | #define GL_TEXTURE28 0x84DC 293 | #define GL_TEXTURE29 0x84DD 294 | #define GL_TEXTURE30 0x84DE 295 | #define GL_TEXTURE31 0x84DF 296 | #define GL_ACTIVE_TEXTURE 0x84E0 297 | #define GL_REPEAT 0x2901 298 | #define GL_CLAMP_TO_EDGE 0x812F 299 | #define GL_MIRRORED_REPEAT 0x8370 300 | #define GL_FLOAT_VEC2 0x8B50 301 | #define GL_FLOAT_VEC3 0x8B51 302 | #define GL_FLOAT_VEC4 0x8B52 303 | #define GL_INT_VEC2 0x8B53 304 | #define GL_INT_VEC3 0x8B54 305 | #define GL_INT_VEC4 0x8B55 306 | #define GL_BOOL 0x8B56 307 | #define GL_BOOL_VEC2 0x8B57 308 | #define GL_BOOL_VEC3 0x8B58 309 | #define GL_BOOL_VEC4 0x8B59 310 | #define GL_FLOAT_MAT2 0x8B5A 311 | #define GL_FLOAT_MAT3 0x8B5B 312 | #define GL_FLOAT_MAT4 0x8B5C 313 | #define GL_SAMPLER_2D 0x8B5E 314 | #define GL_SAMPLER_CUBE 0x8B60 315 | #define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 316 | #define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 317 | #define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 318 | #define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 319 | #define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A 320 | #define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 321 | #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F 322 | #define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A 323 | #define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B 324 | #define GL_COMPILE_STATUS 0x8B81 325 | #define GL_INFO_LOG_LENGTH 0x8B84 326 | #define GL_SHADER_SOURCE_LENGTH 0x8B88 327 | #define GL_SHADER_COMPILER 0x8DFA 328 | #define GL_SHADER_BINARY_FORMATS 0x8DF8 329 | #define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 330 | #define GL_LOW_FLOAT 0x8DF0 331 | #define GL_MEDIUM_FLOAT 0x8DF1 332 | #define GL_HIGH_FLOAT 0x8DF2 333 | #define GL_LOW_INT 0x8DF3 334 | #define GL_MEDIUM_INT 0x8DF4 335 | #define GL_HIGH_INT 0x8DF5 336 | #define GL_FRAMEBUFFER 0x8D40 337 | #define GL_RENDERBUFFER 0x8D41 338 | #define GL_RGBA4 0x8056 339 | #define GL_RGB5_A1 0x8057 340 | #define GL_RGB565 0x8D62 341 | #define GL_DEPTH_COMPONENT16 0x81A5 342 | #define GL_STENCIL_INDEX8 0x8D48 343 | #define GL_RENDERBUFFER_WIDTH 0x8D42 344 | #define GL_RENDERBUFFER_HEIGHT 0x8D43 345 | #define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 346 | #define GL_RENDERBUFFER_RED_SIZE 0x8D50 347 | #define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 348 | #define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 349 | #define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 350 | #define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 351 | #define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 352 | #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 353 | #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 354 | #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 355 | #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 356 | #define GL_COLOR_ATTACHMENT0 0x8CE0 357 | #define GL_DEPTH_ATTACHMENT 0x8D00 358 | #define GL_STENCIL_ATTACHMENT 0x8D20 359 | #define GL_NONE 0 360 | #define GL_FRAMEBUFFER_COMPLETE 0x8CD5 361 | #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 362 | #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 363 | #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 364 | #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD 365 | #define GL_FRAMEBUFFER_BINDING 0x8CA6 366 | #define GL_RENDERBUFFER_BINDING 0x8CA7 367 | #define GL_MAX_RENDERBUFFER_SIZE 0x84E8 368 | #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 369 | GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); 370 | GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); 371 | GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); 372 | GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); 373 | GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); 374 | GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); 375 | GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); 376 | GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 377 | GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); 378 | GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); 379 | GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); 380 | GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); 381 | GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); 382 | GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); 383 | GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); 384 | GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); 385 | GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); 386 | GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); 387 | GL_APICALL void GL_APIENTRY glClearStencil (GLint s); 388 | GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); 389 | GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); 390 | GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); 391 | GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); 392 | GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); 393 | GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); 394 | GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); 395 | GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); 396 | GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); 397 | GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); 398 | GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); 399 | GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); 400 | GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); 401 | GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); 402 | GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); 403 | GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); 404 | GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); 405 | GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); 406 | GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); 407 | GL_APICALL void GL_APIENTRY glDisable (GLenum cap); 408 | GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); 409 | GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); 410 | GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); 411 | GL_APICALL void GL_APIENTRY glEnable (GLenum cap); 412 | GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); 413 | GL_APICALL void GL_APIENTRY glFinish (void); 414 | GL_APICALL void GL_APIENTRY glFlush (void); 415 | GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); 416 | GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); 417 | GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); 418 | GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); 419 | GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); 420 | GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); 421 | GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); 422 | GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); 423 | GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); 424 | GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); 425 | GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); 426 | GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); 427 | GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); 428 | GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); 429 | GL_APICALL GLenum GL_APIENTRY glGetError (void); 430 | GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); 431 | GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); 432 | GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); 433 | GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); 434 | GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 435 | GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); 436 | GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); 437 | GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); 438 | GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); 439 | GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); 440 | GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); 441 | GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); 442 | GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); 443 | GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); 444 | GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); 445 | GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); 446 | GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); 447 | GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); 448 | GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); 449 | GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); 450 | GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); 451 | GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); 452 | GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); 453 | GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); 454 | GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); 455 | GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); 456 | GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); 457 | GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); 458 | GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); 459 | GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); 460 | GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); 461 | GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); 462 | GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); 463 | GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); 464 | GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); 465 | GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); 466 | GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); 467 | GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); 468 | GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); 469 | GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); 470 | GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); 471 | GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); 472 | GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); 473 | GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); 474 | GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); 475 | GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); 476 | GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); 477 | GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); 478 | GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); 479 | GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); 480 | GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); 481 | GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); 482 | GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); 483 | GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); 484 | GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); 485 | GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); 486 | GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); 487 | GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); 488 | GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); 489 | GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); 490 | GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); 491 | GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); 492 | GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); 493 | GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); 494 | GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); 495 | GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); 496 | GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 497 | GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 498 | GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 499 | GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); 500 | GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); 501 | GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); 502 | GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); 503 | GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); 504 | GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); 505 | GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); 506 | GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); 507 | GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); 508 | GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); 509 | GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); 510 | GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); 511 | ]] 512 | 513 | local openGL = { 514 | GL = {}, 515 | gl = {}, 516 | loader = nil, 517 | 518 | import = function(self) 519 | rawset(_G, "GL", self.GL) 520 | rawset(_G, "gl", self.gl) 521 | end 522 | } 523 | 524 | if ffi.os == "Windows" then 525 | glheader = glheader:gsub("GL_APICALLP", "__stdcall *") 526 | glheader = glheader:gsub("GL_APICALL", "__stdcall") 527 | else 528 | glheader = glheader:gsub("GL_APICALLP", "*") 529 | glheader = glheader:gsub("GL_APICALL", "") 530 | glheader = glheader:gsub("GL_APIENTRYP", "*") 531 | glheader = glheader:gsub("GL_APIENTRY", "") 532 | end 533 | 534 | local type_glenum = ffi.typeof("unsigned int") 535 | local type_uint64 = ffi.typeof("uint64_t") 536 | 537 | local function constant_replace(name, value) 538 | local ctype = type_glenum 539 | local GL = openGL.GL 540 | 541 | local num = tonumber(value) 542 | if (not num) then 543 | if (value:match("ull$")) then 544 | --Potentially reevaluate this for LuaJIT 2.1 545 | GL[name] = loadstring("return " .. value)() 546 | elseif (value:match("u$")) then 547 | value = value:gsub("u$", "") 548 | num = tonumber(value) 549 | end 550 | end 551 | 552 | GL[name] = GL[name] or ctype(num) 553 | 554 | return "" 555 | end 556 | 557 | glheader = glheader:gsub("#define GL_(%S+)%s+(%S+)\n", constant_replace) 558 | 559 | ffi.cdef(glheader) 560 | 561 | local ffi = require( "ffi" ) 562 | 563 | local lib = ffi_OpenGLES2_lib or "GLESv2" 564 | local gles2 = ffi.load( lib ) 565 | 566 | local gl_mt = { 567 | __index = function(self, name) 568 | local glname = "gl" .. name 569 | local func = gles2[glname] 570 | --local procname = "PFNGL" .. name:upper() .. "PROC" 571 | -- local procname = glname 572 | -- local func = ffi.cast(procname, openGL.loader(glname)) 573 | rawset(self, name, func) 574 | return func 575 | end 576 | } 577 | 578 | setmetatable(openGL.gl, gl_mt) 579 | 580 | return openGL 581 | -------------------------------------------------------------------------------- /ovr.lua: -------------------------------------------------------------------------------- 1 | --- Oculus Rift support for LÖVE3D. 2 | -- Currently targets SDK 0.6 3 | -- @module ovr 4 | -- @alias ret 5 | 6 | local ffi = require "ffi" 7 | 8 | ffi.cdef [[ 9 | typedef int32_t ovrResult; 10 | typedef enum ovrSuccessType_ 11 | { 12 | ovrSuccess = 0, 13 | ovrSuccess_NotVisible = 1000, 14 | ovrSuccess_HMDFirmwareMismatch = 4100, 15 | ovrSuccess_TrackerFirmwareMismatch = 4101, 16 | } ovrSuccessType; 17 | typedef enum ovrErrorType_ 18 | { 19 | ovrError_MemoryAllocationFailure = -1000, 20 | ovrError_SocketCreationFailure = -1001, 21 | ovrError_InvalidHmd = -1002, 22 | ovrError_Timeout = -1003, 23 | ovrError_NotInitialized = -1004, 24 | ovrError_InvalidParameter = -1005, 25 | ovrError_ServiceError = -1006, 26 | ovrError_NoHmd = -1007, 27 | ovrError_AudioReservedBegin = -2000, 28 | ovrError_AudioReservedEnd = -2999, 29 | ovrError_Initialize = -3000, 30 | ovrError_LibLoad = -3001, 31 | ovrError_LibVersion = -3002, 32 | ovrError_ServiceConnection = -3003, 33 | ovrError_ServiceVersion = -3004, 34 | ovrError_IncompatibleOS = -3005, 35 | ovrError_DisplayInit = -3006, 36 | ovrError_ServerStart = -3007, 37 | ovrError_Reinitialization = -3008, 38 | ovrError_MismatchedAdapters = -3009, 39 | ovrError_InvalidBundleAdjustment = -4000, 40 | ovrError_USBBandwidth = -4001, 41 | ovrError_USBEnumeratedSpeed = -4002, 42 | ovrError_ImageSensorCommError = -4003, 43 | ovrError_GeneralTrackerFailure = -4004, 44 | ovrError_ExcessiveFrameTruncation = -4005, 45 | ovrError_ExcessiveFrameSkipping = -4006, 46 | ovrError_SyncDisconnected = -4007, 47 | ovrError_HMDFirmwareMismatch = -4100, 48 | ovrError_TrackerFirmwareMismatch = -4101, 49 | ovrError_Incomplete = -5000, 50 | ovrError_Abandoned = -5001, 51 | } ovrErrorType; 52 | typedef char ovrBool; 53 | typedef struct ovrVector2i_ { int x, y; } ovrVector2i; 54 | typedef struct ovrSizei_ { int w, h; } ovrSizei; 55 | typedef struct ovrRecti_ 56 | { 57 | ovrVector2i Pos; 58 | ovrSizei Size; 59 | } ovrRecti; 60 | typedef struct ovrQuatf_ { float x, y, z, w; } ovrQuatf; 61 | typedef struct ovrVector2f_ { float x, y; } ovrVector2f; 62 | typedef struct ovrVector3f_ { float x, y, z; } ovrVector3f; 63 | typedef struct ovrMatrix4f_ { float M[4][4]; } ovrMatrix4f; 64 | typedef struct ovrPosef_ 65 | { 66 | ovrQuatf Orientation; 67 | ovrVector3f Position; 68 | } ovrPosef; 69 | typedef struct ovrPoseStatef_ 70 | { 71 | ovrPosef ThePose; 72 | ovrVector3f AngularVelocity; 73 | ovrVector3f LinearVelocity; 74 | ovrVector3f AngularAcceleration; 75 | ovrVector3f LinearAcceleration; 76 | char pad0[4]; 77 | double TimeInSeconds; 78 | } ovrPoseStatef; 79 | typedef struct ovrFovPort_ 80 | { 81 | float UpTan; 82 | float DownTan; 83 | float LeftTan; 84 | float RightTan; 85 | } ovrFovPort; 86 | typedef enum ovrHmdType_ 87 | { 88 | ovrHmd_None = 0, 89 | ovrHmd_DK1 = 3, 90 | ovrHmd_DKHD = 4, 91 | ovrHmd_DK2 = 6, 92 | ovrHmd_CB = 8, 93 | ovrHmd_Other = 9, 94 | ovrHmd_EnumSize = 0x7fffffff 95 | } ovrHmdType; 96 | typedef enum ovrHmdCaps_ 97 | { 98 | ovrHmdCap_DebugDevice = 0x0010, 99 | ovrHmdCap_LowPersistence = 0x0080, 100 | ovrHmdCap_DynamicPrediction = 0x0200, 101 | ovrHmdCap_Writable_Mask = ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction, 102 | ovrHmdCap_Service_Mask = ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction, 103 | ovrHmdCap_EnumSize = 0x7fffffff 104 | } ovrHmdCaps; 105 | typedef enum ovrTrackingCaps_ 106 | { 107 | ovrTrackingCap_Orientation = 0x0010, 108 | ovrTrackingCap_MagYawCorrection = 0x0020, 109 | ovrTrackingCap_Position = 0x0040, 110 | ovrTrackingCap_Idle = 0x0100, 111 | ovrTrackingCap_EnumSize = 0x7fffffff 112 | } ovrTrackingCaps; 113 | typedef enum ovrEyeType_ 114 | { 115 | ovrEye_Left = 0, 116 | ovrEye_Right = 1, 117 | ovrEye_Count = 2, 118 | ovrEye_EnumSize = 0x7fffffff 119 | } ovrEyeType; 120 | typedef struct ovrHmdDesc_ 121 | { 122 | struct ovrHmdStruct* Handle; 123 | ovrHmdType Type; 124 | const char* ProductName; 125 | const char* Manufacturer; 126 | short VendorId; 127 | short ProductId; 128 | char SerialNumber[24]; 129 | short FirmwareMajor; 130 | short FirmwareMinor; 131 | float CameraFrustumHFovInRadians; 132 | float CameraFrustumVFovInRadians; 133 | float CameraFrustumNearZInMeters; 134 | float CameraFrustumFarZInMeters; 135 | unsigned int HmdCaps; 136 | unsigned int TrackingCaps; 137 | ovrFovPort DefaultEyeFov[ovrEye_Count]; 138 | ovrFovPort MaxEyeFov[ovrEye_Count]; 139 | ovrEyeType EyeRenderOrder[ovrEye_Count]; 140 | ovrSizei Resolution; 141 | } ovrHmdDesc; 142 | typedef const ovrHmdDesc* ovrHmd; 143 | typedef enum ovrStatusBits_ 144 | { 145 | ovrStatus_OrientationTracked = 0x0001, 146 | ovrStatus_PositionTracked = 0x0002, 147 | ovrStatus_CameraPoseTracked = 0x0004, 148 | ovrStatus_PositionConnected = 0x0020, 149 | ovrStatus_HmdConnected = 0x0080, 150 | ovrStatus_EnumSize = 0x7fffffff 151 | } ovrStatusBits; 152 | typedef struct ovrSensorData_ 153 | { 154 | ovrVector3f Accelerometer; 155 | ovrVector3f Gyro; 156 | ovrVector3f Magnetometer; 157 | float Temperature; 158 | float TimeInSeconds; 159 | } ovrSensorData; 160 | typedef struct ovrTrackingState_ 161 | { 162 | ovrPoseStatef HeadPose; 163 | ovrPosef CameraPose; 164 | ovrPosef LeveledCameraPose; 165 | ovrSensorData RawSensorData; 166 | unsigned int StatusFlags; 167 | uint32_t LastCameraFrameCounter; 168 | char pad0[4]; 169 | } ovrTrackingState; 170 | typedef struct ovrFrameTiming_ 171 | { 172 | double DisplayMidpointSeconds; 173 | double FrameIntervalSeconds; 174 | unsigned AppFrameIndex; 175 | unsigned DisplayFrameIndex; 176 | } ovrFrameTiming; 177 | typedef struct ovrEyeRenderDesc_ 178 | { 179 | ovrEyeType Eye; 180 | ovrFovPort Fov; 181 | ovrRecti DistortedViewport; 182 | ovrVector2f PixelsPerTanAngleAtCenter; 183 | ovrVector3f HmdToEyeViewOffset; 184 | } ovrEyeRenderDesc; 185 | typedef struct ovrTimewarpProjectionDesc_ 186 | { 187 | float Projection22; 188 | float Projection23; 189 | float Projection32; 190 | } ovrTimewarpProjectionDesc; 191 | typedef struct ovrViewScaleDesc_ 192 | { 193 | ovrVector3f HmdToEyeViewOffset[ovrEye_Count]; 194 | float HmdSpaceToWorldScaleInMeters; 195 | } ovrViewScaleDesc; 196 | typedef enum ovrRenderAPIType_ 197 | { 198 | ovrRenderAPI_None, 199 | ovrRenderAPI_OpenGL, 200 | ovrRenderAPI_Android_GLES, 201 | ovrRenderAPI_D3D9_Obsolete, 202 | ovrRenderAPI_D3D10_Obsolete, 203 | ovrRenderAPI_D3D11, 204 | ovrRenderAPI_Count, 205 | ovrRenderAPI_EnumSize = 0x7fffffff 206 | } ovrRenderAPIType; 207 | typedef struct ovrTextureHeader_ 208 | { 209 | ovrRenderAPIType API; 210 | ovrSizei TextureSize; 211 | } ovrTextureHeader; 212 | typedef struct ovrTexture_ 213 | { 214 | ovrTextureHeader Header; 215 | uintptr_t PlatformData[8]; 216 | } ovrTexture; 217 | typedef struct ovrSwapTextureSet_ 218 | { 219 | ovrTexture* Textures; 220 | int TextureCount; 221 | int CurrentIndex; 222 | } ovrSwapTextureSet; 223 | typedef enum ovrInitFlags_ 224 | { 225 | ovrInit_Debug = 0x00000001, 226 | ovrInit_ServerOptional = 0x00000002, 227 | ovrInit_RequestVersion = 0x00000004, 228 | ovrInit_ForceNoDebug = 0x00000008, 229 | ovrInit_EnumSize = 0x7fffffff 230 | } ovrInitFlags; 231 | typedef enum ovrLogLevel_ 232 | { 233 | ovrLogLevel_Debug = 0, 234 | ovrLogLevel_Info = 1, 235 | ovrLogLevel_Error = 2, 236 | ovrLogLevel_EnumSize = 0x7fffffff 237 | } ovrLogLevel; 238 | typedef void (__cdecl* ovrLogCallback)(int level, const char* message); 239 | typedef struct ovrInitParams_ 240 | { 241 | uint32_t Flags; 242 | uint32_t RequestedMinorVersion; 243 | ovrLogCallback LogCallback; 244 | uint32_t ConnectionTimeoutMS; 245 | } ovrInitParams; 246 | ovrResult ovr_Initialize(const ovrInitParams* params); 247 | void ovr_Shutdown(); 248 | typedef struct ovrErrorInfo_ 249 | { 250 | ovrResult Result; 251 | char ErrorString[512]; 252 | } ovrErrorInfo; 253 | void ovr_GetLastErrorInfo(ovrErrorInfo* errorInfo); 254 | const char* ovr_GetVersionString(); 255 | //int ovr_TraceMessage(int level, const char* message); 256 | ovrResult ovrHmd_Detect(); 257 | ovrResult ovrHmd_Create(int index, ovrHmd* pHmd); 258 | ovrResult ovrHmd_CreateDebug(ovrHmdType type, ovrHmd* pHmd); 259 | void ovrHmd_Destroy(ovrHmd hmd); 260 | unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmd); 261 | void ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int hmdCaps); 262 | ovrResult ovrHmd_ConfigureTracking(ovrHmd hmd, unsigned int supportedTrackingCaps, unsigned int requiredTrackingCaps); 263 | void ovrHmd_RecenterPose(ovrHmd hmd); 264 | ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmd, double absTime); 265 | typedef enum ovrLayerType_ 266 | { 267 | ovrLayerType_Disabled = 0, 268 | ovrLayerType_EyeFov = 1, 269 | ovrLayerType_EyeFovDepth = 2, 270 | ovrLayerType_QuadInWorld = 3, 271 | ovrLayerType_QuadHeadLocked = 4, 272 | ovrLayerType_Direct = 6, 273 | ovrLayerType_EnumSize = 0x7fffffff 274 | } ovrLayerType; 275 | typedef enum ovrLayerFlags_ 276 | { 277 | ovrLayerFlag_HighQuality = 0x01, 278 | ovrLayerFlag_TextureOriginAtBottomLeft = 0x02 279 | } ovrLayerFlags; 280 | typedef struct ovrLayerHeader_ 281 | { 282 | ovrLayerType Type; 283 | unsigned Flags; 284 | } ovrLayerHeader; 285 | typedef struct ovrLayerEyeFov_ 286 | { 287 | ovrLayerHeader Header; 288 | ovrSwapTextureSet* ColorTexture[ovrEye_Count]; 289 | ovrRecti Viewport[ovrEye_Count]; 290 | ovrFovPort Fov[ovrEye_Count]; 291 | ovrPosef RenderPose[ovrEye_Count]; 292 | } ovrLayerEyeFov; 293 | typedef struct ovrLayerEyeFovDepth_ 294 | { 295 | ovrLayerHeader Header; 296 | ovrSwapTextureSet* ColorTexture[ovrEye_Count]; 297 | ovrRecti Viewport[ovrEye_Count]; 298 | ovrFovPort Fov[ovrEye_Count]; 299 | ovrPosef RenderPose[ovrEye_Count]; 300 | ovrSwapTextureSet* DepthTexture[ovrEye_Count]; 301 | ovrTimewarpProjectionDesc ProjectionDesc; 302 | } ovrLayerEyeFovDepth; 303 | typedef struct ovrLayerQuad_ 304 | { 305 | ovrLayerHeader Header; 306 | ovrSwapTextureSet* ColorTexture; 307 | ovrRecti Viewport; 308 | ovrPosef QuadPoseCenter; 309 | ovrVector2f QuadSize; 310 | } ovrLayerQuad; 311 | typedef struct ovrLayerDirect_ 312 | { 313 | ovrLayerHeader Header; 314 | ovrSwapTextureSet* ColorTexture[ovrEye_Count]; 315 | ovrRecti Viewport[ovrEye_Count]; 316 | } ovrLayerDirect; 317 | typedef union ovrLayer_Union_ 318 | { 319 | ovrLayerHeader Header; 320 | ovrLayerEyeFov EyeFov; 321 | ovrLayerEyeFovDepth EyeFovDepth; 322 | ovrLayerQuad Quad; 323 | ovrLayerDirect Direct; 324 | } ovrLayer_Union; 325 | void ovrHmd_DestroySwapTextureSet(ovrHmd hmd, ovrSwapTextureSet* textureSet); 326 | void ovrHmd_DestroyMirrorTexture(ovrHmd hmd, ovrTexture* mirrorTexture); 327 | ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel); 328 | ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmd, ovrEyeType eyeType, ovrFovPort fov); 329 | ovrResult ovrHmd_SubmitFrame(ovrHmd hmd, unsigned int frameIndex, const ovrViewScaleDesc* viewScaleDesc, ovrLayerHeader const * const * layerPtrList, unsigned int layerCount); 330 | ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmd, unsigned int frameIndex); 331 | //void ovrHmd_ResetFrameTiming(ovrHmd hmd, unsigned int frameIndex); 332 | double ovr_GetTimeInSeconds(); 333 | typedef enum ovrPerfHudMode_ 334 | { 335 | ovrPerfHud_Off = 0, 336 | ovrPerfHud_LatencyTiming = 1, 337 | ovrPerfHud_RenderTiming = 2, 338 | ovrPerfHud_Count = 2, 339 | ovrPerfHud_EnumSize = 0x7fffffff 340 | } ovrPerfHudMode; 341 | 342 | //ovrBool ovrHmd_GetBool(ovrHmd hmd, const char* propertyName, ovrBool defaultVal); 343 | //ovrBool ovrHmd_SetBool(ovrHmd hmd, const char* propertyName, ovrBool value); 344 | //int ovrHmd_GetInt(ovrHmd hmd, const char* propertyName, int defaultVal); 345 | //ovrBool ovrHmd_SetInt(ovrHmd hmd, const char* propertyName, int value); 346 | //float ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal); 347 | //ovrBool ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value); 348 | //unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char* propertyName, float values[], unsigned int valuesCapacity); 349 | //ovrBool ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName, const float values[], unsigned int valuesSize); 350 | //const char* ovrHmd_GetString(ovrHmd hmd, const char* propertyName, const char* defaultVal); 351 | //ovrBool ovrHmd_SetString(ovrHmd hmd, const char* propertyName, const char* value); 352 | 353 | typedef enum ovrProjectionModifier_ 354 | { 355 | ovrProjection_None = 0x00, 356 | ovrProjection_RightHanded = 0x01, 357 | ovrProjection_FarLessThanNear = 0x02, 358 | ovrProjection_FarClipAtInfinity = 0x04, 359 | ovrProjection_ClipRangeOpenGL = 0x08, 360 | } ovrProjectionModifier; 361 | 362 | ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, unsigned int projectionModFlags); 363 | //ovrTimewarpProjectionDesc ovrTimewarpProjectionDesc_FromProjection(ovrMatrix4f projection, unsigned int projectionModFlags); 364 | //ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale, float orthoDistance, float hmdToEyeViewOffsetX); 365 | void ovr_CalcEyePoses(ovrPosef headPose, const ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2]); 366 | void ovrHmd_GetEyePoses(ovrHmd hmd, unsigned int frameIndex, const ovrVector3f hmdToEyeViewOffset[2], ovrPosef outEyePoses[2], ovrTrackingState* outHmdTrackingState); 367 | //double ovr_WaitTillTime(double absTime); 368 | 369 | // GL stuff 370 | typedef unsigned int GLuint; 371 | typedef struct ovrGLTextureData_s 372 | { 373 | ovrTextureHeader Header; 374 | GLuint TexId; 375 | } ovrGLTextureData; 376 | typedef union ovrGLTexture_s 377 | { 378 | ovrTexture Texture; ///< General device settings. 379 | ovrGLTextureData OGL; ///< OpenGL-specific settings. 380 | } ovrGLTexture; 381 | ovrResult ovrHmd_CreateSwapTextureSetGL(ovrHmd hmd, GLuint format, int width, int height, ovrSwapTextureSet** outTextureSet); 382 | ovrResult ovrHmd_CreateMirrorTextureGL(ovrHmd hmd, GLuint format, int width, int height, ovrTexture** outMirrorTexture); 383 | 384 | ]] 385 | 386 | local ovr = ffi.load(ffi.os == "Windows" and "bin/LibOVR.dll" or error("Oculus really should support not windows, too.")) 387 | 388 | local ret = {} 389 | 390 | --- Initialize the Rift. 391 | -- Quality defaults to 0.9, set lower or higher depending on GPU performance. 392 | -- In practice 0.9 is usually about ideal, but >1 can be used for super sampling 393 | -- the buffers. 394 | -- Usage: 395 | -- local rift = ovr.init() 396 | -- -- (later) 397 | -- rift:shutdown() 398 | -- @param quality scaling factor for render buffers. 399 | function ret.init(quality) 400 | local rift 401 | quality = quality or 0.9 402 | if ovr.ovr_Initialize(nil) == ovr.ovrSuccess then 403 | rift = {} 404 | print("Initialized LibOVR") 405 | local hmd = ffi.new("ovrHmd[?]", 1) 406 | if ovr.ovrHmd_Create(0, hmd) == ovr.ovrSuccess then 407 | hmd = hmd[0] 408 | print("Initialized HMD") 409 | 410 | local flags = ovr.ovrTrackingCap_Orientation 411 | flags = bit.bor(flags, ovr.ovrTrackingCap_MagYawCorrection) 412 | flags = bit.bor(flags, ovr.ovrTrackingCap_Position) -- DK2+ 413 | 414 | ovr.ovrHmd_SetEnabledCaps(hmd, bit.bor(ovr.ovrHmdCap_LowPersistence, ovr.ovrHmdCap_DynamicPrediction)) 415 | ovr.ovrHmd_ConfigureTracking(hmd, flags, 0) 416 | 417 | rift.hmd = hmd 418 | 419 | local rec_size = ovr.ovrHmd_GetFovTextureSize(hmd, ovr.ovrEye_Left, hmd.DefaultEyeFov[0], quality) 420 | local rec_size_r = ovr.ovrHmd_GetFovTextureSize(hmd, ovr.ovrEye_Right, hmd.DefaultEyeFov[1], quality) 421 | rec_size.w = rec_size.w + rec_size_r.w 422 | rec_size.h = math.max(rec_size.h, rec_size_r.h) 423 | 424 | local function mk_color(hmd, size) 425 | local swaps = ffi.new("ovrSwapTextureSet*[?]", 1) 426 | local textures = {} 427 | assert(ovr.ovrHmd_CreateSwapTextureSetGL(hmd, GL.RGBA, size.w, size.h, swaps) == ovr.ovrSuccess) 428 | print(string.format("Created %dx%d swap texture set.", size.w, size.h)) 429 | for i = 1, swaps[0].TextureCount do 430 | local tex = ffi.cast("ovrGLTexture*", swaps[0].Textures[i-1]) 431 | gl.BindTexture(GL.TEXTURE_2D_MULTISAMPLE, tex.OGL.TexId) 432 | gl.TexParameteri(GL.TEXTURE_2D_MULTISAMPLE, GL.TEXTURE_MIN_FILTER, GL.LINEAR) 433 | gl.TexParameteri(GL.TEXTURE_2D_MULTISAMPLE, GL.TEXTURE_MAG_FILTER, GL.LINEAR) 434 | gl.TexParameteri(GL.TEXTURE_2D_MULTISAMPLE, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE) 435 | gl.TexParameteri(GL.TEXTURE_2D_MULTISAMPLE, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE) 436 | gl.TexImage2DMultisample(GL.TEXTURE_2D_MULTISAMPLE, 4, GL.RGBA8, size.w, size.h, false) 437 | textures[i] = tex.OGL.TexId 438 | end 439 | local fbo = ffi.new("GLuint[?]", 1) 440 | gl.GenFramebuffers(1, fbo) 441 | 442 | local cpml = require "cpml" 443 | return { 444 | swaps = swaps, 445 | size = cpml.vec2(size.w, size.h), 446 | textures = textures, 447 | fbo = fbo 448 | } 449 | end 450 | 451 | local function mk_depth(size) 452 | local dt = ffi.new("GLuint[?]", 1) 453 | gl.GenTextures(1, dt) 454 | gl.BindTexture(GL.TEXTURE_2D, dt[0]) 455 | 456 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MIN_FILTER, GL.LINEAR) 457 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_MAG_FILTER, GL.LINEAR) 458 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_S, GL.CLAMP_TO_EDGE) 459 | gl.TexParameteri(GL.TEXTURE_2D, GL.TEXTURE_WRAP_T, GL.CLAMP_TO_EDGE) 460 | 461 | -- Your shitty system had better have GL_ARB_depth_buffer_float, scrublord. 462 | gl.TexImage2D(GL.TEXTURE_2D, 0, GL.DEPTH_COMPONENT32F, size.w, size.h, 0, GL.DEPTH_COMPONENT, GL.FLOAT, nil) 463 | 464 | return dt 465 | end 466 | 467 | local textures = { 468 | color = {}, 469 | depth = {} 470 | } 471 | for i=0,1 do 472 | local size = ovr.ovrHmd_GetFovTextureSize(hmd, ffi.cast("ovrEyeType", i), hmd.DefaultEyeFov[i], quality) 473 | textures.color[i] = mk_color(hmd, size) 474 | textures.depth[i] = mk_depth(size) 475 | end 476 | rift.textures = textures 477 | 478 | -- Initialize our single full screen Fov layer. 479 | local layer = ffi.new("ovrLayerEyeFov") 480 | layer.Header.Type = ovr.ovrLayerType_EyeFov 481 | layer.Header.Flags = ovr.ovrLayerFlag_TextureOriginAtBottomLeft 482 | 483 | local rect = ffi.new("ovrRecti[?]", 2) 484 | rect[1].Pos.x, rect[1].Pos.y = 0, 0 485 | rect[1].Size.w, rect[1].Size.h = rec_size.w / 2, rec_size.h 486 | 487 | rect[0].Pos.x, rect[0].Pos.y = 0, 0 --rec_size.w / 2, 0 488 | rect[0].Size.w, rect[0].Size.h = rec_size.w / 2, rec_size.h 489 | 490 | -- Initialize VR structures, filling out description. 491 | local eyeRenderDesc = ffi.new("ovrEyeRenderDesc*[?]", 2) 492 | local hmdToEyeViewOffset = ffi.new("ovrVector3f[?]", 2) 493 | eyeRenderDesc[0] = ovr.ovrHmd_GetRenderDesc(hmd, ovr.ovrEye_Left, hmd.DefaultEyeFov[0]) 494 | eyeRenderDesc[1] = ovr.ovrHmd_GetRenderDesc(hmd, ovr.ovrEye_Right, hmd.DefaultEyeFov[1]) 495 | 496 | rift.offsets = {} 497 | for i = 0, 1 do 498 | hmdToEyeViewOffset[i] = eyeRenderDesc[i].HmdToEyeViewOffset 499 | rift.offsets[i] = hmdToEyeViewOffset[i] 500 | layer.ColorTexture[i] = textures.color[i].swaps[0] 501 | layer.Viewport[i] = rect[i] 502 | layer.Fov[i] = eyeRenderDesc[i].Fov 503 | end 504 | 505 | rift.layer = layer 506 | 507 | rift.fov = { 508 | [0] = { 509 | UpTan = eyeRenderDesc[0].Fov.UpTan, 510 | DownTan = eyeRenderDesc[0].Fov.DownTan, 511 | LeftTan = eyeRenderDesc[0].Fov.LeftTan, 512 | RightTan = eyeRenderDesc[0].Fov.RightTan 513 | }, 514 | [1] = { 515 | UpTan = eyeRenderDesc[1].Fov.UpTan, 516 | DownTan = eyeRenderDesc[1].Fov.DownTan, 517 | LeftTan = eyeRenderDesc[1].Fov.LeftTan, 518 | RightTan = eyeRenderDesc[1].Fov.RightTan 519 | } 520 | } 521 | 522 | -- Create mirror texture and an FBO used to copy mirror texture to back buffer 523 | local mirrorTexture = ffi.new("ovrGLTexture*[?]", 1) 524 | local w, h = love.graphics.getDimensions() 525 | ovr.ovrHmd_CreateMirrorTextureGL(hmd, GL.RGBA, w, h, ffi.cast("ovrTexture**", mirrorTexture)) 526 | rift.mirror_texture = mirrorTexture 527 | 528 | -- Configure the mirror read buffer 529 | local mirrorFBO = ffi.new("GLuint[?]", 1) 530 | gl.GenFramebuffers(1, mirrorFBO) 531 | gl.BindFramebuffer(GL.READ_FRAMEBUFFER, mirrorFBO[0]) 532 | gl.FramebufferTexture2D(GL.READ_FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, mirrorTexture[0].OGL.TexId, 0) 533 | gl.FramebufferRenderbuffer(GL.READ_FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.RENDERBUFFER, 0) 534 | gl.BindFramebuffer(GL.READ_FRAMEBUFFER, 0) 535 | rift.mirror_fbo = mirrorFBO 536 | 537 | local layers = ffi.new("const ovrLayerHeader*[?]", 1) 538 | layers[0] = rift.layer.Header 539 | 540 | local vsd = ffi.new("ovrViewScaleDesc") 541 | vsd.HmdSpaceToWorldScaleInMeters = 1.0 542 | vsd.HmdToEyeViewOffset[0] = rift.offsets[0] 543 | vsd.HmdToEyeViewOffset[1] = rift.offsets[1] 544 | 545 | rift.layers = layers 546 | rift.vsd = vsd 547 | 548 | local eye_offsets = ffi.new("ovrVector3f[?]", 2) 549 | eye_offsets[0] = rift.offsets[0] 550 | eye_offsets[1] = rift.offsets[1] 551 | 552 | rift.eye_offsets = eye_offsets 553 | end 554 | end 555 | return rift 556 | end 557 | 558 | --- Clean up all data used by LibOVR. 559 | -- Call this when shutting down your program. 560 | -- @param rift 561 | function ret.shutdown(rift) 562 | if type(rift) == "table" then 563 | if rift.hmd then 564 | ovr.ovrHmd_Destroy(rift.hmd) 565 | rift.hmd = nil 566 | rift.layer = nil 567 | rift.fov = nil 568 | print("Shutdown HMD") 569 | end 570 | ovr.ovr_Shutdown() 571 | rift = nil 572 | print("Shutdown LibOVR") 573 | end 574 | end 575 | 576 | --- Draw a mirror of what is displaying on the Rift. 577 | -- Used to view what is happening on the headset on your monitor. 578 | -- 579 | -- Note: Blits directly to the window. 580 | -- @param rift 581 | function ret.draw_mirror(rift) 582 | if not rift.mirror_texture then 583 | return 584 | end 585 | -- Blit mirror texture to back buffer 586 | gl.BindFramebuffer(GL.READ_FRAMEBUFFER, rift.mirror_fbo[0]) 587 | gl.BindFramebuffer(GL.DRAW_FRAMEBUFFER, 0) 588 | local w = rift.mirror_texture[0].OGL.Header.TextureSize.w 589 | local h = rift.mirror_texture[0].OGL.Header.TextureSize.h 590 | gl.BlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL.COLOR_BUFFER_BIT, GL.NEAREST) 591 | gl.BindFramebuffer(GL.READ_FRAMEBUFFER, 0) 592 | end 593 | 594 | --- Create a projection matrix appropriate for HMD usage. 595 | -- Convenience function. 596 | -- 597 | -- Shortcut for `cpml.mat4():hmd_perspective(rift.fov[eye], near, far, false, false)`. 598 | -- @param rift 599 | -- @param eye eye index 600 | function ret.projection(rift, eye) 601 | local cpml = require "cpml" 602 | local fov = assert(rift.fov[eye]) 603 | return cpml.mat4():hmd_perspective(fov, 0.01, 10000, false, false) 604 | end 605 | 606 | --- Iterator for processing each view. 607 | -- You should draw the same thing for each eye, just offset with the pose. 608 | -- Usage: 609 | -- for eye, pose in rift:eyes() do 610 | -- -- eye is a number, pose is an orientation and a position. 611 | -- -- Usually used like this (ugly! may be cleaned up later). 612 | -- -- cpml.mat4():rotate(pose.orientation:conjugate()):translate(-pose.position) 613 | -- draw(eye, pose) 614 | -- end 615 | -- This function takes care of frame timings and per-eye render setup for you. 616 | -- @param rift 617 | function ret.eyes(rift) 618 | if not rift or not rift.hmd then 619 | return nil 620 | end 621 | 622 | local eye = -1 623 | 624 | local ft = ovr.ovrHmd_GetFrameTiming(rift.hmd, 0) 625 | local ts = ovr.ovrHmd_GetTrackingState(rift.hmd, ft.DisplayMidpointSeconds) 626 | 627 | if bit.band(ts.StatusFlags, bit.bor(ovr.ovrStatus_OrientationTracked, ovr.ovrStatus_PositionTracked)) ~= 0 then 628 | local eye_poses = ffi.new("ovrPosef[?]", 2) 629 | ovr.ovr_CalcEyePoses(ts.HeadPose.ThePose, rift.eye_offsets, eye_poses) 630 | 631 | rift.layer.RenderPose[0] = eye_poses[0] 632 | rift.layer.RenderPose[1] = eye_poses[1] 633 | end 634 | 635 | local idx = ft.AppFrameIndex % 2 636 | 637 | local closure = function() 638 | if eye >= 1 then 639 | local w, h = love.graphics.getDimensions() 640 | 641 | gl.FramebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, 0, 0) 642 | gl.FramebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, 0, 0) 643 | 644 | gl.BindFramebuffer(GL.FRAMEBUFFER, 0) 645 | gl.Viewport(0, 0, w, h) 646 | gl.Clear(bit.bor(tonumber(GL.COLOR_BUFFER_BIT), tonumber(GL.DEPTH_BUFFER_BIT))) 647 | 648 | return nil 649 | else 650 | eye = eye + 1 651 | 652 | local cpml = require "cpml" 653 | local pose = rift.layer.RenderPose[eye] 654 | local orientation = cpml.quat(pose.Orientation.x, pose.Orientation.y, pose.Orientation.z, pose.Orientation.w) 655 | local position = cpml.vec3(pose.Position.x, pose.Position.y, pose.Position.z) 656 | 657 | local texture = { 658 | color = rift.textures.color[eye], 659 | depth = rift.textures.depth[eye], 660 | } 661 | texture.color.swaps[0].CurrentIndex = idx 662 | 663 | local fbo = texture.color.fbo 664 | 665 | gl.BindFramebuffer(GL.FRAMEBUFFER, fbo[0]) 666 | gl.FramebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, texture.color.textures[idx+1], 0) 667 | gl.FramebufferTexture2D(GL.FRAMEBUFFER, GL.DEPTH_ATTACHMENT, GL.TEXTURE_2D, texture.depth[0], 0) 668 | 669 | -- Does the GPU support current FBO configuration? 670 | local status = gl.CheckFramebufferStatus(GL.FRAMEBUFFER) 671 | assert(status == GL.FRAMEBUFFER_COMPLETE) 672 | 673 | gl.Viewport(0, 0, texture.color.size.x, texture.color.size.y) 674 | gl.Clear(bit.bor(tonumber(GL.COLOR_BUFFER_BIT), tonumber(GL.DEPTH_BUFFER_BIT))) 675 | 676 | return eye, { orientation = orientation, position = position } 677 | end 678 | end 679 | return closure 680 | end 681 | 682 | --- Submit current frame to Rift. 683 | -- @param rift 684 | function ret.submit_frame(rift) 685 | assert(ovr.ovrHmd_SubmitFrame(rift.hmd, 0, rift.vsd, rift.layers, 1) == ovr.ovrSuccess) 686 | end 687 | 688 | return setmetatable(ret, { __index = ovr }) 689 | --------------------------------------------------------------------------------