[Solved] Is it possible to directly load a effect from a class files string;

To say if i have a class file .cs with hlsl code in a string there.
Is it possible to directly parse and load it into the gpu as a effect at game load time ?
I mean from the cs file.

I was thinking it would be nice to have its opposite code variables to be passed, vertice buffers, vertex structs noted or contained in a corresponding class so i could reduce it all down to just calling a method.
Because im lazy and all and want to save time, i thought i have to open up the .fx and see which variables i need to pass and then i have to copy them ect… This costs me a extra 20 or 30 seconds and is distracting.
Yes im serious this is a real question lol.

require content pipeline

    public static Effect CompileFX(GraphicsDevice gd, string fxcode)
    {  
        string sourceFile = Directory.GetCurrentDirectory() + "/tmp.txt";
        File.WriteAllText(sourceFile, fxcode);

        EffectImporter importer = new EffectImporter();
        EffectContent content = importer.Import(sourceFile, null);
        EffectProcessor processor = new EffectProcessor();
        PipelineManager pm = PipelineManager(string.Empty, string.Empty, string.Empty);
        PipelineProcessorContext ppc = new PipelineProcessorContext(pm, new PipelineBuildEvent());
        CompiledEffectContent cecontent = processor.Process(content, ppc);
        ContentCompiler compiler = new ContentCompiler();

        return new Effect(gd, cecontent.GetEffectCode());
    }
1 Like

Edit.

Ah ok brain fart been a long time since i messed with the custom content stuff.
im getting a error message that this is a non invocable member ?

PipelineManager pm = PipelineManager(string.Empty, string.Empty, string.Empty);

.
but it looks like a constructor what am i missing here.

public class PipelineManager
    {
        public PipelineManager(string projectDir, string outputDir, string intermediateDir);

inside mgcb folder
(mine is C:\Program Files (x86)\MSBuild\MonoGame\v3.0\Tools\MonoGame.Framework.Content.Pipeline.dll)

Ah ok i used the dll instead it all works except for that same line.

PipelineManager(string.Empty, string.Empty, string.Empty);

Non Invocable member cant be used like a method ?

ah sorry…
new PipelineManager(string.Empty, string.Empty, string.Empty);

Ah im tarded lol just seen it ima try and run it then heap praise on you cause this is really cool.

Edit: worked…woohooo Soooo cool.

You are the man, that is really awesome.

Ah uhh oo

if i try this in a open gl project though im getting a error message…

the effect was built for a different platform.

Works fine on Dx though but, what do i need to do to get it to work in a GL project ?

.
.
here is the test class.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.IO;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
using MonoGame.Framework.Content.Pipeline.Builder;

namespace HowToLoadFxFromStringDx
{

    /// <summary>
    /// This is the main type for your game.
    /// </summary>
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;

        Effect testEffect;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
        protected override void Initialize()
        {
            base.Initialize();
        }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            //font = Content.Load<SpriteFont>("MgFont");

            EffectStandard es = new EffectStandard();
            testEffect = FxStringLoader.CompileFX(GraphicsDevice, es.effectText);
        }
        protected override void UnloadContent()
        {
            //Gv.UnloadContent();
        }
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Moccasin);
            spriteBatch.Begin();
            //
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }

    /// <summary>
    /// Doesn't work on gl though.
    /// Add the refernce the dll here.
    /// C:\Program Files (x86)\MSBuild\MonoGame\v3.0\Tools\
    /// C:\Program Files (x86)\MSBuild\MonoGame\v3.0\Tools\Microsoft.Xna.Framework.Content.Pipeline.dll
    /// </summary>
    public static class FxStringLoader
    {
        /// <summary>
        /// Load a .Fx file from string.
        /// </summary>
        public static Effect CompileFX(GraphicsDevice gd, string fxcode)
        {
            string sourceFile = Directory.GetCurrentDirectory() + "/tmp.txt";
            File.WriteAllText(sourceFile, fxcode);
            EffectImporter importer = new EffectImporter();
            EffectContent content = importer.Import(sourceFile, null);
            EffectProcessor processor = new EffectProcessor();
            PipelineManager pm;
            pm = new PipelineManager(string.Empty, string.Empty, string.Empty);
            PipelineProcessorContext ppc = new PipelineProcessorContext(pm, new PipelineBuildEvent());
            CompiledEffectContent cecontent = processor.Process(content, ppc);
            ContentCompiler compiler = new ContentCompiler();
            return new Effect(gd, cecontent.GetEffectCode());
        }
    }

    public class EffectStandard
    {
        public string effectText =
@"#if OPENGL
    #define SV_POSITION POSITION
    #define VS_SHADERMODEL vs_3_0
    #define PS_SHADERMODEL ps_3_0
#else
    #define VS_SHADERMODEL vs_4_0_level_9_1
    #define PS_SHADERMODEL ps_4_0_level_9_1
#endif

matrix WorldViewProjection;

struct VertexShaderInput
{
    float4 Position : POSITION0;
    float4 Color : COLOR0;
};

struct VertexShaderOutput
{
    float4 Position : SV_POSITION;
    float4 Color : COLOR0;
};

VertexShaderOutput MainVS(in VertexShaderInput input)
{
    VertexShaderOutput output = (VertexShaderOutput)0;

    output.Position = mul(input.Position, WorldViewProjection);
    output.Color = input.Color;

    return output;
}

float4 MainPS(VertexShaderOutput input) : COLOR
{
    return input.Color;
}

technique BasicColorDrawing
{
    pass P0
    {
        VertexShader = compile VS_SHADERMODEL MainVS();
        PixelShader = compile PS_SHADERMODEL MainPS();
    }
};";

    }
}

try

PipelineManager pm = new PipelineManager(string.Empty, string.Empty, string.Empty);
pm.Profile = GraphicsProfile.HiDef;//
pm.Platform = TargetPlatform.Windows;//

Ah unfortunately.

If i use

pm.Platform = TargetPlatform.Windows;

i get…
mgfx was built for another platform

if i use
pm.Platform = TargetPlatform.DesktopGL;

i get…
libmojoshader_64.dll could not be found.
it cant seem to be added as a reference either ?

copy libmojoshader_64.dll(mgcb folder) to your debug/release folder

Something like this ? It may help, maybe not ?

I added the dll to the project itself with add existing item ->.
Set the build action to → none.
Set the copy output directory to → copy newer or always.

And… it compiled.

Very cool.

Strange though why cant i reference the mojoshader dll anyone know ?

Something like this ? It may help, maybe not ?

This actually doesn’t work as is from a class library.

mojoshader is not supposed to get referenced, its probably a native dll. however, monogame calls its api set probably using DllImport

It shouldn’t matter except outside windows desktop though right.