Shader always returns white

Started by
11 comments, last by Buckeye 9 years, 4 months ago

Hi, I'm trying to do some simple D3D9 rendering.

Problem is, with the shader below, the output on screen is always white even though I'm clearly telling it to return blue


float4x4 gWorld : WORLD;
float4x4 viewProj : VIEWPROJECTION;
 
 // Vertex Shader
float4 vs( float3 pos : POSITION ) : POSITION
{
    float4 output;
 
    output = mul( float4( pos.xyz,1 ), gWorld );
    output = mul( float4( output.xyz,1 ),viewProj );
 
    return output;
}
 
// Pixel Shader
float4 ps( float4 pos : POSITION ) : COLOR
{
    // Returning blue, but getting white?
    return float4( 0,0,1,1 );
}

this problem doesn't occur if I simply add another semantic to the vertex shader input, then it returns whatever color I want.

The object is drawn correctly ( cube in this case ) just the wrong color unless I pass the vertex shader more than just the position.

I'll post c++ code if it's needed.

EDIT:

I actually found it it will only apply the color the way it should ONLY if I pass the color through vertices. Continuing to debug...

EDIT AGAIN:

It seems that the pixel shader isn't even getting called. Any color I return from the vertex shader will be the color used assuming that I have the COLOR semantic on it, and if no color is returned the color is white.


// This is how I load the shader, not sure where to go from here.  But I'll google some more
 
D3D9* d3d = CEngine::getD3D9();
D3DXCreateEffectFromFileA( d3d->getDevice(),"Assets/Shaders/SimpleShader.fx",0,0,0,0,&shader,0 );
Advertisement

Effect ? Is this the whole shader source ? No technique/pass ? How do you apply the pass or shaders? FFP pixel shader active instead of yours ? D3D debug log good ?

Anyway debug one such white pixel with PIX, then you can find out exactly what's happening (compile shader with debug enabled).

And yeah, showing more code would help greatly, please.

// This is how I load the shader,


That doesn't "load" the shader. As the name of the function implies, it creates an instance of ID3DXEffect.

As unbird mentions, (much) more information is needed. In particular, are you trying to compile, set and use vertex and pixel shaders themselves (IDirect3dVertexShader9, IDirect3dPixelShader9), or are you trying to compile and use an instance of ID3DXEffect to render something?

EDIT: As it appears you have a HLSL vertex/pixel shader file you're trying to use, I'd suggest (assuming you have the DX SDK June 2010 installed) you work through some of the example solutions in that SDK (located in the (DXSDK)/Samples/C++/Direct3D folder). Several of them demonstrate how to create an effect from a file, set techniques and parameters (such as the world/view/projection matrices), and render objects within an effect Begin/BeginPass-EndPass/End loop.

Also, N.B. D3DX functions return an HRESULT value, which indicates the success or failure of the function call. Check those return values! The easiest way is to use the SUCCEEDED(hr) and FAILED(hr) macros. Handle errors gracefully - don't assume your code will execute correctly.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This shader code looks strange to me in parts, if this is the full code then there's something missing. You need at least one technique and one pass.

Take look at my shader here for comparison. It has 2 techniques with 1 pass each. One runs lighting calculation while the other doesn't.


float4x4 WorldViewProjection;
float4x4 WorldInverseTranspose;
 
float4 AmbientColor = float4(1, 1, 1, 1);
float AmbientIntensity = 0.2;
 
float3 DiffuseLightDirection = float3(1, 1, 1);
float4 DiffuseColor = float4(1, 1, 1, 1);
float DiffuseIntensity = 0.9;
 
float Shininess = 50;
float4 SpecularColor = float4(1, 1, 1, 1);
float SpecularIntensity = 0.33;
float3 ViewVector = float3(1, 0, 0);
 
Texture2D Texture;

SamplerState textureSampler;
 
struct VertexShaderInput
{
    float4 Position : SV_POSITION0;
    float4 Normal : NORMAL0;
    float2 TextureCoordinate : TEXCOORD0;
};
 
