Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1452 chris 1
#region License
2
//
3
// The Open Toolkit Library License
4
//
5
// Copyright (c) 2006 - 2009 the Open Toolkit library.
6
//
7
// Permission is hereby granted, free of charge, to any person obtaining a copy
8
// of this software and associated documentation files (the "Software"), to deal
9
// in the Software without restriction, including without limitation the rights to 
10
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11
// the Software, and to permit persons to whom the Software is furnished to do
12
// so, subject to the following conditions:
13
//
14
// The above copyright notice and this permission notice shall be included in all
15
// copies or substantial portions of the Software.
16
//
17
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
// OTHER DEALINGS IN THE SOFTWARE.
25
//
26
#endregion
27
 
28
using System;
29
using System.Diagnostics;
30
using System.Drawing;
31
 
32
using OpenTK;
33
using OpenTK.Input;
34
using OpenTK.Graphics;
35
using OpenTK.Graphics.OpenGL;
36
 
37
/*
38
 * The idea is to make a simple scene: A box with a checker texture with a sphere inside it. The
39
 * camera will be inside the box looking at the sphere.
40
 *
41
 * Rendering will be done in two passes.  The first pass will render the box from within the
42
 * sphere, looking in along all three axes in the positive and negative directions.  These six
43
 * different camara orientations will be rendered to individual faces of a cubemap, in one
44
 * single pass using the gl_Layer token in the geometry shader. This cubemap will be used the
45
 * the second pass.  
46
 *
47
 * The second pass will render both the box and the sphere. The box will have the checker
48
 * texture, and the sphere will use the cubemap from the first pass.
49
 *
50
 * Keys:
51
 * F1 - switch to cubemap cross texture view
52
 * F2 - switch to the normal scene render
53
 *
54
 * F5 - Polygon mode points
55
 * F6 - Polygon mode lines
56
 * F7 - Polygon mode fill
57
 *
58
 * References:
59
 * http://www.opengl.org/wiki/GL_EXT_framebuffer_object#Quick_example.2C_render_to_texture_.28Cubemap.29
60
 * http://www.opengl.org/registry/specs/EXT/framebuffer_object.txt
61
 * http://www.opengl.org/registry/specs/EXT/geometry_shader4.txt
62
 */
63
 
