原文 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;
}
}
}

所以,现在我们有一个不可变的结构,它同时具有PositionColor。我们还将该[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部分:着色三角形的更多相关文章

  1. SharpDX初学者教程第4部分:绘制三角形

    原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-4-drawing-a-triangle 现在我们有了一个Direct3 ...

  2. SharpDX初学者教程第3部分:初始化DirectX

    原文 http://www.johanfalk.eu/blog/sharpdx-beginners-tutorial-part-3-initializing-directx 在这部分中,我们将初始化D ...

  3. SharpDX初学者教程第1部分:在Visual Studio 2013中设置SharpDX项目

    原文 http://www.johanfalk.eu/blog/sharpdx-tutorial-part-1-setting-up-a-sharpdx-project-in-visual-studi ...

  4. SharpDX初学者教程第2部分:创建窗口

    原文 http://www.johanfalk.eu/blog/sharpdx-tutorial-part-2-creating-a-window 在第二篇教程中,我们将介绍如何创建一个稍后将呈现的简 ...

  5. WebGL简易教程(三):绘制一个三角形(缓冲区对象)

    目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...

  6. Go GraphQL初学者教程

    Go GraphQL初学者教程 https://tutorialedge.net/golang/go-graphql-beginners-tutorial/ https://tutorialedge. ...

  7. 《SLAM for Dummies》中文版《SLAM初学者教程》

    SLAM for Dummies  SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping  一本关于实时定位及绘图 ...

  8. SLAM for Dummies SLAM初学者教程 中文翻译 1到4章

    SLAM for Dummies  SLAM初学者教程A Tutorial Approach to Simultaneous Localization and Mapping  一本关于实时定位及绘图 ...

  9. PANDAS 数据分析初学者教程

    Pandas 初学者教程       2018-05-19 六尺巷人 对于数据科学家,无论是数据分析还是数据挖掘来说,Pandas是一个非常重要的Python包.它不仅提供了很多方法,使得数据处理非常 ...

随机推荐

  1. ssh实现免密码登录和文件传输

    一般的用户名密码认证不安全,很容易被暴力破解,还不方便:而大多数人都是选择使用 SSH 密钥认证,不仅安全还不用每次输密码 ssh密钥对 # 使用 ssh-keygen 生成非对称密钥,一路回车即可 ...

  2. 前端小知识--区分get和post请求

    get和post是HTTP协议中的两种发送请求的方法. 如果你还不了解http,可以点击[HTTP协议①介绍](https://www.jianshu.com/p/632b890b75ac)[HTTP ...

  3. node学习记录——搭建web服务器

    web服务器的基本知识 功能:1.接收HTTP请求(get,post,delete,put)2.处理HTTP请求 常见的web服务器架构: 1. Nginx/Apache:负责接收http请求,确定谁 ...

  4. mybatis官网文档mybatis_doc

    在平时的学习中,我们可以去参考官网的文档来学习,这个文档有中文的,方便我们去阅读,而且这里的分类很详细. 官网文档链接:http://www.mybatis.org/mybatis-3/zh/inde ...

  5. MongoDB 定位 oplog 必须全表扫描吗?

    MongoDB oplog (类似于 MySQL binlog) 记录数据库的所有修改操作,除了用于主备同步:oplog 还能玩出很多花样,比如 全量备份 + 增量备份所有的 oplog,就能实现 M ...

  6. JDBC vs Hibernate(转)

    jdbc和Hibernate区别 刚开始学习JAVA时,认为Hibernate是一个很神圣的东西,好像是会了SSH,就能走遍全世界一样.记得曾经在枫叶面试的时候,我们几个同学出还说这个公司怎么这么的落 ...

  7. Linux ar命令介绍 和常用示例

    制作静态库要用到ar命令,命令格式: ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files... {dmpqrtx}中的 ...

  8. BZOJ 3057圣主的考验题解

    老师居然考这么毒瘤的题目!!!!! 很容易想到dp,f[i][j]表示有i个节点,左子树的最深深度为j的方案数 枚举左子树有多少节点然后转移,复杂度为n^3 T飞~ 我们考虑到有深度为h的树的节点有多 ...

  9. noip考前模板复习

    网络流 Dinic(搭配飞行员) //Serene #include<algorithm> #include<iostream> #include<cstring> ...

  10. 基于jQuery,bootstrap的bootstrapValidator的学习(一)

    bootstrap:能够增加兼容性的强大框架. 因为移动端项目需要数据验证,就开始学习了bootstrapValidator . 1.需要引用的文件: css: bootstrap.min.css b ...