├── .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)
--------------------------------------------------------------------------------