C# SharpDX how to set texture coordinates correctly? - c#
I am trying to render texture on a cube. However, I do something wrong. I have the texture but coordinates looks like wrong and I do not know how to set it correctly. What am I missing ? I think I must do something about IndexBuffer and UV. However, my mind is very mixed.
The result I get :https://www.youtube.com/watch?v=_fdJAaU81sQ
Mesh.cs
public class Mesh : IDisposable
{
public string File;
public string Name;
public Vector4[] Vertices { get; set; }
public int VerticesCount=0;
public Vector3 Position; //BASED ON PIVOT
public Vector3 PivotPosition; //MOVE MESH BASED ON THIS POSITION
public Vector3 Rotation;
public double Weight;
public SharpDX.Direct3D11.Device d3dDevice;
public SharpDX.Direct3D11.Buffer VerticesBuffer;
public bool IsDisposed=false;
public bool IsSelected = false;
public int Triangles;
public string Texture_DiffuseMap;
public Mesh(string _name, Vector4[] _vertices, string _file, SharpDX.Direct3D11.Device _device, string _Texture_DiffuseMap = "")
{
Vertices = new[]
{
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f,-1.0f, -1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4( 1.0f,-1.0f, 1.0f, 1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
new Vector4(-1.0f, -1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, 1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4(-1.0f, 1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
new Vector4( 1.0f, 1.0f, 1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
};
Texture_DiffuseMap = _Texture_DiffuseMap;
_vertices = Vertices;
d3dDevice = _device;
VerticesCount = Vertices.Count();
Name = _name;
File = _file;
Meshes.Add(this);
}
// Other functions go here...
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
IsDisposed = true;
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Dispose();
}
// free native resources if there are any.
VerticesBuffer.Dispose();
IsDisposed = true;
}
public void Render()
{
d3dDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
d3dDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VerticesBuffer, Utilities.SizeOf<Vector4>() * 2, 0));
d3dDevice.ImmediateContext.Draw(VerticesCount,0);
/*d3dDevice.ImmediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineList;
d3dDevice.ImmediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VerticesBuffer, Utilities.SizeOf<Vector4>() * 2, 0));
d3dDevice.ImmediateContext.Draw(VerticesCount, 0);
*/
VerticesBuffer.Dispose();
}
}
Program.cs
[STAThread]
private static void Main()
{
new Thread(new ThreadStart(() =>
{
DisposeCollector DC=new DisposeCollector();
var form = new RenderForm(Globals.Window_Title) { Width = Globals.Window_Size.Width, Height = Globals.Window_Size.Height, AllowUserResizing = false, MinimizeBox = false };
InputHandler IHandler = new InputHandler(form);
SampleDescription SamplerDesc = new SampleDescription(8, 0);
// SwapChain description
var desc = new SwapChainDescription()
{
BufferCount = 2,
ModeDescription = new ModeDescription(form.ClientSize.Width, form.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm),
IsWindowed = true,
OutputHandle = form.Handle,
SampleDescription = SamplerDesc,
SwapEffect = SwapEffect.Discard,
Usage = Usage.RenderTargetOutput
};
var samplerStateDescription = new SamplerStateDescription
{
AddressU = TextureAddressMode.Wrap,
AddressV = TextureAddressMode.Wrap,
AddressW = TextureAddressMode.Wrap,
Filter = Filter.MinMagMipLinear
};
var rasterizerStateDescription = RasterizerStateDescription.Default();
rasterizerStateDescription.IsFrontCounterClockwise = true;
// Used for debugging dispose object references
Configuration.EnableObjectTracking = true;
// Disable throws on shader compilation errors
Configuration.ThrowOnShaderCompileError = false;
SharpDX.DXGI.Factory factory = new SharpDX.DXGI.Factory1();
SharpDX.DXGI.Adapter adapter = factory.GetAdapter(1);
Adapter[] availableAdapters = factory.Adapters;
foreach(Adapter _adapter in availableAdapters)
{
Console.WriteLine(_adapter.Description.Description);
}
// Create Device and SwapChain
Device device;
SwapChain swapChain;
Device.CreateWithSwapChain(adapter, DeviceCreationFlags.SingleThreaded, desc, out device, out swapChain);
var context = device.ImmediateContext;
//factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);
// Compile Vertex and Pixel shaders
var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.hlsl", "VS", "vs_5_0", ShaderFlags.Debug);
var vertexShader = new VertexShader(device, vertexShaderByteCode);
var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.hlsl", "PS", "ps_5_0", ShaderFlags.Debug);
var pixelShader = new PixelShader(device, pixelShaderByteCode);
var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
// Layout from VertexShader input signature
var layout = new InputLayout(device, signature, new[]
{
new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("NORMAL", 0, Format.R32G32B32A32_Float, 0, 0),
new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0),
new InputElement("TEXCOORD", 0, Format.R32G32_Float, InputElement.AppendAligned, 0)
});
var samplerState = new SamplerState(device, samplerStateDescription);
Mesh mesh1 = new Mesh("mesh1", new[] { new Vector4(0, 0, 0, 1) }, "", device, "1_Purple.jpg") { IsSelected=true };
Mesh mesh2 = new Mesh("mesh2", new[] { new Vector4(0, 0, 0, 1) }, "", device, "1_GREEN.jpg");
//MenuCreator menu1 = new MenuCreator(device,new[] {new Vector4(0, 0, 0, 0) });
// Create Constant Buffer
var contantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
ShaderResourceView textureView;
SharpDX.WIC.ImagingFactory2 ImagingFactory2 = new SharpDX.WIC.ImagingFactory2();
// Prepare All the stages
context.InputAssembler.InputLayout = layout;
context.VertexShader.SetConstantBuffer(0, contantBuffer);
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
context.PixelShader.SetSampler(0, samplerState);
//context.PixelShader.SetShaderResource(0, textureView);
Matrix proj = Matrix.Identity;
// Use clock
var clock = new Stopwatch();
FPS fps = new FPS();
clock.Start();
// Declare texture for rendering
bool userResized = true;
Texture2D backBuffer = null;
RenderTargetView renderView = null;
Texture2D depthBuffer = null;
DepthStencilView depthView = null;
// Setup handler on resize form
form.UserResized += (sender, args) => userResized = true;
// Setup full screen mode change F5 (Full) F4 (Window)
form.KeyUp += (sender, args) =>
{
if (args.KeyCode == Keys.F5)
swapChain.SetFullscreenState(true, null);
else if (args.KeyCode == Keys.F4)
swapChain.SetFullscreenState(false, null);
else if (args.KeyCode == Keys.Escape)
form.Close();
};
//CREATE DEPTH STENCIL DESCRIPTION
DepthStencilStateDescription depthSSD = new DepthStencilStateDescription();
depthSSD.IsDepthEnabled = false;
depthSSD.DepthComparison = Comparison.LessEqual;
depthSSD.DepthWriteMask = DepthWriteMask.Zero;
DepthStencilState DSState = new DepthStencilState(device, depthSSD);
Camera camera = new Camera();
camera.eye = new Vector3(0, 0, -5);
camera.target = new Vector3(0, 0, 0);
Globals.Render = true;
/*void DrawEmptyCircle(Vector3 startPoint, Vector2 radius, Color color)
{
List<VertexPositionColor> circle = new List<VertexPositionColor>();
float X, Y;
var stepDegree = 0.3f;
for (float angle = 0; angle <= 360; angle += stepDegree)
{
X = startPoint.X + radius.X * (float)Math.Cos((angle));
Y = startPoint.Y + radius.Y * (float)Math.Sin((angle));
Vector3 point = new Vector3(X, Y, 0);
circle.Add(new VertexPositionColor(point, color));
}
}*/
CubeApp.Windows.SystemInformation.Print(CubeApp.Windows.SystemInformation.GetSystemInformation());
HardwareInformation.GetHardwareInformation("Win32_DisplayConfiguration", "Description");
// Main loop
RenderLoop.Run(form, () =>
{
fps.Count();fps.setFormHeader(form);
// Prepare matrices
if (Globals.Render)
{
var view = camera.getView();
// If Form resized
if (userResized)
{
// Dispose all previous allocated resources
Utilities.Dispose(ref backBuffer);
Utilities.Dispose(ref renderView);
Utilities.Dispose(ref depthBuffer);
Utilities.Dispose(ref depthView);
foreach (Mesh _mesh in Meshes.MeshCollection)
{
if (_mesh.IsDisposed == false)
{
Utilities.Dispose(ref _mesh.VerticesBuffer);
}
}
// Resize the backbuffer
swapChain.ResizeBuffers(desc.BufferCount, form.ClientSize.Width, form.ClientSize.Height, Format.Unknown, SwapChainFlags.None);
// Get the backbuffer from the swapchain
backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
// Renderview on the backbuffer
renderView = new RenderTargetView(device, backBuffer);
// Create the depth buffer
depthBuffer = new Texture2D(device, new Texture2DDescription()
{
Format = Format.D32_Float_S8X24_UInt,
ArraySize = 1,
MipLevels = 1,
Width = form.ClientSize.Width,
Height = form.ClientSize.Height,
SampleDescription = SamplerDesc,
Usage = ResourceUsage.Default,
BindFlags = BindFlags.DepthStencil,
CpuAccessFlags = CpuAccessFlags.None,
OptionFlags = ResourceOptionFlags.None
});
// Create the depth buffer view
depthView = new DepthStencilView(device, depthBuffer);
// Setup targets and viewport for rendering
context.Rasterizer.SetViewport(new Viewport(0, 0, form.ClientSize.Width, form.ClientSize.Height, 0.0f, 1.0f));
//context.OutputMerger.SetDepthStencilState(DSState);
context.OutputMerger.SetTargets(depthView, renderView);
// Setup new projection matrix with correct aspect ratio
proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, form.ClientSize.Width / (float)form.ClientSize.Height, 0.1f, 100.0f);
// We are done resizing
userResized = false;
}
var time = clock.ElapsedMilliseconds / 1000.0f;
var viewProj = Matrix.Multiply(view, proj);
// Clear views
context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
context.ClearRenderTargetView(renderView, Color.WhiteSmoke);
// Update WorldViewProj Matrix
var worldViewProj = Matrix.RotationX(45) * Matrix.RotationY(0 * 2) * Matrix.RotationZ(0 * .7f) * viewProj;
worldViewProj.Transpose();
context.UpdateSubresource(ref worldViewProj, contantBuffer);
//Update Camera Position
Vector3 _camEye = camera.eye;
Vector3 _camTarget = camera.target;
if (IHandler.KeyW)
{
_camEye.Z+= 0.050f; _camTarget.Z += 0.050f;
}
if (IHandler.KeyS)
{
_camEye.Z -= 0.050f; _camTarget.Z -= 0.050f;
}
if (IHandler.KeyA)
{
_camEye.X -= 0.050f; _camTarget.X -= 0.050f;
}
if (IHandler.KeyD)
{
_camTarget.X += 0.050f;
_camEye.X += 0.050f;
}
if (IHandler.KeyQ)
{
}
camera.eye = _camEye;
camera.target = _camTarget;
camera.updateView();
// Draw the cube
foreach (Mesh __mesh in Meshes.MeshCollection)
{
if ( __mesh.IsSelected )
{
for (int i = 0; i <= __mesh.VerticesCount - 1; i++)
{
if (IHandler.KeyRight) __mesh.Vertices[i].X += 0.050f;
if (IHandler.KeyLeft) __mesh.Vertices[i].X -= 0.050f;
if (IHandler.KeyUp) __mesh.Vertices[i].Y += 0.050f;
if (IHandler.KeyDown) __mesh.Vertices[i].Y -= 0.050f;
}
}
var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(ImagingFactory2, __mesh.Texture_DiffuseMap));
textureView = new ShaderResourceView(device, texture);
context.PixelShader.SetShaderResource(0, textureView);
texture.Dispose();
textureView.Dispose();
__mesh.VerticesBuffer = SharpDX.Direct3D11.Buffer.Create(device, BindFlags.VertexBuffer, __mesh.Vertices);
//EnvironmentDisplayModes.SetDisplayMode(device, __mesh, EnvironmentDisplayModes.DisplayMode.Standart);
__mesh.Render();
}
// Present!
swapChain.Present(0, PresentFlags.None);
}
});
// Release all resources
foreach (Mesh msh in Meshes.MeshCollection)
{
msh.d3dDevice.Dispose();
msh.VerticesBuffer.Dispose();
}
DC.DisposeAndClear();
signature.Dispose();
vertexShaderByteCode.Dispose();
vertexShader.Dispose();
pixelShaderByteCode.Dispose();
pixelShader.Dispose();
layout.Dispose();
contantBuffer.Dispose();
depthBuffer.Dispose();
depthView.Dispose();
renderView.Dispose();
backBuffer.Dispose();
ImagingFactory2.Dispose();
device.Dispose();
context.Dispose();
swapChain.Dispose();
factory.Dispose();
adapter.Dispose();
DSState.Dispose();
samplerState.Dispose();
DC.Dispose();
form.Dispose();
})).Start();
}
}
MiniCube.hlsl
Texture2D ShaderTexture : register(t0);
SamplerState Sampler : register(s0);
struct VS_IN
{
float4 pos : POSITION;
float3 Normal : NORMAL;
float4 col : COLOR;
float2 TextureUV: TEXCOORD; // Texture UV coordinate
};
struct VS_OUTPUT
{
float4 pos : POSITION0;
float depth : TEXCOORD0;
float2 TextureUV: TEXCOORD;
};
struct PS_IN
{
float4 pos : SV_POSITION;
float4 col : COLOR;
float2 TextureUV: TEXCOORD;
float3 WorldNormal : NORMAL;
float3 WorldPosition : WORLDPOS;
};
float4x4 worldViewProj;
PS_IN VS( VS_IN input )
{
PS_IN output = (PS_IN)0;
output.pos = mul(input.pos, worldViewProj);
input.pos.z= input.pos.z - 0.9f;
input.pos.z *= 10.0f;
output.col = 1.0f-((input.pos.w /* * input.col*/) / (input.pos.z /* *input.col*/));
output.TextureUV = input.TextureUV;
return output;
}
float4 PS( PS_IN input ) : SV_Target
{
return ShaderTexture.Sample(Sampler, input.TextureUV)*input.col;
}
First of all it is common to store the texture coordinates in the vertices.
So the first thing to do for you is to change your structure of your vertices to:
public MyVertex
{
public Vector3 Position;
public Vector3 Normal;
public Vector2 TextureCoord;
}
I do not see the necessity to make the position and normal a vector4, so this should do it. As you use textures there is also no need to use color in the vertex structure.
Next you change your input structure for the shader to the above structure. In the shader but also in your intialization of it.
It is recommended that you set the texture coordinates in the initialization of the mesh. An example would be for a plane:
var vertices = new MyVertex[]
{
new MyVertex(){Position = new Vector3(0.0f, 0.0f, 0.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(0.0f, 0.0f)},
new MyVertex(){Position = new Vector3(1.0f, 0.0f, 0.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(1.0f, 0.0f)},
new MyVertex(){Position = new Vector3(1.0f, 0.0f, 1.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(1.0f, 1.0f)},
new MyVertex(){Position = new Vector3(0.0f, 0.0f, 1.0f),Normal = new Vector3(0.0f, 1.0f, 0.0f), TextureCoord = new Vector2(0.0f, 1.0f)}
};
If you store your vertices like that, it should work like a charm.
Only thing left to do is, to use the input texturecoordinates for your sampling of the passed texture in the shader.
Also there is no need for manipulation of the texturecoordinates in the shader if you want to use simple texture mapping. Otherwise you can look up different types of texture mapping on wikipedia, like spherical-, box- or plane-texturemapping.
Related
OpenTK - transparency issue on VBO
I just want to create an .obj file loader, which will load 3D objects. Everything went alright but when i try to load a transparent object i got a problem. So, here is a picture of the issue. Transparency is working but i don't know why, there are triangles. I try to load different objects (with and without texture also) but i got this issue always. here is my light settings: class Light { public static void SetLight() { GL.Enable(EnableCap.Lighting); GL.Enable(EnableCap.Light0); GL.Enable(EnableCap.ColorMaterial); Vector4 position = new Vector4(0.0f, 200.0f, 300.0f, 1.0f); Vector4 ambient = new Vector4(0.2f, 0.2f, 0.2f, 1.0f); Vector4 diffuse = new Vector4(0.7f, 0.7f, 0.7f, 1.0f); Vector4 specular = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); GL.Light(LightName.Light0, LightParameter.Position, position); GL.Light(LightName.Light0, LightParameter.Ambient, ambient); GL.Light(LightName.Light0, LightParameter.Diffuse, diffuse); GL.Light(LightName.Light0, LightParameter.Specular, specular); } public static void SetMaterial() { GL.Color4(1.0f, 1.0f, 1.0f, 0.5f); Vector4 ambient = new Vector4(0.3f, 0.3f, 0.3f, 0.5f); Vector4 diffuse = new Vector4(1.0f, 1.0f, 1.0f, 0.5f); Vector4 specular = new Vector4(0.0f, 0.0f, 0.0f, 0.5f); GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, ambient); GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, diffuse); GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, specular); GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, 1.0f); } } and in the main Load function a also have these settings GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); //GL.Enable(EnableCap.DepthTest); //GL.Enable(EnableCap.CullFace); i know that maybe my answer is not the best, but i don't know what is this issue and i don't even find similar issues on the net.
Your problem is this: You need to sort the transparent faces from the furthest to the closest before drawing them.
Meaning of new[] { } in c#
What is the meaning in this code where it reads "new[] {}" ? public Cube(Game game) : base(game) { vertices = Buffer.Vertex.New( game.GraphicsDevice, new[] { new VertexPositionColor(new Vector3(-1.0f, 1.0f, -1.0f), Color.OrangeRed), new VertexPositionColor(new Vector3(-1.0f, 1.0f, 1.0f), Color.OrangeRed), }); }
Just creating an implicity typed array, in your code it is a VertexPositionColor[] with two elements.
How to render image properly
My image appears too large when it is rendered using SharpGL. How do I load it properly? The image's dimension is only 313 x 79 pixels but it almost occupy the rest of the screen when it renders. I got this code from codeplex. The example given is how to render images in 3D (name of project is NativeTexturesSample). https://sharpgl.codeplex.com/downloads/get/614989. I manage to make the rendering in 2D but I think I'm not doing it correctly. private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs e) { const int screenWidth = 1920; const int screenHeight = 1080; SharpGL.OpenGL gl = this.openGLControl1.OpenGL; gl.MatrixMode(OpenGL.GL_PROJECTION); gl.Ortho2D(0, screenWidth , screenHeight , 0); gl.Disable(OpenGL.GL_DEPTH_TEST); gl.LoadIdentity(); texture.Create(gl, #"C:\image\footerlogo.bmp"); texture.Bind(gl); gl.Begin(OpenGL.GL_QUADS); gl.TexCoord(0.0f, 1.0f); gl.Vertex(-2.0f, 0.0f); gl.TexCoord(1.0f, 1.0f); gl.Vertex(1.0f, 0.0f); gl.TexCoord(1.0f, 0.0f); gl.Vertex(1.0f, 1.0f); gl.TexCoord(0.0f, 0.0f); gl.Vertex(-2.0f, 1.0f); gl.End(); gl.Flush(); }
Try this code: public partial class SharpGLForm : Form { private bool TexturesInitialised = false; private float rotation = 0.0f; private float Scale = 1; private Bitmap gImage1; private System.Drawing.Imaging.BitmapData gbitmapdata; private uint[] gtexture = new uint[1]; /// <summary> /// Initializes a new instance of the <see cref="SharpGLForm"/> class. /// </summary> public SharpGLForm() { InitializeComponent(); } private void InitialiseTexture(ref OpenGL gl) { gImage1 = new Bitmap(#"C:\Jess1.bmp");// Environment.GetFolderPath(Environment.SpecialFolder.MyPictures) Rectangle rect = new Rectangle(0, 0, gImage1.Width, gImage1.Height); gbitmapdata = gImage1.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); gImage1.UnlockBits(gbitmapdata); gl.GenTextures(1, gtexture); gl.BindTexture(OpenGL.GL_TEXTURE_2D, gtexture[0]); gl.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, (int)OpenGL.GL_RGB8, gImage1.Width, gImage1.Height, 0, OpenGL.GL_BGR_EXT, OpenGL.GL_UNSIGNED_BYTE, gbitmapdata.Scan0); uint[] array = new uint[] { OpenGL.GL_NEAREST }; gl.TexParameterI(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, array); gl.TexParameterI(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, array); TexturesInitialised = true; } private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e) { // Get the OpenGL object. OpenGL gl = openGLControl.OpenGL; // Clear the color and depth buffer. gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); // Load the identity matrix. gl.LoadIdentity(); if (!TexturesInitialised) { InitialiseTexture(ref gl); } gl.Enable(OpenGL.GL_TEXTURE_2D); gl.BindTexture(OpenGL.GL_TEXTURE_2D, gtexture[0]); gl.Color(1.0f, 1.0f, 1.0f, 0.1f); //Must have, weirdness! gl.Begin(OpenGL.GL_QUADS); gl.TexCoord(1.0f, 1.0f); gl.Vertex(gImage1.Width, gImage1.Height, 1.0f); gl.TexCoord(0.0f, 1.0f); gl.Vertex(0.0f, gImage1.Height, 1.0f); gl.TexCoord(0.0f, 0.0f); gl.Vertex(0.0f, 0.0f, 1.0f); gl.TexCoord(1.0f, 0.0f); gl.Vertex(gImage1.Width, 0.0f, 1.0f); gl.End(); gl.Disable(OpenGL.GL_TEXTURE_2D); } private void openGLControl_OpenGLInitialized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.ClearColor(0, 0, 0, 0); } private void openGLControl_Resized(object sender, EventArgs e) { OpenGL gl = openGLControl.OpenGL; gl.MatrixMode(OpenGL.GL_PROJECTION); gl.LoadIdentity(); gl.Perspective(60.0f, (double)Width / (double)Height, 0.01, 10000.0); gl.LookAt(0, 0, -500, 0, 0, 0, 0, 1, 0); gl.MatrixMode(OpenGL.GL_MODELVIEW); } }
openTK c# roatating cube example
i am using C# (visual studio 2008) to develop a slot machine, using OpenTK for using openGL in my project we have done the basic functionality but the we cant get a code to draw a cube that can rotate. THe cude needs to rotate for some time, but i cant figure out how to do it. we have tried this Cube but this we want to draw it on a form
OpenTK provides a Windows Forms control called GLControl. It has no built-in main loop, but getting continuous rendering to work on the control isn't that hard if you follow this GLControl tutorial. Once you have continuous rendering working, you can move over the code to render a cube and it will be continuously rotating on a form.
Here is an example of a rotating cube in C# using OpenTK: using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; using OpenTK.Input; // adapted from : dreamstatecoding.blogspot.com namespace RotatingCube { public struct Vertex { public const int Size = (4 + 4) * 4; // size of struct in bytes private readonly Vector4 _position; private readonly Color4 _color; public Vertex(Vector4 position, Color4 color) { _position = position; _color = color; } } public sealed class MainWindow : GameWindow { private readonly string _title; private int _width; private int _height; private int _program; private double _time; private bool _initialized; private int _vertexArray; private int _buffer; private int _verticeCount; private Matrix4 _model; private Matrix4 _view; private Matrix4 _projection; private float _FOV = 45.0f; private float _lastTimestamp = Stopwatch.GetTimestamp(); private float _freq = Stopwatch.Frequency; private float _angle; public MainWindow() : base(750, // initial width 500, // initial height GraphicsMode.Default, "", // initial title GameWindowFlags.Default, DisplayDevice.Default, 3, // OpenGL major version 3, // OpenGL minor version GraphicsContextFlags.ForwardCompatible) { _width = 750; _height = 500; _title += "Spinning Cube, OpenGL Version: " + GL.GetString(StringName.Version); } protected override void OnLoad(EventArgs e) { _model = Matrix4.Identity; Vertex[] vertices = { new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Blue), new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Red), new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, -0.5f, -0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, -0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), Color4.Green), new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, 0.5f, -0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4( 0.5f, 0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), Color4.Green), new Vertex(new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), Color4.Green), }; _verticeCount = vertices.Length; _vertexArray = GL.GenVertexArray(); _buffer = GL.GenBuffer(); GL.BindVertexArray(_vertexArray); GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexArray); // create first buffer: vertex GL.NamedBufferStorage( _buffer, Vertex.Size*vertices.Length, // the size needed by this buffer vertices, // data to initialize with BufferStorageFlags.MapWriteBit); // at this point we will only write to the buffer GL.VertexArrayAttribBinding(_vertexArray, 0, 0); GL.EnableVertexArrayAttrib(_vertexArray, 0); GL.VertexArrayAttribFormat( _vertexArray, 0, // attribute index, from the shader location = 0 4, // size of attribute, vec4 VertexAttribType.Float, // contains floats false, // does not need to be normalized as it is already, floats ignore this flag anyway 0); // relative offset, first item GL.VertexArrayAttribBinding(_vertexArray, 1, 0); GL.EnableVertexArrayAttrib(_vertexArray, 1); GL.VertexArrayAttribFormat( _vertexArray, 1, // attribute index, from the shader location = 1 4, // size of attribute, vec4 VertexAttribType.Float, // contains floats false, // does not need to be normalized as it is already, floats ignore this flag anyway 16); // relative offset after a vec4 // link the vertex array and buffer and provide the stride as size of Vertex GL.VertexArrayVertexBuffer(_vertexArray, 0, _buffer, IntPtr.Zero, Vertex.Size); _initialized = true; CursorVisible = true; try { _program = GL.CreateProgram(); var shaders = new List<int>(); ShaderType type = ShaderType.VertexShader; var shader = GL.CreateShader(type); string src = #"#version 330 core layout (location = 0) in vec4 position; layout(location = 1) in vec4 color; out vec4 vs_color; out vec3 original_normal; out vec3 transformed_normal; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(void) { gl_Position = projection * view * model * position; vs_color = color; original_normal = vec3(color); mat3 normal_matrix = transpose(inverse(mat3(view * model))); transformed_normal = normal_matrix * original_normal; }"; GL.ShaderSource(shader, src); GL.CompileShader(shader); var info = GL.GetShaderInfoLog(shader); if (!string.IsNullOrWhiteSpace(info)) throw new Exception($"CompileShader {type} had errors: {info}"); shaders.Add(shader); type = ShaderType.FragmentShader; shader = GL.CreateShader(type); src = #"#version 330 core in vec4 vs_color; in vec3 original_normal; in vec3 transformed_normal; out vec4 color; void main(void) { float lighting = abs(dot(transformed_normal, vec3(0,0,-1))); color = vs_color * lighting; }"; GL.ShaderSource(shader, src); GL.CompileShader(shader); info = GL.GetShaderInfoLog(shader); if (!string.IsNullOrWhiteSpace(info)) throw new Exception($"CompileShader {type} had errors: {info}"); shaders.Add(shader); foreach (var shader_ in shaders) GL.AttachShader(_program, shader_); GL.LinkProgram(_program); var info_ = GL.GetProgramInfoLog(_program); if (!string.IsNullOrWhiteSpace(info_)) throw new Exception($"CompileShaders ProgramLinking had errors: {info}"); foreach (var shader_ in shaders) { GL.DetachShader(_program, shader_); GL.DeleteShader(shader_); } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); throw; } GL.Enable(EnableCap.DepthTest); GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill); GL.PatchParameter(PatchParameterInt.PatchVertices, 3); Closed += OnClosed; } private void OnClosed(object sender, EventArgs eventArgs) { Exit(); } public override void Exit() { Debug.WriteLine("Exit called"); GL.DeleteVertexArray(_vertexArray); GL.DeleteBuffer(_buffer); GL.DeleteProgram(_program); base.Exit(); } protected override void OnResize(EventArgs e) { // Resize the viewport to match the window size. GL.Viewport(0, 0, Width, Height); base.OnResize(e); } private float[] Matrix4ToArray(Matrix4 matrix) { float[] data = new float[16]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { data[i*4+j] = matrix[i, j]; } } return data; } private void PrintMatrix(Matrix4 matrix) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { Console.WriteLine(matrix[i,j]); } } } protected override void OnRenderFrame(FrameEventArgs e) { var timeStamp = Stopwatch.GetTimestamp(); _angle += (float)((timeStamp - _lastTimestamp) / (double)_freq); _lastTimestamp = timeStamp; GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Clear the color buffer. GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // Bind the VBO GL.BindBuffer(BufferTarget.ArrayBuffer, _buffer); // Bind the VAO GL.BindVertexArray(_vertexArray); // Use/Bind the program GL.UseProgram(_program); _model = Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.0f, 1.0f), _angle); _view = Matrix4.LookAt(new Vector3(0.0f,0.0f,5.0f), new Vector3(0.0f,0.0f,0.0f), Vector3.UnitY); _projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI * (_FOV/180f), _width / (float)_height, 0.2f, 256.0f); int location = GL.GetUniformLocation(_program, "model"); GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_model)); location = GL.GetUniformLocation(_program, "view"); GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_view)); location = GL.GetUniformLocation(_program, "projection"); GL.UniformMatrix4(location, 1, false, Matrix4ToArray(_projection)); // This draws the triangle. GL.DrawArrays(PrimitiveType.Triangles, 0, _verticeCount); // Swap the front/back buffers so what we just rendered to the back buffer is displayed in the window. Context.SwapBuffers(); base.OnRenderFrame(e); } [STAThread] static void Main() { new MainWindow().Run(60); } } } Result:
Messed-up triangles when using VertexPositionColorTexture with BasicEffect
image of the problem I used Microsoft's BasicEffect tutorial here and the code sample here: go.microsoft.com/fwlink/?LinkId=198921 and got everything to work fine. Next I changed everything to use vertexPositionNormalTexture, added a few small methods to help with the texture, and was able to render a textured cube just fine. I also made the cube spin a bit. Next I wanted to try using vertexPositionNormalTexture. Unfortunately, I got this image instead of a cube. Here's some pieces of my code that contain major modifications. Draw method protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.SteelBlue); RasterizerState rasterizerState1 = new RasterizerState(); //backface culling rasterizerState1.CullMode = CullMode.None; //turn off texture blurring graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp; graphics.GraphicsDevice.RasterizerState = rasterizerState1; foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Apply(); graphics.GraphicsDevice.DrawPrimitives( PrimitiveType.TriangleList, 0, 12 ); } base.Draw(gameTime); } Part of the method that sets up vertices private void InitializeCube() { Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f); Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f); Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f); Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f); Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f); Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f); Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f); Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f); Vector2 textureTopLeft = new Vector2(0.0f, 0.0f); Vector2 textureTopRight = new Vector2(.25f, 0.0f); Vector2 textureBottomLeft = new Vector2(0.0f, .25f); Vector2 textureBottomRight = new Vector2(.25f, .25f); Color frontColor = new Color(255, 255, 255); Color backColor = new Color(255, 0, 0); Color topColor = new Color(0, 255, 0); Color bottomColor = new Color(0, 0, 255); Color leftColor = new Color(0, 255, 255); Color rightColor = new Color(0, 0, 0); // Front face. cubeVertices[0] = new VertexPositionColorTexture( topLeftFront, frontColor, GetTexPos(2)); cubeVertices[1] = new VertexPositionColorTexture( bottomLeftFront, frontColor, GetTexPos(2) + textureBottomLeft); cubeVertices[2] = new VertexPositionColorTexture( topRightFront, frontColor, GetTexPos(2) + textureTopRight); cubeVertices[3] = new VertexPositionColorTexture( bottomLeftFront, frontColor, GetTexPos(2) + textureBottomLeft); cubeVertices[4] = new VertexPositionColorTexture( bottomRightFront, frontColor, GetTexPos(2) + textureBottomRight); cubeVertices[5] = new VertexPositionColorTexture( topRightFront, frontColor, GetTexPos(2) + textureTopRight); Initializing basicEffect private void InitializeEffect() { basicEffect = new BasicEffect(graphics.GraphicsDevice); basicEffect.World = worldMatrix; basicEffect.View = viewMatrix; basicEffect.Projection = projectionMatrix; //basicEffect.EnableDefaultLighting } LoadContent protected override void LoadContent() { canyonTexture = Content.Load<Texture2D>("CanyonTexture"); textureSheetWidth = canyonTexture.Width / 16; InitializeTransform(); InitializeEffect(); basicEffect.TextureEnabled = true; basicEffect.VertexColorEnabled = true; basicEffect.Texture = canyonTexture; InitializeCube(); } Setting up the VertexBuffer private void CreateVertexBuffer() { vertexDeclaration = new VertexDeclaration(new VertexElement[] { new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), new VertexElement(12, VertexElementFormat.Color, VertexElementUsage.Color, 0), new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) }); vertexBuffer = new VertexBuffer( graphics.GraphicsDevice, vertexDeclaration, number_of_vertices, BufferUsage.None ); cubeVertices = new VertexPositionColorTexture[number_of_vertices]; InitializeCube(); vertexBuffer.SetData<VertexPositionColorTexture>(cubeVertices); graphics.GraphicsDevice.SetVertexBuffer(vertexBuffer); } protected override void Initialize() { // TODO: Add your initialization logic here CreateVertexBuffer(); base.Initialize(); }
Basically your vertex declaration is wrong. A Color is only four bytes wide. So the offset of the texture-coordinate element that follows should be 16, not 24. However you don't even need to create a vertex declaration for this in XNA 4.0. Simply pass VertexPositionColorTexture.VertexDeclaration or typeof(VertexPositionColorTexture) to the constructor of your VertexBuffer. There is a blog post here that explains how this all works.