Mateusz Antoniak
Mateusz Antoniak

Reputation: 11

Texture Loading Problem in c# using sharpDx Direct3D11

I started doing my 3d engine in sharpdx and it works pretty well, but there is small one problem with the texture(How it looks on objects). So the texture loader works as well with shaders but how can i achieve the full texture(The texture fit my object vertices) on my objects(I'm using simple brick texture in png format and only what i see is wrapped stripes).

My code:

Main Dx11 Parts

private void InitDX11()
{
    Logger.Log($"Starting initializing dx11..", LogType.INFO);
    lastFrameTime = 0f;  // Zainicjuj czas ostatniej klatki
    // Create the RenderForm
    renderForm = new RenderForm("DirectX 3D Cube")
    {
        FormBorderStyle = FormBorderStyle.None,
        KeyPreview = true,
        TopLevel = false,
        Dock = DockStyle.Fill,
    };
    this.WindowState = FormWindowState.Normal;

    renderForm.MouseClick += (sender, e) =>
    {
        renderForm.Focus();
    };

    renderForm.MouseLeave += (sender, e) =>
    {
        this.Focus();
    };

    renderForm.MouseMove += (sender, e) =>
    {
        if (!Initialized)
        {
            return; // Ignoruj zdarzenia myszy, jeśli program jeszcze się nie załadował.
        }

        if (attachCursor)
        {
            var centerX = renderForm.ClientSize.Width / 2;
            var centerY = renderForm.ClientSize.Height / 2;

            // Calculate mouse movement delta
            var deltaX = e.X - centerX;
            var deltaY = e.Y - centerY;

            // Update camera rotation based on mouse movement
            cameraYaw += deltaX * sensitivity;
            cameraPitch += -(deltaY * sensitivity);

            // Constrain the pitch to avoid gimbal lock (restrict pitch angle)
            cameraPitch = MathUtil.Clamp(cameraPitch, -MathUtil.PiOverTwo + 0.01f, MathUtil.PiOverTwo - 0.01f);

            // Center cursor back to the screen center (to keep continuous movement)
            Cursor.Position = renderForm.PointToScreen(new System.Drawing.Point(centerX, centerY));
        }
    };

    renderForm.KeyDown += (sender, e) =>
    {
        if (attachCursor)
        {
            if (e.KeyCode == Keys.W) isWKeyPressed = true;
            else if (e.KeyCode == Keys.S) isSKeyPressed = true;
            else if (e.KeyCode == Keys.A) isAKeyPressed = true;
            else if (e.KeyCode == Keys.D) isDKeyPressed = true;
            else if (e.KeyCode == Keys.Space) isSpacePressed = true; // Spacebar pressed (upward)
            else if (e.KeyCode == Keys.ShiftKey) isShiftPressed = true; // Shift pressed (downward)
            else if (e.KeyCode == Keys.ControlKey) isCtrlPressed = true; // Shift pressed (downward)
        }
    };

    renderForm.KeyUp += (sender, e) =>
    {
        switch (e.KeyCode)
        {
            case Keys.F5:
                SetFullScreen(true);
                break;
            case Keys.F4:
                SetFullScreen(false);
                break;
            case Keys.F3:
                ToggleAttachCursor();
                break;

        }
        if (attachCursor)
        {
            if (e.KeyCode == Keys.W) isWKeyPressed = false;
            else if (e.KeyCode == Keys.Oemtilde)
            {
                ToggleAttachCursor();
                ToggleConsole();
            }
            else if (e.KeyCode == Keys.S) isSKeyPressed = false;
            else if (e.KeyCode == Keys.A) isAKeyPressed = false;
            else if (e.KeyCode == Keys.D) isDKeyPressed = false;
            else if (e.KeyCode == Keys.Space) isSpacePressed = false; // Spacebar released
            else if (e.KeyCode == Keys.ShiftKey) isShiftPressed = false; // Shift released
            else if (e.KeyCode == Keys.ControlKey) isCtrlPressed = false; // Shift released
        }
    };

    Logger.Log($"Events Added", LogType.INFO);

    dxApiRenderPanel.Controls.Add(renderForm);
    renderForm.BringToFront();
    renderForm.Show();

    // Set up the SwapChain description
    desc = new SwapChainDescription()
    {
        BufferCount = 2, // Number of back buffers
        ModeDescription = new ModeDescription(dxApiRenderPanel.ClientSize.Width, dxApiRenderPanel.ClientSize.Height, new Rational(60, 1), Format.R8G8B8A8_UNorm), // Resolution, refresh rate, and format
        IsWindowed = true, // Windowed mode
        OutputHandle = renderForm.Handle, // Handle to the window
        SampleDescription = new SampleDescription(8, 0), // multisampling
        SwapEffect = SwapEffect.Discard, // Swap effect
        Usage = Usage.RenderTargetOutput // Usage of the back buffer
    };


    Logger.Log($"Creating device using swapchain..", LogType.INFO);
    try
    {
        // Create Device and SwapChain
        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain);
        context = device.ImmediateContext;
    }
    catch
    {
        Logger.Log($"Cannot create device with swapchain!", LogType.ERROR);
    }
    Logger.Log($"Succesfully created and added device with context!", LogType.INFO);


    Logger.Log($"Creating factory and making window association..", LogType.INFO);
    try
    {
        // Ignore all windows events
        var factory = swapChain.GetParent<SharpDX.DXGI.Factory>();
        var adapter = factory.GetAdapter(0);
        var adapterDescription = adapter.Description;
        this.Text = $"RapidEngine11 - GPU: {adapterDescription.Description}";
        factory.MakeWindowAssociation(renderForm.Handle, WindowAssociationFlags.IgnoreAll);
    }
    catch
    {
        Logger.Log($"Cannot create factory!", LogType.ERROR);
    }
    Logger.Log($"Succesfully created and added factory with window association!", LogType.INFO);


    Logger.Log($"Compiling shaders..", LogType.INFO);
    try
    {
        // Compile Shaders
        var vertexShaderByteCode = ShaderBytecode.CompileFromFile("Shader.fx", "VS", "vs_4_0");
        vertexShader = new VertexShader(device, vertexShaderByteCode);

        var pixelShaderByteCode = ShaderBytecode.CompileFromFile("Shader.fx", "PS", "ps_4_0");
        pixelShader = new PixelShader(device, pixelShaderByteCode);

        try
        {
            var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
            layout = new InputLayout(device, signature, new[]
            {
                new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 32, 0)
            });
        }
        catch
        {
            Logger.Log($"Cannot create layout!", LogType.ERROR);
        }

    }
    catch
    {
        Logger.Log($"Cannot compile shaders!", LogType.ERROR);
    }
    Logger.Log($"Succesfully compiled shaders and created shaders layout!", LogType.INFO);

    Logger.Log($"Preparing for objects initialization..", LogType.INFO);
    try
    {
        InitObjects();
    }
    catch
    {
        Logger.Log($"Cannot initialize objects!", LogType.ERROR);
    }
    Logger.Log($"Succesfully initialized objects!", LogType.INFO);


    Logger.Log($"Preparing for constant buffer creation..", LogType.INFO);
    try
    {
        // Create Constant Buffer for transformation matrices
        contantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);
    }
    catch
    {
        Logger.Log($"Cannot create constant buffer!", LogType.ERROR);
    }
    Logger.Log($"Succesfully created constant buffer!", LogType.INFO);


    Logger.Log($"Setting up rendering state..", LogType.INFO);
    try
    {
        // Set up Render State
        context.InputAssembler.InputLayout = layout;
        context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
        context.VertexShader.SetConstantBuffer(0, contantBuffer);
        context.VertexShader.Set(vertexShader);
        context.PixelShader.Set(pixelShader);
    }
    catch
    {
        Logger.Log($"Cannot set up rendering state!", LogType.ERROR);
    }
    Logger.Log($"Succesfully set up rendering state!", LogType.INFO);


    Logger.Log($"Preparing camera setup..", LogType.INFO);
    try
    {
        // Prepare matrices for the view and projection and initialize camera setup
        view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 1), new Vector3(0, 1, 0)); // View matrix
        proj = Matrix.Identity; // Projection matrix
    }
    catch
    {
        Logger.Log($"Cannot prepare for camera setup!", LogType.ERROR);
    }
    Logger.Log($"Succesfully prepared camera setup!", LogType.INFO);



    renderForm.Focus();

    // Define a RasterizerStateDescription with backface culling enabled
    rasterizerStateDescription = new RasterizerStateDescription
    {
        FillMode = SharpDX.Direct3D11.FillMode.Solid,
        CullMode = CullMode.None, // Enable backface culling
        IsMultisampleEnabled = true,
    };


    Logger.Log($"Starting RenderLoop", LogType.INFO);
    // Start rendering loop
    RenderLoop.Run(renderForm, () =>
    {
        RenderingLoop();
    });
}

