/// <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));
        }
Esempio n. 5
0
        /// <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);
        }