/// <summary>image processing render pass on entire image; given multiple input images, technique name, and parms</summary> public ImageTex Xrender(ImageTex[] inimages, String name, float[] parms) { FullTechnique technique = GetTechnique(name, parms); ImageTex nimage = Xrender(inimages, technique); return(nimage); }
/* test * for(int i=0; i<100;i++) { DE("q", "float p1=parms[1]; float p2=parms[2];col=(ii0+i[p1,p2])/2;"); i1.Xrender("q", new float[]{2,i,2*i}).Show(); } * */ /// <summary> /// Get the technique given a possibly abbbreviated name, and apply parms /// </summary> /// <param name="name"></param> /// <returns></returns> public FullTechnique GetTechnique(string name, float[] parms) { name = name.ToLower(); FullTechnique r = null; if (dynamicEffects.ContainsKey(name)) { r = dynamicEffects[name]; } foreach (var technique in mainEffect.Techniques) { if (technique.Name.ToLower().StartsWith(name.ToLower())) { r = new FullTechnique(mainEffect, technique, technique.Name); } } if (r == null) { r = DynamicTechnique(name); } if (r == null) { throw new Exception("Technique not found for " + name); } r = new FullTechnique(r); // clone so we don't corrupt others r.parms = parms; return(new FullTechnique(r)); // surely we don't need TWO new FullTechnique ??? }
/// <summary>copy constructor for technique (eg use this if you want different parms)</summary> internal FullTechnique(FullTechnique t) { technique = t.technique; effect = t.effect; stepKernelXy = t.stepKernelXy; imageparm = t.imageparm; parms = t.parms == null ? null : (float[])(t.parms.Clone()); Name = t.Name; }
///// <summary>Create an effect from a string, using a file as a temporary staging post (only used for some time tests)</summary> //internal Effect CreateEffectViaFile(string name, string s) { // string fid = "temp.fx"; // string c = CreateFullEffectCode(s); // File.WriteAllText(fid, c, Encoding.ASCII); // Effect effect = LoadContentRuntimeFid(fid); // dynamicEffects[name] = new FullTechnique(effect, effect.Techniques["Standard"]); // return effect; //} /// <summary>Create a named technique from the "Standard" technique in an effect string </summary> private FullTechnique CreateEffectDirectI(string name, string s) { string c = CreateFullEffectCode(s); Effect effect = LoadContentRuntimeString(c, name); if (effect == null) { return(null); } FullTechnique ft = new FullTechnique(effect, effect.Techniques["Standard"], name); return(ft); }
/// <summary> /// generate a dynamic technique for the given name (TODO: make more generic) /// name may be xxx_N_M for an NxM filter, and also xxx_N for an NxN filter /// Unsharp_ 1..5 /// Percentile_ 0..2 (requires a single percentile parameter) /// Median_ 0..2 /// </summary> /// <param name="name"></param> /// <returns></returns> private FullTechnique DynamicTechnique(String name) { name = name.ToLower(); string[] nn = name.Split('_'); int pp0 = nn.Count() > 1 ? nn[1].Int() : 0; int pp1 = nn.Count() > 2 ? nn[2].Int() : pp0; FullTechnique ft = null; try { if (nn[0] == "median") { ft = MedianTest(pp0, pp1); } else if (nn[0] == "percentile") { ft = PercentileTest(pp0, pp1); } else if (nn[0] == "unsharp") { ft = CreateEffectDirect(name, DynamicFx.Unsharp, "X", pp0 + "", "Y", pp1 + ""); } else { return(null); } } catch (Exception e) { Form1.Beep("Cannot create technique " + name + " " + e); return(null); } string nname = nn[0] + "_" + pp0 + "_" + pp1; Console.Out.WriteLine("Generated technique " + nname); dynamicEffects[nname] = ft; if (pp0 == pp1) { dynamicEffects[nn[0] + "_" + pp0] = ft; } return(ft); }
/// <summary>image processing render pass on entire image; /// given multiple input images, technique and transformation matrix and required output size /// </summary> internal ImageTex Xrender(ImageTex[] inimage, FullTechnique ftechnique, Matrix tran, int ssizeX, int ssizeY) { //*//if (dotime) timer.Start(); EffectTechnique ltechnique = ftechnique.technique; Effect effect = ftechnique.effect; RenderTarget2D xxtarget; NextOp op = inimage[0].nextOpNew; // STD, ALT, SHARE, NEW int isizeX = inimage[0].Width; int isizeY = inimage[0].Height; if (ssizeX == 0) { ssizeX = isizeX; } if (ssizeY == 0) { ssizeY = isizeY; } switch (op) { case NextOp.STD: xxtarget = xtarget; break; case NextOp.ALT: xxtarget = xtarget1; break; case NextOp.SHARE: rtn++; xxtarget = rts[rtn % SIZE]; break; case NextOp.NEW: xxtarget = null; break; default: throw new Exception("Unexpected NewOp " + op); } SurfaceFormat sf = useVector4 ? SurfaceFormat.Vector4 : graphicsDevice.DisplayMode.Format; if (xxtarget == null || xxtarget.Width != ssizeX || xxtarget.Height != ssizeY || xxtarget.Format != sf) { // programming note: TODO: // If the xxtarget is not the right size, I can't get things to work. // Even if it is too big and I cut it down with viewports. // This reallocation does not seem to matter too much with graphicsDevice.DisplayMode.Format, // but is a performance problem with SurfaceFormat.Vector4. // We probably don't need Vector4 too much anyway, but if we do we should cache a few RenderTargets for the case of size changing often // (this multisize case arises a lot in the scanline test code). // Console.WriteLine("xxsize " + ssizeX + " " + ssizeY); xxtarget = new RenderTarget2D(graphicsDevice, ssizeX, ssizeY, 1, sf); switch (op) { case NextOp.STD: xtarget = xxtarget; break; case NextOp.ALT: xtarget1 = xxtarget; break; case NextOp.SHARE: rts[rtn % SIZE] = xxtarget; break; case NextOp.NEW: break; default: throw new Exception("Unexpected NewOp " + op); } } Viewport savevp = graphicsDevice.Viewport; // this should match the screen size graphicsDevice.SetRenderTarget(0, xxtarget); // << note that this changes graphicsDevice.Viewport to xxtarget = image size graphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.Gray); // this processing should often cover entire image, so no need to clear float h = 0.5f; //Matrix mat = new Matrix(h, 0, 0, 0, 0, -h, 0, 0, 0, 0, 1, 0, h + h / isizeX, h + h / isizeY, 0, 1); //Matrix ss0 = new Matrix(1, 0, 0, 0, 0, isizeY * 1.0f / isizeX, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); //Matrix ss1 = new Matrix(1, 0, 0, 0, 0, isizeX * 1.0f / isizeY, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); //mat = mat * ss0 * tran * ss1; // *mat; Matrix mat = new Matrix(h, 0, 0, 0, 0, -h, 0, 0, 0, 0, 1, 0, h + h / isizeX, h + h / isizeY, 0, 1); mat = mat * tran; // *mat; effect.Parameters["TexProj"].SetValue(mat); effect.Parameters["isize"].SetValue(new Vector2(isizeX, isizeY)); effect.Parameters["stepImageXy"].SetValue(inimage[0].stepImageXy); ftechnique.SetParameters(); if (inimage.Length >= 1) { effect.Parameters["image"].SetValue(inimage[0].texture); } if (inimage.Length >= 2) { effect.Parameters["image2"].SetValue(inimage[1].texture); } if (inimage.Length >= 3) { effect.Parameters["image3"].SetValue(inimage[2].texture); } if (inimage.Length >= 4) { effect.Parameters["image4"].SetValue(inimage[3].texture); } RunEffect(effect); graphicsDevice.SetRenderTarget(0, null); // << note that this changes graphicsDevice.Viewport to (large) backBuffer size Texture2D result = xxtarget.GetTexture(); graphicsDevice.Viewport = savevp; // restore the back buffer // ? timer not reliable, work not complete behind the scenes //*//if (dotime) timer.time(ltechnique.Name); // TODO: improve fid text ImageTex r = new ImageTex(inimage[0].fid + ";" + ltechnique, result, this, inimage[0].fileInfo + " " + ftechnique.Name); // r.Show(); return(r); }
/// <summary>image processing render pass on entire image; given multiple input images and technique</summary> public ImageTex Xrender(ImageTex[] inimage, FullTechnique ltechnique) { return(Xrender(inimage, ltechnique, Matrix.Identity, 0, 0)); }
/// <summary>image processing render pass on entire image; given input image and technique</summary> public ImageTex Xrender(ImageTex inimage, FullTechnique ltechnique) { return(Xrender(new ImageTex[] { inimage }, ltechnique)); }