private void InitObjects()
{
    // Create a root TreeNode for the scene
    scene = new TreeNode
    {
        ImageIndex = 0,
        SelectedImageIndex = 0,
        Text = "Scene",
        Tag = "Scene"
    };

    // Add the scene root node to the objectsView TreeView
    objectsView.Nodes.Add(scene);


    // Initialize Cube and Floor objects
    Cube cube1 = new Cube("Cube1", ObjectType.Cube);
    var cubeBuffer = Buffer.Create(device, BindFlags.VertexBuffer, cube1.VertexData);
    cube1.Pos = new Vector3(-2f, 0, 0);
    cube1.HasTexture = true;
    cube1.VertexBuffer = cubeBuffer;


    try
    {
        Texture2D texture;
        ShaderResourceView textureView;

        texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), "brick_texture.png"));
        textureView = new ShaderResourceView(device, texture);

        cube1.TextureView = textureView;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    


    Cylinder cylinder1 = new Cylinder("Cylinder1", ObjectType.Cylinder);
    var cylinder1Buffer = Buffer.Create(device, BindFlags.VertexBuffer, cylinder1.VertexData);
    cylinder1.Pos = new Vector3(2f, 0, 0);
    cylinder1.VertexBuffer = cylinder1Buffer;

    Floor floor1 = new Floor("Floor1", ObjectType.Floor);
    var floorBuffer = Buffer.Create(device, BindFlags.VertexBuffer, floor1.VertexData);
    floor1.VertexBuffer = floorBuffer;
    floor1.Pos = new Vector3(0f, (-1.01f) - 0.05f, 0f);

    try
    {
        // Add the objects to the scene
        objects.Add(cube1);
        objects.Add(cylinder1);
        objects.Add(floor1);
    }
    catch
    {
        Logger.Log($"Cannot add objects!", LogType.ERROR);
    }

    // Now add the objects to the scene TreeNode
    foreach (Object obj in objects)
    {
        TreeNode objectNode = new TreeNode
        {
            ImageIndex = 1,
            SelectedImageIndex = 1,
            Tag = "Object",
            Text = obj.Name // Set the name of the object as the text for the node
        };
        scene.Nodes.Add(objectNode);
        Logger.Log($"Succesfully added object {obj.Name}", LogType.INFO);
    }


    // Refresh the objectsView TreeView to display the newly added nodes
    objectsView.ExpandAll();
}

