How to load vertex/fragment programs from string?

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

How to load vertex/fragment programs from string?

Post by KungFooMasta »

I wasn't sure if I should post this in the Help or Developers section, its a somewhat technical question for more advanced Ogre usage.

I previously had a class that could perform basic 2d rendering operations against a RenderTarget, which is my UI solution, however I no longer have the fixed function pipeline to use. (DX11, hlsl 4_0, WinRT) So I need to create shaders to do my UI drawing.

Fortunately the vertex and fragment programs should be simple. (Although I have to admit my programs could likely be unusable :mrgreen: )

Vertex Shader: Basically I think it should just pass through the vertices and not do translation. Would like to be able to test this..

Code: Select all

//-----------------------------------------------------------------------------
// Function Name: main
// Function Desc: Vertex Program Entry point
//-----------------------------------------------------------------------------
void main
	(
	 in float2	inPos : POSITION, 
	 in float4	inColor : SV_Target, 
	 in float2	inTexcoord2 : TEXCOORD0, 
	 out float2	outPos : SV_Position, 
	 out float4	outColor : SV_Target, 
	 out float2	outTexcoord2 : TEXCOORD0
	)
{
	outPos = inPos;
	outColor = inColor;
	outTexcoord2 = inTexcoord2;
}
Fragment shader: slightly more complex, sample a texture and return its color.

Code: Select all

//-----------------------------------------------------------------------------
//                         GLOBAL PARAMETERS
//-----------------------------------------------------------------------------

Texture2D	gTextureSampler0 : register(t0);
SamplerState	gTextureSamplerState0 : register(s0);

//-----------------------------------------------------------------------------
// Function Name: main
// Function Desc: Pixel Program Entry point
//-----------------------------------------------------------------------------
void main
	(
	 in float4	inColor : SV_Target, 
	 in float2	inTexcoord2 : TEXCOORD0, 
	 out float4	outColor : SV_Target
	)
{
	return gTextureSampler0.Sample(gTextureSamplerState0, inTexcoord2) * inColor;
}
Question:
My Renderer2D class manually sets up the render system, and so I don't use the material system, and I don't know how the RTSS would come into play here. (I believe it is also material related) I want to manually setup the render system using the RenderSystem::bindGpuProgram method, however I need a GpuProgramPtr instance. So how to go from a string, which contains the Vertex Shader code above, to a GpuProgramPtr? I tried using the GpuProgramManager::loadFromString method, however I get the following exception:

Code: Select all

    void D3D11GpuProgram::loadFromSource(void)
    {
        String message = "AIZ:D3D11 dosn't support assembly shaders. Shader name:" + mName + "\n" ;
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
            "D3D11GpuProgram::loadFromSource");
    }
I'm also not sure what the correct "syntaxCode" is, or if its even relevant here. Here is how I invoke the API:

Code: Select all

mVertexProgram = mgr->loadFromString(gVertexProgramName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, gVertexProgram, Ogre::GpuProgramType::GPT_VERTEX_PROGRAM, Ogre::String("vs_4_0"));
I've searched the source code trying to look for syntaxes to use, but didn't find a list.

Also, will I need to call bindGpuParameters? These shaders are very simple in what they do, I just want to be able to draw lines, rectangles, and images on the screen!

Please help. I want to get back to writing my game. :)
Creator of QuickGUI!
User avatar
tod
Troll
Posts: 1394
Joined: Wed Aug 02, 2006 9:41 am
Location: Bucharest
x 94
Contact:

Re: How to load vertex/fragment programs from string?

Post by tod »

Ogre deferred shading generates materials from templates and in code. Look how it does it.
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: How to load vertex/fragment programs from string?

Post by KungFooMasta »

Thanks tod. I read through it, but I'm actually working even lower than this. When it comes down to it, a material is a collection of passes, and each pass will configure the underlying RenderSystem class to prepare it for performing a render operation. I don't need to create materials or passes, I just need to figure out how they are able to load a program from string/disk and compile it.

For example, materials are used by the SceneManager class when rendering objects, notable SceneManager::_setPass. The SceneManager class is doing all the work for us, taking the pass and setting up the RenderSystem:

