예제 #1
0
파일: Shader.cs 프로젝트: yaram/OpenGL.Net
        /// <summary>
        /// Generate ShaderObject source.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the information required for compiling this ShaderObject.
        /// </param>
        /// <returns>
        /// It returns a <see cref="List{T}"/> which represent this ShaderObject source. This source text is ready to be compiled.
        /// </returns>
        private List <string> GenerateSource(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }

            if (_SourceStrings == null)
            {
                throw new InvalidOperationException("no source loaded");
            }

            List <string> shaderSource = new List <string>(256);

            string[] shaderSourceStrings = _SourceStrings.ToArray();

            // Append imposed header - Every source shall compile with this header
            AppendHeader(ctx, cctx, shaderSource, cctx.ShaderVersion.VersionId);

            // Append required #define statments
            if (cctx.Defines != null)
            {
                foreach (string def in cctx.Defines)
                {
                    shaderSource.Add(String.Format("#define {0} 1\n", def));
                    Log("  Symbol: {0}", def);
                }
            }

            // Append specific source for composing shader essence
            AppendSourceStrings(shaderSource, shaderSourceStrings);

            // Remove comment lines
            shaderSource = CleanSource(shaderSource);

            // Preprocessing
            // Manage #include preprocessor directives in the case GL_ARB_shading_language_include is not supported
            // When #include are replaced, conditionals are processed too
            if (ctx.Extensions.ShadingLanguageInclude_ARB == false)
            {
                shaderSource = ShaderPreprocessor.Process(shaderSource, cctx, ctx.IncludeLibrary, ShaderPreprocessor.Stage.All);
            }

            shaderSource = CleanSource(shaderSource);

            return(shaderSource);
        }
예제 #2
0
        /// <summary>
        /// Generate Shader source.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for the compilation process.
        /// </param>
        /// <param name="cctx">
        /// A <see cref="ShaderCompilerContext"/> that specify the information required for compiling this Shader.
        /// </param>
        /// <returns>
        /// It returns a <see cref="List{T}"/> which represent this Shader source. This source text is ready to be compiled.
        /// </returns>
        private List <string> GenerateSource(GraphicsContext ctx, ShaderCompilerContext cctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException("ctx");
            }
            if (cctx == null)
            {
                throw new ArgumentNullException("cctx");
            }
            if (_SourceStrings == null)
            {
                throw new InvalidOperationException("no source loaded");
            }

            List <string> sourceLines = new List <string>();

            // Initial status: original
            AppendSourceStrings(sourceLines, _SourceStrings.ToArray());

            // Append imposed header - Every source shall compile with this header
            int headerLine = 0;

            if (ctx.ShadingVersion.Api == KhronosVersion.ApiGlsl)
            {
                // Automatically prepend required shader version, if necessary
                if (sourceLines.Count > 0 && !Regex.IsMatch(sourceLines[0], @"\s*#version \d+.*"))
                {
                    int version = cctx.ShaderVersion.VersionId;

                    if (version >= 150)
                    {
                        // Starting from GLSL 1.50, profiles are implemented

                        if ((ctx.Flags & GraphicsContextFlags.ForwardCompatible) != 0)
                        {
                            sourceLines.Insert(headerLine++, $"#version {version} core\n");
                        }
                        else
                        {
                            sourceLines.Insert(headerLine++, $"#version {version} compatibility\n");
                        }
                    }
                    else
                    {
                        sourceLines.Insert(headerLine++, $"#version {version}\n");
                    }
                }
                else
                {
                    headerLine++;                               // #version already specified by implementor
                }
                // #extension
                if (ctx.Extensions.ShadingLanguageInclude_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_shading_language_include : require\n");
                }

                if (ctx.Extensions.UniformBufferObject_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_uniform_buffer_object : enable\n");
                }
                else
                {
                    sourceLines.Insert(headerLine++, "#define DISABLE_GL_ARB_uniform_buffer_object\n");
                }

                if (ObjectStage == ShaderType.GeometryShader && ctx.Extensions.GeometryShader4_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_geometry_shader4 : enable\n");
                }

                if (ctx.Extensions.ShaderDrawParameters_ARB)
                {
                    sourceLines.Insert(headerLine++, "#extension GL_ARB_shader_draw_parameters : enable\n");
                }

                foreach (ShaderExtension shaderExtension in cctx.Extensions)
                {
                    // Do not include any #extension directive on extensions not supported by driver
                    if (ctx.Extensions.HasExtensions(shaderExtension.Name) == false)
                    {
                        continue;
                    }
                    sourceLines.Insert(headerLine++, $"#extension {shaderExtension.Name} : {shaderExtension.Behavior.ToString().ToLowerInvariant()}\n");
                }

                // #pragma
#if DEBUG
                // Debug directives
                sourceLines.Insert(headerLine++, "#pragma optimization(off)\n");
                sourceLines.Insert(headerLine++, "#pragma debug(on)\n");
#else
                sourceLines.Insert(headerLine++, "#pragma optimization(on)\n");
                sourceLines.Insert(headerLine++, "#pragma debug(off)\n");
#endif
            }
            else
            {
                switch (ObjectStage)
                {
                case ShaderType.FragmentShader:
                    sourceLines.Insert(headerLine++, "precision mediump float;\n");
                    break;
                }
            }

            // Append required #define statments
            if (cctx.Defines != null)
            {
                foreach (string def in cctx.Defines)
                {
                    sourceLines.Insert(headerLine++, $"#define {def} 1\n");
                    Log("  Symbol: {0}", def);
                }
            }

            // Remove comment lines
            sourceLines = CleanSource(sourceLines);

            // Preprocessing
            // Manage #include preprocessor directives in the case GL_ARB_shading_language_include is not supported
            // When #include are replaced, conditionals are processed too
            if (!ctx.Extensions.ShadingLanguageInclude_ARB)
            {
                sourceLines = ShaderPreprocessor.Process(sourceLines, cctx, ctx.IncludeLibrary, ShaderPreprocessor.Stage.All);
                sourceLines = CleanSource(sourceLines);
            }

            return(sourceLines);
        }