Некоректно отображаются цвета, если в координатах фигуры использовать vector3 вместо vector4 и добавлении 4 компоненты в вершином шейдере SharpDX
vertex.hlsl
struct vertexData
{
float3 position : POSITION;
float4 color : COLOR;
};
struct pixelData
{
float4 position : SV_POSITION; // SV - System Value
float4 color : COLOR;
};
cbuffer perObjectData : register(b0)
{
float4x4 worldViewProjectionMatrix;
float time;
int timeScaling; // matrix 4x4 4 байта 4*4*4 = 64 + 4 + 4 = 72 соответ 4-х компонентному вектору
float2 _padding;
}
pixelData vertexShader(vertexData input)
{
pixelData output = (pixelData)0;
float4 position = float4(input.position.xyz, 1.0f);
float scale = 0.5f * sin(time * 0.785f) + 1.0f; //0.785 - скорость масштабирования
if (timeScaling > 0) // масштабирования
position.xyz = mul(scale, position.xyz); // mul - multiplication
output.position = mul(position, worldViewProjectionMatrix); // V * M
output.color = input.color;
return output;
}
Renderer.cs
class Renderer : IDisposable
{
[StructLayout(LayoutKind.Sequential)]
public struct VertexDataStruct
{
public Vector3 position;
public Vector2 texCoord;
}
[StructLayout(LayoutKind.Sequential)]
public struct PerObjectConstantBuffer
{
public Matrix worldViewProjectionMatrix;
public float time;
public int timeScaling;
public Vector2 _padding;
}
private DirectX3DGraphics _directX3DGraphics;
private Device11 _device;
private DeviceContext _deviceContext;
private VertexShader _vertexShader;
private PixelShader _pixelShader;
private ShaderSignature _shaderSignature;
private InputLayout _inputLayout;//задаем формат входных данных - описание соотв структуре
private PerObjectConstantBuffer _perObjectConstantBuffer;
private Buffer11 _perObjectConstantBufferObject;
private SamplerState _anisotropicSampler;
public SamplerState AnisotropicSampler { get => _anisotropicSampler; }
public Renderer(DirectX3DGraphics directX3DGraphics)
{
_directX3DGraphics = directX3DGraphics;
_device = _directX3DGraphics.Device;
_deviceContext = _directX3DGraphics.DeviceContext;
CompilationResult vertexShaderByteCode =
ShaderBytecode.CompileFromFile("vertex.hlsl", "vertexShader", "vs_5_0");
_vertexShader = new VertexShader(_device, vertexShaderByteCode);
CompilationResult pixelShaderByteCode =
ShaderBytecode.CompileFromFile("pixel.hlsl", "pixelShader", "ps_5_0");
_pixelShader = new PixelShader(_device, pixelShaderByteCode);
InputElement[] inputElements = new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0)
};
_shaderSignature = ShaderSignature.GetInputOutputSignature(vertexShaderByteCode);
_inputLayout = new InputLayout(_device, _shaderSignature, inputElements);
Utilities.Dispose(ref vertexShaderByteCode);
Utilities.Dispose(ref pixelShaderByteCode);
_deviceContext.InputAssembler.InputLayout = _inputLayout;
_deviceContext.VertexShader.Set(_vertexShader);
_deviceContext.PixelShader.Set(_pixelShader);
SamplerStateDescription samplerStateDescription =
new SamplerStateDescription
{
Filter = Filter.Anisotropic,
AddressU = TextureAddressMode.Clamp,
AddressV = TextureAddressMode.Clamp,
AddressW = TextureAddressMode.Clamp,
MipLodBias = 0.0f,
MaximumAnisotropy = 16, // уровень качетсва результирующей картинки
ComparisonFunction = Comparison.Never,
BorderColor = new SharpDX.Mathematics.Interop.RawColor4(1.0f, 1.0f, 1.0f, 1.0f),
MinimumLod = 0,
MaximumLod = float.MaxValue
};
_anisotropicSampler = new SamplerState(_directX3DGraphics.Device, samplerStateDescription);
}
public void CreateConstantBuffer()
{
_perObjectConstantBufferObject = new Buffer11(
_device, Utilities.SizeOf<PerObjectConstantBuffer>(),
ResourceUsage.Dynamic, BindFlags.ConstantBuffer,
CpuAccessFlags.Write, ResourceOptionFlags.None,
0);
}
public void SetPerObjectConstantBuffer(float time, int timeScaling)
{
_perObjectConstantBuffer.time = time;
_perObjectConstantBuffer.timeScaling = timeScaling;
}
public void BeginRender()
{
_directX3DGraphics.ClearBuffers(Color.Black); //фоновый цвет для буфера кадров
}
public void UpdatePerObjectConstantBuffers(Matrix world, Matrix view,
Matrix projection)
{
_perObjectConstantBuffer.worldViewProjectionMatrix =
Matrix.Multiply(Matrix.Multiply(world, view), projection);
_perObjectConstantBuffer.worldViewProjectionMatrix.Transpose();
DataStream dataStream; // поток с помощью которого будем заливать данные в буфер память
_deviceContext.MapSubresource(_perObjectConstantBufferObject,// генерируем
MapMode.WriteDiscard,
SharpDX.Direct3D11.MapFlags.None,
out dataStream);
dataStream.Write(_perObjectConstantBuffer); // заливаем
_deviceContext.UnmapSubresource(_perObjectConstantBufferObject, 0); // отключаемся
_deviceContext.VertexShader.SetConstantBuffer(0, _perObjectConstantBufferObject);
}
public void SetTexture(Texture texture)
{
_deviceContext.PixelShader.SetShaderResource(0, texture.ShaderResourceView);
_deviceContext.PixelShader.SetSampler(0, texture.SamplerState);
}
public void RenderMeshObject(MeshObject meshObject)
{
_deviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
_deviceContext.InputAssembler.SetVertexBuffers(0, meshObject.VertexBufferBinding);
_deviceContext.InputAssembler.SetIndexBuffer(meshObject.IndicesBufferObject,
Format.R32_UInt, 0);
_deviceContext.DrawIndexed(meshObject.IndicesCount, 0, 0);
}
public void EndRender()
{
_directX3DGraphics.SwapChain.Present(1, PresentFlags.Restart);
}
public void Dispose()
{
Utilities.Dispose(ref _anisotropicSampler);
Utilities.Dispose(ref _perObjectConstantBufferObject);
Utilities.Dispose(ref _inputLayout);
Utilities.Dispose(ref _shaderSignature);
Utilities.Dispose(ref _pixelShader);
Utilities.Dispose(ref _vertexShader);
}
}
Loader.cs
class Loader : IDisposable
{
private DirectX3DGraphics _directX3DGraphics;
private ImagingFactory _imagingFactory;
public Loader(DirectX3DGraphics directX3DGraphics)
{
_directX3DGraphics = directX3DGraphics;
_imagingFactory = new ImagingFactory();
}
public Texture LoadTextureFromFile(string fileName, SamplerState samplerState)
{
BitmapDecoder decoder = new BitmapDecoder(_imagingFactory,
fileName, DecodeOptions.CacheOnDemand);
BitmapFrameDecode bitmapFirstFrame = decoder.GetFrame(0);
Utilities.Dispose(ref decoder);
FormatConverter formatConverter = new FormatConverter(_imagingFactory);
formatConverter.Initialize(bitmapFirstFrame, PixelFormat.Format32bppRGBA,
BitmapDitherType.None, null, 0.0f, BitmapPaletteType.Custom);
int stride = formatConverter.Size.Width * 4; //одна строка пикселей
DataStream buffer = new DataStream(formatConverter.Size.Height * stride, true, true);
formatConverter.CopyPixels(stride, buffer);
int width = formatConverter.Size.Width;
int height = formatConverter.Size.Height;
Texture2DDescription texture2DDescription = new Texture2DDescription()
{
Width = width,
Height = height,
MipLevels = 1,
ArraySize = 1,
Format = Format.R8G8B8A8_UNorm,
SampleDescription = _directX3DGraphics.SampleDescription, //не где-то не совпадет, работать не будет
BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
};
Texture2D textureObject = new Texture2D(_directX3DGraphics.Device, texture2DDescription,
new DataRectangle(buffer.DataPointer, stride));
ShaderResourceViewDescription shaderResourceViewDescription = new ShaderResourceViewDescription()
{
Dimension = ShaderResourceViewDimension.Texture2D,
Format = Format.R8G8B8A8_UNorm,
Texture2D = new ShaderResourceViewDescription.Texture2DResource
{
MostDetailedMip = 0,
MipLevels = -1
}
};
ShaderResourceView shaderResourceView = new ShaderResourceView(_directX3DGraphics.Device, textureObject,
shaderResourceViewDescription);
Utilities.Dispose(ref formatConverter);
return new Texture(textureObject, shaderResourceView, width, height, samplerState);
}
public MeshObject MakeOctahedron(Vector4 position, float yaw, float pitch, float roll)
{
Renderer.VertexDataStruct[] vertices =
new Renderer.VertexDataStruct[]
{
//Верхняя часть
new Renderer.VertexDataStruct // side 1
{
position =new Vector3(-2.0f, 0.0f, -2.0f), //0
texCoord = new Vector2(517f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 1
{
position = new Vector3(0.0f, 4.0f, 0.0f),
texCoord = new Vector2(848f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 1
{
position = new Vector3(-2.0f, 0.0f, 2.0f),//3
texCoord = new Vector2(682f/1200f, 170f/1200f)
},
new Renderer.VertexDataStruct // side 2
{
position = new Vector3(-2.0f, 0.0f, 2.0f), //3
texCoord = new Vector2(1178f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 2
{
position = new Vector3 (0.0f, 4.0f, 0.0f),
texCoord = new Vector2(848f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 2
{
position = new Vector3 (2.0f, 0.0f, 2.0f), //2
texCoord = new Vector2(1013f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 3
{
position = new Vector3 (2.0f, 0.0f, 2.0f), //2
texCoord = new Vector2(1013f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 3
{
position = new Vector3(0.0f, 4.0f, 0.0f),
texCoord = new Vector2(848f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 3
{
position = new Vector3 (2.0f, 0.0f, -2.0f),//1
texCoord = new Vector2(682f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 4
{
position = new Vector3(2.0f, 0.0f, -2.0f),//1
texCoord = new Vector2(682f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 4
{
position = new Vector3(0.0f, 4.0f, 0.0f),
texCoord = new Vector2(848f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 4
{
position = new Vector3(-2.0f, 0.0f, -2.0f),//0
texCoord = new Vector2(517f/1200f, 457f/1200f)
},
//Нижняя часть
new Renderer.VertexDataStruct // side 5
{
position =new Vector3(-2.0f, 0.0f, -2.0f), //0
texCoord = new Vector2(517f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 5
{
position = new Vector3(0.0f, -4.0f, 0.0f),
texCoord = new Vector2(351f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 5
{
position = new Vector3 (-2.0f, 0.0f, 2.0f), //3
texCoord = new Vector2(186f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 6
{
position = new Vector3 (-2.0f, 0.0f, 2.0f), //3
texCoord = new Vector2(186f/1200f, 457f/1200f)
},
new Renderer.VertexDataStruct // side 6
{
position = new Vector3(0.0f, -4.0f, 0.0f),
texCoord = new Vector2(351f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 6
{
position = new Vector3 (2.0f, 0.0f, 2.0f), //2
texCoord = new Vector2(22f/1200f, 741f/1200f)
},
new Renderer.VertexDataStruct // side 7
{
position = new Vector3 (2.0f, 0.0f, 2.0f), //2
texCoord = new Vector2(517f/1200f, 1027f/1200f)
},
new Renderer.VertexDataStruct // side 7
{
position = new Vector3(0.0f, -4.0f, 0.0f),
texCoord = new Vector2(351f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 7
{
position = new Vector3 (2.0f, 0.0f, -2.0f), //1
texCoord = new Vector2(682f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 8
{
position = new Vector3 (2.0f, 0.0f, -2.0f), //1
texCoord = new Vector2(682f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 8
{
position = new Vector3(0.0f, -4.0f, 0.0f),
texCoord = new Vector2(351f/1200f, 742f/1200f)
},
new Renderer.VertexDataStruct // side 8
{
position = new Vector3 (-2.0f, 0.0f, -2.0f), //0
texCoord = new Vector2(517f/1200f, 457f/1200f)
}
};
uint[] indices = new uint[]
{
//Верхняя часть
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
//Нижняя часть
14, 13, 12,
17, 16,15,
20, 19, 18,
23, 22, 21
};
return new MeshObject(_directX3DGraphics, position,
yaw, pitch, roll, vertices, indices);
}
public void Dispose()
{
Utilities.Dispose(ref _imagingFactory);
}
}