FNA-XNA / FNA

FNA - Accuracy-focused XNA4 reimplementation for open platforms
https://fna-xna.github.io/
2.62k stars 264 forks source link

Shaders for new projects on macos #165

Closed sherjilozair closed 6 years ago

sherjilozair commented 6 years ago

Hello,

Is it possible to use shaders with FNA on new projects on macos?

I'm guessing the answer is no, but is there any workaround to get shaders working for macos development?

Thanks.

flibitijibibo commented 6 years ago

You'll have to use FXC with Wine. This is what I do on Linux and it seems to work well, the easiest way to get this is to use winetricks dxsdk_jun2010.

sherjilozair commented 6 years ago

I managed to get my hands on fxc.exe. How do I create an effects file which FNA can load? And how do I load the file?

I did the following but got an error:

SherjilOzair:x86 sherjilozair$ wine fxc.exe /T ps_2_0 /Fo shader.fxc shader.fx
Microsoft (R) Direct3D Shader Compiler 9.29.952.3111
Copyright (C) Microsoft Corporation 2002-2009. All rights reserved.

error X3501: 'main': entrypoint not found

compilation failed; no code produced

shader.fx has:

float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.1;

struct VertexShaderInput
{
    float4 Position : POSITION0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    return AmbientColor * AmbientIntensity;
}

technique Ambient
{
    pass Pass1
    {
        VertexShader = compile vs_2_0 VertexShaderFunction();
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}
flibitijibibo commented 6 years ago

You want the fx_2_0 profile, per the FXC docs:

https://msdn.microsoft.com/en-us/library/windows/desktop/jj215820(v=vs.85).aspx#legacy_effects

Everything else in your line is correct, though if you use ContentManager we'll be searching for .fxb rather than .fxc.

EDIT: The profile is also listed in the FNA docs: https://github.com/FNA-XNA/FNA/wiki/2:-Building-with-FNA#2a-about-effect-support

sherjilozair commented 6 years ago

Okay. So I managed to compile it now. But I can't seem to load it in the project.

I have the following code:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Runtime.InteropServices;
using SDL2;

namespace FNATestProject
{
    public class TestGame : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D sheet;
        Effect effect;

        public TestGame() //This is the constructor, this function is called whenever the game class is created.
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            FileStream fileStream = new FileStream("Content/sprites.png", FileMode.Open);

            sheet = Texture2D.FromStream(GraphicsDevice, fileStream);

            effect = Content.Load<Effect>("shader");

            Console.WriteLine(sheet.Bounds);
        }

        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointWrap, null, null);
            effect.CurrentTechnique.Passes[0].Apply();
            spriteBatch.Draw(sheet, new Rectangle(0, 0, 64, 64), new Rectangle(8, 8, 8, 8), Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

I get a not found error:

Microsoft.Xna.Framework.Content.ContentLoadException: Could not load asset shader! Error: The content file was not found. ---> Microsoft.Xna.Framework.Content.ContentLoadException: The content file was not found. ---> System.IO.FileNotFoundException: Could not find file "/Users/sherjilozair/Projects/FNATestProject/FNATestProject/bin/Debug/Content/shader.xnb"
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x00191] in /Users/builder/data/lanes/5533/mono-mac-sdk/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.IO/FileStream.cs:239
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) [0x00000] in /Users/builder/data/lanes/5533/mono-mac-sdk/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.IO/FileStream.cs:91
  at at (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare)
  at System.IO.File.OpenRead (System.String path) [0x00000] in /Users/builder/data/lanes/5533/mono-mac-sdk/external/bockbuild/builds/mono-x64/mcs/class/corlib/System.IO/File.cs:350
  at Microsoft.Xna.Framework.TitleContainer.OpenStream (System.String name) [0x0002b] in /Users/sherjilozair/FNA/src/TitleContainer.cs:52
  at Microsoft.Xna.Framework.Content.ContentManager.OpenStream (System.String assetName) [0x00018] in /Users/sherjilozair/FNA/src/Content/ContentManager.cs:241
  --- End of inner exception stack trace ---
  at Microsoft.Xna.Framework.Content.ContentManager.OpenStream (System.String assetName) [0x0002c] in /Users/sherjilozair/FNA/src/Content/ContentManager.cs:247
  at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T] (System.String assetName, System.Action`1[T] recordDisposableObject) [0x00080] in /Users/sherjilozair/FNA/src/Content/ContentManager.cs:287
  --- End of inner exception stack trace ---
  at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T] (System.String assetName, System.Action`1[T] recordDisposableObject) [0x001b8] in /Users/sherjilozair/FNA/src/Content/ContentManager.cs:321
  at Microsoft.Xna.Framework.Content.ContentManager.Load[T] (System.String assetName) [0x00077] in /Users/sherjilozair/FNA/src/Content/ContentManager.cs:213
  at FNATestProject.TestGame.LoadContent () [0x00030] in /Users/sherjilozair/Projects/FNATestProject/FNATestProject/TestGame.cs:41
  at Microsoft.Xna.Framework.Game.Initialize () [0x00064] in /Users/sherjilozair/FNA/src/Game.cs:731
  at FNATestProject.TestGame.Initialize () [0x00001] in /Users/sherjilozair/Projects/FNATestProject/FNATestProject/TestGame.cs:31
  at Microsoft.Xna.Framework.Game.DoInitialize () [0x0000f] in /Users/sherjilozair/FNA/src/Game.cs:842
  at Microsoft.Xna.Framework.Game.Run () [0x00014] in /Users/sherjilozair/FNA/src/Game.cs:418
  at FNATestProject.Program.Main (System.String[] args) [0x00008] in /Users/sherjilozair/Projects/FNATestProject/FNATestProject/Program.cs:11
