Example #1
0
        public static void Bind(NativeTexture tex, int texUnit = 0)
        {
            if (!texInit)
            {
                InitTextureFields();
            }

            if (curBound[texUnit] == tex)
            {
                return;
            }
            if (activeTexUnit != texUnit)
            {
                GL.ActiveTexture(texUnits[texUnit]);
            }
            activeTexUnit = texUnit;

            if (tex == null)
            {
                GL.BindTexture(TextureTarget.Texture2D, 0);
                GL.Disable(EnableCap.Texture2D);
                curBound[texUnit] = null;
            }
            else
            {
                GL.Enable(EnableCap.Texture2D);
                GL.BindTexture(TextureTarget.Texture2D, tex.Handle);
                curBound[texUnit] = tex;
            }
        }
Example #2
0
        private void SetupNonMultisampled()
        {
            // Generate FBO
            if (this.handleMainFBO == 0)
            {
                GL.Ext.GenFramebuffers(1, out this.handleMainFBO);
            }
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.handleMainFBO);

            // Attach textures
            int oglWidth  = 0;
            int oglHeight = 0;

            for (int i = 0; i < this.targetInfos.Count; i++)
            {
                NativeTexture tex = this.targetInfos[i].Target;

                FramebufferAttachment attachment = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                GL.Ext.FramebufferTexture2D(
                    FramebufferTarget.FramebufferExt,
                    attachment,
                    TextureTarget.Texture2D,
                    tex.Handle,
                    0);
                oglWidth  = tex.Width;
                oglHeight = tex.Height;
            }

            // Generate or delete depth renderbuffer
            if (this.depthBuffer)
            {
                if (this.handleDepthRBO == 0)
                {
                    GL.Ext.GenRenderbuffers(1, out this.handleDepthRBO);
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);
                GL.Ext.RenderbufferStorage(RenderbufferTarget.RenderbufferExt, RenderbufferStorage.DepthComponent24, oglWidth, oglHeight);
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);
            }
            else
            {
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, 0);
                if (this.handleDepthRBO != 0)
                {
                    GL.Ext.DeleteRenderbuffers(1, ref this.handleDepthRBO);
                }
                this.handleDepthRBO = 0;
            }

            // Check status
            FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);

            if (status != FramebufferErrorCode.FramebufferCompleteExt)
            {
                throw new BackendException(string.Format("Incomplete Framebuffer: {0}", status));
            }

            GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
        }
Example #3
0
        private void FinishMaterial(BatchInfo material)
        {
            DrawTechnique tech = material.Technique.Res;

            this.SetupBlendType(BlendMode.Reset);
            NativeShaderProgram.Bind(null as NativeShaderProgram);
            NativeTexture.ResetBinding();
        }
Example #4
0
        private void FinishMaterial(BatchInfo material)
        {
            DrawTechnique tech = material.Technique.Res;

            this.FinishBlendState();
            NativeShaderProgram.Bind(null);
            NativeTexture.ResetBinding(this.sharedSamplerBindings);
        }
Example #5
0
        private void FinishSharedParameters()
        {
            NativeTexture.ResetBinding();

            this.sharedSamplerBindings = 0;
            this.sharedShaderParameters.Clear();
            this.activeShaders.Clear();
        }
Example #6
0
        /// <summary>
        /// Applies the specified parameter values to all currently active shaders.
        /// </summary>
        /// <param name="sharedParams"></param>
        /// <seealso cref="RetrieveActiveShaders"/>
        private void SetupSharedParameters(ShaderParameterCollection sharedParams)
        {
            this.sharedSamplerBindings = 0;
            this.sharedShaderParameters.Clear();
            if (sharedParams == null)
            {
                return;
            }

            foreach (NativeShaderProgram shader in this.activeShaders)
            {
                NativeShaderProgram.Bind(shader);

                ShaderFieldInfo[] varInfo   = shader.Fields;
                int[]             locations = shader.FieldLocations;

                // Setup shared sampler bindings and uniform data
                for (int i = 0; i < varInfo.Length; i++)
                {
                    ShaderFieldInfo field    = varInfo[i];
                    int             location = locations[i];

                    if (field.Scope == ShaderFieldScope.Attribute)
                    {
                        continue;
                    }
                    if (field.Type == ShaderFieldType.Sampler2D)
                    {
                        ContentRef <Texture> texRef;
                        if (!sharedParams.TryGetInternal(field.Name, out texRef))
                        {
                            continue;
                        }

                        NativeTexture.Bind(texRef, this.sharedSamplerBindings);
                        GL.Uniform1(location, this.sharedSamplerBindings);

                        this.sharedSamplerBindings++;
                    }
                    else
                    {
                        float[] data;
                        if (!sharedParams.TryGetInternal(field.Name, out data))
                        {
                            continue;
                        }

                        NativeShaderProgram.SetUniform(field, location, data);
                    }

                    this.sharedShaderParameters.Add(field.Name);
                }
            }

            NativeShaderProgram.Bind(null);
        }
