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
Alkher
March 26, 2018, 7:21am
12
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.