File: GeometryShader.cs

package info (click to toggle)
opentk 1.1.4c%2Bdfsg-2.1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster
  • size: 68,640 kB
  • sloc: cs: 525,501; xml: 277,501; ansic: 3,597; makefile: 41
file content (246 lines) | stat: -rw-r--r-- 8,611 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
// This code was written for the OpenTK library and has been released
// to the Public Domain.
// It is provided "as is" without express or implied warranty of any kind.

using System;
using System.Diagnostics;
using System.Drawing;

using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;

namespace Examples.Tutorial
{
    [Example("Basic Geometry Shader", ExampleCategory.OpenGL, "2.x", Documentation = "Simple usage of EXT_geometry_shader4")]
    public class SimpleGeometryShader : GameWindow
    {
        public SimpleGeometryShader()
            : base(800, 600)
        {
        }

        int shaderProgram = 0;

        protected override void OnLoad(EventArgs e)
        {
            if (!GL.GetString(StringName.Extensions).Contains("EXT_geometry_shader4"))
            {
                System.Windows.Forms.MessageBox.Show(
                     "Your video card does not support EXT_geometry_shader4. Please update your drivers.",
                     "EXT_geometry_shader4 not supported",
                     System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
                Exit();
                throw new NotSupportedException();
            }

            // create a shader object.
            shaderProgram = GL.CreateProgram();
            // create shader objects for all three types.
            int vert = GL.CreateShader(ShaderType.VertexShader);
            int frag = GL.CreateShader(ShaderType.FragmentShader);
            int geom = GL.CreateShader(ShaderType.GeometryShaderExt);

            // GLSL for fragment shader.
            String fragSource = @"
				void main( void )
				{
					gl_FragColor = vec4(0, 1, 0, 0);
				}	
			";

            // GLSL for vertex shader.
            String vertSource = @"
				void main( void )
				{
					gl_Position = ftransform();
				}	
			";

            // GLSL for geometry shader.
            // Note this is a version 1.20 shader
            // Also note GL_EXT_geometry_shader4 must be enabled explicitly, correct
            // OpenGL implementations should only have the new tokens, like
            // EmitVertex and EndPrimitive, when this extension is enabled.
            String geomSource = @"
				#version 120 
				#extension GL_EXT_geometry_shader4 : enable

				void main(void)
				{
					// variable to use in for loops
					int i;

					// Emit the original vertices without changing, making
					// this part exactly the same as if no geometry shader
					// was used.
					for(i=0; i< gl_VerticesIn; i++)
					{
						gl_Position = gl_PositionIn[i];
						EmitVertex();
					}
					// End the one primitive with the original vertices
					EndPrimitive();

					// Now we generate some more! This translates 0.2 over
					// the positive x axis.
					for(i=0; i< gl_VerticesIn; i++)
					{
						gl_Position = gl_PositionIn[i];
						gl_Position.x += 0.2;
						EmitVertex();
					}
					EndPrimitive();
				}
			";

            // compile shaders.
            compileShader(frag, fragSource);
            compileShader(vert, vertSource);
            compileShader(geom, geomSource);

            // attach shaders and link the program.
            GL.AttachShader(shaderProgram, frag);
            GL.AttachShader(shaderProgram, vert);
            GL.AttachShader(shaderProgram, geom);

            // Set the input type of the primitives we are going to feed the geometry shader, this should be the same as
            // the primitive type given to GL.Begin. If the types do not match a GL error will occur (todo: verify GL_INVALID_ENUM, on glBegin)
            GL.Ext.ProgramParameter(shaderProgram, AssemblyProgramParameterArb.GeometryInputType, (int)BeginMode.Lines);
            // Set the output type of the geometry shader. Becasue we input Lines we will output LineStrip(s).
            GL.Ext.ProgramParameter(shaderProgram, AssemblyProgramParameterArb.GeometryOutputType, (int)BeginMode.LineStrip);

            // We must tell the shader program how much vertices the geometry shader will output (at most).
            // One simple way is to query the maximum and use that.
            // NOTE: Make sure that the number of vertices * sum(components of active varyings) does not
            // exceed MaxGeometryTotalOutputComponents.
            GL.Ext.ProgramParameter(shaderProgram, AssemblyProgramParameterArb.GeometryVerticesOut, 50);

            // NOTE: calls to ProgramParameter do not take effect until you call LinkProgram.
            GL.LinkProgram(shaderProgram);

            // output link info log.
            string info;
            GL.GetProgramInfoLog(shaderProgram, out info);
            Debug.WriteLine(info);
            
            // Set clearcolor and bind the shader program.
            GL.ClearColor(0.1f, 0.1f, 0.1f, 0.1f);
            GL.UseProgram(shaderProgram);
            // Set color to red. If the shader fails the fixed pipeline will be used and 
            // the lines will be red, if all is ok the fragment shader is used and they will be green.
            GL.Color3(1.0f, 0, 0);

            // Clean up resources. Note the program object is not deleted.
            if (frag != 0)
                GL.DeleteShader(frag);
            if (vert != 0)
                GL.DeleteShader(vert);
            if (geom != 0)
                GL.DeleteShader(geom);
        }

        /// <summary>
        /// Helper method to avoid code duplication.
        /// Compiles a shader and prints results using Debug.WriteLine.
        /// </summary>
        /// <param name="shader">A shader object, gotten from GL.CreateShader.</param>
        /// <param name="source">The GLSL source to compile.</param>
        void compileShader(int shader, string source)
        {
            GL.ShaderSource(shader, source);
            GL.CompileShader(shader);

            string info;
            GL.GetShaderInfoLog(shader, out info);
            Debug.WriteLine(info);

            int compileResult;
            GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
            if (compileResult != 1)
            {
                Debug.WriteLine("Compile Error!");
                Debug.WriteLine(source);
            }
        }

        protected override void OnUnload(EventArgs e)
        {
            if (shaderProgram != 0)
                GL.DeleteProgram(shaderProgram);
            base.OnUnload(e);
        }

        /// <summary>
        /// Sets the viewport and projection matrix for orthographic projection.
        /// </summary>
        /// <param name="e">resize event args</param>
        protected override void OnResize(EventArgs e)
        {
            GL.Viewport(ClientRectangle);

            // Set projection matrix
            GL.MatrixMode(MatrixMode.Projection);
            OpenTK.Matrix4 ortho = OpenTK.Matrix4.CreateOrthographicOffCenter(-1, 1, -1, 1, 1, -1);
            GL.LoadMatrix(ref ortho);

            // Set selector state back to matrix mode
            GL.MatrixMode(MatrixMode.Modelview);

            base.OnResize(e);
        }

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            var keyboard = OpenTK.Input.Keyboard.GetState();
            if (keyboard[Key.Space])
            {
                ErrorCode err = GL.GetError();
                //Console.WriteLine(err + "  " + Glu.ErrorString((GluErrorCode)err));
                Console.WriteLine("GL error code: {0}", err);
            }

            if (keyboard[Key.Escape])
                this.Exit();
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // draw two vertical lines
            GL.Begin(PrimitiveType.Lines);
            {
                // line one
                GL.Vertex2(-0.5f, -0.5f);
                GL.Vertex2(-0.5f, 0.5f);
                // line two
                GL.Vertex2(0.5f, 0.5f);
                GL.Vertex2(0.5f, -0.5f);
            }
            GL.End();

            this.SwapBuffers();
        }

        #region public static void Main()

        /// <summary>
        /// Entry point of this example.
        /// </summary>
        [STAThread]
        public static void Main()
        {
            using (SimpleGeometryShader example = new SimpleGeometryShader())
            {
                Utilities.SetWindowTitle(example);
                example.Run(30.0, 0.0);
            }
        }

        #endregion
    }
}