SamplerState samplerState;
private void RenderObjects()
{
    context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; // Define the primitive topology
                                                                               
    foreach (var rObject in objects)
    {
        // Convert degrees to radians
        float radiansX = MathUtil.DegreesToRadians(rObject.Rotation.X);
        float radiansY = MathUtil.DegreesToRadians(rObject.Rotation.Y);
        float radiansZ = MathUtil.DegreesToRadians(rObject.Rotation.Z);
        // Calculate world transformation matrices
        var worldRotationX = Matrix.RotationX(radiansX); // Rotation around X-axis
        var worldRotationY = Matrix.RotationY(radiansY); // Rotation around Y-axis
        var worldRotationZ = Matrix.RotationZ(radiansZ); // Rotation around Z-axis


        var worldRotation = worldRotationX * worldRotationY * worldRotationZ;
        var worldTranslation = Matrix.Translation(rObject.Pos.X, rObject.Pos.Y, rObject.Pos.Z); // Position
        var worldScaling = Matrix.Scaling(rObject.Scale.X, rObject.Scale.Y, rObject.Scale.Z); // Scale
                                                                                              // Combine transformations: Scaling -> Rotation -> Translation
        var worldMatrix = worldScaling * worldRotation * worldTranslation;
        var worldViewProj = worldMatrix * viewProj;
        worldViewProj.Transpose();

        // Check if the object has a texture
        if (rObject.HasTexture)
        {
            // Set the texture
            context.PixelShader.SetShaderResource(0, rObject.TextureView);

            // Create and set sampler state
            if (samplerState == null)
            {
                SamplerStateDescription samplerDesc = new SamplerStateDescription
                {
                    Filter = SharpDX.Direct3D11.Filter.MinimumMinMagLinearMipPoint,
                    AddressU = TextureAddressMode.Wrap,
                    AddressV = TextureAddressMode.Wrap,
                    AddressW = TextureAddressMode.Wrap,
                    ComparisonFunction = Comparison.Never,
                    BorderColor = Color4.White,
                    MinimumLod = 0,
                    MaximumLod = float.MaxValue
                };

                samplerState = new SamplerState(device, samplerDesc);
            }
            context.PixelShader.SetSampler(0, samplerState);
        }
        else
        {
            context.PixelShader.SetShaderResource(0, null); // Unset texture to use color
        }

        // Map the constant buffer for writing (use MapMode.WriteDiscard)
        DataStream dataStream;
        context.MapSubresource(contantBuffer, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out dataStream);

        // Write the worldViewProj matrix to the constant buffer
        dataStream.Write(worldViewProj);

        // Unmap the constant buffer, allowing the GPU to use it
        context.UnmapSubresource(contantBuffer, 0);

        // Set the object's vertex buffer and input layout
        context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(rObject.VertexBuffer, Utilities.SizeOf<Vertex>(), 0));

        // Draw the object
        context.Draw(rObject.VertexData.Length, 0);
    }
}