Example #7
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();
                }
            }
        }
Example #8
0
        void INativeRenderTarget.Setup(IReadOnlyList <INativeTexture> targets, AAQuality multisample)
        {
            DefaultOpenTKBackendPlugin.GuardSingleThreadState();

            if (targets == null)
            {
                return;
            }
            if (targets.Count == 0)
            {
                return;
            }
            if (targets.All(i => i == null))
            {
                return;
            }

            int highestAALevel = MathF.RoundToInt(MathF.Log(MathF.Max(MaxRenderTargetSamples, 1.0f), 2.0f));
            int targetAALevel  = highestAALevel;

            switch (multisample)
            {
            case AAQuality.High:    targetAALevel = highestAALevel;         break;

            case AAQuality.Medium:  targetAALevel = highestAALevel / 2; break;

            case AAQuality.Low:             targetAALevel = highestAALevel / 4; break;

            case AAQuality.Off:             targetAALevel = 0;                                      break;
            }
            int          targetSampleCount = MathF.RoundToInt(MathF.Pow(2.0f, targetAALevel));
            GraphicsMode sampleMode        =
                GraphicsBackend.ActiveInstance.AvailableGraphicsModes.LastOrDefault(m => m.Samples <= targetSampleCount) ??
                GraphicsBackend.ActiveInstance.AvailableGraphicsModes.Last();

            this.samples = sampleMode.Samples;

            // Synchronize target information
            {
                this.targetInfos.Reserve(targets.Count);
                int localIndex = 0;
                for (int i = 0; i < targets.Count; i++)
                {
                    if (targets[i] == null)
                    {
                        continue;
                    }

                    this.targetInfos.Count = Math.Max(this.targetInfos.Count, localIndex + 1);
                    this.targetInfos.Data[localIndex].Target = targets[i] as NativeTexture;

                    localIndex++;
                }
            }

            #region Setup FBO & RBO: Non-multisampled
            if (this.samples == 0)
            {
                // Generate FBO
                if (this.handleMainFBO == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.handleMainFBO);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.handleMainFBO);

                // Attach textures
                int oglWidth  = 0;
                int oglHeight = 0;
                for (int i = 0; i < this.targetInfos.Count; i++)
                {
                    NativeTexture tex = this.targetInfos[i].Target;

                    FramebufferAttachment attachment = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    GL.Ext.FramebufferTexture2D(
                        FramebufferTarget.FramebufferExt,
                        attachment,
                        TextureTarget.Texture2D,
                        tex.Handle,
                        0);
                    oglWidth  = tex.Width;
                    oglHeight = tex.Height;
                }

                // Generate Depth Renderbuffer
                if (this.handleDepthRBO == 0)
                {
                    GL.Ext.GenRenderbuffers(1, out this.handleDepthRBO);
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);
                GL.Ext.RenderbufferStorage(RenderbufferTarget.RenderbufferExt, RenderbufferStorage.DepthComponent24, oglWidth, oglHeight);
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);

                // Check status
                FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    throw new BackendException(string.Format("Incomplete Framebuffer: {0}", status));
                }

                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
            }
            #endregion

            #region Setup FBO & RBO: Multisampled
            if (this.samples > 0)
            {
                // Generate texture target FBO
                if (this.handleMainFBO == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.handleMainFBO);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.handleMainFBO);

                // Attach textures
                int oglWidth  = 0;
                int oglHeight = 0;
                for (int i = 0; i < this.targetInfos.Count; i++)
                {
                    NativeTexture tex = this.targetInfos[i].Target;

                    FramebufferAttachment attachment = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    GL.Ext.FramebufferTexture2D(
                        FramebufferTarget.FramebufferExt,
                        attachment,
                        TextureTarget.Texture2D,
                        tex.Handle,
                        0);
                    oglWidth  = tex.Width;
                    oglHeight = tex.Height;
                }

                // Check status
                FramebufferErrorCode status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    throw new BackendException(string.Format("Incomplete Framebuffer: {0}", status));
                }

                // Generate rendering FBO
                if (this.handleMsaaFBO == 0)
                {
                    GL.Ext.GenFramebuffers(1, out this.handleMsaaFBO);
                }
                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.handleMsaaFBO);

                // Attach color renderbuffers
                for (int i = 0; i < this.targetInfos.Count; i++)
                {
                    TargetInfo info = this.targetInfos.Data[i];

                    FramebufferAttachment attachment    = (FramebufferAttachment)((int)FramebufferAttachment.ColorAttachment0Ext + i);
                    RenderbufferStorage   rbColorFormat = TexFormatToRboFormat(info.Target.Format);

                    if (info.HandleMsaaColorRBO == 0)
                    {
                        GL.GenRenderbuffers(1, out info.HandleMsaaColorRBO);
                    }
                    GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, info.HandleMsaaColorRBO);
                    GL.Ext.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, this.samples, rbColorFormat, oglWidth, oglHeight);
                    GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, attachment, RenderbufferTarget.RenderbufferExt, info.HandleMsaaColorRBO);

                    this.targetInfos.Data[i] = info;
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);

                // Attach depth renderbuffer
                if (this.handleDepthRBO == 0)
                {
                    GL.Ext.GenRenderbuffers(1, out this.handleDepthRBO);
                }
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);
                GL.Ext.RenderbufferStorageMultisample(RenderbufferTarget.RenderbufferExt, this.samples, RenderbufferStorage.DepthComponent24, oglWidth, oglHeight);
                GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, this.handleDepthRBO);
                GL.Ext.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);

                // Check status
                status = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
                if (status != FramebufferErrorCode.FramebufferCompleteExt)
                {
                    throw new BackendException(string.Format("Incomplete Multisample Framebuffer: {0}", status));
                }

                GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
            }
            #endregion
        }
