public void PixelShaderEffect_FeatureLevelValidation() { const string hlsl = @" float4 main() : SV_Target { return 0; } "; var effect93 = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0_level_9_3")); var effect40 = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); using (var featureLevel93Device = DeviceCreator.CreateDevice(useFeatureLevel93: true)) using (var canvasDevice = CanvasDevice.CreateFromDirect3D11Device(featureLevel93Device)) { Assert.IsTrue(effect93.IsSupported(canvasDevice)); Assert.IsFalse(effect40.IsSupported(canvasDevice)); using (var renderTarget = new CanvasRenderTarget(canvasDevice, 1, 1, 96)) using (var drawingSession = renderTarget.CreateDrawingSession()) { drawingSession.DrawImage(effect93); Utils.AssertThrowsException <COMException>( () => drawingSession.DrawImage(effect40), "This shader requires a higher Direct3D feature level than is supported by the device. Check PixelShaderEffect.IsSupported before using it."); } } }
// For matrix types that are accessed as component arrays (int or bool matrix + float matrices other than 3x2 and 4x4). void TestMatrixPropertyType <T>(string hlsl, T[] initialValue, T[] initialArray, T[] newValue, T[] newArray) { var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); // Verify initial values. CollectionAssert.AreEqual(initialValue, (T[])effect.Properties["value_row"]); CollectionAssert.AreEqual(initialValue, (T[])effect.Properties["value_col"]); CollectionAssert.AreEqual(initialArray, (T[])effect.Properties["array_row"]); CollectionAssert.AreEqual(initialArray, (T[])effect.Properties["array_col"]); // Set new values. effect.Properties["value_row"] = newValue; effect.Properties["value_col"] = newValue; effect.Properties["array_row"] = newArray; effect.Properties["array_col"] = newArray; // Read back the modified values. CollectionAssert.AreEqual(newValue, (T[])effect.Properties["value_row"]); CollectionAssert.AreEqual(newValue, (T[])effect.Properties["value_col"]); CollectionAssert.AreEqual(newArray, (T[])effect.Properties["array_row"]); CollectionAssert.AreEqual(newArray, (T[])effect.Properties["array_col"]); }
async Task canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { DissolveEffect = new PixelShaderEffect(await ReadAllBytes("Assets/Shaders/WipeUp.bin")); //DissolveEffect.Properties["feather"] = 0.1f; DissolveMask = await CreateRippleEffect(); CanvasSourceImageLarge1 = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///" + "Assets/Images/beautiful-bloom-blooming-blossom-414083.jpg")); CanvasSourceImageLarge2 = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///" + "Assets/Images/nature-red-forest-leaves-33109.jpg")); CanvasSourceImageSmall1 = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///" + "Assets/Images/beach-birds-calm-clouds-219998.jpg")); CanvasSourceImageSmall2 = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///" + "Assets/Images/photography-of-trees-covered-with-snow-773594.jpg")); try { var info = Windows.Graphics.Display.DisplayInformation.GetForCurrentView(); DissolveEffect.Properties["dpi"] = info.LogicalDpi; DissolveEffect.Properties["height"] = 369f; //DissolveEffect.Properties["progress"] = (float)ProgressSlider.Value; DissolveEffect.Source1 = CanvasSourceImageSmall1; //DissolveEffect.Source2 = CanvasSourceImageSmall2; } catch { } }
void ValidateSourceProperty(PixelShaderEffect effect, Func <IGraphicsEffectSource> getter, Action <IGraphicsEffectSource> setter, int expectedSourceCount, int whichSource) { // Should be initially null. Assert.IsNull(getter()); // Should always be able to set to null. setter(null); Assert.IsNull(getter()); var source = new ColorSourceEffect(); if (whichSource <= expectedSourceCount) { // Should be able to set and get non-null values for this source of the shader. setter(source); Assert.AreEqual(source, getter()); } else { // Should not be able to set this source. Utils.AssertThrowsException <ArgumentException>( () => setter(source), "Source" + whichSource + " must be null when using this pixel shader (shader inputs: " + expectedSourceCount + ")."); } }
/// <summary> /// Renders a texture that contains surface normals /// in the R, G and B channels and height information in /// the A channel based on the specified height map. /// </summary> /// <param name="resourceCreator">Resource creator</param> /// <param name="heightMap">Height map</param> /// <returns>A combination of a normal map and the height map</returns> private static async Task <CanvasBitmap> RenderNormalHeightMapAsync(ICanvasResourceCreatorWithDpi resourceCreator, CanvasBitmap heightMap, float heightDifference) { var bytes = await Utilities.ReadBytesFromUriAsync(new Uri("ms-appx:///Shaders/NormalMapFromHeightMapShader.bin")); var heightMapConverterEffect = new PixelShaderEffect(bytes) { Source1 = heightMap, Source1Mapping = SamplerCoordinateMapping.Offset, MaxSamplerOffset = 1, }; heightMapConverterEffect.Properties["dpi"] = resourceCreator.Dpi; heightMapConverterEffect.Properties["height"] = heightDifference; var normalHeightMap = new CanvasRenderTarget( resourceCreator, (float)heightMap.Size.Width, (float)heightMap.Size.Height, heightMap.Dpi); using (var g = normalHeightMap.CreateDrawingSession()) { g.DrawImage(heightMapConverterEffect); } return(normalHeightMap); }
public void PixelShaderEffect_PropertiesDictionary_Methods() { const string hlsl = @" float foo = 23; int i = 42; float4 main() : SV_Target { return foo * i; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); // Test the various dictionary methods that are forwarded from our // Map<> implementation via PixelShaderEffectPropertyMapTraits. // Count. Assert.AreEqual(2, effect.Properties.Count); // HasKey. Assert.IsTrue(effect.Properties.ContainsKey("foo")); Assert.IsTrue(effect.Properties.ContainsKey("i")); Assert.IsFalse(effect.Properties.ContainsKey("bar")); Assert.IsFalse(effect.Properties.ContainsKey("I")); Assert.IsFalse(effect.Properties.ContainsKey(string.Empty)); // Lookup. Assert.AreEqual(23.0f, effect.Properties["foo"]); Assert.AreEqual(42, effect.Properties["i"]); object value; Utils.AssertThrowsException <ArgumentException>( () => value = effect.Properties["bar"], "Shader does not have a property named 'bar'."); Utils.AssertThrowsException <ArgumentException>( () => value = effect.Properties[string.Empty], "Shader does not have a property named ''."); // GetKeyValuePairs. var array = effect.Properties.ToArray(); Assert.AreEqual(2, array.Length); Assert.AreEqual("foo", array[0].Key); Assert.AreEqual(23.0f, array[0].Value); Assert.AreEqual("i", array[1].Key); Assert.AreEqual(42, array[1].Value); // Remove and Clear are not supported. Assert.ThrowsException <NotImplementedException>(() => effect.Properties.Remove("foo")); Assert.ThrowsException <NotImplementedException>(() => effect.Properties.Clear()); }
public void PixelShaderEffect_ShaderReflectionSetsCoordinateMappingDefaults() { const string hlsl = @" texture2D t0; sampler s0; texture2D t1; sampler s1; texture2D t2; sampler s2; texture2D t3; sampler s3; float4 main(float4 texcoord0 : TEXCOORD0, float4 texcoord1 : TEXCOORD1, float4 texcoord2 : TEXCOORD2, float4 texcoord3 : TEXCOORD3) : SV_Target { return t0.Sample(s0, texcoord0) + t1.Sample(s1, texcoord1) + t2.Sample(s2, texcoord2) + t3.Sample(s3, texcoord3); } export float4 ShaderLinkingFunction(float4 input0 : INPUT0, float4 texcoord1 : TEXCOORD1, float4 texcoord2 : TEXCOORD2, float4 input3 : INPUT3) { return input0 + t1.Sample(s1, texcoord1) + t2.Sample(s2, texcoord2) + input3; } "; // If we compile without support for shader linking, all mappings default to Unknown. var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source1Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source2Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source3Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source4Mapping); // But if we include a shader linking function, reflection now has enough // info to detect which inputs are simple. These are set to OneToOne mapping. effect = new PixelShaderEffect(ShaderCompiler.CompileShaderAndEmbedLinkingFunction(hlsl)); Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source1Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source2Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source3Mapping); Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source4Mapping); }
async Task <PixelShaderEffect> CreateRippleEffect() { var ripplesPixelShaderEffect = new PixelShaderEffect(await ReadAllBytes("Assets/Shaders/Ripples.bin")); ripplesPixelShaderEffect.Properties["frequency"] = 0.05f; ripplesPixelShaderEffect.Properties["dpi"] = 96f; ripplesPixelShaderEffect.Properties["offset"] = 0f; ripplesPixelShaderEffect.Properties["center"] = new Vector2(1280f / 2f, 853 / 2f); return(ripplesPixelShaderEffect); }
public void PixelShaderEffect_MaxOffsetAndOffsetMappingValidation() { const string hlsl = @" texture2D t1; sampler s1; float4 main() : SV_Target { return t1.Sample(s1, 0); } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")) { Source1 = new ColorSourceEffect() }; var device = new CanvasDevice(); var renderTarget = new CanvasRenderTarget(device, 1, 1, 96); // It's an error to draw with Offset mapping mode but MaxSamplerOffset not set. effect.Source1Mapping = SamplerCoordinateMapping.Offset; effect.MaxSamplerOffset = 0; Utils.AssertThrowsException <ArgumentException>(() => { using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } }, "When PixelShaderEffect.Source1Mapping is set to Offset, MaxSamplerOffset should also be set."); // Also an error to draw with MaxSamplerOffset but no Offset mapping mode. effect.Source1Mapping = SamplerCoordinateMapping.OneToOne; effect.MaxSamplerOffset = 1; Utils.AssertThrowsException <ArgumentException>(() => { using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } }, "When PixelShaderEffect.MaxSamplerOffset is set, at least one source should be using SamplerCoordinateMapping.Offset."); // Ok if we have both. effect.Source1Mapping = SamplerCoordinateMapping.Offset; effect.MaxSamplerOffset = 1; using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } }
async Task Canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { bitmapTiger = await CanvasBitmap.LoadAsync(sender, "imageTiger.jpg"); tigerSize = bitmapTiger.Size.ToVector2(); // The Sketch shader has two input textures: // // - First is the image that will be processed by the sketch effect. // The sketch shader applies a 3x3 edge detection filter kernel to this input, // so we specify Offset coordinate mapping mode with a max offset of 1 dip. // // - Second is an overlay containing a pencil sketch texture. The JitterX and JitterY // properties offset this by randomly varying amounts, so we specify Unknown mapping // mode to indicate that the entire image must be made available to the shader. sketchEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Sketch.bin")) { Source1 = bitmapTiger, Source1BorderMode = EffectBorderMode.Hard, Source1Mapping = SamplerCoordinateMapping.Offset, MaxSamplerOffset = (int)Math.Ceiling(sender.Dpi / 96), Source2 = await CanvasBitmap.LoadAsync(sender, "Shaders/SketchTexture.jpg"), Source2Mapping = SamplerCoordinateMapping.Unknown }; sketchEffect.Properties["EdgeOffset"] = sender.Dpi / 96; // The Dissolve shader has two input textures: // // - The first is an image that will be dissolved away to nothing. // // - The second is a dissolve mask whose red channel controls the order in which pixels // of the first image disappear as the dissolveAmount property is animated. // // This example selects different dissolve masks depending on the CurrentEffect. dissolveEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Dissolve.bin")); // The Ripples shader has no input textures. // It generates an animatable series of concentric circles. // This is used as a mask input to the dissolveEffect. rippleEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Ripples.bin")); rippleEffect.Properties["frequency"] = 0.15f; rippleEffect.Properties["dpi"] = sender.Dpi; rippleEffect.Properties["center"] = tigerSize / 3; // Create other dissolve mask images. CreateTurbulence(); CreateLinearGradient(sender); CreateRadialGradient(sender); }
public void InitializeShaders() { string[] shaderList = System.IO.Directory.GetFiles(compiledShadersDir, "*.ps"); foreach (string curString in shaderList) { string name = System.IO.Path.GetFileName(curString); PixelShaderEffect newShaderEffect = new PixelShaderEffect(name); this.PixelShaders.Add(name, newShaderEffect); } }
void ValidateSourceProperties(string hlsl, int expectedSourceCount) { var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); ValidateSourceProperty(effect, () => effect.Source1, (s) => effect.Source1 = s, expectedSourceCount, 1); ValidateSourceProperty(effect, () => effect.Source2, (s) => effect.Source2 = s, expectedSourceCount, 2); ValidateSourceProperty(effect, () => effect.Source3, (s) => effect.Source3 = s, expectedSourceCount, 3); ValidateSourceProperty(effect, () => effect.Source4, (s) => effect.Source4 = s, expectedSourceCount, 4); ValidateSourceProperty(effect, () => effect.Source5, (s) => effect.Source5 = s, expectedSourceCount, 5); ValidateSourceProperty(effect, () => effect.Source6, (s) => effect.Source6 = s, expectedSourceCount, 6); ValidateSourceProperty(effect, () => effect.Source7, (s) => effect.Source7 = s, expectedSourceCount, 7); ValidateSourceProperty(effect, () => effect.Source8, (s) => effect.Source8 = s, expectedSourceCount, 8); }
async Task Canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { bmpImage = await CanvasBitmap.LoadAsync(sender, "Assets/grumpy.jpg"); grumpySize = bmpImage.Size.ToVector2(); // See Win2D custom effect example dissolveEffect = new PixelShaderEffect(await ReadAllBytes("Shaders/Dissolve.bin")); rippleEffect = new PixelShaderEffect(await ReadAllBytes("Shaders/Ripples.bin")); rippleEffect.Properties["dpi"] = sender.Dpi; rippleEffect.Properties["center"] = grumpySize / 2; dissolveEffect.Properties["dissolveAmount"] = 0.5f; }
public void PixelShaderEffect_CoordinateMappingAccessors() { const string hlsl = @" float4 main() : SV_Target { return 0; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); // Check defaults. Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source1Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source2Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source3Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source4Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source5Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source6Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source7Mapping); Assert.AreEqual(SamplerCoordinateMapping.Unknown, effect.Source8Mapping); Assert.AreEqual(0, effect.MaxSamplerOffset); // Setters. effect.Source1Mapping = SamplerCoordinateMapping.OneToOne; effect.Source2Mapping = SamplerCoordinateMapping.Offset; effect.Source3Mapping = SamplerCoordinateMapping.OneToOne; effect.Source4Mapping = SamplerCoordinateMapping.Offset; effect.Source5Mapping = SamplerCoordinateMapping.OneToOne; effect.Source6Mapping = SamplerCoordinateMapping.Offset; effect.Source7Mapping = SamplerCoordinateMapping.OneToOne; effect.Source8Mapping = SamplerCoordinateMapping.Offset; effect.MaxSamplerOffset = 23; // Getters. Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source1Mapping); Assert.AreEqual(SamplerCoordinateMapping.Offset, effect.Source2Mapping); Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source3Mapping); Assert.AreEqual(SamplerCoordinateMapping.Offset, effect.Source4Mapping); Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source5Mapping); Assert.AreEqual(SamplerCoordinateMapping.Offset, effect.Source6Mapping); Assert.AreEqual(SamplerCoordinateMapping.OneToOne, effect.Source7Mapping); Assert.AreEqual(SamplerCoordinateMapping.Offset, effect.Source8Mapping); Assert.AreEqual(23, effect.MaxSamplerOffset); }
async Task Canvas_CreateResourcesAsync(CanvasVirtualControl sender) { mandelbrotEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Mandelbrot.bin")); // The Mandelbrot pixel shader outputs grayscale values. To make the result more interesting, // we run it through a TableTransferEffect. This applies a color gradient that goes from black // through blue, cyan, green, yellow, red, magenta, blue again, and finally back toward cyan. colorizeEffect = new TableTransferEffect { Source = mandelbrotEffect, RedTable = new float[] { 0, 0, 0, 0, 1, 1, 0.67f, 0, 0 }, GreenTable = new float[] { 0, 0, 1, 1, 1, 0, 0, 0, 0.5f }, BlueTable = new float[] { 0, 1, 1, 0, 0, 0, 1, 1, 1 }, }; }
async Task Canvas_CreateResourcesAsync(CanvasVirtualControl sender) { mandelbrotEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Mandelbrot.bin")); // The Mandelbrot pixel shader outputs grayscale values. To make the result more interesting, // we run it through a TableTransferEffect. This applies a color gradient that goes from black // through blue, cyan, green, yellow, red, magenta, blue again, and finally back toward cyan. colorizeEffect = new TableTransferEffect { Source = mandelbrotEffect, RedTable = new float[] { 0, 0, 0, 0, 1, 1, 0.67f, 0, 0 }, GreenTable = new float[] { 0, 0, 1, 1, 1, 0, 0, 0, 0.5f }, BlueTable = new float[] { 0, 1, 1, 0, 0, 0, 1, 1, 1 }, }; }
async Task Canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { bitmapTiger = await CanvasBitmap.LoadAsync(sender, "imageTiger.jpg"); bitmapSize = bitmapTiger.Size.ToVector2(); // The Dissolve shader has two input textures: // // - The first is an image that will be dissolved away to nothing. // // - The second is a dissolve mask whose red channel controls the order in which pixels // of the first image disappear as the dissolveAmount property is animated. // // This example selects different dissolve masks depending on the CurrentEffect. dissolveEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Dissolve.bin")) { Source1 = bitmapTiger }; // The Ripples shader has no input textures. // It generates an animatable series of concentric circles. // This is used as a mask input to the dissolveEffect. rippleEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Ripples.bin")); rippleEffect.Properties["frequency"] = 0.15f; rippleEffect.Properties["dpi"] = sender.Dpi; #if WINDOWS_UWP rippleEffect.Properties["center"] = bitmapSize / 3; #else rippleEffect.Properties["center"] = (Microsoft.Graphics.Canvas.Numerics.Vector2)(bitmapSize / 3); // When compiling for Windows 8.1, we must explicitly convert vector and matrix values // from System.Numerics to their Microsoft.Graphics.Canvas.Numerics equivalents before // passing them to PixelShaderEffect.Properties. This is not neccessary when targetting // UWP, which handles the conversion automatically. For more info, see the article: // http://blogs.msdn.com/b/win2d/archive/2015/06/02/winrt-vector-and-matrix-types-in-windows-10.aspx #endif // Create other dissolve mask images. CreateTurbulence(); CreateLinearGradient(sender); CreateRadialGradient(sender); }
public void PixelShaderEffect_Realize_NoConstants() { const string hlsl = @" float4 main() : SV_Target { return 0; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); using (var canvasDevice = new CanvasDevice()) using (var renderTarget = new CanvasRenderTarget(canvasDevice, 1, 1, 96)) using (var drawingSession = renderTarget.CreateDrawingSession()) { drawingSession.DrawImage(effect); } }
public void PixelShaderEffect_OneElementArraysAppearAsArraysNotScalars() { const string hlsl = @" float foo[1] = { 23 }; float4 main() : SV_Target { return foo[0]; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); CollectionAssert.AreEqual(new float[] { 23 }, (float[])effect.Properties["foo"]); effect.Properties["foo"] = new float[] { 42 }; CollectionAssert.AreEqual(new float[] { 42 }, (float[])effect.Properties["foo"]); }
private async Task OnCreateResourcesAsync(EngineCreateResourcesEventArgs e) { var grass = GrassSprite.Resolve(Entity); var snow = SnowSprite.Resolve(Entity); var rock = RockSprite.Resolve(Entity); var heightMap = _terrain.HeightMap.Resolve(Entity); if (!heightMap.IsPreScaled || !grass.IsPreScaled || !snow.IsPreScaled || !rock.IsPreScaled) { throw new ArgumentException("The heightmap, grass, snow and rock textures must be prescaled in order to be used for terrain rendering"); } // Calculate average colors (these are used at small zoom levels) _grassColor = GetAverageColor(e.Sender, grass.Image); _snowColor = GetAverageColor(e.Sender, snow.Image); _rockColor = GetAverageColor(e.Sender, rock.Image); _normalHeightMap = await RenderNormalHeightMapAsync(e.Sender, heightMap.Image, _terrain.Height - _terrain.BaseHeight); var wrap = CanvasEdgeBehavior.Wrap; var grassTiled = new BorderEffect { Source = grass.Image, ExtendX = wrap, ExtendY = wrap, CacheOutput = true }; var snowTiled = new BorderEffect { Source = snow.Image, ExtendX = wrap, ExtendY = wrap, CacheOutput = true }; var rockTiled = new BorderEffect { Source = rock.Image, ExtendX = wrap, ExtendY = wrap, CacheOutput = true }; var shaderBytes = await Utilities.ReadBytesFromUriAsync(new Uri("ms-appx:///Shaders/TerrainShader.bin")); _terrainMap = new PixelShaderEffect(shaderBytes) { Source1 = _normalHeightMap, Source2 = grassTiled, Source3 = snowTiled, Source4 = rockTiled, CacheOutput = true }; }
public void PixelShaderEffect_OneElementVectorsAndMatricesAppearAsScalarsNotArrays() { const string hlsl = @" float1 foo = { 23 }; float1x1 bar = { 42 }; float4 main() : SV_Target { return foo * bar; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); Assert.AreEqual(23f, effect.Properties["foo"]); Assert.AreEqual(42f, effect.Properties["bar"]); effect.Properties["foo"] = 1f; effect.Properties["bar"] = 2f; Assert.AreEqual(1f, effect.Properties["foo"]); Assert.AreEqual(2f, effect.Properties["bar"]); }
public void PixelShaderEffect_PropertiesDictionary_InsertErrorCases() { const string hlsl = @" float foo; int i; float array[5]; float4 main() : SV_Target { return foo * array[i]; } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")); // Setting valid types should work. effect.Properties["foo"] = 1f; effect.Properties["i"] = 1; effect.Properties["array"] = new float[5]; // Try to insert an unknown property. Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["bar"] = 1, "Shader does not have a property named 'bar'."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties[string.Empty] = 1, "Shader does not have a property named ''."); // Pass wrong property types. Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["foo"] = 1, "Wrong type. Shader property 'foo' is of type Single."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["foo"] = new Vector3[1], "Wrong type. Shader property 'foo' is of type Single."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["i"] = 1f, "Wrong type. Shader property 'i' is of type Int32."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["i"] = new Matrix3x2[1], "Wrong type. Shader property 'i' is of type Int32."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["array"] = 1, "Wrong type. Shader property 'array' is an array of Single."); Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["array"] = new bool[1], "Wrong type. Shader property 'array' is an array of Single."); // Pass a wrong array size. Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["array"] = new float[4], "Wrong array size. Shader property 'array' is an array of 5 elements."); // Insert null. Utils.AssertThrowsException <ArgumentException>( () => effect.Properties["foo"] = null, "Wrong type. Shader property 'foo' is of type Single."); }
async Task Canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { bitmapTiger = await CanvasBitmap.LoadAsync(sender, "imageTiger.jpg"); tigerSize = bitmapTiger.Size.ToVector2(); // The Sketch shader has two input textures: // // - First is the image that will be processed by the sketch effect. // The sketch shader applies a 3x3 edge detection filter kernel to this input, // so we specify Offset coordinate mapping mode with a max offset of 1 dip. // // - Second is an overlay containing a pencil sketch texture. The JitterX and JitterY // properties offset this by randomly varying amounts, so we specify Unknown mapping // mode to indicate that the entire image must be made available to the shader. sketchEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Sketch.bin")) { Source1 = bitmapTiger, Source1BorderMode = EffectBorderMode.Hard, Source1Mapping = SamplerCoordinateMapping.Offset, MaxSamplerOffset = (int)Math.Ceiling(sender.Dpi / 96), Source2 = await CanvasBitmap.LoadAsync(sender, "Shaders/SketchTexture.jpg"), Source2Mapping = SamplerCoordinateMapping.Unknown }; sketchEffect.Properties["EdgeOffset"] = sender.Dpi / 96; // The Dissolve shader has two input textures: // // - The first is an image that will be dissolved away to nothing. // // - The second is a dissolve mask whose red channel controls the order in which pixels // of the first image disappear as the dissolveAmount property is animated. // // This example selects different dissolve masks depending on the CurrentEffect. dissolveEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Dissolve.bin")); // The Ripples shader has no input textures. // It generates an animatable series of concentric circles. // This is used as a mask input to the dissolveEffect. rippleEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Ripples.bin")); rippleEffect.Properties["frequency"] = 0.15f; rippleEffect.Properties["dpi"] = sender.Dpi; #if WINDOWS_UWP rippleEffect.Properties["center"] = tigerSize / 3; #else rippleEffect.Properties["center"] = (Microsoft.Graphics.Canvas.Numerics.Vector2)(tigerSize / 3); // When compiling for Windows 8.1, we must explicitly convert vector and matrix values // from System.Numerics to their Microsoft.Graphics.Canvas.Numerics equivalents before // passing them to PixelShaderEffect.Properties. This is not neccessary when targetting // UWP, which handles the conversion automatically. For more info, see the article: // http://blogs.msdn.com/b/win2d/archive/2015/06/02/winrt-vector-and-matrix-types-in-windows-10.aspx #endif // Create other dissolve mask images. CreateTurbulence(); CreateLinearGradient(sender); CreateRadialGradient(sender); }
async Task Canvas_CreateResourcesAsync(CanvasAnimatedControl sender) { bitmapTiger = await CanvasBitmap.LoadAsync(sender, "imageTiger.jpg"); tigerSize = bitmapTiger.Size.ToVector2(); // The Sketch shader has two input textures: // // - First is the image that will be processed by the sketch effect. // The sketch shader applies a 3x3 edge detection filter kernel to this input, // so we specify Offset coordinate mapping mode with a max offset of 1 dip. // // - Second is an overlay containing a pencil sketch texture. The JitterX and JitterY // properties offset this by randomly varying amounts, so we specify Unknown mapping // mode to indicate that the entire image must be made available to the shader. sketchEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Sketch.bin")) { Source1 = bitmapTiger, Source1BorderMode = EffectBorderMode.Hard, Source1Mapping = SamplerCoordinateMapping.Offset, MaxSamplerOffset = (int)Math.Ceiling(sender.Dpi / 96), Source2 = await CanvasBitmap.LoadAsync(sender, "Shaders/SketchTexture.jpg"), Source2Mapping = SamplerCoordinateMapping.Unknown }; sketchEffect.Properties["EdgeOffset"] = sender.Dpi / 96; // The Dissolve shader has two input textures: // // - The first is an image that will be dissolved away to nothing. // // - The second is a dissolve mask whose red channel controls the order in which pixels // of the first image disappear as the dissolveAmount property is animated. // // This example selects different dissolve masks depending on the CurrentEffect. dissolveEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Dissolve.bin")); // The Ripples shader has no input textures. // It generates an animatable series of concentric circles. // This is used as a mask input to the dissolveEffect. rippleEffect = new PixelShaderEffect(await Utils.ReadAllBytes("Shaders/Ripples.bin")); rippleEffect.Properties["frequency"] = 0.15f; rippleEffect.Properties["dpi"] = sender.Dpi; #if WINDOWS_UWP rippleEffect.Properties["center"] = tigerSize / 3; #else rippleEffect.Properties["center"] = (Microsoft.Graphics.Canvas.Numerics.Vector2)(tigerSize / 3); // When compiling for Windows 8.1, we must explicitly convert vector and matrix values // from System.Numerics to their Microsoft.Graphics.Canvas.Numerics equivalents before // passing them to PixelShaderEffect.Properties. This is not neccessary when targetting // UWP, which handles the conversion automatically. For more info, see the article: // http://blogs.msdn.com/b/win2d/archive/2015/06/02/winrt-vector-and-matrix-types-in-windows-10.aspx #endif // Create other dissolve mask images. CreateTurbulence(); CreateLinearGradient(sender); CreateRadialGradient(sender); }
internal async Task CreateResources() { _dissolveEffect = new PixelShaderEffect(await ReadAllBytes("Assets/Dissolve.bin")); UpdateMask(); }
public void PixelShaderEffect_InputRectTooBigError() { const string hlsl = @" texture2D t1; sampler s1; float4 main() : SV_Target { return t1.Sample(s1, 0); } "; var effect = new PixelShaderEffect(ShaderCompiler.CompileShader(hlsl, "ps_4_0")) { Source1Mapping = SamplerCoordinateMapping.Unknown }; var device = new CanvasDevice(); var renderTarget = new CanvasRenderTarget(device, 1, 1, 96); // Drawing with a fixed size input is ok. effect.Source1 = new CanvasRenderTarget(device, 1, 1, 96); using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } // Drawing with an infinite sized input is not! effect.Source1 = new ColorSourceEffect(); Utils.AssertThrowsException <Exception>(() => { using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } }, "Drawing this effect would require too big an intermediate surface. Make sure PixelShaderEffect.Source1Mapping is set correctly, or wrap the source image with a CropEffect to reduce its size."); // But it's ok if we clamp the input back down to finite size. effect.Source1 = new CropEffect { Source = new ColorSourceEffect(), SourceRectangle = new Rect(0, 0, 100, 100) }; using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } // Also ok if we change our mapping mode to something other than infinite. effect.Source1 = new ColorSourceEffect(); effect.Source1Mapping = SamplerCoordinateMapping.OneToOne; using (var ds = renderTarget.CreateDrawingSession()) { ds.DrawImage(effect); } }