Other Classes that i use

public class TextureLoader
{
    /// <summary>
    /// Loads a bitmap using WIC.
    /// </summary>
    /// <param name="deviceManager"></param>
    /// <param name="filename"></param>
    /// <returns></returns>
    public static SharpDX.WIC.BitmapSource LoadBitmap(SharpDX.WIC.ImagingFactory2 factory, string filename)
    {
        var bitmapDecoder = new SharpDX.WIC.BitmapDecoder(
            factory,
            filename,
            SharpDX.WIC.DecodeOptions.CacheOnDemand
            );

        var formatConverter = new SharpDX.WIC.FormatConverter(factory);

        formatConverter.Initialize(
            bitmapDecoder.GetFrame(0),
            SharpDX.WIC.PixelFormat.Format32bppPRGBA,
            SharpDX.WIC.BitmapDitherType.None,
            null,
            0.0,
            SharpDX.WIC.BitmapPaletteType.Custom);

        return formatConverter;
    }

    /// <summary>
    /// Creates a <see cref="SharpDX.Direct3D11.Texture2D"/> from a WIC <see cref="SharpDX.WIC.BitmapSource"/>
    /// </summary>
    /// <param name="device">The Direct3D11 device</param>
    /// <param name="bitmapSource">The WIC bitmap source</param>
    /// <returns>A Texture2D</returns>
    public static SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(SharpDX.Direct3D11.Device device, SharpDX.WIC.BitmapSource bitmapSource)
    {
        // Allocate DataStream to receive the WIC image pixels
        int stride = bitmapSource.Size.Width * 4;
        using (var buffer = new SharpDX.DataStream(bitmapSource.Size.Height * stride, true, true))
        {
            // Copy the content of the WIC to the buffer
            bitmapSource.CopyPixels(stride, buffer);
            return new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription()
            {
                Width = bitmapSource.Size.Width,
                Height = bitmapSource.Size.Height,
                ArraySize = 1,
                BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource,
                Usage = SharpDX.Direct3D11.ResourceUsage.Immutable,
                CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
                Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm,
                MipLevels = 1,
                OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
                SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
            }, new SharpDX.DataRectangle(buffer.DataPointer, stride));
        }
    }
}