64
namespace Examples.Tutorial
65
{
66
    [Example("Advanced Geometry Shader", ExampleCategory.OpenGL, "2.x", Documentation = "Advanced usage of EXT_geometry_shader4")]
67
    public class SimpleGeometryShader2 : GameWindow
68
    {
69
        public SimpleGeometryShader2()
70
            : base(800, 600)
71
        {
72
            Keyboard.KeyDown += Keyboard_KeyDown;
73
        }
74
 
75
        enum ViewMode
76
        {
77
            CubemapCross,
78
            Scene,
79
        }
80
 
81
        struct VertexPositionNormalTexture
82
        {
83
            public Vector3 Position, Normal;
84
            public Vector2 Texture;
85
 
86
            public VertexPositionNormalTexture(Vector3 position, Vector3 normal, Vector2 texture)
87
            {
88
                Position = position;
89
                Normal = normal;
90
                Texture = texture;
91
            }
92
        }
93
 
94
        #region Fields
95
 
96
        int shaderProgramBox;
97
        int shaderProgramSphere;
98
        int shaderProgramCubemap;
99
 
100
        int textureCubeColor;
101
        int textureCubeDepth;
102
        int textureCubeFBO;
103
 
104
        int vboCube;
105
        int vboCubeStride;
106
        int vboSphere;
107
        int vboSphereStride = BlittableValueType<VertexPositionNormalTexture>.Stride;
108
        int eboSphere;
109
        int sphereElementCount;
110
 
111
        ViewMode mode = ViewMode.Scene;
112
        Vector3 eyePos = new Vector3(0, -8, 0);
113
        Vector3 eyeLookat = new Vector3(0, -9, -0);
114
        Vector3 spherePos = new Vector3(0, -9, 0);
115
        DateTime startTime = DateTime.Now;
116
 
117
        #endregion
118
 
119
        #region keyboard handler
120
 
121
        void Keyboard_KeyDown(object sender, KeyboardKeyEventArgs e)
122
        {
123
            switch (e.Key)
124
            {
125
                case Key.F1:
126
                    switchToMode(ViewMode.CubemapCross);
127
                    break;
128
                case Key.F2:
129
                    switchToMode(ViewMode.Scene);
130
                    break;
131
                case Key.F5:
132
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Point);
133
                    break;
134
                case Key.F6:
135
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
136
                    break;
137
                case Key.F7:
138
                    GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
139
                    break;
140
                case Key.Escape:
141
                    this.Exit();
142
                    break;
143
                default:
144
                    break;
145
            }
146
        }
147
 
148
        #endregion
149
 
150
        #region init methods
151
 
152
        void initShaderProgramBox()
153
        {
154
            // create a program object.
155
            shaderProgramBox = GL.CreateProgram();
156
            // create shader objects.
157
            int vert = GL.CreateShader(ShaderType.VertexShader);
158
            int frag = GL.CreateShader(ShaderType.FragmentShader);
159
 
160
            // GLSL for fragment shader.
161
            // diagonal checker
162
            String fragSource = @"
163
                varying vec3 normal;
164
                void main( void )
165
                {  
166
                    float s = gl_TexCoord[0].s * 6.28 * 8.0;
167
                    float t = gl_TexCoord[0].t * 6.28 * 8.0;
168
                    gl_FragColor = gl_TexCoord[1] * vec4(sign(cos(s)+cos(t)));
169
                    //gl_FragColor = vec4(normal*vec3(0.5)+vec3(0.5), 1);
170
                }
171
            ";
172
 
173
            // GLSL for vertex shader.
174
            String vertSource = @"
175
                varying vec3 normal;
176
                void main( void )
177
                {
178
                    gl_Position = ftransform();
179
                    normal = gl_Normal;
180
                    gl_TexCoord[0] = gl_MultiTexCoord0;
181
                    gl_TexCoord[1] = normalize(gl_Vertex)*0.5+0.5;
182
                }  
183
            ";
184
 
185
            // compile shaders.
186
            compileShader(frag, fragSource);
187
            compileShader(vert, vertSource);
188
 
189
            // attach shaders and link the program.
190
            GL.AttachShader(shaderProgramBox, frag);
191
            GL.AttachShader(shaderProgramBox, vert);
192
            GL.LinkProgram(shaderProgramBox);
193
 
194
            // output link info log.
195
            string info;
196
            GL.GetProgramInfoLog(shaderProgramBox, out info);
197
            Debug.WriteLine(info);
198
 
199
            // Clean up resources. Note the program object is not deleted.
200
            if (frag != 0)
201
                GL.DeleteShader(frag);
202
            if (vert != 0)
203
                GL.DeleteShader(vert);
204
        }
205
 
206
        void initShaderProgramSphere()
207
        {
208
            // create a program object.
209
            shaderProgramSphere = GL.CreateProgram();
210
            // create shader objects.
211
            int vert = GL.CreateShader(ShaderType.VertexShader);
212
            int frag = GL.CreateShader(ShaderType.FragmentShader);
213
 
214
            // GLSL for fragment shader.
215
            String fragSource = @"
216
                varying vec3 normal;
217
                varying vec3 eyevec;
218
                uniform samplerCube tex;
219
 
220
                void main( void )
221
                {
222
                    gl_FragColor = textureCube(tex, reflect(normalize(-eyevec), normalize(normal)));
223
                }  
224
            ";
225
 
226
            // GLSL for vertex shader.
227
            String vertSource = @"
228
                varying vec3 normal;
229
                varying vec3 eyevec;
230
 
231
                void main( void )
232
                {
233
                    gl_Position = ftransform();
234
                    eyevec = -gl_Vertex.xyz;
235
                    normal = gl_Normal;
236
                }  
237
            ";
238
 
239
            // compile shaders.
240
            compileShader(frag, fragSource);
241
            compileShader(vert, vertSource);
242
 
243
            // attach shaders and link the program.
244
            GL.AttachShader(shaderProgramSphere, frag);
245
            GL.AttachShader(shaderProgramSphere, vert);
246
            GL.LinkProgram(shaderProgramSphere);
247
 
248
            // output link info log.
249
            string info;
250
            GL.GetProgramInfoLog(shaderProgramSphere, out info);
251
            Debug.WriteLine(info);
252
 
253
            // Clean up resources. Note the program object is not deleted.
254
            if (frag != 0)
255
                GL.DeleteShader(frag);
256
            if (vert != 0)
257
                GL.DeleteShader(vert);
258
        }
259
 
260
        void initShaderProgramCubemap()
261
        {
262
            // create a program object.
263
            shaderProgramCubemap = GL.CreateProgram();
264
            // create shader objects.
265
            int vert = GL.CreateShader(ShaderType.VertexShader);
266
            int frag = GL.CreateShader(ShaderType.FragmentShader);
267
            int geom = GL.CreateShader(ShaderType.GeometryShaderExt);
268
 
269
            // GLSL for fragment shader.
270
            // Checkerboard :)
271
            String fragSource = @"
272
                #version 120
273
                #extension GL_EXT_gpu_shader4 : enable
274
 
275
                void main( void )
276
                {
277
                    float s = gl_TexCoord[0].s * 6.28 * 8.0;
278
                    float t = gl_TexCoord[0].t * 6.28 * 8.0;
279
                    gl_FragColor = gl_TexCoord[2] * vec4(sign(cos(s)+cos(t)))/* * gl_TexCoord[1]*/;
280
//                  gl_FragColor = gl_TexCoord[1];
281
                }  
282
            ";
283
 
284
            // GLSL for vertex shader.
285
            String vertSource = @"
286
                #version 120
287
                #extension GL_EXT_gpu_shader4 : enable
288
 
289
                //varying vec4 p[2];
290
                //varying vec4 nx;
291
 
292
                void main( void )
293
                {
294
                    gl_Position = gl_Vertex;
295
                    gl_TexCoord[2] = normalize(gl_Vertex)*0.5+0.5;
296
                    gl_TexCoord[0] = gl_MultiTexCoord0;
297
                }
298
            ";
299
 
300
            // GLSL for geometry shader.
301
            String geomSource = @"
302
                #version 120
303
                #extension GL_EXT_geometry_shader4 : enable
304
                #extension GL_EXT_gpu_shader4 : enable
305
                uniform mat4 matrixPX;
306
                uniform mat4 matrixNX;
307
                uniform mat4 matrixPY;
308
                uniform mat4 matrixNY;
309
                uniform mat4 matrixPZ;
310
                uniform mat4 matrixNZ;
311
 
312
                void main(void) {
313
                    int i, layer;
314
                    gl_Layer = 0;
315
                    gl_TexCoord[1] = vec4(1, 0, 0, 1);
316
                    for (i = 0; i < gl_VerticesIn; i++) {
317
                            gl_Position = matrixPX * gl_PositionIn[i];
318
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
319
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
320
                            EmitVertex();
321
                    }
322
                    EndPrimitive();
323
                    gl_Layer = 1;
324
                    gl_TexCoord[1] = vec4(0, 0, 1, 1);
325
                    for (i = 0; i < gl_VerticesIn; i++) {
326
                            gl_Position = matrixNX * gl_PositionIn[i];
327
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
328
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
329
                            EmitVertex();
330
                    }
331
                    EndPrimitive();
332
                    gl_Layer = 2;
333
                    gl_TexCoord[1] = vec4(0, 1, 0, 1);
334
                    for (i = 0; i < gl_VerticesIn; i++) {
335
                            gl_Position = matrixPY* gl_PositionIn[i];
336
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
337
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
338
                            EmitVertex();
339
                    }
340
                    EndPrimitive();
341
                    gl_Layer = 3;
342
                    gl_TexCoord[1] = vec4(1, 1, 0, 1);
343
                    for (i = 0; i < gl_VerticesIn; i++) {
344
                            gl_Position = matrixNY * gl_PositionIn[i];
345
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
346
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
347
                            EmitVertex();
348
                    }
349
                    EndPrimitive();
350
                    gl_Layer = 4;
351
                    gl_TexCoord[1] = vec4(1, 1, 1, 1);
352
                    for (i = 0; i < gl_VerticesIn; i++) {
353
                            gl_Position = matrixPZ * gl_PositionIn[i];
354
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
355
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
356
                            EmitVertex();
357
                    }
358
                    EndPrimitive();
359
                    gl_Layer = 5;
360
                    gl_TexCoord[1] = vec4(1, 0, 1, 1);
361
                    for (i = 0; i < gl_VerticesIn; i++) {
362
                            gl_Position = matrixNZ * gl_PositionIn[i];
363
                            gl_TexCoord[0] = gl_TexCoordIn[i][0];
364
                            gl_TexCoord[2] = gl_TexCoordIn[i][2];
365
                            EmitVertex();
366
                    }
367
                    EndPrimitive();
368
                }
369
            ";
370
 
371
            // compile shaders.
372
            compileShader(frag, fragSource);
373
            compileShader(vert, vertSource);
374
            compileShader(geom, geomSource);
375
 
376
            int tmp;
377
            GL.GetInteger((GetPName)ExtGeometryShader4.MaxGeometryOutputVerticesExt, out tmp);
378
            GL.Ext.ProgramParameter(shaderProgramCubemap, ExtGeometryShader4.GeometryVerticesOutExt, 18);
379
 
380
            GL.Ext.ProgramParameter(shaderProgramCubemap, ExtGeometryShader4.GeometryInputTypeExt, (int)All.Triangles);
381
            GL.Ext.ProgramParameter(shaderProgramCubemap, ExtGeometryShader4.GeometryOutputTypeExt, (int)All.TriangleStrip);
382
 
383
            // attach shaders and link the program.
384
            GL.AttachShader(shaderProgramCubemap, frag);
385
            GL.AttachShader(shaderProgramCubemap, vert);
386
            GL.AttachShader(shaderProgramCubemap, geom);
387
            GL.LinkProgram(shaderProgramCubemap);
388
 
389
            // output link info log.
390
            string info;
391
            GL.GetProgramInfoLog(shaderProgramCubemap, out info);
392
            Debug.WriteLine(info);
393
 
394
            // Clean up resources. Note the program object is not deleted.
395
            if (frag != 0)
396
                GL.DeleteShader(frag);
397
            if (vert != 0)
398
                GL.DeleteShader(vert);
399
            if (geom != 0)
400
                GL.DeleteShader(geom);
401
        }
402
 
403
        /// <summary>
404
        /// Helper method to avoid code duplication.
405
        /// Compiles a shader and prints results using Debug.WriteLine.
406
        /// </summary>
407
        /// <param name="shader">A shader object, gotten from GL.CreateShader.</param>
408
        /// <param name="source">The GLSL source to compile.</param>
409
        void compileShader(int shader, string source)
410
        {
411
            GL.ShaderSource(shader, source);
412
            GL.CompileShader(shader);
413
 
414
            string info;
415
            GL.GetShaderInfoLog(shader, out info);
416
            Debug.WriteLine(info);
417
 
418
            int compileResult;
419
            GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
420
            if (compileResult != 1)
421
            {
422
                Debug.WriteLine("Compile Error!");
423
                Debug.WriteLine(source);
424
            }
425
        }
426
 
427
        void initTextureCube()
428
        {
429
            textureCubeColor = GL.GenTexture();
430
            GL.BindTexture(TextureTarget.TextureCubeMap, textureCubeColor);
431
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
432
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
433
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
434
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
435
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
436
            foreach (TextureTarget target in new TextureTarget[] {
437
                TextureTarget.TextureCubeMapPositiveX,
438
                TextureTarget.TextureCubeMapNegativeX,
439
                TextureTarget.TextureCubeMapPositiveY,
440
                TextureTarget.TextureCubeMapNegativeY,
441
                TextureTarget.TextureCubeMapPositiveZ,
442
                TextureTarget.TextureCubeMapNegativeZ,
443
            })
444
            {
445
                GL.TexImage2D(target, 0, PixelInternalFormat.Rgba8, 512, 512, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
446
            }
447
 
448
            /*
449
            GL.BindTexture(TextureTarget.TextureCubeMap, textureCubeDepth);
450
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
451
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
452
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
453
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
454
            GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int)TextureWrapMode.ClampToEdge);
455
            foreach (TextureTarget target in new TextureTarget[] {
456
                TextureTarget.TextureCubeMapPositiveX,
457
                TextureTarget.TextureCubeMapNegativeX,
458
                TextureTarget.TextureCubeMapPositiveY,
459
                TextureTarget.TextureCubeMapNegativeY,
460
                TextureTarget.TextureCubeMapPositiveZ,
461
                TextureTarget.TextureCubeMapNegativeZ,
462
            }) {
463
                GL.TexImage2D(target, 0, (PixelInternalFormat)All.DepthComponent32, 512, 512, 0, PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
464
            }
465
            */
466
            GL.Ext.GenFramebuffers(1, out textureCubeFBO);
467
            GL.Ext.GenRenderbuffers(1, out textureCubeDepth);
468
 
469
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, textureCubeFBO);
470
            GL.Ext.FramebufferTexture(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, textureCubeColor, 0);
471
 
472
            //GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, textureCubeDepth);
473
            //GL.Ext.RenderbufferStorage(RenderbufferTarget.RenderbufferExt, (RenderbufferStorage)All.DepthComponent24, 512, 512);
474
            //GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, textureCubeDepth);
475
 
476
            #region Test for Error
477
            FramebufferErrorCode e = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
478
            switch (e)
479
            {
480
                case FramebufferErrorCode.FramebufferCompleteExt:
481
                    {
482
                        Console.WriteLine("FBO: The framebuffer is complete and valid for rendering.");
483
                        break;
484
                    }
485
                case FramebufferErrorCode.FramebufferIncompleteAttachmentExt:
486
                    {
487
                        Console.WriteLine("FBO: One or more attachment points are not framebuffer attachment complete. This could mean there’s no texture attached or the format isn’t renderable. For color textures this means the base format must be RGB or RGBA and for depth textures it must be a DEPTH_COMPONENT format. Other causes of this error are that the width or height is zero or the z-offset is out of range in case of render to volume.");
488
                        break;
489
                    }
490
                case FramebufferErrorCode.FramebufferIncompleteMissingAttachmentExt:
491
                    {
492
                        Console.WriteLine("FBO: There are no attachments.");
493
                        break;
494
                    }
495
                /*               case  FramebufferErrorCode.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
496
                                     {
497
                                         Console.WriteLine("FBO: An object has been attached to more than one attachment point.");
498
                                         break;
499
                                     }*/
500
                case FramebufferErrorCode.FramebufferIncompleteDimensionsExt:
501
                    {
502
                        Console.WriteLine("FBO: Attachments are of different size. All attachments must have the same width and height.");
503
                        break;
504
                    }
505
                case FramebufferErrorCode.FramebufferIncompleteFormatsExt:
506
                    {
507
                        Console.WriteLine("FBO: The color attachments have different format. All color attachments must have the same format.");
508
                        break;
509
                    }
510
                case FramebufferErrorCode.FramebufferIncompleteDrawBufferExt:
511
                    {
512
                        Console.WriteLine("FBO: An attachment point referenced by GL.DrawBuffers() doesn’t have an attachment.");
513
                        break;
514
                    }
515
                case FramebufferErrorCode.FramebufferIncompleteReadBufferExt:
516
                    {
517
                        Console.WriteLine("FBO: The attachment point referenced by GL.ReadBuffers() doesn’t have an attachment.");
518
                        break;
519
                    }
520
                case FramebufferErrorCode.FramebufferUnsupportedExt:
521
                    {
522
                        Console.WriteLine("FBO: This particular FBO configuration is not supported by the implementation.");
523
                        break;
524
                    }
525
                case (FramebufferErrorCode)All.FramebufferIncompleteLayerTargetsExt:
526
                    {
527
                        Console.WriteLine("FBO: Framebuffer Incomplete Layer Targets.");
528
                        break;
529
                    }
530
                case (FramebufferErrorCode)All.FramebufferIncompleteLayerCountExt:
531
                    {
532
                        Console.WriteLine("FBO: Framebuffer Incomplete Layer Count.");
533
                        break;
534
                    }
535
                default:
536
                    {
537
                        Console.WriteLine("FBO: Status unknown. (yes, this is really bad.)");
538
                        break;
539
                    }
540
            }
541
 
542
            // using FBO might have changed states, e.g. the FBO might not support stereoscopic views or double buffering
543
            int[] queryinfo = new int[6];
544
            GL.GetInteger(GetPName.MaxColorAttachmentsExt, out queryinfo[0]);
545
            GL.GetInteger(GetPName.AuxBuffers, out queryinfo[1]);
546
            GL.GetInteger(GetPName.MaxDrawBuffers, out queryinfo[2]);
547
            GL.GetInteger(GetPName.Stereo, out queryinfo[3]);
548
            GL.GetInteger(GetPName.Samples, out queryinfo[4]);
549
            GL.GetInteger(GetPName.Doublebuffer, out queryinfo[5]);
550
            Console.WriteLine("max. ColorBuffers: " + queryinfo[0] + " max. AuxBuffers: " + queryinfo[1] + " max. DrawBuffers: " + queryinfo[2] +
551
                               "\nStereo: " + queryinfo[3] + " Samples: " + queryinfo[4] + " DoubleBuffer: " + queryinfo[5]);
552
 
553
            Console.WriteLine("Last GL Error: " + GL.GetError());
554
 
555
            #endregion Test for Error
556
 
557
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0); // disable rendering into the FBO
558
        }
