diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/F1Circuit.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/F1Circuit.cs new file mode 100644 index 00000000..e0f4f78d --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/F1Circuit.cs @@ -0,0 +1,444 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.DirectX.Direct3D; +using System.Drawing; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.TgcSceneLoader; +using TgcViewer; +using TgcViewer.Utils; + +namespace Examples.Shaders.WorkshopShaders +{ + public class F1Circuit + { + VertexBuffer vb; + public Texture textura_piso; + public Texture textura_guardrail; + public Texture textura_cartel; + public int totalVertices; + public Vector3[] pt_ruta = new Vector3[500]; + public int cant_ptos_ruta; + public float M_PI = 3.14151f; + public float ancho_ruta = 200; + public float ancho_guarray = 3; + public float dh = 3; // alto de la pared + public float scaleXZ = 20; + public float scaleY = 15; + public bool en_ruta = false; + public float Hpiso; // Altura del piso en la Pos + public int pos_en_ruta; + public int cant_carteles; + public int pos_carteles; + + public TgcMesh []arbol = new TgcMesh[10]; + public int cant_arboles; + + + + public F1Circuit() + { + CrearRuta(); + + TgcSceneLoader loader = new TgcSceneLoader(); + + arbol[cant_arboles] = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\ArbolSelvatico\\ArbolSelvatico-TgcScene.xml").Meshes[0]; + cant_arboles++; + + arbol[cant_arboles] = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\Palmera3\\Palmera3-TgcScene.xml").Meshes[0]; + arbol[cant_arboles].Scale = new Vector3(2, 2, 2); + ++cant_arboles; + + arbol[cant_arboles] = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\Palmera2\\Palmera2-TgcScene.xml").Meshes[0]; + arbol[cant_arboles].Scale = new Vector3(1, 1, 1); + ++cant_arboles; + + arbol[cant_arboles] = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\Pino\\Pino-TgcScene.xml").Meshes[0]; + arbol[cant_arboles].Scale = new Vector3(4, 4, 4); + ++cant_arboles; + + + } + + + // Carga los ptos de la ruta + public int load_pt_ruta() + { + // Genero el path de la ruta + double dt = M_PI/64; + double t = 0; + double hasta = 2*M_PI; + int cant = 0; + float dw = 10000; + while(t + /// Carga la textura del terreno + /// + public void loadTextures() + { + //Dispose textura anterior, si habia + if (textura_piso != null && !textura_piso.Disposed) + { + textura_piso.Dispose(); + } + + Device d3dDevice = GuiController.Instance.D3dDevice; + + String MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + textura_piso = Texture.FromBitmap(d3dDevice, (Bitmap)Bitmap.FromFile(MyMediaDir + "f1\\piso2.png"), Usage.None, Pool.Managed); + textura_guardrail = Texture.FromBitmap(d3dDevice, (Bitmap)Bitmap.FromFile(MyMediaDir + "f1\\guardrail.png"), Usage.None, Pool.Managed); + textura_cartel = Texture.FromBitmap(d3dDevice, (Bitmap)Bitmap.FromFile(MyMediaDir + "f1\\cartel1.png"), Usage.None, Pool.Managed); + } + + + public void render(Effect effect) + { + Device device = GuiController.Instance.D3dDevice; + GuiController.Instance.Shaders.setShaderMatrixIdentity(effect); + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, vb, 0); + + // primero dibujo los objetos opacos: + // piso de la ruta + effect.SetValue("texDiffuseMap", textura_piso); + device.RenderState.AlphaBlendEnable = false; + int numPasses = effect.Begin(0); + for (int n = 0; n < numPasses; n++) + { + effect.BeginPass(n); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2 * (cant_ptos_ruta - 1)); + effect.EndPass(); + } + effect.End(); + + // vegetacion + if (pos_en_ruta != -1) + { + float[] K = new float[10]; + for (int i = 0; i < cant_arboles; ++i) + { + K[i] = 1; + arbol[i].Effect = effect; + arbol[i].Technique = "DefaultTechnique"; + } + + int[] P = new int[10]; + P[0] = 11; + P[1] = 7; + P[2] = 13; + P[3] = 5; + + + float dr = ancho_ruta / 2; + for (int i = 0; i < cant_ptos_ruta; ++i) + { + Vector3 dir = pt_ruta[i + 1] - pt_ruta[i]; + dir.Normalize(); + Vector3 n = Vector3.Cross(dir, new Vector3(0, 1, 0)); + Vector3 p0 = pt_ruta[i] - n * dr; + Vector3 p1 = pt_ruta[i] + n * dr; + + for (int j = 0; j < cant_arboles; ++j) + { + if (i % P[j] == 0) + { + Vector3 pos = pt_ruta[i] - n * 300 * K[j]; + pos.Y = 0; + arbol[j].Position = pos; + arbol[j].render(); + K[j] *= -1; + } + } + } + } + + // Ahora los objetos transparentes (el guarda rail, y los carteles) + // guarda rail + device.RenderState.AlphaBlendEnable = true; + GuiController.Instance.Shaders.setShaderMatrixIdentity(effect); + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, vb, 0); + effect.SetValue("texDiffuseMap", textura_guardrail); + numPasses = effect.Begin(0); + for (int n = 0; n < numPasses; n++) + { + effect.BeginPass(n); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 2 * cant_ptos_ruta, 2 * (cant_ptos_ruta - 1)); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 4 * cant_ptos_ruta, 2 * (cant_ptos_ruta - 1)); + effect.EndPass(); + } + effect.End(); + + // carteles + effect.SetValue("texDiffuseMap", textura_cartel); + numPasses = effect.Begin(0); + for (int n = 0; n < numPasses; n++) + { + effect.BeginPass(n); + for (int i = 0; i < cant_carteles; ++i) + device.DrawPrimitives(PrimitiveType.TriangleStrip, pos_carteles + 4 * i, 2); + effect.EndPass(); + } + effect.End(); + + } + + + + + public float updatePos(float x,float z) + { + // Verifico si el pto x,z esta cerca de la ruta + // busco todos los puntos de la ruta cercanos a Pos + float mdist = ancho_ruta/2 + ancho_guarray; + int aux_tramo = -1; + en_ruta = false; + int cant_p = 0; + int []ndx = new int[700]; + for(int i=0; i=-0.5 && d<=rm+0.5) + { + Vector2 rc = r0 + r*d; + float dist = (rc - p).Length(); + if(dist1) + k = 1; + float Hruta = pt_ruta[i].Y*(1-k) + pt_ruta[i+1].Y*k; + if(dist<=dr) + { + // esta en la ruta + en_ruta = true; + H = Hruta; + } + else + { + // esta en el guarray + en_ruta = false; + H = (1-(dist-dr)/ancho_guarray)*Hruta; + } + } + } + } + + // Actualizo el status + Hpiso = H; + pos_en_ruta = aux_tramo; + + return H ; + } + + + // se fue de la ruta, devuelve que posicion mas cercana en el centro de la ruta + public Vector3 que_pos_buena(float x, float z) + { + float mdist = 10000000000f; + int aux_tramo = -1; + float dr = ancho_ruta / 2; + float H = 0; + Vector2 p = new Vector2(x, z); + for (int i = 0; i < cant_ptos_ruta; ++i) + { + Vector2 r0 = new Vector2(pt_ruta[i].X, pt_ruta[i].Z); + Vector2 r1 = new Vector2(pt_ruta[i + 1].X, pt_ruta[i + 1].Z); + Vector2 r = r1 - r0; + float rm = r.Length(); + r.Normalize(); + float d = Vector2.Dot(p - r0, r); + // d ==0 , rm + + if (d >= -0.5 && d <= rm + 0.5) + { + Vector2 rc = r0 + r * d; + float dist = (rc - p).Length(); + if (dist < mdist) + { + aux_tramo = i; + mdist = dist; + } + } + } + + if(aux_tramo!=-1) + { + x = pt_ruta[aux_tramo].X; + z = pt_ruta[aux_tramo].Z; + } + + + return new Vector3(x, updatePos(x,z), z); + } + + + public void dispose() + { + if (vb != null) + { + vb.Dispose(); + } + if (textura_piso != null) + { + textura_piso.Dispose(); + } + if (textura_guardrail != null) + { + textura_guardrail.Dispose(); + } + if (textura_cartel != null) + { + textura_cartel.Dispose(); + } + + for (int i = 0; i < cant_arboles; ++i) + arbol[i].dispose(); + } + } +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/FullQuad.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/FullQuad.cs new file mode 100644 index 00000000..7304dd70 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/FullQuad.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Input; +using TgcViewer.Utils.Shaders; +using TgcViewer.Utils; + +namespace Examples.Shaders.WorkshopShaders +{ + + public class FullScreenQuad : TgcExample + { + string MyMediaDir; + string MyShaderDir; + List meshes; + Effect effect; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget; + VertexBuffer g_pVBV3D; + public float time; + + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-FullScreenQuad"; + } + + public override string getDescription() + { + return "full screen quad"; + } + + public override void init() + { + GuiController.Instance.CustomRenderEnabled = true; + time = 0; + + Device d3dDevice = GuiController.Instance.D3dDevice; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Cargamos un escenario + TgcSceneLoader loader = new TgcSceneLoader(); + TgcScene scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Scenes\\Deposito\\Deposito-TgcScene.xml"); + meshes = scene.Meshes; + + //Cargar Shader personalizado + string compilationErrors; + effect = Effect.FromFile(GuiController.Instance.D3dDevice, + GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\FullQuad.fx", + null, null, ShaderFlags.PreferFlowControl, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique dentro del shader + effect.Technique = "DefaultTechnique"; + + //Camara en primera personas + GuiController.Instance.FpsCamera.Enable = true; + GuiController.Instance.FpsCamera.setCamera(new Vector3(-182.3816f, 82.3252f, -811.9061f), new Vector3(-182.0957f, 82.3147f, -810.9479f)); + + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + GuiController.Instance.Modifiers.addBoolean("activar_efecto", "Activar efecto", true); + + } + + + public override void render(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + + time += elapsedTime; + bool activar_efecto = (bool)GuiController.Instance.Modifiers["activar_efecto"]; + + //Cargar variables de shader + + // dibujo la escena una textura + effect.Technique = "DefaultTechnique"; + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); + if (activar_efecto) + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + // Probar de comentar esta linea, para ver como se produce el fallo en el ztest + // por no soportar usualmente el multisampling en el render to texture. + if (activar_efecto) + device.DepthStencilSurface = g_pDepthStencil; + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + + //Dibujamos todos los meshes del escenario + foreach (TgcMesh m in meshes) + { + m.render(); + } + device.EndScene(); + pSurf.Dispose(); + + if (activar_efecto) + { + // restuaro el render target y el stencil + device.DepthStencilSurface = pOldDS; + device.SetRenderTarget(0, pOldRT); + + // dibujo el quad pp dicho : + device.BeginScene(); + effect.Technique = "PostProcess"; + effect.SetValue("time", time); + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + + GuiController.Instance.Text3d.drawText("FPS: " + HighResolutionTimer.Instance.FramesPerSecond, 0, 0, Color.Yellow); + device.EndScene(); + } + + } + + public override void close() + { + foreach (TgcMesh m in meshes) + { + m.dispose(); + } effect.Dispose(); + g_pRenderTarget.Dispose(); + g_pVBV3D.Dispose(); + g_pDepthStencil.Dispose(); + } + } + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/GaussianBlur.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/GaussianBlur.cs new file mode 100644 index 00000000..457beacd --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/GaussianBlur.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Input; +using TgcViewer.Utils.Shaders; +using TgcViewer.Utils; + +namespace Examples.Shaders.WorkshopShaders +{ + + public class GaussianBlur: TgcExample + { + string MyMediaDir; + string MyShaderDir; + List meshes; + Effect effect; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget, g_pRenderTarget4, g_pRenderTarget4Aux; + VertexBuffer g_pVBV3D; + + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-GaussianBlur"; + } + + public override string getDescription() + { + return "Gaussin blur filter"; + } + + public override void init() + { + GuiController.Instance.CustomRenderEnabled = true; + + Device d3dDevice = GuiController.Instance.D3dDevice; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Cargamos un escenario + TgcSceneLoader loader = new TgcSceneLoader(); + TgcScene scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Scenes\\Deposito\\Deposito-TgcScene.xml"); + meshes = scene.Meshes; + + //Cargar Shader personalizado + string compilationErrors; + effect = Effect.FromFile(GuiController.Instance.D3dDevice, + GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\GaussianBlur.fx", + null, null, ShaderFlags.PreferFlowControl, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique dentro del shader + effect.Technique = "DefaultTechnique"; + + //Camara en primera personas + GuiController.Instance.FpsCamera.Enable = true; + GuiController.Instance.FpsCamera.setCamera(new Vector3(-182.3816f, 82.3252f, -811.9061f), new Vector3(-182.0957f, 82.3147f, -810.9479f)); + + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + g_pRenderTarget4 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth/4 + , d3dDevice.PresentationParameters.BackBufferHeight/4, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + g_pRenderTarget4Aux = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth / 4 + , d3dDevice.PresentationParameters.BackBufferHeight / 4, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + GuiController.Instance.Modifiers.addBoolean("activar_efecto", "Activar efecto", true); + GuiController.Instance.Modifiers.addBoolean("separable", "Separable Blur", true); + GuiController.Instance.Modifiers.addInt("cant_pasadas", 1, 10, 1); + + } + + + public override void render(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + + + bool activar_efecto = (bool)GuiController.Instance.Modifiers["activar_efecto"]; + + //Cargar variables de shader + + // dibujo la escena una textura + effect.Technique = "DefaultTechnique"; + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); + if(activar_efecto) + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + // Probar de comentar esta linea, para ver como se produce el fallo en el ztest + // por no soportar usualmente el multisampling en el render to texture. + if (activar_efecto) + device.DepthStencilSurface = g_pDepthStencil; + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + + //Dibujamos todos los meshes del escenario + foreach (TgcMesh m in meshes) + { + m.render(); + } + device.EndScene(); + pSurf.Dispose(); + + if (activar_efecto) + { + bool separable = (bool)GuiController.Instance.Modifiers["separable"]; + int cant_pasadas = (int)GuiController.Instance.Modifiers["cant_pasadas"]; + + if (separable) + { + // 1er pasada: downfilter x 4 + // ----------------------------------------------------- + pSurf = g_pRenderTarget4.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + device.BeginScene(); + effect.Technique = "DownFilter4"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + pSurf.Dispose(); + device.EndScene(); + + // TextureLoader.Save("scene.bmp", ImageFileFormat.Bmp, g_pRenderTarget4); + device.DepthStencilSurface = pOldDS; + + // Pasadas de blur + for (int P = 0; P < cant_pasadas; ++P) + { + // Gaussian blur Horizontal + // ----------------------------------------------------- + pSurf = g_pRenderTarget4Aux.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // dibujo el quad pp dicho : + device.BeginScene(); + effect.Technique = "GaussianBlurSeparable"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget4); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + pSurf.Dispose(); + device.EndScene(); + //TextureLoader.Save("blurH.bmp", ImageFileFormat.Bmp, g_pRenderTarget4Aux); + + if (P < cant_pasadas - 1) + { + pSurf = g_pRenderTarget4.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + pSurf.Dispose(); + } + else + // Ultima pasada vertical va sobre la pantalla pp dicha + device.SetRenderTarget(0, pOldRT); + + + // Gaussian blur Vertical + // ----------------------------------------------------- + device.BeginScene(); + effect.Technique = "GaussianBlurSeparable"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget4Aux); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(1); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + if (P < cant_pasadas - 1) + device.EndScene(); + + //TextureLoader.Save("blurV.bmp", ImageFileFormat.Bmp, g_pRenderTarget4); + + } + } + else + { + // Naive Gaussian blur + // restuaro el render target y el stencil + device.DepthStencilSurface = pOldDS; + device.SetRenderTarget(0, pOldRT); + + // dibujo el quad pp dicho : + device.BeginScene(); + effect.Technique = "GaussianBlur"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + } + GuiController.Instance.Text3d.drawText("FPS: " + HighResolutionTimer.Instance.FramesPerSecond, 0, 0, Color.Yellow); + device.EndScene(); + } + + } + + public override void close() + { + foreach (TgcMesh m in meshes) + { + m.dispose(); + } effect.Dispose(); + g_pRenderTarget.Dispose(); + g_pRenderTarget4Aux.Dispose(); + g_pRenderTarget4.Dispose(); + g_pVBV3D.Dispose(); + g_pDepthStencil.Dispose(); + } + } + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/MotionBlur.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/MotionBlur.cs new file mode 100644 index 00000000..4f985aef --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/MotionBlur.cs @@ -0,0 +1,221 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using System.Drawing; +using Microsoft.DirectX; +using TgcViewer.Utils.Modifiers; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Shaders; +using TgcViewer.Utils.Input; +using TgcViewer.Utils; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.TgcSceneLoader; + +namespace Examples.Shaders.WorkshopShaders +{ + + + public class MotionBlur : TgcExample + { + string MyMediaDir; + string MyShaderDir; + Effect effect; + TgcMesh mesh; + float time = 0; + + VertexBuffer g_pVBV3D; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget; + Texture g_pVel1, g_pVel2; // velocidad + Matrix antMatWorldView; + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-MotionBlur"; + } + + public override string getDescription() + { + return "Motion Effect"; + } + + public override void init() + { + Device d3dDevice = GuiController.Instance.D3dDevice; + GuiController.Instance.CustomRenderEnabled = true; + + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Cargar mesh + TgcSceneLoader loader = new TgcSceneLoader(); + mesh = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "ModelosTgc\\Teapot\\Teapot-TgcScene.xml").Meshes[0]; + + //Cargar Shader personalizado + string compilationErrors; + effect = Effect.FromFile(GuiController.Instance.D3dDevice,MyShaderDir + "MotionBlur.fx", + null, null, ShaderFlags.PreferFlowControl, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique dentro del shader + effect.Technique = "DefaultTechnique"; + mesh.Effect = effect; + //Camara + GuiController.Instance.RotCamera.Enable = true; + GuiController.Instance.RotCamera.CameraCenter = new Vector3(0, 0, 0); + GuiController.Instance.RotCamera.CameraDistance = 150; + + GuiController.Instance.BackgroundColor = Color.Black; + + + // stencil + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + + // velocidad del pixel + g_pVel1 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.A16B16G16R16F, Pool.Default); + g_pVel2 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.A16B16G16R16F, Pool.Default); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + antMatWorldView = Matrix.Identity; + + + + } + + public void update(float elapsedTime) + { + time += elapsedTime; + float r = 40; + mesh.Position = new Vector3(r * (float)Math.Cos(time*0.5), 0, 0 * (float)Math.Sin(time*0.5)); + //mesh.rotateY(elapsedTime); + } + + public void renderScene(String technique) + { + mesh.Technique = technique; + mesh.render(); + } + + + public override void render(float elapsedTime) + { + update(elapsedTime); + Device device = GuiController.Instance.D3dDevice; + + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pVel1.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + device.DepthStencilSurface = g_pDepthStencil; + + // 1 - Genero un mapa de velocidad + effect.Technique = "VelocityMap"; + // necesito mandarle la matrix de view proj anterior + effect.SetValue("matWorldViewProjAnt", antMatWorldView * device.Transform.Projection); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + renderScene("VelocityMap"); + device.EndScene(); + pSurf.Dispose(); + + + // 2- Genero la imagen pp dicha + effect.Technique = "DefaultTechnique"; + pSurf = g_pRenderTarget.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + renderScene("DefaultTechnique"); + device.EndScene(); + pSurf.Dispose(); + + // Ultima pasada vertical va sobre la pantalla pp dicha + device.SetRenderTarget(0, pOldRT); + device.BeginScene(); + effect.Technique = "PostProcessMotionBlur"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + effect.SetValue("texVelocityMap", g_pVel1); + effect.SetValue("texVelocityMapAnt", g_pVel2); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + device.EndScene(); + + // actualizo los valores para el proximo frame + antMatWorldView = mesh.Transform* device.Transform.View; + Texture aux = g_pVel2; + g_pVel2 = g_pVel1; + g_pVel1 = aux; + + + } + + + + + public override void close() + { + mesh.dispose(); + + g_pRenderTarget.Dispose(); + g_pDepthStencil.Dispose(); + g_pVBV3D.Dispose(); + g_pVel1.Dispose(); + g_pVel2.Dispose(); + } + + + } + + + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/MySimpleTerrain.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/MySimpleTerrain.cs index 367d1667..3141cac6 100644 --- a/TgcViewer/Examples/Shaders/WorkshopShaders/MySimpleTerrain.cs +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/MySimpleTerrain.cs @@ -13,9 +13,6 @@ namespace Examples.Shaders.WorkshopShaders { /// /// Customizacion de SimpleTerrain para renderizado de terrenos - /// - /// Autor: Mariano Banquiero - /// /// public class MySimpleTerrain { @@ -325,4 +322,6 @@ public void dispose() } } } + + } diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/NightVision.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/NightVision.cs new file mode 100644 index 00000000..b0db98f3 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/NightVision.cs @@ -0,0 +1,552 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Input; +using TgcViewer.Utils.Shaders; +using TgcViewer.Utils; +using TgcViewer.Utils.TgcSkeletalAnimation; + +namespace Examples.Shaders.WorkshopShaders +{ + + public class NightVision: TgcExample + { + string MyMediaDir; + string MyShaderDir; + List meshes; + TgcMesh pasto , arbol , arbusto; + Effect effect; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget, g_pGlowMap,g_pRenderTarget4, g_pRenderTarget4Aux; + VertexBuffer g_pVBV3D; + int cant_pasadas = 3; + List enemigos = new List(); + float []timer_firing ; + Vector3[] pos_bala; + Vector3[] dir_bala; + + int cant_balas = 100; + float total_timer_firing = 2f; + float vel_bala = 300; + float vel_bot = 100; + + + int []bot_status = new int[100]; + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-NightVision"; + } + + public override string getDescription() + { + return "NightVision Effect"; + } + + + public override void init() + { + GuiController.Instance.CustomRenderEnabled = true; + + Device d3dDevice = GuiController.Instance.D3dDevice; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Cargamos un escenario + TgcSceneLoader loader = new TgcSceneLoader(); + + //TgcScene scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Scenes\\Deposito\\Deposito-TgcScene.xml"); + TgcScene scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Scenes\\Selva\\Selva-TgcScene.xml"); + meshes = scene.Meshes; + TgcScene scene2 = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\Pasto\\Pasto-TgcScene.xml"); + pasto = scene2.Meshes[0]; + TgcScene scene3 = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\ArbolSelvatico\\ArbolSelvatico-TgcScene.xml"); + arbol = scene3.Meshes[0]; + TgcScene scene4 = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vegetacion\\Arbusto2\\Arbusto2-TgcScene.xml"); + arbusto = scene4.Meshes[0]; + + + //Cargar personaje con animaciones + TgcSkeletalLoader skeletalLoader = new TgcSkeletalLoader(); + Random rnd = new Random(); + for (int t = 0; t < 25; ++t) + { + enemigos.Add(skeletalLoader.loadMeshAndAnimationsFromFile( + GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\" + "CombineSoldier-TgcSkeletalMesh.xml", + GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\", + new string[] { + GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\Animations\\" + "StandBy-TgcSkeletalAnim.xml", + GuiController.Instance.ExamplesMediaDir + "SkeletalAnimations\\BasicHuman\\Animations\\" + "Run-TgcSkeletalAnim.xml", + })); + + + //Configurar animacion inicial + enemigos[t].playAnimation("StandBy", true); + enemigos[t].Position = new Vector3(-rnd.Next(0, 1500) - 250, 0, -rnd.Next(0, 1500) - 250); + enemigos[t].Scale = new Vector3(2f, 2f, 2f); + + + bot_status[t] = 0; + + } + + + //Cargar Shader personalizado + string compilationErrors; + effect = Effect.FromFile(GuiController.Instance.D3dDevice, + GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\GaussianBlur.fx", + null, null, ShaderFlags.PreferFlowControl, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique dentro del shader + effect.Technique = "DefaultTechnique"; + + //Camara en primera personas + GuiController.Instance.FpsCamera.Enable = true; + GuiController.Instance.FpsCamera.setCamera(new Vector3(-1000, 50, -1000), new Vector3(-1000, 50, -1001)); + GuiController.Instance.FpsCamera.MovementSpeed *= 2; + GuiController.Instance.FpsCamera.JumpSpeed = 600f; + GuiController.Instance.FpsCamera.RotationSpeed *= 4; + + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + g_pGlowMap = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + g_pRenderTarget4 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth/4 + , d3dDevice.PresentationParameters.BackBufferHeight/4, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + g_pRenderTarget4Aux = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth / 4 + , d3dDevice.PresentationParameters.BackBufferHeight / 4, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + GuiController.Instance.Modifiers.addBoolean("activar_efecto", "Activar efecto", true); + + timer_firing = new float[100]; + pos_bala = new Vector3[100]; + dir_bala = new Vector3[100]; + + for (int i = 0; i < cant_balas;++i ) + { + timer_firing[i] = (float)i / (float)cant_balas * total_timer_firing; + } + } + + + + public void update(float elapsedTime) + { + Vector3 pos = GuiController.Instance.CurrentCamera.getPosition(); + if (pos.X < -2000 || pos.Z < -2000 || pos.X >0 || pos.Z >0) + { + // reset + pos.X = -1000; + pos.Z = -1000; + GuiController.Instance.FpsCamera.setCamera(pos, pos + new Vector3(0, 0, 1)); + } + + + //Activar animacion de caminando + int t = 0; + foreach (TgcSkeletalMesh m in enemigos) + { + Vector3 dir_escape = m.Position - pos; + dir_escape.Y = 0; + float dist = dir_escape.Length(); + + if (Math.Abs(dist) <10) + { + // lo alcance, lo mato + bot_status[t] = 99; + } + else + switch (bot_status[t]) + { + // escondido + case 0: + if (dist < 400) + // me escapo + bot_status[t] = 1; + break; + + // escapando + case 1: + if (dist > 1000) + // me esconde + bot_status[t] = 0; + break; + + // perseguir + case 2: + break; + + } + + switch (bot_status[t]) + { + // escondido + case 0: + m.playAnimation("StandBy", true); + break; + + // escapando + case 1: + dir_escape.Normalize(); + m.rotateY((float)Math.Atan2(dir_escape.X, dir_escape.Z) - m.Rotation.Y + 3.1415f) ; + m.move(dir_escape * (vel_bot * elapsedTime)); + float X = m.Position.X; + float Z = m.Position.Z; + if (X < -2000) + X = -1000; + if (X > 0) + X = -1000; + if (Z < -2000) + Z = -1000; + if (Z > 0) + Z = -1000; + m.Position = new Vector3(X,m.Position.Y,Z); + m.playAnimation("Run", true, 20); + break; + + // persiguiendo + case 2: + dir_escape.Normalize(); + if (Math.Abs(dir_escape.Z) > 0.01f) + { + m.rotateY((float)Math.Atan2(dir_escape.X, dir_escape.Z) - m.Rotation.Y); + m.move(dir_escape * (-60 * elapsedTime)); + } + m.playAnimation("Run", true, 20); + break; + + case 99: + m.rotateZ(3.1415f*0.5f - m.Rotation.Z); + m.playAnimation("StandBy", true); + break; + + } + m.updateAnimation(); + ++t; + } + + Random rnd = new Random(); + for (int i = 0; i < cant_balas; ++i) + { + + timer_firing[i] -= elapsedTime; + if (timer_firing[i] < 0) + { + timer_firing[i] += total_timer_firing; + pos_bala[i] = pos + new Vector3(rnd.Next(-10, 10), rnd.Next(-10, 10), rnd.Next(-10, 10)); + dir_bala[i] = GuiController.Instance.CurrentCamera.getLookAt() - pos; + dir_bala[i].Normalize(); + } + else + { + pos_bala[i] = pos_bala[i] + dir_bala[i] * (vel_bala* elapsedTime); + } + } + } + + + public override void render(float elapsedTime) + { + update(elapsedTime); + if((bool)GuiController.Instance.Modifiers["activar_efecto"]) + renderConEfectos(elapsedTime); + else + renderSinEfectos(elapsedTime); + } + + + public void renderSinEfectos(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + + // dibujo la escena una textura + effect.Technique = "DefaultTechnique"; + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + //Dibujamos todos los meshes del escenario + renderScene(elapsedTime, "DefaultTechnique"); + //Render personames enemigos + foreach (TgcSkeletalMesh m in enemigos) + m.render(); + + GuiController.Instance.Text3d.drawText("Pos: " + GuiController.Instance.CurrentCamera.getPosition(), 0, 0, Color.Yellow); + + + device.EndScene(); + } + + + public void renderConEfectos(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + + // dibujo la escena una textura + effect.Technique = "DefaultTechnique"; + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + device.DepthStencilSurface = g_pDepthStencil; + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + //Dibujamos todos los meshes del escenario + renderScene(elapsedTime, "DefaultTechnique"); + //Render personames enemigos + foreach (TgcSkeletalMesh m in enemigos) + m.render(); + + device.EndScene(); + pSurf.Dispose(); + + + // dibujo el glow map + effect.Technique = "DefaultTechnique"; + pSurf = g_pGlowMap.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + + //Dibujamos SOLO los meshes que tienen glow brillantes + //Render personaje brillante + //Render personames enemigos + foreach (TgcSkeletalMesh m in enemigos) + m.render(); + + if (GuiController.Instance.D3dInput.keyDown(Microsoft.DirectX.DirectInput.Key.F)) + for (int i = 0; i < cant_balas; ++i) + if (timer_firing[i] > 0) + { + TgcArrow bala = new TgcArrow(); + bala.PStart = pos_bala[i]; + bala.PEnd = pos_bala[i] + dir_bala[i] * 3; + bala.Thickness = 0.05f; + bala.HeadSize = new Vector2(0.01f,0.01f); + bala.Effect = effect; + bala.Technique = "DefaultTechnique"; + bala.updateValues(); + bala.render(); + } + + // El resto opacos + renderScene(elapsedTime,"DibujarObjetosOscuros"); + + device.EndScene(); + pSurf.Dispose(); + + // Hago un blur sobre el glow map + // 1er pasada: downfilter x 4 + // ----------------------------------------------------- + pSurf = g_pRenderTarget4.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + device.BeginScene(); + effect.Technique = "DownFilter4"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pGlowMap); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + pSurf.Dispose(); + device.EndScene(); + device.DepthStencilSurface = pOldDS; + + // Pasadas de blur + for (int P = 0; P < cant_pasadas; ++P) + { + // Gaussian blur Horizontal + // ----------------------------------------------------- + pSurf = g_pRenderTarget4Aux.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // dibujo el quad pp dicho : + device.BeginScene(); + effect.Technique = "GaussianBlurSeparable"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget4); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + pSurf.Dispose(); + device.EndScene(); + + pSurf = g_pRenderTarget4.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + pSurf.Dispose(); + + // Gaussian blur Vertical + // ----------------------------------------------------- + device.BeginScene(); + effect.Technique = "GaussianBlurSeparable"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget4Aux); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(1); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + device.EndScene(); + + } + + + // To Gray Scale + // ----------------------------------------------------- + // Ultima pasada vertical va sobre la pantalla pp dicha + device.SetRenderTarget(0, pOldRT); + //pSurf = g_pRenderTarget4Aux.GetSurfaceLevel(0); + //device.SetRenderTarget(0, pSurf); + + device.BeginScene(); + effect.Technique = "GrayScale"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + effect.SetValue("g_GlowMap", g_pRenderTarget4Aux); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + + GuiController.Instance.Text3d.drawText("FPS: " + HighResolutionTimer.Instance.FramesPerSecond, 0, 0, Color.Yellow); + device.EndScene(); + } + + + public void renderScene(float elapsedTime,String Technique) + { + //Dibujamos todos los meshes del escenario + /* + foreach (TgcMesh m in meshes) + { + m.Effect = effect; + m.Technique = Technique; + m.render(); + }*/ + + Random rnd = new Random(1); + pasto.Effect = effect; + pasto.Technique = Technique; + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + { + pasto.Position = new Vector3(-i * 200 + rnd.Next(0, 50), 0, -j * 200 + rnd.Next(0, 50)); + pasto.Scale = new Vector3(3, 4 + rnd.Next(0,4), 5); + pasto.render(); + } + + arbusto.Effect = effect; + arbusto.Technique = Technique; + for (int i = 0; i < 5; ++i) + for (int j = 0; j < 5; ++j) + { + arbusto.Position = new Vector3(-i * 400 + rnd.Next(0, 50), 0, -j * 400 + rnd.Next(0, 50)); + arbusto.render(); + } + + + arbol.Effect = effect; + arbol.Technique = Technique; + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + { + arbol.Position = new Vector3(-i * 700 + rnd.Next(0, 50), 0, -j * 700 + rnd.Next(0, 50)); + arbol.render(); + } + + } + + + + + public override void close() + { + foreach (TgcMesh m in meshes) + { + m.dispose(); + } + effect.Dispose(); + pasto.dispose(); + arbol.dispose(); + arbusto.dispose(); + g_pRenderTarget.Dispose(); + g_pGlowMap.Dispose(); + g_pRenderTarget4Aux.Dispose(); + g_pRenderTarget4.Dispose(); + g_pVBV3D.Dispose(); + g_pDepthStencil.Dispose(); + foreach (TgcSkeletalMesh m in enemigos) + m.dispose(); + } + } + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/OutRun.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/OutRun.cs new file mode 100644 index 00000000..bc223211 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/OutRun.cs @@ -0,0 +1,390 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using System.Drawing; +using Microsoft.DirectX; +using TgcViewer.Utils.Modifiers; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Shaders; +using TgcViewer.Utils.Input; +using TgcViewer.Utils; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.TgcSceneLoader; + +namespace Examples.Shaders.WorkshopShaders +{ + + + public class OutRun : TgcExample + { + string MyMediaDir; + string MyShaderDir; + + TgcSimpleTerrain terrain; + TgcSkyBox skyBox; + F1Circuit circuito; + Effect effect; + public float vel = 100f; + public float acel_mouse_wheel = 20f; + public Vector3 pos; + public Vector3 dir; + TgcMesh car; + public Vector3 car_Scale = new Vector3(0.5f, 0.5f, 0.5f); + + public Vector3 desf = new Vector3(0, 20, 0); // 40 + public float dist_cam = 13; //130; + public float rotationSpeed = 0.1f; + + public bool paused = false; + public bool mouseCaptured = false; + public Point mouseCenter; + + VertexBuffer g_pVBV3D; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget, g_pRenderTarget2, g_pRenderTarget3, g_pRenderTarget4, g_pRenderTarget5; + public float ftime = 0; // frame time + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-OutRun"; + } + + public override string getDescription() + { + return "OutRun Circuit Demo"; + } + + public override void init() + { + Device d3dDevice = GuiController.Instance.D3dDevice; + GuiController.Instance.CustomRenderEnabled = true; + + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + circuito = new F1Circuit(); + + //Cargar terreno: cargar heightmap y textura de color + terrain = new TgcSimpleTerrain(); + terrain.loadHeightmap(GuiController.Instance.ExamplesMediaDir + "Heighmaps\\" + "TerrainTexture2.jpg", + 20, 0.1f, new Vector3(0, -125, 0)); + terrain.loadTexture( GuiController.Instance.ExamplesMediaDir + "Heighmaps\\" + "TerrainTexture2.jpg"); + + //Crear SkyBox + skyBox = new TgcSkyBox(); + skyBox.Center = new Vector3(0, 500, 0); + skyBox.Size = new Vector3(10000, 10000, 10000); + string texturesPath = GuiController.Instance.ExamplesMediaDir + "Texturas\\Quake\\SkyBox LostAtSeaDay\\"; + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Up, texturesPath + "lostatseaday_up.jpg"); + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Down, texturesPath + "lostatseaday_dn.jpg"); + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Left, texturesPath + "lostatseaday_lf.jpg"); + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Right, texturesPath + "lostatseaday_rt.jpg"); + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Front, texturesPath + "lostatseaday_bk.jpg"); + skyBox.setFaceTexture(TgcSkyBox.SkyFaces.Back, texturesPath + "lostatseaday_ft.jpg"); + skyBox.updateValues(); + + + TgcSceneLoader loader = new TgcSceneLoader(); + TgcScene scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + "MeshCreator\\Meshes\\Vehiculos\\Auto\\Auto-TgcScene.xml"); + car = scene.Meshes[0]; + car.AutoTransformEnable = false; + + //Cargar Shader personalizado + string compilationErrors; + effect = Effect.FromFile(GuiController.Instance.D3dDevice,MyShaderDir + "OutRun.fx", + null, null, ShaderFlags.PreferFlowControl, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique dentro del shader + effect.Technique = "DefaultTechnique"; + + //Configurar FPS Camara + GuiController.Instance.FpsCamera.Enable = true; + GuiController.Instance.FpsCamera.MovementSpeed = 250f; + GuiController.Instance.FpsCamera.JumpSpeed = 50f; + //GuiController.Instance.FpsCamera.setCamera(new Vector3(315.451f, 40, -464.28490f), new Vector3(316.1626f, 40, -463.6029f)); + + reset_pos(); + + // para capturar el mouse + Control focusWindows = GuiController.Instance.D3dDevice.CreationParameters.FocusWindow; + mouseCenter = focusWindows.PointToScreen(new Point(focusWindows.Width / 2,focusWindows.Height / 2)); + mouseCaptured = true; + Cursor.Hide(); + + + // stencil + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget2 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget3 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget4 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget5 = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + + } + + public void reset_pos() + { + // pongo el auto en el primer tramo de la ruta + pos = circuito.pt_ruta[40]; + dir = circuito.pt_ruta[41] - pos; + pos.Y += 15; + dir.Y = 0; + dir.Normalize(); + } + + public void update(float elapsedTime) + { + + TgcD3dInput d3dInput = GuiController.Instance.D3dInput; + + if (d3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.F1)) + paused = !paused; + + if (paused) + return; + + if (d3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.M)) + { + mouseCaptured = !mouseCaptured; + if (mouseCaptured) + Cursor.Hide(); + else + Cursor.Show(); + } + + vel += d3dInput.WheelPos * acel_mouse_wheel; + + if (mouseCaptured && d3dInput.buttonDown(TgcD3dInput.MouseButtons.BUTTON_LEFT)) + { + //float pitch = d3dInput.YposRelative * rotationSpeed; + float heading = d3dInput.XposRelative * rotationSpeed; + dir = rotar_xz(dir, -heading); + } + + if (mouseCaptured) + Cursor.Position = mouseCenter; + + + // aplico la velocidad + pos = pos + dir*vel * elapsedTime; + + // verifico si sigue en la ruta + float H = circuito.updatePos(pos.X, pos.Z); + if (!circuito.en_ruta) + { + // lo mando de nuevo a la ruta + pos = circuito.que_pos_buena(pos.X, pos.Z); + } + + // mantengo el auto en la ruta + pos.Y = H; + + // actualizo la posiicon del auto + car.Position = pos; + car.Transform = CalcularMatriz(pos, car_Scale, -dir); + + // actualizo la camara + GuiController.Instance.FpsCamera.setCamera(pos - dir * dist_cam + desf, pos + desf); + //GuiController.Instance.FpsCamera.setCamera(new Vector3(500, 4000, 500), new Vector3(0, 0, 0)); + GuiController.Instance.FpsCamera.updateCamera(); + + } + + public override void render(float elapsedTime) + { + update(elapsedTime); + + Device device = GuiController.Instance.D3dDevice; + effect.Technique = "DefaultTechnique"; + + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + device.DepthStencilSurface = g_pDepthStencil; + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + + // ------------------------------------- + //Renderizar terreno + terrain.Effect = effect; + terrain.Technique = "DefaultTechnique"; + terrain.render(); + // skybox + skyBox.render(); + //Renderizar pista + circuito.render(effect); + //Renderizar auto + car.Effect = effect; + car.Technique = "DefaultTechnique"; + car.render(); + // ------------------------------------- + + device.EndScene(); + pSurf.Dispose(); + + // Ultima pasada vertical va sobre la pantalla pp dicha + device.SetRenderTarget(0, pOldRT); + device.BeginScene(); + effect.Technique = "FrameMotionBlur"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + effect.SetValue("g_RenderTarget2", g_pRenderTarget2); + effect.SetValue("g_RenderTarget3", g_pRenderTarget3); + effect.SetValue("g_RenderTarget4", g_pRenderTarget4); + effect.SetValue("g_RenderTarget5", g_pRenderTarget5); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + + + //GuiController.Instance.Text3d.drawText("FPS: " + HighResolutionTimer.Instance.FramesPerSecond, 0, 0, Color.Yellow); + //GuiController.Instance.Text3d.drawText("Pos: " + GuiController.Instance.CurrentCamera.getPosition(), 0, 0, Color.Yellow); + //GuiController.Instance.Text3d.drawText("Look At: " + GuiController.Instance.CurrentCamera.getLookAt(), 500, 0, Color.Yellow); + + if(circuito.en_ruta) + GuiController.Instance.Text3d.drawText("Tramo:" + circuito.pos_en_ruta, 0, 0, Color.Yellow); + + //GuiController.Instance.Text3d.drawText("dist_cam:" + dist_cam + "defY" + desf.Y, 0, 0, Color.Yellow); + //GuiController.Instance.Text3d.drawText("vel:" + vel, 0, 0, Color.Yellow); + device.EndScene(); + + + ftime += elapsedTime; + if (ftime > 0.03f) + { + ftime = 0; + Texture aux = g_pRenderTarget5; + g_pRenderTarget5 = g_pRenderTarget4; + g_pRenderTarget4 = g_pRenderTarget3; + g_pRenderTarget3 = g_pRenderTarget2; + g_pRenderTarget2 = g_pRenderTarget; + g_pRenderTarget = aux; + } + } + + public override void close() + { + circuito.dispose(); + car.dispose(); + effect.Dispose(); + terrain.dispose(); + skyBox.dispose(); + + g_pRenderTarget.Dispose(); + g_pRenderTarget2.Dispose(); + g_pRenderTarget3.Dispose(); + g_pRenderTarget4.Dispose(); + g_pRenderTarget5.Dispose(); + g_pDepthStencil.Dispose(); + g_pVBV3D.Dispose(); + + } + + + // helper + public Matrix CalcularMatriz(Vector3 Pos, Vector3 Scale, Vector3 Dir) + { + Vector3 VUP = new Vector3(0, 1, 0); + + Matrix matWorld = Matrix.Scaling(Scale); + // determino la orientacion + Vector3 U = Vector3.Cross(VUP, Dir); + U.Normalize(); + Vector3 V = Vector3.Cross(Dir, U); + Matrix Orientacion; + Orientacion.M11 = U.X; + Orientacion.M12 = U.Y; + Orientacion.M13 = U.Z; + Orientacion.M14 = 0; + + Orientacion.M21 = V.X; + Orientacion.M22 = V.Y; + Orientacion.M23 = V.Z; + Orientacion.M24 = 0; + + Orientacion.M31 = Dir.X; + Orientacion.M32 = Dir.Y; + Orientacion.M33 = Dir.Z; + Orientacion.M34 = 0; + + Orientacion.M41 = 0; + Orientacion.M42 = 0; + Orientacion.M43 = 0; + Orientacion.M44 = 1; + matWorld = matWorld * Orientacion; + + // traslado + matWorld = matWorld * Matrix.Translation(Pos); + return matWorld; + } + + + public Vector3 rotar_xz(Vector3 v,float an) + { + return new Vector3((float)(v.X * Math.Cos(an) - v.Z * Math.Sin(an)), + v.Y, + (float)(v.X * Math.Sin(an) + v.Z * Math.Cos(an))); + + } + + + } + + + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/ParallaxOcclusion.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/ParallaxOcclusion.cs new file mode 100644 index 00000000..13eb04bc --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/ParallaxOcclusion.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Input; + +namespace Examples.Shaders.WorkshopShaders +{ + public class ParallaxOcclusion : TgcExample + { + string MyMediaDir; + string MyShaderDir; + TgcScene scene; + TgcMesh mesh; + Effect effect; + Texture g_pBaseTexture; + Texture g_pHeightmap; + Texture g_pBaseTexture2; + Texture g_pHeightmap2; + Texture g_pBaseTexture3; + Texture g_pHeightmap3; + + float time; + bool pom; + bool phong; + int nro_textura; + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-ParallaxOcclusion"; + } + + public override string getDescription() + { + return "Parallax Occlusion. L->Luz Space->Metodo S->Malla"; + } + + public override void init() + { + time = 0f; + Device d3dDevice = GuiController.Instance.D3dDevice; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Crear loader + TgcSceneLoader loader = new TgcSceneLoader(); + + // parallax oclussion + scene = loader.loadSceneFromFile(MyMediaDir +"Piso\\Piso-TgcScene.xml"); + + g_pBaseTexture = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\wood.bmp"); + g_pHeightmap = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\four_NM_height.tga"); + + g_pBaseTexture2 = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\stones.bmp"); + g_pHeightmap2 = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\stones_NM_height.tga"); + + g_pBaseTexture3 = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\rocks.jpg"); + g_pHeightmap3 = TextureLoader.FromFile(d3dDevice, MyMediaDir + + "Piso\\Textures\\rocks_NM_height.tga"); + + mesh = scene.Meshes[0]; + int[] adj = new int[mesh.D3dMesh.NumberFaces * 3]; + mesh.D3dMesh.GenerateAdjacency(0, adj); + mesh.D3dMesh.ComputeNormals(adj); + + //Cargar Shader + string compilationErrors; + effect = Effect.FromFile(d3dDevice, MyShaderDir + "Parallax.fx", null, null, ShaderFlags.None, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + + GuiController.Instance.Modifiers.addVertex3f("LightDir", new Vector3(-1, -1, -1), new Vector3(1, 1, 1), new Vector3(0, -1, 0)); + GuiController.Instance.Modifiers.addFloat("minSample", 1f, 10f, 10f); + GuiController.Instance.Modifiers.addFloat("maxSample", 11f, 50f, 50f); + GuiController.Instance.Modifiers.addFloat("HeightMapScale", 0.001f, 0.5f, 0.1f); + + //Centrar camara rotacional respecto a este mesh + GuiController.Instance.RotCamera.targetObject(mesh.BoundingBox); + GuiController.Instance.RotCamera.CameraCenter = new Vector3(0, 0, 0); + GuiController.Instance.RotCamera.CameraDistance = 100; + GuiController.Instance.RotCamera.RotationSpeed = 1000f; + + + + pom = false; + phong = true; + nro_textura = 0; + } + + + public override void render(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + time += elapsedTime; + if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.Space)) + pom = !pom; + if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.L)) + phong = !phong; + if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.S)) + { + if (++nro_textura >= 3) + nro_textura = 0; + } + + + Vector3 lightDir = (Vector3)GuiController.Instance.Modifiers["LightDir"]; + effect.SetValue("g_LightDir", TgcParserUtils.vector3ToFloat3Array(lightDir)); + effect.SetValue("min_cant_samples", (float)GuiController.Instance.Modifiers["minSample"]); + effect.SetValue("max_cant_samples", (float)GuiController.Instance.Modifiers["maxSample"]); + effect.SetValue("fHeightMapScale", (float)GuiController.Instance.Modifiers["HeightMapScale"]); + effect.SetValue("fvEyePosition", TgcParserUtils.vector3ToFloat3Array(GuiController.Instance.RotCamera.getPosition())); + + device.EndScene(); + effect.SetValue("time", time); + switch(nro_textura) + { + case 0: + default: + effect.SetValue("aux_Tex", g_pBaseTexture); + effect.SetValue("height_map", g_pHeightmap); + break; + case 1: + effect.SetValue("aux_Tex", g_pBaseTexture2); + effect.SetValue("height_map", g_pHeightmap2); + break; + case 2: + effect.SetValue("aux_Tex", g_pBaseTexture3); + effect.SetValue("height_map", g_pHeightmap3); + break; + } + effect.SetValue("phong_lighting", phong); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + + mesh.Effect = effect; + mesh.Technique = pom ? "ParallaxOcclusion" : "BumpMap"; + mesh.render(); + + + GuiController.Instance.Text3d.drawText((pom ? "ParallaxOcclusion" : "BumpMap") + + " "+ (phong?"Phong Lighting":"Iluminación estática") + , 0, 0, Color.Yellow); + + + } + + public override void close() + { + mesh.dispose(); + effect.Dispose(); + g_pBaseTexture.Dispose(); + g_pBaseTexture2.Dispose(); + g_pBaseTexture3.Dispose(); + g_pHeightmap.Dispose(); + g_pHeightmap2.Dispose(); + g_pHeightmap3.Dispose(); + + } + + } + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/BasicShader.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/BasicShader.fx index 2dffc273..4506ee58 100644 --- a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/BasicShader.fx +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/BasicShader.fx @@ -74,9 +74,17 @@ VS_OUTPUT vs_main2( VS_INPUT Input ) VS_OUTPUT Output; // Animar posicion - Input.Position.x += sin(time)*30*sign(Input.Position.x); + /*Input.Position.x += sin(time)*30*sign(Input.Position.x); Input.Position.y += cos(time)*30*sign(Input.Position.y-20); Input.Position.z += sin(time)*30*sign(Input.Position.z); + */ + + // Animar posicion + float Y = Input.Position.y; + float Z = Input.Position.z; + Input.Position.y = Y * cos(time) - Z * sin(time); + Input.Position.z = Z * cos(time) + Y * sin(time); + //Proyectar posicion Output.Position = mul( Input.Position, matWorldViewProj); diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/FullQuad.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/FullQuad.fx new file mode 100644 index 00000000..b9cb93ee --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/FullQuad.fx @@ -0,0 +1,154 @@ + +//Matrices de transformacion +float4x4 matWorld; //Matriz de transformacion World +float4x4 matWorldView; //Matriz World * View +float4x4 matWorldViewProj; //Matriz World * View * Projection +float4x4 matInverseTransposeWorld; //Matriz Transpose(Invert(World)) + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = WRAP; + ADDRESSV = WRAP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; +float time; + +//Input del Vertex Shader +struct VS_INPUT +{ + float4 Position : POSITION0; + float3 Normal : NORMAL0; + float4 Color : COLOR; + float2 Texcoord : TEXCOORD0; +}; + +texture g_RenderTarget; +sampler RenderTarget = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +//Output del Vertex Shader +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 Texcoord : TEXCOORD0; + float3 Norm : TEXCOORD1; // Normales + float3 Pos : TEXCOORD2; // Posicion real 3d +}; + +//Vertex Shader +VS_OUTPUT vs_main( VS_INPUT Input ) +{ + VS_OUTPUT Output; + + //Proyectar posicion + Output.Position = mul( Input.Position, matWorldViewProj); + + //Las Texcoord quedan igual + Output.Texcoord = Input.Texcoord; + + // Calculo la posicion real + float4 pos_real = mul(Input.Position,matWorld); + Output.Pos = float3(pos_real.x,pos_real.y,pos_real.z); + + // Transformo la normal y la normalizo + //Output.Norm = normalize(mul(Input.Normal,matInverseTransposeWorld)); + Output.Norm = normalize(mul(Input.Normal,matWorld)); + return( Output ); + +} + +//Pixel Shader +float4 ps_main( float3 Texcoord: TEXCOORD0, float3 N:TEXCOORD1, + float3 Pos: TEXCOORD2) : COLOR0 +{ + //Obtener el texel de textura + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + return fvBaseColor; +} + +technique DefaultTechnique +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } +} + + + +void VSCopy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + + +float4 PSPostProcess( in float2 Tex : TEXCOORD0 , in float2 vpos : VPOS) : COLOR0 +{ + float4 ColorBase = tex2D(RenderTarget, Tex); + // float4 ColorBase = tex2D(RenderTarget, Tex + float2(34*sin(time+Tex.x*15)/screen_dx,25*cos(time+Tex.y*15)/screen_dy)); + + return ColorBase; + + // gray scale + // Y = 0.2126 R + 0.7152 G + 0.0722 B + //float Y = 0.2126*ColorBase.r + 0.7152*ColorBase.g + 0.0722*ColorBase.b; + //return float4(Y,Y,Y,1); +} + + + + + + +static const int kernel_r = 6; +static const int kernel_size = 13; +static const float Kernel[kernel_size] = +{ + 0.002216, 0.008764, 0.026995, 0.064759, 0.120985, 0.176033, 0.199471, 0.176033, 0.120985, 0.064759, 0.026995, 0.008764, 0.002216, +}; + + +void Blur(float2 screen_pos : TEXCOORD0,out float4 Color : COLOR) +{ + Color = 0; + for(int i=0;i; + MipFilter = NONE; + MinFilter = NONE; + MagFilter = NONE; +}; + + + + +void Hash(int4 clave,out int4 buffer) +{ + int k = (clave[0] + clave[1] + clave[2] + clave[3]) % 256; + for(int i=0;i<4;++i) + { + k = round(round(a*k + c) % m); + buffer[i] = k; + k = round(k + clave[i]); + } +} + + +float4 PSComputeHash( float2 pos : VPOS) : COLOR0 +{ + int4 hash; + int4 clave; + int group_x = floor((float)pos.x / 32.0); + int x = floor((float)pos.x % 32.0); + int group_y = floor((float)pos.y / 32.0); + int y = floor((float)pos.y % 32.0); + + clave[0] = 'A' + group_x; + clave[1] = 'A' + group_y; + clave[2] = 'A' + x; + clave[3] = 'A' + y; + Hash(clave,hash); + + // compara con el hash buscado + if(distance(hash,hash_buscado)==0) + return float4(1,1,1,1); + else + return float4(0,0,0,1); + + // retorna el hash pp dicho + //return float4((float)hash[0]/255.0,(float)hash[1]/255.0,(float)hash[2]/255.0,(float)hash[3]/255.0); +} + +void vs_copy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + + +technique ComputeHash +{ + pass P0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSComputeHash(); + } +} + + + +void Hash6(int clave[6],out int buffer[6]) +{ + int k = round(clave[0] + clave[1] + clave[2] + clave[3]+ clave[4]+ clave[5]) % 256; + for(int i=0;i<6;++i) + { + k = round(round(a*k + c) % m); + buffer[i] = k; + k = round(k + clave[i]); + } +} + +int prefix_x = 0; +int prefix_y = 0; +int hash_buscado6[6]; + +float4 PSComputeHash6( float2 pos : VPOS) : COLOR0 +{ + int hash[6]; + int clave[6]; + int group_x = floor((float)pos.x / 32.0); + int x = floor((float)pos.x % 32.0); + int group_y = floor((float)pos.y / 32.0); + int y = floor((float)pos.y % 32.0); + + clave[0] = 'A' + prefix_x; + clave[1] = 'A' + prefix_y; + clave[2] = 'A' + group_x; + clave[3] = 'A' + group_y; + clave[4] = 'A' + x; + clave[5] = 'A' + y; + Hash6(clave,hash); + + + // compara con el hash buscado + float dist = 0; + for(int i=0;i<6;++i) + dist += abs(hash[i] - hash_buscado6[i]); + + if(dist<0.01) + return float4(1,1,1,1); + else + return float4(0,0,0,1); + +/* clave[0] = 'A'; + clave[1] = 'A'; + clave[2] = 'W'; + clave[3] = 'W'; + clave[4] = 'W'; + clave[5] = 'W'; + Hash6(clave,hash); + return float4((float)hash[0]/255.0,(float)hash[1]/255.0,(float)hash[2]/255.0,(float)hash[3]/255.0); + */ + +} + +technique ComputeHash6 +{ + pass P0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSComputeHash6(); + } +} + diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GPUcompute.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GPUcompute.fx new file mode 100644 index 00000000..2a6f390c --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GPUcompute.fx @@ -0,0 +1,266 @@ +#define MAX_DS 512 + +//Variables utilizadas por el Vertex Shader +float3 fvLightPosition = float3( -100.00, 100.00, -100.00 ); +float3 fvEyePosition = float3( 0.00, 0.00, -100.00 ); +float4x4 matViewProjection; +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; + +float4x4 matWorld; +float4x4 matWorldView; +float4x4 matWorldViewProj; +float4x4 matInverseTransposeWorld; + +float k_la = 0.3; // luz ambiente global +float k_ld = 0.9; // luz difusa +float k_ls = 0.4; // luz specular +float fSpecularPower = 16.84; + +float elapsedTime = 0; +float map_size = 64.0; +float map_desf = 0.5/64.0; +float Kp = 1; + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = MIRROR; + ADDRESSV = MIRROR; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +// mapa de Velocidad +texture g_pVelocidad; +sampler Velocidad = +sampler_state +{ + Texture = ; + MipFilter = NONE; + MinFilter = NONE; + MagFilter = NONE; +}; + +// mapa de Posiciones +texture g_pPos; +sampler Posicion = +sampler_state +{ + Texture = ; + MipFilter = NONE; + MinFilter = NONE; + MagFilter = NONE; +}; + + +// Height map +texture height_map; +sampler2D heightMap = +sampler_state +{ + Texture = ; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = NONE; +}; + +float currentScaleXZ = 100; +float currentScaleY = 10; + +// ------------------------------------ +struct VS_INPUT +{ + float4 Position : POSITION0; + float3 Normal : NORMAL0; + float4 Color : COLOR; + float2 Texcoord : TEXCOORD0; +}; + +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 Texcoord : TEXCOORD0; + float3 Norm : TEXCOORD1; // Normales + float3 Pos : TEXCOORD2; // Posicion real 3d +}; + +//Vertex Shader Trivial: +VS_OUTPUT vs_main( VS_INPUT Input ) +{ + VS_OUTPUT Output; + //Proyectar posicion + Output.Position = mul( Input.Position, matWorldViewProj); + //Las Texcoord quedan igual + Output.Texcoord = Input.Texcoord; + // Calculo la posicion real + float4 pos_real = mul(Input.Position,matWorld); + Output.Pos = float3(pos_real.x,pos_real.y,pos_real.z); + // Transformo la normal y la normalizo + Output.Norm = normalize(mul(Input.Normal,matInverseTransposeWorld)); + return( Output ); +} + +//Pixel Shader +float4 ps_main( float3 Texcoord: TEXCOORD0, float3 N:TEXCOORD1, + float3 Pos: TEXCOORD2) : COLOR0 +{ + float ld = 0; // luz difusa + float le = 0; // luz specular + + N = normalize(N); + // 1- calculo la luz diffusa + float3 LD = normalize(fvLightPosition-float3(Pos.x,Pos.y,Pos.z)); + ld += saturate(dot(N, LD))*k_ld; + + // 2- calcula la reflexion specular + float3 D = normalize(float3(Pos.x,Pos.y,Pos.z)-fvEyePosition); + float ks = saturate(dot(reflect(LD,N), D)); + ks = pow(ks,fSpecularPower); + le += ks*k_ls; + + //Obtener el texel de textura + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + + // suma luz diffusa, ambiente y especular + float4 RGBColor = 0; + RGBColor.rgb = saturate(fvBaseColor*(saturate(k_la+ld)) + le); + return RGBColor; +} + +technique DefaultTechnique +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } + +} + +// ----------------------------------------------- + +struct PS_OUTPUT +{ + float4 Velocity : COLOR0; + float4 Position : COLOR1; +}; + +float CalcularAltura(float x,float y) +{ + float u = y/(currentScaleXZ*map_size) + 0.5; + float v = x/(currentScaleXZ*map_size) + 0.5; + float3 T0 = tex2D(heightMap,float2(u+map_desf,v+map_desf)); + float H0 = T0.r*0.299 + T0.g*0.587 + T0.b*0.114; + return 255*H0*currentScaleY; +} + +PS_OUTPUT PSInitVel( float2 Texcoord: TEXCOORD0) +{ + PS_OUTPUT Output; + Output.Velocity = float4(0,0,0,0); + + /* + float x0 = 0.2 + 0.6*(Texcoord.x-0.5)*currentScaleXZ*map_size; + float z0 = 0.2 + 0.6*(Texcoord.y-0.5)*currentScaleXZ*map_size; + Output.Position = float4(x0,z0,220+CalcularAltura(x0, z0),0); + */ + + float an = 200*Texcoord.x*3.1415; + float z0 = 0.1*(Texcoord.y-0.5)*currentScaleXZ*map_size; + Output.Position = float4(sin(an)*20,cos(an)*20-1000,2000+z0*50,0); + + return Output; +} + +PS_OUTPUT PSComputeVel( float2 Texcoord: TEXCOORD0) +{ + PS_OUTPUT Output; + + float4 Vel = tex2D( Velocidad, Texcoord ); + float vel_x = Vel.x; + float vel_z = Vel.y; + + float4 Pos = tex2D( Posicion, Texcoord ); + float x0 = Pos.x; + float z0 = Pos.y; + float H = CalcularAltura(x0, z0); + float ddx,ddz,alfa; + if(Pos.z>H+10) + { + H = Pos.z - elapsedTime*500; + ddx = ddz = 0; + alfa = 0; + } + else + { + float dt = 20; + ddx = (CalcularAltura(x0 + dt, z0) - H) / dt; + ddz = (CalcularAltura(x0, z0 + dt) - H) / dt; + vel_x -= elapsedTime * ddx * 150; + vel_z -= elapsedTime * ddz * 150; + + // rozamiento + vel_x *= 1-elapsedTime/25; + vel_z *= 1-elapsedTime/25; + + x0 += elapsedTime * vel_x; + z0 += elapsedTime * vel_z; + + // calculo el angulo rodado: + float dx = x0 - Pos.x; + float dz = z0 - Pos.y; + alfa = sqrt(dx*dx + dz*dz) / Kp; + } + + + Output.Velocity = float4(vel_x,vel_z,ddx,ddz); + Output.Position = float4(x0,z0,H,alfa); + + return Output; +} + +float4 PSPreview( float2 Texcoord: TEXCOORD0) : COLOR0 +{ + float4 fvVelPos = tex2D( Velocidad, Texcoord ); + float2 vel = fvVelPos.xy; + float2 pos = fvVelPos.zw; + return float4(1,1,1,1); +} + +void vs_copy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + +// Genera el mapa de velocidad +technique ComputeVel +{ + pass P0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSInitVel(); + } + pass P1 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSComputeVel(); + } + + pass P2 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSPreview(); + } + +} + + + diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GaussianBlur.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GaussianBlur.fx new file mode 100644 index 00000000..ebee532a --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/GaussianBlur.fx @@ -0,0 +1,253 @@ +// --------------------------------------------------------- +// Ejemplo toon Shading +// --------------------------------------------------------- + +/**************************************************************************************/ +/* Variables comunes */ +/**************************************************************************************/ + +//Matrices de transformacion +float4x4 matWorld; //Matriz de transformacion World +float4x4 matWorldView; //Matriz World * View +float4x4 matWorldViewProj; //Matriz World * View * Projection +float4x4 matInverseTransposeWorld; //Matriz Transpose(Invert(World)) + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = WRAP; + ADDRESSV = WRAP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; + + +//Input del Vertex Shader +struct VS_INPUT +{ + float4 Position : POSITION0; + float3 Normal : NORMAL0; + float4 Color : COLOR; + float2 Texcoord : TEXCOORD0; +}; + +texture g_RenderTarget; +sampler RenderTarget = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture g_GlowMap; +sampler GlowMap = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +//Output del Vertex Shader +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 Texcoord : TEXCOORD0; + float3 Norm : TEXCOORD1; // Normales + float3 Pos : TEXCOORD2; // Posicion real 3d +}; + +//Vertex Shader +VS_OUTPUT vs_main( VS_INPUT Input ) +{ + VS_OUTPUT Output; + + //Proyectar posicion + Output.Position = mul( Input.Position, matWorldViewProj); + + //Las Texcoord quedan igual + Output.Texcoord = Input.Texcoord; + + // Calculo la posicion real + float4 pos_real = mul(Input.Position,matWorld); + Output.Pos = float3(pos_real.x,pos_real.y,pos_real.z); + + // Transformo la normal y la normalizo + //Output.Norm = normalize(mul(Input.Normal,matInverseTransposeWorld)); + Output.Norm = normalize(mul(Input.Normal,matWorld)); + return( Output ); + +} + +//Pixel Shader +float4 ps_main( float3 Texcoord: TEXCOORD0, float3 N:TEXCOORD1, + float3 Pos: TEXCOORD2) : COLOR0 +{ + //Obtener el texel de textura + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + return fvBaseColor; +} + +technique DefaultTechnique +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } +} + + +// dibuja negro (tiene que ocultar lo que esta oscuro) +float4 PSOscuros(float3 Texcoord: TEXCOORD0) : COLOR0 +{ + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + return float4(0,0,0,fvBaseColor.a); +} + +technique DibujarObjetosOscuros +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 PSOscuros(); + } +} + + + +void VSCopy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + +// Gaussian Blur + +static const int kernel_r = 6; +static const int kernel_size = 13; +static const float Kernel[kernel_size] = +{ + 0.002216, 0.008764, 0.026995, 0.064759, 0.120985, 0.176033, 0.199471, 0.176033, 0.120985, 0.064759, 0.026995, 0.008764, 0.002216, +}; + + +void Blur(float2 screen_pos : TEXCOORD0,out float4 Color : COLOR) +{ + Color = 0; + for(int i=0;i; + MipFilter = NONE; + MinFilter = NONE; + MagFilter = NONE; +}; + +sampler RenderTargetAnt = +sampler_state +{ + Texture = ; + MipFilter = NONE; + MinFilter = NONE; + MagFilter = NONE; +}; + + + +void vs_copy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + +float4 PSGaussianBlur(float2 vPos : VPOS,float2 TextureUV : TEXCOORD0) : COLOR0 +{ + float3 color11 = tex2D(baseMap, TextureUV+float2(-2*screen_inc_x,-2*screen_inc_y)).rgb; + float3 color12 = tex2D(baseMap, TextureUV+float2(-2*screen_inc_x,-screen_inc_y)).rgb; + float3 color13 = tex2D(baseMap, TextureUV+float2(-2*screen_inc_x,0)).rgb; + float3 color14 = tex2D(baseMap, TextureUV+float2(-2*screen_inc_x,screen_inc_y)).rgb; + float3 color15 = tex2D(baseMap, TextureUV+float2(-2*screen_inc_x,2*screen_inc_y)).rgb; + + float3 color21 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,-2*screen_inc_y)).rgb; + float3 color22 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,-screen_inc_y)).rgb; + float3 color23 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,0)).rgb; + float3 color24 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,screen_inc_y)).rgb; + float3 color25 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,2*screen_inc_y)).rgb; + + float3 color31 = tex2D(baseMap, TextureUV+float2(0,-2*screen_inc_y)).rgb; + float3 color32 = tex2D(baseMap, TextureUV+float2(0,-screen_inc_y)).rgb; + float3 color33 = tex2D(baseMap, TextureUV+float2(0,0)).rgb; + float3 color34 = tex2D(baseMap, TextureUV+float2(0,screen_inc_y)).rgb; + float3 color35 = tex2D(baseMap, TextureUV+float2(0,2*screen_inc_y)).rgb; + + float3 color41 = tex2D(baseMap, TextureUV+float2(screen_inc_x,-2*screen_inc_y)).rgb; + float3 color42 = tex2D(baseMap, TextureUV+float2(screen_inc_x,-screen_inc_y)).rgb; + float3 color43 = tex2D(baseMap, TextureUV+float2(screen_inc_x,0)).rgb; + float3 color44 = tex2D(baseMap, TextureUV+float2(screen_inc_x,screen_inc_y)).rgb; + float3 color45 = tex2D(baseMap, TextureUV+float2(screen_inc_x,2*screen_inc_y)).rgb; + + float3 color51 = tex2D(baseMap, TextureUV+float2(2*screen_inc_x,-2*screen_inc_y)).rgb; + float3 color52 = tex2D(baseMap, TextureUV+float2(2*screen_inc_x,-screen_inc_y)).rgb; + float3 color53 = tex2D(baseMap, TextureUV+float2(2*screen_inc_x,0)).rgb; + float3 color54 = tex2D(baseMap, TextureUV+float2(2*screen_inc_x,screen_inc_y)).rgb; + float3 color55 = tex2D(baseMap, TextureUV+float2(2*screen_inc_x,2*screen_inc_y)).rgb; + + float3 T = 0; + T += 2*color11+4*color12+5*color13+4*color14+2*color15; + T += 4*color21+9*color22+12*color23+9*color24+4*color25; + T += 5*color31+12*color32+15*color33+12*color34+5*color35; + T += 4*color41+9*color42+12*color43+9*color44+4*color45; + T += 2*color51+4*color52+5*color53+4*color54+2*color55; + T /= 159.0; + + return float4(T,1); +} + + +float4 PSIntensidad(float2 vPos : VPOS,float2 TextureUV : TEXCOORD0) : COLOR0 +{ + // Red 0.212 + // Green 0.701 + // Blue 0.087 + float3 color = tex2D(baseMap, TextureUV).rgb; + float K = color.r*0.212 + color.g*0.701 + color.b*0.087; + return float4(K,K,K,1); +} + +float4 PSErotionFilter(float2 vPos : VPOS,float2 TextureUV : TEXCOORD0) : COLOR0 +{ + float color11 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,-screen_inc_y)).r; + float color12 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,0)).r; + float color13 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,screen_inc_y)).r; + + float color21 = tex2D(baseMap, TextureUV+float2(0,-screen_inc_y)).r; + float color22 = tex2D(baseMap, TextureUV+float2(0,0)).r; + float color23 = tex2D(baseMap, TextureUV+float2(0,screen_inc_y)).r; + + float color31 = tex2D(baseMap, TextureUV+float2(screen_inc_x,-screen_inc_y)).r; + float color32 = tex2D(baseMap, TextureUV+float2(screen_inc_x,0)).r; + float color33 = tex2D(baseMap, TextureUV+float2(screen_inc_x,screen_inc_y)).r; + + float min1 = min(color11,min(color12,color13)); + float min2 = min(color21,min(color22,color23)); + float min3 = min(color31,min(color32,color33)); + float K = min(min1,min(min2,min3)); + return float4(K,K,K,1); +} + + +float4 PSSobelOperator(float2 vPos : VPOS,float2 TextureUV : TEXCOORD0) : COLOR0 +{ + float color11 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,-screen_inc_y)).r; + float color12 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,0)).r; + float color13 = tex2D(baseMap, TextureUV+float2(-screen_inc_x,screen_inc_y)).r; + + float color21 = tex2D(baseMap, TextureUV+float2(0,-screen_inc_y)).r; + float color22 = tex2D(baseMap, TextureUV+float2(0,0)).r; + float color23 = tex2D(baseMap, TextureUV+float2(0,screen_inc_y)).r; + + float color31 = tex2D(baseMap, TextureUV+float2(screen_inc_x,-screen_inc_y)).r; + float color32 = tex2D(baseMap, TextureUV+float2(screen_inc_x,0)).r; + float color33 = tex2D(baseMap, TextureUV+float2(screen_inc_x,screen_inc_y)).r; + + float Gx = -color11 + color13 -2*color22 + 2*color23 -color31 + color33; + float Gy = -color11 - 2*color21 - color13 + color31 + 2*color32+color33; + float gradiente = sqrt(Gx*Gx + Gy*Gy); + float angulo = atan2(Gy,Gx); + return float4(gradiente,gradiente,gradiente,1); +} + + + +technique ImageFilter +{ + pass p0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSIntensidad(); + } + pass p1 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSErotionFilter(); + } + + pass p2 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSSobelOperator(); + } + + pass p3 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSGaussianBlur(); + } +} + + +float4 PSMotionDetect(float2 vPos : VPOS,float2 TextureUV : TEXCOORD0) : COLOR0 +{ + return tex2D(RenderTarget,TextureUV); + + /* + float t = distance(tex2D(RenderTarget, TextureUV) , tex2D(RenderTargetAnt,TextureUV)); + if(t>0.5) + t = 1; + else + t = 0; + //return float4(t,t,t,1); + + return tex2D(baseMap, TextureUV) + float4(0,t,t,1); + */ + + +} + +technique motionDetect +{ + pass p0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 PSMotionDetect(); + } +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/MotionBlur.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/MotionBlur.fx new file mode 100644 index 00000000..fc992277 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/MotionBlur.fx @@ -0,0 +1,226 @@ +// --------------------------------------------------------- +// Ejemplo toon Shading +// --------------------------------------------------------- + +/**************************************************************************************/ +/* Variables comunes */ +/**************************************************************************************/ + +//Matrices de transformacion +float4x4 matWorld; //Matriz de transformacion World +float4x4 matWorldView; //Matriz World * View +float4x4 matWorldViewProj; //Matriz World * View * Projection +float4x4 matInverseTransposeWorld; //Matriz Transpose(Invert(World)) +float4x4 matWorldViewProjAnt; //Matriz World * View * Proj anterior + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = MIRROR; + ADDRESSV = MIRROR; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; + +//Input del Vertex Shader +struct VS_INPUT +{ + float4 Position : POSITION0; + float3 Normal : NORMAL0; + float4 Color : COLOR; + float2 Texcoord : TEXCOORD0; +}; + +texture g_RenderTarget; +sampler RenderTarget = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +texture texVelocityMap; +sampler2D velocityMap = sampler_state +{ + Texture = (texVelocityMap); + MinFilter = POINT; + MagFilter = POINT; + AddressU = Clamp; + AddressV = Clamp; +}; + +texture texVelocityMapAnt; +sampler2D velocityMapAnt = sampler_state +{ + Texture = (texVelocityMapAnt); + MinFilter = POINT; + MagFilter = POINT; + AddressU = Clamp; + AddressV = Clamp; +}; + +//Output del Vertex Shader +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 Texcoord : TEXCOORD0; + float3 Norm : TEXCOORD1; // Normales + float3 Pos : TEXCOORD2; // Posicion real 3d + float2 Vel : TEXCOORD3; // velocidad por pixel + +}; + +//Vertex Shader +VS_OUTPUT vs_main( VS_INPUT Input ) +{ + VS_OUTPUT Output; + + //Proyectar posicion + Output.Position = mul( Input.Position, matWorldViewProj); + + //Las Texcoord quedan igual + Output.Texcoord = Input.Texcoord; + + // Calculo la posicion real + float4 pos_real = mul(Input.Position,matWorld); + Output.Pos = float3(pos_real.x,pos_real.y,pos_real.z); + + // Transformo la normal y la normalizo + Output.Norm = normalize(mul(Input.Normal,matWorld)); + + + // Computo la velocidad del vertice + // posicion actual + float4 vPosActual = Output.Position; + // posicion anterior + float4 vPosAnterior = mul( Input.Position,matWorldViewProjAnt); + vPosActual /= vPosActual.w; + vPosAnterior /= vPosAnterior.w; + float2 velocity = vPosActual - vPosAnterior; + // lo propago + Output.Vel = velocity; + + + + return( Output ); + +} + +//Pixel Shader +float4 ps_main( float3 Texcoord: TEXCOORD0) : COLOR0 +{ + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + if(fvBaseColor.a<0.1) + discard; + return fvBaseColor; +} + + +//Pixel Shader Velocity +float4 ps_velocity( float3 Texcoord: TEXCOORD0, float2 Vel:TEXCOORD3) : COLOR0 +{ + //Obtener el texel de textura + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + if(fvBaseColor.a<0.1) + discard; + return float4(Vel.x,Vel.y,0.0f,1.0f); +} + +technique DefaultTechnique +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } +} + +technique VelocityMap +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_velocity(); + } + +} + + + + +void vs_copy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + +float PixelBlurConst = 400; +static const float NumberOfPostProcessSamples = 12.0f; + +float4 ps_motion_blur( in float2 Tex : TEXCOORD0) : COLOR0 +{ + float4 curFramePixelVelocity = tex2D(velocityMap, Tex); + float4 lastFramePixelVelocity = tex2D(velocityMapAnt, Tex); + + float2 pixelVelocity; + float curVelocitySqMag = curFramePixelVelocity.r * curFramePixelVelocity.r + + curFramePixelVelocity.g * curFramePixelVelocity.g; + float lastVelocitySqMag = lastFramePixelVelocity.r * lastFramePixelVelocity.r + + lastFramePixelVelocity.g * lastFramePixelVelocity.g; + + if( lastVelocitySqMag > curVelocitySqMag ) + { + pixelVelocity.x = lastFramePixelVelocity.r * PixelBlurConst; + pixelVelocity.y = -lastFramePixelVelocity.g * PixelBlurConst; + } + else + { + pixelVelocity.x = curFramePixelVelocity.r * PixelBlurConst; + pixelVelocity.y = -curFramePixelVelocity.g * PixelBlurConst; + } + + + //= curFramePixelVelocity.rg* PixelBlurConst; + //pixelVelocity.y *= -1; + + float3 Blurred = 0; + for(float i = 0; i < NumberOfPostProcessSamples; i++) + { + float2 lookup = pixelVelocity * i / NumberOfPostProcessSamples + Tex; + float4 Current = tex2D(RenderTarget, lookup); + Blurred += Current.rgb; + } + return float4(Blurred / NumberOfPostProcessSamples, 1.0f); + +// return tex2D(velocityMap,Tex) ; +// return tex2D(RenderTarget,Tex) ; + +} + + + + +technique PostProcessMotionBlur +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 ps_motion_blur(); + } + +} + + diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/OutRun.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/OutRun.fx new file mode 100644 index 00000000..999e6014 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/OutRun.fx @@ -0,0 +1,179 @@ +// --------------------------------------------------------- +// Ejemplo toon Shading +// --------------------------------------------------------- + +/**************************************************************************************/ +/* Variables comunes */ +/**************************************************************************************/ + +//Matrices de transformacion +float4x4 matWorld; //Matriz de transformacion World +float4x4 matWorldView; //Matriz World * View +float4x4 matWorldViewProj; //Matriz World * View * Projection +float4x4 matInverseTransposeWorld; //Matriz Transpose(Invert(World)) + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = MIRROR; + ADDRESSV = MIRROR; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; + + +//Input del Vertex Shader +struct VS_INPUT +{ + float4 Position : POSITION0; + float3 Normal : NORMAL0; + float4 Color : COLOR; + float2 Texcoord : TEXCOORD0; +}; + +texture g_RenderTarget; +sampler RenderTarget = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture g_RenderTarget2; +sampler RenderTarget2 = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture g_RenderTarget3; +sampler RenderTarget3 = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture g_RenderTarget4; +sampler RenderTarget4 = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture g_RenderTarget5; +sampler RenderTarget5 = +sampler_state +{ + Texture = ; + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +//Output del Vertex Shader +struct VS_OUTPUT +{ + float4 Position : POSITION0; + float2 Texcoord : TEXCOORD0; + float3 Norm : TEXCOORD1; // Normales + float3 Pos : TEXCOORD2; // Posicion real 3d +}; + +//Vertex Shader +VS_OUTPUT vs_main( VS_INPUT Input ) +{ + VS_OUTPUT Output; + + //Proyectar posicion + Output.Position = mul( Input.Position, matWorldViewProj); + + //Las Texcoord quedan igual + Output.Texcoord = Input.Texcoord; + + // Calculo la posicion real + float4 pos_real = mul(Input.Position,matWorld); + Output.Pos = float3(pos_real.x,pos_real.y,pos_real.z); + + // Transformo la normal y la normalizo + //Output.Norm = normalize(mul(Input.Normal,matInverseTransposeWorld)); + Output.Norm = normalize(mul(Input.Normal,matWorld)); + return( Output ); + +} + +//Pixel Shader +float4 ps_main( float3 Texcoord: TEXCOORD0, float3 N:TEXCOORD1, + float3 Pos: TEXCOORD2) : COLOR0 +{ + //Obtener el texel de textura + float4 fvBaseColor = tex2D( diffuseMap, Texcoord ); + if(fvBaseColor.a<0.1) + discard; + return fvBaseColor; +} + +technique DefaultTechnique +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 vs_main(); + PixelShader = compile ps_3_0 ps_main(); + } +} + + + +void VSCopy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + +float4 PSFrameCombine( in float2 Tex : TEXCOORD0 , in float2 vpos : VPOS) : COLOR0 +{ + return (tex2D(RenderTarget,Tex) + tex2D(RenderTarget2,Tex) + tex2D(RenderTarget3,Tex) + + + tex2D(RenderTarget4,Tex)+ + tex2D(RenderTarget5,Tex)) *0.2; +} + + +technique FrameMotionBlur +{ + pass Pass_0 + { + VertexShader = compile vs_3_0 VSCopy(); + PixelShader = compile ps_3_0 PSFrameCombine(); + } + +} + + diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/Parallax.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/Parallax.fx new file mode 100644 index 00000000..7f939c5a --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/Parallax.fx @@ -0,0 +1,252 @@ + +float time = 0; + +float3 g_LightDir = float3(0,-1,0); +float3 fvEyePosition = float3( 0.00, 0.00, -100.00 ); +float g_fSpecularExponent = 3; +float k_ld = 0.5; // luz difusa +float k_le = 0.6; // luz specular +float k_la = 0.4; // luz ambiente +bool phong_lighting = true; + +float min_cant_samples = 10; +float max_cant_samples = 50; + +// Transformaciones +float4x4 matWorld; +float4x4 matWorldView; +float4x4 matWorldViewProj; +float4x4 matInverseTransposeWorld; + +float fHeightMapScale = 0.1; +float fTexScale = 10; + +//Textura para DiffuseMap +texture texDiffuseMap; +sampler2D diffuseMap = sampler_state +{ + Texture = (texDiffuseMap); + ADDRESSU = WRAP; + ADDRESSV = WRAP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +// Textura basica: +texture base_Tex; +sampler2D baseMap = +sampler_state +{ + Texture = (base_Tex); + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +texture aux_Tex; +sampler2D auxMap = +sampler_state +{ + Texture = ; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + +// Heighmap +texture height_map; +sampler2D heightMap = +sampler_state +{ + Texture = ; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + + +// calcula la iluminaciond dinamica +float4 Phong( float2 texCoord, float3 vLightTS, float3 vViewTS,float dx,float dy) +{ + // Color Basico + float4 cBaseColor = tex2Dgrad( auxMap, texCoord,dx,dy ); + if(phong_lighting) + { + // Busco el vector normal en la textura Normal-Height Map (esta en Tangent Space) + float3 vNormalTS = normalize( tex2Dgrad( heightMap, texCoord ,dx,dy) * 2 - 1 ); + + + // Color difuso + float3 vLightTSAdj = float3( vLightTS.x, -vLightTS.y, vLightTS.z ); + float cDiffuse = saturate( dot( vNormalTS, vLightTSAdj)) * k_ld; + + // Color specular + float4 cSpecular = 0; + float3 vReflectionTS = normalize( 2 * dot( vViewTS, vNormalTS ) * vNormalTS - vViewTS ); + float fRdotL = saturate( dot( vReflectionTS, vLightTSAdj )); + cSpecular = saturate( pow( fRdotL, g_fSpecularExponent))*k_le; + + // Retorno color difuso + luz especular + cBaseColor = (k_la+cDiffuse)*cBaseColor + cSpecular; + } + return cBaseColor; +} + + +void RenderSceneVS( float4 Pos : POSITION, + float2 Texcoord : TEXCOORD0, + float3 normal : NORMAL, + out float4 oPos : POSITION, + out float2 Tex : TEXCOORD0, + out float3 tsView : TEXCOORD1, + out float3 tsLight : TEXCOORD3, + out float3 wsNormal : TEXCOORD2, + out float3 wsView : TEXCOORD4 + ) +{ + + // Vector View = desde el ojo a la pos del vertice + float4 VertexPositionWS = mul( Pos,matWorld ); + wsView = fvEyePosition.xyz - VertexPositionWS.xyz; + + + // calculo la tg y la binormal ? + float3 up = float3(0,0,1); + if(abs(normal.z-1)<=0.0001) + up = float3(0,1,0); + float3 tangent = cross(normal,up); + float3 binormal = cross(normal,tangent); + + /* + // o la dejo fija? + normal = float3(0,1,0); + float3 tangent = float3(1,0,0); + float3 binormal = float3(0,0,1); + */ + + float3x3 tangentToWorldSpace; + tangentToWorldSpace[0] = mul( tangent, matWorld ); + tangentToWorldSpace[1] = mul( binormal, matWorld); + tangentToWorldSpace[2] = mul( normal, matWorld); + + // tangentToWorldSpace es una matriz ortogonal, su inversa = a su transpuesta + // A es OrtoNorm <=> A-1 == At + float3x3 worldToTangentSpace = transpose(tangentToWorldSpace); + + // proyecto + oPos = mul( Pos, matWorldViewProj ); + //Propago la textura + Tex = Texcoord*fTexScale; + + tsView = mul( wsView, worldToTangentSpace ); // Vector View en TangentSpace + tsLight = mul( g_LightDir, worldToTangentSpace); // Vector Light en TangentSpace + + // propago el vector normal en Worldspace + wsNormal = normal; + // tambien devuelve el vector view en worldspace wsView + + } + + +// ws = worldspace ts = tangentspace +float4 PSParallaxOcclusion( float2 Texcoord: TEXCOORD0, + float3 Pos: POSITION, + float3 tsView: TEXCOORD1, + float3 wsNormal: TEXCOORD2, + float3 tsLight: TEXCOORD3, + float3 wsView: TEXCOORD4 + ) : COLOR0 +{ + // normalizo todo lo que interpola el PS + wsView = normalize(wsView); + tsView = normalize(tsView); + tsLight = normalize(tsLight); + wsNormal = normalize(wsNormal); + + // POM Algoritmo Standard + float fParallaxLimit = length(tsView.xy) / tsView.z; + fParallaxLimit *= fHeightMapScale; + float2 vOffset = normalize( -tsView.xy); + vOffset = vOffset * fParallaxLimit; + // interpola entre un min y un max, proporcionalmente al angulo de vision + int nNumSamples = (int)lerp( min_cant_samples ,max_cant_samples, + abs(dot(wsView,wsNormal))); + float fStepSize = 1.0 / (float)nNumSamples; + + float2 dx, dy; + dx = ddx( Texcoord ); + dy = ddy( Texcoord ); + + // Ray casting: + float2 vOffsetStep = fStepSize * vOffset; + float2 vCurrOffset = float2( 0, 0 ); + float2 vLastOffset = float2( 0, 0 ); + + float fCurrH = 0; + float fLastH = 0; + + float stepHeight = 1.0; + int nCurrSample = 0; + float4 vCurrSample; + float4 vLastSample; + + while ( nCurrSample < nNumSamples ) + { + vCurrSample = tex2Dgrad( heightMap, Texcoord + vCurrOffset, dx, dy ); + fCurrH = vCurrSample.a; + if ( fCurrH > stepHeight) + { + float Ua = 0; + float X = ( fStepSize + (fCurrH - fLastH)); + if(X!=0.0f) + Ua = ((stepHeight+fStepSize)- fLastH) / X; + vCurrOffset = vLastOffset + Ua* vOffsetStep; + nCurrSample = nNumSamples + 1; + } + else + { + nCurrSample++; + stepHeight -= fStepSize; + vLastOffset = vCurrOffset; + vCurrOffset += vOffsetStep; + vLastSample = vCurrSample; + fLastH = fCurrH; + } + } + + return Phong( Texcoord + vCurrOffset, tsLight, -tsView,dx,dy); +} + +// Parallax oclussion +technique ParallaxOcclusion +{ + pass p0 + { + VertexShader = compile vs_3_0 RenderSceneVS(); + PixelShader = compile ps_3_0 PSParallaxOcclusion(); + } +} + +float4 PSBumpMap(float2 Texcoord: TEXCOORD0, + float3 Pos: POSITION, + float3 tsView: TEXCOORD1, + float3 wsNormal: TEXCOORD2, + float3 tsLight: TEXCOORD3 + ) : COLOR0 +{ + return Phong( Texcoord, tsLight, -tsView,ddx( Texcoord),ddy( Texcoord )); +} + + +technique BumpMap +{ + pass p0 + { + VertexShader = compile vs_3_0 RenderSceneVS(); + PixelShader = compile ps_3_0 PSBumpMap(); + } +} + diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/VolRender.fx b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/VolRender.fx new file mode 100644 index 00000000..c540c68c --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/Shaders/VolRender.fx @@ -0,0 +1,39 @@ + +float screen_dx; // tamaño de la pantalla en pixels +float screen_dy; + +//Textura utilizada por el Pixel Shader +texture tex_buffer; +sampler2D buffer = +sampler_state +{ + Texture = (tex_buffer); + ADDRESSU = CLAMP; + ADDRESSV = CLAMP; + MINFILTER = LINEAR; + MAGFILTER = LINEAR; + MIPFILTER = LINEAR; +}; + + +void vs_copy( float4 vPos : POSITION, float2 vTex : TEXCOORD0,out float4 oPos : POSITION,out float2 oScreenPos: TEXCOORD0) +{ + oPos = vPos; + oScreenPos = vTex; + oPos.w = 1; +} + + +float4 ps_raytracing(float2 vPos : VPOS,float2 texcoords : TEXCOORD0) : COLOR0 +{ + return tex2D(buffer,texcoords); +} + +technique volRender +{ + pass p0 + { + VertexShader = compile vs_3_0 vs_copy(); + PixelShader = compile ps_3_0 ps_raytracing(); + } +} \ No newline at end of file diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/ToonShading.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/ToonShading.cs index 796217e5..aba22104 100644 --- a/TgcViewer/Examples/Shaders/WorkshopShaders/ToonShading.cs +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/ToonShading.cs @@ -1,283 +1,283 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using TgcViewer.Example; -using TgcViewer; -using Microsoft.DirectX.Direct3D; -using Microsoft.DirectX; -using TgcViewer.Utils.TgcSceneLoader; -using System.Drawing; -using TgcViewer.Utils.TgcGeometry; -using TgcViewer.Utils.Terrain; +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; using TgcViewer.Utils.Input; -using TgcViewer.Utils.Shaders; - -namespace Examples.Shaders.WorkshopShaders -{ - - /// - /// Ejemplo ShadowMap: - /// Unidades Involucradas: - /// # Unidad 8 - Adaptadores de Video - Shaders +using TgcViewer.Utils.Shaders; + +namespace Examples.Shaders.WorkshopShaders +{ + + /// + /// Ejemplo ShadowMap: + /// Unidades Involucradas: + /// # Unidad 8 - Adaptadores de Video - Shaders + /// + /// Ejemplo avanzado. Ver primero ejemplo "Shaders/WorkshopShaders/BasicShader". /// - /// Ejemplo avanzado. Ver primero ejemplo "Shaders/WorkshopShaders/BasicShader". - /// - /// Muestra como utilizar el efecto de ToonShading, que le da a un mesh un aspecto de caricatura. - /// - /// Autor: Mariano Banquiero - /// - /// - public class ToonShading: TgcExample - { - string MyMediaDir; - string MyShaderDir; - TgcScene scene; + /// Muestra como utilizar el efecto de ToonShading, que le da a un mesh un aspecto de caricatura. + /// + /// Autor: Mariano Banquiero + /// + /// + public class ToonShading: TgcExample + { + string MyMediaDir; + string MyShaderDir; + TgcScene scene; TgcMesh mesh; - List instances; - Effect effect; - Surface g_pDepthStencil; // Depth-stencil buffer - Texture g_pRenderTarget; - Texture g_pNormals; - VertexBuffer g_pVBV3D; - bool efecto_blur; - - - public override string getCategory() - { - return "Shaders"; - } - - public override string getName() - { - return "Workshop-ToonShading"; - } - - public override string getDescription() - { - return "Ejemplo de Render no-realistico. [BARRA]->Activa/Desactiva efecto Blur"; - } - - public override void init() - { - Device d3dDevice = GuiController.Instance.D3dDevice; - MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; - MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; - - //Crear loader - TgcSceneLoader loader = new TgcSceneLoader(); - - //Cargar mesh - scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir - + "ModelosTgc\\Teapot\\Teapot-TgcScene.xml"); - - mesh = scene.Meshes[0]; - mesh.Scale = new Vector3(1f, 1f, 1f); - mesh.Position = new Vector3(-100f, -5f, 0f); - - // Arreglo las normales - int [] adj = new int[mesh.D3dMesh.NumberFaces*3]; - mesh.D3dMesh.GenerateAdjacency(0,adj); - mesh.D3dMesh.ComputeNormals(adj); + List instances; + Effect effect; + Surface g_pDepthStencil; // Depth-stencil buffer + Texture g_pRenderTarget; + Texture g_pNormals; + VertexBuffer g_pVBV3D; + bool efecto_blur; + + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-ToonShading"; + } + + public override string getDescription() + { + return "Ejemplo de Render no-realistico. [BARRA]->Activa/Desactiva efecto Blur"; + } + + public override void init() + { + Device d3dDevice = GuiController.Instance.D3dDevice; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + //Crear loader + TgcSceneLoader loader = new TgcSceneLoader(); + + //Cargar mesh + scene = loader.loadSceneFromFile(GuiController.Instance.ExamplesMediaDir + + "ModelosTgc\\Teapot\\Teapot-TgcScene.xml"); + + mesh = scene.Meshes[0]; + mesh.Scale = new Vector3(1f, 1f, 1f); + mesh.Position = new Vector3(-100f, -5f, 0f); + + // Arreglo las normales + int [] adj = new int[mesh.D3dMesh.NumberFaces*3]; + mesh.D3dMesh.GenerateAdjacency(0,adj); + mesh.D3dMesh.ComputeNormals(adj); //Cargar Shader personalizado - effect = TgcShaders.loadEffect(GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\ToonShading.fx"); - - // le asigno el efecto a la malla + effect = TgcShaders.loadEffect(GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\ToonShading.fx"); + + // le asigno el efecto a la malla mesh.Effect = effect; - mesh.Technique = "DefaultTechnique"; - - // Creo las instancias de malla - instances = new List(); - for (int i = -5; i < 5; i++) - for (int j = -5; j < 5; j++) + mesh.Technique = "DefaultTechnique"; + + // Creo las instancias de malla + instances = new List(); + for (int i = -5; i < 5; i++) + for (int j = -5; j < 5; j++) { - TgcMesh instance = mesh.createMeshInstance(mesh.Name + i); - instance.move(i * 50, (i + j) * 5, j * 50); - instances.Add(instance); - } - - - GuiController.Instance.Modifiers.addVertex3f("LightPosition", new Vector3(-100, -100, -100), new Vector3(100, 100, 100), new Vector3(0, 40, 0)); - GuiController.Instance.Modifiers.addFloat("Ambient", 0, 1, 0.5f); - GuiController.Instance.Modifiers.addFloat("Diffuse", 0, 1, 0.6f); - GuiController.Instance.Modifiers.addFloat("Specular", 0, 1, 0.5f); - GuiController.Instance.Modifiers.addFloat("SpecularPower", 1, 100, 16); - - GuiController.Instance.RotCamera.setCamera(new Vector3(20, 20, 0), 200); - GuiController.Instance.RotCamera.CameraDistance = 300; - GuiController.Instance.RotCamera.RotationSpeed = 1.5f; - - // Creo un depthbuffer sin multisampling, para que sea compatible con el render to texture - - // Nota: - // El render to Texture no es compatible con el multisampling en dx9 - // Por otra parte la mayor parte de las placas de ultima generacion no soportan - // mutisampling para texturas de punto flotante con lo cual - // hay que suponer con generalidad que no se puede usar multisampling y render to texture - - // Para resolverlo hay que crear un depth buffer que no tenga multisampling, - // (de lo contrario falla el zbuffer y se producen artifacts tipicos de que no tiene zbuffer) - - // Si uno quisiera usar el multisampling, la tecnica habitual es usar un RenderTarget - // en lugar de una textura. - // Por ejemplo en c++: - // - // Render Target formato color buffer con multisampling - // - // g_pd3dDevice->CreateRenderTarget(Ancho,Alto, - // D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, - // FALSE, &g_pRenderTarget, NULL); - // - // Luego, ese RenderTarget NO ES una textura, y nosotros necesitamos acceder a esos - // pixeles, ahi lo que se hace es COPIAR del rendertartet a una textura, - // para poder trabajar con esos datos en el contexto del Pixel shader: - // - // Eso se hace con la funcion StretchRect: - // copia de rendertarget ---> sceneSurface (que es la superficie asociada a una textura) - // g_pd3dDevice->StretchRect(g_pRenderTarget, NULL, g_pSceneSurface, NULL, D3DTEXF_NONE); - // - // Esta tecnica se llama downsampling - // Y tiene el costo adicional de la transferencia de memoria entre el rendertarget y la - // textura, pero que no traspasa los limites de la GPU. (es decir es muy performante) - // no es lo mismo que lockear una textura para acceder desde la CPU, que tiene el problema - // de transferencia via AGP. - - g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, - d3dDevice.PresentationParameters.BackBufferHeight, - DepthFormat.D24S8, - MultiSampleType.None, - 0, - true); - - // inicializo el render target - g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth - , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, - Format.X8R8G8B8, Pool.Default); - - effect.SetValue("g_RenderTarget", g_pRenderTarget); - - // inicializo el mapa de normales - g_pNormals = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth - , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, - Format.A16B16G16R16F, Pool.Default); - - effect.SetValue("g_Normals", g_pNormals); - - // Resolucion de pantalla - effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); - effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); - - //Se crean 2 triangulos con las dimensiones de la pantalla con sus posiciones ya transformadas - // x = -1 es el extremo izquiedo de la pantalla, x=1 es el extremo derecho - // Lo mismo para la Y con arriba y abajo - // la Z en 1 simpre - CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] - { - new CustomVertex.PositionTextured( -1, 1, 1, 0,0), - new CustomVertex.PositionTextured(1, 1, 1, 1,0), - new CustomVertex.PositionTextured(-1, -1, 1, 0,1), - new CustomVertex.PositionTextured(1,-1, 1, 1,1) - }; - //vertex buffer de los triangulos - g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), - 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, - CustomVertex.PositionTextured.Format, Pool.Default); - g_pVBV3D.SetData(vertices, 0, LockFlags.None); - - efecto_blur = false; - - } - - - public override void render(float elapsedTime) - { - Device device = GuiController.Instance.D3dDevice; - Control panel3d = GuiController.Instance.Panel3d; - float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; - - Vector3 lightPosition = (Vector3)GuiController.Instance.Modifiers["LightPosition"]; - - if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.Space)) - efecto_blur = !efecto_blur; - - - //Cargar variables de shader - effect.SetValue("fvLightPosition", TgcParserUtils.vector3ToFloat3Array(lightPosition)); - effect.SetValue("fvEyePosition", TgcParserUtils.vector3ToFloat3Array(GuiController.Instance.RotCamera.getPosition())); - effect.SetValue("k_la", (float)GuiController.Instance.Modifiers["Ambient"]); - effect.SetValue("k_ld", (float)GuiController.Instance.Modifiers["Diffuse"]); - effect.SetValue("k_ls", (float)GuiController.Instance.Modifiers["Specular"]); - effect.SetValue("fSpecularPower", (float)GuiController.Instance.Modifiers["SpecularPower"]); - - device.EndScene(); - - // dibujo la escena una textura - effect.Technique = "DefaultTechnique"; - // guardo el Render target anterior y seteo la textura como render target - Surface pOldRT = device.GetRenderTarget(0); - Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); - device.SetRenderTarget(0, pSurf); - // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling - Surface pOldDS = device.DepthStencilSurface; - // Probar de comentar esta linea, para ver como se produce el fallo en el ztest - // por no soportar usualmente el multisampling en el render to texture. - device.DepthStencilSurface = g_pDepthStencil; - - device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); - device.BeginScene(); - foreach (TgcMesh instance in instances) - { - instance.Technique = "DefaultTechnique"; - instance.render(); - } - device.EndScene(); - //TextureLoader.Save("scene.bmp", ImageFileFormat.Bmp, g_pRenderTarget); - - - // genero el normal map: - pSurf = g_pNormals.GetSurfaceLevel(0); - device.SetRenderTarget(0, pSurf); - device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); - device.BeginScene(); - foreach (TgcMesh instance in instances) + TgcMesh instance = mesh.createMeshInstance(mesh.Name + i); + instance.move(i * 50, (i + j) * 5, j * 50); + instances.Add(instance); + } + + + GuiController.Instance.Modifiers.addVertex3f("LightPosition", new Vector3(-100, -100, -100), new Vector3(100, 100, 100), new Vector3(0, 40, 0)); + GuiController.Instance.Modifiers.addFloat("Ambient", 0, 1, 0.5f); + GuiController.Instance.Modifiers.addFloat("Diffuse", 0, 1, 0.6f); + GuiController.Instance.Modifiers.addFloat("Specular", 0, 1, 0.5f); + GuiController.Instance.Modifiers.addFloat("SpecularPower", 1, 100, 16); + + GuiController.Instance.RotCamera.setCamera(new Vector3(20, 20, 0), 200); + GuiController.Instance.RotCamera.CameraDistance = 300; + GuiController.Instance.RotCamera.RotationSpeed = 1.5f; + + // Creo un depthbuffer sin multisampling, para que sea compatible con el render to texture + + // Nota: + // El render to Texture no es compatible con el multisampling en dx9 + // Por otra parte la mayor parte de las placas de ultima generacion no soportan + // mutisampling para texturas de punto flotante con lo cual + // hay que suponer con generalidad que no se puede usar multisampling y render to texture + + // Para resolverlo hay que crear un depth buffer que no tenga multisampling, + // (de lo contrario falla el zbuffer y se producen artifacts tipicos de que no tiene zbuffer) + + // Si uno quisiera usar el multisampling, la tecnica habitual es usar un RenderTarget + // en lugar de una textura. + // Por ejemplo en c++: + // + // Render Target formato color buffer con multisampling + // + // g_pd3dDevice->CreateRenderTarget(Ancho,Alto, + // D3DFMT_A8R8G8B8, D3DMULTISAMPLE_2_SAMPLES, 0, + // FALSE, &g_pRenderTarget, NULL); + // + // Luego, ese RenderTarget NO ES una textura, y nosotros necesitamos acceder a esos + // pixeles, ahi lo que se hace es COPIAR del rendertartet a una textura, + // para poder trabajar con esos datos en el contexto del Pixel shader: + // + // Eso se hace con la funcion StretchRect: + // copia de rendertarget ---> sceneSurface (que es la superficie asociada a una textura) + // g_pd3dDevice->StretchRect(g_pRenderTarget, NULL, g_pSceneSurface, NULL, D3DTEXF_NONE); + // + // Esta tecnica se llama downsampling + // Y tiene el costo adicional de la transferencia de memoria entre el rendertarget y la + // textura, pero que no traspasa los limites de la GPU. (es decir es muy performante) + // no es lo mismo que lockear una textura para acceder desde la CPU, que tiene el problema + // de transferencia via AGP. + + g_pDepthStencil = d3dDevice.CreateDepthStencilSurface(d3dDevice.PresentationParameters.BackBufferWidth, + d3dDevice.PresentationParameters.BackBufferHeight, + DepthFormat.D24S8, + MultiSampleType.None, + 0, + true); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + // inicializo el mapa de normales + g_pNormals = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.A16B16G16R16F, Pool.Default); + + effect.SetValue("g_Normals", g_pNormals); + + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + + //Se crean 2 triangulos con las dimensiones de la pantalla con sus posiciones ya transformadas + // x = -1 es el extremo izquiedo de la pantalla, x=1 es el extremo derecho + // Lo mismo para la Y con arriba y abajo + // la Z en 1 simpre + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + //vertex buffer de los triangulos + g_pVBV3D = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVBV3D.SetData(vertices, 0, LockFlags.None); + + efecto_blur = false; + + } + + + public override void render(float elapsedTime) + { + Device device = GuiController.Instance.D3dDevice; + Control panel3d = GuiController.Instance.Panel3d; + float aspectRatio = (float)panel3d.Width / (float)panel3d.Height; + + Vector3 lightPosition = (Vector3)GuiController.Instance.Modifiers["LightPosition"]; + + if (GuiController.Instance.D3dInput.keyPressed(Microsoft.DirectX.DirectInput.Key.Space)) + efecto_blur = !efecto_blur; + + + //Cargar variables de shader + effect.SetValue("fvLightPosition", TgcParserUtils.vector3ToFloat3Array(lightPosition)); + effect.SetValue("fvEyePosition", TgcParserUtils.vector3ToFloat3Array(GuiController.Instance.RotCamera.getPosition())); + effect.SetValue("k_la", (float)GuiController.Instance.Modifiers["Ambient"]); + effect.SetValue("k_ld", (float)GuiController.Instance.Modifiers["Diffuse"]); + effect.SetValue("k_ls", (float)GuiController.Instance.Modifiers["Specular"]); + effect.SetValue("fSpecularPower", (float)GuiController.Instance.Modifiers["SpecularPower"]); + + device.EndScene(); + + // dibujo la escena una textura + effect.Technique = "DefaultTechnique"; + // guardo el Render target anterior y seteo la textura como render target + Surface pOldRT = device.GetRenderTarget(0); + Surface pSurf = g_pRenderTarget.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + // hago lo mismo con el depthbuffer, necesito el que no tiene multisampling + Surface pOldDS = device.DepthStencilSurface; + // Probar de comentar esta linea, para ver como se produce el fallo en el ztest + // por no soportar usualmente el multisampling en el render to texture. + device.DepthStencilSurface = g_pDepthStencil; + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + foreach (TgcMesh instance in instances) + { + instance.Technique = "DefaultTechnique"; + instance.render(); + } + device.EndScene(); + //TextureLoader.Save("scene.bmp", ImageFileFormat.Bmp, g_pRenderTarget); + + + // genero el normal map: + pSurf = g_pNormals.GetSurfaceLevel(0); + device.SetRenderTarget(0, pSurf); + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + device.BeginScene(); + foreach (TgcMesh instance in instances) { - instance.Technique = "NormalMap"; - instance.render(); - } - - device.EndScene(); - // restuaro el render target y el stencil - device.DepthStencilSurface = pOldDS; - device.SetRenderTarget(0, pOldRT); - //TextureLoader.Save("normal.bmp", ImageFileFormat.Bmp, g_pNormals); - - // dibujo el quad pp dicho : - device.BeginScene(); - effect.Technique = efecto_blur? "CopyScreen" : "EdgeDetect"; - device.VertexFormat = CustomVertex.PositionTextured.Format; - device.SetStreamSource(0, g_pVBV3D, 0); - effect.SetValue("g_Normals", g_pNormals); - effect.SetValue("g_RenderTarget", g_pRenderTarget); - - device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); - effect.Begin(FX.None); - effect.BeginPass(0); - device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); - effect.EndPass(); - effect.End(); - - } - - public override void close() - { - effect.Dispose(); - scene.disposeAll(); - g_pRenderTarget.Dispose(); - g_pNormals.Dispose(); - g_pVBV3D.Dispose(); - g_pDepthStencil.Dispose(); - } - } - -} + instance.Technique = "NormalMap"; + instance.render(); + } + + device.EndScene(); + // restuaro el render target y el stencil + device.DepthStencilSurface = pOldDS; + device.SetRenderTarget(0, pOldRT); + //TextureLoader.Save("normal.bmp", ImageFileFormat.Bmp, g_pNormals); + + // dibujo el quad pp dicho : + device.BeginScene(); + effect.Technique = efecto_blur? "CopyScreen" : "EdgeDetect"; + device.VertexFormat = CustomVertex.PositionTextured.Format; + device.SetStreamSource(0, g_pVBV3D, 0); + effect.SetValue("g_Normals", g_pNormals); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + + device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.Begin(FX.None); + effect.BeginPass(0); + device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + + } + + public override void close() + { + effect.Dispose(); + scene.disposeAll(); + g_pRenderTarget.Dispose(); + g_pNormals.Dispose(); + g_pVBV3D.Dispose(); + g_pDepthStencil.Dispose(); + } + } + +} diff --git a/TgcViewer/Examples/Shaders/WorkshopShaders/VideoPostProcess.cs b/TgcViewer/Examples/Shaders/WorkshopShaders/VideoPostProcess.cs new file mode 100644 index 00000000..fc3fc536 --- /dev/null +++ b/TgcViewer/Examples/Shaders/WorkshopShaders/VideoPostProcess.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using TgcViewer.Example; +using TgcViewer; +using Microsoft.DirectX.Direct3D; +using Microsoft.DirectX; +using TgcViewer.Utils.TgcSceneLoader; +using System.Drawing; +using TgcViewer.Utils.TgcGeometry; +using TgcViewer.Utils.Terrain; +using TgcViewer.Utils.Input; + +namespace Examples.Shaders +{ + + public class EjemploVideoPostProcess: TgcExample + { + string MyMediaDir; + string MyShaderDir; + + int cur_frame; + float time; + VertexBuffer g_pVB; + Texture[] g_pVideoBuffer; + Texture g_pVideoFrame; + int cant_frames; + Effect effect; + Texture g_pRenderTarget; + Texture g_pRenderTarget_ant; + + // Render Target pasadas + Texture g_pRenderTarget_A; + Texture g_pRenderTarget_B; + Texture g_pRenderTarget_C; + private Surface pOldRT; + private Surface pOldDS; + private Surface pSurf; + + public override string getCategory() + { + return "Shaders"; + } + + public override string getName() + { + return "Workshop-VideoPostProcess"; + } + + public override string getDescription() + { + return "Procesamiento de imagenes"; + } + + public override void init() + { + Device d3dDevice = GuiController.Instance.D3dDevice; + GuiController.Instance.CustomRenderEnabled = true; + MyMediaDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Media\\"; + MyShaderDir = GuiController.Instance.ExamplesDir + "Shaders\\WorkshopShaders\\Shaders\\"; + + cur_frame = 0; + time = 0; + g_pVideoBuffer = new Texture[500]; + + + GuiController.Instance.RotCamera.Enable = true; + GuiController.Instance.RotCamera.setCamera(new Vector3(0, 0, 0), 100); + + + // Quad + CustomVertex.PositionTextured[] vertices = new CustomVertex.PositionTextured[] + { + new CustomVertex.PositionTextured( -1, 1, 1, 0,0), + new CustomVertex.PositionTextured(1, 1, 1, 1,0), + new CustomVertex.PositionTextured(-1, -1, 1, 0,1), + new CustomVertex.PositionTextured(1,-1, 1, 1,1) + }; + + //vertex buffer de los triangulos + g_pVB = new VertexBuffer(typeof(CustomVertex.PositionTextured), + 4, d3dDevice, Usage.Dynamic | Usage.WriteOnly, + CustomVertex.PositionTextured.Format, Pool.Default); + g_pVB.SetData(vertices, 0, LockFlags.None); + + // inicializo el render target + g_pRenderTarget = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget_ant = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget_A = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget_B = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + g_pRenderTarget_C = new Texture(d3dDevice, d3dDevice.PresentationParameters.BackBufferWidth + , d3dDevice.PresentationParameters.BackBufferHeight, 1, Usage.RenderTarget, + Format.X8R8G8B8, Pool.Default); + + //Cargar Shader de post.procesado de imagenes + string compilationErrors; + effect = Effect.FromFile(d3dDevice, MyShaderDir + "ImageProccesing.fx", null, null, ShaderFlags.None, null, out compilationErrors); + if (effect == null) + { + throw new Exception("Error al cargar shader. Errores: " + compilationErrors); + } + //Configurar Technique + // Resolucion de pantalla + effect.SetValue("screen_dx", d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_dy", d3dDevice.PresentationParameters.BackBufferHeight); + effect.SetValue("screen_inc_x", 1.0f / (float)d3dDevice.PresentationParameters.BackBufferWidth); + effect.SetValue("screen_inc_y", 1.0f / (float)d3dDevice.PresentationParameters.BackBufferHeight); + + cant_frames = 400; + + // parche: convierto todos los bmps a jpgs: + /* + for (int i = 0; i < cant_frames; ++i) + { + string fname = "c:\\msdev\\varios\\videoana\\" + string.Format("snap{0:D}.bmp", i); + Bitmap b = (Bitmap)Bitmap.FromFile(fname); + string fname_jpg = "c:\\msdev\\varios\\videoana\\" + string.Format("snap{0:D}.jpg", i); + b.Save(fname_jpg, System.Drawing.Imaging.ImageFormat.Jpeg); + b.Dispose(); + }*/ + + /* + for (int i = 0; i < cant_frames; ++i) + { + string fname = "c:\\msdev\\varios\\videoana\\" + string.Format("snap{0:D}.jpg", i*6); + Bitmap b = (Bitmap)Bitmap.FromFile(fname); + g_pVideoBuffer[i] = Texture.FromBitmap(d3dDevice, b, Usage.None, Pool.Managed); + b.Dispose(); + }*/ + } + + + public override void render(float elapsedTime) + { + Device d3dDevice = GuiController.Instance.D3dDevice; + + time += elapsedTime; + int ant_frame = cur_frame; + //cur_frame = (int)(time * 24); // 24 fps? + cur_frame += 2; + if (cur_frame >= cant_frames) + cur_frame = 0; // reinicio + + if (cur_frame != ant_frame) + { + + if (g_pVideoFrame != null) + g_pVideoFrame.Dispose(); + + // cargo y proceso el frame: + // Cargo el frame en una texture + string fname = MyMediaDir+"video\\" + string.Format("snap{0:D}.jpg", cur_frame); + Bitmap b = (Bitmap)Bitmap.FromFile(fname); + g_pVideoFrame = Texture.FromBitmap(d3dDevice, b, Usage.None, Pool.Managed); + b.Dispose(); + } + + // seteos varios + d3dDevice.Transform.View = Matrix.Identity; + d3dDevice.Transform.World = Matrix.Identity; + d3dDevice.Transform.Projection = Matrix.Identity; + d3dDevice.VertexFormat = CustomVertex.PositionTextured.Format; + d3dDevice.SetStreamSource(0, g_pVB, 0); + + // dibujo la escena una textura + effect.Technique = "ImageFilter"; + pOldRT = d3dDevice.GetRenderTarget(0); + pSurf = g_pRenderTarget_A.GetSurfaceLevel(0); + d3dDevice.SetRenderTarget(0, pSurf); + effect.SetValue("base_Tex", g_pVideoFrame); + + //1-era pasada: calculo la intensidad + // imagen-->rendertarget_A + d3dDevice.BeginScene(); + effect.Begin(0); + d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.BeginPass(0); + d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + + //2-da pasada: aplico el erotion filter + // rendertarget_A--->rendertarget_B + pSurf = g_pRenderTarget_B.GetSurfaceLevel(0); + d3dDevice.SetRenderTarget(0, pSurf); + d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.SetValue("base_Tex", g_pRenderTarget_A); + effect.BeginPass(1); + d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + + //3-da pasada: aplico el filtro sobel + // rendertarget_B->rendertarget_C + pSurf = g_pRenderTarget_C.GetSurfaceLevel(0); + d3dDevice.SetRenderTarget(0, pSurf); + d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.SetValue("base_Tex", g_pRenderTarget_B); + effect.BeginPass(2); + d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + + + //4-da pasada: gaussian blur + // rendertarget_C->rendertarget + pSurf = g_pRenderTarget.GetSurfaceLevel(0); + d3dDevice.SetRenderTarget(0, pSurf); + d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0); + effect.SetValue("base_Tex", g_pRenderTarget_C); + effect.BeginPass(3); + d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + d3dDevice.EndScene(); + + + // restuaro el render target + d3dDevice.SetRenderTarget(0, pOldRT); + d3dDevice.BeginScene(); + effect.Technique = "motionDetect"; + effect.SetValue("base_Tex", g_pVideoFrame); + effect.SetValue("g_RenderTarget", g_pRenderTarget); + effect.SetValue("g_RenderTarget_ant", g_pRenderTarget_ant); + effect.Begin(0); + effect.BeginPass(0); + d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); + effect.EndPass(); + effect.End(); + d3dDevice.EndScene(); + + // cambio los render Targets + Texture p_aux = g_pRenderTarget_ant; + g_pRenderTarget_ant = g_pRenderTarget; + g_pRenderTarget = p_aux; + + + } + + /// + /// Método que se llama cuando termina la ejecución del ejemplo. + /// Hacer dispose() de todos los objetos creados. + /// + public override void close() + { + //for (int i = 0; i < cant_frames; ++i) + // g_pVideoBuffer[i].Dispose(); + + if (g_pVideoFrame != null) + g_pVideoFrame.Dispose(); + effect.Dispose(); + } + + + /// + /// opens a video from an avi file + /// and plays the first frame inside the panel + /// + + } +}