internal class Cube : Object
{
    public Cube(string name, ObjectType objType) : base(name, objType)
    {
        VertexData = new Vertex[]
        {
            // Front Face
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Color4(1.0f, 0.0f, 0.0f, 1.0f), new Vector2(1.0f, 1.0f)),

            // Back Face
            new Vertex(new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Color4(0.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),

            // Top Face
            new Vertex(new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4(-1.0f, 1.0f,  1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f, 1.0f, -1.0f,  1.0f), new Color4(0.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 1.0f)),

            // Bottom Face
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f,  1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f,  1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f, -1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f,  1.0f,  1.0f), new Color4(1.0f, 1.0f, 0.0f, 1.0f), new Vector2(1.0f, 0.0f)),

            // Left Face
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4(-1.0f,  1.0f,  1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f,  1.0f, -1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4(-1.0f, -1.0f,  1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(1.0f, 1.0f)),
            new Vertex(new Vector4(-1.0f,  1.0f,  1.0f,  1.0f), new Color4(0.0f, 1.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),

            // Right Face
            new Vertex(new Vector4( 1.0f, -1.0f, -1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f,  1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f, -1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 0.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f, -1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(0.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f, -1.0f,  1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 1.0f)),
            new Vertex(new Vector4( 1.0f,  1.0f,  1.0f,  1.0f), new Color4(1.0f, 0.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f)),
        };
    }
}

public abstract class Object
{
    // Basic transformation properties
    public Vector3 Rotation { get; set; } = new Vector3 (0.0f, 0.0f, 0.0f);
    public Vector3 Scale { get; set; } = new Vector3 (1.0f, 1.0f, 1.0f);
    public Vector3 Pos { get; set; }

    public Vertex[] VertexData { get; set; }

    public Buffer VertexBuffer { get; set; }

    // Name of the object (required by all derived classes)
    public string Name { get; private set; }
    public string Tag { get; private set; }

    public ObjectType ObjectType { get; private set; }

    public bool HasTexture { get; set; }
    public ShaderResourceView TextureView { get; set; }

    // Constructor that enforces providing a name
    public Object(string name, ObjectType objectType = ObjectType.Cube, bool hasTexture = false, string tag = null)
    {
        Name = name ?? throw new ArgumentNullException(nameof(name), "Object name cannot be null");
        Tag = tag;
        HasTexture = hasTexture;
        ObjectType = objectType;
    }

    // Dispose resources
    public virtual void Dispose()
    {
        VertexBuffer?.Dispose();
    }
}

public enum ObjectType
{
    Cube,
    Cylinder,
    Floor
}

 [StructLayout(LayoutKind.Sequential)]
 public struct Vertex
 {
     public Vector4 Position;
     public Color4 Color;
     public Vector2? TexCoord; // Add texture coordinates

     public Vertex(Vector4 position, Color4 color, Vector2? texCoord = null)
     {
         Position = position;
         Color = color;
         TexCoord = texCoord;
     }
 }

My Shader code

// Shader.fx

cbuffer MatrixBuffer : register(b0)
{
    matrix WorldViewProj;
};

Texture2D tex : register(t0);  // Add texture sampler
SamplerState samp : register(s0); 

struct VS_IN
{
    float4 pos : POSITION;
    float4 col : COLOR;
    float2 tex : TEXCOORD;  // Add texture coordinates
};

struct PS_IN
{
    float4 pos : SV_POSITION;
    float4 col : COLOR;
    float2 tex : TEXCOORD;
};

float4x4 worldViewProj;

PS_IN VS(VS_IN input)
{
    PS_IN output = (PS_IN)0;
    
    output.pos = mul(input.pos, WorldViewProj);
    output.col = input.col;
    output.tex = input.tex;
    
    return output;
}

float4 PS(PS_IN input) : SV_Target
{
    float4 textureColor = tex.Sample(samp, input.tex);

    // Debugging: Check the sampled color
    // Uncomment the line below to see the texture color being sampled
    //return textureColor;

    // Fallback to vertex color if texture alpha is zero
    return (textureColor.a > 0.0f) ? textureColor : input.col;
}

I hope someone will try to figure this out!

I expected that the textures will be kind of fitting all of the sides on object and not be messy, I Used brick texture for example but i dont get bricks i get brick strips, here is the texture look

Texture: Brick Texture

How the texture looks in my engine Brick Texture Look in engine

Upvotes: 0

Views: 56

Answers (0)

Related Questions