protected void UpdateContextVersion() { // If the request version number is anything up to and including 2.1, standard render contexts // will provide what we need (as long as the graphics card drivers are up to date). var requestedVersionNumber = VersionAttribute.GetVersionAttribute(_requestedOpenGLVersion); if (requestedVersionNumber.IsAtLeastVersion(3, 0) == false) { return; } // Now the none-trivial case. We must use the WGL_ARB_create_context extension to // attempt to create a 3.0+ context. try { Int32[] attributes = { WGL_CONTEXT_MAJOR_VERSION_ARB, requestedVersionNumber.Major, WGL_CONTEXT_MINOR_VERSION_ARB, requestedVersionNumber.Minor, WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 0 }; var hrc = CreateContextAttribsARB(IntPtr.Zero, attributes); GLWindows.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero); GLWindows.wglDeleteContext(_renderContextHandle); GLWindows.wglMakeCurrent(_deviceContextHandle, hrc); _renderContextHandle = hrc; } catch (Exception) { // TODO: can we actually get the real version? } }
public HelloTriangle(Form form, IntPtr handle) { _form = form; _requestedOpenGLVersion = OpenGLVersion.OpenGL4_4; _delegateCache = new DelegateCache(); _windowBuilder = new GLWindowBuilder("OpenGLSurface"); _dibSection = new DIBSection(); var _hostGraphics = Graphics.FromHwnd(handle); _hostDc = _hostGraphics.GetHdc(); _windowHandle = _windowBuilder.BuildNativeWindow(_roundedWidth, _roundedHeight); _deviceContextHandle = Native.GetDC(_windowHandle); var pfd = new Pixelformatdescriptor(); pfd.Init(); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = _bitDepth; pfd.cDepthBits = 16; pfd.cStencilBits = 8; pfd.iLayerType = PFD_MAIN_PLANE; Int32 iPixelformat; if ((iPixelformat = Native.ChoosePixelFormat(_deviceContextHandle, pfd)) == 0) { throw new InvalidOperationException(); } if (Native.SetPixelFormat(_deviceContextHandle, iPixelformat, pfd) == 0) { throw new InvalidOperationException(); } _renderContextHandle = GLWindows.wglCreateContext(_deviceContextHandle); GLWindows.wglMakeCurrent(_deviceContextHandle, _renderContextHandle); UpdateContextVersion(); CreateDBOs(); OnSizeChanged(); const String vertexShaderSource = "#version 330 core\n" + "layout (location = 0) in vec3 aPos;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" + "}\0"; const String fragmentShaderSource = "#version 330 core\n" + "out vec4 FragColor;\n" + "void main()\n" + "{\n" + " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" + "}\n\0"; var vertexShader = GL.CreateVertexShader(); GL.ShaderSource(vertexShader, vertexShaderSource); GL.CompileShader(vertexShader); var rdrr = GL.GetCompileStatus(vertexShader); if (!rdrr) { throw new InvalidProgramException("Unable to compile vertex shader"); } var fragmentShader = GL.CreateShader(GL.GL_FRAGMENT_SHADER); GL.ShaderSource(fragmentShader, fragmentShaderSource); GL.CompileShader(fragmentShader); rdrr = GL.GetCompileStatus(fragmentShader); if (!rdrr) { throw new InvalidProgramException("Unable to compile fragment shader"); } _shaderProgram = GL.CreateProgram(); GL.AttachShader(_shaderProgram, vertexShader); GL.AttachShader(_shaderProgram, fragmentShader); GL.LinkProgram(_shaderProgram); // check for linking errors var parameters = new[] { 0 }; GL.GetProgram(_shaderProgram, GL.GL_LINK_STATUS, parameters); var ok = parameters[0] == GL.GL_TRUE; if (!ok) { throw new InvalidProgramException("Unable to link shader"); } GL.DeleteShader(vertexShader); GL.DeleteShader(fragmentShader); var vertices = new[] { 0.5f, 0.5f, 0.0f, // top right 0.5f, -0.5f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, // bottom left -0.5f, 0.5f, 0.0f // top left }; UInt16[] indices = { // note that we start from 0! 0, 1, 3, // first Triangle 1, 2, 3 // second Triangle }; var buff = new UInt32[1]; GL.GenVertexArrays(1, buff); VAO = buff[0]; GL.GenBuffers(1, buff); VBO = buff[0]; GL.GenBuffers(1, buff); EBO = buff[0]; //// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). GL.BindVertexArray(VAO); GL.BindBuffer(GL.GL_ARRAY_BUFFER, VBO); GL.BufferData(GL.GL_ARRAY_BUFFER, vertices, GL.GL_STATIC_DRAW); GL.BindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, EBO); GL.BufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices, GL.GL_STATIC_DRAW); GL.VertexAttribPointer(0, 3, GL.GL_FLOAT, false, 3 * sizeof(Single), IntPtr.Zero); GL.EnableVertexAttribArray(0); //// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind GL.BindBuffer(GL.GL_ARRAY_BUFFER, 0); // remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound. //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. GL.BindVertexArray(0); }