/// <inheritdoc/> public override EffectImplementation Process(ContentManager manager, IContentProcessorMetadata metadata, String input) { var isFragShader = (metadata.Extension == ".frag"); var isVertShader = (metadata.Extension == ".vert"); if (!isFragShader && !isVertShader) { throw new InvalidDataException(OpenGLStrings.ImplicitEffectsMustLoadFromShaders.Format(metadata.AssetPath)); } var vertShaderFilePath = isFragShader ? Path.ChangeExtension(metadata.AssetPath, "vert") : metadata.AssetPath; var fragShaderFilePath = isFragShader ? metadata.AssetPath : Path.ChangeExtension(metadata.AssetPath, "frag"); metadata.AddAssetDependency(isFragShader ? vertShaderFilePath : fragShaderFilePath); var vertShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(vertShaderFilePath), Externs); var vertShader = new OpenGLVertexShader(manager.Ultraviolet, new[] { vertShaderSource }); var fragShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(fragShaderFilePath), Externs); var fragShader = new OpenGLFragmentShader(manager.Ultraviolet, new[] { fragShaderSource }); var program = new OpenGLShaderProgram(manager.Ultraviolet, vertShader, fragShader, false); var pass = new OpenGLEffectPass(manager.Ultraviolet, "Default", new[] { program }); var technique = new OpenGLEffectTechnique(manager.Ultraviolet, "Default", new[] { pass }); return(new OpenGLEffectImplementation(manager.Ultraviolet, new[] { technique })); }
/// <inheritdoc/> public override EffectImplementation Process(ContentManager manager, IContentProcessorMetadata metadata, XDocument input) { var techniques = new List <OpenGLEffectTechnique>(); var techniqueElements = input.Root.Elements("Technique"); if (!techniqueElements.Any()) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveTechniques); } foreach (var techniqueElement in techniqueElements) { var techniqueName = (String)techniqueElement.Attribute("Name"); var techniquePasses = new List <OpenGLEffectPass>(); var passElements = techniqueElement.Elements("Pass"); if (!passElements.Any()) { throw new ContentLoadException(OpenGLStrings.EffectTechniqueMustHavePasses); } foreach (var passElement in passElements) { var passName = (String)passElement.Attribute("Name"); var vertPath = GetShader(passElement, "VertexShader"); if (String.IsNullOrEmpty(vertPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } vertPath = ResolveDependencyAssetPath(metadata, vertPath); metadata.AddAssetDependency(vertPath); var fragPath = GetShader(passElement, "FragmentShader"); if (String.IsNullOrEmpty(fragPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } fragPath = ResolveDependencyAssetPath(metadata, fragPath); metadata.AddAssetDependency(fragPath); var vertShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(vertPath), Externs); var vertShader = new OpenGLVertexShader(manager.Ultraviolet, new[] { vertShaderSource }); var fragShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(fragPath), Externs); var fragShader = new OpenGLFragmentShader(manager.Ultraviolet, new[] { fragShaderSource }); var programs = new[] { new OpenGLShaderProgram(manager.Ultraviolet, vertShader, fragShader, false) }; techniquePasses.Add(new OpenGLEffectPass(manager.Ultraviolet, passName, programs)); } techniques.Add(new OpenGLEffectTechnique(manager.Ultraviolet, techniqueName, techniquePasses)); } return(new OpenGLEffectImplementation(manager.Ultraviolet, techniques)); }
/// <inheritdoc/> public override EffectImplementation ImportPreprocessed(ContentManager manager, IContentProcessorMetadata metadata, BinaryReader reader) { var techniques = new List <OpenGLEffectTechnique>(); var techniqueCount = reader.ReadInt32(); if (techniqueCount == 0) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveTechniques); } for (int i = 0; i < techniqueCount; i++) { var techniqueName = reader.ReadString(); var passes = new List <OpenGLEffectPass>(); var passCount = reader.ReadInt32(); if (passCount == 0) { throw new ContentLoadException(OpenGLStrings.EffectTechniqueMustHavePasses); } for (int j = 0; j < passCount; j++) { var passName = reader.ReadString(); var vertPathGL = reader.ReadString(); var vertPathES = reader.ReadString(); var vertPath = GetShaderForCurrentPlatform(vertPathGL, vertPathES); if (String.IsNullOrEmpty(vertPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } vertPath = ResolveDependencyAssetPath(metadata, vertPath); metadata.AddAssetDependency(vertPath); var fragPathGL = reader.ReadString(); var fragPathES = reader.ReadString(); var fragPath = GetShaderForCurrentPlatform(fragPathGL, fragPathES); if (String.IsNullOrEmpty(fragPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } fragPath = ResolveDependencyAssetPath(metadata, fragPath); metadata.AddAssetDependency(fragPath); var vertShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(vertPath), Externs); var vertShader = new OpenGLVertexShader(manager.Ultraviolet, new[] { vertShaderSource }); var fragShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(fragPath), Externs); var fragShader = new OpenGLFragmentShader(manager.Ultraviolet, new[] { fragShaderSource }); var programs = new[] { new OpenGLShaderProgram(manager.Ultraviolet, vertShader, fragShader, false) }; passes.Add(new OpenGLEffectPass(manager.Ultraviolet, passName, programs)); } techniques.Add(new OpenGLEffectTechnique(manager.Ultraviolet, techniqueName, passes)); } return(new OpenGLEffectImplementation(manager.Ultraviolet, techniques)); }
/// <inheritdoc/> public override EffectImplementation Process(ContentManager manager, IContentProcessorMetadata metadata, XDocument input) { var desc = DeserializeDescription(input); var parameters = new HashSet <String>(desc.Parameters); var techniques = new List <OpenGLEffectTechnique>(); if (!desc.Techniques?.Any() ?? false) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveTechniques); } foreach (var technique in desc.Techniques) { var techniqueName = technique.Name; var techniquePasses = new List <OpenGLEffectPass>(); if (!technique.Passes?.Any() ?? false) { throw new ContentLoadException(OpenGLStrings.EffectTechniqueMustHavePasses); } foreach (var pass in technique.Passes) { var passName = pass.Name; var vertPath = GetShaderForCurrentPlatform(pass.Stages.VertexShader, pass.Stages.VertexShaderES); if (String.IsNullOrEmpty(vertPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } vertPath = ResolveDependencyAssetPath(metadata, vertPath); metadata.AddAssetDependency(vertPath); var fragPath = GetShaderForCurrentPlatform(pass.Stages.FragmentShader, pass.Stages.FragmentShaderES); if (String.IsNullOrEmpty(fragPath)) { throw new ContentLoadException(OpenGLStrings.EffectMustHaveVertexAndFragmentShader); } fragPath = ResolveDependencyAssetPath(metadata, fragPath); metadata.AddAssetDependency(fragPath); var vertShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(vertPath), Externs); var vertShader = new OpenGLVertexShader(manager.Ultraviolet, new[] { vertShaderSource }); var fragShaderSource = ShaderSource.ProcessExterns(manager.Load <ShaderSource>(fragPath), Externs); var fragShader = new OpenGLFragmentShader(manager.Ultraviolet, new[] { fragShaderSource }); foreach (var hint in vertShader.ShaderSourceMetadata.ParameterHints) { parameters.Add(hint); } foreach (var hint in fragShader.ShaderSourceMetadata.ParameterHints) { parameters.Add(hint); } var programs = new[] { new OpenGLShaderProgram(manager.Ultraviolet, vertShader, fragShader, false) }; techniquePasses.Add(new OpenGLEffectPass(manager.Ultraviolet, passName, programs)); } techniques.Add(new OpenGLEffectTechnique(manager.Ultraviolet, techniqueName, techniquePasses)); } return(new OpenGLEffectImplementation(manager.Ultraviolet, techniques, parameters)); }
/// <summary> /// Initializes a new instance of the OpenGLShaderProgram class. /// </summary> /// <param name="uv">The Ultraviolet context.</param> /// <param name="vertexShader">The program's vertex shader.</param> /// <param name="fragmentShader">The program's fragment shader.</param> /// <param name="programOwnsShaders">A value indicating whether the program owns the shader objects.</param> public OpenGLShaderProgram(UltravioletContext uv, OpenGLVertexShader vertexShader, OpenGLFragmentShader fragmentShader, Boolean programOwnsShaders) : base(uv) { Contract.Require(vertexShader, nameof(vertexShader)); Contract.Require(fragmentShader, nameof(fragmentShader)); Ultraviolet.ValidateResource(vertexShader); Ultraviolet.ValidateResource(fragmentShader); this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; this.programOwnsShaders = programOwnsShaders; var concatenatedSourceMetadata = new ShaderSourceMetadata(); concatenatedSourceMetadata.Concat(vertexShader.ShaderSourceMetadata); concatenatedSourceMetadata.Concat(fragmentShader.ShaderSourceMetadata); var program = 0u; uv.QueueWorkItem(state => { program = gl.CreateProgram(); gl.ThrowIfError(); gl.AttachShader(program, vertexShader.OpenGLName); gl.ThrowIfError(); gl.AttachShader(program, fragmentShader.OpenGLName); gl.ThrowIfError(); gl.LinkProgram(program); gl.ThrowIfError(); var log = gl.GetProgramInfoLog(program); gl.ThrowIfError(); var status = gl.GetProgrami(program, gl.GL_LINK_STATUS); gl.ThrowIfError(); var attributeCount = gl.GetProgrami(program, gl.GL_ACTIVE_ATTRIBUTES); gl.ThrowIfError(); unsafe { var namebuf = Marshal.AllocHGlobal(256); try { for (int i = 0; i < attributeCount; i++) { var attrNameLen = 0; var attrName = default(String); var attrSize = 0; var attrType = 0u; gl.GetActiveAttrib(program, (uint)i, 256, &attrNameLen, &attrSize, &attrType, (sbyte *)namebuf); gl.ThrowIfError(); attrName = Marshal.PtrToStringAnsi(namebuf); var location = gl.GetAttribLocation(program, attrName); gl.ThrowIfError(); attributeLocations[attrName] = location; attributeTypes[attrName] = attrType; } } finally { Marshal.FreeHGlobal(namebuf); } } if (status == 0) { throw new InvalidOperationException(log); } }).Wait(); this.program = program; this.uniforms = CreateUniformCollection(concatenatedSourceMetadata); }