SharpDX初学者教程第5部分:着色三角形
原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-5-coloring-the-triangle
在第4部分中,我们创建了一个三角形,我们可以在像素着色器中为整个三角形设置单一颜色。在本教程中,我们将看到如何为三角形的每个顶点添加单独的颜色。我们将继续处理上一个教程中的代码,您也可以在此处找到该代码。
最终结果如下:

1.创建顶点结构
请记住,当我们渲染三角形时,我们上传了一个数组Vector3,因为每个顶点只是一个位置。现在我们希望每个顶点都有一个位置和一个颜色。因此,我们首先创建一个VertexPositionColor.cs通过右键单击项目调用的新文件,然后选择Add -> New Item...:

选择“ 代码文件 ” 类型,并为其命名VertexPositionColor.cs,然后单击“ 添加”:

现在使用以下代码创建一个结构:
using SharpDX;
using System.Runtime.InteropServices;
namespace MySharpDXGame
{
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct VertexPositionColor
{
public readonly Vector3 Position;
public readonly Color4 Color;
public VertexPositionColor(Vector3 position, Color4 color)
{
Position = position;
Color = color;
}
}
}
所以,现在我们有一个不可变的结构,它同时具有Position和Color。我们还将该[StructLayoutAttribute(LayoutKind.Sequential)] 属性添加到结构中。这样可以确保值以与struct中指定的顺序相同的顺序排列在内存中。这很重要,因为我们后来需要告诉GPU。
2.更改顶点
作为下一步,我们需要Game.cs使用新顶点类型的数组替换上一个教程中的顶点数组。我们还为每个顶点选择一种颜色。所以替换这段代码:
private Vector3[] vertices = new Vector3[] { new Vector3(-0.5f, 0.5f, 0.0f), new Vector3(0.5f, 0.5f, 0.0f), new Vector3(0.0f, -0.5f, 0.0f) };
使用此代码:
private VertexPositionColor[] vertices = new VertexPositionColor[]
{
new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0.0f), SharpDX.Color.Red),
new VertexPositionColor(new Vector3(0.5f, 0.5f, 0.0f), SharpDX.Color.Green),
new VertexPositionColor(new Vector3(0.0f, -0.5f, 0.0f), SharpDX.Color.Blue)
};
3.更新VertexBuffer
我们还需要更改我们的顶点缓冲区以包含新的顶点结构而不是Vector3,所以<Vector3>从以下行中删除(在InitializeTriangle()方法中):
triangleVertexBuffer = D3D11.Buffer.Create<Vector3>(d3dDevice, D3D11.BindFlags.VertexBuffer, vertices);
现在编译器会自动推断它是<VertexPositionColor>来自参数的,所以如果我们以后更改它,我们将不需要再次更改。
我们也必须改变在顶点缓冲器中的每个元件的尺寸,所以更换Vector3 用VertexPositionColor 下面的行(在Draw()法):
d3dDeviceContext.InputAssembler.SetVertexBuffers(0, new D3D11.VertexBufferBinding(triangleVertexBuffer, Utilities.SizeOf<Vector3VertexPositionColor>(), 0));
4.更改输入布局
您可能还记得在上一个教程中我们创建了一个输入布局,它描述了顶点数据的结构。在上一个教程中,它看起来像这样:
private D3D11.InputElement[] inputElements = new D3D11.InputElement[]
{
new D3D11.InputElement("POSITION", 0, Format.R32G32B32_Float, 0)
};
由于我们还为每个顶点添加了颜色,我们需要将输入布局更改为以下内容:
private D3D11.InputElement[] inputElements = new D3D11.InputElement[]
{
new D3D11.InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, D3D11.InputClassification.PerVertexData, 0),
new D3D11.InputElement("COLOR", 0, Format.R32G32B32A32_Float, 12, 0, D3D11.InputClassification.PerVertexData, 0)
};
我们添加了另一个InputElement,其中类型是a R32G32B32A32_Float,因为SharpDX.Color4我们在vertex结构中使用的结构包含4个浮点数(以RGBA顺序)。我们还添加了一些其他参数,大多数现在都是无关紧要的,除了第4个,我们为“POSITION”指定0 ,但为“COLOR”元素指定12 。此参数是此数据开始的结构中的偏移量(以字节为单位),并且因为位置首先出现偏移0,并且每个位置Vector3 包含3个浮点数(x,y,z),每个字节数为4个字节= 12字节。因此,颜色数据将在12个字节后找到。
5.更新顶点着色器
打开vertexShader.hlsl文件。首先,我们将更改主要功能参数列表以包含颜色:
float4 main(float4 position : POSITION, float4 color : COLOR) : SV_POSITION
{
[...]
}
正如您所看到的,顶点着色器现在也会接收颜色,但由于颜色是在像素着色器中设置的,因此我们还需要从此函数返回颜色。要从函数返回多个值,我们需要创建一个结构,其中包含着色器文件顶部的位置和颜色:
struct VSOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
现在我们将函数返回值更改为此结构,并删除SV_POSITION 语义:
VSOut main(float4 position : POSITION, float4 color : COLOR)
{
[…]
}
而不是仅仅从着色器返回位置,我们将创建一个VSOut 结构,并在其中设置位置和颜色值。所以最终的顶点着色器应如下所示:
struct VSOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VSOut main(float4 position : POSITION, float4 color : COLOR)
{
VSOut output;
output.position = position;
output.color = color;
return output;
}
6.更新像素着色器
在像素着色器(pixelShader.hlsl)中,我们需要将颜色添加为函数参数,然后返回红色而不是返回提供的颜色,因此完整像素着色器应如下所示:
float4 main(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
7.修复bug
如果您在02-08-2016之前已经按照之前的教程进行操作,那么您可能会遇到错误(在GitHub repo和教程中已修复)。你必须移动这一行 Game.cs:
d3dDeviceContext.OutputMerger.SetRenderTargets(renderTargetView);
从最后开始InitializeDeviceResources(), 并将其置于第一位Draw(),因为必须在每帧的开头调用它。
8.最终结果
我们现在已经完成了,如果您运行该项目,您现在应该得到以下结果:

和往常一样,GitHub上提供了完整的代码:https://github.com/mrjfalk/SharpDXTutorials/tree/master/BeginnersTutorial-Part5
public class Game : IDisposable
{
private RenderForm renderForm; private const int Width = ;
private const int Height = ; private D3D11.Device d3dDevice;
private D3D11.DeviceContext d3dDeviceContext;
private SwapChain swapChain;
private D3D11.RenderTargetView renderTargetView;
private Viewport viewport; // Shaders
private D3D11.VertexShader vertexShader;
private D3D11.PixelShader pixelShader;
private ShaderSignature inputSignature;
private D3D11.InputLayout inputLayout; private D3D11.InputElement[] inputElements = new D3D11.InputElement[]
{
new D3D11.InputElement("POSITION", , Format.R32G32B32_Float, , , D3D11.InputClassification.PerVertexData, ),
new D3D11.InputElement("COLOR", , Format.R32G32B32A32_Float, , , D3D11.InputClassification.PerVertexData, )
}; // Triangle vertices
private VertexPositionColor[] vertices = new VertexPositionColor[] { new VertexPositionColor(new Vector3(-0.5f, 0.5f, 0.0f), SharpDX.Color.Red), new VertexPositionColor(new Vector3(0.5f, 0.5f, 0.0f), SharpDX.Color.Green), new VertexPositionColor(new Vector3(0.0f, -0.5f, 0.0f), SharpDX.Color.Blue) };
private D3D11.Buffer triangleVertexBuffer; /// <summary>
/// Create and initialize a new game.
/// </summary>
public Game()
{
// Set window properties
renderForm = new RenderForm("My first SharpDX game");
renderForm.ClientSize = new Size(Width, Height);
renderForm.AllowUserResizing = false; InitializeDeviceResources();
InitializeShaders();
InitializeTriangle();
} /// <summary>
/// Start the game.
/// </summary>
public void Run()
{
// Start the render loop
RenderLoop.Run(renderForm, RenderCallback);
} private void RenderCallback()
{
Draw();
} private void InitializeDeviceResources()
{
ModeDescription backBufferDesc = new ModeDescription(Width, Height, new Rational(, ), Format.R8G8B8A8_UNorm); // Descriptor for the swap chain
SwapChainDescription swapChainDesc = new SwapChainDescription()
{
ModeDescription = backBufferDesc,
SampleDescription = new SampleDescription(, ),
Usage = Usage.RenderTargetOutput,
BufferCount = ,
OutputHandle = renderForm.Handle,
IsWindowed = true
}; // Create device and swap chain
D3D11.Device.CreateWithSwapChain(DriverType.Hardware, D3D11.DeviceCreationFlags.None, swapChainDesc, out d3dDevice, out swapChain);
d3dDeviceContext = d3dDevice.ImmediateContext; viewport = new Viewport(, , Width, Height);
d3dDeviceContext.Rasterizer.SetViewport(viewport); // Create render target view for back buffer
using(D3D11.Texture2D backBuffer = swapChain.GetBackBuffer<D3D11.Texture2D>())
{
renderTargetView = new D3D11.RenderTargetView(d3dDevice, backBuffer);
}
} private void InitializeShaders()
{
// Compile the vertex shader code
using(var vertexShaderByteCode = ShaderBytecode.CompileFromFile("vertexShader.hlsl", "main", "vs_4_0", ShaderFlags.Debug))
{
// Read input signature from shader code
inputSignature = ShaderSignature.GetInputSignature(vertexShaderByteCode); vertexShader = new D3D11.VertexShader(d3dDevice, vertexShaderByteCode);
} // Compile the pixel shader code
using(var pixelShaderByteCode = ShaderBytecode.CompileFromFile("pixelShader.hlsl", "main", "ps_4_0", ShaderFlags.Debug))
{
pixelShader = new D3D11.PixelShader(d3dDevice, pixelShaderByteCode);
} // Set as current vertex and pixel shaders
d3dDeviceContext.VertexShader.Set(vertexShader);
d3dDeviceContext.PixelShader.Set(pixelShader); d3dDeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; // Create the input layout from the input signature and the input elements
inputLayout = new D3D11.InputLayout(d3dDevice, inputSignature, inputElements); // Set input layout to use
d3dDeviceContext.InputAssembler.InputLayout = inputLayout;
} private void InitializeTriangle()
{
// Create a vertex buffer, and use our array with vertices as data
triangleVertexBuffer = D3D11.Buffer.Create(d3dDevice, D3D11.BindFlags.VertexBuffer, vertices);
} /// <summary>
/// Draw the game.
/// </summary>
private void Draw()
{
// Set render targets
d3dDeviceContext.OutputMerger.SetRenderTargets(renderTargetView); // Clear the screen
d3dDeviceContext.ClearRenderTargetView(renderTargetView, new SharpDX.Color(, , )); // Set vertex buffer
d3dDeviceContext.InputAssembler.SetVertexBuffers(, new D3D11.VertexBufferBinding(triangleVertexBuffer, Utilities.SizeOf<VertexPositionColor>(), )); // Draw the triangle
d3dDeviceContext.Draw(vertices.Count(), ); // Swap front and back buffer
swapChain.Present(, PresentFlags.None);
} public void Dispose()
{
inputLayout.Dispose();
inputSignature.Dispose();
triangleVertexBuffer.Dispose();
vertexShader.Dispose();
pixelShader.Dispose();
renderTargetView.Dispose();
swapChain.Dispose();
d3dDevice.Dispose();
d3dDeviceContext.Dispose();
renderForm.Dispose();
}
}
SharpDX初学者教程第5部分:着色三角形的更多相关文章
- SharpDX初学者教程第4部分:绘制三角形
原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-4-drawing-a-triangle 现在我们有了一个Direct3 ...
- SharpDX初学者教程第3部分:初始化DirectX
原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-3-initializing-directx 在这部分中,我们将初始化D ...
- SharpDX初学者教程第1部分:在Visual Studio 2013中设置SharpDX项目
原文 http://www.johanfalk.eu/blog/sharpdx-tutorial-part-1-setting-up-a-sharpdx-project-in-visual-studi ...
- SharpDX初学者教程第2部分:创建窗口
原文 http://www.johanfalk.eu/blog/sharpdx-tutorial-part-2-creating-a-window 在第二篇教程中,我们将介绍如何创建一个稍后将呈现的简 ...
- WebGL简易教程(三):绘制一个三角形(缓冲区对象)
目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...
- Go GraphQL初学者教程
Go GraphQL初学者教程 https://tutorialedge.net/golang/go-graphql-beginners-tutorial/ https://tutorialedge. ...
- 《SLAM for Dummies》中文版《SLAM初学者教程》
SLAM for Dummies SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping 一本关于实时定位及绘图 ...
- SLAM for Dummies SLAM初学者教程 中文翻译 1到4章
SLAM for Dummies SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping 一本关于实时定位及绘图 ...
- PANDAS 数据分析初学者教程
Pandas 初学者教程 2018-05-19 六尺巷人 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非常重要的Python包.它不仅提供了很多方法,使得数据处理非常 ...
随机推荐
- bzoj 3029 守卫者的挑战——概率期望dp+状态数思考
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3029 先随便写了个dfs,记录“前 i 次.成功 j 次.容量-残片=k”的概率.因为是否可 ...
- bzoj 1179 [Apio2009]Atm——SCC缩点+spfa
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1179 显然SCC缩点. 然后准备倒着拓扑序推到st,结果WA. 听TJ说dj求最长路会发生不 ...
- ACdream 1108(莫队)
题目链接 The kth number Time Limit: 12000/6000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) ...
- 如何获取Expression Design 4工具与Expression Blend 4工具
在VS2010+C#+WPF 开发项目过程中涉及到界面的布局与设计,网上有人讲采用Expression Design 4与Expression Blend 4工具相当方便, 于是决定试看看,下面将这个 ...
- 读书笔记--Apache.Tomcat.6高级编程 目录
1.Apache Tomcat 2.web的应用:Servlet.JSP及其他 3.Tomcat安装 4.Tomcat架构 5.Tomcat基本配置 6.高级Tomcat特性 7.Web应用程序配置 ...
- win10 基础上装一个 ubuntu 双系统
1.准备一个空闲的分区: 1)确定每个磁盘都已经是 EFI 分区格式,如果不是,可以使用分区工具,将分区都转成EFI (例如 DiskGenius 工具挺好) 2)选择一个剩余空间较大的压缩空间,压 ...
- ES6 新的数据类型Map和Set
Map Map是一组键值对的结构,具有极快的查找速度. 举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array: var names = ['Michael', 'Bo ...
- MySQL数据库起步 关于数据库的基本操作(更新中...)
mysql的基本操作 连接指定的服务器(需要服务器开启3306端口) mysql -h ip地址 -P 端口号 -u 账号 -p 密码 删除游客模式 mysql -h ip地址 -P 端口号 -u 账 ...
- 洛谷P1368 均分纸牌(加强版) [2017年6月计划 数论14]
P1368 均分纸牌(加强版) 题目描述 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,纸牌总数必为 N 的倍数.可以在任一堆上取1张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取 ...
- QT_string转char*
char* convertQString2char(const QString &str) { QByteArray ba = str.toUtf8(); char * pathChar = ...