Code: Select all

        if (pass->hasVertexProgram())
        {
            bindGpuProgram(pass->getVertexProgram()->_getBindingDelegate());
Now I need to see how the pass is able to load Vertex Programs. Anyhow I'll keep digging..
Creator of QuickGUI!
User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Re: How to load vertex/fragment programs from string?

Post by KungFooMasta »

Ok I found a solution, although not entirely what I wanted. For some reason the Material system, when it parses my scripts, it will load the GpuPrograms correctly. However when I manually load it, I see the following:

Code: Select all

    void D3D11GpuProgram::loadImpl(void)
    {
        // Normal load-from-source approach
        if (mLoadFromFile)
        {
            // find & load source code
            DataStreamPtr stream = 
                ResourceGroupManager::getSingleton().openResource(
                mFilename, mGroup, true, this);
            mSource = stream->getAsString();
        }

        // Call polymorphic load
        loadFromSource();
    }
    //-----------------------------------------------------------------------------
    void D3D11GpuProgram::loadFromSource(void)
    {
        String message = "AIZ:D3D11 dosn't support assembly shaders. Shader name:" + mName + "\n" ;
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
            "D3D11GpuProgram::loadFromSource");
    }
If you'll notice, loadFromSource() is called in any case, leading to an exception.

I could figure out how the Material parsing system created the GpuPrograms using a different approach, but I'm fine with loading from disk using the material system.

And just in case it might help others, Here are my shaders and material:
UI_Rendering_VertexShader.hlsl

Code: Select all

//-----------------------------------------------------------------------------
// Function Name: main
// Function Desc: Vertex Program Entry point
//-----------------------------------------------------------------------------
void main
	(
	 in float4	inPos : SV_Position,
	 in float4	inColor : COLOR,
	 in float2	inTexcoord2 : TEXCOORD0, 
	 out float4	outPos : SV_Position, 
	 out float4	outColor : COLOR,
	 out float2	outTexcoord2 : TEXCOORD0
	)
{
	outPos = inPos;
	outColor = inColor;
	outTexcoord2 = inTexcoord2;
}
UI_Rendering_FragmentShader.hlsl

Code: Select all

//-----------------------------------------------------------------------------
//                         GLOBAL PARAMETERS
//-----------------------------------------------------------------------------

Texture2D	gTexture : register(t0);
SamplerState	gTextureSamplerState0 : register(s0);

//-----------------------------------------------------------------------------
// Function Name: main_w_Sampling
// Function Desc: Pixel Program Entry point
//-----------------------------------------------------------------------------
void main_w_Sampling
	(
	 in float4	inPos : SV_Position,
	 in float4	inColor : COLOR,
	 in float2	inTexcoord2 : TEXCOORD0, 
	 out float4	outColor : SV_Target
	)
{
	outColor = gTexture.Sample(gTextureSamplerState0, inTexcoord2) * inColor;
}

//-----------------------------------------------------------------------------
// Function Name: main_no_Sampling
// Function Desc: Pixel Program Entry point
//-----------------------------------------------------------------------------
void main_no_Sampling
	(
	 in float4	inPos : SV_Position,
	 in float4	inColor : COLOR,
	 in float2	inTexcoord2 : TEXCOORD0,
	 out float4	outColor : SV_Target
	)
{
	outColor = inColor;
}
UI_Rendering.material

Code: Select all

vertex_program UI_Rendering_VertexShader hlsl
{
 	source UI_Rendering_VertexShader.hlsl
	entry_point main
	target vs_4_0
}

fragment_program UI_Rendering_FragmentShader_w_Sampling hlsl
{
	source UI_Rendering_FragmentShader.hlsl
	entry_point main_w_Sampling
	target ps_4_0
}

fragment_program UI_Rendering_FragmentShader_no_Sampling hlsl
{
	source UI_Rendering_FragmentShader.hlsl
	entry_point main_no_Sampling
	target ps_4_0
}

material UI_Rendering_w_Sampling
{
	technique
	{
		pass
		{
			lighting off			 
			depth_check off
			depth_write off
			diffuse vertexcolour
			ambient vertexcolour
			scene_blend alpha_blend
			
			vertex_program_ref UI_Rendering_VertexShader
			{
			}

			fragment_program_ref UI_Rendering_FragmentShader_w_Sampling
			{
			}
		}
	}
}

material UI_Rendering_no_Sampling
{
	technique
	{
		pass
		{
			lighting off			 
			depth_check off
			depth_write off
			diffuse vertexcolour
			ambient vertexcolour
			scene_blend alpha_blend
			
			vertex_program_ref UI_Rendering_VertexShader
			{
			}

			fragment_program_ref UI_Rendering_FragmentShader_no_Sampling
			{
			}
		}
	}
}
Creator of QuickGUI!
Post Reply