559
 
560
        void initVBOCube()
561
        {
562
            GL.GenBuffers(1, out vboCube);
563
            // vertex 3 floats
564
            // normal 3 floats
565
            // texcoord 2 floats
566
            // 3+3+2=8 floats = 8*4 = 32 bytes
567
            vboCubeStride = 32;
568
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboCube);
569
            GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(cubeData.Length * vboCubeStride), cubeData, BufferUsageHint.StaticDraw);
570
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
571
        }
572
 
573
        void initVBOSpere()
574
        {
575
            VertexPositionNormalTexture[] sphereVertices = CalculateSphereVertices(1, 1, 16, 16);
576
            ushort[] sphereElements = CalculateSphereElements(1, 1, 16, 16);
577
            sphereElementCount = sphereElements.Length;
578
 
579
            GL.GenBuffers(1, out vboSphere);
580
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboSphere);
581
            GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(BlittableValueType.StrideOf(sphereVertices) * sphereVertices.Length), sphereVertices, BufferUsageHint.StaticDraw);
582
 
583
            GL.GenBuffers(1, out eboSphere);
584
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboSphere);
585
            GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(BlittableValueType.StrideOf(sphereElements) * sphereElements.Length), sphereElements, BufferUsageHint.StaticDraw);
586
 
587
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
588
        }
