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
}
}
|