Example #9
0
        private void SetupMaterial(BatchInfo material, BatchInfo lastMaterial)
        {
            DrawTechnique tech     = material.Technique.Res ?? DrawTechnique.Solid.Res;
            DrawTechnique lastTech = lastMaterial != null ? lastMaterial.Technique.Res : null;

            // Setup BlendType
            if (lastTech == null || tech.Blending != lastTech.Blending)
            {
                this.SetupBlendState(tech.Blending);
            }

            // Bind Shader
            NativeShaderProgram nativeShader = tech.NativeShader as NativeShaderProgram;

            NativeShaderProgram.Bind(nativeShader);

            // Setup shader data
            ShaderFieldInfo[] varInfo   = nativeShader.Fields;
            int[]             locations = nativeShader.FieldLocations;

            // Setup sampler bindings and uniform data
            int curSamplerIndex = this.sharedSamplerBindings;

            for (int i = 0; i < varInfo.Length; i++)
            {
                ShaderFieldInfo field    = varInfo[i];
                int             location = locations[i];

                if (field.Scope == ShaderFieldScope.Attribute)
                {
                    continue;
                }
                if (this.sharedShaderParameters.Contains(field.Name))
                {
                    continue;
                }

                if (field.Type == ShaderFieldType.Sampler2D)
                {
                    ContentRef <Texture> texRef = material.GetInternalTexture(field.Name);
                    if (texRef == null)
                    {
                        this.internalShaderState.TryGetInternal(field.Name, out texRef);
                    }

                    NativeTexture.Bind(texRef, curSamplerIndex);
                    GL.Uniform1(location, curSamplerIndex);

                    curSamplerIndex++;
                }
                else
                {
                    float[] data = material.GetInternalData(field.Name);
                    if (data == null && !this.internalShaderState.TryGetInternal(field.Name, out data))
                    {
                        continue;
                    }

                    NativeShaderProgram.SetUniform(field, location, data);
                }
            }
            NativeTexture.ResetBinding(curSamplerIndex);
        }