589
 
590
        #endregion
591
 
592
        #region perspective
593
 
594
        void setOrtho()
595
        {
596
            OpenTK.Matrix4 proj;
597
            proj = OpenTK.Matrix4.CreateOrthographicOffCenter(-1, 1, -1, 1, 1, -1);
598
            GL.LoadMatrix(ref proj);
599
        }
600
 
601
        void setPerspective()
602
        {
603
            OpenTK.Matrix4 proj;
604
            proj = OpenTK.Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Width / (float)Height, 0.1f, 200f);
605
            GL.LoadMatrix(ref proj);
606
        }
607
 
608
        void switchToMode(ViewMode m)
609
        {
610
            mode = m;
611
            // force update of projection matrix by calling OnResize
612
            this.OnResize(EventArgs.Empty);
613
        }
614
 
615
        #endregion
616
 
617
        #region render methods
618
 
619
        void drawCubemapCross()
620
        {
621
            GL.ClearColor(0.1f, 0.1f, 0.1f, 0.1f);
622
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
623
 
624
            GL.PushAttrib(AttribMask.PolygonBit);
625
            GL.Enable(EnableCap.TextureCubeMap);
626
            GL.BindTexture(TextureTarget.TextureCubeMap, textureCubeColor);
627
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
628
 
629
            /*
630
             *
631
             *     +---+
632
             *     | 4 |
633
             * +---+---+---+---+
634
             * | 0 | 1 | 2 | 3 |
635
             * +---+---+---+---+
636
             *     | 5 |
637
             *     +---+
638
             * 0 -x
639
             * 1 +z
640
             * 2 +x
641
             * 3 -z
642
             * 4 +y
643
             * 5 -y
644
             */
645
 
646
 
647
            GL.PushMatrix();
648
            GL.LoadIdentity();
649
            GL.Begin(BeginMode.Quads);
650
 
651
            // 0 -x
652
            GL.TexCoord3(-1.0f, +1.0f, -1.0f);
653
            GL.Vertex2(-1.0f, +0.3333f);
654
            GL.TexCoord3(-1.0f, +1.0f, +1.0f);
655
            GL.Vertex2(-0.5f, +0.3333f);
656
            GL.TexCoord3(-1.0f, -1.0f, +1.0f);
657
            GL.Vertex2(-0.5f, -0.3333f);
658
            GL.TexCoord3(-1.0f, -1.0f, -1.0f);
659
            GL.Vertex2(-1.0f, -0.3333f);
660
 
661
            // 1 +z
662
            GL.TexCoord3(-1.0f, +1.0f, +1.0f);
663
            GL.Vertex2(-0.5f, +0.3333f);
664
            GL.TexCoord3(+1.0f, +1.0f, +1.0f);
665
            GL.Vertex2(+0.0f, +0.3333f);
666
            GL.TexCoord3(+1.0f, -1.0f, +1.0f);
667
            GL.Vertex2(+0.0f, -0.3333f);
668
            GL.TexCoord3(-1.0f, -1.0f, +1.0f);
669
            GL.Vertex2(-0.5f, -0.3333f);
670
 
671
            // 2 +x
672
            GL.TexCoord3(+1.0f, +1.0f, +1.0f);
673
            GL.Vertex2(+0.0f, +0.3333f);
674
            GL.TexCoord3(+1.0f, +1.0f, -1.0f);
675
            GL.Vertex2(+0.5f, +0.3333f);
676
            GL.TexCoord3(+1.0f, -1.0f, -1.0f);
677
            GL.Vertex2(+0.5f, -0.3333f);
678
            GL.TexCoord3(+1.0f, -1.0f, +1.0f);
679
            GL.Vertex2(+0.0f, -0.3333f);
680
 
681
            // 3 -z
682
            GL.TexCoord3(+1.0f, +1.0f, -1.0f);
683
            GL.Vertex2(+0.5f, +0.3333f);
684
            GL.TexCoord3(-1.0f, +1.0f, -1.0f);
685
            GL.Vertex2(+1.0f, +0.3333f);
686
            GL.TexCoord3(-1.0f, -1.0f, -1.0f);
687
            GL.Vertex2(+1.0f, -0.3333f);
688
            GL.TexCoord3(+1.0f, -1.0f, -1.0f);
689
            GL.Vertex2(+0.5f, -0.3333f);
690
 
691
            // 4 +y
692
            GL.TexCoord3(-1.0f, +1.0f, -1.0f);
693
            GL.Vertex2(-0.5f, +1.0f);
694
            GL.TexCoord3(+1.0f, +1.0, -1.0f);
695
            GL.Vertex2(+0.0f, +1.0);
696
            GL.TexCoord3(+1.0f, +1.0f, +1.0f);
697
            GL.Vertex2(+0.0f, +0.3333f);
698
            GL.TexCoord3(-1.0f, +1.0f, +1.0f);
699
            GL.Vertex2(-0.5f, +0.3333f);
700
 
701
            // 5 -y
702
            GL.TexCoord3(-1.0f, -1.0f, +1.0f);
703
            GL.Vertex2(-0.5f, -0.3333f);
704
            GL.TexCoord3(+1.0f, -1.0, +1.0f);
705
            GL.Vertex2(+0.0f, -0.3333f);
706
            GL.TexCoord3(+1.0f, -1.0f, -1.0f);
707
            GL.Vertex2(+0.0f, -1.0f);
708
            GL.TexCoord3(-1.0f, -1.0f, -1.0f);
709
            GL.Vertex2(-0.5f, -1.0f);
710
 
711
            GL.End();
712
            GL.PopMatrix();
713
 
714
            GL.Disable(EnableCap.TextureCubeMap);
715
            GL.PopAttrib();
716
        }
