diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionSamplerVert.refresh b/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionSamplerVert.refresh
new file mode 100644
index 0000000..c95c648
Binary files /dev/null and b/MoonWorks.Test.Common/Content/Shaders/Compiled/PositionSamplerVert.refresh differ
diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/PositionSamplerVert.vert b/MoonWorks.Test.Common/Content/Shaders/Source/PositionSamplerVert.vert
new file mode 100644
index 0000000..f0fa89c
--- /dev/null
+++ b/MoonWorks.Test.Common/Content/Shaders/Source/PositionSamplerVert.vert
@@ -0,0 +1,14 @@
+#version 450
+
+layout (location = 0) in vec3 Position;
+layout (location = 1) in vec2 TexCoord;
+
+layout (location = 0) out vec4 outColor;
+
+layout(binding = 0, set = 0) uniform sampler2D Sampler;
+
+void main()
+{
+ outColor = texture(Sampler, TexCoord);
+ gl_Position = vec4(Position, 1);
+}
diff --git a/MoonWorksGraphicsTests.sln b/MoonWorksGraphicsTests.sln
index 436f94f..d151083 100644
--- a/MoonWorksGraphicsTests.sln
+++ b/MoonWorksGraphicsTests.sln
@@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Texture3D", "Texture3D\Text
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InstancingAndOffsets", "InstancingAndOffsets\InstancingAndOffsets.csproj", "{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VertexSampler", "VertexSampler\VertexSampler.csproj", "{C525B6DE-3003-45D5-BB83-89679B108C08}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -129,6 +131,10 @@ Global
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Debug|x64.Build.0 = Debug|x64
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|x64.ActiveCfg = Release|x64
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|x64.Build.0 = Release|x64
+ {C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|x64.ActiveCfg = Debug|x64
+ {C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|x64.Build.0 = Debug|x64
+ {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.ActiveCfg = Release|Any CPU
+ {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/README.md b/README.md
index 05e3033..42ef261 100644
--- a/README.md
+++ b/README.md
@@ -71,3 +71,7 @@ Plays a sample Ogg Theora video file. Tests YUV textures and video rendering.
**Texture3D**
Displays 2D slices of a 3D texture. Tests creating and drawing 3D textures.
+
+**VertexSampler**
+
+Displays a triangle whose colors are driven by sampling a texture in the vertex shader.
diff --git a/VertexSampler/VertexSampler.csproj b/VertexSampler/VertexSampler.csproj
new file mode 100644
index 0000000..2868e63
--- /dev/null
+++ b/VertexSampler/VertexSampler.csproj
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+ Exe
+ net7.0
+ enable
+ x64
+
+
+
+
+
diff --git a/VertexSampler/VertexSamplerGame.cs b/VertexSampler/VertexSamplerGame.cs
new file mode 100644
index 0000000..323586c
--- /dev/null
+++ b/VertexSampler/VertexSamplerGame.cs
@@ -0,0 +1,82 @@
+using MoonWorks;
+using MoonWorks.Graphics;
+using MoonWorks.Math.Float;
+
+namespace MoonWorks.Test
+{
+ class VertexSamplerGame : Game
+ {
+ private GraphicsPipeline pipeline;
+ private Buffer vertexBuffer;
+ private Texture texture;
+ private Sampler sampler;
+
+ public VertexSamplerGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
+ {
+ // Load the shaders
+ ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionSamplerVert"));
+ ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor"));
+
+ // Create the graphics pipeline
+ GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
+ MainWindow.SwapchainFormat,
+ vertShaderModule,
+ fragShaderModule
+ );
+ pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding();
+ pipelineCreateInfo.VertexShaderInfo.SamplerBindingCount = 1;
+ pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
+
+ // Create and populate the GPU resources
+ vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 3);
+ texture = new Texture(GraphicsDevice, new TextureCreateInfo
+ {
+ Width = 3,
+ Height = 1,
+ Depth = 1,
+ Format = TextureFormat.R8G8B8A8,
+ IsCube = false,
+ LevelCount = 1,
+ UsageFlags = TextureUsageFlags.Sampler
+ });
+ sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
+
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ cmdbuf.SetBufferData(
+ vertexBuffer,
+ new PositionTextureVertex[]
+ {
+ new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 0)),
+ new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(0.334f, 0)),
+ new PositionTextureVertex(new Vector3(0, -1, 0), new Vector2(0.667f, 0)),
+ }
+ );
+ cmdbuf.SetTextureData(texture, new Color[] { Color.Yellow, Color.Indigo, Color.HotPink });
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ protected override void Update(System.TimeSpan delta) { }
+
+ protected override void Draw(double alpha)
+ {
+ CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
+ Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
+ if (backbuffer != null)
+ {
+ cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
+ cmdbuf.BindGraphicsPipeline(pipeline);
+ cmdbuf.BindVertexBuffers(vertexBuffer);
+ cmdbuf.BindVertexSamplers(new TextureSamplerBinding(texture, sampler));
+ cmdbuf.DrawPrimitives(0, 1, 0, 0);
+ cmdbuf.EndRenderPass();
+ }
+ GraphicsDevice.Submit(cmdbuf);
+ }
+
+ public static void Main(string[] args)
+ {
+ VertexSamplerGame p = new VertexSamplerGame();
+ p.Run();
+ }
+ }
+}