private void CompileIfNecessary(ref ShaderFragment fragment, string header, string @class, ShaderType type) { // No compilation needed if (fragment != null) { return; } string typeName = GetShaderName(type); ShaderPart source = null; foreach (var sp in this.parts) { if (sp.type != typeName) { continue; } if (sp.className != @class) { continue; } source = sp; break; } if (source == null) { // Search for default shader foreach (var sp in this.parts) { if (sp.type != typeName) { continue; } if (sp.className != null) { continue; } source = sp; break; } } if (source == null) { return; // No source found, no shader available } string input = ""; input = GetInput(source.properties["input"]); fragment = new ShaderFragment(type, header + input + source.source); }
void cache_Miss(object sender, ShaderCacheMissEventArgs e) { if (e.ResultShader != null) { return; } ShaderFragment vertexShader = e.Fragments.FirstOrDefault((s) => s.Type == ShaderType.VertexShader); ShaderFragment tessCtrlShader = e.Fragments.FirstOrDefault((s) => s.Type == ShaderType.TessControlShader); ShaderFragment tessEvalShader = e.Fragments.FirstOrDefault((s) => s.Type == ShaderType.TessEvaluationShader); ShaderFragment geometryShader = e.Fragments.FirstOrDefault((s) => s.Type == ShaderType.GeometryShader); ShaderFragment fragmentShader = e.Fragments.FirstOrDefault((s) => s.Type == ShaderType.FragmentShader); string header = "#version " + this.version + "\n"; foreach (var include in this.includes) { header += include.Value + "\n"; } foreach (var sp in this.parts) { if (sp.type == "global" && (sp.className == null || sp.className == e.ShaderClass)) { header += sp.source + "\n"; } } CompileIfNecessary(ref vertexShader, header, e.ShaderClass, ShaderType.VertexShader); CompileIfNecessary(ref tessCtrlShader, header, e.ShaderClass, ShaderType.TessControlShader); CompileIfNecessary(ref tessEvalShader, header, e.ShaderClass, ShaderType.TessEvaluationShader); CompileIfNecessary(ref geometryShader, header, e.ShaderClass, ShaderType.GeometryShader); CompileIfNecessary(ref fragmentShader, header, e.ShaderClass, ShaderType.FragmentShader); int program = GL.CreateProgram(); if (vertexShader != null) { GL.AttachShader(program, vertexShader.Id); } if (tessCtrlShader != null) { GL.AttachShader(program, tessCtrlShader.Id); } if (tessEvalShader != null) { GL.AttachShader(program, tessEvalShader.Id); } if (geometryShader != null) { GL.AttachShader(program, geometryShader.Id); } if (fragmentShader != null) { GL.AttachShader(program, fragmentShader.Id); } GL.LinkProgram(program); int result; GL.GetProgram(program, GetProgramParameterName.LinkStatus, out result); string infoLog = GL.GetProgramInfoLog(program); if (result == 0) { Log.WriteLine(LocalizedStrings.ShaderLinkerFailed); if (!string.IsNullOrWhiteSpace(infoLog)) { Log.WriteLine(infoLog); } GL.DeleteProgram(program); return; } else { if (!string.IsNullOrWhiteSpace(infoLog)) { Log.WriteLine(LocalizedStrings.ShaderLinkerResult); Log.WriteLine(infoLog); } } e.ResultShader = new CompiledShader(this, program); }
/// <summary> /// Creates a new deferred renderer. /// </summary> /// <param name="width">Width of the render targets.</param> /// <param name="height">Height of the render targets.</param> public DeferredRenderer(int width, int height) { this.lightCube = Model.CreateCube(1.1f); this.Width = width; this.Height = height; // Create graphics buffer this.PositionBuffer = CreateTexture(width, height); this.NormalBuffer = CreateTexture(width, height); this.DiffuseLightBuffer = CreateTexture(width, height); this.SpecularLightBuffer = CreateTexture(width, height); this.sceneBuffer = CreateTexture(width, height); // Create 3d shaders this.geometryPixelShader = new ShaderFragment(ShaderType.FragmentShader); this.geometryPixelShader.Compile( @"#version 410 core uniform sampler2D meshNormalMap; uniform sampler2D meshDiffuseTexture; uniform float mtlSpecularPower; in vec3 position; in vec3 normal; in vec3 tangent; in vec3 bitangent; in vec2 uv; layout(location = 0) out vec4 positionOut; layout(location = 1) out vec4 normalOut; void main() { if(texture(meshDiffuseTexture, uv).a < 0.5f) discard; positionOut = vec4(position, 1); vec3 bump = normalize(2.0f * texture(meshNormalMap, uv).xyz - 1.0f); normalOut.xyz = mat3(tangent, bitangent, normal) * bump; normalOut.w = mtlSpecularPower; //normalOut.xyz = normal; }"); this.lightShader = new LightShader(); // Create post processing shaders this.gammaCorrectionShader = new GammaCorrectionShader(); this.gammaCorrectionShader.Gamma = 2.2f; this.lightScatteringShader = new LightScatteringShader(); this.lightScatteringShader.OcclusionBuffer = this.NormalBuffer; this.ditheringShader = new DitheringShader(); this.tonemappingShader = new TonemappingShader(); this.tonemappingShader.HdrExposure = 1.25f; this.tonemappingShader.WhitePoint = 5.0f; this.blurShader = new BlurShader(); this.blurShader.BlurStrength = new Vector2(0.04f, 0.04f); this.bloomCombineShader = new CombineShader(); this.highPassShader = new HighPassShader(); this.highPassShader.BloomThreshold = 0.95f; // Create post processing stages this.preBloomStages = new PostProcessingStage(this.lightScatteringShader) { TargetTexture = CreateTexture(width, height), Stage = new PostProcessingStage(this.gammaCorrectionShader) { TargetTexture = CreateTexture(width, height) } }; this.bloomStages = new PostProcessingStage(this.highPassShader) { TargetTexture = CreateTexture(width, height), Stage = new PostProcessingStage(this.blurShader) { TargetTexture = CreateTexture(width / 2, height / 2), Stage = new PostProcessingStage(this.blurShader) { TargetTexture = CreateTexture(width / 2, height / 2), Stage = new PostProcessingStage(this.bloomCombineShader) { TargetTexture = CreateTexture(width, height), } } } }; this.postBloomStages = new PostProcessingStage(this.tonemappingShader) { TargetTexture = CreateTexture(width, height), Stage = new PostProcessingStage(this.ditheringShader) { TargetTexture = CreateTexture(width, height), } }; //this.tonemapping = new PostProcessingStage(this.tonemappingShader); //this.tonemapping.TargetTexture = CreateTexture(width, height); this.depthBuffer = new RenderBuffer(width, height); this.frameBufferGeometry = new FrameBuffer(this.depthBuffer, this.PositionBuffer, this.NormalBuffer); this.frameBufferClearDiffuse = new FrameBuffer(this.DiffuseLightBuffer); this.frameBufferClearSpecular = new FrameBuffer(this.SpecularLightBuffer); this.frameBufferLights = new FrameBuffer(this.depthBuffer, this.DiffuseLightBuffer, this.SpecularLightBuffer); this.frameBufferScene = new FrameBuffer(this.depthBuffer, this.sceneBuffer); this.DefaultShader = new ObjectShader(); }