717
 
718
        void renderCubeVBO()
719
        {
720
            GL.EnableClientState(EnableCap.VertexArray);
721
            GL.EnableClientState(EnableCap.NormalArray);
722
            GL.EnableClientState(EnableCap.TextureCoordArray);
723
            //GL.ClientActiveTexture(TextureUnit.Texture0 + 0);
724
 
725
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboCube);
726
            GL.VertexPointer(3, VertexPointerType.Float, vboCubeStride, new IntPtr(0));
727
            GL.NormalPointer(NormalPointerType.Float, vboCubeStride, new IntPtr(Vector3.SizeInBytes));
728
            GL.TexCoordPointer(2, TexCoordPointerType.Float, vboCubeStride, new IntPtr(Vector3.SizeInBytes + Vector3.SizeInBytes));
729
 
730
            //GL.Arb.DrawArraysInstanced(BeginMode.Triangles, 0, cubeData.Length/8, 1);
731
            GL.DrawArrays(BeginMode.Triangles, 0, cubeData.Length / (vboCubeStride / sizeof(float)));
732
 
733
            GL.DisableClientState(EnableCap.VertexArray);
734
            GL.DisableClientState(EnableCap.NormalArray);
735
            GL.DisableClientState(EnableCap.TextureCoordArray);
736
        }
