/// <summary> /// Creates a new instance of <see cref="QVertexArrayObject"/> /// </summary> /// <param name="state">The <see cref="QFontSharedState"/> to use</param> public QVertexArrayObject(QFontSharedState state) { QFontSharedState = state; _vertices = new List <QVertex>(INITIAL_SIZE); _bufferMaxVertexCount = INITIAL_SIZE; _bufferSize = _bufferMaxVertexCount * QVertexStride; #if !OPENGL_ES _VAOID = GL.GenVertexArray(); #endif GL.UseProgram(QFontSharedState.ShaderVariables.ShaderProgram); #if !OPENGL_ES GL.BindVertexArray(_VAOID); #endif GL.GenBuffers(1, out _VBOID); GL.BindBuffer(BufferTarget.ArrayBuffer, _VBOID); EnableAttributes(); GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)_bufferSize, IntPtr.Zero, BufferUsageHint.StreamDraw); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); #if !OPENGL_ES GL.BindVertexArray(0); #endif }
/// <summary> /// Initialises the instance render state /// </summary> /// <param name="state"> /// If state is null, this method will instead initialise the static state, which is returned when no /// instance state is set /// </param> private void InitialiseState(QFontSharedState state) { if (state != null) { _instanceSharedState = state; } else if (SharedState == null) { InitialiseStaticState(); } }
/// <summary> /// Creates a new instance of <see cref="QFontDrawing"/> /// </summary> /// <param name="useDefaultBlendFunction">Whether to use the default blend function</param> /// <param name="state">The QFontSharedState of this object. If null, will use the static state</param> public QFontDrawing(bool useDefaultBlendFunction = true, QFontSharedState state = null) { _useDefaultBlendFunction = useDefaultBlendFunction; _glFontDrawingPrimitives = new List <QFontDrawingPrimitive>(); InitialiseState(state); }
/// <summary> /// Initializes the static shared render state using builtin shaders /// </summary> private static void InitialiseStaticState() { // Enable 2D textures GL.Enable(EnableCap.Texture2D); //Create vertex and fragment shaders int vert = GL.CreateShader(ShaderType.VertexShader); int frag = GL.CreateShader(ShaderType.FragmentShader); //Check shaders were created succesfully if (vert == -1 || frag == -1) { throw new Exception(string.Format("Error creating shader name for {0}", vert == -1 ? (frag == -1 ? "vert and frag shaders" : "vert shader") : "frag shader")); } // We try to compile the shaders with ever increasing version numbers (up to 1.50) // This fixes a bug on MaxOSX where the Core profile only supports shaders >= 1.50 (or sometimes 1.40) var versions = new[] { SHADER_VERSION_STRING130, SHADER_VERSION_STRING140, SHADER_VERSION_STRING150 }; // Holds the compilation status of the shaders int vertCompileStatus = 0; int fragCompileStatus = 0; foreach (var version in versions) { #if OPENGL_ES GL.ShaderSource(vert, LoadShaderFromResource("simple_es.vs")); GL.ShaderSource(frag, LoadShaderFromResource("simple_es.fs")); #else GL.ShaderSource(vert, version + LoadShaderFromResource("simple.vs")); GL.ShaderSource(frag, version + LoadShaderFromResource("simple.fs")); #endif GL.CompileShader(vert); GL.CompileShader(frag); GL.GetShader(vert, ShaderParameter.CompileStatus, out vertCompileStatus); GL.GetShader(frag, ShaderParameter.CompileStatus, out fragCompileStatus); // Check shaders were compiled correctly // If they have, we break out of the foreach loop as we have found the minimum supported glsl version if (vertCompileStatus != 0 && fragCompileStatus != 0) { break; } // Otherwise continue with the loop } // Check that we ended up with a compiled shader at the end of all this // These will only be 0 if all compilations with different versions failed, // since we break out of the version loop as soon as one compiles if (vertCompileStatus == 0 || fragCompileStatus == 0) { string vertInfo = GL.GetShaderInfoLog(vert); string fragInfo = GL.GetShaderInfoLog(frag); throw new Exception(String.Format("Shaders were not compiled correctly. Info logs are\nVert:\n{0}\nFrag:\n{1}", vertInfo, fragInfo)); } int prog; int progLinkStatus; prog = GL.CreateProgram(); GL.AttachShader(prog, vert); GL.AttachShader(prog, frag); GL.LinkProgram(prog); //Check program was linked without errors GL.GetProgram(prog, GetProgramParameterName.LinkStatus, out progLinkStatus); if (progLinkStatus == 0) { string programInfoLog = GL.GetProgramInfoLog(prog); throw new Exception(String.Format("Program was not linked correctly. Info log is\n{0}", programInfoLog)); } //Detach then delete unneeded shaders GL.DetachShader(prog, vert); GL.DetachShader(prog, frag); GL.DeleteShader(vert); GL.DeleteShader(frag); //Retrieve shader attribute and uniform locations int projLoc = GL.GetUniformLocation(prog, "proj_matrix"); int mvLoc = GL.GetUniformLocation(prog, "modelview_matrix"); int samplerLoc = GL.GetUniformLocation(prog, "tex_object"); int posLoc = GL.GetAttribLocation(prog, "in_position"); int tcLoc = GL.GetAttribLocation(prog, "in_tc"); int colLoc = GL.GetAttribLocation(prog, "in_colour"); //Now we have all the information, time to create the shared state object var shaderVariables = new ShaderLocations { ShaderProgram = prog, ProjectionMatrixUniformLocation = projLoc, ModelViewMatrixUniformLocation = mvLoc, TextureCoordAttribLocation = tcLoc, PositionCoordAttribLocation = posLoc, SamplerLocation = samplerLoc, ColorCoordAttribLocation = colLoc, }; var sharedState = new QFontSharedState(TextureUnit.Texture0, shaderVariables); _sharedState = sharedState; }