/// <summary> /// OnRenderFrame is called on every frame for rendering /// </summary> /// <param name="e">event arguments</param> protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); // Clear the color & depth buffer gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Start with identity every frame _viewMatrix.Identity(); // View transform: move the coordinate system away from the camera _viewMatrix.Translate(0, 0, _camZ); // View transform: rotate the coordinate system increasingly _viewMatrix.Rotate(_rotX + _deltaX, 1, 0, 0); _viewMatrix.Rotate(_rotY + _deltaY, 0, 1, 0); // Transform light position & direction into view space SLVec3f lightPosVS = _viewMatrix * _lightPos; // The light dir is not a position. We only take the rotation of the mv matrix. SLMat3f viewRot = _viewMatrix.Mat3(); SLVec3f lightDirVS = viewRot * _lightDir; // Rotate the model so that we see it _modelMatrix.Identity(); _modelMatrix.Rotate(90, -1, 0, 0); // Build the combined modelview-projection matrix SLMat4f mvp = new SLMat4f(_projectionMatrix); SLMat4f mv = new SLMat4f(_viewMatrix); mv.Multiply(_modelMatrix); mvp.Multiply(mv); // Build normal matrix SLMat3f nm = mv.InverseTransposed(); // Pass the matrix uniform variables unsafe { gl.UniformMatrix4(_mvMatrixLoc, 1, false, mv.m); gl.UniformMatrix3(_nMatrixLoc, 1, false, nm.m); gl.UniformMatrix4(_mvpMatrixLoc, 1, false, mvp.m); // Pass lighting uniforms variables gl.Uniform4(_globalAmbiLoc, 1, (float[])_globalAmbi); gl.Uniform3(_lightPosVSLoc, 1, (float[])lightPosVS); gl.Uniform3(_lightSpotDirVSLoc, 1, (float[])lightDirVS); gl.Uniform4(_lightAmbientLoc, 1, (float[])_lightAmbient); gl.Uniform4(_lightDiffuseLoc, 1, (float[])_lightDiffuse); gl.Uniform4(_lightSpecularLoc, 1, (float[])_lightSpecular); gl.Uniform4(_matAmbientLoc, 1, (float[])_matAmbient); gl.Uniform4(_matDiffuseLoc, 1, (float[])_matDiffuse); gl.Uniform4(_matSpecularLoc, 1, (float[])_matSpecular); gl.Uniform4(_matEmissiveLoc, 1, (float[])_matEmissive); } gl.Uniform1(_matShininessLoc, _matShininess); gl.Uniform1(_texture0Loc, 0); ////////////////////// // Draw with 2 VBOs // ////////////////////// // Enable all of the vertex attribute arrays gl.EnableVertexAttribArray(_pLoc); gl.EnableVertexAttribArray(_nLoc); gl.EnableVertexAttribArray(_tLoc); // Activate VBOs gl.BindBuffer(BufferTarget.ArrayBuffer, _vboV); gl.BindBuffer(BufferTarget.ElementArrayBuffer, _vboI); // Activate Texture gl.BindTexture(TextureTarget.Texture2D, _textureID); // For VBO only offset instead of data pointer int stride = 32; int offsetN = 3 * sizeof(float); int offsetT = 6 * sizeof(float); gl.VertexAttribPointer(_pLoc, 3, VertexAttribPointerType.Float, false, stride, 0); gl.VertexAttribPointer(_nLoc, 3, VertexAttribPointerType.Float, false, stride, offsetN); gl.VertexAttribPointer(_tLoc, 2, VertexAttribPointerType.Float, false, stride, offsetT); ///////////////////////////////////////////////////////////////////////////// // Draw cube model triangles by indexes gl.DrawElements(BeginMode.Triangles, _numI, DrawElementsType.UnsignedInt, 0); ///////////////////////////////////////////////////////////////////////////// // Deactivate buffers gl.BindBuffer(BufferTarget.ArrayBuffer, 0); gl.BindBuffer(BufferTarget.ElementArrayBuffer, 0); // Disable the vertex arrays gl.DisableVertexAttribArray(_pLoc); gl.DisableVertexAttribArray(_nLoc); gl.DisableVertexAttribArray(_tLoc); // Fast copy the back buffer to the front buffer. This is OS dependent. SwapBuffers(); // Check for errors glUtils.GetGLError("OnRenderFrame", true); }