737
 
738
        void renderSphereVBO()
739
        {
740
            GL.EnableClientState(EnableCap.VertexArray);
741
            GL.EnableClientState(EnableCap.NormalArray);
742
            GL.EnableClientState(EnableCap.TextureCoordArray);
743
            //GL.ClientActiveTexture(TextureUnit.Texture0 + 0);
744
 
745
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboSphere);
746
            GL.VertexPointer(3, VertexPointerType.Float, vboSphereStride, new IntPtr(0));
747
            GL.NormalPointer(NormalPointerType.Float, vboSphereStride, new IntPtr(Vector3.SizeInBytes));
748
            GL.TexCoordPointer(2, TexCoordPointerType.Float, vboSphereStride, new IntPtr(Vector3.SizeInBytes + Vector3.SizeInBytes));
749
 
750
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboSphere);
751
            GL.DrawElements(BeginMode.Triangles, 16 * 16 * 6, DrawElementsType.UnsignedShort, IntPtr.Zero);
752
 
753
            //GL.Arb.DrawArraysInstanced(BeginMode.Triangles, 0, cubeData.Length/8, 1);
754
            //GL.DrawArrays(BeginMode.Triangles, 0, sphereData.Length / (vboSphereStride / sizeof(float)));
755
 
756
            GL.DisableClientState(EnableCap.VertexArray);
757
            GL.DisableClientState(EnableCap.NormalArray);
758
            GL.DisableClientState(EnableCap.TextureCoordArray);
759
        }
760
 
761
        void renderCubemap()
762
        {
763
            GL.Disable(EnableCap.DepthTest);
764
 
765
            // draw onto cubemap FBO using geometry shader
766
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, textureCubeFBO);
767
            GL.UseProgram(shaderProgramCubemap);
768
            GL.PushAttrib(AttribMask.ViewportBit);
769
            {
770
                GL.Viewport(0, 0, 512, 512);
771
 
772
                // clear all cubemap faces to blue
773
                GL.ClearColor(0f, 0f, 1f, 0f);
774
                for (int i = 0; i < 6; i++)
775
                {
776
                    GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0, TextureTarget.TextureCubeMapPositiveX + i, textureCubeColor, 0);
777
                    //todo select depth renderbuffer face and trun depth_test on again
778
                    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
779
                }
780
                GL.Ext.FramebufferTexture(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0, textureCubeColor, 0);
781
                // Create 6 ModelViewProjection matrices, one to look in each direction
782
                // proj with 90 degrees (1/2 pi) fov
783
                // translate negative to place cam insize sphere
784
                Matrix4 model = Matrix4.Scale(-1) * Matrix4.CreateTranslation(spherePos);
785
                Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.PiOver2, 1, 0.1f, 100f);
786
 
787
                Matrix4[] m = new Matrix4[6];
788
 
789
                m[0] = model * Matrix4.LookAt(Vector3.Zero, Vector3.UnitX, -Vector3.UnitY) * proj;
790
                m[1] = model * Matrix4.LookAt(Vector3.Zero, -Vector3.UnitX, -Vector3.UnitY) * proj;
791
                m[2] = model * Matrix4.LookAt(Vector3.Zero, Vector3.UnitY, Vector3.UnitZ) * proj;
792
                m[3] = model * Matrix4.LookAt(Vector3.Zero, -Vector3.UnitY, -Vector3.UnitZ) * proj;
793
                m[4] = model * Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, -Vector3.UnitY) * proj;
794
                m[5] = model * Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, -Vector3.UnitY) * proj;
795
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixPX"), false, ref m[0]);
796
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixNX"), false, ref m[1]);
797
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixPY"), false, ref m[2]);
798
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixNY"), false, ref m[3]);
799
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixPZ"), false, ref m[4]);
800
                GL.UniformMatrix4(GL.GetUniformLocation(shaderProgramCubemap, "matrixNZ"), false, ref m[5]);
801
 
802
 
803
                renderCubeVBO();
804
            }
805
            GL.PopAttrib();