struct VertexShaderOutput
{
    float4 Position : SV_POSITION0;
    float4 Color : COLOR0;
    float3 Normal : TEXCOORD0;
    float2 TextureCoordinate : TEXCOORD1;
};
 
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;
 
	output.Position = mul(input.Position, WorldViewProjection);
 
    float4 normal = normalize(input.Normal);
    float lightIntensity = dot(normal, DiffuseLightDirection);
    output.Color = saturate(DiffuseColor * DiffuseIntensity * lightIntensity);
 
    output.Normal = normal;
 
    output.TextureCoordinate = input.TextureCoordinate;
    return output;
}
 
VertexShaderOutput VertexShaderStarsphere(VertexShaderInput input)
{
	VertexShaderOutput output;

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

	output.TextureCoordinate = input.TextureCoordinate;
	return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : SV_TARGET0
{
    float3 light = normalize(DiffuseLightDirection);
    float3 normal = normalize(input.Normal);
    float3 r = normalize(2 * dot(light, normal) * normal - light);
    float3 v = normalize(mul(normalize(ViewVector), WorldViewProjection));
    float dotProduct = dot(r, v);
 
    float4 specular = SpecularIntensity * SpecularColor * max(pow(abs(dotProduct), Shininess), 0) * length(input.Color);
 
		float4 textureColor = Texture.Sample(textureSampler, input.TextureCoordinate);
    textureColor.a = 1;
 
    return saturate(textureColor * (input.Color) + AmbientColor * AmbientIntensity + specular);
}

float4 PixelShaderStarsphere(VertexShaderOutput input) : SV_TARGET0
{
	float4 textureColor = Texture.Sample(textureSampler, input.TextureCoordinate);
	textureColor.a = 1;

	return textureColor;
}
 
technique Textured
{
    pass Pass1
    {
		AlphaBlendEnable = TRUE;
        DestBlend = INVSRCALPHA;
        SrcBlend = SRCALPHA;
        VertexShader = compile vs_4_0 VertexShaderFunction();
        PixelShader = compile ps_4_0 PixelShaderFunction();
    }
}

technique Starsphere
{
	pass Pass1
	{
		VertexShader = compile vs_4_0 VertexShaderStarsphere();
		PixelShader = compile ps_4_0 PixelShaderStarsphere();
	}
};

The technique is fine, I didn't post it as it's quite unnecessary. It uses version 3.0.

The HRESULT returns SUCCESS, already been there done that before I made the post.

Here is where I actually render the object


// The technique
technique Tech
{
    pass pass1
    {
        vertexShader = compile vs_3_0 vs();
        pixelShader  = compile ps_3_0 ps();
 
        CullMode = CCW;
        FillMode = Solid;
    }
}
 
// Rendering
IDirect3DDevice9* device = CEngine::getD3D9()->getDevice();  
 
unsigned passes = 0;  
 
pShader->Begin( &passes,0 );  
 
pShader->SetMatrix( "gWorld",&worldMatrix);   // Pass the world matrix
pShader->SetMatrix( "viewProj",&(cam * proj) ); // Pass the View and Projection  
pShader->CommitChanges();  
 
device->SetVertexDeclaration( _pVertDecl );
device->SetStreamSource( 0,_pVertBuff,0,_nVertStride );  
 
for( unsigned i = 0;i < passes;++i )
{    
    pShader->BeginPass( i );      
 
    device->DrawPrimitive( D3DPT_TRIANGLELIST,0,_nNumVerts/3 );
 
    pShader->EndPass();
}  
 
pShader->End();

Initializing


D3DVERTEXELEMENT9 decl[] =
{
    { 0,0,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION,0 },
    { 0,12,D3DDECLTYPE_FLOAT3,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_NORMAL,0 },
    D3DDECL_END()
};
 

unsigned vertSize = nNumVerts * nVertexSize;
 
device->CreateVertexBuffer( vertSize,0,0,D3DPOOL_DEFAULT,&_pVertBuff,0 );
device->CreateVertexDeclaration( decl,&_pVertDecl );
 
void* vram = nullptr;
 
_pVertBuff->Lock( 0,0,&vram,0 );
memcpy( vram,verts,vertSize );
_pVertBuff->Unlock();
 
 
// The actual verts in case you want to see that
 
// CUBE

float size = fWidth/2;
 
VERTEX_POSNORM verts[] =
{
    { Vector3( -size, size,-size ), Vector3(  0, 0,-1 ) }, // 0 Front Top Left
    { Vector3(  size, size,-size ), Vector3(  0, 0,-1 ) }, // 1 Front Top Right
    { Vector3(  size,-size,-size ), Vector3(  0, 0,-1 ) }, // 2 Front Bottom Right
    { Vector3(  size,-size,-size ), Vector3(  0, 0,-1 ) }, // 2 Front Bottom Right
    { Vector3( -size,-size,-size ), Vector3(  0, 0,-1 ) }, // 3 Front Bottom Left
    { Vector3( -size, size,-size ), Vector3(  0, 0,-1 ) }, // 0 Front Top Left
 
    { Vector3( -size, size, size ), Vector3(  0, 0, 1 ) }, // 4 Back Top Left
    { Vector3( -size,-size, size ), Vector3(  0, 0, 1 ) }, // 7 Back Bottom Left
    { Vector3(  size,-size, size ), Vector3(  0, 0, 1 ) }, // 6 Back Bottom Right
    { Vector3(  size,-size, size ), Vector3(  0, 0, 1 ) }, // 6 Back Bottom Right
    { Vector3(  size, size, size ), Vector3(  0, 0, 1 ) }, // 5 Back Top Right
    { Vector3( -size, size, size ), Vector3(  0, 0, 1 ) }, // 4 Back Top Left
 
    { Vector3( -size, size, size ), Vector3( -1, 0, 0 ) }, // 4 Back Top Left
    { Vector3( -size, size,-size ), Vector3( -1, 0, 0 ) }, // 0 Front Top Left
    { Vector3( -size,-size,-size ), Vector3( -1, 0, 0 ) }, // 3 Front Bottom Left
    { Vector3( -size,-size,-size ), Vector3( -1, 0, 0 ) }, // 3 Front Bottom Left
    { Vector3( -size,-size, size ), Vector3( -1, 0, 0 ) }, // 7 Back Bottom Left
    { Vector3( -size, size, size ), Vector3( -1, 0, 0 ) }, // 4 Back Top Left
 
    { Vector3(  size, size,-size ), Vector3(  1, 0, 0 ) }, // 1 Front Top Right
    { Vector3(  size, size, size ), Vector3(  1, 0, 0 ) }, // 5 Back Top Right
    { Vector3(  size,-size, size ), Vector3(  1, 0, 0 ) }, // 6 Back Bottom Right
    { Vector3(  size,-size, size ), Vector3(  1, 0, 0 ) }, // 6 Back Bottom Right
    { Vector3(  size,-size,-size ), Vector3(  1, 0, 0 ) }, // 2 Front Bottom Right
    { Vector3(  size, size,-size ), Vector3(  1, 0, 0 ) }, // 1 Front Top Right
 
    { Vector3( -size, size,-size ), Vector3(  0, 1, 0 ) }, // 0 Front Top Left
    { Vector3( -size, size, size ), Vector3(  0, 1, 0 ) }, // 4 Back Top Left
    { Vector3(  size, size, size ), Vector3(  0, 1, 0 ) }, // 5 Back Top Right
    { Vector3(  size, size, size ), Vector3(  0, 1, 0 ) }, // 5 Back Top Right
    { Vector3(  size, size,-size ), Vector3(  0, 1, 0 ) }, // 1 Front Top Right
    { Vector3( -size, size,-size ), Vector3(  0, 1, 0 ) }, // 0 Front Top Left
 
    { Vector3( -size,-size,-size ), Vector3(  0,-1, 0 ) }, // 3 Front Bottom Left
    { Vector3(  size,-size,-size ), Vector3(  0,-1, 0 ) }, // 2 Front Bottom Right
    { Vector3(  size,-size, size ), Vector3(  0,-1, 0 ) }, // 6 Back Bottom Right
    { Vector3(  size,-size, size ), Vector3(  0,-1, 0 ) }, // 6 Back Bottom Right
    { Vector3( -size,-size, size ), Vector3(  0,-1, 0 ) }, // 7 Back Bottom Left
    { Vector3( -size,-size,-size ), Vector3(  0,-1, 0 ) }, // 3 Front Bottom Left
};
 


Hmm, what happens if you try comment out CullMode and FillMode in your technique so it runs the vertex and pixel shaders and nothing else, like my "Starsphere" technique does?

That didn't change anything, it still returns only white. I've updated the shader since I first posted it so I'll just re-post it here, but I highly doubt the shader is the problem.


float4x4 gWorld : WORLD;
float4x4 viewProj : VIEWPROJECTION;
 
float4 gColor;
float3 gLightPos = float3( 6,4,-5 );
 
struct VS_IN
{
    float4 pos : POSITION;
    float3 norm : NORMAL;
};
struct VS_OUT
{
    float4 pos : POSITION;
    //float4 color : COLOR;
};
 
VS_OUT vs( VS_IN input )
{
    // Positions
    float3 world = mul( float4( input.pos.xyz,1 ), gWorld ).xyz;
    float4 pos = mul( float4( world,1 ),viewProj );
 
    // Normals
    float3 norm = normalize( mul( float4( input.norm,0 ), gWorld ).xyz );
    float3 ldir = normalize( gLightPos - world );
 
    // Amount of light hitting the vertex
    float scale = saturate( dot( ldir,norm ) );
 
    // Save
    VS_OUT output;
    output.pos = pos;
    //output.color = float4( gColor.rgb * scale,gColor.a  );
 
    return output;
}
 
float4 ps( VS_OUT input ) : COLOR
{ 
/*
    float3 ldir = normalize( gLightPos - input.world );
    float3 norm = normalize( input.norm );
 
    float scale = saturate( dot( ldir,norm ) );
 
    input.color.xyz *= scale;
    return float4( input.color.xyz,intput.a );
*/
    return float4( 0,1,0,1 );
}
 
technique Tech
{
    pass pass1
    {
        vertexShader = compile vs_3_0 vs();
        pixelShader  = compile ps_3_0 ps();
 
        CullMode = CCW;
        //FillMode = Solid;
    }
}

Here is the result

shader_example.png

EDIT:


static volatile const unsigned long long var[5];
 
// ^^ WIN!!

Got bored lol


FFP pixel shader active instead of yours ? ... debug one such white pixel with PIX, then you can find out exactly what's happening (compile shader with debug enabled).

unbird posted an indication of what may be your problem a week ago, which you apparently decided to ignore. I.e., "all white" is an indication that the object is probably being rendered with the FFP pixel shader, not your shader. Did you try his suggestion of using PIX to see if your effect is, in fact, what's being used to render your object?

Because you indicate your technique is "fine," and you don't post code you feel is "unnecessary," there's no way to tell, but it still appears you're not setting the technique properly, or, as may be the case, at all. You may want to take a look at the docs for ID3DXEffect::SetTechnique, or, as previously suggested, take a look at some of the examples in the DX SDK for comparison, to see if you are, in fact, setting the technique properly.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Please don't be condescending, I'm trying to get help. I never post all of my code at once, I try to keep the problem as simple as I possibly can so I can get as much help as possible. Nobody likes to look at a HUGE wall of code to help with what might simply be a typo when rendering or making the shader =).

PIX hasn't been working well for me, whether I have the Direct X debugging tools turned on or not. It becomes an annoyance to mess with and get it to work correctly, which is why I've gotten lazy with using PIX lately. I'm trying again though, will reply with my result.


Please don't be condescending,

Acknowledged.


I'm trying to get help ... as much help as possible

Then a suggestion: acknowledge responses, perhaps with something other than "been there done that" or something is "fine," which seems rather condescending.

Having exchanged shots across the bow, did you set the technique properly?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement