├── .gitignore ├── GLK2.xcodeproj └── project.xcworkspace │ └── xcshareddata │ └── GLK2.xccheckout ├── GLKX-Demo ├── Assets │ ├── Base.lproj │ │ ├── Main_iPad.storyboard │ │ └── Main_iPhone.storyboard │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── Shaders │ │ ├── FragmentColourOnly.fsh │ │ ├── FragmentFunkyAlgorithm1.fsh │ │ ├── FragmentTextureOnly.fsh │ │ ├── FragmentVideoPairTexture.fsh │ │ ├── FragmentWithTexture.fsh │ │ ├── FragmentXYParameterized.fsh │ │ ├── VertexPassThroughAlgorithmData.vsh │ │ ├── VertexPositionUnprojected.vsh │ │ ├── VertexPositionUnprojectedAndShifted.vsh │ │ ├── VertexProjectedWithTexture.vsh │ │ └── VertexUnprojectedWithTexture.vsh │ ├── black-with-white-stripe.png │ └── tex2.png ├── Classes │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── AppleFixBadTimeAPI.h │ ├── AppleFixBadTimeAPI.m │ ├── CommonGLEngineCode.h │ ├── CommonGLEngineCode.m │ ├── ViewControllers │ │ ├── CALayerTextureViewController.h │ │ ├── CALayerTextureViewController.m │ │ ├── MemoryUsageViewController.h │ │ ├── MemoryUsageViewController.m │ │ ├── MultithreadedLoadingTexturesViewController.h │ │ ├── MultithreadedLoadingTexturesViewController.m │ │ ├── VideoTextureViewController.h │ │ ├── VideoTextureViewController.m │ │ ├── ViewController.h │ │ └── ViewController.m │ ├── main.m │ └── split-mesh-lat-lines.mov ├── Configuration │ ├── GLKitExtended-Demo-Info.plist │ ├── GLKitExtended-Demo-Prefix.pch │ └── InfoPlist.strings ├── GLK2 │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── GLK2-Info.plist │ ├── GLK2-Prefix.pch │ └── en.lproj │ │ └── InfoPlist.strings ├── GLKitExtended-Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── Libraries │ └── GLKitExtended │ ├── libGLKX-Library.a │ └── usr │ └── local │ └── include │ └── include │ ├── GLK2Attribute.h │ ├── GLK2BufferFormat.h │ ├── GLK2BufferObject.h │ ├── GLK2Cube.h │ ├── GLK2DrawCall.h │ ├── GLK2DrawCallViewController.h │ ├── GLK2ExampleUniformValueGenerator.h │ ├── GLK2HardwareMaximums.h │ ├── GLK2Shader.h │ ├── GLK2ShaderProgram.h │ ├── GLK2Texture+CoreGraphics.h │ ├── GLK2Texture+CoreVideo.h │ ├── GLK2Texture.h │ ├── GLK2TextureLoaderPVRv1.h │ ├── GLK2TextureTracker.h │ ├── GLK2Uniform.h │ ├── GLK2UniformMap.h │ ├── GLK2UniformMapGenerator.h │ ├── GLK2UniformValueGenerator.h │ ├── GLK2VertexArrayObject.h │ └── GLKX_Library.h ├── GLKX-Library ├── GLKX-Library-Prefix.pch ├── GLKX-Library.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── GLKX-Library │ ├── Essential OpenGL classes │ │ ├── GLK2Attribute.h │ │ ├── GLK2Attribute.m │ │ ├── GLK2BufferFormat.h │ │ ├── GLK2BufferFormat.m │ │ ├── GLK2BufferObject.h │ │ ├── GLK2BufferObject.m │ │ ├── GLK2DrawCall.h │ │ ├── GLK2DrawCall.m │ │ ├── GLK2Shader.h │ │ ├── GLK2Shader.m │ │ ├── GLK2ShaderProgram.h │ │ ├── GLK2ShaderProgram.m │ │ ├── GLK2Texture.h │ │ ├── GLK2Texture.m │ │ ├── GLK2Texture_MutableName.h │ │ ├── GLK2Uniform.h │ │ ├── GLK2Uniform.m │ │ ├── GLK2VertexArrayObject.h │ │ └── GLK2VertexArrayObject.m │ ├── GLKX-Library-Prefix.pch │ ├── GLKX_Library.h │ ├── OpenGL OOP Improvements │ │ ├── GLK2Cube.h │ │ ├── GLK2Cube.m │ │ ├── GLK2ExampleUniformValueGenerator.h │ │ ├── GLK2ExampleUniformValueGenerator.m │ │ ├── GLK2HardwareMaximums.h │ │ ├── GLK2HardwareMaximums.m │ │ ├── GLK2TextureTracker.h │ │ ├── GLK2TextureTracker.m │ │ ├── GLK2TextureTracker_UnitTesting.h │ │ ├── GLK2UniformMap.h │ │ ├── GLK2UniformMap.m │ │ ├── GLK2UniformMapGenerator.h │ │ ├── GLK2UniformMapGenerator.m │ │ └── Protocols │ │ │ └── GLK2UniformValueGenerator.h │ ├── OpenGL with Textures │ │ ├── GLK2Texture+CoreGraphics.h │ │ ├── GLK2Texture+CoreGraphics.m │ │ ├── GLK2Texture+CoreVideo.h │ │ ├── GLK2Texture+CoreVideo.m │ │ ├── GLK2TextureLoaderPVRv1.h │ │ └── GLK2TextureLoaderPVRv1.m │ └── OpenGL with UIKit │ │ ├── GLK2DrawCallViewController.h │ │ └── GLK2DrawCallViewController.m └── GLKX-LibraryTests │ ├── GLKX-LibraryTests-Info.plist │ ├── GLKX_LibraryTests.m │ ├── GLKX_Test_OOP_Improvements.m │ └── en.lproj │ └── InfoPlist.strings └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 / OS X Source projects 3 | # 4 | # Version 2.1 5 | # For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 6 | # 7 | # 2013 updates: 8 | # - fixed the broken "save personal Schemes" 9 | # - added line-by-line explanations for EVERYTHING (some were missing) 10 | # 11 | # NB: if you are storing "built" products, this WILL NOT WORK, 12 | # and you should use a different .gitignore (or none at all) 13 | # This file is for SOURCE projects, where there are many extra 14 | # files that we want to exclude 15 | # 16 | ######################### 17 | 18 | ##### 19 | # OS X temporary files that should never be committed 20 | # 21 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 22 | 23 | .DS_Store 24 | 25 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 26 | 27 | .Trashes 28 | 29 | # c.f. http://www.westwind.com/reference/os-x/invisibles.html 30 | 31 | *.swp 32 | 33 | # *.lock - this is used and abused by many editors for many different things. 34 | # For the main ones I use (e.g. Eclipse), it should be excluded 35 | # from source-control, but YMMV 36 | 37 | *.lock 38 | 39 | # 40 | # profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?) 41 | #profile 42 | 43 | 44 | #### 45 | # Xcode temporary files that should never be committed 46 | # 47 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 48 | 49 | *~.nib 50 | 51 | 52 | #### 53 | # Xcode build files - 54 | # 55 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 56 | 57 | DerivedData/ 58 | 59 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 60 | 61 | build/ 62 | 63 | 64 | ##### 65 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 66 | # 67 | # This is complicated: 68 | # 69 | # SOMETIMES you need to put this file in version control. 70 | # Apple designed it poorly - if you use "custom executables", they are 71 | # saved in this file. 72 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 73 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 74 | 75 | # .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html 76 | 77 | *.pbxuser 78 | 79 | # .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 80 | 81 | *.mode1v3 82 | 83 | # .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html 84 | 85 | *.mode2v3 86 | 87 | # .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file 88 | 89 | *.perspectivev3 90 | 91 | # NB: also, whitelist the default ones, some projects need to use these 92 | !default.pbxuser 93 | !default.mode1v3 94 | !default.mode2v3 95 | !default.perspectivev3 96 | 97 | 98 | #### 99 | # Xcode 4 - semi-personal settings 100 | # 101 | # 102 | # OPTION 1: --------------------------------- 103 | # throw away ALL personal settings (including custom schemes! 104 | # - unless they are "shared") 105 | # 106 | # NB: this is exclusive with OPTION 2 below 107 | xcuserdata 108 | 109 | # OPTION 2: --------------------------------- 110 | # get rid of ALL personal settings, but KEEP SOME OF THEM 111 | # - NB: you must manually uncomment the bits you want to keep 112 | # 113 | # NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X, 114 | # or manually install git over the top of the OS X version 115 | # NB: this is exclusive with OPTION 1 above 116 | # 117 | #xcuserdata/**/* 118 | 119 | # (requires option 2 above): Personal Schemes 120 | # 121 | #!xcuserdata/**/xcschemes/* 122 | 123 | #### 124 | # XCode 4 workspaces - more detailed 125 | # 126 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 127 | # 128 | # Workspace layout is quite spammy. For reference: 129 | # 130 | # /(root)/ 131 | # /(project-name).xcodeproj/ 132 | # project.pbxproj 133 | # /project.xcworkspace/ 134 | # contents.xcworkspacedata 135 | # /xcuserdata/ 136 | # /(your name)/xcuserdatad/ 137 | # UserInterfaceState.xcuserstate 138 | # /xcsshareddata/ 139 | # /xcschemes/ 140 | # (shared scheme name).xcscheme 141 | # /xcuserdata/ 142 | # /(your name)/xcuserdatad/ 143 | # (private scheme).xcscheme 144 | # xcschememanagement.plist 145 | # 146 | # 147 | 148 | #### 149 | # Xcode 4 - Deprecated classes 150 | # 151 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 152 | # 153 | # We're using source-control, so this is a "feature" that we do not want! 154 | 155 | *.moved-aside 156 | 157 | #### 158 | # UNKNOWN: recommended by others, but I can't discover what these files are 159 | # 160 | # ...none. Everything is now explained. 161 | -------------------------------------------------------------------------------- /GLK2.xcodeproj/project.xcworkspace/xcshareddata/GLK2.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4C545F22-D567-4D32-B089-741CD687E44F 9 | IDESourceControlProjectName 10 | GLK2 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 099500A3-2819-455B-B309-B4303B4CFB84 14 | ssh://github.com/adamgit/GL2KitExtensions.git 15 | 16 | IDESourceControlProjectPath 17 | GLK2.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 099500A3-2819-455B-B309-B4303B4CFB84 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | ssh://github.com/adamgit/GL2KitExtensions.git 25 | IDESourceControlProjectVersion 26 | 110 27 | IDESourceControlProjectWCCIdentifier 28 | 099500A3-2819-455B-B309-B4303B4CFB84 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 099500A3-2819-455B-B309-B4303B4CFB84 36 | IDESourceControlWCCName 37 | GL2KitExtensions 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentColourOnly.fsh: -------------------------------------------------------------------------------- 1 | void main() 2 | { 3 | gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 ); 4 | } 5 | -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentFunkyAlgorithm1.fsh: -------------------------------------------------------------------------------- 1 | uniform mediump float timeInSeconds; 2 | 3 | varying mediump float v_algorithmVirtualX, v_algorithmVirtualY; 4 | 5 | #define PI 3.14145926 // GLSL / shaders don't have PI in the language! We have to write it ourselves... 6 | 7 | void main() 8 | { 9 | /** Let's do something interesting with the virtual X, Y we've been given */ 10 | 11 | mediump float xInTime = v_algorithmVirtualX + timeInSeconds; 12 | 13 | mediump float waves1 = 0.5 + 0.5 * sin( cos(10.0 * xInTime) + 2.0 * PI * ( 1.0 * v_algorithmVirtualX*v_algorithmVirtualX + v_algorithmVirtualY)); 14 | 15 | mediump float theta = 0.5 + 0.5 * cos( 2.0 * PI * v_algorithmVirtualX ) * sin( 2.0 * PI * v_algorithmVirtualY ); 16 | 17 | mediump float thetaed = theta ; 18 | 19 | gl_FragColor = vec4( sin(timeInSeconds) * waves1, waves1, cos(1.1*timeInSeconds) * sqrt(waves1) + waves1, 1.0 ); 20 | } 21 | -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentTextureOnly.fsh: -------------------------------------------------------------------------------- 1 | varying mediump vec2 varyingtextureCoordinate; 2 | 3 | uniform sampler2D s_texture1, s2; 4 | uniform mediump float textureOffsetU; 5 | 6 | void main() 7 | { 8 | /** outputs: */ 9 | mediump vec4 topcolour = texture2D( s2, vec2( varyingtextureCoordinate.x + textureOffsetU, varyingtextureCoordinate.y) ); 10 | mediump vec4 botcolour = texture2D( s_texture1, vec2( varyingtextureCoordinate.x + textureOffsetU, varyingtextureCoordinate.y) ); 11 | 12 | gl_FragColor = mix( topcolour, botcolour, varyingtextureCoordinate.y); 13 | 14 | //CORRECT: gl_FragColor = texture2D( s_texture1, vec2( varyingtextureCoordinate.x + textureOffsetU, varyingtextureCoordinate.y) ); 15 | //DEBUG: gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 ); 16 | } 17 | -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentVideoPairTexture.fsh: -------------------------------------------------------------------------------- 1 | /** Based on Apple's code: 2 | https://developer.apple.com/library/ios/samplecode/GLCameraRipple/Listings/GLCameraRipple_Shaders_Shader_fsh.html#//apple_ref/doc/uid/DTS40011222-GLCameraRipple_Shaders_Shader_fsh-DontLinkElementID_9 3 | */ 4 | varying mediump vec2 varyingtextureCoordinate; 5 | 6 | uniform sampler2D s_texture1, s_texture2; 7 | 8 | void main() 9 | { 10 | mediump vec3 yuv; 11 | lowp vec3 rgb; 12 | 13 | yuv.x = texture2D(s_texture1, varyingtextureCoordinate).r; 14 | yuv.yz = texture2D(s_texture2, varyingtextureCoordinate).rg - vec2(0.5, 0.5); 15 | 16 | 17 | // BT.601, which is the standard for SDTV is provided as a reference 18 | /* 19 | rgb = mat3( 1, 1, 1, 20 | 0, -.34413, 1.772, 21 | 1.402, -.71414, 0) * yuv; 22 | */ 23 | 24 | 25 | // Using BT.709 which is the standard for HDTV 26 | rgb = mat3( 1, 1, 1, 27 | 0, -.18732, 1.8556, 28 | 1.57481, -.46813, 0) * yuv; 29 | 30 | gl_FragColor = vec4(rgb, 1); 31 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentWithTexture.fsh: -------------------------------------------------------------------------------- 1 | varying mediump vec2 varyingtextureCoordinate; 2 | 3 | uniform sampler2D s_texture1; 4 | 5 | void main() 6 | { 7 | /** outputs: */ 8 | gl_FragColor = texture2D( s_texture1, varyingtextureCoordinate ); 9 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/FragmentXYParameterized.fsh: -------------------------------------------------------------------------------- 1 | varying mediump vec2 v_virtualXY; 2 | 3 | void main() 4 | { 5 | /** Let's do something interesting with the virtual X, Y we've been given */ 6 | 7 | mediump float red, green, blue; // some Local variables. Inefficient, but makes code easier to read 8 | red = green = blue = sin( v_virtualXY.x ) + sin( v_virtualXY.y ); 9 | blue *= cos( v_virtualXY.y ); 10 | 11 | gl_FragColor = vec4( red, green, blue, 1.0 ); 12 | } 13 | -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/VertexPassThroughAlgorithmData.vsh: -------------------------------------------------------------------------------- 1 | uniform mediump float timeInSeconds; 2 | 3 | attribute vec4 position; 4 | attribute float algorithmVirtualX, algorithmVirtualY; 5 | 6 | varying mediump float v_algorithmVirtualX, v_algorithmVirtualY; 7 | 8 | void main() 9 | { 10 | /** This LOOKS LIKE an assignment, but the magic of Vertex -> Fragment shaders 11 | is that as soon as we write a value into a "varying", it gets converted into 12 | an "interpolated copy of that value, that is automatically interpolated for 13 | each pixel in the fragment shader" 14 | */ 15 | v_algorithmVirtualX = algorithmVirtualX; 16 | v_algorithmVirtualY = algorithmVirtualY; 17 | 18 | gl_Position = position; 19 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/VertexPositionUnprojected.vsh: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | 3 | void main() 4 | { 5 | gl_Position = position; 6 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/VertexPositionUnprojectedAndShifted.vsh: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 virtualXY; 3 | 4 | uniform vec2 positionOffset; 5 | 6 | varying mediump vec2 v_virtualXY; 7 | 8 | void main() 9 | { 10 | v_virtualXY = 3.1415926 * (2.0 * virtualXY) - 3.1415926; 11 | gl_Position = position + vec4( positionOffset, 0, 0 ); 12 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/VertexProjectedWithTexture.vsh: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 textureCoordinate; 3 | 4 | varying mediump vec2 varyingtextureCoordinate; 5 | 6 | /** In old desktop terms, this is the MVP matrix, pre-multiplied on the CPU. 7 | Useless in general apps, but perfect for simple apps */ 8 | uniform mediump mat4 projectionMatrix; 9 | 10 | void main() 11 | { 12 | /** outputs: */ 13 | varyingtextureCoordinate = textureCoordinate; 14 | gl_Position = projectionMatrix * position; 15 | // gl_Position = position; 16 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/Shaders/VertexUnprojectedWithTexture.vsh: -------------------------------------------------------------------------------- 1 | attribute vec4 position; 2 | attribute vec2 textureCoordinate; 3 | 4 | varying mediump vec2 varyingtextureCoordinate; 5 | 6 | void main() 7 | { 8 | /** outputs: */ 9 | varyingtextureCoordinate = textureCoordinate; 10 | gl_Position = position; 11 | } -------------------------------------------------------------------------------- /GLKX-Demo/Assets/black-with-white-stripe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/Assets/black-with-white-stripe.png -------------------------------------------------------------------------------- /GLKX-Demo/Assets/tex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/Assets/tex2.png -------------------------------------------------------------------------------- /GLKX-Demo/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | Self-contained demo app to test / experiment with the GLKExtended library 3 | */ 4 | #import 5 | 6 | @interface AppDelegate : UIResponder 7 | 8 | @property (strong, nonatomic) UIWindow *window; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // GLKitExtended-Demo 4 | // 5 | // Created by adam on 30/11/2013. 6 | // Copyright (c) 2013 n/a. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/AppleFixBadTimeAPI.h: -------------------------------------------------------------------------------- 1 | /** 2 | Apple's own timing class that is literally hundreds of times faster than NSDate. 3 | 4 | Why Apple doesn't provide an ObjectiveC time-measuring class that's fast? ... I have no idea. 5 | */ 6 | #import 7 | #include 8 | #include 9 | 10 | #define MILLISECONDS_PER_NANOSECOND ( 1.0 / 1000000 ) 11 | 12 | @interface AppleFixBadTimeAPI : NSObject 13 | 14 | uint64_t timeAbsoluteNanoseconds(void); 15 | uint64_t timeAbsoluteMilliseconds(); 16 | uint64_t millisecondsFromNanoseconds( uint64_t nanos ); 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/AppleFixBadTimeAPI.m: -------------------------------------------------------------------------------- 1 | #import "AppleFixBadTimeAPI.h" 2 | 3 | 4 | @implementation AppleFixBadTimeAPI 5 | 6 | /** From Apple docs: https://developer.apple.com/library/mac/qa/qa1398/_index.html 7 | This is ... over-complicated 8 | */ 9 | uint64_t timeAbsoluteNanoseconds(void) 10 | { 11 | uint64_t time; 12 | uint64_t timeNano; 13 | static mach_timebase_info_data_t sTimebaseInfo; 14 | 15 | time = mach_absolute_time(); 16 | 17 | // Convert to nanoseconds. 18 | 19 | // If this is the first time we've run, get the timebase. 20 | // We can use denom == 0 to indicate that sTimebaseInfo is 21 | // uninitialised because it makes no sense to have a zero 22 | // denominator is a fraction. 23 | 24 | if ( sTimebaseInfo.denom == 0 ) { 25 | (void) mach_timebase_info(&sTimebaseInfo); 26 | } 27 | 28 | // Do the maths. We hope that the multiplication doesn't 29 | // overflow; the price you pay for working in fixed point. 30 | 31 | timeNano = time * sTimebaseInfo.numer / sTimebaseInfo.denom; 32 | 33 | return timeNano; 34 | } 35 | 36 | uint64_t timeAbsoluteMilliseconds() 37 | { 38 | uint64_t timeNanoseconds = timeAbsoluteNanoseconds(); 39 | 40 | return millisecondsFromNanoseconds( timeNanoseconds ); 41 | } 42 | 43 | uint64_t millisecondsFromNanoseconds( uint64_t nanos ) 44 | { 45 | return nanos * MILLISECONDS_PER_NANOSECOND; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/CommonGLEngineCode.h: -------------------------------------------------------------------------------- 1 | /** 2 | ************************** WARNING ************************* 3 | 4 | Code in this class is going beyond my intent of "just modify GLKit 5 | to add what's missing". 6 | 7 | This class contains methods and features you would expect to 8 | create when writing your own rendering-engine. 9 | 10 | I am including them here because they are CODE I ALREADY SHOWED 11 | in previous tutorials, and RE-USING THEM MAKES IT EASIER TO WRITE 12 | SHORT TUTORIALS going forwards. 13 | 14 | If you're doing your own 3D engine based on OpenGL - please throw-away 15 | this class! 16 | ************************** WARNING ************************* 17 | 18 | In another sense ... the code in this class is stuff you used to find 19 | in OpenGL's "GLU" library, that was never officially part of GL itself, 20 | but was almost always available on every platform. 21 | 22 | GL ES implementations were shipped without GLU, partly because GLU relies 23 | upon lots of desktop-GL features that GL ES removed. This is a minor 24 | tragedy. 25 | 26 | This class is fine for demos and tutorials - but I RECOMMEND that you 27 | look for GLU source code online (it was most/all open-source) and port 28 | it to GL ES rather than use the crappy code contained in this class :). 29 | */ 30 | #import 31 | 32 | #import "GLK2DrawCall.h" 33 | #import "GLK2ShaderProgram.h" 34 | 35 | @interface CommonGLEngineCode : NSObject 36 | 37 | +(GLK2DrawCall*) drawCallWithUnitTriangleAtOriginUsingShaders:(GLK2ShaderProgram*) shaderProgram; 38 | +(GLK2DrawCall*) drawCallWithUnitCubeAtOriginUsingShaders:(GLK2ShaderProgram*) shaderProgram; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/CommonGLEngineCode.m: -------------------------------------------------------------------------------- 1 | #import "CommonGLEngineCode.h" 2 | 3 | @implementation CommonGLEngineCode 4 | 5 | +(GLK2DrawCall*) drawCallWithUnitTriangleAtOriginUsingShaders:(GLK2ShaderProgram*) shaderProgram 6 | { 7 | GLK2DrawCall* dc = [[GLK2DrawCall new] autorelease]; 8 | 9 | dc.shaderProgram = shaderProgram; 10 | 11 | /** ... Make some geometry */ 12 | 13 | GLfloat z = -0.0; // must be more than -1 * zNear, and ABS() less than zFar 14 | GLKVector3 cpuBuffer[3] = 15 | { 16 | GLKVector3Make(-0.5, -0.5, z), 17 | GLKVector3Make( 0, -0.5, z), 18 | GLKVector3Make(-0.5, 0, z) 19 | }; 20 | GLK2BufferObject* sharedVBOPositions = [GLK2BufferObject newVBOFilledWithData:cpuBuffer inFormat:[GLK2BufferFormat bufferFormatOneAttributeMadeOfGLFloats:3] numVertices:3 updateFrequency:GLK2BufferObjectFrequencyStatic]; 21 | 22 | GLKVector2 attributesVirtualXY [3] = 23 | { 24 | GLKVector2Make( 0, 0 ), 25 | GLKVector2Make( 1, 0 ), 26 | GLKVector2Make( 0, 1 ) 27 | }; 28 | GLK2BufferObject* sharedVBOVirtualXYs = [GLK2BufferObject newVBOFilledWithData:attributesVirtualXY inFormat:[GLK2BufferFormat bufferFormatOneAttributeMadeOfGLFloats:2] numVertices:3 updateFrequency:GLK2BufferObjectFrequencyStatic]; 29 | 30 | GLK2Attribute* attPosition = [shaderProgram attributeNamed:@"position"]; // will fail if you haven't called glUseProgram yet 31 | GLK2Attribute* attXY = [shaderProgram attributeNamed:@"textureCoordinate"]; 32 | 33 | dc.numVerticesToDraw = 3; 34 | dc.glDrawCallType = GL_TRIANGLES; 35 | 36 | dc.VAO = [[GLK2VertexArrayObject new] autorelease]; 37 | [dc.VAO addVBO:sharedVBOPositions forAttributes:@[attPosition] numVertices:3]; 38 | if( attXY != nil ) 39 | [dc.VAO addVBO:sharedVBOVirtualXYs forAttributes:@[attXY] numVertices:3]; 40 | 41 | return dc; 42 | 43 | } 44 | 45 | +(GLK2DrawCall*) drawCallWithUnitCubeAtOriginUsingShaders:(GLK2ShaderProgram*) shaderProgram 46 | { 47 | GLK2DrawCall* dc = [[GLK2DrawCall new] autorelease]; 48 | 49 | dc.shaderProgram = shaderProgram; 50 | 51 | /** ... Make some geometry */ 52 | 53 | GLKVector3 cpuBuffer[36] = 54 | { 55 | // bottom 56 | GLKVector3Make(-0.5,-0.5, -0.5), 57 | GLKVector3Make( 0.5, 0.5, -0.5), 58 | GLKVector3Make( 0.5,-0.5, -0.5), 59 | GLKVector3Make(-0.5,-0.5, -0.5), 60 | GLKVector3Make(-0.5, 0.5, -0.5), 61 | GLKVector3Make( 0.5, 0.5, -0.5), 62 | 63 | // top 64 | GLKVector3Make(-0.5,-0.5, 0.5), 65 | GLKVector3Make( 0.5,-0.5, 0.5), 66 | GLKVector3Make( 0.5, 0.5, 0.5), 67 | GLKVector3Make(-0.5,-0.5, 0.5), 68 | GLKVector3Make( 0.5, 0.5, 0.5), 69 | GLKVector3Make(-0.5, 0.5, 0.5), 70 | 71 | // north 72 | GLKVector3Make(-0.5, 0.5,-0.5), 73 | GLKVector3Make( 0.5, 0.5, 0.5), 74 | GLKVector3Make( 0.5, 0.5,-0.5), 75 | GLKVector3Make(-0.5, 0.5,-0.5), 76 | GLKVector3Make(-0.5, 0.5, 0.5), 77 | GLKVector3Make( 0.5, 0.5, 0.5), 78 | 79 | // south 80 | GLKVector3Make(-0.5, -0.5,-0.5), 81 | GLKVector3Make( 0.5, -0.5,-0.5), 82 | GLKVector3Make( 0.5, -0.5, 0.5), 83 | GLKVector3Make(-0.5, -0.5,-0.5), 84 | GLKVector3Make( 0.5, -0.5, 0.5), 85 | GLKVector3Make(-0.5, -0.5, 0.5), 86 | 87 | // east 88 | GLKVector3Make( 0.5,-0.5,-0.5), 89 | GLKVector3Make( 0.5, 0.5,-0.5), 90 | GLKVector3Make( 0.5, 0.5, 0.5), 91 | GLKVector3Make( 0.5,-0.5,-0.5), 92 | GLKVector3Make( 0.5, 0.5, 0.5), 93 | GLKVector3Make( 0.5,-0.5, 0.5), 94 | 95 | // west 96 | GLKVector3Make(-0.5,-0.5,-0.5), 97 | GLKVector3Make(-0.5, 0.5, 0.5), 98 | GLKVector3Make(-0.5, 0.5,-0.5), 99 | GLKVector3Make(-0.5,-0.5,-0.5), 100 | GLKVector3Make(-0.5,-0.5, 0.5), 101 | GLKVector3Make(-0.5, 0.5, 0.5), 102 | }; 103 | GLK2BufferObject* sharedVBOPositions = [GLK2BufferObject newVBOFilledWithData:cpuBuffer inFormat:[GLK2BufferFormat bufferFormatOneAttributeMadeOfGLFloats:3] numVertices:36 updateFrequency:GLK2BufferObjectFrequencyStatic]; 104 | 105 | GLKVector2 attributesVirtualXY [36] = 106 | { 107 | GLKVector2Make( 0, 0 ), 108 | GLKVector2Make( 1, 1 ), 109 | GLKVector2Make( 1, 0 ), 110 | GLKVector2Make( 0, 0 ), 111 | GLKVector2Make( 0, 1 ), 112 | GLKVector2Make( 1, 1 ), 113 | 114 | GLKVector2Make( 0, 0 ), 115 | GLKVector2Make( 1, 0 ), 116 | GLKVector2Make( 1, 1 ), 117 | GLKVector2Make( 0, 0 ), 118 | GLKVector2Make( 1, 1 ), 119 | GLKVector2Make( 0, 1 ), 120 | 121 | GLKVector2Make( 0, 0 ), 122 | GLKVector2Make( 1, 1 ), 123 | GLKVector2Make( 0, 1 ), 124 | GLKVector2Make( 0, 0 ), 125 | GLKVector2Make( 1, 0 ), 126 | GLKVector2Make( 1, 1 ), 127 | 128 | GLKVector2Make( 0, 0 ), 129 | GLKVector2Make( 1, 0 ), 130 | GLKVector2Make( 1, 1 ), 131 | GLKVector2Make( 0, 0 ), 132 | GLKVector2Make( 1, 1 ), 133 | GLKVector2Make( 0, 1 ), 134 | 135 | GLKVector2Make( 0, 0 ), 136 | GLKVector2Make( 1, 0 ), 137 | GLKVector2Make( 1, 1 ), 138 | GLKVector2Make( 0, 0 ), 139 | GLKVector2Make( 1, 1 ), 140 | GLKVector2Make( 0, 1 ), 141 | 142 | GLKVector2Make( 0, 0 ), 143 | GLKVector2Make( 1, 1 ), 144 | GLKVector2Make( 0, 1 ), 145 | GLKVector2Make( 0, 0 ), 146 | GLKVector2Make( 1, 0 ), 147 | GLKVector2Make( 1, 1 ), 148 | }; 149 | 150 | GLK2BufferObject* sharedVBOVirtualXYs = [GLK2BufferObject newVBOFilledWithData:attributesVirtualXY inFormat:[GLK2BufferFormat bufferFormatOneAttributeMadeOfGLFloats:2] numVertices:36 updateFrequency:GLK2BufferObjectFrequencyStatic]; 151 | 152 | GLK2Attribute* attPosition = [shaderProgram attributeNamed:@"position"]; // will fail if you haven't called glUseProgram yet 153 | GLK2Attribute* attXY = [shaderProgram attributeNamed:@"textureCoordinate"]; 154 | 155 | dc.numVerticesToDraw = 36; 156 | dc.glDrawCallType = GL_TRIANGLES; 157 | dc.VAO = [[GLK2VertexArrayObject new] autorelease]; 158 | [dc.VAO addVBO:sharedVBOPositions forAttributes:@[attPosition] numVertices:3]; 159 | if( attXY != nil ) 160 | [dc.VAO addVBO:sharedVBOVirtualXYs forAttributes:@[attXY] numVertices:3]; 161 | 162 | return dc; 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/CALayerTextureViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Contains the sample code for rendering the current blog post at http://t-machine.org 3 | 4 | Any code that we wrote in early posts, and frequently re-use without changes, gets 5 | moved into the superclass for convenience 6 | */ 7 | #import 8 | #import 9 | 10 | #import "GLK2HardwareMaximums.h" 11 | #import "GLK2DrawCallViewController.h" 12 | 13 | #import 14 | 15 | @interface CALayerTextureViewController : GLK2DrawCallViewController 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/CALayerTextureViewController.m: -------------------------------------------------------------------------------- 1 | #import "CALayerTextureViewController.h" 2 | 3 | #import "GLKX_Library.h" 4 | 5 | #import "GLK2Texture.h" 6 | 7 | #import "GLK2Texture+CoreGraphics.h" 8 | 9 | #import "CommonGLEngineCode.h" 10 | 11 | @interface CALayerTextureViewController () 12 | 13 | @end 14 | 15 | @implementation CALayerTextureViewController 16 | 17 | -(NSMutableArray*) createAllDrawCalls 18 | { 19 | /** All the local setup for the ViewController */ 20 | NSMutableArray* result = [NSMutableArray array]; 21 | 22 | /** -- Draw Call 1: 23 | 24 | triangle that contains a CALayer texture 25 | */ 26 | 27 | GLK2DrawCall* dcTri = [CommonGLEngineCode drawCallWithUnitTriangleAtOriginUsingShaders: 28 | [GLK2ShaderProgram shaderProgramFromVertexFilename:@"VertexProjectedWithTexture" fragmentFilename:@"FragmentWithTexture"]]; 29 | 30 | /** Do some drawing to a CGContextRef */ 31 | CGContextRef cgContext = [GLK2Texture createCGContextForOpenGLTextureRGBAWidth:256 h:256 bitsPerPixel:8 shouldFlipY:FALSE fillColorOrNil:[UIColor blueColor]]; 32 | CGContextSetFillColorWithColor( cgContext, [UIColor yellowColor].CGColor ); 33 | CGContextFillEllipseInRect( cgContext, CGRectMake( 50, 50, 150, 150 )); 34 | 35 | /** Convert the CGContext into a GL texture */ 36 | GLK2Texture* newTexture = [GLK2Texture uploadTextureRGBAToOpenGLFromCGContext:cgContext width:256 height:256]; 37 | 38 | /** Add the GL texture to our Draw call / shader so it uses it */ 39 | GLK2Uniform* samplerTexture1 = [dcTri.shaderProgram uniformNamed:@"s_texture1"]; 40 | [dcTri setTexture:newTexture forSampler:samplerTexture1]; 41 | 42 | /** Set the projection matrix to Identity (i.e. "dont change anything") */ 43 | GLK2Uniform* uniProjectionMatrix = [dcTri.shaderProgram uniformNamed:@"projectionMatrix"]; 44 | GLKMatrix4 rotatingProjectionMatrix = GLKMatrix4Identity; 45 | [dcTri.shaderProgram setValueOutsideRenderLoopRestoringProgramAfterwards:&rotatingProjectionMatrix forUniform:uniProjectionMatrix]; 46 | 47 | [result addObject:dcTri]; 48 | 49 | return result; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/MemoryUsageViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | A ViewController 4 | 5 | */ 6 | #import 7 | 8 | @interface MemoryUsageViewController : UIViewController 9 | 10 | @property(nonatomic,retain) IBOutlet UILabel* lFreeMem, *lUsedMem; 11 | 12 | -(IBAction) tappedLoadTexture1:(id)sender; 13 | -(IBAction) tappedUnloadTexture1:(id)sender; 14 | 15 | -(IBAction) tappedLoadTexture2:(id)sender; 16 | -(IBAction) tappedUnloadTexture2:(id)sender; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/MemoryUsageViewController.m: -------------------------------------------------------------------------------- 1 | #import "MemoryUsageViewController.h" 2 | 3 | #import 4 | #import 5 | 6 | #import "GLK2Texture.h" 7 | #import 8 | 9 | #import "GLK2TextureLoaderPVRv1.h" 10 | 11 | #pragma mark - Class Extension (private properties etc) 12 | @interface MemoryUsageViewController () 13 | @property(nonatomic,retain) NSTimer* timerForUpdatingMemUsage; 14 | @property(nonatomic,retain) EAGLContext* myContext; 15 | @property(nonatomic,retain) GLK2Texture* texture1, * texture2; 16 | @end 17 | 18 | #pragma mark - Main Class 19 | @implementation MemoryUsageViewController 20 | 21 | /** Apple Storyboards ONLY call this method */ 22 | -(id)initWithCoder:(NSCoder *)aDecoder 23 | { 24 | self = [super initWithCoder:aDecoder]; 25 | if (self) { 26 | self.myContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 27 | [EAGLContext setCurrentContext:self.myContext]; 28 | 29 | self.timerForUpdatingMemUsage = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(tickCheckMemUsage) userInfo:nil repeats:TRUE]; 30 | } 31 | return self; 32 | } 33 | 34 | /** In source code, you can ONLY call this method */ 35 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 36 | { 37 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 38 | if (self) { 39 | } 40 | return self; 41 | } 42 | 43 | - (void)viewDidLoad 44 | { 45 | [super viewDidLoad]; 46 | // Do any additional setup after loading the view. 47 | } 48 | 49 | - (void)didReceiveMemoryWarning 50 | { 51 | [super didReceiveMemoryWarning]; 52 | // Dispose of any resources that can be recreated. 53 | } 54 | 55 | -(void) tickCheckMemUsage 56 | { 57 | mach_port_t hostPort; 58 | mach_msg_type_number_t hostSize; 59 | vm_size_t pageSize; 60 | 61 | hostPort = mach_host_self(); 62 | hostSize = sizeof( vm_statistics_data_t) / sizeof(integer_t); 63 | host_page_size( hostPort, &pageSize); 64 | 65 | vm_statistics_data_t vmStat; 66 | 67 | if( host_statistics( hostPort, HOST_VM_INFO, (host_info_t) &vmStat, &hostSize) != KERN_SUCCESS) 68 | { 69 | NSLog(@"failed"); 70 | } 71 | else 72 | { 73 | natural_t memUsed = (vmStat.active_count + vmStat.inactive_count + vmStat.wire_count) * pageSize; 74 | 75 | natural_t memFree = vmStat.free_count * pageSize; 76 | // natural_t memTotal = memUsed + memFree; 77 | 78 | self.lFreeMem.text = [NSString stringWithFormat:@"%@ bytes", [NSNumberFormatter localizedStringFromNumber:@(memFree) numberStyle:NSNumberFormatterDecimalStyle]]; 79 | self.lUsedMem.text = [NSString stringWithFormat:@"%@ bytes", [NSNumberFormatter localizedStringFromNumber:@(memUsed) numberStyle:NSNumberFormatterDecimalStyle]]; 80 | } 81 | } 82 | 83 | -(void)tappedLoadTexture1:(id)sender 84 | { 85 | self.texture1 = [GLK2Texture textureNamed:@"world.topo.bathy.200412.3x16384x8192.A1-legacy"]; 86 | } 87 | 88 | -(void)tappedUnloadTexture1:(id)sender 89 | { 90 | self.texture1 = nil; 91 | } 92 | 93 | -(void)tappedLoadTexture2:(id)sender 94 | { 95 | self.texture2 = [GLK2Texture textureNamed:@"world.topo.200412.3x5400x2700"]; 96 | } 97 | 98 | -(void)tappedUnloadTexture2:(id)sender 99 | { 100 | self.texture2 = nil; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/MultithreadedLoadingTexturesViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | A ViewController 4 | 5 | */ 6 | #import "GLK2DrawCallViewController.h" 7 | 8 | @interface MultithreadedLoadingTexturesViewController : GLK2DrawCallViewController 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/MultithreadedLoadingTexturesViewController.m: -------------------------------------------------------------------------------- 1 | #import "MultithreadedLoadingTexturesViewController.h" 2 | 3 | #import "GLKX_Library.h" 4 | 5 | #import "GLK2Texture.h" 6 | 7 | #import "GLK2Texture+CoreGraphics.h" 8 | 9 | #import "CommonGLEngineCode.h" 10 | 11 | @interface MultithreadedLoadingTexturesViewController () 12 | 13 | @end 14 | 15 | @implementation MultithreadedLoadingTexturesViewController 16 | 17 | /** Override and trigger a background thread to upload textures to a new EAGLContext instance */ 18 | -(void)viewDidLoad 19 | { 20 | [super viewDidLoad]; 21 | 22 | 23 | } 24 | 25 | -(NSMutableArray*) createAllDrawCalls 26 | { 27 | /** All the local setup for the ViewController */ 28 | NSMutableArray* result = [NSMutableArray array]; 29 | 30 | /** 31 | Rotating cube with simple CALayer texture ("real" texture will be loaded asynch) 32 | */ 33 | 34 | GLK2DrawCall* dcCube = [CommonGLEngineCode drawCallWithUnitCubeAtOriginUsingShaders: 35 | [GLK2ShaderProgram shaderProgramFromVertexFilename:@"VertexProjectedWithTexture" fragmentFilename:@"FragmentWithTexture"]]; 36 | 37 | /** Do some drawing to a CGContextRef */ 38 | CGContextRef cgContext = [GLK2Texture createCGContextForOpenGLTextureRGBAWidth:256 h:256 bitsPerPixel:8 shouldFlipY:FALSE fillColorOrNil:[UIColor whiteColor]]; 39 | CGContextSetFillColorWithColor( cgContext, [UIColor colorWithRed:0 green:0.5 blue:0 alpha:1].CGColor ); 40 | UIGraphicsPushContext( cgContext ); // so we can use Apple's badly-designed NSString methods 41 | NSString* message = @"Loading\nPlease Wait"; 42 | [message drawInRect:CGRectMake(0,0,256,256) withFont:[UIFont systemFontOfSize:70]]; 43 | UIGraphicsPopContext(); 44 | 45 | /** Convert the CGContext into a GL texture */ 46 | GLK2Texture* newTexture = [GLK2Texture uploadTextureRGBAToOpenGLFromCGContext:cgContext width:256 height:256]; 47 | 48 | /** Add the GL texture to our Draw call / shader so it uses it */ 49 | GLK2Uniform* samplerTexture1 = [dcCube.shaderProgram uniformNamed:@"s_texture1"]; 50 | [dcCube setTexture:newTexture forSampler:samplerTexture1]; 51 | 52 | /** Set the projection matrix to Identity (i.e. "dont change anything") */ 53 | GLK2Uniform* uniProjectionMatrix = [dcCube.shaderProgram uniformNamed:@"projectionMatrix"]; 54 | GLKMatrix4 rotatingProjectionMatrix = GLKMatrix4Identity; 55 | [dcCube.shaderProgram setValueOutsideRenderLoopRestoringProgramAfterwards:&rotatingProjectionMatrix forUniform:uniProjectionMatrix]; 56 | 57 | [result addObject:dcCube]; 58 | 59 | return result; 60 | } 61 | 62 | -(void)willRenderDrawCallUsingVAOShaderProgramAndDefaultUniforms:(GLK2DrawCall *)drawCall 63 | { 64 | /*************** Rotate the entire world, for Shaders that support it *******************/ 65 | GLK2Uniform* uniProjectionMatrix = [drawCall.shaderProgram uniformNamed:@"projectionMatrix"]; 66 | if( uniProjectionMatrix != nil ) 67 | { 68 | /** Generate a smoothly increasing value using GLKit's built-in frame-count and frame-timers */ 69 | long slowdownFactor = 5; // scales the counter down before we modulus, so rotation is slower 70 | long framesOutOfFramesPerSecond = self.framesDisplayed % (self.framesPerSecond * slowdownFactor); 71 | float radians = framesOutOfFramesPerSecond / (float) (self.framesPerSecond * slowdownFactor); 72 | 73 | // rotate it 74 | GLKMatrix4 rotatingProjectionMatrix = GLKMatrix4MakeRotation( radians * 2.0 * M_PI, 1.0, 1.0, 1.0 ); 75 | 76 | [drawCall.shaderProgram setValue:&rotatingProjectionMatrix forUniform:uniProjectionMatrix]; 77 | } 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/VideoTextureViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Contains the sample code for rendering the current blog post at http://t-machine.org 3 | 4 | Any code that we wrote in early posts, and frequently re-use without changes, gets 5 | moved into the superclass for convenience 6 | */ 7 | #import 8 | #import 9 | 10 | #import "GLK2HardwareMaximums.h" 11 | #import "GLK2DrawCallViewController.h" 12 | 13 | #import 14 | 15 | @interface VideoTextureViewController : GLK2DrawCallViewController 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/ViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Contains the sample code for rendering the current blog post at http://t-machine.org 3 | 4 | Any code that we wrote in early posts, and frequently re-use without changes, gets 5 | moved into the superclass for convenience 6 | */ 7 | #import 8 | 9 | @interface ViewController : UIViewController 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/ViewControllers/ViewController.m: -------------------------------------------------------------------------------- 1 | #import "ViewController.h" 2 | 3 | @interface ViewController () 4 | 5 | @end 6 | 7 | @implementation ViewController 8 | 9 | - (void)dealloc 10 | { 11 | [super dealloc]; 12 | } 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GLKitExtended-Demo 4 | // 5 | // Created by adam on 30/11/2013. 6 | // Copyright (c) 2013 n/a. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /GLKX-Demo/Classes/split-mesh-lat-lines.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/Classes/split-mesh-lat-lines.mov -------------------------------------------------------------------------------- /GLKX-Demo/Configuration/GLKitExtended-Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.t-machine.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main_iPhone 29 | UIMainStoryboardFile~ipad 30 | Main_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /GLKX-Demo/Configuration/GLKitExtended-Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /GLKX-Demo/Configuration/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/GLK2/Default-568h@2x.png -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/GLK2/Default.png -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/GLK2/Default@2x.png -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/GLK2-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.t-machine.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard 29 | UIMainStoryboardFile~ipad 30 | MainStoryboard-iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIStatusBarHidden 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/GLK2-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GLK2' target in the 'GLK2' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /GLKX-Demo/GLK2/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /GLKX-Demo/GLKitExtended-Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/libGLKX-Library.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamgit/GL2KitExtensions/27d197f0a21e32f2c28c45e196785cd9a7eb868b/GLKX-Demo/Libraries/GLKitExtended/libGLKX-Library.a -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Attribute.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | Corresponds to an OpenGL 'attribute' item found in a shader source file, e.g. 5 | 6 | "mediump attribute vec4 color" 7 | 8 | */ 9 | #import 10 | 11 | @interface GLK2Attribute : NSObject 12 | 13 | +(GLK2Attribute*) attributeNamed:(NSString*) nameOfAttribute GLType:(GLenum) openGLType GLLocation:(GLint) openGLLocation GLSize:(GLint) openGLSize; 14 | 15 | /** The name of the variable inside the shader source file(s) */ 16 | @property(nonatomic, retain) NSString* nameInSourceFile; 17 | 18 | /** The magic key that allows you to "set" this attribute later by uploading a list/array of data to the GPU, e.g. using a VBO */ 19 | @property(nonatomic) GLint glLocation; 20 | 21 | /** GL ES 2 specifies possible types: 22 | 23 | (NB: Desktop GL has *more* types; the complete list is here, but most of them ARE NOT ALLOWED in ES 2: http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml ) 24 | 25 | BOOLEANS: bool, 2-bool-vector, 3-bool-vector, 4-bool-vector, 26 | INTEGERS: int, 2-int-vector, 3-int-vector, 4-int-vector, 27 | FLOATING POINTS: float, 2-float-vector, 3-float-vector, 4-float-vector, 2-matrix, 3-matrix, 4-matrix 28 | 29 | ... and the special types: (technically "uniforms" but have special code in OpenGL that treats them differently): 30 | 31 | TEXTURES: 2D texture, Cubemap texture 32 | */ 33 | @property(nonatomic) GLenum glType; 34 | 35 | /** Defined by OpenGL as "the size of the attribute, in units of the type returned in type." 36 | 37 | e.g. if "type" is 4-int-vector, and the attribute was declared as "vec4", then size will be "1". 38 | 39 | But (unconfirmed): if the attribute were declared as "vec4[2]", then size would be "2". i.e. "size" really 40 | means "sizeOfArrayIfThisIsAnArrayOtherwiseOne" - but I've seen it return some unexpected values in the past, 41 | so CAVEAT EMPTOR. 42 | */ 43 | @property(nonatomic) GLint glSize; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2BufferFormat.h: -------------------------------------------------------------------------------- 1 | /** 2 | This does not directly map to anything in OpenGL, but when you put interleaved data into a 3 | VertexBufferObject, OpenGL *requires* you to track the format of that interleaved data, and 4 | supply it back to OpenGL later. 5 | 6 | This class holds that data 7 | */ 8 | #import 9 | #import 10 | 11 | @interface GLK2BufferFormat : NSObject 12 | 13 | /** 14 | It would be much cleaner to accept e.g. "GLKVector3" as argument, but Apple chose to implement 15 | their OpenGL code in C, and C is a weak language, which has no introspection for struct types. 16 | 17 | i.e. there is no way for us to detect the difference between a GLKVector2 and a GLKVector3 etc. 18 | 19 | So, instead, we ask for the number of GL_FLOAT's. 20 | 21 | NB: this method is the "most commonly used simple VBO (1 x attribute containing a single GLKit 22 | struct - e.g. GLKVector3 or GLKMatrix4)" ... which explains the lack of detailed options. 23 | */ 24 | +(GLK2BufferFormat *)bufferFormatOneAttributeMadeOfGLFloats:(GLuint)numFloats; 25 | 26 | /** 27 | Fully configurable instantiator: this lets you specify multiple attributes in a single 28 | VBO, with any number of floats each, and any number of bytes per attribute (maybe you're using 29 | 32bit floats, maybe you're using 16bit, maybe you're using 64bit, etc) 30 | */ 31 | +(GLK2BufferFormat *)bufferFormatWithFloatsPerItem:(NSArray*) floatsArray bytesPerItem:(NSArray*) bytesArray; 32 | 33 | @property(nonatomic) int numberOfSubTypes; 34 | 35 | /** 36 | The VertexArrayObject methods are fundamentally incompatible, and use "floats" as the unit-of-size, instead of "bytes", 37 | so you need to know the number of floats-per-item-in-the-buffer, when it comes time to call glVertexAttribPointer 38 | */ 39 | -(GLuint) sizePerItemInFloatsForSubTypeIndex:(int) index; 40 | 41 | /** Buffers can contain any freeform data; however, to use a Buffer, OpenGL requires you to track the format of the 42 | contents, and tell it how many "bytes" each element in the buffer uses. 43 | 44 | e.g. for a GLKVector3, you have 3 floats, and each float is a 32bit number, i.e. 4 bytes. So, a GLKVector3 has 45 | a bytesPerItem = 3 * 4 = 12. 46 | 47 | Usually, you use C's sizeof property to auto-calculate this for you correctly. 48 | */ 49 | -(GLsizeiptr) bytesPerItemForSubTypeIndex:(int) index; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2BufferObject.h: -------------------------------------------------------------------------------- 1 | /** 2 | An OpenGL BufferObject - http://www.opengl.org/wiki/Buffer_Object 3 | 4 | Note that OpenGL requires you set the following for you to "use" a live buffer: 5 | 6 | - glBufferType (many GL methods need to be told which type, e.g. GL_ARRAY_BUFFER 7 | - bytesPerItem (required before uploading data to the GPU/bufferobject) 8 | 9 | */ 10 | #import 11 | #import "GLK2BufferFormat.h" 12 | 13 | /** Half of the "usage" parameter as defined on http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml */ 14 | typedef enum GLK2BufferObjectFrequency 15 | { 16 | GLK2BufferObjectFrequencyStream, 17 | GLK2BufferObjectFrequencyStatic, 18 | GLK2BufferObjectFrequencyDynamic 19 | } GLK2BufferObjectFrequency; 20 | 21 | /** Half of the "usage" parameter as defined on http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml */ 22 | typedef enum GLK2BufferObjectNature 23 | { 24 | GLK2BufferObjectNatureDraw, 25 | GLK2BufferObjectNatureRead, 26 | GLK2BufferObjectNatureCopy 27 | } GLK2BufferObjectNature; 28 | 29 | @interface GLK2BufferObject : NSObject 30 | 31 | /** 32 | Pre-Configures the buffertype to "GL_ARRAY_BUFFER", as required for VBO's 33 | 34 | The format argument is required (although you could provide "nil") because a VBO where you don't know 35 | the format is effectively junk data; it's very dangerous (in bugs / debugging terms) to allow yourself 36 | to create VBO's with no format 37 | */ 38 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat; 39 | 40 | /** 41 | Uploads an empty buffer exactly large enough to hold the specified number of 'items', so that you can later fill it up 42 | using glBufferSubData. Even though glBufferSubData might be horribly slow, this method is needed in the cases 43 | where you have to store different data over time into the same buffer with the SAME attribute. 44 | 45 | If you are storing different data in different attributes, create new Buffers for each attribute - it's 46 | faster and much easier to implement 47 | */ 48 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat allocateCapacity:(NSUInteger) numItemsToPreAllocate; 49 | 50 | /** 51 | Create a VBO and immediately upload some data to it - don't forget the format! You'll need this later in order to 52 | attach it to one or more VAO's */ 53 | +(GLK2BufferObject*) newVBOFilledWithData:(const void*) data inFormat:(GLK2BufferFormat*) bFormat numVertices:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq; 54 | 55 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 56 | @property(nonatomic, readonly) GLuint glName; 57 | 58 | /** A buffer can have any type; but as soon as you use it with a GL method, you have to specify the type. Generally, 59 | you create a buffer for a specific purpose and only use it for that - unless you're low on memory and need to re-use. 60 | 61 | You are allowed to change this, while keeping the data the same - OpenGL is happy for you to treat the data as 62 | "typeless". However, it may reduce performance if you change the type to a different type while the app is running, 63 | since the GPU *may have* done optimization based on the type you 'first' used with this buffer. 64 | 65 | c.f. http://www.opengl.org/wiki/Buffer_Object 66 | 67 | The static methods - e.g. "vertexBufferObject" - set this automatically 68 | */ 69 | @property(nonatomic) GLenum glBufferType; 70 | 71 | /** Buffers can contain any freeform data; however, to use a Buffer, OpenGL requires you to track the format of the 72 | contents, and tell it how many "bytes" each element in the buffer uses. 73 | 74 | e.g. for a GLKVector3, you have 3 floats, and each float is a 32bit number, i.e. 4 bytes. So, a GLKVector3 has 75 | a bytesPerItem = 3 * 4 = 12. 76 | 77 | Usually, you use C's sizeof property to auto-calcualte this for you correctly. I.e. if you've stored GLKVector3 objects 78 | in the buffer, call: 79 | 80 | (GLK2BufferObject).bytesPerItem = sizeof( GLKVector3 ); 81 | 82 | */ 83 | @property(nonatomic,retain) GLK2BufferFormat* currentFormat; 84 | 85 | /** 86 | Whenever you change the contentsFormat, this will be automatically updated 87 | */ 88 | @property(nonatomic,readonly) GLsizeiptr totalBytesPerItem; 89 | 90 | /** 91 | OpenGL has two parameters which are combined into a single value and used as a "usage hint"; obviously, it would have 92 | been cleaner and saner to use TWO "usage hints", but we're stuck with it. This method does the combining correctly for 93 | you, and automatically detects the cases that are illegal in GL ES 2 (but may be legal in other GL versions) 94 | */ 95 | -(GLenum) getUsageEnumValueFromFrequency:(GLK2BufferObjectFrequency) frequency nature:(GLK2BufferObjectNature) nature; 96 | 97 | /** Wraps glBufferData 98 | 99 | To automatically get the correct value for usageHint, use "getUsageEnumValueFromFrequency:nature:" 100 | */ 101 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage withNewFormat:(GLK2BufferFormat*) bFormat; 102 | 103 | /** 104 | Uses the existing buffer format (self.contentsFormat) - will fail if that is not set 105 | */ 106 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage; 107 | 108 | /** Wraps glBufferSubData -- NB this will ONLY work if you've already done a call to one of the "upload:" methods, 109 | OR if you created the buffer with a specific initial capacity; if not, the GPU won't have any memory allocated yet 110 | for you to upload into! 111 | 112 | */ 113 | -(void)uploadToOffset:(GLintptr)startOffset withData:(const void *)dataArray numItems:(int)count; 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Cube.h: -------------------------------------------------------------------------------- 1 | /** 2 | Apple has CGRect, and NSRect -- which use CGPoint and NSPoint 3 | Apple has NOTHING -- which uses GLKVector3 4 | 5 | ...but we need it whenever we talk about bounding-boxes in 3D, which is ...almost all the time! 6 | */ 7 | #import 8 | #import 9 | 10 | typedef struct GLK2Cube 11 | { 12 | GLKVector3 origin; 13 | GLKVector3 vectorAcross, vectorUp, vectorOut; 14 | } GLK2Cube; 15 | 16 | #pragma mark - NOTE: Apple doesn't provide a way for C projects/files to read the GLKit.h file, so we have to create a fake "class" to be allowed to write C functions 17 | 18 | @interface FAKE_CLASS_TO_SATISFY_APPLE : NSObject 19 | 20 | /** 21 | @param origin the "bottom left innermost corner" of the cube 22 | @param vAcross the vector in world space giving the cube's internal x-axis 23 | @param vUp the vector in world space giving the cube's internal y-axis 24 | @param vOut the vector in world space giving the cube's internal z-axis 25 | */ 26 | GLK2Cube GLK2CubeFromOriginAndBaseVectors( GLKVector3 o, GLKVector3 vAcross, GLKVector3 vUp, GLKVector3 vOut ); 27 | 28 | /** 29 | Returns a new cube with all base axes multiplied by the scalar 30 | */ 31 | GLK2Cube GLK2CubeMultiplyScalar( GLK2Cube oldCube, CGFloat scalar ); 32 | 33 | /** 34 | Adds offset to the cube's origin 35 | */ 36 | GLK2Cube GLK2CubeOffsetBy( GLK2Cube oldCube, GLKVector3 offset ); 37 | 38 | /** 39 | Takes the X, Y, and Z of vector, and multiplies the cube along its own axes by those 40 | amounts. 41 | 42 | e.g. for vector( 2, 1, 0 ), you get a new cube with cube.vectorAcross = 2* original, 43 | cube.vectorUp = original, and cube.vectorOut = 0 44 | */ 45 | GLK2Cube GLK2CubeMultiplyBaseVectors( GLK2Cube oldCube, GLKVector3 vector ); 46 | 47 | //NSString* NSStringFromGLK2Cube( GLK2Cube cube ); 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2DrawCall.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "GLK2ShaderProgram.h" 5 | #import "GLK2VertexArrayObject.h" 6 | #import "GLK2Texture.h" 7 | #import "GLK2UniformValueGenerator.h" 8 | 9 | /** 10 | Version 1: c.f. http://t-machine.org/index.php/2013/09/08/opengl-es-2-basic-drawing/ 11 | Part 3: ... not published yet ... 12 | */ 13 | @interface GLK2DrawCall : NSObject 14 | 15 | /** Massively helpful when debugging: give each one a human-readable title */ 16 | @property(nonatomic,retain) NSString* title; 17 | 18 | @property(nonatomic) BOOL shouldClearColorBit, shouldClearDepthBit; 19 | 20 | /** Every draw call MUST have a shaderprogram, or else it cannot draw objects nor pixels */ 21 | @property(nonatomic,retain) GLK2ShaderProgram* shaderProgram; 22 | 23 | /** You nearly always want this on, so that overlapping triangles correctly overlap, instead of having one or the other 24 | overwriting the ones IN FRONT OF it */ 25 | @property(nonatomic) BOOL requiresDepthTest; 26 | 27 | /** In almost all apps you want it ON */ 28 | @property(nonatomic) BOOL requiresCullFace; 29 | 30 | /** Enabling this on Apple/PVR devices MASSIVELY reduces performance, so only use it when genuinely needed. 31 | 32 | Requires you to also set: 33 | - alphaBlendSourceFactor 34 | - alphaBlendDestinationFactor 35 | */ 36 | @property(nonatomic) BOOL requiresAlphaBlending; 37 | 38 | /** 39 | For mode "requiresAlphaBlending = TRUE", defaults to: source = GL_ONE, dest = GL_ONE_MINUS_SRC_ALPHA 40 | */ 41 | @property(nonatomic) GLenum alphaBlendSourceFactor, alphaBlendDestinationFactor; 42 | 43 | /** If this draw call has ANY geometry, it should go in a VBO (stores raw Vertex attributes), 44 | and the VBO should be embedded in a VAO (which stores the metadata about the geometry) */ 45 | @property(nonatomic,retain) GLK2VertexArrayObject* VAO; 46 | 47 | /** i.e. GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN */ 48 | @property(nonatomic) GLuint glDrawCallType; 49 | 50 | /** When you run a Draw call, it can optionally render anything from "0" up to "all" of the 51 | vertex-data stored in the VAO/VBO's. 52 | 53 | So ... OpenGL requires you to specify exactly how many vertices you want to use 54 | every time you Draw. 55 | 56 | It's easiest to save this number at the time you upload data into your VBO's (it IS possible 57 | to get the number back later - but your VBO's may (optionally) be different lengths, e.g. if 58 | you're sharing VBO's between multiple draw-calls. So you need to store the nubmer-to-draw 59 | on a per-drawcall basis. 60 | */ 61 | @property(nonatomic) GLuint numVerticesToDraw; 62 | 63 | /** Each drawcall, this is inspected to calculate new values for every "uniform" in the pair of shaders */ 64 | @property(nonatomic,retain) NSObject* uniformValueGenerator; 65 | 66 | /** Textures in GL ES 2 are different from old-style OpenGL, and you MUST track the named 67 | shader-uniform / shader-sampler2d variable that each texture is 'attached' to; because of 68 | the way OpenGL handles texture-memory, you can't "do this once and forget about it", you 69 | have to keep re-doing it frame to frame */ 70 | @property(nonatomic,retain) NSMutableDictionary* texturesFromSamplers; 71 | 72 | #pragma mark - All the possible Draw call types supported in GL ES 2 73 | 74 | +(GLK2DrawCall*) drawCallPoints; 75 | +(GLK2DrawCall*) drawCallLines; 76 | +(GLK2DrawCall*) drawCallLineLoop; 77 | +(GLK2DrawCall*) drawCallLineStrip; 78 | +(GLK2DrawCall*) drawCallTriangles; 79 | +(GLK2DrawCall*) drawCallTriangleStrip; 80 | +(GLK2DrawCall*) drawCallTriangleFan; 81 | 82 | #pragma mark - init methods 83 | 84 | /** 85 | Defaults to: 86 | 87 | - clear color MAGENTA 88 | - depth test ON 89 | - cull back-facing polygons ON 90 | 91 | ... everything else: OFF 92 | */ 93 | -(id) initWithTitle:(NSString*) title; 94 | 95 | /** 96 | Delegates to initWithTitle, using a random string for the title 97 | */ 98 | - (id)init; 99 | 100 | -(float*) clearColourArray; 101 | -(void) setClearColourRed:(float) r green:(float) g blue:(float) b alpha:(float) a; 102 | 103 | #pragma mark Missing GL methods for handling Uniforms in Shaders each frame 104 | 105 | /** MUST be called AFTER setting this drawcall's shader to current 106 | (e.g. within the update / drawFrame loop) 107 | */ 108 | -(void) setAllUniformValuesForShader; 109 | 110 | #pragma mark Texturing and texture-mapping methods 111 | 112 | /** When the draw-call runs, it will look up all the 'sampler2D' objects in the Shader sourcecode, 113 | and then try to find an appropriate OpenGL Texture / GLK2Texture for each one. 114 | 115 | Make sure you call this method at least for each sampler in your shader (the contents are preserved 116 | even if you change shader-program at runtime, so you can have "more" of these mapped than necessary, 117 | if you want) 118 | 119 | @param texture if nil, will "remove" the sampler/texture pair from the mapping for this drawcall 120 | @return the OpenGL texture-unit that this drawcall wants to use for that texture 121 | */ 122 | -(GLuint) setTexture:(GLK2Texture*) texture forSampler:(GLK2Uniform*) sampler; 123 | /** 124 | Convenience version of method that takes a name, and fetches the sampler for you */ 125 | -(GLuint) setTexture:(GLK2Texture*) texture forSamplerNamed:(NSString*) samplerName; 126 | 127 | /** 128 | For hot-swapping textures, you often need to ask a drawcall: 129 | 130 | "which GLK2Texture object do you currently use for sampler BLAH?" 131 | 132 | */ 133 | -(GLK2Texture*)getTextureForSamplerNamed:(NSString *)samplerName; 134 | 135 | /** Massive bug in OpenGL API: ShaderPrograms DO NOT USE the correct texture-unit ID's (i.e. GL_TEXTURE0 etc) 136 | for identifying texture-units; instead, they use "the offset to add to GL_TEXTURE0" 137 | */ 138 | -(GLint)textureUnitOffsetForSampler:(GLK2Uniform *)sampler; 139 | 140 | #pragma mark - workaround for OpenGL API bug: GL ES VAO's "cannot" be shared across threads 141 | 142 | /** 143 | Converts this DrawCall from one created on "any thread except the main one" to "a valid 144 | renderable drawcall", assuming you are CURRENTLY EXECUTING ON THE MAIN RENDER THREAD 145 | 146 | Alternatively, use copyDrawCallAllocatingNewVAO below 147 | */ 148 | -(void) reCreateVAOOnCurrentThread; 149 | 150 | /** 151 | The OpenGL committee are sometimes evil - they decided to break GL ES so that VAO's 152 | can't be shared across threads. 153 | 154 | This also prevents you from loading background geometry. It's a MAJOR bug in the API. 155 | 156 | The only workaround is to load your geometry once, then clone your draw-calls, creating 157 | new VAO's, and re-assign the VBO's (which ARE shared) to the new VAO's on the new thread. 158 | 159 | Alternatively, use reCreateVAOOnCurrentThread above (but make sure you're in the main thread and not mid-render!) 160 | */ 161 | -(id) copyDrawCallAllocatingNewVAO; 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2DrawCallViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Refactoring-1 (approximately Part 7) 3 | 4 | Extension of Apple's GLKViewController that adds support for the 5 | GLK2DrawCall class. OpenGL revolves around Draw calls! 6 | 7 | This class implements the basic OpenGL rendering loop, layered on 8 | top of Apple's GLKViewController built-in loop: 9 | 10 | 0. GENERAL: integrates correctly with viewDidLoad etc, as per Apple docs 11 | 1. SETUP: create and set a valid EAGLContext, or crash/error 12 | 2. SETUP: generate a set of "initial Draw calls" (or none) 13 | 3. LOOP FOREVER: render a single "frame" to the screen 14 | 15 | The "frame" doesn't exist in OpenGL, strictly speaking, but it's a 16 | useful concept. To render a frame, we split it up like this: 17 | 18 | 3a. EACH FRAME: callback for subclasses to know a new frame is starting 19 | 3b. EACH FRAME: request a sorted list of Draw calls to render 20 | 3c. EACH FRAME LOOP: for each Draw call: 21 | 3c-i. update all GL state 22 | 3c-ii. update all shader-uniforms 23 | 3c-iii. render that Draw call 24 | 3c-iv. reset state as required 25 | 26 | OpenGL ES 2 has approximately 15 different pieces of "high-level" 27 | render-state; to render a single Draw call, all of them have to be 28 | turned on, or off, and configured, or reset, or re-allocated, or 29 | re-uploaded (e.g. texture maps). Hence the "for each Draw call" 30 | above is a lot of boilerplate code. 31 | 32 | IMPORTANT NOTE: 33 | 34 | This class is incomplete; it only handles the bits of GL state that have 35 | been covered by the tutorials already posted to http://t-machine.org - anything 36 | not yet written about will need to be added by hand if you use this class. 37 | */ 38 | #import 39 | 40 | #import 41 | 42 | #import "GLK2DrawCall.h" 43 | 44 | @interface GLK2DrawCallViewController : GLKViewController 45 | 46 | /** 47 | An EAGLContext is needed for 95% of OpenGL calls to work. 48 | 49 | It's supposed to be 100%, but some - e.g. glClear - miraculously work without it 50 | when running on Apple OS's. 51 | */ 52 | @property(nonatomic,retain) EAGLContext* localContext; 53 | 54 | @property(nonatomic, retain) NSMutableArray* drawCalls; 55 | 56 | /** 57 | Every app needs to use its own code here: the exact set of draw-calls 58 | is where the custom rendering takes place, or is configured 59 | */ 60 | -(NSMutableArray*) createAllDrawCalls; 61 | 62 | /** 63 | Called once at start of each frame; sole purpose is to allow you to do per-frame 64 | setup (note: per-drawcall setup of Uniforms is done in a different callback) 65 | */ 66 | -(void)willRenderFrame; 67 | 68 | /** Called prior to rendering a draw-call, enabling subclasses to e.g. change uniforms 69 | just prior to that draw-call being rendered 70 | 71 | NB: this is called AFTER the VAO and shader-program have been set - so you are safe 72 | to immediately, nakedly, set Uniforms etc 73 | */ 74 | -(void) willRenderDrawCallUsingVAOShaderProgramAndDefaultUniforms:(GLK2DrawCall*) drawCall; 75 | 76 | #pragma mark - Optional overrides for subclasses ONLY 77 | 78 | /** Subclasses can override this if they need to subvert the render-loop itself. 79 | 80 | This is rare but sometimes useful if e.g. you want to have all your app-logic triggered 81 | by the renderloop itself. 82 | 83 | If overriding, be sure to call [super update] when you want the main rendering logic to 84 | execute 85 | */ 86 | -(void) update; 87 | 88 | /** Subclasses can override this if they need to e.g. specialize the order in which drawcalls are 89 | drawn (e.g. pre-sorting, alpha-sorting, etc) 90 | */ 91 | -(void) renderSingleFrame; 92 | 93 | /** Subclasses can call this if overriding "renderSingleFrame", to use this class's detailed 94 | version (it's a long method) 95 | */ 96 | -(void) renderSingleDrawCall:(GLK2DrawCall*) drawCall; 97 | 98 | /** Apple's driver is very slow at switching shaderprogram, and won't check if it's already set */ 99 | @property(nonatomic) GLuint currentlyActiveShaderProgramName; 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2ExampleUniformValueGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Trivial example / base class for implementing the GLK2UniformValueGenerator protocol 5 | 6 | (note how the .m file implements the different methods) 7 | */ 8 | #import 9 | 10 | #import "GLK2UniformValueGenerator.h" 11 | 12 | @interface GLK2ExampleUniformValueGenerator : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2HardwareMaximums.h: -------------------------------------------------------------------------------- 1 | /** 2 | Requesting this info actually takes time, but cannot change over lifetime of the app, 3 | because it's permanent hardware info. 4 | 5 | Note: some Android phones might switch between multiple GPUs, but for OpenGL ES on iOS 6 | ... you'll only ever have one GPU / GL driver available 7 | 8 | Makes life easier to collect this info at program start, and cache it on CPU side. 9 | 10 | Make sure you call [* readAllGLMaximums] at least once at the start of your app - but AFTER 11 | the GL has been setup and configured, and you've done a [GLKview bindDrawable] etc 12 | */ 13 | #import 14 | 15 | /** Apple's engineers are misguided in believing you can write software without knowing how 16 | much RAM is in the physical device. 17 | 18 | With OpenGL, where e.g. iPad Mini loads the same 4k 19 | textures as an iPad3, but has considerably LESS RAM ... you WILL get crashes if you try to 20 | load the same textures on both devices. 21 | */ 22 | typedef NS_ENUM(NSInteger, DeviceMemoryInBytes ) 23 | { 24 | DeviceMemory0Bytes, 25 | DeviceMemory128MegaBytes, 26 | DeviceMemory256MegaBytes, 27 | DeviceMemory512MegaBytes, 28 | DeviceMemory1024MegaBytes, 29 | DeviceMemory2048MegaBytes 30 | }; 31 | 32 | @interface GLK2HardwareMaximums : NSObject 33 | 34 | /** The first time you invoke this, it reads the values from the GPU. 35 | 36 | Afterwards, it uses cached data 37 | */ 38 | +(GLK2HardwareMaximums*) sharedInstance; 39 | 40 | /** Maximum width or height of any texture, in pixels */ 41 | @property(nonatomic,readonly) GLint glMaxTextureSize; 42 | 43 | /** Amount of RAM the iOS device contains (constrains texture-ram, but is total RAM) */ 44 | @property(nonatomic,readonly) DeviceMemoryInBytes iOSDeviceRAM; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Shader.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | The most important method is shaderFromFilename:type: 5 | */ 6 | #import 7 | 8 | #import "GLK2ShaderProgram.h" 9 | 10 | /** 11 | GL ES 2 has exactly two types of shader, but desktop GL has more, and we expect future versions of ES to add them in 12 | */ 13 | typedef enum GLK2ShaderType 14 | { 15 | GLK2ShaderTypeVertex = GL_VERTEX_SHADER, 16 | GLK2ShaderTypeFragment = GL_FRAGMENT_SHADER 17 | } GLK2ShaderType; 18 | 19 | /** 20 | Useful for internal sanity checks 21 | */ 22 | typedef enum GLK2ShaderStatus 23 | { 24 | GLK2ShaderStatusUncompiled, 25 | GLK2ShaderStatusCompiled, 26 | GLK2ShaderStatusLinked 27 | } GLK2ShaderStatus; 28 | 29 | @interface GLK2Shader : NSObject 30 | 31 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 32 | @property(nonatomic, readonly) GLuint glName; 33 | 34 | @property(nonatomic) GLK2ShaderType type; 35 | @property(nonatomic) GLK2ShaderStatus status; 36 | 37 | /** Filename for the shader with NO extension; assumes all Vertex shaders end .vsh, all Fragment shaders end .fsh */ 38 | @property(nonatomic,retain) NSString* filename; 39 | 40 | /** Convenience method that sets up the shader, ready to be compiled */ 41 | +(GLK2Shader*) shaderFromFilename:(NSString*) fname type:(GLK2ShaderType) type; 42 | 43 | /** Compiles the shader; you have to do setup of a GLK2ShaderProgram / OpenGL ShaderProgram also */ 44 | -(void) compile; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2ShaderProgram.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | ShaderProgram is a boilerplate concept that is REQUIRED to be identical for all OpenGL apps; this class is intended to be 5 | reused everywhere without changes. A ShaderProgram in OpenGL ES 2 is "1 x vertex shader + 1 x fragment shader, combined into 6 | a single item". 7 | 8 | (NB: this version is incomplete, a basic implementation only, next version will add a few missing features, and then never 9 | need to be edited again) 10 | */ 11 | #import 12 | 13 | #import "GLK2Attribute.h" 14 | #import "GLK2Uniform.h" 15 | 16 | #define DEBUG_ATTRIBUTE_HANDLING 0 17 | #define DEBUG_UNIFORM_HANDLING 0 18 | 19 | typedef enum GLK2ShaderProgramStatus 20 | { 21 | GLK2ShaderProgramStatusUnlinked, 22 | GLK2ShaderProgramStatusLinked 23 | } GLK2ShaderProgramStatus; 24 | 25 | @class GLK2Shader; 26 | 27 | @interface GLK2ShaderProgram : NSObject 28 | 29 | /** 30 | 31 | Does all the work of: 32 | 33 | - finding vertex + fragment shaders on disk 34 | - loading the source code of the shaders 35 | - compiling them 36 | - linking them 37 | - storing post-link info that OpenGL apps MUST have in order to work corectly 38 | 39 | */ 40 | +(GLK2ShaderProgram*) shaderProgramFromVertexFilename:(NSString*) vFilename fragmentFilename:(NSString*) fFilename; 41 | 42 | @property(nonatomic) GLK2ShaderProgramStatus status; 43 | 44 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 45 | @property(nonatomic, readonly) GLuint glName; 46 | 47 | /** Setting either property automatically calls glAttachShader */ 48 | @property(nonatomic,retain) GLK2Shader* vertexShader, * fragmentShader; 49 | 50 | /** the "link" stage automatically finds all "attribute" lines in the shader source, and creates one GLK2Attribute for each */ 51 | -(GLK2Attribute*) attributeNamed:(NSString*) name; 52 | /** the "link" stage automatically finds all "attribute" lines in the shader source, and creates one GLK2Attribute for each */ 53 | -(NSArray*) allAttributes; 54 | 55 | -(GLK2Uniform*) uniformNamed:(NSString*) name; 56 | -(NSArray*) allUniforms; 57 | 58 | #pragma mark - GLSL validation - do NOT use in a live app! 59 | 60 | -(void) validate; 61 | 62 | #pragma mark - Set the value of a Uniform 63 | 64 | /** 65 | NOTE: it is always safe to call this from anywhere in the program, so long as the renderer's thread is blocked, 66 | OR you are inside that thread. 67 | 68 | The simpler/faster version of this method only works if you are actually inside the render-loop itself, which is 69 | only true for the renderer 70 | 71 | Note: both methods set internal state that helps with debugging; you can use either - but don't use the private 72 | internal methods! 73 | */ 74 | -(void) setValueOutsideRenderLoopRestoringProgramAfterwards:(const void*) value forUniform:(GLK2Uniform*) uniform; 75 | 76 | /** NOTE: this must ONLY be invoked inside the main render-loop, and ONLY when the render-loop has set the 77 | current glProgram to this one. 78 | 79 | When you need to set values outside the render-loop - e.g. nearly always: because you're configuring a new shader/ 80 | drawcall - instead use setValueOutsideRenderLoopRestoringProgramAfterwards:forUniform -- that method will switch to 81 | this shaderprogram, set the value, and then switch BACK to the original program being used by the main renderer. 82 | 83 | If you incorrectly use this method when you should have used the other, GL state will leak between drawcalls/shaders 84 | and CHAOS! will break loose upon thy rendering... You will also think you've gone insane when you try to debug it, 85 | and 1 proves to be equal to 0. (voice of bitter experience) 86 | 87 | Note: both methods set internal state that helps with debugging; you can use either - but don't use the private 88 | internal methods! 89 | */ 90 | -(void) setValue:(const void*) value forUniform:(GLK2Uniform*) uniform; 91 | 92 | /** 93 | OpenGL debugging is badly designed and almost unusable; all manufacturers provide hacks to give you what you need, 94 | except Apple - who prevents you from using the manufacturer's tools (Imagination / PowerVR doesn't seem very happy 95 | about this!). 96 | 97 | One side-effect: OpenGL will silently break everything if a Uniform that needs to be set ... isn't ... for any reason 98 | and will not give you any way of finding this out. 99 | 100 | This method tracks (imperfectly, but accurate so long as you only use the public methods in this class) what uniforms 101 | you've set / not set yet 102 | */ 103 | -(NSArray*) uniformsWithoutValues; 104 | 105 | /** automatically calls glCreateProgram() */ 106 | - (id)init; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Texture+CoreGraphics.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | */ 4 | 5 | #import "GLK2Texture.h" 6 | #import 7 | 8 | @interface GLK2Texture (CoreGraphics) 9 | 10 | /** 11 | 1 of 2: 12 | 13 | Create a CGContext that you can convert into a texture. 14 | 15 | This creates the CPU-side memory and context 16 | */ 17 | +(CGContextRef) createCGContextForOpenGLTextureRGBAWidth:(int) width h:(int) height bitsPerPixel:(int) bpp shouldFlipY:(BOOL) flipY fillColorOrNil:(UIColor*) fillColor; 18 | 19 | /** 20 | 2 of 2: 21 | 22 | Convert a previously-created CGContext into an OpenGL texture, and upload to the GPU 23 | */ 24 | +(GLK2Texture*) uploadTextureRGBAToOpenGLFromCGContext:(CGContextRef) context width:(int)w height:(int)h; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Texture+CoreVideo.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Requires you to add the CoreVideo framework to your project if you want to use this. 5 | */ 6 | #import "GLK2Texture.h" 7 | 8 | @interface GLK2Texture (CoreVideo) 9 | 10 | +(GLK2Texture*) texturePreCreatedByApplesCoreVideo:(CVOpenGLESTextureRef) applCoreVideoTexture; 11 | 12 | /** 13 | THIS METHOD IS AGAINST THE ENTIRE ETHOS OF OPENGL, but Apple does some weird and crazy stuff 14 | inside CoreVideo, and refuses to document it - as a result, we HAVE to do this, or else we'll 15 | get memory leaks and app crashes and flickering etc. 16 | 17 | (basically: Apple trashes the GL textures, over and over again, at random rates, depending on 18 | how much CPU / GPU processing is happening in the background. NONE OF THIS IS DOCUMENTED!) 19 | 20 | Until Apple documents their shamefully obscure API (it's been 2 years now and we're all still waiting!) 21 | we have to accept that Apple "switches" the texture IDs of live textures around, and we have to 22 | follow suit. 23 | */ 24 | -(void) liveAlterGLNameToWorkaroundAppleCoreVideoBug:(GLuint) newName; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Texture.h: -------------------------------------------------------------------------------- 1 | /** 2 | From the OpenGL org wiki (http://www.opengl.org/wiki/Texture): 3 | 4 | "Binding textures for use in OpenGL is a little weird." 5 | 6 | -- Really? You don't say... 7 | 8 | And Apple solves half the problems, but creates as many new problems as the ones they solve. 9 | 10 | ARGH! 11 | 12 | So ... this is an annoying class, it shouldn't be needed - but it is, let me explain... 13 | 14 | -------------- (explanation starts) -------------- 15 | From the Apple docs on GLKTextureInfo: 16 | 17 | (https://developer.apple.com/library/ios/documentation/GLkit/Reference/GLKTextureInfo_Ref/Reference/Reference.html#//apple_ref/occ/instp/GLKTextureInfo/textureOrigin) 18 | 19 | "Your app never creates GLKTextureInfo objects directly" 20 | 21 | Why? Ideology? Someone at Apple doesn't like other programmers writing 22 | source code, adding features, fixing bugs, extending functionality? 23 | 24 | If Apple's GLKTextureLoader class actually worked (it doesn't; it has massive bugs - that 25 | I've reported to Apple, but been told 'I'll never fix it' by Apple engineers) 26 | ... maybe they could get away with sealing their classes like this. 27 | 28 | But it doesn't work. And it doesn't support PVR any more (the file-format has moved on, 29 | Apple's source code is now obsolete, and Apple hasn't updated it). So ... we need to 30 | replace GLKTextureInfo with a class that we're "allowed" to set values on, so we can 31 | fix Apple's bugs. 32 | -------------- (explanation ends) -------------- 33 | 34 | What does this class does: 35 | 36 | - unifies "Apple's proprietary GLKTextureInfo class" with "genuine OpenGL textures" 37 | - represents 1:1 an OpenGL texture 38 | - OpenGL textures can live on CPU, GPU, both, neither - this class tracks where the texture is, and if it needs reloading 39 | - provides a single datatype that your own, custom, texture importers can safely import to, and your app code can read from 40 | 41 | Very important: 42 | 43 | - this class can UNLOAD it's texture from the GPU (e.g. when low on memory), and then RELOAD it later, while the app is running 44 | 45 | (OpenGL can't/won't do that automatically, and if you don't track texture-status using a class like this one, it's hard 46 | to do yourself) 47 | 48 | */ 49 | #import 50 | #import 51 | 52 | #define USE_GLK2TEXTURETRACKER_INTERNALLY 1 // set to 0 if you want to build without the extended classes e.g. GLK2TextureTracker 53 | 54 | @interface GLK2Texture : NSObject 55 | 56 | /** 57 | Creates a new empty texture on the GPU. You'll have to fill this later with one of the uploading methods. 58 | 59 | Generally, you do NOT want this method - it's best to upload a texture immmediately, or not create it until you 60 | need it. But in some cases (e.g. when multiple drawcalls are going to share a texture) it's safer to create the 61 | GPU texture first, and pass this texture object to each drawcall during config, so that they never get out of 62 | synch, and upload the texture data later. 63 | */ 64 | +(GLK2Texture*) textureNewEmpty; 65 | 66 | /** Tries to load a texture in the same way as Apple's [UIImage imageNamed] method: by searching the bundle, and then 67 | delegating to Apple's broken GLKit texture-loader (because that loader explicitly is designed to do this, even though 68 | it's very buggy) */ 69 | +(GLK2Texture*) textureNamed:(NSString*) filename; 70 | 71 | /** If you use Apple's broken GLKit texture-loader, you'll need to store and manipulate the output, but Apple blocks you 72 | from doing this (for no apparent reason). So this method lets you convert from Apple's badly designed proprietary class 73 | into an instance that you can safely use */ 74 | +(GLK2Texture*) texturePreLoadedByApplesGLKit:(GLKTextureInfo*) appleMetadata; 75 | 76 | /** 77 | If your texture is already on the GPU and/or was created by 3rdparty code, this lets you 78 | create a CPU-side GLK2Texture object to manage it 79 | */ 80 | +(GLK2Texture*) textureAlreadyOnGPUWithName:(GLuint) existingName; 81 | 82 | /** 83 | Note that a raw stream of bytes contains NO INFORMATION about width/height of texture, so you need to provide those 84 | details in the parametrs. 85 | 86 | Critically important: this requires the data to be in RAW BYTES, exactly as you'd expect from the method name; this is 87 | INCOMPATIBLE with Apple's undocumented NSData-loading method (which crashes if you give it anything except 88 | an ENCODED jpeg or png or pvr-v1) */ 89 | +(GLK2Texture *)textureFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh; 90 | 91 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 92 | @property(nonatomic, readonly) GLuint glName; 93 | 94 | /** Defaults to TRUE: there is only one known case where you DON'T want this behaviour: Apple's badly-documented CoreVideo for pulling frames from Camera onto GL texture, where Apple REQUIRES you to manually buffer 95 | textures from frame-to-frame until they "die" at a non-specified time of Apple's internal choosing */ 96 | @property(nonatomic) BOOL willDeleteOnDealloc; 97 | 98 | /** Creates a new, blank, OpenGL texture on the GPU. 99 | 100 | If you already created a texture from some other source, use the initWithName: method instead 101 | */ 102 | - (id)init; 103 | 104 | /** If a texture was loaded by an external source - e.g. Apple's GLKit - you'll already have a name for it, and can 105 | use this method 106 | 107 | NB: this is the designated initializer; this is particularly important w.r.t. GLK2TextureTracker and subclassing 108 | this class 109 | */ 110 | - (id)initWithName:(GLuint) name; 111 | 112 | -(void) uploadFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh; 113 | 114 | /** Advanced: 115 | 116 | Mostly useful when hot-swapping a teture, this call drops the old .glName (and issues a glDeleteTeture on it 117 | unless willDeleteOnDealloc is set to FALSE), then it grabs the incoming value and sets it as self.glName. 118 | 119 | From this moment onwards, all rendering that indirects via this instance will use the "new" GPU-side teture 120 | instead of the old one. 121 | */ 122 | -(void) reAssociateWithNewGPUTeture:(GLuint) newTetureName; 123 | 124 | /** Wraps the texture in S */ 125 | -(void) setWrapSRepeat; 126 | -(void) setWrapTRepeat; 127 | /** Clamps the texture in S */ 128 | -(void) setWrapSClamp; 129 | -(void) setWrapTClamp; 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2TextureLoaderPVRv1.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Based on Apple's example source code "PVRTexture.h / .m version 1.5", heavily modified 5 | 6 | Apple's code is very outdated, and only loads v1 PVR files. PVR supports these using 7 | the "legacy" option in the Imagination / PVR tools - anything else will fail / crash. 8 | */ 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | #import "GLK2Texture.h" 15 | 16 | @interface PVRTextureV1 : GLK2Texture 17 | 18 | @property(nonatomic,retain,readonly) NSMutableArray *imageData; 19 | 20 | @property(nonatomic,readonly) uint32_t width, height; 21 | 22 | @property(nonatomic,readonly) GLenum internalFormat; 23 | @property(nonatomic,readonly) BOOL hasAlpha; 24 | 25 | /** filename/path if it was from disk, or URL string if from URL */ 26 | @property(nonatomic,retain,readonly) NSString* textureSourceFileInfo; 27 | 28 | @end 29 | 30 | @interface GLK2TextureLoaderPVRv1 : NSObject 31 | 32 | /** 33 | Returns a GL2KTexture object, with the PVR texture pre-uploaded to the GPU, 34 | and any MipMaps created as appropriate, as limited by setMaximumTextureSizeToLoadInMipMaps: 35 | */ 36 | + (PVRTextureV1*)pvrTextureWithContentsOfFile:(NSString *)path; 37 | 38 | /** 39 | Returns a GL2KTexture object, with the PVR texture pre-uploaded to the GPU, 40 | and any MipMaps created as appropriate, as limited by setMaximumTextureSizeToLoadInMipMaps: 41 | */ 42 | + (PVRTextureV1*)pvrTextureWithContentsOfURL:(NSURL *)url; 43 | 44 | /** 45 | Some Apple hardware - most notably the iPad Mini - "can" read 4k,4k textures, but the thing has 46 | nowhere near enough RAM to actually run an app at the same time (it uses same-size textures as an 47 | iPad 3 / 4 / 5, but has ONE QUARTER of the RAM!). 48 | 49 | This method allows you to prevent mipmaps being loaded, even if the chip says it "can", but you know 50 | it "shouldn't" 51 | 52 | This is measured in the same units as GL's glGetIntegerv( GL_MAX_TEXTURE_SIZE, ... ) - e.g. 4096 is 53 | equal to "a texture 4096 pixels wide, and 4096 pixels high" 54 | 55 | If you send a value of "0" that will be treated as "no limit" (which is the default) 56 | */ 57 | +(void)setMaximumTextureSizeToLoadInMipMaps:(GLint) newMax; 58 | 59 | @end -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2TextureTracker.h: -------------------------------------------------------------------------------- 1 | /** 2 | Tracks all GL texture allocation, creation, destruction, re-use, etc. 3 | 4 | ALSO: intelligently manages memory for textures (e.g. calling glDeleteTextures 5 | when appropriate). 6 | 7 | Partly this class is for debugging! If only Apple's Frame-analyzer were faster / had the 8 | features of ATI, nVidia, etc. 9 | 10 | BUT ALSO: this class is very useful as a low-level / generic texture management system. 11 | You can extend it / build on it to make your own custom manager - but this handles the 12 | very basics that all GL apps need. 13 | */ 14 | #import 15 | 16 | #import "GLK2Texture.h" 17 | 18 | @interface GLK2TextureTracker : NSObject 19 | 20 | +(GLK2TextureTracker*) sharedInstance; 21 | 22 | #pragma mark - General methods for supporting 3rd party classes 23 | 24 | /** If you create a texture manually, NOT using GLK2Texture, make sure you inform the tracker, or else it MIGHT auto-delete your texture when there are no more GLK2Texture's using it */ 25 | -(void) gpuTextureCreatedWithoutClassTexture:(GLuint) textureName; 26 | /** Signals to this class that it MAY delete the GPU texture if nothing else is still using it */ 27 | -(void) gpuTextureReleasedWithoutClassTexture:(GLuint) textureName; 28 | 29 | #pragma mark - Automatic Integration with GLKX / GLK2 classes 30 | 31 | /** Invoked by GLK2Texture every time a new class is created on CPU representing a texture */ 32 | -(void) classTextureCreated:(GLK2Texture*) texture; 33 | 34 | /** Invoked by GLK2Texture every time a class on CPU representing a texture is dealloc'd */ 35 | -(void) classTextureDeallocing:(GLK2Texture*) texture; 36 | 37 | #pragma mark - Useful diagnostics and output info 38 | 39 | -(NSUInteger) totalGLTexturesCurrentlyOnGPU; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2Uniform.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | **** NB: if you add any properties, make sure you add them to "copyWithZone:" method too 4 | 5 | */ 6 | #import 7 | 8 | @interface GLK2Uniform : NSObject /** Apple's design of NSDictionary forces us to 'copy' keys, instead of mapping them */ 9 | 10 | +(GLK2Uniform*) uniformNamed:(NSString*) nameOfUniform GLType:(GLenum) openGLType GLLocation:(GLint) openGLLocation numElementsInArray:(GLint) numElements; 11 | 12 | /** The name of the variable inside the shader source file(s) */ 13 | @property(nonatomic, retain) NSString* nameInSourceFile; 14 | 15 | /** The magic key that allows you to "set" this uniform later, with a new value every frame (or draw call) */ 16 | @property(nonatomic) GLint glLocation; 17 | 18 | /** GL ES 2 specifies possible types: 19 | 20 | (NB: Desktop GL has *more* types; the complete list is here, but most of them ARE NOT ALLOWED in ES 2: http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml ) 21 | 22 | BOOLEANS: bool, 2-bool-vector, 3-bool-vector, 4-bool-vector, 23 | INTEGERS: int, 2-int-vector, 3-int-vector, 4-int-vector, 24 | FLOATING POINTS: float, 2-float-vector, 3-float-vector, 4-float-vector, 2-matrix, 3-matrix, 4-matrix 25 | 26 | ... and the special types: (technically "uniforms" but have special code in OpenGL that treats them differently): 27 | 28 | TEXTURES: 2D texture, Cubemap texture 29 | */ 30 | @property(nonatomic) GLenum glType; 31 | 32 | /** A uniform can be an "array of" values, rather than a single value. This is "1" for a single value, or array length otherwise. From GL docs: 33 | 34 | "Uniform variables other than arrays 35 | will have a size of 1. Structures and arrays of structures will 36 | be reduced as described earlier, such that each of the names 37 | returned will be a data type in the earlier list. If this 38 | reduction results in an array, the size returned will be as 39 | described for uniform arrays; otherwise, the size returned will 40 | be 1." 41 | 42 | */ 43 | @property(nonatomic) GLint arrayLength; 44 | 45 | #pragma mark - Interpretation of OpenGL's badly-typed "type" feature 46 | 47 | @property(nonatomic,readonly) BOOL isInteger, isFloat, isVector, isMatrix; 48 | 49 | /** 4x4 matrix returns "4", etc - OpenGL has this info, refuses to provide it, but bizarrely: requires the application to re-submit it */ 50 | -(int) matrixWidth; 51 | 52 | /** 4x1 vector returns "4", etc - OpenGL has this info, refuses to provide it, but bizarrely: requires the application to re-submit it */ 53 | -(int) vectorWidth; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2UniformMap.h: -------------------------------------------------------------------------------- 1 | /** 2 | OpenGL is a C-only library. Apple did NOT implement it to be Obj-C compatible. 3 | 4 | Mostly this is not a problem, but Shader Uniforms have to be sent as "non-object pointers", 5 | which causes chaos: none of the Obj-C libraries support this. You are required to 6 | write some pure-C code to convert ObjC, which is ridiculous (and VERY slow). 7 | 8 | This class uses the info we have about Uniforms (that they can only have one of a small number 9 | of types, each of which is a struct) to construct an efficient and simple solution. 10 | 11 | Apple REALLY should have included this in GLKit! 12 | */ 13 | #import 14 | 15 | #import 16 | #import "GLK2ShaderProgram.h" 17 | 18 | @interface GLK2UniformMap : NSObject 19 | 20 | /** 21 | Allocates precisely the amount of storage needed to hold all uniform names and values 22 | for the ShaderProgram you provide. 23 | 24 | Make sure the shaderProgram is already linked, otherwise it might have NO INFO on which 25 | uniforms it contains! 26 | */ 27 | +(GLK2UniformMap*) uniformMapForLinkedShaderProgram:(GLK2ShaderProgram*) shaderProgram; 28 | 29 | /** 30 | Allocates precisely the amount of storage needed to hold all uniform names and values 31 | listed. 32 | */ 33 | - (id)initWithUniforms:(NSArray*) allUniforms; 34 | 35 | #pragma mark - methods for setting and getting via pointers 36 | -(GLKMatrix2*) pointerToMatrix2Named:(NSString*) name; 37 | -(GLKMatrix3*) pointerToMatrix3Named:(NSString*) name; 38 | -(GLKMatrix4*) pointerToMatrix4Named:(NSString*) name; 39 | -(void) setMatrix2:(GLKMatrix2) value named:(NSString*) name; 40 | -(void) setMatrix3:(GLKMatrix3) value named:(NSString*) name; 41 | -(void) setMatrix4:(GLKMatrix4) value named:(NSString*) name; 42 | 43 | -(GLKVector2*) pointerToVector2Named:(NSString*) name; 44 | -(GLKVector3*) pointerToVector3Named:(NSString*) name; 45 | -(GLKVector4*) pointerToVector4Named:(NSString*) name; 46 | -(void) setVector2:(GLKVector2) value named:(NSString*) name; 47 | -(void) setVector3:(GLKVector3) value named:(NSString*) name; 48 | -(void) setVector4:(GLKVector4) value named:(NSString*) name; 49 | 50 | #pragma mark - Primitives 51 | 52 | -(GLint*) pointerToIntNamed:(NSString*) name isValid:(BOOL*) isValid; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2UniformMapGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | */ 4 | #import 5 | 6 | #import "GLK2UniformValueGenerator.h" 7 | #import "GLK2UniformMap.h" 8 | #import "GLK2DrawCall.h" 9 | 10 | @interface GLK2UniformMapGenerator : GLK2UniformMap 11 | 12 | /** 13 | Generally, you should use createAndAddToDrawCall: instead - that method delegates 14 | to this one 15 | */ 16 | +(GLK2UniformMapGenerator*) generatorForShaderProgram:(GLK2ShaderProgram*) shaderProgram; 17 | 18 | /** Creates a generator for the drawcall's current ShaderProgram, and attaches it 19 | directly to the DrawCall 20 | */ 21 | +(GLK2UniformMapGenerator *)createAndAddToDrawCall:(GLK2DrawCall *)drawcall; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2UniformValueGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Each drawcall, you can ask this object to provide values for any/all of the GL Uniforms 5 | in the current shader program. 6 | 7 | This attempts to efficiently extend VertexArrayObjects to cover ShaderProgram Uniforms, 8 | which the OpenGL committee failed to include. 9 | 10 | c.f. http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt 11 | 12 | "This extension introduces vertex array objects which encapsulate 13 | vertex array states on the server side (vertex buffer objects). 14 | These objects aim to keep pointers to vertex data and to provide 15 | names for different sets of vertex data. Therefore applications are 16 | allowed to rapidly switch between different sets of vertex array 17 | state, and to easily return to the default vertex array state." 18 | 19 | Design: 20 | - whenever the engine switches to a new Draw call, it queries 21 | the Draw call for one of these objects 22 | - the engine inspects the current ShaderProgram to find out what 23 | Uniforms it possesses, and then asks this object to provide them 24 | - any value that this object DOES NOT PROVIDE (returns NULL or FALSE) 25 | causes the engine to NOT CHANGE THE EXISTING GPU-SIDE VALUE 26 | */ 27 | #import 28 | #import 29 | 30 | #import "GLK2Uniform.h" 31 | 32 | @class GLK2DrawCall; 33 | 34 | @protocol GLK2UniformValueGenerator 35 | 36 | @optional 37 | 38 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 39 | -(GLKVector2*) vector2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 40 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 41 | -(GLKVector3*) vector3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 42 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 43 | -(GLKVector4*) vector4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 44 | 45 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 46 | -(GLKMatrix2*) matrix2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 47 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 48 | -(GLKMatrix3*) matrix3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 49 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 50 | -(GLKMatrix4*) matrix4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 51 | 52 | /** Returns FALSE if this object has no value / wants you to leave the value alone, because C doesn't support null primitives */ 53 | -(BOOL) floatForUniform:(GLK2Uniform*) v returnIn:(float*) value inDrawCall:(GLK2DrawCall*) drawCall; 54 | /** Returns FALSE if this object has no value / wants you to leave the value alone, because C doesn't support null primitives */ 55 | -(BOOL) intForUniform:(GLK2Uniform*) v returnIn:(GLint*) value inDrawCall:(GLK2DrawCall*) drawCall; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLK2VertexArrayObject.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "GLK2BufferObject.h" 3 | #import "GLK2Attribute.h" 4 | 5 | #define DEBUG_VAO_LIFECYCLE 0 6 | #define DEBUG_VBO_HANDLING 0 7 | 8 | @interface GLK2VertexArrayObject : NSObject 9 | 10 | @property(nonatomic, readonly) GLuint glName; 11 | 12 | @property(nonatomic,retain) NSMutableArray* VBOs; 13 | 14 | /** Delegates to the other method, defaults to using "GL_STATIC_DRAW" as the BufferObject update frequency */ 15 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems; 16 | 17 | /** Fully configurable creation of VBO + upload of data into that VBO */ 18 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq; 19 | 20 | /** If you have a VBO already uploaded to the GPU (e.g. used elsewhere), you can ADDITIONALLY add it to this VAO */ 21 | -(void) addVBO:(GLK2BufferObject*) vbo forAttributes:(NSArray*) targetAttributes; 22 | 23 | /** 24 | If you forget which VBO was which, you can use this to find the one that used the EXACT set of attributes (a single attribute, or an interleaved set) */ 25 | -(GLK2BufferObject*) VBOContainingOrderedAttributes:(NSArray*) targetAttributes; 26 | 27 | /** Detaching DOES NOT AFFECT THE GPU; but it releases all of this VAO's references to that VBO on client-side, 28 | which should trigger a dealloc, which MAY trigger a deletion from the GPU (but only if its safe) 29 | */ 30 | -(void) detachVBO:(GLK2BufferObject*) bufferToDetach; 31 | 32 | /** OpenGL's association of VAO's/VBO's has a very poor API, so you have to manually check and associate 33 | them whenever needed */ 34 | -(BOOL) containsVBO:(GLK2BufferObject*) buffer; 35 | 36 | /** ONLY exists so that you can clone a VAO while *sharing* the VBO's (required by the terrible 37 | design decisions of the OpenGL committee) 38 | */ 39 | -(NSArray*) attributesArrayForVBO:(GLK2BufferObject*) vbo; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /GLKX-Demo/Libraries/GLKitExtended/usr/local/include/include/GLKX_Library.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #pragma mark - all library public-headers should be imported here, so you can import this one file 4 | 5 | #import "GLK2Attribute.h" 6 | #import "GLK2Uniform.h" 7 | #import "GLK2BufferObject.h" 8 | #import "GLK2BufferFormat.h" 9 | #import "GLK2DrawCall.h" 10 | #import "GLK2Shader.h" 11 | #import "GLK2ShaderProgram.h" 12 | #import "GLK2Texture.h" 13 | #import "GLK2Texture+Coregraphics.h" 14 | #import "GLK2Uniform.h" 15 | #import "GLK2UniformValueGenerator.h" 16 | #import "GLK2VertexArrayObject.h" -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Attribute.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | Corresponds to an OpenGL 'attribute' item found in a shader source file, e.g. 5 | 6 | "mediump attribute vec4 color" 7 | 8 | */ 9 | #import 10 | 11 | @interface GLK2Attribute : NSObject 12 | 13 | +(GLK2Attribute*) attributeNamed:(NSString*) nameOfAttribute GLType:(GLenum) openGLType GLLocation:(GLint) openGLLocation GLSize:(GLint) openGLSize; 14 | 15 | /** The name of the variable inside the shader source file(s) */ 16 | @property(nonatomic, retain) NSString* nameInSourceFile; 17 | 18 | /** The magic key that allows you to "set" this attribute later by uploading a list/array of data to the GPU, e.g. using a VBO */ 19 | @property(nonatomic) GLint glLocation; 20 | 21 | /** GL ES 2 specifies possible types: 22 | 23 | (NB: Desktop GL has *more* types; the complete list is here, but most of them ARE NOT ALLOWED in ES 2: http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml ) 24 | 25 | BOOLEANS: bool, 2-bool-vector, 3-bool-vector, 4-bool-vector, 26 | INTEGERS: int, 2-int-vector, 3-int-vector, 4-int-vector, 27 | FLOATING POINTS: float, 2-float-vector, 3-float-vector, 4-float-vector, 2-matrix, 3-matrix, 4-matrix 28 | 29 | ... and the special types: (technically "uniforms" but have special code in OpenGL that treats them differently): 30 | 31 | TEXTURES: 2D texture, Cubemap texture 32 | */ 33 | @property(nonatomic) GLenum glType; 34 | 35 | /** Defined by OpenGL as "the size of the attribute, in units of the type returned in type." 36 | 37 | e.g. if "type" is 4-int-vector, and the attribute was declared as "vec4", then size will be "1". 38 | 39 | But (unconfirmed): if the attribute were declared as "vec4[2]", then size would be "2". i.e. "size" really 40 | means "sizeOfArrayIfThisIsAnArrayOtherwiseOne" - but I've seen it return some unexpected values in the past, 41 | so CAVEAT EMPTOR. 42 | */ 43 | @property(nonatomic) GLint glSize; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Attribute.m: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | */ 4 | #import "GLK2Attribute.h" 5 | 6 | @implementation GLK2Attribute 7 | 8 | 9 | +(GLK2Attribute*) attributeNamed:(NSString*) nameOfAttribute GLType:(GLenum) openGLType GLLocation:(GLint) openGLLocation GLSize:(GLint) openGLSize 10 | { 11 | GLK2Attribute* newValue = [[GLK2Attribute new] autorelease]; 12 | 13 | newValue.nameInSourceFile = nameOfAttribute; 14 | newValue.glType = openGLType; 15 | newValue.glLocation = openGLLocation; 16 | newValue.glSize = openGLSize; 17 | /****** NB: if you add any properties, make sure you add them to "isEqual:" method too */ 18 | 19 | return newValue; 20 | } 21 | 22 | -(BOOL)isEqual:(id)object 23 | { 24 | /** 25 | WARNING! Because we overrode this, we MUST override hash too! 26 | 27 | Apple's default implementation of "hash" silently breaks if you don't 28 | overwrite it :( :( :( :(. Very bad design. 29 | */ 30 | if( [object class] != [self class] ) 31 | return FALSE; 32 | 33 | GLK2Attribute* other = (GLK2Attribute*) object; 34 | 35 | return other.glLocation == self.glLocation 36 | && other.glType == self.glType 37 | && [other.nameInSourceFile isEqualToString:self.nameInSourceFile]; 38 | } 39 | 40 | -(NSUInteger)hash 41 | { 42 | return [self.nameInSourceFile hash]; // very closely corresponds to the bucket/hash we would choose to use anyway 43 | } 44 | @end 45 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2BufferFormat.h: -------------------------------------------------------------------------------- 1 | /** 2 | This does not directly map to anything in OpenGL, but when you put interleaved data into a 3 | VertexBufferObject, OpenGL *requires* you to track the format of that interleaved data, and 4 | supply it back to OpenGL later. 5 | 6 | This class holds that data 7 | */ 8 | #import 9 | #import 10 | 11 | @interface GLK2BufferFormat : NSObject 12 | 13 | /** 14 | It would be much cleaner to accept e.g. "GLKVector3" as argument, but Apple chose to implement 15 | their OpenGL code in C, and C is a weak language, which has no introspection for struct types. 16 | 17 | i.e. there is no way for us to detect the difference between a GLKVector2 and a GLKVector3 etc. 18 | 19 | So, instead, we ask for the number of GL_FLOAT's. 20 | 21 | NB: this method is the "most commonly used simple VBO (1 x attribute containing a single GLKit 22 | struct - e.g. GLKVector3 or GLKMatrix4)" ... which explains the lack of detailed options. 23 | */ 24 | +(GLK2BufferFormat *)bufferFormatOneAttributeMadeOfGLFloats:(GLuint)numFloats; 25 | 26 | /** 27 | Fully configurable instantiator: this lets you specify multiple attributes in a single 28 | VBO, with any number of floats each, and any number of bytes per attribute (maybe you're using 29 | 32bit floats, maybe you're using 16bit, maybe you're using 64bit, etc) 30 | */ 31 | +(GLK2BufferFormat *)bufferFormatWithFloatsPerItem:(NSArray*) floatsArray bytesPerItem:(NSArray*) bytesArray; 32 | 33 | @property(nonatomic) int numberOfSubTypes; 34 | 35 | /** 36 | The VertexArrayObject methods are fundamentally incompatible, and use "floats" as the unit-of-size, instead of "bytes", 37 | so you need to know the number of floats-per-item-in-the-buffer, when it comes time to call glVertexAttribPointer 38 | */ 39 | -(GLuint) sizePerItemInFloatsForSubTypeIndex:(int) index; 40 | 41 | /** Buffers can contain any freeform data; however, to use a Buffer, OpenGL requires you to track the format of the 42 | contents, and tell it how many "bytes" each element in the buffer uses. 43 | 44 | e.g. for a GLKVector3, you have 3 floats, and each float is a 32bit number, i.e. 4 bytes. So, a GLKVector3 has 45 | a bytesPerItem = 3 * 4 = 12. 46 | 47 | Usually, you use C's sizeof property to auto-calculate this for you correctly. 48 | */ 49 | -(GLsizeiptr) bytesPerItemForSubTypeIndex:(int) index; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2BufferFormat.m: -------------------------------------------------------------------------------- 1 | #import "GLK2BufferFormat.h" 2 | 3 | @interface GLK2BufferFormat() 4 | @property(nonatomic,retain) NSArray* numFloatsPerItem, *bytesPerItem; 5 | @end 6 | 7 | @implementation GLK2BufferFormat 8 | 9 | +(GLK2BufferFormat *)bufferFormatOneAttributeMadeOfGLFloats:(GLuint)numFloats 10 | { 11 | GLK2BufferFormat* newValue = [[GLK2BufferFormat new] autorelease]; 12 | 13 | newValue.numberOfSubTypes = 1; 14 | newValue.numFloatsPerItem = @[ @(numFloats) ]; 15 | newValue.bytesPerItem = @[ @( sizeof(GLfloat) * numFloats ) ]; 16 | 17 | return newValue; 18 | } 19 | 20 | +(GLK2BufferFormat *)bufferFormatWithFloatsPerItem:(NSArray*) floatsArray bytesPerItem:(NSArray*) bytesArray 21 | { 22 | GLK2BufferFormat* newValue = [[GLK2BufferFormat new] autorelease]; 23 | 24 | newValue.numberOfSubTypes = 1; 25 | newValue.numFloatsPerItem = floatsArray; 26 | newValue.bytesPerItem = bytesArray; 27 | 28 | return newValue; 29 | } 30 | 31 | - (id)init 32 | { 33 | self = [super init]; 34 | if (self) { 35 | self.numFloatsPerItem = [NSMutableArray array]; 36 | self.bytesPerItem = [NSMutableArray array]; 37 | } 38 | return self; 39 | } 40 | 41 | -(void)dealloc 42 | { 43 | self.numFloatsPerItem = nil; 44 | self.bytesPerItem = nil; 45 | 46 | [super dealloc]; 47 | } 48 | 49 | -(NSString *)description 50 | { 51 | NSMutableString* s = [NSMutableString string]; 52 | 53 | [s appendFormat:@"Format: %i [", self.numberOfSubTypes]; 54 | int i = -1; 55 | for( NSNumber* numFloats in self.numFloatsPerItem ) 56 | { 57 | i++; 58 | 59 | NSNumber* numBytes = [self.bytesPerItem objectAtIndex:i]; 60 | if( i > 0 ) 61 | [s appendString:@", "]; 62 | [s appendFormat:@"%i floats == %i bytes", numFloats.intValue, numBytes.intValue]; 63 | } 64 | [s appendString:@"]"]; 65 | 66 | return s; 67 | } 68 | 69 | -(GLuint)sizePerItemInFloatsForSubTypeIndex:(int)index 70 | { 71 | /** Apple currently defines GLuint as "unsigned int" */ 72 | return [((NSNumber*)[self.numFloatsPerItem objectAtIndex:index]) unsignedIntValue]; 73 | } 74 | 75 | -(GLsizeiptr)bytesPerItemForSubTypeIndex:(int)index 76 | { 77 | /** Apple currently defines GLsizeiptr as "long" */ 78 | return [((NSNumber*)[self.bytesPerItem objectAtIndex:index]) longValue]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2BufferObject.h: -------------------------------------------------------------------------------- 1 | /** 2 | An OpenGL BufferObject - http://www.opengl.org/wiki/Buffer_Object 3 | 4 | Note that OpenGL requires you set the following for you to "use" a live buffer: 5 | 6 | - glBufferType (many GL methods need to be told which type, e.g. GL_ARRAY_BUFFER 7 | - bytesPerItem (required before uploading data to the GPU/bufferobject) 8 | 9 | */ 10 | #import 11 | #import "GLK2BufferFormat.h" 12 | 13 | /** Half of the "usage" parameter as defined on http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml */ 14 | typedef enum GLK2BufferObjectFrequency 15 | { 16 | GLK2BufferObjectFrequencyStream, 17 | GLK2BufferObjectFrequencyStatic, 18 | GLK2BufferObjectFrequencyDynamic 19 | } GLK2BufferObjectFrequency; 20 | 21 | /** Half of the "usage" parameter as defined on http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml */ 22 | typedef enum GLK2BufferObjectNature 23 | { 24 | GLK2BufferObjectNatureDraw, 25 | GLK2BufferObjectNatureRead, 26 | GLK2BufferObjectNatureCopy 27 | } GLK2BufferObjectNature; 28 | 29 | @interface GLK2BufferObject : NSObject 30 | 31 | /** 32 | Pre-Configures the buffertype to "GL_ARRAY_BUFFER", as required for VBO's 33 | 34 | The format argument is required (although you could provide "nil") because a VBO where you don't know 35 | the format is effectively junk data; it's very dangerous (in bugs / debugging terms) to allow yourself 36 | to create VBO's with no format 37 | */ 38 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat; 39 | 40 | /** 41 | Uploads an empty buffer exactly large enough to hold the specified number of 'items', so that you can later fill it up 42 | using glBufferSubData. Even though glBufferSubData might be horribly slow, this method is needed in the cases 43 | where you have to store different data over time into the same buffer with the SAME attribute. 44 | 45 | If you are storing different data in different attributes, create new Buffers for each attribute - it's 46 | faster and much easier to implement 47 | */ 48 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat allocateCapacity:(NSUInteger) numItemsToPreAllocate; 49 | 50 | /** 51 | Create a VBO and immediately upload some data to it - don't forget the format! You'll need this later in order to 52 | attach it to one or more VAO's */ 53 | +(GLK2BufferObject*) newVBOFilledWithData:(const void*) data inFormat:(GLK2BufferFormat*) bFormat numVertices:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq; 54 | 55 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 56 | @property(nonatomic, readonly) GLuint glName; 57 | 58 | /** A buffer can have any type; but as soon as you use it with a GL method, you have to specify the type. Generally, 59 | you create a buffer for a specific purpose and only use it for that - unless you're low on memory and need to re-use. 60 | 61 | You are allowed to change this, while keeping the data the same - OpenGL is happy for you to treat the data as 62 | "typeless". However, it may reduce performance if you change the type to a different type while the app is running, 63 | since the GPU *may have* done optimization based on the type you 'first' used with this buffer. 64 | 65 | c.f. http://www.opengl.org/wiki/Buffer_Object 66 | 67 | The static methods - e.g. "vertexBufferObject" - set this automatically 68 | */ 69 | @property(nonatomic) GLenum glBufferType; 70 | 71 | /** Buffers can contain any freeform data; however, to use a Buffer, OpenGL requires you to track the format of the 72 | contents, and tell it how many "bytes" each element in the buffer uses. 73 | 74 | e.g. for a GLKVector3, you have 3 floats, and each float is a 32bit number, i.e. 4 bytes. So, a GLKVector3 has 75 | a bytesPerItem = 3 * 4 = 12. 76 | 77 | Usually, you use C's sizeof property to auto-calcualte this for you correctly. I.e. if you've stored GLKVector3 objects 78 | in the buffer, call: 79 | 80 | (GLK2BufferObject).bytesPerItem = sizeof( GLKVector3 ); 81 | 82 | */ 83 | @property(nonatomic,retain) GLK2BufferFormat* currentFormat; 84 | 85 | /** 86 | Whenever you change the contentsFormat, this will be automatically updated 87 | */ 88 | @property(nonatomic,readonly) GLsizeiptr totalBytesPerItem; 89 | 90 | /** 91 | OpenGL has two parameters which are combined into a single value and used as a "usage hint"; obviously, it would have 92 | been cleaner and saner to use TWO "usage hints", but we're stuck with it. This method does the combining correctly for 93 | you, and automatically detects the cases that are illegal in GL ES 2 (but may be legal in other GL versions) 94 | */ 95 | -(GLenum) getUsageEnumValueFromFrequency:(GLK2BufferObjectFrequency) frequency nature:(GLK2BufferObjectNature) nature; 96 | 97 | /** Wraps glBufferData 98 | 99 | To automatically get the correct value for usageHint, use "getUsageEnumValueFromFrequency:nature:" 100 | */ 101 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage withNewFormat:(GLK2BufferFormat*) bFormat; 102 | 103 | /** 104 | Uses the existing buffer format (self.contentsFormat) - will fail if that is not set 105 | */ 106 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage; 107 | 108 | /** Wraps glBufferSubData -- NB this will ONLY work if you've already done a call to one of the "upload:" methods, 109 | OR if you created the buffer with a specific initial capacity; if not, the GPU won't have any memory allocated yet 110 | for you to upload into! 111 | 112 | */ 113 | -(void)uploadToOffset:(GLintptr)startOffset withData:(const void *)dataArray numItems:(int)count; 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2BufferObject.m: -------------------------------------------------------------------------------- 1 | #import "GLK2BufferObject.h" 2 | 3 | @interface GLK2BufferObject() 4 | @property(nonatomic, readwrite) GLuint glName; 5 | @property(nonatomic, readwrite) GLsizeiptr totalBytesPerItem; 6 | @end 7 | 8 | @implementation GLK2BufferObject 9 | 10 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat 11 | { 12 | GLK2BufferObject* newObject = [[GLK2BufferObject new] autorelease]; 13 | newObject.glBufferType = GL_ARRAY_BUFFER; 14 | newObject.currentFormat = newFormat; 15 | 16 | return newObject; 17 | } 18 | 19 | +(GLK2BufferObject *)vertexBufferObjectWithFormat:(GLK2BufferFormat*) newFormat allocateCapacity:(NSUInteger) numItemsToPreAllocate 20 | { 21 | GLK2BufferObject* newObject = [self vertexBufferObjectWithFormat:newFormat]; 22 | 23 | glBindBuffer( newObject.glBufferType, newObject.glName ); 24 | 25 | glBufferData( GL_ARRAY_BUFFER, numItemsToPreAllocate * newObject.totalBytesPerItem, NULL, GL_DYNAMIC_DRAW); 26 | 27 | return newObject; 28 | } 29 | 30 | +(GLK2BufferObject*) newVBOFilledWithData:(const void*) data inFormat:(GLK2BufferFormat*) bFormat numVertices:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq 31 | { 32 | /** Create a VBO on the GPU, to store data */ 33 | GLK2BufferObject* newVBO = [GLK2BufferObject vertexBufferObjectWithFormat:bFormat]; 34 | 35 | /** Send the vertex data to the new VBO */ 36 | [newVBO upload:data numItems:numDataItems usageHint:[newVBO getUsageEnumValueFromFrequency:freq nature:GLK2BufferObjectNatureDraw]]; 37 | 38 | return newVBO; 39 | } 40 | 41 | - (id)init 42 | { 43 | self = [super init]; 44 | if (self) { 45 | glGenBuffers(1, &_glName); 46 | } 47 | return self; 48 | } 49 | 50 | - (void)dealloc 51 | { 52 | if( self.glName > 0 ) 53 | { 54 | NSLog(@"[%@] glDeleteBuffer(%i)", [self class], self.glName); 55 | glDeleteBuffers(1, &_glName); 56 | } 57 | 58 | [super dealloc]; 59 | } 60 | 61 | -(NSString *)description 62 | { 63 | NSMutableString* s = [NSMutableString string]; 64 | 65 | [s appendFormat:@"VBO-%i:", self.glName]; 66 | [s appendFormat:@" totalBytes: %li", self.totalBytesPerItem ]; 67 | [s appendFormat:@" %@", self.currentFormat]; 68 | 69 | return s; 70 | } 71 | 72 | -(void) bind 73 | { 74 | glBindBuffer(GL_ARRAY_BUFFER, self.glName); 75 | } 76 | 77 | -(GLenum) getUsageEnumValueFromFrequency:(GLK2BufferObjectFrequency) frequency nature:(GLK2BufferObjectNature) nature 78 | { 79 | GLenum usage; 80 | 81 | switch( frequency ) 82 | { 83 | case GLK2BufferObjectFrequencyDynamic: 84 | { 85 | switch( nature ) 86 | { 87 | case GLK2BufferObjectNatureCopy: 88 | case GLK2BufferObjectNatureRead: 89 | NSAssert(FALSE, @"Illegal in GL ES 2"); 90 | usage = 0; 91 | break; 92 | case GLK2BufferObjectNatureDraw: 93 | usage = GL_DYNAMIC_DRAW; 94 | break; 95 | 96 | default: 97 | NSAssert(FALSE, @"Illegal parameters"); 98 | } 99 | }break; 100 | 101 | case GLK2BufferObjectFrequencyStatic: 102 | { 103 | switch( nature ) 104 | { 105 | case GLK2BufferObjectNatureCopy: 106 | case GLK2BufferObjectNatureRead: 107 | NSAssert(FALSE, @"Illegal in GL ES 2"); 108 | usage = 0; 109 | break; 110 | case GLK2BufferObjectNatureDraw: 111 | usage = GL_STATIC_DRAW; 112 | break; 113 | 114 | default: 115 | NSAssert(FALSE, @"Illegal parameters"); 116 | } 117 | }break; 118 | 119 | case GLK2BufferObjectFrequencyStream: 120 | { 121 | switch( nature ) 122 | { 123 | case GLK2BufferObjectNatureCopy: 124 | case GLK2BufferObjectNatureRead: 125 | NSAssert(FALSE, @"Illegal in GL ES 2"); 126 | usage = 0; 127 | break; 128 | case GLK2BufferObjectNatureDraw: 129 | usage = GL_STREAM_DRAW; 130 | break; 131 | 132 | default: 133 | NSAssert(FALSE, @"Illegal parameters"); 134 | } 135 | }break; 136 | 137 | default: 138 | NSAssert(FALSE, @"Illegal parameters"); 139 | } 140 | return usage; 141 | } 142 | 143 | -(void)setCurrentFormat:(GLK2BufferFormat *)newValue 144 | { 145 | [_currentFormat release]; 146 | _currentFormat = newValue; 147 | [_currentFormat retain]; 148 | 149 | self.totalBytesPerItem = 0; 150 | for( int i=0; i 0 , @"Invalid GLK2BufferFormat"); 155 | 156 | self.totalBytesPerItem += bytesPerItem; 157 | } 158 | } 159 | 160 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage withNewFormat:(GLK2BufferFormat*) bFormat 161 | { 162 | self.currentFormat = bFormat; 163 | [self upload:dataArray numItems:count usageHint:usage]; 164 | } 165 | 166 | -(void) upload:(const void *) dataArray numItems:(int) count usageHint:(GLenum) usage 167 | { 168 | NSAssert( self.currentFormat != nil, @"Use the version of this method that takes a new GLK2BufferFormat, or set self.contentsFormat manually"); 169 | 170 | glBindBuffer( self.glBufferType, self.glName ); 171 | 172 | glBufferData( GL_ARRAY_BUFFER, count * self.totalBytesPerItem, dataArray, usage); 173 | } 174 | 175 | -(void)uploadToOffset:(GLintptr)startOffset withData:(const void *)dataArray numItems:(int)count 176 | { 177 | glBindBuffer( self.glBufferType, self.glName ); 178 | 179 | glBufferSubData( GL_ARRAY_BUFFER, startOffset, count * self.totalBytesPerItem, dataArray); 180 | } 181 | @end 182 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2DrawCall.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import "GLK2ShaderProgram.h" 5 | #import "GLK2VertexArrayObject.h" 6 | #import "GLK2Texture.h" 7 | #import "GLK2UniformValueGenerator.h" 8 | 9 | /** 10 | Version 1: c.f. http://t-machine.org/index.php/2013/09/08/opengl-es-2-basic-drawing/ 11 | Part 3: ... not published yet ... 12 | */ 13 | @interface GLK2DrawCall : NSObject 14 | 15 | /** Massively helpful when debugging: give each one a human-readable title */ 16 | @property(nonatomic,retain) NSString* title; 17 | 18 | @property(nonatomic) BOOL shouldClearColorBit, shouldClearDepthBit; 19 | 20 | /** Every draw call MUST have a shaderprogram, or else it cannot draw objects nor pixels */ 21 | @property(nonatomic,retain) GLK2ShaderProgram* shaderProgram; 22 | 23 | /** You nearly always want this on, so that overlapping triangles correctly overlap, instead of having one or the other 24 | overwriting the ones IN FRONT OF it */ 25 | @property(nonatomic) BOOL requiresDepthTest; 26 | 27 | /** In almost all apps you want it ON */ 28 | @property(nonatomic) BOOL requiresCullFace; 29 | 30 | /** Enabling this on Apple/PVR devices MASSIVELY reduces performance, so only use it when genuinely needed. 31 | 32 | Requires you to also set: 33 | - alphaBlendSourceFactor 34 | - alphaBlendDestinationFactor 35 | */ 36 | @property(nonatomic) BOOL requiresAlphaBlending; 37 | 38 | /** 39 | For mode "requiresAlphaBlending = TRUE", defaults to: source = GL_ONE, dest = GL_ONE_MINUS_SRC_ALPHA 40 | */ 41 | @property(nonatomic) GLenum alphaBlendSourceFactor, alphaBlendDestinationFactor; 42 | 43 | /** If this draw call has ANY geometry, it should go in a VBO (stores raw Vertex attributes), 44 | and the VBO should be embedded in a VAO (which stores the metadata about the geometry) */ 45 | @property(nonatomic,retain) GLK2VertexArrayObject* VAO; 46 | 47 | /** i.e. GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN */ 48 | @property(nonatomic) GLuint glDrawCallType; 49 | 50 | /** When you run a Draw call, it can optionally render anything from "0" up to "all" of the 51 | vertex-data stored in the VAO/VBO's. 52 | 53 | So ... OpenGL requires you to specify exactly how many vertices you want to use 54 | every time you Draw. 55 | 56 | It's easiest to save this number at the time you upload data into your VBO's (it IS possible 57 | to get the number back later - but your VBO's may (optionally) be different lengths, e.g. if 58 | you're sharing VBO's between multiple draw-calls. So you need to store the nubmer-to-draw 59 | on a per-drawcall basis. 60 | */ 61 | @property(nonatomic) GLuint numVerticesToDraw; 62 | 63 | /** Each drawcall, this is inspected to calculate new values for every "uniform" in the pair of shaders */ 64 | @property(nonatomic,retain) NSObject* uniformValueGenerator; 65 | 66 | /** Textures in GL ES 2 are different from old-style OpenGL, and you MUST track the named 67 | shader-uniform / shader-sampler2d variable that each texture is 'attached' to; because of 68 | the way OpenGL handles texture-memory, you can't "do this once and forget about it", you 69 | have to keep re-doing it frame to frame */ 70 | @property(nonatomic,retain) NSMutableDictionary* texturesFromSamplers; 71 | 72 | #pragma mark - All the possible Draw call types supported in GL ES 2 73 | 74 | +(GLK2DrawCall*) drawCallPoints; 75 | +(GLK2DrawCall*) drawCallLines; 76 | +(GLK2DrawCall*) drawCallLineLoop; 77 | +(GLK2DrawCall*) drawCallLineStrip; 78 | +(GLK2DrawCall*) drawCallTriangles; 79 | +(GLK2DrawCall*) drawCallTriangleStrip; 80 | +(GLK2DrawCall*) drawCallTriangleFan; 81 | 82 | #pragma mark - init methods 83 | 84 | /** 85 | Defaults to: 86 | 87 | - clear color MAGENTA 88 | - depth test ON 89 | - cull back-facing polygons ON 90 | 91 | ... everything else: OFF 92 | */ 93 | -(id) initWithTitle:(NSString*) title; 94 | 95 | /** 96 | Delegates to initWithTitle, using a random string for the title 97 | */ 98 | - (id)init; 99 | 100 | -(float*) clearColourArray; 101 | -(void) setClearColourRed:(float) r green:(float) g blue:(float) b alpha:(float) a; 102 | 103 | #pragma mark Missing GL methods for handling Uniforms in Shaders each frame 104 | 105 | /** MUST be called AFTER setting this drawcall's shader to current 106 | (e.g. within the update / drawFrame loop) 107 | */ 108 | -(void) setAllUniformValuesForShader; 109 | 110 | #pragma mark Texturing and texture-mapping methods 111 | 112 | /** When the draw-call runs, it will look up all the 'sampler2D' objects in the Shader sourcecode, 113 | and then try to find an appropriate OpenGL Texture / GLK2Texture for each one. 114 | 115 | Make sure you call this method at least for each sampler in your shader (the contents are preserved 116 | even if you change shader-program at runtime, so you can have "more" of these mapped than necessary, 117 | if you want) 118 | 119 | @param texture if nil, will "remove" the sampler/texture pair from the mapping for this drawcall 120 | @return the OpenGL texture-unit that this drawcall wants to use for that texture 121 | */ 122 | -(GLuint) setTexture:(GLK2Texture*) texture forSampler:(GLK2Uniform*) sampler; 123 | /** 124 | Convenience version of method that takes a name, and fetches the sampler for you */ 125 | -(GLuint) setTexture:(GLK2Texture*) texture forSamplerNamed:(NSString*) samplerName; 126 | 127 | /** 128 | For hot-swapping textures, you often need to ask a drawcall: 129 | 130 | "which GLK2Texture object do you currently use for sampler BLAH?" 131 | 132 | */ 133 | -(GLK2Texture*)getTextureForSamplerNamed:(NSString *)samplerName; 134 | 135 | /** For debugging: returns an array of all the GLK2Texture objects currently bound to a sampler */ 136 | -(NSArray*) getCurrentTextures; 137 | 138 | /** Massive bug in OpenGL API: ShaderPrograms DO NOT USE the correct texture-unit ID's (i.e. GL_TEXTURE0 etc) 139 | for identifying texture-units; instead, they use "the offset to add to GL_TEXTURE0" 140 | */ 141 | -(GLint)textureUnitOffsetForSampler:(GLK2Uniform *)sampler; 142 | 143 | #pragma mark - workaround for OpenGL API bug: GL ES VAO's "cannot" be shared across threads 144 | 145 | /** 146 | Converts this DrawCall from one created on "any thread except the main one" to "a valid 147 | renderable drawcall", assuming you are CURRENTLY EXECUTING ON THE MAIN RENDER THREAD 148 | 149 | Alternatively, use copyDrawCallAllocatingNewVAO below 150 | */ 151 | -(void) reCreateVAOOnCurrentThread; 152 | 153 | /** 154 | The OpenGL committee are sometimes evil - they decided to break GL ES so that VAO's 155 | can't be shared across threads. 156 | 157 | This also prevents you from loading background geometry. It's a MAJOR bug in the API. 158 | 159 | The only workaround is to load your geometry once, then clone your draw-calls, creating 160 | new VAO's, and re-assign the VBO's (which ARE shared) to the new VAO's on the new thread. 161 | 162 | Alternatively, use reCreateVAOOnCurrentThread above (but make sure you're in the main thread and not mid-render!) 163 | */ 164 | -(id) copyDrawCallAllocatingNewVAO; 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Shader.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | The most important method is shaderFromFilename:type: 5 | */ 6 | #import 7 | 8 | #import "GLK2ShaderProgram.h" 9 | 10 | /** 11 | GL ES 2 has exactly two types of shader, but desktop GL has more, and we expect future versions of ES to add them in 12 | */ 13 | typedef enum GLK2ShaderType 14 | { 15 | GLK2ShaderTypeVertex = GL_VERTEX_SHADER, 16 | GLK2ShaderTypeFragment = GL_FRAGMENT_SHADER 17 | } GLK2ShaderType; 18 | 19 | /** 20 | Useful for internal sanity checks 21 | */ 22 | typedef enum GLK2ShaderStatus 23 | { 24 | GLK2ShaderStatusUncompiled, 25 | GLK2ShaderStatusCompiled, 26 | GLK2ShaderStatusLinked 27 | } GLK2ShaderStatus; 28 | 29 | @interface GLK2Shader : NSObject 30 | 31 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 32 | @property(nonatomic, readonly) GLuint glName; 33 | 34 | @property(nonatomic) GLK2ShaderType type; 35 | @property(nonatomic) GLK2ShaderStatus status; 36 | 37 | /** Filename for the shader with NO extension; assumes all Vertex shaders end .vsh, all Fragment shaders end .fsh */ 38 | @property(nonatomic,retain) NSString* filename; 39 | 40 | /** Convenience method that sets up the shader, ready to be compiled */ 41 | +(GLK2Shader*) shaderFromFilename:(NSString*) fname type:(GLK2ShaderType) type; 42 | 43 | /** Compiles the shader; you have to do setup of a GLK2ShaderProgram / OpenGL ShaderProgram also */ 44 | -(void) compile; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Shader.m: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | */ 4 | #import "GLK2Shader.h" 5 | 6 | @interface GLK2Shader() 7 | @property(nonatomic, readwrite) GLuint glName; 8 | @end 9 | 10 | @implementation GLK2Shader 11 | 12 | +(GLK2Shader*) shaderFromFilename:(NSString*) fname type:(GLK2ShaderType) type 13 | { 14 | GLK2Shader* newShader = [[[GLK2Shader alloc]initWithType:type]autorelease]; 15 | newShader.filename = fname; 16 | return newShader; 17 | } 18 | 19 | - (id)initWithType:(GLK2ShaderType) type 20 | { 21 | self = [super init]; 22 | if (self) { 23 | self.type = type; 24 | self.glName = glCreateShader( self.type ); 25 | 26 | NSLog(@"[%@] Created new GL shader with GL name = %i", [self class], self.glName ); 27 | } 28 | return self; 29 | } 30 | 31 | -(void)dealloc 32 | { 33 | self.filename = nil; 34 | 35 | /** 36 | 37 | Do NOT "glDeleteShader" when this deallocs; the way OpenGL committee designed Shaders is incompatible 38 | with the rest of GL, and you delete IMMEDIATELY AFTER CREATING, rather than waiting until you stop using it 39 | 40 | */ 41 | 42 | [super dealloc]; 43 | } 44 | 45 | -(void) compile 46 | { 47 | NSAssert( self.status == GLK2ShaderStatusUncompiled, @"Can't compile; already compiled"); 48 | 49 | NSString *shaderPathname; 50 | 51 | // Create and compile shader. 52 | switch( self.type ) 53 | { 54 | case GLK2ShaderTypeFragment: 55 | { 56 | self.type = GL_FRAGMENT_SHADER; 57 | shaderPathname = [[NSBundle mainBundle] pathForResource:self.filename ofType: @"fsh"]; 58 | }break; 59 | 60 | case GLK2ShaderTypeVertex: 61 | { 62 | self.type = GL_VERTEX_SHADER; 63 | shaderPathname = [[NSBundle mainBundle] pathForResource:self.filename ofType: @"vsh"]; 64 | }break; 65 | } 66 | 67 | const GLchar *source = (GLchar *)[[NSString stringWithContentsOfFile:shaderPathname encoding:NSUTF8StringEncoding error:nil] UTF8String]; 68 | if( source == 0 ) 69 | @throw [NSException exceptionWithName:@"Shader Compile failure" reason:[NSString stringWithFormat:@"Failed to load shader from file: %@ (using filename:%@)", shaderPathname, self.filename ] userInfo:@{ @"Resolved path":shaderPathname==nil ? [NSNull null] : shaderPathname, @"Original filename":self.filename == nil ? [NSNull null] : self.filename} ]; 70 | 71 | glShaderSource( self.glName, 1, &source, NULL); 72 | 73 | /** Compile it! */ 74 | glCompileShader( self.glName ); 75 | 76 | /** Check for success - throw exception on failure (failure to compile is VERY bad sign) */ 77 | GLint status; 78 | glGetShaderiv( self.glName, GL_COMPILE_STATUS, &status); 79 | if( status == GL_TRUE ) 80 | { 81 | self.status = GLK2ShaderStatusCompiled; 82 | } 83 | else 84 | { 85 | NSString* log = [GLK2Shader fetchLogForGLCompileShader:self]; 86 | 87 | @throw [NSException exceptionWithName:@"Shader Compile failure" reason:[NSString stringWithFormat:@"Compile failure for: %@", shaderPathname ] userInfo:@{ @"filename":shaderPathname, @"Compiler output":log} ]; 88 | } 89 | } 90 | 91 | +(NSString*) fetchLogForGLCompileShader:(GLK2Shader*) shader 92 | { 93 | int loglen; 94 | char logbuffer[1000]; 95 | glGetShaderInfoLog( shader.glName, sizeof(logbuffer), &loglen, logbuffer); 96 | 97 | if (loglen > 0) 98 | { 99 | return [NSString stringWithUTF8String:logbuffer]; 100 | } 101 | else 102 | return @""; 103 | } 104 | 105 | +(NSString*) fetchLogForGLLinkShaderProgram:(GLK2ShaderProgram*) program 106 | { 107 | int loglen; 108 | char logbuffer[1000]; 109 | glGetProgramInfoLog(program.glName, sizeof(logbuffer), &loglen, logbuffer); 110 | if (loglen > 0) { 111 | return [NSString stringWithUTF8String:logbuffer]; 112 | } 113 | else 114 | return @""; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2ShaderProgram.h: -------------------------------------------------------------------------------- 1 | /** 2 | Part 3: ... not published yet ... 3 | 4 | ShaderProgram is a boilerplate concept that is REQUIRED to be identical for all OpenGL apps; this class is intended to be 5 | reused everywhere without changes. A ShaderProgram in OpenGL ES 2 is "1 x vertex shader + 1 x fragment shader, combined into 6 | a single item". 7 | 8 | (NB: this version is incomplete, a basic implementation only, next version will add a few missing features, and then never 9 | need to be edited again) 10 | */ 11 | #import 12 | 13 | #import "GLK2Attribute.h" 14 | #import "GLK2Uniform.h" 15 | 16 | #define DEBUG_ATTRIBUTE_HANDLING 0 17 | #define DEBUG_UNIFORM_HANDLING 0 18 | 19 | typedef enum GLK2ShaderProgramStatus 20 | { 21 | GLK2ShaderProgramStatusUnlinked, 22 | GLK2ShaderProgramStatusLinked 23 | } GLK2ShaderProgramStatus; 24 | 25 | @class GLK2Shader; 26 | 27 | @interface GLK2ShaderProgram : NSObject 28 | 29 | /** 30 | 31 | Does all the work of: 32 | 33 | - finding vertex + fragment shaders on disk 34 | - loading the source code of the shaders 35 | - compiling them 36 | - linking them 37 | - storing post-link info that OpenGL apps MUST have in order to work corectly 38 | 39 | */ 40 | +(GLK2ShaderProgram*) shaderProgramFromVertexFilename:(NSString*) vFilename fragmentFilename:(NSString*) fFilename; 41 | 42 | @property(nonatomic) GLK2ShaderProgramStatus status; 43 | 44 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 45 | @property(nonatomic, readonly) GLuint glName; 46 | 47 | /** Setting either property automatically calls glAttachShader */ 48 | @property(nonatomic,retain) GLK2Shader* vertexShader, * fragmentShader; 49 | 50 | /** the "link" stage automatically finds all "attribute" lines in the shader source, and creates one GLK2Attribute for each */ 51 | -(GLK2Attribute*) attributeNamed:(NSString*) name; 52 | /** the "link" stage automatically finds all "attribute" lines in the shader source, and creates one GLK2Attribute for each */ 53 | -(NSArray*) allAttributes; 54 | 55 | -(GLK2Uniform*) uniformNamed:(NSString*) name; 56 | -(NSArray*) allUniforms; 57 | 58 | #pragma mark - GLSL validation - do NOT use in a live app! 59 | 60 | -(void) validate; 61 | 62 | #pragma mark - Set the value of a Uniform 63 | 64 | /** 65 | NOTE: it is always safe to call this from anywhere in the program, so long as the renderer's thread is blocked, 66 | OR you are inside that thread. 67 | 68 | The simpler/faster version of this method only works if you are actually inside the render-loop itself, which is 69 | only true for the renderer 70 | 71 | Note: both methods set internal state that helps with debugging; you can use either - but don't use the private 72 | internal methods! 73 | */ 74 | -(void) setValueOutsideRenderLoopRestoringProgramAfterwards:(const void*) value forUniform:(GLK2Uniform*) uniform; 75 | 76 | /** NOTE: this must ONLY be invoked inside the main render-loop, and ONLY when the render-loop has set the 77 | current glProgram to this one. 78 | 79 | When you need to set values outside the render-loop - e.g. nearly always: because you're configuring a new shader/ 80 | drawcall - instead use setValueOutsideRenderLoopRestoringProgramAfterwards:forUniform -- that method will switch to 81 | this shaderprogram, set the value, and then switch BACK to the original program being used by the main renderer. 82 | 83 | If you incorrectly use this method when you should have used the other, GL state will leak between drawcalls/shaders 84 | and CHAOS! will break loose upon thy rendering... You will also think you've gone insane when you try to debug it, 85 | and 1 proves to be equal to 0. (voice of bitter experience) 86 | 87 | Note: both methods set internal state that helps with debugging; you can use either - but don't use the private 88 | internal methods! 89 | */ 90 | -(void) setValue:(const void*) value forUniform:(GLK2Uniform*) uniform; 91 | 92 | /** 93 | OpenGL debugging is badly designed and almost unusable; all manufacturers provide hacks to give you what you need, 94 | except Apple - who prevents you from using the manufacturer's tools (Imagination / PowerVR doesn't seem very happy 95 | about this!). 96 | 97 | One side-effect: OpenGL will silently break everything if a Uniform that needs to be set ... isn't ... for any reason 98 | and will not give you any way of finding this out. 99 | 100 | This method tracks (imperfectly, but accurate so long as you only use the public methods in this class) what uniforms 101 | you've set / not set yet 102 | */ 103 | -(NSArray*) uniformsWithoutValues; 104 | 105 | /** automatically calls glCreateProgram() */ 106 | - (id)init; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Texture.h: -------------------------------------------------------------------------------- 1 | /** 2 | From the OpenGL org wiki (http://www.opengl.org/wiki/Texture): 3 | 4 | "Binding textures for use in OpenGL is a little weird." 5 | 6 | -- Really? You don't say... 7 | 8 | And Apple solves half the problems, but creates as many new problems as the ones they solve. 9 | 10 | ARGH! 11 | 12 | So ... this is an annoying class, it shouldn't be needed - but it is, let me explain... 13 | 14 | -------------- (explanation starts) -------------- 15 | From the Apple docs on GLKTextureInfo: 16 | 17 | (https://developer.apple.com/library/ios/documentation/GLkit/Reference/GLKTextureInfo_Ref/Reference/Reference.html#//apple_ref/occ/instp/GLKTextureInfo/textureOrigin) 18 | 19 | "Your app never creates GLKTextureInfo objects directly" 20 | 21 | Why? Ideology? Someone at Apple doesn't like other programmers writing 22 | source code, adding features, fixing bugs, extending functionality? 23 | 24 | If Apple's GLKTextureLoader class actually worked (it doesn't; it has massive bugs - that 25 | I've reported to Apple, but been told 'I'll never fix it' by Apple engineers) 26 | ... maybe they could get away with sealing their classes like this. 27 | 28 | But it doesn't work. And it doesn't support PVR any more (the file-format has moved on, 29 | Apple's source code is now obsolete, and Apple hasn't updated it). So ... we need to 30 | replace GLKTextureInfo with a class that we're "allowed" to set values on, so we can 31 | fix Apple's bugs. 32 | -------------- (explanation ends) -------------- 33 | 34 | What does this class does: 35 | 36 | - unifies "Apple's proprietary GLKTextureInfo class" with "genuine OpenGL textures" 37 | - represents 1:1 an OpenGL texture 38 | - OpenGL textures can live on CPU, GPU, both, neither - this class tracks where the texture is, and if it needs reloading 39 | - provides a single datatype that your own, custom, texture importers can safely import to, and your app code can read from 40 | 41 | Very important: 42 | 43 | - this class can UNLOAD it's texture from the GPU (e.g. when low on memory), and then RELOAD it later, while the app is running 44 | 45 | (OpenGL can't/won't do that automatically, and if you don't track texture-status using a class like this one, it's hard 46 | to do yourself) 47 | 48 | */ 49 | #import 50 | #import 51 | 52 | #define USE_GLK2TEXTURETRACKER_INTERNALLY 1 // set to 0 if you want to build without the extended classes e.g. GLK2TextureTracker 53 | 54 | @interface GLK2Texture : NSObject 55 | 56 | /** 57 | Creates a new empty texture on the GPU. You'll have to fill this later with one of the uploading methods. 58 | 59 | Generally, you do NOT want this method - it's best to upload a texture immmediately, or not create it until you 60 | need it. But in some cases (e.g. when multiple drawcalls are going to share a texture) it's safer to create the 61 | GPU texture first, and pass this texture object to each drawcall during config, so that they never get out of 62 | synch, and upload the texture data later. 63 | */ 64 | +(GLK2Texture*) textureNewEmpty; 65 | 66 | /** Tries to load a texture in the same way as Apple's [UIImage imageNamed] method: by searching the bundle, and then 67 | delegating to Apple's broken GLKit texture-loader (because that loader explicitly is designed to do this, even though 68 | it's very buggy) */ 69 | +(GLK2Texture*) textureNamed:(NSString*) filename; 70 | 71 | /** If you use Apple's broken GLKit texture-loader, you'll need to store and manipulate the output, but Apple blocks you 72 | from doing this (for no apparent reason). So this method lets you convert from Apple's badly designed proprietary class 73 | into an instance that you can safely use */ 74 | +(GLK2Texture*) texturePreLoadedByApplesGLKit:(GLKTextureInfo*) appleMetadata; 75 | 76 | /** 77 | If your texture is already on the GPU and/or was created by 3rdparty code, this lets you 78 | create a CPU-side GLK2Texture object to manage it 79 | */ 80 | +(GLK2Texture*) textureAlreadyOnGPUWithName:(GLuint) existingName; 81 | 82 | /** 83 | Note that a raw stream of bytes contains NO INFORMATION about width/height of texture, so you need to provide those 84 | details in the parametrs. 85 | 86 | Critically important: this requires the data to be in RAW BYTES, exactly as you'd expect from the method name; this is 87 | INCOMPATIBLE with Apple's undocumented NSData-loading method (which crashes if you give it anything except 88 | an ENCODED jpeg or png or pvr-v1) */ 89 | +(GLK2Texture *)textureFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh; 90 | 91 | /** OpenGL uses integers as "names" instead of Strings, because Strings in C are a pain to work with, and slower */ 92 | @property(nonatomic, readonly) GLuint glName; 93 | 94 | /** 95 | DEFAULTS to FALSE 96 | 97 | There is one known case where you DON'T want to delete your own textures: 98 | Apple's badly-documented CoreVideo for pulling frames from Camera onto GL texture, where Apple REQUIRES you to manually buffer 99 | textures from frame-to-frame until they "die" at a non-specified time of Apple's internal choosing */ 100 | @property(nonatomic) BOOL disableAutoDelete; 101 | 102 | /** Creates a new, blank, OpenGL texture on the GPU. 103 | 104 | If you already created a texture from some other source, use the initWithName: method instead 105 | */ 106 | - (id)init; 107 | 108 | /** If a texture was loaded by an external source - e.g. Apple's GLKit - you'll already have a name for it, and can 109 | use this method 110 | 111 | NB: this is the designated initializer; this is particularly important w.r.t. GLK2TextureTracker and subclassing 112 | this class 113 | */ 114 | - (id)initWithName:(GLuint) name; 115 | 116 | -(void) uploadFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh; 117 | 118 | /** Advanced: 119 | 120 | Mostly useful when hot-swapping a teture, this call drops the old .glName (and issues a glDeleteTeture on it 121 | unless willDeleteOnDealloc is set to FALSE), then it grabs the incoming value and sets it as self.glName. 122 | 123 | From this moment onwards, all rendering that indirects via this instance will use the "new" GPU-side teture 124 | instead of the old one. 125 | */ 126 | -(void) reAssociateWithNewGPUTexture:(GLuint) newTextureName; 127 | 128 | /** Wraps the texture in S */ 129 | -(void) setWrapSRepeat; 130 | -(void) setWrapTRepeat; 131 | /** Clamps the texture in S */ 132 | -(void) setWrapSClamp; 133 | -(void) setWrapTClamp; 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Texture.m: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | */ 4 | #import "GLK2Texture.h" 5 | 6 | #import "GLK2Texture_MutableName.h" 7 | 8 | #import "GLK2TextureLoaderPVRv1.h" // for textureNamed: auto-loading PVR's without Apple's bug 9 | 10 | #if USE_GLK2TEXTURETRACKER_INTERNALLY 11 | #import "GLK2TextureTracker.h" 12 | #endif 13 | 14 | @implementation GLK2Texture 15 | 16 | +(GLK2Texture *)textureNewEmpty 17 | { 18 | GLK2Texture* newValue = [[GLK2Texture new] autorelease]; 19 | 20 | return newValue; 21 | } 22 | 23 | +(GLK2Texture *)texturePreLoadedByApplesGLKit:(GLKTextureInfo *)appleMetadata 24 | { 25 | GLK2Texture* newValue = [[[GLK2Texture alloc] initWithName:appleMetadata.name] autorelease]; 26 | 27 | return newValue; 28 | } 29 | 30 | +(GLK2Texture *)textureFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh 31 | { 32 | GLK2Texture* newValue = [self textureNewEmpty]; 33 | 34 | [newValue uploadFromNSData:rawData pixelsWide:pWide pixelsHigh:pHigh]; 35 | 36 | return newValue; 37 | } 38 | 39 | +(GLK2Texture*) textureAlreadyOnGPUWithName:(GLuint) existingName 40 | { 41 | GLK2Texture* newValue = [[[GLK2Texture alloc] initWithName:existingName] autorelease]; 42 | 43 | return newValue; 44 | } 45 | 46 | +(GLK2Texture *)textureNamed:(NSString *)filename 47 | { 48 | NSString* guessedPath = nil; 49 | 50 | /** if it already has an extension, try it */ 51 | if( [filename pathExtension] != nil ) 52 | guessedPath = [[NSBundle mainBundle] pathForResource:[filename stringByDeletingPathExtension] ofType:[filename pathExtension]]; 53 | 54 | if( guessedPath == nil ) 55 | { 56 | NSArray* possibleExtensions = @[ @"png", @"jpg", @"gif", @"pvr" ]; 57 | for( NSString* extension in possibleExtensions ) 58 | { 59 | if( [[filename pathExtension] isEqualToString:extension] ) 60 | { 61 | filename = [filename stringByDeletingPathExtension]; 62 | break; 63 | } 64 | } 65 | 66 | for( NSString* extension in possibleExtensions ) 67 | { 68 | guessedPath = [[NSBundle mainBundle] pathForResource:filename ofType:extension]; 69 | if( guessedPath != nil ) 70 | break; 71 | } 72 | } 73 | 74 | NSAssert( guessedPath != nil, @"Failed to find a texture with base filename '%@' and no extension (Apple doesn't allow them)", filename); 75 | 76 | NSError* error; 77 | 78 | if( [guessedPath hasSuffix:@"pvr"]) // Apple's loader is broken for mipmaps; MUST use custom loader here: 79 | { 80 | NSLog(@"using special PVR loader"); 81 | GLK2Texture* newTexture; 82 | 83 | newTexture = [GLK2TextureLoaderPVRv1 pvrTextureWithContentsOfFile:guessedPath]; 84 | 85 | return newTexture; 86 | } 87 | else // use apple's GLKit loader (which has many bugs, including some they refuse to fix!) 88 | { 89 | GLKTextureInfo* appleTexture = [GLKTextureLoader textureWithContentsOfFile:guessedPath options:nil error:&error]; 90 | 91 | if( appleTexture == nil ) 92 | NSLog(@"Failed to load texture using Apple's buggy texture loader; error message (usually wrong!) from Apple: %@", error ); 93 | 94 | NSAssert( appleTexture != nil, @"Failed to load a texture using Apple's texture loader, with base filename '%@' and no extension", filename); 95 | 96 | return [self texturePreLoadedByApplesGLKit:appleTexture]; 97 | } 98 | } 99 | 100 | - (id)init 101 | { 102 | GLuint newName; 103 | glGenTextures(1, &newName); 104 | 105 | return [self initWithName:newName]; 106 | } 107 | 108 | /** DESIGNATED INITIALIZER: MUST BE CALLED EVENTUALLY, or else GLK2TextureTracker etc will break */ 109 | - (id)initWithName:(GLuint) name 110 | { 111 | self = [super init]; 112 | if (self) { 113 | self.glName = name; 114 | 115 | #if USE_GLK2TEXTURETRACKER_INTERNALLY 116 | [[GLK2TextureTracker sharedInstance] classTextureCreated:self]; 117 | #endif 118 | } 119 | return self; 120 | } 121 | 122 | - (void)dealloc 123 | { 124 | #if USE_GLK2TEXTURETRACKER_INTERNALLY 125 | [[GLK2TextureTracker sharedInstance] classTextureDeallocing:self]; 126 | 127 | // no need to glDeleteTextures - the GLK2TextureTracker will do that *IF* required 128 | #else 129 | if( self.willDeleteOnDealloc ) 130 | { 131 | NSLog(@"Dealloc: %@, glDeleteTexures( 1, %i)", [self class], self.glName ); 132 | glDeleteTextures(1, &_glName); 133 | } 134 | #endif 135 | 136 | [super dealloc]; 137 | } 138 | 139 | -(void)setDisableAutoDelete:(BOOL)newValue 140 | { 141 | if( _disableAutoDelete == newValue ) 142 | return; 143 | 144 | _disableAutoDelete = newValue; 145 | 146 | #if USE_GLK2TEXTURETRACKER_INTERNALLY 147 | if( self.disableAutoDelete ) 148 | { 149 | // create an artificial thing to keep it live 150 | [[GLK2TextureTracker sharedInstance] gpuTextureArtificiallyRetain:self.glName retainer:self]; 151 | } 152 | else 153 | { 154 | // REMOVE an artificial thing to keep it live 155 | [[GLK2TextureTracker sharedInstance] gpuTextureStopArtificiallyRetaining:self.glName retainer:self]; 156 | } 157 | #endif 158 | } 159 | 160 | -(NSString *)description 161 | { 162 | return [NSString stringWithFormat:@"Texture-%i%@", self.glName, self.disableAutoDelete? @"(WILL NEVER DELETE)" : @"" ]; 163 | } 164 | 165 | -(void) uploadFromNSData:(NSData *)rawData pixelsWide:(int) pWide pixelsHigh:(int) pHigh 166 | { 167 | /*************** 2. Upload NSData to OpenGL */ 168 | glBindTexture( GL_TEXTURE_2D, self.glName); 169 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 170 | 171 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pWide, pHigh, 0, GL_RGBA, GL_UNSIGNED_BYTE, [rawData bytes]); 172 | } 173 | 174 | -(void) reAssociateWithNewGPUTexture:(GLuint) newTextureName 175 | { 176 | if( newTextureName == self.glName ) 177 | return; // no effect 178 | 179 | #if USE_GLK2TEXTURETRACKER_INTERNALLY 180 | [[GLK2TextureTracker sharedInstance] classTexture:self switchingFrom:self.glName toNew:newTextureName]; 181 | #endif 182 | 183 | self.glName = newTextureName; 184 | } 185 | 186 | -(void)setWrapSClamp 187 | { 188 | glBindTexture( GL_TEXTURE_2D, self.glName); 189 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 190 | } 191 | -(void)setWrapTClamp 192 | { 193 | glBindTexture( GL_TEXTURE_2D, self.glName); 194 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 195 | } 196 | 197 | -(void)setWrapSRepeat 198 | { 199 | NSLog(@"Warning: GL ES is broken and makes wrap-S textures go all black if NPOT - but provides NO WAY to check if a texture is NPOT. Seriously bad API design"); 200 | 201 | glBindTexture( GL_TEXTURE_2D, self.glName); 202 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 203 | } 204 | -(void)setWrapTRepeat 205 | { 206 | NSLog(@"Warning: GL ES is broken and makes wrap-S textures go all black if NPOT - but provides NO WAY to check if a texture is NPOT. Seriously bad API design"); 207 | 208 | glBindTexture( GL_TEXTURE_2D, self.glName); 209 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 210 | } 211 | 212 | @end 213 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Texture_MutableName.h: -------------------------------------------------------------------------------- 1 | /** 2 | This is EXTREMELY DANGEROUS: it allows you to change the gl name of a texture; by definition, 3 | that's impossible - but Apple does it internally inside CoreVideo, and until Apple explains 4 | what they're doing and gives an official instrution, we have to play it safe and simply hack 5 | around their strangeness. 6 | 7 | c.f. GLK2Texture+CoreVideo.h 8 | */ 9 | 10 | @interface GLK2Texture() 11 | @property(nonatomic, readwrite) GLuint glName; 12 | @end 13 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Uniform.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | **** NB: if you add any properties, make sure you add them to "copyWithZone:" method too 4 | 5 | */ 6 | #import 7 | 8 | @interface GLK2Uniform : NSObject /** Apple's design of NSDictionary forces us to 'copy' keys, instead of mapping them */ 9 | 10 | +(GLK2Uniform*) uniformNamed:(NSString*) nameOfUniform GLType:(GLenum) openGLType GLLocation:(GLint) openGLLocation numElementsInArray:(GLint) numElements; 11 | 12 | /** The name of the variable inside the shader source file(s) */ 13 | @property(nonatomic, retain) NSString* nameInSourceFile; 14 | 15 | /** The magic key that allows you to "set" this uniform later, with a new value every frame (or draw call) */ 16 | @property(nonatomic) GLint glLocation; 17 | 18 | /** GL ES 2 specifies possible types: 19 | 20 | (NB: Desktop GL has *more* types; the complete list is here, but most of them ARE NOT ALLOWED in ES 2: http://www.opengl.org/sdk/docs/man/xhtml/glGetActiveUniform.xml ) 21 | 22 | BOOLEANS: bool, 2-bool-vector, 3-bool-vector, 4-bool-vector, 23 | INTEGERS: int, 2-int-vector, 3-int-vector, 4-int-vector, 24 | FLOATING POINTS: float, 2-float-vector, 3-float-vector, 4-float-vector, 2-matrix, 3-matrix, 4-matrix 25 | 26 | ... and the special types: (technically "uniforms" but have special code in OpenGL that treats them differently): 27 | 28 | TEXTURES: 2D texture, Cubemap texture 29 | */ 30 | @property(nonatomic) GLenum glType; 31 | 32 | /** A uniform can be an "array of" values, rather than a single value. This is "1" for a single value, or array length otherwise. From GL docs: 33 | 34 | "Uniform variables other than arrays 35 | will have a size of 1. Structures and arrays of structures will 36 | be reduced as described earlier, such that each of the names 37 | returned will be a data type in the earlier list. If this 38 | reduction results in an array, the size returned will be as 39 | described for uniform arrays; otherwise, the size returned will 40 | be 1." 41 | 42 | */ 43 | @property(nonatomic) GLint arrayLength; 44 | 45 | #pragma mark - Interpretation of OpenGL's badly-typed "type" feature 46 | 47 | @property(nonatomic,readonly) BOOL isInteger, isFloat, isVector, isMatrix; 48 | 49 | /** 4x4 matrix returns "4", etc - OpenGL has this info, refuses to provide it, but bizarrely: requires the application to re-submit it */ 50 | -(int) matrixWidth; 51 | 52 | /** 4x1 vector returns "4", etc - OpenGL has this info, refuses to provide it, but bizarrely: requires the application to re-submit it */ 53 | -(int) vectorWidth; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2Uniform.m: -------------------------------------------------------------------------------- 1 | #import "GLK2Uniform.h" 2 | 3 | @implementation GLK2Uniform 4 | 5 | +(GLK2Uniform *)uniformNamed:(NSString *)nameOfUniform GLType:(GLenum)openGLType GLLocation:(GLint)openGLLocation numElementsInArray:(GLint)numElements 6 | { 7 | GLK2Uniform* newValue = [[GLK2Uniform new] autorelease]; 8 | 9 | newValue.nameInSourceFile = nameOfUniform; 10 | newValue.glType = openGLType; 11 | newValue.glLocation = openGLLocation; 12 | newValue.arrayLength = numElements; 13 | /****** NB: if you add any properties, make sure you add them to "copyWithZone:" method too */ 14 | /****** NB: if you add any properties, make sure you add them to "isEqual:" method too */ 15 | 16 | return newValue; 17 | } 18 | 19 | #pragma mark - Interpretation of OpenGL's badly-typed "type" feature 20 | 21 | -(BOOL)isInteger 22 | { 23 | switch( self.glType ) 24 | { 25 | case GL_INT: 26 | case GL_INT_VEC2: 27 | case GL_INT_VEC3: 28 | case GL_INT_VEC4: 29 | return TRUE; 30 | 31 | default: 32 | return FALSE; 33 | } 34 | } 35 | 36 | -(BOOL)isFloat 37 | { 38 | switch( self.glType ) 39 | { 40 | case GL_FLOAT: 41 | case GL_FLOAT_VEC2: 42 | case GL_FLOAT_VEC3: 43 | case GL_FLOAT_VEC4: 44 | case GL_FLOAT_MAT2: 45 | case GL_FLOAT_MAT3: 46 | case GL_FLOAT_MAT4: 47 | return TRUE; 48 | 49 | default: 50 | return FALSE; 51 | } 52 | } 53 | 54 | -(BOOL)isMatrix 55 | { 56 | switch( self.glType ) 57 | { 58 | case GL_FLOAT_MAT2: 59 | case GL_FLOAT_MAT3: 60 | case GL_FLOAT_MAT4: 61 | return TRUE; 62 | 63 | default: 64 | return FALSE; 65 | } 66 | } 67 | 68 | -(BOOL)isVector 69 | { 70 | switch( self.glType ) 71 | { 72 | case GL_FLOAT_VEC2: 73 | case GL_FLOAT_VEC3: 74 | case GL_FLOAT_VEC4: 75 | case GL_INT_VEC2: 76 | case GL_INT_VEC3: 77 | case GL_INT_VEC4: 78 | return TRUE; 79 | 80 | default: 81 | return FALSE; 82 | } 83 | } 84 | 85 | -(int)vectorWidth 86 | { 87 | switch( self.glType ) 88 | { 89 | case GL_INT_VEC2: 90 | case GL_FLOAT_VEC2: 91 | return 2; 92 | case GL_INT_VEC3: 93 | case GL_FLOAT_VEC3: 94 | return 3; 95 | case GL_INT_VEC4: 96 | case GL_FLOAT_VEC4: 97 | return 4; 98 | 99 | default: 100 | return 0; 101 | } 102 | } 103 | 104 | -(int)matrixWidth 105 | { 106 | switch( self.glType ) 107 | { 108 | case GL_FLOAT_MAT2: 109 | return 2; 110 | case GL_FLOAT_MAT3: 111 | return 3; 112 | case GL_FLOAT_MAT4: 113 | return 4; 114 | 115 | default: 116 | return 0; 117 | } 118 | } 119 | 120 | -(NSString *)description 121 | { 122 | return [NSString stringWithFormat:@"", self.nameInSourceFile, self.glLocation, self.isVector? [NSString stringWithFormat:@"vec%i", self.vectorWidth] : self.isMatrix? [NSString stringWithFormat:@"mat%i", self.matrixWidth] : self.isFloat? @"float" : self.isInteger? @"int" : @"unknown type", self.arrayLength<2? @"" : [NSString stringWithFormat:@" (%i array elements)", self.arrayLength] ]; 123 | } 124 | 125 | #pragma mark - methods Apple requires us to implement to use this as a key in an NSDictionary 126 | 127 | -(id)copyWithZone:(NSZone *)zone 128 | { 129 | GLK2Uniform* newCopy = [[GLK2Uniform allocWithZone:zone] init]; 130 | 131 | newCopy.nameInSourceFile = self.nameInSourceFile; 132 | newCopy.glType = self.glType; 133 | newCopy.glLocation = self.glLocation; 134 | newCopy.arrayLength = self.arrayLength; 135 | 136 | return newCopy; 137 | } 138 | 139 | -(BOOL)isEqual:(id)object 140 | { 141 | /** 142 | WARNING! Because we overrode this, we MUST override hash too! 143 | 144 | Apple's default implementation of "hash" silently breaks if you don't 145 | overwrite it :( :( :( :(. Very bad design. 146 | */ 147 | if( [object class] != [self class] ) 148 | return FALSE; 149 | 150 | GLK2Uniform* other = (GLK2Uniform*) object; 151 | 152 | return other.glLocation == self.glLocation 153 | && other.glType == self.glType 154 | && other.arrayLength == self.arrayLength 155 | && [other.nameInSourceFile isEqualToString:self.nameInSourceFile]; 156 | } 157 | 158 | -(NSUInteger)hash 159 | { 160 | return [self.nameInSourceFile hash]; // very closely corresponds to the bucket/hash we would choose to use anyway 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2VertexArrayObject.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import "GLK2BufferObject.h" 3 | #import "GLK2Attribute.h" 4 | 5 | #define DEBUG_VAO_LIFECYCLE 0 6 | #define DEBUG_VBO_HANDLING 0 7 | 8 | @interface GLK2VertexArrayObject : NSObject 9 | 10 | @property(nonatomic, readonly) GLuint glName; 11 | 12 | @property(nonatomic,retain) NSMutableArray* VBOs; 13 | 14 | /** Delegates to the other method, defaults to using "GL_STATIC_DRAW" as the BufferObject update frequency */ 15 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems; 16 | 17 | /** Fully configurable creation of VBO + upload of data into that VBO */ 18 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq; 19 | 20 | /** If you have a VBO already uploaded to the GPU (e.g. used elsewhere), you can ADDITIONALLY add it to this VAO */ 21 | -(void) addVBO:(GLK2BufferObject*) vbo forAttributes:(NSArray*) targetAttributes; 22 | 23 | /** 24 | If you forget which VBO was which, you can use this to find the one that used the EXACT set of attributes (a single attribute, or an interleaved set) */ 25 | -(GLK2BufferObject*) VBOContainingOrderedAttributes:(NSArray*) targetAttributes; 26 | 27 | /** Detaching DOES NOT AFFECT THE GPU; but it releases all of this VAO's references to that VBO on client-side, 28 | which should trigger a dealloc, which MAY trigger a deletion from the GPU (but only if its safe) 29 | */ 30 | -(void) detachVBO:(GLK2BufferObject*) bufferToDetach; 31 | 32 | /** OpenGL's association of VAO's/VBO's has a very poor API, so you have to manually check and associate 33 | them whenever needed */ 34 | -(BOOL) containsVBO:(GLK2BufferObject*) buffer; 35 | 36 | /** ONLY exists so that you can clone a VAO while *sharing* the VBO's (required by the terrible 37 | design decisions of the OpenGL committee) 38 | */ 39 | -(NSArray*) attributesArrayForVBO:(GLK2BufferObject*) vbo; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/Essential OpenGL classes/GLK2VertexArrayObject.m: -------------------------------------------------------------------------------- 1 | #import "GLK2VertexArrayObject.h" 2 | 3 | #import 4 | 5 | @interface GLK2VertexArrayObject() 6 | @property(nonatomic, readwrite) GLuint glName; 7 | @property(nonatomic, retain) NSMutableDictionary* attributeArraysByVBOName; 8 | @end 9 | 10 | @implementation GLK2VertexArrayObject 11 | 12 | - (id)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | glGenVertexArraysOES( 1, &_glName ); 17 | self.VBOs = [NSMutableArray array]; 18 | self.attributeArraysByVBOName = [NSMutableDictionary dictionary]; // so we can find the VBO containing a set of attributes later 19 | } 20 | return self; 21 | } 22 | 23 | - (void)dealloc 24 | { 25 | NSArray* tempVBOS = [NSArray arrayWithArray:self.VBOs]; 26 | for( GLK2BufferObject* vbo in tempVBOS ) 27 | { 28 | [self detachVBO:vbo]; 29 | } 30 | 31 | self.attributeArraysByVBOName = nil; 32 | self.VBOs = nil; 33 | 34 | if( self.glName > 0 ) 35 | { 36 | #if DEBUG_VAO_LIFECYCLE 37 | NSLog(@"[%@] glDeleteVertexArraysOES(%i)", [self class], self.glName); 38 | #endif 39 | glDeleteVertexArraysOES( 1, &_glName); 40 | } 41 | 42 | [super dealloc]; 43 | } 44 | 45 | -(NSString *)description 46 | { 47 | NSMutableString* s = [NSMutableString string]; 48 | 49 | [s appendFormat:@"VAO-%i: ", self.glName]; 50 | [s appendString:@"["]; 51 | for( GLK2BufferObject* bo in self.VBOs ) 52 | { 53 | [s appendFormat:@" VBO-%i: format=%@", bo.glName, bo.currentFormat]; 54 | } 55 | [s appendString:@"]"]; 56 | return s; 57 | } 58 | 59 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems 60 | { 61 | return [self addVBOForAttribute:targetAttribute filledWithData:data bytesPerArrayElement:bytesPerDataItem arrayLength:numDataItems updateFrequency:GLK2BufferObjectFrequencyStatic]; 62 | } 63 | 64 | -(GLK2BufferObject*) addVBOForAttribute:(GLK2Attribute*) targetAttribute filledWithData:(const void*) data bytesPerArrayElement:(GLsizeiptr) bytesPerDataItem arrayLength:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq 65 | { 66 | NSAssert(targetAttribute != nil, @"Can't add a VBO for a nil vertex-attribute"); 67 | 68 | 69 | return [self addVBOForAttributes:@[targetAttribute] filledWithData:data inFormat:[GLK2BufferFormat bufferFormatOneAttributeMadeOfGLFloats:(GLuint)(bytesPerDataItem/4)] numVertices:numDataItems updateFrequency:freq]; 70 | } 71 | 72 | -(GLK2BufferObject*) addVBOForAttributes:(NSArray*) targetAttributes filledWithData:(const void*) data inFormat:(GLK2BufferFormat*) bFormat numVertices:(int) numDataItems updateFrequency:(GLK2BufferObjectFrequency) freq 73 | { 74 | /** Create a VBO on the GPU, to store data */ 75 | GLK2BufferObject* newVBO = [GLK2BufferObject newVBOFilledWithData:data inFormat:bFormat numVertices:numDataItems updateFrequency:freq]; 76 | 77 | /** Add to this VAO */ 78 | [self addVBO:newVBO forAttributes:targetAttributes]; 79 | return newVBO; 80 | } 81 | 82 | -(void) addVBO:(GLK2BufferObject*) vbo forAttributes:(NSArray*) targetAttributes 83 | { 84 | NSAssert( ![self.VBOs containsObject:vbo], @"Can't add a VBO, it's already added to this VAO"); 85 | /** Check if we already have a buffer that's mapped to any of those Attributes; GL does NOT ALLOW two buffers 86 | to provide data for the same Attribute (sadly, pathetically) */ 87 | for( NSNumber* numberOfName in self.attributeArraysByVBOName ) 88 | { 89 | NSArray* attsForNumber = [self.attributeArraysByVBOName objectForKey:numberOfName]; 90 | for( GLK2Attribute* previouslyMappedAttribute in attsForNumber ) 91 | { 92 | for( GLK2Attribute* newMappingAttribute in targetAttributes ) 93 | { 94 | NSAssert( previouslyMappedAttribute.glLocation != newMappingAttribute.glLocation, @"Attribute named: %@ was already mapped to a VBO in this VAO; you should detach VBO %i before adding VBO %i", newMappingAttribute.nameInSourceFile, [numberOfName intValue], vbo.glName ); 95 | } 96 | } 97 | } 98 | 99 | [self.VBOs addObject:vbo]; // so we can auto-release it when this class deallocs 100 | [self.attributeArraysByVBOName setObject:targetAttributes forKey:@(vbo.glName)]; 101 | #if DEBUG_VBO_HANDLING 102 | NSLog(@"VAO[%i] now has %lu VBOs", self.glName, (unsigned long)[self.VBOs count]); 103 | #endif 104 | 105 | /** Configure the VAO (state) */ 106 | glBindVertexArrayOES( self.glName ); 107 | GLsizeiptr bytesForPreviousItems = 0; 108 | int i = -1; 109 | for( GLK2Attribute* targetAttribute in targetAttributes ) 110 | { 111 | i++; 112 | GLuint numFloatsForItem = [vbo.currentFormat sizePerItemInFloatsForSubTypeIndex:i]; 113 | GLsizeiptr bytesPerItem = [vbo.currentFormat bytesPerItemForSubTypeIndex:i]; 114 | 115 | glBindBuffer( vbo.glBufferType, vbo.glName ); 116 | glEnableVertexAttribArray( targetAttribute.glLocation ); 117 | glVertexAttribPointer( targetAttribute.glLocation, numFloatsForItem, GL_FLOAT, GL_FALSE, (GLsizei) vbo.totalBytesPerItem, (const GLvoid*) bytesForPreviousItems); 118 | bytesForPreviousItems += bytesPerItem; 119 | } 120 | glBindVertexArrayOES(0); //unbind the vertex array, as a precaution against accidental changes by other classes 121 | } 122 | 123 | -(NSArray*) attributesArrayForVBO:(GLK2BufferObject*) vbo 124 | { 125 | return [self.attributeArraysByVBOName objectForKey:@(vbo.glName)]; 126 | } 127 | 128 | -(GLK2BufferObject*) VBOContainingOrderedAttributes:(NSArray*) targetAttributes 129 | { 130 | GLuint matchedBufferName = 0; 131 | for( NSNumber* numberOfName in self.attributeArraysByVBOName ) 132 | { 133 | NSArray* attsForNumber = [self.attributeArraysByVBOName objectForKey:numberOfName]; 134 | 135 | if( [targetAttributes isEqualToArray:attsForNumber] ) // only works because we implemented isEqual: on GLK2Attribute 136 | { 137 | matchedBufferName = (GLuint) [numberOfName unsignedIntValue]; 138 | break; 139 | } 140 | } 141 | if( matchedBufferName != 0 ) 142 | { 143 | for( GLK2BufferObject* bo in self.VBOs ) 144 | { 145 | if( bo.glName == matchedBufferName ) 146 | return bo; 147 | } 148 | 149 | NSAssert(FALSE, @"Major error: we found a buffer name (%i) that should have matched to one of our buffers in: %@", matchedBufferName, self.VBOs ); 150 | return nil; 151 | } 152 | else 153 | return nil; 154 | } 155 | 156 | -(void) detachVBO:(GLK2BufferObject*) bufferToDetach 157 | { 158 | NSUInteger index = [self.VBOs indexOfObject:bufferToDetach]; 159 | 160 | NSAssert( index != NSNotFound, @"Couldn't find that VBO to detach!" ); 161 | 162 | /** Major problem with Xcode5: even without ARC, Apple is incorrectly release'ing a reference too early here, the moment something leaves the array, instead of "at end of main loop" */ 163 | [bufferToDetach retain]; 164 | 165 | [self.VBOs removeObjectAtIndex:index]; 166 | [self.attributeArraysByVBOName removeObjectForKey:@(bufferToDetach.glName)]; 167 | 168 | #if DEBUG_VBO_HANDLING 169 | NSLog(@"VAO[%i]: released VBO with name = %i; if I was last remaining VAO, ObjC should dealloc it, and OpenGL will then delete it", self.glName, bufferToDetach.glName ); 170 | #endif 171 | 172 | [bufferToDetach release]; 173 | } 174 | 175 | -(BOOL)containsVBO:(GLK2BufferObject *)buffer 176 | { 177 | return [self.VBOs containsObject:buffer]; 178 | } 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/GLKX-Library-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #import 10 | #endif 11 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/GLKX_Library.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #pragma mark - all library public-headers should be imported here, so you can import this one file 4 | 5 | #import "GLK2Attribute.h" 6 | #import "GLK2Uniform.h" 7 | #import "GLK2BufferObject.h" 8 | #import "GLK2BufferFormat.h" 9 | #import "GLK2DrawCall.h" 10 | #import "GLK2Shader.h" 11 | #import "GLK2ShaderProgram.h" 12 | #import "GLK2Texture.h" 13 | #import "GLK2Texture+Coregraphics.h" 14 | #import "GLK2Uniform.h" 15 | #import "GLK2UniformValueGenerator.h" 16 | #import "GLK2VertexArrayObject.h" -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2Cube.h: -------------------------------------------------------------------------------- 1 | /** 2 | Apple has CGRect, and NSRect -- which use CGPoint and NSPoint 3 | Apple has NOTHING -- which uses GLKVector3 4 | 5 | ...but we need it whenever we talk about bounding-boxes in 3D, which is ...almost all the time! 6 | */ 7 | #import 8 | #import 9 | 10 | typedef struct GLK2Cube 11 | { 12 | GLKVector3 origin; 13 | GLKVector3 vectorAcross, vectorUp, vectorOut; 14 | } GLK2Cube; 15 | 16 | #pragma mark - NOTE: Apple doesn't provide a way for C projects/files to read the GLKit.h file, so we have to create a fake "class" to be allowed to write C functions 17 | 18 | @interface FAKE_CLASS_TO_SATISFY_APPLE : NSObject 19 | 20 | /** 21 | @param origin the "bottom left innermost corner" of the cube 22 | @param vAcross the vector in world space giving the cube's internal x-axis 23 | @param vUp the vector in world space giving the cube's internal y-axis 24 | @param vOut the vector in world space giving the cube's internal z-axis 25 | */ 26 | GLK2Cube GLK2CubeFromOriginAndBaseVectors( GLKVector3 o, GLKVector3 vAcross, GLKVector3 vUp, GLKVector3 vOut ); 27 | 28 | /** 29 | Returns a new cube with all base axes multiplied by the scalar 30 | */ 31 | GLK2Cube GLK2CubeMultiplyScalar( GLK2Cube oldCube, CGFloat scalar ); 32 | 33 | /** 34 | Adds offset to the cube's origin 35 | */ 36 | GLK2Cube GLK2CubeOffsetBy( GLK2Cube oldCube, GLKVector3 offset ); 37 | 38 | /** 39 | Takes the X, Y, and Z of vector, and multiplies the cube along its own axes by those 40 | amounts. 41 | 42 | e.g. for vector( 2, 1, 0 ), you get a new cube with cube.vectorAcross = 2* original, 43 | cube.vectorUp = original, and cube.vectorOut = 0 44 | */ 45 | GLK2Cube GLK2CubeMultiplyBaseVectors( GLK2Cube oldCube, GLKVector3 vector ); 46 | 47 | //NSString* NSStringFromGLK2Cube( GLK2Cube cube ); 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2Cube.m: -------------------------------------------------------------------------------- 1 | #import "GLK2Cube.h" 2 | 3 | @implementation FAKE_CLASS_TO_SATISFY_APPLE 4 | 5 | GLK2Cube GLK2CubeFromOriginAndBaseVectors( GLKVector3 o, GLKVector3 vAcross, GLKVector3 vUp, GLKVector3 vOut ) 6 | { 7 | GLK2Cube cube = { o, vAcross, vUp, vOut }; 8 | 9 | return cube; 10 | } 11 | 12 | GLK2Cube GLK2CubeMultiplyScalar( GLK2Cube oldCube, CGFloat scalar ) 13 | { 14 | GLK2Cube cube = { oldCube.origin, 15 | GLKVector3MultiplyScalar( oldCube.vectorAcross, scalar), 16 | GLKVector3MultiplyScalar( oldCube.vectorUp, scalar), 17 | GLKVector3MultiplyScalar( oldCube.vectorOut, scalar) 18 | }; 19 | 20 | return cube; 21 | } 22 | 23 | GLK2Cube GLK2CubeMultiplyBaseVectors( GLK2Cube oldCube, GLKVector3 vector ) 24 | { 25 | GLK2Cube cube = { oldCube.origin, 26 | GLKVector3MultiplyScalar( oldCube.vectorAcross, vector.x ), 27 | GLKVector3MultiplyScalar( oldCube.vectorUp, vector.y ), 28 | GLKVector3MultiplyScalar( oldCube.vectorOut, vector.z ) 29 | }; 30 | 31 | return cube; 32 | } 33 | 34 | GLK2Cube GLK2CubeOffsetBy( GLK2Cube oldCube, GLKVector3 offset ) 35 | { 36 | GLK2Cube cube = { GLKVector3Add( oldCube.origin, offset ), 37 | oldCube.vectorAcross, 38 | oldCube.vectorUp, 39 | oldCube.vectorOut 40 | }; 41 | 42 | return cube; 43 | } 44 | 45 | /*GLK2Cube GLK2CubeFromRect( GLKVector3 topLeft, GLKVector3 topRight, GLKVector3 bottomRight, GLKVector3 bottomLeft ) 46 | { 47 | GLK2Cube cube; 48 | 49 | 50 | return cube; 51 | }*/ 52 | 53 | /*NSString* NSStringFromGLK2Cube( GLK2Cube cube ) 54 | { 55 | return [NSString stringWithFormat:@"{ %@, %@, %@, %@}", NSStringFromGLKVector3(cube.topLeft), NSStringFromGLKVector3(rect.topRight), NSStringFromGLKVector3(rect.bottomRight), NSStringFromGLKVector3(rect.bottomLeft) ]; 56 | } 57 | */ 58 | @end 59 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2ExampleUniformValueGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Trivial example / base class for implementing the GLK2UniformValueGenerator protocol 5 | 6 | (note how the .m file implements the different methods) 7 | */ 8 | #import 9 | 10 | #import "GLK2UniformValueGenerator.h" 11 | 12 | @interface GLK2ExampleUniformValueGenerator : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2ExampleUniformValueGenerator.m: -------------------------------------------------------------------------------- 1 | #import "GLK2ExampleUniformValueGenerator.h" 2 | 3 | @implementation GLK2ExampleUniformValueGenerator 4 | 5 | -(GLKVector2*) vector2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 6 | -(GLKVector3*) vector3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 7 | -(GLKVector4*) vector4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 8 | 9 | -(GLKMatrix2*) matrix2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 10 | -(GLKMatrix3*) matrix3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 11 | -(GLKMatrix4*) matrix4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall { return NULL; } 12 | 13 | -(BOOL) floatForUniform:(GLK2Uniform*) v returnIn:(GLfloat*) value inDrawCall:(GLK2DrawCall*) drawCall { return FALSE; } 14 | -(BOOL) intForUniform:(GLK2Uniform*) v returnIn:(GLint*) value inDrawCall:(GLK2DrawCall*) drawCall { return FALSE; } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2HardwareMaximums.h: -------------------------------------------------------------------------------- 1 | /** 2 | Requesting this info actually takes time, but cannot change over lifetime of the app, 3 | because it's permanent hardware info. 4 | 5 | Note: some Android phones might switch between multiple GPUs, but for OpenGL ES on iOS 6 | ... you'll only ever have one GPU / GL driver available 7 | 8 | Makes life easier to collect this info at program start, and cache it on CPU side. 9 | 10 | Make sure you call [* readAllGLMaximums] at least once at the start of your app - but AFTER 11 | the GL has been setup and configured, and you've done a [GLKview bindDrawable] etc 12 | */ 13 | #import 14 | 15 | /** Apple's engineers are misguided in believing you can write software without knowing how 16 | much RAM is in the physical device. 17 | 18 | With OpenGL, where e.g. iPad Mini loads the same 4k 19 | textures as an iPad3, but has considerably LESS RAM ... you WILL get crashes if you try to 20 | load the same textures on both devices. 21 | */ 22 | typedef NS_ENUM(NSInteger, DeviceMemoryInBytes ) 23 | { 24 | DeviceMemory0Bytes, 25 | DeviceMemory128MegaBytes, 26 | DeviceMemory256MegaBytes, 27 | DeviceMemory512MegaBytes, 28 | DeviceMemory1024MegaBytes, 29 | DeviceMemory2048MegaBytes 30 | }; 31 | 32 | @interface GLK2HardwareMaximums : NSObject 33 | 34 | /** The first time you invoke this, it reads the values from the GPU. 35 | 36 | Afterwards, it uses cached data 37 | */ 38 | +(GLK2HardwareMaximums*) sharedInstance; 39 | 40 | /** Maximum width or height of any texture, in pixels */ 41 | @property(nonatomic,readonly) GLint glMaxTextureSize; 42 | 43 | /** Amount of RAM the iOS device contains (constrains texture-ram, but is total RAM) */ 44 | @property(nonatomic,readonly) DeviceMemoryInBytes iOSDeviceRAM; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2HardwareMaximums.m: -------------------------------------------------------------------------------- 1 | #import "GLK2HardwareMaximums.h" 2 | 3 | #include // So we can calculate RAM in device 4 | #include // So we can calculate RAM in device 5 | 6 | @interface GLK2HardwareMaximums() 7 | @property(nonatomic,readwrite) GLint glMaxTextureSize; 8 | @property(nonatomic,readwrite) DeviceMemoryInBytes iOSDeviceRAM; 9 | @end 10 | 11 | @implementation GLK2HardwareMaximums 12 | 13 | +(GLK2HardwareMaximums*) sharedInstance 14 | { 15 | static GLK2HardwareMaximums* internalInstance; 16 | if( internalInstance == nil ) 17 | { 18 | internalInstance = [GLK2HardwareMaximums new]; 19 | [internalInstance readAllGLMaximums]; 20 | } 21 | 22 | return internalInstance; 23 | } 24 | 25 | - (id)init 26 | { 27 | self = [super init]; 28 | if (self) { 29 | self.iOSDeviceRAM = DeviceMemory0Bytes; 30 | } 31 | return self; 32 | } 33 | 34 | -(void) readAllGLMaximums 35 | { 36 | glGetIntegerv( GL_MAX_TEXTURE_SIZE, &_glMaxTextureSize ); 37 | 38 | /** 39 | This section exists because Apple refuses to give core info to iOS developers. 40 | 41 | It is not possible to make games that work on 128Mb ram and 1,024Mb 42 | RAM while ignoring the difference. It's stupid to pretend otherwise! 43 | 44 | Data comes from Wikipedia etc on which hardware-codes refer to which device, with how much RAM 45 | */ 46 | size_t size; 47 | sysctlbyname("hw.machine", NULL, &size, NULL, 0); 48 | char *machine = malloc(size); 49 | sysctlbyname("hw.machine", machine, &size, NULL, 0); 50 | NSString *platform = [NSString stringWithUTF8String:machine]; 51 | free(machine); 52 | 53 | if( [platform hasPrefix:@"iPhone1"]) 54 | self.iOSDeviceRAM = DeviceMemory128MegaBytes; 55 | else if( [platform hasPrefix:@"iPhone2"]) 56 | self.iOSDeviceRAM = DeviceMemory256MegaBytes; 57 | else if( [platform hasPrefix:@"iPhone3"]) // iPhone4 in reality 58 | self.iOSDeviceRAM = DeviceMemory512MegaBytes; 59 | else if( [platform hasPrefix:@"iPhone4"]) // iPhone4S in reality 60 | self.iOSDeviceRAM = DeviceMemory1024MegaBytes; 61 | else if( [platform hasPrefix:@"iPhone5"]) // iPhone5 AND iPhone5C 62 | self.iOSDeviceRAM = DeviceMemory1024MegaBytes; 63 | else if( [platform hasPrefix:@"iPhone6"]) // iPhone5S in reality 64 | self.iOSDeviceRAM = DeviceMemory1024MegaBytes; 65 | else if( [platform hasPrefix:@"iPhone"]) // catch-all for higher-end devices not yet existing 66 | self.iOSDeviceRAM = DeviceMemory1024MegaBytes; 67 | 68 | else if( [platform hasPrefix:@"iPod1"]) 69 | self.iOSDeviceRAM = DeviceMemory128MegaBytes; 70 | else if( [platform hasPrefix:@"iPod2"]) 71 | self.iOSDeviceRAM = DeviceMemory128MegaBytes; 72 | else if( [platform hasPrefix:@"iPod3"]) 73 | self.iOSDeviceRAM = DeviceMemory256MegaBytes; 74 | else if( [platform hasPrefix:@"iPod4"]) 75 | self.iOSDeviceRAM = DeviceMemory256MegaBytes; 76 | else if( [platform hasPrefix:@"iPod5"]) 77 | self.iOSDeviceRAM = DeviceMemory512MegaBytes; 78 | else if( [platform hasPrefix:@"iPod"]) // catch-all for higher-end devices not yet existing 79 | self.iOSDeviceRAM = DeviceMemory512MegaBytes; 80 | 81 | else if( [platform hasPrefix:@"iPad1"]) 82 | self.iOSDeviceRAM = DeviceMemory256MegaBytes; 83 | else if( [platform hasPrefix:@"iPad2"]) // includes iPad Mini, which has same RAM as iPad2 84 | self.iOSDeviceRAM = DeviceMemory512MegaBytes; 85 | else if( [platform hasPrefix:@"iPad3"]) 86 | self.iOSDeviceRAM = DeviceMemory2048MegaBytes; 87 | else if( [platform hasPrefix:@"iPad4"]) 88 | self.iOSDeviceRAM = DeviceMemory2048MegaBytes; 89 | else if( [platform hasPrefix:@"iPad5"]) 90 | self.iOSDeviceRAM = DeviceMemory2048MegaBytes; 91 | else if( [platform hasPrefix:@"iPad"]) // catch-all for higher-end devices not yet existing 92 | self.iOSDeviceRAM = DeviceMemory2048MegaBytes; 93 | 94 | else if( [platform hasPrefix:@"x86_64"]) 95 | self.iOSDeviceRAM = DeviceMemory1024MegaBytes; // Simulator, running on desktop machine 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2TextureTracker.h: -------------------------------------------------------------------------------- 1 | /** 2 | Tracks all GL texture allocation, creation, destruction, re-use, etc. 3 | 4 | ALSO: intelligently manages memory for textures (e.g. calling glDeleteTextures 5 | when appropriate). 6 | 7 | Partly this class is for debugging! If only Apple's Frame-analyzer were faster / had the 8 | features of ATI, nVidia, etc. 9 | 10 | BUT ALSO: this class is very useful as a low-level / generic texture management system. 11 | You can extend it / build on it to make your own custom manager - but this handles the 12 | very basics that all GL apps need. 13 | */ 14 | #import 15 | 16 | #import "GLK2Texture.h" 17 | 18 | typedef enum GLK2TextureTrackerCleanupMode 19 | { 20 | GLK2TextureTrackerCleanupModeInstant = 0, // instantaneously cals glDeleteTextures whenever a texture has no referrers 21 | GLK2TextureTrackerCleanupModePeriodic // requires you to manually call garbageCollectDanglingGPUTextures periodically 22 | } GLK2TextureTrackerCleanupMode; 23 | 24 | @interface GLK2TextureTracker : NSObject 25 | 26 | +(GLK2TextureTracker*) sharedInstance; 27 | 28 | #pragma mark - Critical cleanup 29 | 30 | @property(nonatomic) GLK2TextureTrackerCleanupMode cleanupMode; 31 | 32 | /** 33 | If you change cleanupMode to GLK2TextureTrackerCleanupModePeriodic, you MUST call this method periodically, 34 | or you will get infinite memory leaks every time you stop using a texture 35 | 36 | Alternatively, use the default mode and cleanup will be done automatically for each texture as soon as the 37 | texture is no longer in use. 38 | 39 | Call this periodically - e.g. once at end of each frame 40 | */ 41 | -(NSUInteger) garbageCollectDanglingGPUTextures; 42 | 43 | #pragma mark - General methods for supporting 3rd party classes 44 | 45 | /** If you create a texture manually, NOT using GLK2Texture, make sure you inform the tracker, or else it MIGHT auto-delete your texture when there are no more GLK2Texture's using it */ 46 | -(void) gpuTextureCreatedWithoutClassTexture:(GLuint) textureName; 47 | /** Signals to this class that it MAY delete the GPU texture if nothing else is still using it */ 48 | -(void) gpuTextureReleasedWithoutClassTexture:(GLuint) textureName; 49 | 50 | -(void) gpuTextureArtificiallyRetain:(GLuint)textureName retainer:(NSObject*) retainer; 51 | -(void) gpuTextureStopArtificiallyRetaining:(GLuint)textureName retainer:(NSObject*) retainer; 52 | 53 | #pragma mark - Automatic Integration with GLKX / GLK2 classes 54 | 55 | /** Invoked by GLK2Texture every time a new class is created on CPU representing a texture */ 56 | -(void) classTextureCreated:(GLK2Texture*) texture; 57 | 58 | /** Invoked when GLK2Texture disassociates from one GPU texture, and reassociates with another */ 59 | -(void)classTexture:(GLK2Texture*) texture switchingFrom:(GLuint)oldTextureName toNew:(GLuint)newTextureName; 60 | 61 | /** Invoked by GLK2Texture every time a class on CPU representing a texture is dealloc'd */ 62 | -(void) classTextureDeallocing:(GLK2Texture*) texture; 63 | 64 | #pragma mark - Useful diagnostics and output info 65 | 66 | -(NSUInteger) totalGLTexturesCurrentlyOnGPU; 67 | -(NSArray*) textureNamesOnGPU; 68 | -(NSArray*) referencesToTexture:(GLuint) textureName; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2TextureTracker_UnitTesting.h: -------------------------------------------------------------------------------- 1 | #import "GLK2TextureTracker.h" 2 | 3 | @interface GLK2TextureTracker () 4 | 5 | +(void) forceDeallocSharedInstance; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2UniformMap.h: -------------------------------------------------------------------------------- 1 | /** 2 | OpenGL is a C-only library. Apple did NOT implement it to be Obj-C compatible. 3 | 4 | Mostly this is not a problem, but Shader Uniforms have to be sent as "non-object pointers", 5 | which causes chaos: none of the Obj-C libraries support this. You are required to 6 | write some pure-C code to convert ObjC, which is ridiculous (and VERY slow). 7 | 8 | This class uses the info we have about Uniforms (that they can only have one of a small number 9 | of types, each of which is a struct) to construct an efficient and simple solution. 10 | 11 | Apple REALLY should have included this in GLKit! 12 | */ 13 | #import 14 | 15 | #import 16 | #import "GLK2ShaderProgram.h" 17 | 18 | #define LOG_WARNINGS_ON_MISSING_UNIFORMS 1 19 | 20 | @interface GLK2UniformMap : NSObject 21 | 22 | /** 23 | Allocates precisely the amount of storage needed to hold all uniform names and values 24 | for the ShaderProgram you provide. 25 | 26 | Make sure the shaderProgram is already linked, otherwise it might have NO INFO on which 27 | uniforms it contains! 28 | */ 29 | +(GLK2UniformMap*) uniformMapForLinkedShaderProgram:(GLK2ShaderProgram*) shaderProgram; 30 | 31 | /** 32 | Allocates precisely the amount of storage needed to hold all uniform names and values 33 | listed. 34 | */ 35 | - (id)initWithUniforms:(NSArray*) allUniforms; 36 | 37 | #pragma mark - methods for setting and getting via pointers 38 | -(GLKMatrix2*) pointerToMatrix2Named:(NSString*) name; 39 | -(GLKMatrix3*) pointerToMatrix3Named:(NSString*) name; 40 | -(GLKMatrix4*) pointerToMatrix4Named:(NSString*) name; 41 | -(void) setMatrix2:(GLKMatrix2) value named:(NSString*) name; 42 | -(void) setMatrix3:(GLKMatrix3) value named:(NSString*) name; 43 | -(void) setMatrix4:(GLKMatrix4) value named:(NSString*) name; 44 | 45 | -(GLKVector2*) pointerToVector2Named:(NSString*) name; 46 | -(GLKVector3*) pointerToVector3Named:(NSString*) name; 47 | -(GLKVector4*) pointerToVector4Named:(NSString*) name; 48 | -(void) setVector2:(GLKVector2) value named:(NSString*) name; 49 | -(void) setVector3:(GLKVector3) value named:(NSString*) name; 50 | -(void) setVector4:(GLKVector4) value named:(NSString*) name; 51 | 52 | #pragma mark - Primitives 53 | 54 | -(GLint*) pointerToIntNamed:(NSString*) name isValid:(BOOL*) isValid; 55 | -(GLfloat*) pointerToFloatNamed:(NSString*) name isValid:(BOOL*) isValid; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2UniformMapGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | */ 4 | #import 5 | 6 | #import "GLK2UniformValueGenerator.h" 7 | #import "GLK2UniformMap.h" 8 | #import "GLK2DrawCall.h" 9 | 10 | @interface GLK2UniformMapGenerator : GLK2UniformMap 11 | 12 | /** 13 | Generally, you should use createAndAddToDrawCall: instead - that method delegates 14 | to this one 15 | */ 16 | +(GLK2UniformMapGenerator*) generatorForShaderProgram:(GLK2ShaderProgram*) shaderProgram; 17 | 18 | /** Creates a generator for the drawcall's current ShaderProgram, and attaches it 19 | directly to the DrawCall 20 | */ 21 | +(GLK2UniformMapGenerator *)createAndAddToDrawCall:(GLK2DrawCall *)drawcall; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/GLK2UniformMapGenerator.m: -------------------------------------------------------------------------------- 1 | #import "GLK2UniformMapGenerator.h" 2 | 3 | @implementation GLK2UniformMapGenerator 4 | 5 | +(GLK2UniformMapGenerator *)generatorForShaderProgram:(GLK2ShaderProgram *)shaderProgram 6 | { 7 | if( shaderProgram == nil ) 8 | return nil; 9 | 10 | GLK2UniformMapGenerator* newValue = [[GLK2UniformMapGenerator alloc] initWithUniforms:shaderProgram.allUniforms]; 11 | 12 | return newValue; 13 | } 14 | 15 | +(GLK2UniformMapGenerator *)createAndAddToDrawCall:(GLK2DrawCall *)drawcall 16 | { 17 | if( drawcall == nil ) 18 | return nil; 19 | 20 | GLK2UniformMapGenerator* newValue = [self generatorForShaderProgram:drawcall.shaderProgram]; 21 | drawcall.uniformValueGenerator = newValue; 22 | 23 | return newValue; 24 | } 25 | 26 | #pragma mark - Matrices 27 | 28 | -(GLKMatrix2*) matrix2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall 29 | { 30 | return [self pointerToMatrix2Named:v.nameInSourceFile]; 31 | } 32 | 33 | -(GLKMatrix3*) matrix3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall 34 | { 35 | return [self pointerToMatrix3Named:v.nameInSourceFile]; 36 | } 37 | 38 | -(GLKMatrix4 *)matrix4ForUniform:(GLK2Uniform *)v inDrawCall:(GLK2DrawCall *)drawCall 39 | { 40 | return [self pointerToMatrix4Named:v.nameInSourceFile]; 41 | } 42 | 43 | #pragma mark - Vectors 44 | 45 | -(GLKVector2*) vector2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall 46 | { 47 | return [self pointerToVector2Named:v.nameInSourceFile]; 48 | } 49 | 50 | -(GLKVector3*) vector3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall 51 | { 52 | return [self pointerToVector3Named:v.nameInSourceFile]; 53 | } 54 | 55 | -(GLKVector4 *)vector4ForUniform:(GLK2Uniform *)v inDrawCall:(GLK2DrawCall *)drawCall 56 | { 57 | return [self pointerToVector4Named:v.nameInSourceFile]; 58 | } 59 | 60 | -(BOOL) floatForUniform:(GLK2Uniform*) v returnIn:(GLfloat*) value inDrawCall:(GLK2DrawCall*) drawCall 61 | { 62 | BOOL isValid; 63 | *value = *[self pointerToFloatNamed:v.nameInSourceFile isValid:&isValid]; 64 | 65 | return isValid; 66 | } 67 | 68 | -(BOOL) intForUniform:(GLK2Uniform*) v returnIn:(GLint*) value inDrawCall:(GLK2DrawCall*) drawCall 69 | { 70 | BOOL isValid; 71 | *value = *[self pointerToIntNamed:v.nameInSourceFile isValid:&isValid]; 72 | 73 | return isValid; 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL OOP Improvements/Protocols/GLK2UniformValueGenerator.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Each drawcall, you can ask this object to provide values for any/all of the GL Uniforms 5 | in the current shader program. 6 | 7 | This attempts to efficiently extend VertexArrayObjects to cover ShaderProgram Uniforms, 8 | which the OpenGL committee failed to include. 9 | 10 | c.f. http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt 11 | 12 | "This extension introduces vertex array objects which encapsulate 13 | vertex array states on the server side (vertex buffer objects). 14 | These objects aim to keep pointers to vertex data and to provide 15 | names for different sets of vertex data. Therefore applications are 16 | allowed to rapidly switch between different sets of vertex array 17 | state, and to easily return to the default vertex array state." 18 | 19 | Design: 20 | - whenever the engine switches to a new Draw call, it queries 21 | the Draw call for one of these objects 22 | - the engine inspects the current ShaderProgram to find out what 23 | Uniforms it possesses, and then asks this object to provide them 24 | - any value that this object DOES NOT PROVIDE (returns NULL or FALSE) 25 | causes the engine to NOT CHANGE THE EXISTING GPU-SIDE VALUE 26 | */ 27 | #import 28 | #import 29 | 30 | #import "GLK2Uniform.h" 31 | 32 | @class GLK2DrawCall; 33 | 34 | @protocol GLK2UniformValueGenerator 35 | 36 | @optional 37 | 38 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 39 | -(GLKVector2*) vector2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 40 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 41 | -(GLKVector3*) vector3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 42 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 43 | -(GLKVector4*) vector4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 44 | 45 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 46 | -(GLKMatrix2*) matrix2ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 47 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 48 | -(GLKMatrix3*) matrix3ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 49 | /** Returns NULL pointer if this object has no value / wants you to leave the value alone */ 50 | -(GLKMatrix4*) matrix4ForUniform:(GLK2Uniform*) v inDrawCall:(GLK2DrawCall*) drawCall; 51 | 52 | /** Returns FALSE if this object has no value / wants you to leave the value alone, because C doesn't support null primitives */ 53 | -(BOOL) floatForUniform:(GLK2Uniform*) v returnIn:(float*) value inDrawCall:(GLK2DrawCall*) drawCall; 54 | /** Returns FALSE if this object has no value / wants you to leave the value alone, because C doesn't support null primitives */ 55 | -(BOOL) intForUniform:(GLK2Uniform*) v returnIn:(GLint*) value inDrawCall:(GLK2DrawCall*) drawCall; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with Textures/GLK2Texture+CoreGraphics.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | */ 4 | 5 | #import "GLK2Texture.h" 6 | #import 7 | 8 | @interface GLK2Texture (CoreGraphics) 9 | 10 | /** 11 | 1 of 2: 12 | 13 | Create a CGContext that you can convert into a texture. 14 | 15 | This creates the CPU-side memory and context 16 | */ 17 | +(CGContextRef) createCGContextForOpenGLTextureRGBAWidth:(int) width h:(int) height bitsPerPixel:(int) bpp shouldFlipY:(BOOL) flipY fillColorOrNil:(UIColor*) fillColor; 18 | 19 | /** 20 | 2 of 2: 21 | 22 | Convert a previously-created CGContext into an OpenGL texture, and upload to the GPU 23 | */ 24 | +(GLK2Texture*) uploadTextureRGBAToOpenGLFromCGContext:(CGContextRef) context width:(int)w height:(int)h; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with Textures/GLK2Texture+CoreGraphics.m: -------------------------------------------------------------------------------- 1 | #import "GLK2Texture+CoreGraphics.h" 2 | 3 | @implementation GLK2Texture (CoreGraphics) 4 | 5 | +(CGContextRef) createCGContextForOpenGLTextureRGBAWidth:(int) width h:(int) height bitsPerPixel:(int) bpp shouldFlipY:(BOOL) flipY fillColorOrNil:(UIColor*) fillColor 6 | { 7 | NSAssert( (width & (width - 1)) == 0, @"PowerVR will render your texture as ALL BLACK because you provided a width that's not power-of-two"); 8 | NSAssert( (height & (height - 1)) == 0, @"PowerVR will render your texture as ALL BLACK because you provided a height that's not power-of-two"); 9 | 10 | /** Create a texture to render from */ 11 | /*************** 1. Convert to NSData */ 12 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 13 | CGContextRef context = CGBitmapContextCreate( NULL/*malloc( self.size.width * self.size.height * 4 )*/, width, height, 8, 4 * width, colorSpace, /** NB: very bad API coding from Apple - incompatible types EXPECTED here accoriding to API docs! */ (CGBitmapInfo) kCGImageAlphaPremultipliedLast ); 14 | CGColorSpaceRelease( colorSpace ); 15 | //DEBUG: 16 | //CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 17 | 18 | if( fillColor != nil ) 19 | { 20 | CGContextSetFillColorWithColor(context, fillColor.CGColor); 21 | CGContextFillRect(context, CGRectMake(0,0,width,height)); 22 | } 23 | 24 | if( flipY ) 25 | { 26 | CGAffineTransform flipVertical = CGAffineTransformMake( 27 | 1, 0, 0, -1, 0, height 28 | ); 29 | CGContextConcatCTM(context, flipVertical); 30 | } 31 | 32 | return context; 33 | } 34 | 35 | +(GLK2Texture*) uploadTextureRGBAToOpenGLFromCGContext:(CGContextRef) context width:(int)w height:(int)h 36 | { 37 | void* resultAsVoidStar = CGBitmapContextGetData(context); 38 | 39 | size_t dataSize = 4 * w * h; // RGBA = 4 * 8-bit components == 4 * 1 bytes 40 | NSData* result = [NSData dataWithBytes:resultAsVoidStar length:dataSize]; 41 | 42 | //DEBUG: NSLog(@"texture raw data = %@", result ); 43 | 44 | CGContextRelease(context); 45 | 46 | /*************** 2. Upload NSData to OpenGL */ 47 | GLK2Texture* newTextureReference = [[[GLK2Texture alloc] init] autorelease]; 48 | 49 | glBindTexture( GL_TEXTURE_2D, newTextureReference.glName); 50 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 51 | 52 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)w, (int)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, [result bytes]); 53 | 54 | return newTextureReference; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with Textures/GLK2Texture+CoreVideo.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Requires you to add the CoreVideo framework to your project if you want to use this. 5 | */ 6 | #import "GLK2Texture.h" 7 | 8 | @interface GLK2Texture (CoreVideo) 9 | 10 | +(GLK2Texture*) texturePreCreatedByApplesCoreVideo:(CVOpenGLESTextureRef) applCoreVideoTexture; 11 | 12 | /** 13 | THIS METHOD IS AGAINST THE ENTIRE ETHOS OF OPENGL, but Apple does some weird and crazy stuff 14 | inside CoreVideo, and refuses to document it - as a result, we HAVE to do this, or else we'll 15 | get memory leaks and app crashes and flickering etc. 16 | 17 | (basically: Apple trashes the GL textures, over and over again, at random rates, depending on 18 | how much CPU / GPU processing is happening in the background. NONE OF THIS IS DOCUMENTED!) 19 | 20 | Until Apple documents their shamefully obscure API (it's been 2 years now and we're all still waiting!) 21 | we have to accept that Apple "switches" the texture IDs of live textures around, and we have to 22 | follow suit. 23 | */ 24 | -(void) liveAlterGLNameToWorkaroundAppleCoreVideoBug:(GLuint) newName; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with Textures/GLK2Texture+CoreVideo.m: -------------------------------------------------------------------------------- 1 | #import "GLK2Texture+CoreVideo.h" 2 | 3 | #import "GLK2Texture_MutableName.h" 4 | 5 | @implementation GLK2Texture (CoreVideo) 6 | 7 | +(GLK2Texture*) texturePreCreatedByApplesCoreVideo:(CVOpenGLESTextureRef) appleCoreVideoTexture 8 | { 9 | GLK2Texture* newValue = [[[GLK2Texture alloc] initWithName:CVOpenGLESTextureGetName(appleCoreVideoTexture)]autorelease]; 10 | 11 | return newValue; 12 | } 13 | 14 | -(void) liveAlterGLNameToWorkaroundAppleCoreVideoBug:(GLuint) newName 15 | { 16 | self.glName = newName; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with Textures/GLK2TextureLoaderPVRv1.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Part 7 3 | 4 | Based on Apple's example source code "PVRTexture.h / .m version 1.5", heavily modified 5 | 6 | Apple's code is very outdated, and only loads v1 PVR files. PVR supports these using 7 | the "legacy" option in the Imagination / PVR tools - anything else will fail / crash. 8 | */ 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | #import "GLK2Texture.h" 15 | 16 | @interface PVRTextureV1 : GLK2Texture 17 | 18 | @property(nonatomic,retain,readonly) NSMutableArray *imageData; 19 | 20 | @property(nonatomic,readonly) uint32_t width, height; 21 | 22 | @property(nonatomic,readonly) GLenum internalFormat; 23 | @property(nonatomic,readonly) BOOL hasAlpha; 24 | 25 | /** filename/path if it was from disk, or URL string if from URL */ 26 | @property(nonatomic,retain,readonly) NSString* textureSourceFileInfo; 27 | 28 | @end 29 | 30 | @interface GLK2TextureLoaderPVRv1 : NSObject 31 | 32 | /** 33 | Returns a GL2KTexture object, with the PVR texture pre-uploaded to the GPU, 34 | and any MipMaps created as appropriate, as limited by setMaximumTextureSizeToLoadInMipMaps: 35 | */ 36 | + (PVRTextureV1*)pvrTextureWithContentsOfFile:(NSString *)path; 37 | 38 | /** 39 | Returns a GL2KTexture object, with the PVR texture pre-uploaded to the GPU, 40 | and any MipMaps created as appropriate, as limited by setMaximumTextureSizeToLoadInMipMaps: 41 | */ 42 | + (PVRTextureV1*)pvrTextureWithContentsOfURL:(NSURL *)url; 43 | 44 | /** 45 | Some Apple hardware - most notably the iPad Mini - "can" read 4k,4k textures, but the thing has 46 | nowhere near enough RAM to actually run an app at the same time (it uses same-size textures as an 47 | iPad 3 / 4 / 5, but has ONE QUARTER of the RAM!). 48 | 49 | This method allows you to prevent mipmaps being loaded, even if the chip says it "can", but you know 50 | it "shouldn't" 51 | 52 | This is measured in the same units as GL's glGetIntegerv( GL_MAX_TEXTURE_SIZE, ... ) - e.g. 4096 is 53 | equal to "a texture 4096 pixels wide, and 4096 pixels high" 54 | 55 | If you send a value of "0" that will be treated as "no limit" (which is the default) 56 | */ 57 | +(void)setMaximumTextureSizeToLoadInMipMaps:(GLint) newMax; 58 | 59 | @end -------------------------------------------------------------------------------- /GLKX-Library/GLKX-Library/OpenGL with UIKit/GLK2DrawCallViewController.h: -------------------------------------------------------------------------------- 1 | /** 2 | Introduced in: Refactoring-1 (approximately Part 7) 3 | 4 | Extension of Apple's GLKViewController that adds support for the 5 | GLK2DrawCall class. OpenGL revolves around Draw calls! 6 | 7 | This class implements the basic OpenGL rendering loop, layered on 8 | top of Apple's GLKViewController built-in loop: 9 | 10 | 0. GENERAL: integrates correctly with viewDidLoad etc, as per Apple docs 11 | 1. SETUP: create and set a valid EAGLContext, or crash/error 12 | 2. SETUP: generate a set of "initial Draw calls" (or none) 13 | 3. LOOP FOREVER: render a single "frame" to the screen 14 | 15 | The "frame" doesn't exist in OpenGL, strictly speaking, but it's a 16 | useful concept. To render a frame, we split it up like this: 17 | 18 | 3a. EACH FRAME: callback for subclasses to know a new frame is starting 19 | 3b. EACH FRAME: request a sorted list of Draw calls to render 20 | 3c. EACH FRAME LOOP: for each Draw call: 21 | 3c-i. update all GL state 22 | 3c-ii. update all shader-uniforms 23 | 3c-iii. render that Draw call 24 | 3c-iv. reset state as required 25 | 26 | OpenGL ES 2 has approximately 15 different pieces of "high-level" 27 | render-state; to render a single Draw call, all of them have to be 28 | turned on, or off, and configured, or reset, or re-allocated, or 29 | re-uploaded (e.g. texture maps). Hence the "for each Draw call" 30 | above is a lot of boilerplate code. 31 | 32 | IMPORTANT NOTE: 33 | 34 | This class is incomplete; it only handles the bits of GL state that have 35 | been covered by the tutorials already posted to http://t-machine.org - anything 36 | not yet written about will need to be added by hand if you use this class. 37 | */ 38 | #import 39 | 40 | #import 41 | 42 | #import "GLK2DrawCall.h" 43 | 44 | @interface GLK2DrawCallViewController : GLKViewController 45 | 46 | /** 47 | An EAGLContext is needed for 95% of OpenGL calls to work. 48 | 49 | It's supposed to be 100%, but some - e.g. glClear - miraculously work without it 50 | when running on Apple OS's. 51 | */ 52 | @property(nonatomic,retain) EAGLContext* localContext; 53 | 54 | @property(nonatomic, retain) NSMutableArray* drawCalls; 55 | 56 | /** 57 | Every app needs to use its own code here: the exact set of draw-calls 58 | is where the custom rendering takes place, or is configured 59 | */ 60 | -(NSMutableArray*) createAllDrawCalls; 61 | 62 | /** 63 | Called once at start of each frame; sole purpose is to allow you to do per-frame 64 | setup (note: per-drawcall setup of Uniforms is done in a different callback) 65 | */ 66 | -(void)willRenderFrame; 67 | 68 | /** Called prior to rendering a draw-call, enabling subclasses to e.g. change uniforms 69 | just prior to that draw-call being rendered 70 | 71 | NB: this is called AFTER the VAO and shader-program have been set - so you are safe 72 | to immediately, nakedly, set Uniforms etc 73 | */ 74 | -(void) willRenderDrawCallUsingVAOShaderProgramAndDefaultUniforms:(GLK2DrawCall*) drawCall; 75 | 76 | #pragma mark - Optional overrides for subclasses ONLY 77 | 78 | /** Subclasses can override this if they need to subvert the render-loop itself. 79 | 80 | This is rare but sometimes useful if e.g. you want to have all your app-logic triggered 81 | by the renderloop itself. 82 | 83 | If overriding, be sure to call [super update] when you want the main rendering logic to 84 | execute 85 | */ 86 | -(void) update; 87 | 88 | /** Subclasses can override this if they need to e.g. specialize the order in which drawcalls are 89 | drawn (e.g. pre-sorting, alpha-sorting, etc) 90 | */ 91 | -(void) renderSingleFrame; 92 | 93 | /** Subclasses can call this if overriding "renderSingleFrame", to use this class's detailed 94 | version (it's a long method) 95 | */ 96 | -(void) renderSingleDrawCall:(GLK2DrawCall*) drawCall; 97 | 98 | /** Apple's driver is very slow at switching shaderprogram, and won't check if it's already set */ 99 | @property(nonatomic) GLuint currentlyActiveShaderProgramName; 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-LibraryTests/GLKX-LibraryTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.t-machine.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-LibraryTests/GLKX_LibraryTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GLKX_LibraryTests.m 3 | // GLKX-LibraryTests 4 | // 5 | // Created by adam on 30/11/2013. 6 | // Copyright (c) 2013 n/a. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GLKX_LibraryTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation GLKX_LibraryTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | /*- (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | */ 34 | @end 35 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-LibraryTests/GLKX_Test_OOP_Improvements.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "GLK2TextureTracker.h" 4 | #import "GLK2TextureTracker_UnitTesting.h" 5 | 6 | @interface GLKX_Test_OOP_Improvements : XCTestCase 7 | @property(nonatomic,retain) EAGLContext* privateGLContext; 8 | @end 9 | 10 | @implementation GLKX_Test_OOP_Improvements 11 | 12 | - (void)setUp 13 | { 14 | [super setUp]; 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | 17 | self.privateGLContext = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2] autorelease]; 18 | [EAGLContext setCurrentContext:self.privateGLContext]; 19 | } 20 | 21 | - (void)tearDown 22 | { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | 26 | /** Critically important to ensure that each test is isolated from the behaviour of the others: */ 27 | [GLK2TextureTracker forceDeallocSharedInstance]; 28 | 29 | /** Critically important to ensure that each test is isolated from the behaviour of the others: */ 30 | // ... must come last! This kills the GL context (potentially) 31 | [EAGLContext setCurrentContext:nil]; 32 | self.privateGLContext = nil; 33 | } 34 | 35 | - (void)testTextureTrackerAddsTextures 36 | { 37 | GLK2TextureTracker* tracker = [GLK2TextureTracker sharedInstance]; 38 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 0, @"Should be no textures yet"); 39 | 40 | 41 | GLK2Texture* newClassTexture = [GLK2Texture textureNewEmpty]; 42 | XCTAssertNotEqual( 0, newClassTexture.glName, @"Texture created OK on GPU (proves we have a valid EAGLContext)"); 43 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 1, @"Should now be 1 tracked texture"); 44 | } 45 | 46 | - (void)testTextureTrackerDropsTextures 47 | { 48 | GLK2TextureTracker* tracker = [GLK2TextureTracker sharedInstance]; 49 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 0, @"Should be no textures yet"); 50 | 51 | GLK2Texture* temporaryClassTexture; 52 | @autoreleasepool 53 | { 54 | temporaryClassTexture = [GLK2Texture textureNewEmpty]; 55 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 1, @"Should now be 1 tracked texture"); 56 | } 57 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 0, @"The temporary texture should have been dropped, and the GL texture untracked"); 58 | } 59 | 60 | - (void)testTextureTrackerSharesTextureReferences 61 | { 62 | GLK2TextureTracker* tracker = [GLK2TextureTracker sharedInstance]; 63 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 0, @"Should be no textures yet"); 64 | 65 | GLK2Texture* textureOne; 66 | GLK2Texture* textureTwo; 67 | GLK2Texture* textureThatSwitches; 68 | @autoreleasepool 69 | { 70 | textureOne = [GLK2Texture textureNewEmpty]; 71 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 1, @"Should be 1 tracked texture"); 72 | textureTwo = [[GLK2Texture textureNewEmpty] retain]; 73 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 2, @"Should be 2 tracked textures"); 74 | textureThatSwitches = [[GLK2Texture textureAlreadyOnGPUWithName:textureOne.glName] retain]; 75 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 2, @"Should be 2 tracked texture"); 76 | } 77 | 78 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 2, @"Should be 2 tracked textures"); 79 | } 80 | 81 | - (void)testTextureTrackerReAssociatesTextures 82 | { 83 | GLK2TextureTracker* tracker = [GLK2TextureTracker sharedInstance]; 84 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 0, @"Should be no textures yet"); 85 | 86 | GLK2Texture* textureOne; 87 | GLK2Texture* textureTwo; 88 | GLK2Texture* textureThatSwitches; 89 | @autoreleasepool 90 | { 91 | textureOne = [GLK2Texture textureNewEmpty]; 92 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 1, @"Should be 1 tracked texture"); 93 | 94 | textureTwo = [GLK2Texture textureNewEmpty]; 95 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 2, @"Should be 2 tracked textures"); 96 | 97 | textureThatSwitches = [[GLK2Texture textureAlreadyOnGPUWithName:textureOne.glName] retain]; 98 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 2, @"Should be 2 tracked texture"); 99 | 100 | [textureThatSwitches reAssociateWithNewGPUTexture:textureTwo.glName]; 101 | } 102 | 103 | XCTAssertEqual( tracker.totalGLTexturesCurrentlyOnGPU, 1, @"Should be 1 tracked texture"); 104 | } 105 | 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /GLKX-Library/GLKX-LibraryTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GLKitExtended 2 | 3 | Apple's excellent GLKit.framework makes working with OpenGL much easier on iOS and OS X. However, there is a *lot* missing - this library aims to add the missing bits. 4 | 5 | (it also fixes some MAJOR bugs that Apple has left unfixed for the last few years, and/or refused to fix when we submitted bug reports) 6 | 7 | ## Usage 8 | 9 | This library is the side-effect of a series of blog posts aimed at beginners, who've never used OpenGL or GL ES before. Those posts are the primary reference / documentation: 10 | 11 | 1. Part1: http://t-machine.org/index.php/2013/08/29/glkit-to-the-max-opengl-es-2-0-for-ios-part-1-features/ 12 | 1. Part2: http://t-machine.org/index.php/2013/09/08/opengl-es-2-basic-drawing/ 13 | 1. Part3: http://t-machine.org/index.php/2013/10/05/ios-open-gl-es-2-shaders-and-geometry/ 14 | 1. Part4: http://t-machine.org/index.php/2013/10/18/ios-open-gl-es-2-multiple-objects-at-once/ 15 | 1. Part5: http://t-machine.org/index.php/2013/11/29/opengl-es2-textures-1-of-3-texturing-triangles-using-shaders/ 16 | 17 | ## Library 18 | 19 | This project has two sub-folders, one for the "pure" library, and the other for the "demo iPhone/iPad app" that lets you test the library with simple code. 20 | 21 | * GLKX-Demo -- stand-alone demo for iOS 22 | * GLKX-Library -- stand-alone Static Library project 23 | 24 | ### Re-compiling/building the Library 25 | 26 | Apple broke Static Libraries twice - once in Xcode 3, and again in Xcode 4.4. Apple admits this publicly, but so far refuses to fix it. So, we're using the standard workaround from this StackOverflow answer: 27 | 28 | http://stackoverflow.com/questions/3520977/build-fat-static-library-device-simulator-using-xcode-and-sdk-4 29 | 30 | If you've never used it before, a couple of things to note: 31 | 32 | 1. When you re-build the library, it AUTOMATICALLY builds both "simulator", "device" and "new devices" (64bit etc), all at once. 33 | 1. There is ONLY ONE lib*.a file - it contains everything (Apple used to do this for you until Xcode 3.x) 34 | 1. The header files are AUTOMATICALLY output into the subfolder "usr/local/include" (Apple used to do this until Xcode 4.4) 35 | 1. To be safe, the script outputs all builds to "Debug-Universal" or "Release-Universal" instead of "Debug-Device"/"Debug-Simulator"/etc. Make sure you grab the right copy. 36 | 1. After you've built the library, right click the Product, find it in Finder, go up one folder, find the "*-Universal" folder (which has the final output), and drag/drop that into your App project, overwriting what was there before. 37 | 38 | 39 | ## Questions / Comments 40 | 41 | Best on twitter : @t_machine_org 42 | 43 | Alternatively : comment directly on the above blog posts (you'll get an answer quickly). 44 | 45 | ## License 46 | 47 | Everything here is MIT. All code and assets are Copyright Adam Martin (so that I can legally declare "everything here is MIT". Copyright law is strange) 48 | 49 | ## Contributions 50 | 51 | If you submit a pull-request to this repository, you surrender your Copyrights for that code to Adam Martin, and warrant that you own what you've submitted. (this is so to prevent legal problems for everyone who uses the library) --------------------------------------------------------------------------------