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; } }
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); }
private void FinishMaterial(BatchInfo material) { DrawTechnique tech = material.Technique.Res; this.SetupBlendType(BlendMode.Reset); NativeShaderProgram.Bind(null as NativeShaderProgram); NativeTexture.ResetBinding(); }
private void FinishMaterial(BatchInfo material) { DrawTechnique tech = material.Technique.Res; this.FinishBlendState(); NativeShaderProgram.Bind(null); NativeTexture.ResetBinding(this.sharedSamplerBindings); }
private void FinishSharedParameters() { NativeTexture.ResetBinding(); this.sharedSamplerBindings = 0; this.sharedShaderParameters.Clear(); this.activeShaders.Clear(); }
/// <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); }
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(); } } }
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 }
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); }