flibitijibibo commented 6 years ago

Rename it to .fxb rather than .fxc.

sherjilozair commented 6 years ago

It is .fxb. :)

flibitijibibo commented 6 years ago

Looks like you'll need to start stepping then - that stack should be enough to get started with, though TitleContainer.OpenStream is where you'll want to pay the most attention.

sherjilozair commented 6 years ago

Okay, my bad. I didn't add the "copy to output" property.

sherjilozair commented 6 years ago

@flibitijibibo On a side note, do you actually recommend FNA for new projects?

flibitijibibo commented 6 years ago

I only recommend it if you're already familiar with XNA, and if you're desperate, familiar with C# and nothing else, since I'm unaware of any good C# game development tools (engines don't count). I do happily recommend all the native libraries we use though, along with native programming languages in general.

sherjilozair commented 6 years ago

I'm not at all familiar with XNA, and new to game development. What I'm looking for is a good 2d game framework. Unity fails to be good at 2D, and is too bloaty. Godot is buggy right now. GMS is not open and expensive. I liked FNA the most, since it was at the optimum abstraction level (not as low as SDL, and not as high as Unity). Which framework would you recommend if not FNA?

EDIT: I like SFML after FNA, but its showcase is pretty weak. I don't know of any popular games done with it, while FNA's list is huge. Almost all my fav games are made in FNA, and ported by you. This is why I want to get into XNA/FNA.

flibitijibibo commented 6 years ago

If you're entirely new to game development, please refer to Handmade Hero:

https://handmadehero.org/

sherjilozair commented 6 years ago

@flibitijibibo I don't see how that's related to my question. IIUC, handmade hero is a tutorial series on low-level game programming on Windows. I use macos, and I'm not looking for tutorials (I prefer reading API docs), but I would like a recommendation on which framework to use. Which framework, according to you, is most similar to the XNA design and usable today for new projects?

flibitijibibo commented 6 years ago

There isn't one. FNA is the closest but I don't create new projects with it and therefore have no experience doing so, nor do I have any intention of making new projects with it since I would not use a framework like FNA or even the language FNA uses for my own personal use, nor would I do so on macOS specifically as I have always been a Linux user for all of my programming. Your only real choices are this:

I really really strongly recommend taking option 3. If you as a newcomer want advice from a professional, that is it.

sherjilozair commented 6 years ago

Let me begin by thanking you for being more than helpful on this matter, even though this is of little interest to you and the FNA project. I understand now that FNA intends to remain a preservation project, and that's quite reasonable.

I think I will take option 3. I liked SFML, and I could be productive with it. Do you have any recommendations on how to go about that? How would you do it yourself? Would you use LibSDL and write your own classes using OpenGL? I was hoping to work at a level slightly higher than that since I know from experience and advice that writing correct OpenGL code (which works cross-platform) can be tricky.

flibitijibibo commented 6 years ago

I'd use SDL and write a rendering system not too far off of FNA's IGLDevice, but probably with C structures and function pointers rather than interfaces:

https://github.com/FNA-XNA/FNA/blob/master/src/FNAPlatform/IGLDevice.cs

OpenGL is easier to make multiplatform than you might think; there are only three real tricks involved:

Nail those three down and it'll run pretty much anywhere, including OpenGL ES platforms like RPi/iOS/Android/Switch. More importantly, over time you'll find that the rendering code is probably about 5% or less of what you actually write at the end of the day (consider the size of OpenGLDevice vs. a game that reaches 50k LOC). While I don't recommend FNA itself for use, I do often recommend reading the FNAPlatform source, as it's become my personal cheat sheet over the last half decade. Some of it has even shipped in Unreal Engine 3 games!

https://github.com/FNA-XNA/FNA/tree/master/src/FNAPlatform