internal void Parse(ShaderRepository repository, string source) { // Parse include statements // TODO: regex match includes all leading new line chars var versionMatches = Regex.Matches(source, @"^\s*\#version\s+(.*?)\s*$", RegexOptions.Multiline); if (versionMatches.Count > 0) { VersionString = versionMatches[0].Groups[1].Value; if (versionMatches.Count > 1) { _device.TextOutput.Print(OutputTypeGlob.Warning, "Shader source " + Filename + " contains multiple #version statements!"); } } else { VersionString = repository.DefaultVersionString; _device.TextOutput.Print(OutputTypeGlob.Debug, "Shader source " + Filename + " contains no #version statement!"); } var matches = Regex.Matches(source, @"^\s*\#include\s+(.*?)\s*$", RegexOptions.Multiline); foreach (Match m in matches) { var dependency = repository.GetShaderSource(m.Groups[1].Value.Trim()); repository.AddDependency(this, dependency); } // TODO: version handling // Remove include statements from source ParsedCode = source; ParsedCode = ParsedCode.Replace("\r\n", "\n"); ParsedCode = Regex.Replace(ParsedCode, @"^\s*\#include\s+(.*?)\s*\r?$", match => { return("/* " + match.Value + " */"); }, RegexOptions.Multiline); ParsedCode = Regex.Replace(ParsedCode, @"^\s*\#version\s+(.*?)\s*$", match => { return("/* " + match.Value + " */"); }, RegexOptions.Multiline); }
/// <summary> /// Returns GLSL code with resolved dependencies that is ready to compile. /// </summary> internal ResolvedShader GetResolvedGlsl(ShaderRepository repository, Shader shader) { Dictionary <ShaderSource, int> dependencyOrder = new Dictionary <ShaderSource, int>(); GetDependencyOrder(new HashSet <ShaderSource>(), dependencyOrder, 0); var ordered = dependencyOrder.OrderByDescending(x => x.Value).ToList(); StringBuilder sb = new StringBuilder(); sb.AppendLine("#version " + VersionString); sb.AppendLine(repository.ShaderHeader); // Not needed when compiling to Spirv since macros can be specified with args in glsLang foreach (var macro in shader.Macros) { sb.AppendLine("#define " + macro.Item1 + " " + macro.Item2); } List <Tuple <int, string> > blocks = new List <Tuple <int, string> >(); blocks.Add(new Tuple <int, string>(0, "Shader version, header and macros")); int lines = CountLines(repository.ShaderHeader) + 1; for (int i = 0; i < ordered.Count; i++) { var dependency = ordered[i].Key; sb.AppendLine("/* File: " + dependency.Filename + " */"); lines += 1; blocks.Add(new Tuple <int, string>(lines, dependency.Filename)); sb.AppendLine(dependency.ParsedCode); lines += CountLines(dependency.ParsedCode); } return(new ResolvedShader() { Code = sb.ToString(), Blocks = blocks, }); }
/// <summary> /// Creates a new Glob Device. Can only be called once the OpenGL context is already created, for example by creating an OpenTK GameWindow. /// </summary> /// <param name="textOutput">Text output that will be used by Glob</param> /// <param name="fileManager">File manager that will be used by Glob</param> public Device(ITextOutputGlob textOutput, IFileManagerGlob fileManager) { TextOutput = textOutput; FileManager = fileManager; DeviceInfo = new DeviceInfo(); // TODO: move these to DeviceInfo.ToString() TextOutput.Print(OutputTypeGlob.Notify, "OpenGL: " + DeviceInfo.OpenGLVersion + " GLSL: " + DeviceInfo.GLSLVersion); TextOutput.Print(OutputTypeGlob.Notify, "Renderer: " + DeviceInfo.DeviceRenderer + ", " + DeviceInfo.DeviceVendor); // Print extensions StringBuilder allExtensionsStr = new StringBuilder(); foreach (string extension in DeviceInfo.Extensions) { allExtensionsStr.Append(extension); allExtensionsStr.Append(" "); } TextOutput.Print(OutputTypeGlob.Notify, DeviceInfo.Extensions.Count.ToString() + " GL extensions found"); TextOutput.Print(OutputTypeGlob.LogOnly, allExtensionsStr.ToString()); ShaderRepository = new ShaderRepository(this, "#extension GL_ARB_separate_shader_objects : enable\n"); ShaderRepository.StartFileWatcher(FileManager.GetPathShaderSource("")); _bufferBindingManager = new BufferBindingManager(); DebugMessageManager = new DebugMessageManager(true); _textureUnit = new TextureUnitState(); _currentRasterizerState = new RasterizerState(); _currentDepthState = new DepthState(); _currentBlendState = new BlendState(); // Create and bind a global vertex array object _vaoGlobal = GL.GenVertexArray(); GL.BindVertexArray(_vaoGlobal); }