/// <summary> /// Hacer blur de bright-pass para generar efecto de bloom /// </summary> /// <param name="d3dDevice"></param> private void bloomPass(Device d3dDevice) { d3dDevice.BeginScene(); //Gaussian blur horizontal Vector2[] texCoordOffsets; float[] colorWeights; Surface bloomTempS = bloomTempRT.GetSurfaceLevel(0); TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(bloomTempS.Description.Width, 1, 1, true, out texCoordOffsets, out colorWeights); effect.Technique = "BloomPass"; effect.SetValue("texBloomRT", brightPassRT); d3dDevice.SetRenderTarget(0, bloomTempS); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); //Gaussian blur vertical TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(bloomTempS.Description.Height, 1, 1, false, out texCoordOffsets, out colorWeights); effect.Technique = "BloomPass"; effect.SetValue("texBloomRT", bloomTempRT); effect.SetValue("gauss_offsets", TgcParserUtils.vector2ArrayToFloat2Array(texCoordOffsets)); effect.SetValue("gauss_weights", colorWeights); Surface bloomS = bloomRT.GetSurfaceLevel(0); d3dDevice.SetRenderTarget(0, bloomS); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); bloomTempS.Dispose(); bloomS.Dispose(); d3dDevice.EndScene(); }
/// <summary> /// Se toma todo lo dibujado antes, que se guardo en una textura, y se le aplica un shader para borronear la imagen /// </summary> private void drawPostProcess(Device d3dDevice) { //Arrancamos la escena d3dDevice.BeginScene(); //Ver si el efecto de oscurecer esta activado, configurar Technique del shader segun corresponda bool activar_efecto = (bool)GuiController.Instance.Modifiers["activar_efecto"]; //Hacer blur if (activar_efecto) { float deviation = (float)GuiController.Instance.Modifiers["deviation"]; Surface blurTempS = blurTempRT.GetSurfaceLevel(0); //Gaussian blur horizontal Vector2[] texCoordOffsets; float[] colorWeights; TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(blurTempS.Description.Width, deviation, 1, true, out texCoordOffsets, out colorWeights); effect.Technique = "GaussianBlurPass"; effect.SetValue("texSceneRT", sceneRT); effect.SetValue("gauss_offsets", TgcParserUtils.vector2ArrayToFloat2Array(texCoordOffsets)); effect.SetValue("gauss_weights", colorWeights); d3dDevice.SetRenderTarget(0, blurTempS); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); //Gaussian blur vertical TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(blurTempS.Description.Height, deviation, 1, false, out texCoordOffsets, out colorWeights); effect.Technique = "GaussianBlurPass"; effect.SetValue("texSceneRT", blurTempRT); effect.SetValue("gauss_offsets", TgcParserUtils.vector2ArrayToFloat2Array(texCoordOffsets)); effect.SetValue("gauss_weights", colorWeights); d3dDevice.SetRenderTarget(0, pOldRT); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); blurTempS.Dispose(); } //No hacer blur else { effect.Technique = "DefaultTechnique"; effect.SetValue("texSceneRT", sceneRT); d3dDevice.SetRenderTarget(0, pOldRT); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); } //Como estamos en modo CustomRenderEnabled, tenemos que dibujar todo nosotros, incluso el contador de FPS GuiController.Instance.Text3d.drawText("FPS: " + HighResolutionTimer.Instance.FramesPerSecond, 0, 0, Color.Yellow); //Tambien hay que dibujar el indicador de los ejes cartesianos GuiController.Instance.AxisLines.render(); //Terminamos el renderizado de la escena d3dDevice.EndScene(); }
/// <summary> /// Se toma todo lo dibujado antes, que se guardo en una textura, y se le aplica un shader para borronear la imagen /// </summary> private void drawPostProcess(Device d3dDevice) { //Arrancamos la escena d3dDevice.BeginScene(); //Ver si el efecto de oscurecer esta activado, configurar Technique del shader segun corresponda var activar_efecto = (bool)Modifiers["activar_efecto"]; //Hacer blur if (activar_efecto) { var deviation = (float)Modifiers["deviation"]; var blurTempS = blurTempRT.GetSurfaceLevel(0); //Gaussian blur horizontal Vector2[] texCoordOffsets; float[] colorWeights; TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(blurTempS.Description.Width, deviation, 1, true, out texCoordOffsets, out colorWeights); effect.Technique = "GaussianBlurPass"; effect.SetValue("texSceneRT", sceneRT); effect.SetValue("gauss_offsets", TgcParserUtils.vector2ArrayToFloat2Array(texCoordOffsets)); effect.SetValue("gauss_weights", colorWeights); d3dDevice.SetRenderTarget(0, blurTempS); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); //Gaussian blur vertical TgcPostProcessingUtils.computeGaussianBlurSampleOffsets15(blurTempS.Description.Height, deviation, 1, false, out texCoordOffsets, out colorWeights); effect.Technique = "GaussianBlurPass"; effect.SetValue("texSceneRT", blurTempRT); effect.SetValue("gauss_offsets", TgcParserUtils.vector2ArrayToFloat2Array(texCoordOffsets)); effect.SetValue("gauss_weights", colorWeights); d3dDevice.SetRenderTarget(0, pOldRT); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); blurTempS.Dispose(); } //No hacer blur else { effect.Technique = "DefaultTechnique"; effect.SetValue("texSceneRT", sceneRT); d3dDevice.SetRenderTarget(0, pOldRT); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); } //Terminamos el renderizado de la escena RenderFPS(); RenderAxis(); d3dDevice.EndScene(); d3dDevice.Present(); }
/// <summary> /// Generar imagen reducida del RT de HDR original de la escena. /// Lo reducimos a una textura de 1/4 x 1/4 de la original. /// El shader lee 4x4 texels y los promedia /// </summary> private void scaleScene(Device d3dDevice) { d3dDevice.BeginScene(); var backBufferWidth = d3dDevice.PresentationParameters.BackBufferWidth; var backBufferHeight = d3dDevice.PresentationParameters.BackBufferHeight; var sampleOffsets = TgcPostProcessingUtils.computeDownScaleOffsets4x4(backBufferWidth, backBufferHeight); effect.Technique = "DownScale4x4"; effect.SetValue("texSceneRT", sceneRT); effect.SetValue("sampleOffsets", TgcParserUtils.vector2ArrayToFloat2Array(sampleOffsets)); var scaledSceneS = scaledSceneRT.GetSurfaceLevel(0); d3dDevice.SetRenderTarget(0, scaledSceneS); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); d3dDevice.EndScene(); scaledSceneS.Dispose(); }
/// <summary> /// Recorremos toda la imagen de scaledSceneRT y buscamos el pixel con el maximo nivel de luminosidad. /// Lo hacemos en GPU, con varias pasadas de downsampling, hasta llegar a una textura de 1x1. /// </summary> private void findAverageLuminance(Device d3dDevice) { d3dDevice.BeginScene(); //Obtener surfaces de todos los luminanceRTs Surface[] luminanceSurfaces = new Surface[luminanceRTs.Length]; for (int i = 0; i < luminanceRTs.Length; i++) { luminanceSurfaces[i] = luminanceRTs[i].GetSurfaceLevel(0); } int curTexture = luminanceRTs.Length - 1; int surfWidth = luminanceSurfaces[curTexture].Description.Width; int surfHeight = luminanceSurfaces[curTexture].Description.Height; //Calcular los offsets de la primera pasada de downsampling de luminance float tU, tV; tU = 1.0f / (3.0f * surfWidth); tV = 1.0f / (3.0f * surfHeight); int x, y; int index = 0; Vector2[] sampleOffsets = new Vector2[16]; for (x = -1; x <= 1; x++) { for (y = -1; y <= 1; y++) { sampleOffsets[index] = new Vector2(x * tU, y * tV); index++; } } //Primera pasada de luminance: calculamos el promedio de log(luminance) de 4x4 effect.Technique = "SampleAvgLuminance_Init"; effect.SetValue("texSceneRT", scaledSceneRT); effect.SetValue("sampleOffsets", TgcParserUtils.vector2ArrayToFloat2Array(sampleOffsets)); d3dDevice.SetRenderTarget(0, luminanceSurfaces[curTexture]); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); curTexture--; //DEBUG //TextureLoader.Save(GuiController.Instance.ExamplesMediaDir + "Shaders\\luminance_" + (curTexture+1) + ".bmp", ImageFileFormat.Bmp, luminanceRTs[curTexture + 1]); //Hacer pasadas de downsampling intermedio while (curTexture > 0) { //Calcular offsets de esta pasada de downsampling surfWidth = luminanceSurfaces[curTexture].Description.Width; surfHeight = luminanceSurfaces[curTexture].Description.Height; sampleOffsets = TgcPostProcessingUtils.computeDownScaleOffsets4x4(surfWidth, surfHeight); //Hacer downsampling effect.Technique = "SampleAvgLuminance_Intermediate"; effect.SetValue("texSceneRT", luminanceRTs[curTexture + 1]); effect.SetValue("sampleOffsets", TgcParserUtils.vector2ArrayToFloat2Array(sampleOffsets)); d3dDevice.SetRenderTarget(0, luminanceSurfaces[curTexture]); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); curTexture--; //DEBUG //TextureLoader.Save(GuiController.Instance.ExamplesMediaDir + "Shaders\\luminance_" + (curTexture+1) + ".bmp", ImageFileFormat.Bmp, luminanceRTs[curTexture + 1]); } //Hacer downsampling final de 1x1 surfWidth = luminanceSurfaces[1].Description.Width; surfHeight = luminanceSurfaces[1].Description.Height; sampleOffsets = TgcPostProcessingUtils.computeDownScaleOffsets4x4(surfWidth, surfHeight); //Esta ultima pasada hace un promedio de 4x4 y luego hace exp para quitar el log y obtener el promedio de luminance de toda la escena effect.Technique = "SampleAvgLuminance_End"; effect.SetValue("texSceneRT", luminanceRTs[1]); effect.SetValue("sampleOffsets", TgcParserUtils.vector2ArrayToFloat2Array(sampleOffsets)); d3dDevice.SetRenderTarget(0, luminanceSurfaces[0]); d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); screenQuad.render(effect); //DEBUG //TextureLoader.Save(GuiController.Instance.ExamplesMediaDir + "Shaders\\luminance_" + 0 + ".bmp", ImageFileFormat.Bmp, luminanceRTs[0]); //Liberar todos los surfaces usados for (int i = 0; i < luminanceSurfaces.Length; i++) { luminanceSurfaces[i].Dispose(); } d3dDevice.EndScene(); }