Ejemplo n.º 1
0
        private void SetupMaterial(BatchInfo material, BatchInfo lastMaterial)
        {
            if (material == lastMaterial)
            {
                return;
            }
            DrawTechnique tech     = material.Technique.Res ?? DrawTechnique.Solid.Res;
            DrawTechnique lastTech = lastMaterial != null ? lastMaterial.Technique.Res : null;

            // Prepare Rendering
            if (tech.NeedsPreparation)
            {
                material = new BatchInfo(material);
                tech.PrepareRendering(this.currentDevice, material);
            }

            // Setup BlendType
            if (lastTech == null || tech.Blending != lastTech.Blending)
            {
                this.SetupBlendType(tech.Blending, this.currentDevice.DepthWrite);
            }

            // Bind Shader
            NativeShaderProgram shader = (tech.Shader.Res != null ? tech.Shader.Res.Native : null) as NativeShaderProgram;

            NativeShaderProgram.Bind(shader);

            // Setup shader data
            if (shader != null)
            {
                ShaderFieldInfo[] varInfo        = shader.Fields;
                int[]             locations      = shader.FieldLocations;
                int[]             builtinIndices = shader.BuiltinVariableIndex;

                // Setup sampler bindings automatically
                int curSamplerIndex = 0;
                if (material.Textures != null)
                {
                    for (int i = 0; i < varInfo.Length; i++)
                    {
                        if (locations[i] == -1)
                        {
                            continue;
                        }
                        if (varInfo[i].Type != ShaderFieldType.Sampler2D)
                        {
                            continue;
                        }

                        // Bind Texture
                        ContentRef <Texture> texRef = material.GetTexture(varInfo[i].Name);
                        NativeTexture.Bind(texRef, curSamplerIndex);
                        GL.Uniform1(locations[i], curSamplerIndex);

                        curSamplerIndex++;
                    }
                }
                NativeTexture.ResetBinding(curSamplerIndex);

                // Transfer uniform data from material to actual shader
                if (material.Uniforms != null)
                {
                    for (int i = 0; i < varInfo.Length; i++)
                    {
                        if (locations[i] == -1)
                        {
                            continue;
                        }
                        float[] data = material.GetUniform(varInfo[i].Name);
                        if (data == null)
                        {
                            continue;
                        }

                        NativeShaderProgram.SetUniform(ref varInfo[i], locations[i], data);
                    }
                }

                // Specify builtin shader variables, if requested
                float[] fieldValue = null;
                for (int i = 0; i < builtinIndices.Length; i++)
                {
                    if (BuiltinShaderFields.TryGetValue(this.currentDevice, builtinIndices[i], ref fieldValue))
                    {
                        NativeShaderProgram.SetUniform(ref varInfo[i], locations[i], fieldValue);
                    }
                }
            }
            // Setup fixed function data
            else
            {
                // Fixed function texture binding
                if (material.Textures != null)
                {
                    int samplerIndex = 0;
                    foreach (var pair in material.Textures)
                    {
                        NativeTexture.Bind(pair.Value, samplerIndex);
                        samplerIndex++;
                    }
                    NativeTexture.ResetBinding(samplerIndex);
                }
                else
                {
                    NativeTexture.ResetBinding();
                }
            }
        }
Ejemplo n.º 2
0
        void INativeShaderProgram.LoadProgram(INativeShaderPart vertex, INativeShaderPart fragment)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (this.handle == 0)
            {
                this.handle = GL.CreateProgram();
            }
            else
            {
                this.DetachShaders();
            }

            // Attach both shaders
            if (vertex != null)
            {
                GL.AttachShader(this.handle, (vertex as NativeShaderPart).Handle);
            }
            if (fragment != null)
            {
                GL.AttachShader(this.handle, (fragment 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 variable infos from sub programs
            {
                NativeShaderPart vert = vertex as NativeShaderPart;
                NativeShaderPart frag = fragment as NativeShaderPart;

                ShaderFieldInfo[] fragVarArray = frag != null ? frag.Fields : null;
                ShaderFieldInfo[] vertVarArray = vert != null ? vert.Fields : null;

                if (fragVarArray != null && vertVarArray != null)
                {
                    this.fields = vertVarArray.Union(fragVarArray).ToArray();
                }
                else if (vertVarArray != null)
                {
                    this.fields = vertVarArray.ToArray();
                }
                else
                {
                    this.fields = fragVarArray.ToArray();
                }
            }

            // Determine each variables location
            this.fieldLocations = new int[this.fields.Length];
            for (int i = 0; i < this.fields.Length; i++)
            {
                if (this.fields[i].Scope == ShaderFieldScope.Uniform)
                {
                    this.fieldLocations[i] = GL.GetUniformLocation(this.handle, this.fields[i].Name);
                }
                else
                {
                    this.fieldLocations[i] = GL.GetAttribLocation(this.handle, this.fields[i].Name);
                }
            }

            // Determine whether we're using builtin shader variables
            this.builtinIndex = new int[this.fields.Length];
            bool anyBuildinUsed = false;

            for (int i = 0; i < this.fields.Length; i++)
            {
                if (this.fields[i].Scope == ShaderFieldScope.Uniform)
                {
                    this.builtinIndex[i] = BuiltinShaderFields.GetIndex(this.fields[i].Name);
                    if (this.builtinIndex[i] != BuiltinShaderFields.InvalidIndex)
                    {
                        anyBuildinUsed = true;
                    }
                }
                else
                {
                    this.builtinIndex[i] = BuiltinShaderFields.InvalidIndex;
                }
            }
            if (!anyBuildinUsed)
            {
                this.builtinIndex = new int[0];
            }
        }