806
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
807
            GL.UseProgram(0);
808
            GL.Enable(EnableCap.DepthTest);
809
        }
810
 
811
        void renderScene()
812
        {
813
            GL.MatrixMode(MatrixMode.Projection);
814
            GL.PushMatrix();
815
            setPerspective();
816
            GL.MatrixMode(MatrixMode.Modelview);
817
            GL.PushMatrix();
818
            Matrix4 lookat = Matrix4.LookAt(eyePos, eyeLookat, Vector3.UnitY);
819
            GL.LoadMatrix(ref lookat);
820
 
821
 
822
            GL.UseProgram(shaderProgramBox);
823
            renderCubeVBO();
824
            GL.UseProgram(shaderProgramSphere);
825
            GL.BindTexture(TextureTarget.TextureCubeMap, textureCubeColor);
826
            GL.Uniform1(GL.GetUniformLocation(shaderProgramSphere, "tex"), 0);
827
            GL.Translate(spherePos);
828
            GL.Enable(EnableCap.DepthTest);
829
            renderSphereVBO();
830
            GL.UseProgram(0);
831
 
832
            GL.MatrixMode(MatrixMode.Projection);
833
            GL.PopMatrix();
834
            GL.MatrixMode(MatrixMode.Modelview);
835
            GL.PopMatrix();
836
        }
837
 
838
        #endregion
839
 
840
        #region overrides
841
 
842
        protected override void OnLoad(EventArgs e)
