Page 1 of 1

can't output DEPTH in a fragment program

Posted: Wed Mar 05, 2008 2:55 pm
by Thieum
Hi!
I am trying to write depth in the Z-Buffer with this minimal pixel shader :

Code: Select all

void TerrainDecalFP(
	out float4 oColor : COLOR,
	out float oDepth : DEPTH
)
{
	oColor = 1;
	oDepth = 1;
}
but when the material is loaded I get this error

Code: Select all

(15): error X2022: scalar registers cannot be masked
There is two strange thing : the Cg file containing the function is only 9 lines long but the error says "(15)" and the exception raised by the error shows an error box whereas other cg compilation errors are just written in the log

The shader is compiled with the ps_2_0 profile and there is only a call to the shader in the material.
This shader works with XSI's real-time materials, then can this be an OGRE bug ?

Posted: Wed Mar 05, 2008 5:27 pm
by sinbad
That message is coming from the Cg compiler, not Ogre.

I've tried this and it works fine. Please post how you've declared the shader.

Posted: Thu Mar 06, 2008 9:54 am
by Thieum
here is the declaration :

Code: Select all

fragment_program TerrainDecalFP cg
{
	source TerrainDecal2.cg
	entry_point TerrainDecalFP 
	profiles ps_2_0
}

material decal
{
	technique
	{
		pass
		{
			fragment_program_ref TerrainDecalFP 
			{	
			}
		}
	}
}
As I said, it is minimal. I also tested it outside OGRE and it worked too.

Posted: Thu Mar 06, 2008 12:43 pm
by iloseall
Maybe you has two files named "TerrainDecal2.cg".
Try to search TerrainDecal2.cg.

Posted: Thu Mar 06, 2008 4:30 pm
by Thieum
I'am afraid this is the only file with this name. If i remove the "oDepth = 1;" line from the script, there is no longer an error.

Posted: Sat Apr 26, 2008 11:21 pm
by Caelin
I am getting the same problem with a tech demo I am trying to create. Currently I am taking the deferred shading demo and translating it in to cg instead of using HLSL and GLSL. I would rather just use cg so I only have to learn the syntax for the one language. One problem I am running in to however is the ambient lighting pixel shader outputs depth and I am getting the same error from it. I enabled logging on the cg program manager plugin and it is showing that cg is compiling the depth output as a float3 instead of a plain float like it should. I am still working on seeing if I can try to get cg to compile depth as a single float scalar but figured I would post here and let everyone know what I had found. Also here is a snippet from the log of the plugin compiling the ambient lighting shader I was using along with the actual cg code.


Cg Code

Code: Select all

struct AMBIENTOUTPUT
{
	float4 Color : COLOR;
	float Depth : DEPTH;
};

AMBIENTOUTPUT AmbientLightingP( float2 TexCoord: TEXCOORD0, 
			  float3 ProjCoord: TEXCOORD1,

			uniform float4x4 Proj,
			uniform float4 AmbientColor,
			uniform sampler2D Tex0 : register(s0),
			uniform sampler2D Tex1 : register(s1),
			uniform sampler2D Tex2 : register(s2),
			uniform sampler2D Tex3 : register(s3) )
{
	// Load GBuffer in to structure;
	GBUFFER In;
	LoadGBuffer( In, TexCoord, Tex0, Tex1, Tex2, Tex3 );

	// Clip fragment if depth is too close, so the skybox can be rendered on the background
	float Depth = GetDepth( In );
	clip( Depth - 5.0f );

	AMBIENTOUTPUT Out;
	// Calculate ambient colour of fragment
	Out.Color = float4(AmbientColor * GetDiffuse( In ), 0.0f);

	// Calculate depth of fragment;
	Out.Depth = ProjCoord.z * Proj[2][2] + Proj[2][3] / Depth;
	
	return Out;
}

Log output

Code: Select all

16:08:24: ps_3_0
// cgc version 2.0.0010, build date Dec 12 2007
// command line args: -q -profile ps_3_0 -entry AmbientLightingP
//vendor NVIDIA Corporation
//version 2.0.0.10
//profile ps_3_0
//program AmbientLightingP
//semantic AmbientLightingP.Proj
//semantic AmbientLightingP.AmbientColor
//semantic AmbientLightingP.Tex0 : TEXUNIT0
//semantic AmbientLightingP.Tex1 : TEXUNIT1
//semantic AmbientLightingP.Tex2 : TEXUNIT2
//semantic AmbientLightingP.Tex3 : TEXUNIT3
//var float2 TexCoord : $vin.TEXCOORD0 : ATTR0 : 0 : 1
//var float3 ProjCoord : $vin.TEXCOORD1 : ATTR1 : 1 : 1
//var float4x4 Proj :  : c[0], 4 : 2 : 1
//var float4 AmbientColor :  : c[4] : 3 : 1
//var sampler2D Tex0 : TEXUNIT0 : texunit 0 : 4 : 1
//var sampler2D Tex1 : TEXUNIT1 : texunit 1 : 5 : 0
//var sampler2D Tex2 : TEXUNIT2 : texunit 2 : 6 : 0
//var sampler2D Tex3 : TEXUNIT3 : texunit 3 : 7 : 1
//var float4 AmbientLightingP.Color : $vout.COLOR : COL : -1 : 1
//var float3 AmbientLightingP.Depth : $vout.DEPTH : DEPR : -1 : 1
//var <none>4 $kill_0000 : $vout.$kill : $kill : -1 : 0
//const c[5] = 65536 0.00390625 256 -1
//const c[6] = 1.5258789e-005 -5 0 1
dcl_2d s0
dcl_2d s3
def c5, 65536.00000000, 0.00390625, 256.00000000, -1.00000000
def c6, 0.00001526, -5.00000000, 0.00000000, 1.00000000
dcl_texcoord0 v0.xy
dcl_texcoord1 v1.xyz
texld r0.xy, v0, s0
mul r0.z, r0.y, c5.x
mul r0.w, r0.z, c5.y
abs r0.w, r0
frc r0.w, r0
mul r0.w, r0, c5.z
cmp r0.z, r0, r0.w, -r0.w
mad r0.y, -r0.z, c6.x, r0
add r0.w, r0.z, c5
mul r0.w, r0, r0
rcp r0.z, r0.w
mad r0.x, r0.y, c6, r0
mul r0.x, r0, r0.z
add r0.y, r0.x, c6
cmp r0.y, r0, c6.z, c6.w
mov_pp r1, -r0.y
rcp r0.x, r0.x
mul r0.w, r0.x, c2
texld r0.xyz, v0, s3
texkill r1.xyzw
mad oDepth.z, v1.z, c2.z, r0.w
mul oC0.xyz, r0, c4
mov oC0.w, c6.z

