Ejemplo n.º 1
0
 void INativeShaderPart.LoadSource(string sourceCode, Resources.ShaderType type)
 {
 }
Ejemplo n.º 2
0
        void INativeShaderProgram.LoadProgram(IEnumerable <INativeShaderPart> shaderParts, IEnumerable <ShaderFieldInfo> shaderFields)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            // Verify that we have exactly one shader part for each stage.
            // Other scenarios are valid in desktop GL, but not GL ES, so
            // we'll enforce the stricter rules manually to ease portability.
            int vertexCount   = 0;
            int fragmentCount = 0;

            foreach (INativeShaderPart part in shaderParts)
            {
                Resources.ShaderType type = (part as NativeShaderPart).Type;
                if (type == Resources.ShaderType.Fragment)
                {
                    fragmentCount++;
                }
                else if (type == Resources.ShaderType.Vertex)
                {
                    vertexCount++;
                }
            }
            if (vertexCount == 0)
            {
                throw new ArgumentException("Cannot load program without vertex shader.");
            }
            if (fragmentCount == 0)
            {
                throw new ArgumentException("Cannot load program without fragment shader.");
            }
            if (vertexCount > 1)
            {
                throw new ArgumentException("Cannot attach multiple vertex shaders to the same program.");
            }
            if (fragmentCount > 1)
            {
                throw new ArgumentException("Cannot attach multiple fragment shaders to the same program.");
            }

            // Create or reset GL program
            if (this.handle == 0)
            {
                this.handle = GL.CreateProgram();
            }
            else
            {
                this.DetachShaders();
            }

            // Attach all individual shaders to the program
            foreach (INativeShaderPart part in shaderParts)
            {
                GL.AttachShader(this.handle, (part as NativeShaderPart).Handle);
            }

            // Link the shader program
            GL.LinkProgram(this.handle);

            int result;

            GL.GetProgram(this.handle, GetProgramParameterName.LinkStatus, out result);
            if (result == 0)
            {
                string errorLog = GL.GetProgramInfoLog(this.handle);
                this.RollbackAtFault();
                throw new BackendException(string.Format("Linker error:{1}{0}", errorLog, Environment.NewLine));
            }

            // Collect variables that are available through shader reflection, e.g.
            // haven't been optimized of #ifdef'd away.
            List <int>             validLocations = new List <int>();
            List <ShaderFieldInfo> validFields    = new List <ShaderFieldInfo>();

            foreach (ShaderFieldInfo field in shaderFields)
            {
                int location;
                if (field.Scope == ShaderFieldScope.Uniform)
                {
                    location = GL.GetUniformLocation(this.handle, field.Name);
                }
                else
                {
                    location = GL.GetAttribLocation(this.handle, field.Name);
                }

                if (location >= 0)
                {
                    validLocations.Add(location);
                    validFields.Add(field);
                }
            }

            this.fields         = validFields.ToArray();
            this.fieldLocations = validLocations.ToArray();
        }