843
        {
844
            if (!GL.GetString(StringName.Extensions).Contains("EXT_geometry_shader4"))
845
            {
846
                System.Windows.Forms.MessageBox.Show(
847
                     "Your video card does not support EXT_geometry_shader4. Please update your drivers.",
848
                     "EXT_geometry_shader4 not supported",
849
                     System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
850
                Exit();
851
            }
852
 
853
            //int tmp;
854
            //GL.GetInteger(GetPName.MaxVertexUniformComponents, out tmp);
855
            //0x0400
856
            // 6 * 4x4 mat (0x10) = 0x60
857
 
858
            // init shaders
859
            initShaderProgramBox();
860
            initShaderProgramSphere();
861
            initShaderProgramCubemap();
862
            // init textures / fbos
863
            initTextureCube();
864
            // init vbos
865
            initVBOCube();
866
            initVBOSpere();
867
 
868
            //switchToMode(ViewMode.Scene);
869
 
870
        }
871
 
872
        protected override void OnUnload(EventArgs e)
873
        {
874
            if (shaderProgramBox != 0)
875
                GL.DeleteProgram(shaderProgramBox);
876
            if (shaderProgramSphere != 0)
877
                GL.DeleteProgram(shaderProgramSphere);
878
            if (shaderProgramCubemap != 0)
879
                GL.DeleteProgram(shaderProgramCubemap);
880
            if (textureCubeColor != 0)
881
                GL.DeleteTexture(textureCubeColor);
882
            if (textureCubeDepth != 0)
883
                GL.DeleteTexture(textureCubeDepth);
884
            if (textureCubeFBO != 0)
885
                GL.DeleteFramebuffers(1, ref textureCubeFBO);
886
            base.OnUnload(e);
887
        }
888
 
889
        protected override void OnResize(EventArgs e)
890
        {
891
            GL.Viewport(0, 0, Width, Height);
892
 
893
            // Set projection matrix
894
            GL.MatrixMode(MatrixMode.Projection);
895
            switch (mode)
896
            {
897
                case ViewMode.CubemapCross:
898
                    setOrtho();
899
                    break;
900
                case ViewMode.Scene:
901
                    setPerspective();
902
                    break;
903
                default:
904
                    GL.LoadIdentity();
905
                    break;
906
            }
907
 
908
            // Set selector state back to ModelView matrix mode
909
            GL.MatrixMode(MatrixMode.Modelview);
910
            base.OnResize(e);
911
 
912
        }
913
 
914
        protected override void OnUpdateFrame(FrameEventArgs e)
915
        {
916
            base.OnUpdateFrame(e);
917
 
918
            // elapsed time in ms since last start
919
            double elapsed = (DateTime.Now - startTime).TotalMilliseconds;
920
 
921
            spherePos.X = (float)Math.Sin(elapsed / 5000) * 3;
922
            spherePos.Z = (float)Math.Cos(elapsed / 5000) * 3;
923
            eyePos.X = (float)Math.Cos(elapsed / 3000) * 8;
924
            eyePos.Z = (float)Math.Sin(elapsed / 2000) * 8;
925
 
926
            if (Keyboard[Key.Space])
927
            {
928
                ErrorCode err = GL.GetError();
929
                //Console.WriteLine(err + "  " + Glu.ErrorString((GluErrorCode)err));
930
                Console.WriteLine("GL error code: {0}", err);
931
            }
932
        }
933
 
934
        protected override void OnRenderFrame(FrameEventArgs e)
935
        {
936
            if (mode == ViewMode.CubemapCross)
937
            {
938
                renderCubemap();
939
                drawCubemapCross();
940
            }
941
            if (mode == ViewMode.Scene)
942
            {
943
                renderCubemap();
944
                GL.ClearColor(0.1f, 0.1f, 0.1f, 0.1f);
945
                GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
946
                renderScene();
947
            }
948
 
949
            this.SwapBuffers();
950
        }
951
 
952
        #endregion
953
 
954
        #region public static void Main()
955
 
956
        /// <summary>
957
        /// Entry point of this example.
958
        /// </summary>
959
        [STAThread]
960
        public static void Main()
961
        {
962
            using (SimpleGeometryShader2 example = new SimpleGeometryShader2())
963
            {
964
                Utilities.SetWindowTitle(example);
965
                example.Run(60.0, 0.0);
966
            }
967
        }
968
 
969
        #endregion
970
 
971
        #region data
972
        //structure: vec3 pos, vec3 normal, vec2 texcoord
973
        static float[] cubeData = {
974
            -10,-10,-10, 0,0,-10, 1.0f,0.0f,
975
            -10,10,-10, 0,0,-10, 1.0f,1.0f,
976
            10,10,-10, 0,0,-10, 0.0f,1.0f,
977
 
978
            10,10,-10, 0,0,-10, 0.0f,1.0f,
979
            10,-10,-10, 0,0,-10, 0.0f,0.0f,
980
            -10,-10,-10, 0,0,-10, 1.0f,0.0f,
981
 
982
            -10,-10,10, 0,0,10, 0.0f,0.0f,
983
            10,-10,10, 0,0,10, 1.0f,0.0f,
984
            10,10,10, 0,0,10, 1.0f,1.0f,
985
 
986
            10,10,10, 0,0,10, 1.0f,1.0f,
987
            -10,10,10, 0,0,10, 0.0f,1.0f,
988
            -10,-10,10, 0,0,10, 0.0f,0.0f,
989
 
990
            -10,-10,-10, 0,-10,0, 0.0f,0.0f,
991
            10,-10,-10, 0,-10,0, 1.0f,0.0f,
992
            10,-10,10, 0,-10,0, 1.0f,1.0f,
993
 
994
            10,-10,10, 0,-10,0, 1.0f,1.0f,
995
            -10,-10,10, 0,-10,0, 0.0f,1.0f,
996
            -10,-10,-10, 0,-10,0, 0.0f,0.0f,
997
 
998
            10,-10,-10, 10,0,0, 0.0f,0.0f,
999
            10,10,-10, 10,0,0, 1.0f,0.0f,
1000
            10,10,10, 10,0,0, 1.0f,1.0f,
1001
 
1002
            10,10,10, 10,0,0, 1.0f,1.0f,
1003
            10,-10,10, 10,0,0, 0.0f,1.0f,
1004
            10,-10,-10, 10,0,0, 0.0f,0.0f,
1005
 
1006
            10,10,-10, 0,10,0, 0.0f,0.0f,
1007
            -10,10,-10, 0,10,0, 1.0f,0.0f,
1008
            -10,10,10, 0,10,0, 1.0f,1.0f,
1009
 
1010
            -10,10,10, 0,10,0, 1.0f,1.0f,
1011
            10,10,10, 0,10,0, 0.0f,1.0f,
1012
            10,10,-10, 0,10,0, 0.0f,0.0f,
1013
 
1014
            -10,10,-10, -10,0,0, 0.0f,0.0f,
1015
            -10,-10,-10, -10,0,0, 1.0f,0.0f,
1016
            -10,-10,10, -10,0,0, 1.0f,1.0f,
1017
 
1018
            -10,-10,10, -10,0,0, 1.0f,1.0f,
1019
            -10,10,10, -10,0,0, 0.0f,1.0f,
1020
            -10,10,-10, -10,0,0, 0.0f,0.0f,
1021
        };
1022
 
1023
        static VertexPositionNormalTexture[] CalculateSphereVertices(float radius, float height, byte segments, byte rings)
1024
        {
1025
            VertexPositionNormalTexture[] data = new VertexPositionNormalTexture[segments * rings];
1026
 
1027
            int i = 0;
1028
 
1029
            for (double y = 0; y < rings; y++)
1030
            {
1031
                double phi = (y / (rings - 1)) * Math.PI;
1032
                for (double x = 0; x < segments; x++)
1033
                {
1034
                    double theta = (x / (segments - 1)) * 2 * Math.PI;
1035
 
1036
                    Vector3 v = new Vector3(
1037
                        (float)(radius * Math.Sin(phi) * Math.Cos(theta)),
1038
                        (float)(height * Math.Cos(phi)),
1039
                        (float)(radius * Math.Sin(phi) * Math.Sin(theta)));
1040
                    Vector3 n = Vector3.Normalize(v);
1041
                    Vector2 uv = new Vector2(
1042
                        (float)(x / (segments - 1)),
1043
                        (float)(y / (rings - 1)));
1044
                    // Using data[i++] causes i to be incremented multiple times in Mono 2.2 (bug #479506).
1045
                    data[i] = new VertexPositionNormalTexture(v, n, uv);
1046
                    i++;
1047
                }
1048
 
1049
            }
1050
 
1051
            return data;
1052
        }
1053
 
1054
        static ushort[] CalculateSphereElements(float radius, float height, byte segments, byte rings)
1055
        {
1056
            int num_vertices = segments * rings;
1057
            ushort[] data = new ushort[num_vertices * 6];
1058
 
1059
            ushort i = 0;
1060
 
1061
            for (byte y = 0; y < rings - 1; y++)
1062
            {
1063
                for (byte x = 0; x < segments - 1; x++)
1064
                {
1065
                    data[i++] = (ushort)((y + 0) * segments + x);
1066
                    data[i++] = (ushort)((y + 1) * segments + x);
1067
                    data[i++] = (ushort)((y + 1) * segments + x + 1);
1068
 
1069
                    data[i++] = (ushort)((y + 1) * segments + x + 1);
1070
                    data[i++] = (ushort)((y + 0) * segments + x + 1);
1071
                    data[i++] = (ushort)((y + 0) * segments + x);
1072
                }
1073
            }
1074
 
1075
            // Verify that we don't access any vertices out of bounds:
1076
            foreach (int index in data)
1077
                if (index >= segments * rings)
1078
                    throw new IndexOutOfRangeException();
1079
 
1080
            return data;
1081
        }
1082
 
1083
        #endregion
1084
    }
1085
}