Posted: Sat Apr 26, 2008 11:55 pm
by Caelin
I found a post on the cg forums stating that this is a bug with the code generation of cgc that is specific to D3D. So this has nothing to do with Ogre and is actually a problem with the cg toolkit. Here is the link to the post.

http://developer.nvidia.com/forums/inde ... #entry2378

Posted: Mon Apr 28, 2008 8:41 am
by Thieum
Thanks for the answer!

Posted: Sun May 04, 2008 7:20 pm
by _tommo_
I also have this problem...
so, knowing that it's a CG bug, what we could do to avoid it?

Posted: Mon May 05, 2008 5:53 am
by Caelin
_tommo_ wrote:I also have this problem...
so, knowing that it's a CG bug, what we could do to avoid it?
I added a couple of lines to the D3D9_RenderSystem plugin to patch the problem as a temporary fix until the CG compiler is fixed. Hopefully this is in the next patch. To fix this issue I just replaced the oDepth.z with oDepth using a simple find and replace. I did this in the D3D9GpuProgram::loadFromSource function in the file OgreD3D9GpuProgram.cpp. The following code is the original function and then the modified version.

Original Function

Code: Select all

void D3D9GpuProgram::loadFromSource(void)
{
    // Create the shader
    // Assemble source into microcode
    LPD3DXBUFFER microcode;
    LPD3DXBUFFER errors;
		
    HRESULT hr = D3DXAssembleShader(
        mSource.c_str(),
        static_cast<UINT>(mSource.length()),
        NULL,               // no #define support
        NULL,               // no #include support
        0,                  // standard compile options
        &microcode,
        &errors);

    if (FAILED(hr))
    {
        String message = "Cannot assemble D3D9 shader " + mName + " Errors:\n" +
        static_cast<const char*>(errors->GetBufferPointer()) + "\nSource:\n" + mSource.c_str();
        errors->Release();
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
                "D3D9GpuProgram::loadFromSource");
            
    }

    loadFromMicrocode(microcode);

    SAFE_RELEASE(microcode);
    SAFE_RELEASE(errors);
}

"Fixed" Function

Code: Select all

void D3D9GpuProgram::loadFromSource(void)
{
    // Create the shader
    // Assemble source into microcode
    LPD3DXBUFFER microcode;
    LPD3DXBUFFER errors;
		
    // Fix issue with DEPTH output in fragment programs for D3D code generation in CG
    size_t idx = 0;
    while( (idx=mSource.find( "oDepth.z", idx )) != std::string::npos )
    {
        mSource.replace( idx, 8, "oDepth" );
    }
		
    HRESULT hr = D3DXAssembleShader(
        mSource.c_str(),
        static_cast<UINT>(mSource.length()),
        NULL,               // no #define support
        NULL,               // no #include support
        0,                  // standard compile options
        &microcode,
        &errors);

    if (FAILED(hr))
    {
        String message = "Cannot assemble D3D9 shader " + mName + " Errors:\n" +
        static_cast<const char*>(errors->GetBufferPointer()) + "\nSource:\n" + mSource.c_str();
        errors->Release();
        OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, message,
                "D3D9GpuProgram::loadFromSource");
            
    }

    loadFromMicrocode(microcode);

    SAFE_RELEASE(microcode);
    SAFE_RELEASE(errors);
}

Re: can't output DEPTH in a fragment program

Posted: Thu Sep 16, 2010 5:47 am
by Aldous11
FX Composer is quite a bit different from ARB_FRAGMENT_PROGRAM; the output bindings are not analogous. The fragment program you have looks fine, though you should make sure that there are no errors generated from reading it in (which it looks like you do.)

Here's why the fragment program you have is valid, from the spec:

Code:

Code: Select all

If a fragment program does not write a color value, what should
    be the final color of the fragment?

      RESOLVED: The final fragment color is undefined.  Note that it may
      be perfectly reasonable to have a program that computes depth 
      values but not colors.  Fragment colors are often irrelevant if
      color writes are disabled (via ColorMask).
I would actually mess around and try some different fragment programs to make sure your code works. For example, you could draw every pixel red and check your color buffer to make sure it's doing the right thing.