Jump to content
  • Advertisement
Sign in to follow this  
BattleMetalChris

Pixel shader only outputs alpha

This topic is 2761 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

This is my pixel shader, it takes a number of point lights and applies diffuse lighting to the mesh:

float4 PS( VS_OUTPUT input ) : SV_Target
{
float4 finalColour = (float4)0;
Light_Point p_light;

for (int i = 0; i < NumPointLights; i++)
{
p_light = PointLights;
float3 lightVec = (float3)input.Pos - p_light.position;

float4 ambientTerm;
float4 diffuseTerm;
float4 specularTerm;
float attenuation;
float distance = length(lightVec);

ambientTerm = Ambient;
float dotP = dot(normalize(-lightVec), input.Normal);
diffuseTerm = mul(dotP, p_light.colour); // diffuse light striking surface
diffuseTerm = mul(diffuseTerm, Diffuse);
specularTerm = (float4)0;

attenuation = 1 / (p_light.attenuation1 * pow(distance, 2) + p_light.attenuation2 * distance + p_light.attenuation3);

float4 tempColour = mul(diffuseTerm, attenuation);
finalColour = finalColour + tempColour;

}

return finalColour;

}


The problem is, no matter what finalColour is at the end, the colour of the pixel is a greyscale colour, the value of the output's alpha. So if finalColour is (0.3, 0.2, 0.1, 1.0) then the pixel ends up (1.0, 1.0, 1.0, 1.0). In desperation, I changed the end to:


finalColour = (0.0f, 0.0f, 0.0f, 1.0f);
return finalColour;


and the same thing happens. Here I get a white pixel despite the R,G and B values being 0.

Any ideas what's going on?

Share this post


Link to post
Share on other sites
Advertisement
If return float4(not white) yields white, then the problem doesn't lie in your shader, so you've posted the wrong code. Post the blending code etc. instead.

Share this post


Link to post
Share on other sites
Of course it should. Post some other code then, or better try using PIX to debug a pixel that gets the wrong color. If you can replace your shader with another that only does "return float4(1.0f, 0.0f, 0.0f, 1.0f)" and it's still white it obviously has nothing to do with the shader.

Share this post


Link to post
Share on other sites
I'm not really sure what else to post :unsure:

I've used PIX to debug the shader. The colour that gets written just seems to be different to the colour returned by the pixel shader - running through the shader in PIX's debugger shows everything in the shader working fine.


Here's how I set up the device:


void DX10Renderer::initialise()
{
// create swap chain

DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory( &scd, sizeof( scd ) );
scd.BufferCount = 1;

scd.BufferDesc.Width = m_width;
scd.BufferDesc.Height = m_height;
scd.BufferDesc.RefreshRate.Numerator = 60;
scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
//scd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
//scd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 1;

scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = m_hWnd;
scd.Windowed = true;
scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
scd.Flags = 0;

// create device

HRESULT result;
UINT createDeviceFlags = 0;

#if defined(DEBUG) || defined(_DEBUG)
createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif

result = D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, createDeviceFlags, D3D10_SDK_VERSION, &scd, &m_swapChain, &m_d3dDevice);
DXerror(result);

D3D10_RASTERIZER_DESC rasterizerState;
rasterizerState.CullMode = D3D10_CULL_BACK;
rasterizerState.FillMode = D3D10_FILL_SOLID;
rasterizerState.FrontCounterClockwise = true;
rasterizerState.DepthBias = false;
rasterizerState.DepthBiasClamp = 0;
rasterizerState.SlopeScaledDepthBias = 0;
rasterizerState.DepthClipEnable = true;
rasterizerState.ScissorEnable = false;
rasterizerState.MultisampleEnable = false;
rasterizerState.AntialiasedLineEnable = true;

ID3D10RasterizerState* pRS;
m_d3dDevice->CreateRasterizerState( &rasterizerState, &pRS);
m_d3dDevice->RSSetState(pRS);



// create render target

DXerror(m_swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&m_backBuffer)));
DXerror(m_d3dDevice->CreateRenderTargetView(m_backBuffer, 0, &m_renderTargetView));
m_backBuffer->Release(); // need this because the call to GetBuffer adds an extra COM reference

// create depth buffer

D3D10_TEXTURE2D_DESC descDepth;
descDepth.Width = m_width;
descDepth.Height = m_height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D32_FLOAT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
DXerror(m_d3dDevice->CreateTexture2D( &descDepth, NULL, &m_depthBuffer ));

// Create the depth stencil view
D3D10_DEPTH_STENCIL_VIEW_DESC descDSV;
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
DXerror(m_d3dDevice->CreateDepthStencilView( m_depthBuffer, &descDSV, &m_depthStencilView ));

m_d3dDevice->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView);

// set viewport

D3D10_VIEWPORT vp;
vp.Height = m_height;
vp.Width = m_width;
vp.MaxDepth = 1;
vp.MinDepth = 0;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
m_d3dDevice->RSSetViewports(1, &vp);

}


Here's my draw routine


void DX10Renderer::draw(float deltaTime)
{
using rendering::Renderable;
using rendering::ShaderBase;

std::vector<Renderable>& renderables = m_resourceManager->getRenderables();
std::vector<Light>& lights = m_resourceManager->getAllLights();

assignLights(renderables, lights);

const FLOAT clearColour[4] = {0.0f, 0.0f, 0.0f, 1.0f};
m_d3dDevice->ClearRenderTargetView(m_renderTargetView, clearColour);
m_d3dDevice->ClearDepthStencilView( m_depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 );

int shaderID = -1;
int materialID = -1;
int meshID = -1;
for (std::vector<Renderable>::iterator it = renderables.begin(); it != renderables.end(); ++it)
{
if (it->shaderID() != shaderID) shaderID = it->updatePerShader(&m_viewMatrix, &m_projMatrix);
if (it->materialID() != materialID) materialID = it->updatePerMaterial();
if (it->meshID() != meshID) meshID = it->updatePerMesh();

D3DXMATRIX rotate;
D3DXMatrixRotationY(&rotate, deltaTime);
rotate = it->getWorldMatrix() * rotate;
it->setWM(rotate);

ID3D10EffectTechnique* technique;
D3D10_TECHNIQUE_DESC techDesc;
technique = it->getTechnique();

technique->GetDesc( &techDesc );

UINT offset = 0;

for ( UINT p = 0; p < techDesc.Passes; p++)
{
technique->GetPassByIndex( p )->Apply(0);
m_d3dDevice->DrawIndexed( it->meshIndices(), 0, 0 );
}
}

m_swapChain->Present(0, 0);

}


And here's the entire .fx file it's using:


//--------------------------------------------------------------------------------------
// File: Tutorial02.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------

struct VS_OUTPUT
{
float4 PosH : SV_POSITION;
float4 Color : COLOR0;
float3 Normal : TEXCOORD0;
float3 Pos : TEXCOORD1;
};

struct Light_Point
{
float attenuation1;
float attenuation2;
float attenuation3;
float3 position;
float4 colour;
};

struct Light_Parallel
{
float3 direction;
float4 colour;
};

struct Light_Spot
{
float attenuation1;
float attenuation2;
float attenuation3;
float3 position;
float4 colour;
float3 direction;
float coneAngle1;
float coneAngle2;
};

cbuffer matrices
{
matrix WorldMatrix;
matrix ViewMatrix;
matrix ProjectionMatrix;
};

cbuffer surfaceProperties
{
float4 Diffuse;
float4 Ambient;
float4 Specular;
};

cbuffer lights
{
Light_Point PointLights[3];
Light_Parallel ParallelLights[3];
Light_Spot SpotLights[3];
int NumPointLights;
int NumParallelLights;
int NumSpotLights;

};


//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS( float4 Pos : POSITION , float4 Color : COLOR, float3 Normal : NORMAL)
{
matrix WorldView = mul(WorldMatrix, ViewMatrix); // so we don't have to calculate it twice
VS_OUTPUT output = (VS_OUTPUT)0;

output.Pos = (float3)Pos;

output.PosH = mul(Pos, WorldView);
output.PosH = mul(output.PosH, ProjectionMatrix);

output.Color = Color;

output.Normal = mul(Normal, WorldView);

return output;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( VS_OUTPUT input ) : SV_Target
{
float4 finalColour = (float4)0;
Light_Point p_light;

for (int i = 0; i < NumPointLights; i++)
{
p_light = PointLights;
float3 lightVec = (float3)input.Pos - p_light.position;

float4 ambientTerm;
float4 diffuseTerm;
float4 specularTerm;
float attenuation;
float distance = length(lightVec);

ambientTerm = Ambient;
float dotP = dot(normalize(-lightVec), input.Normal);
diffuseTerm = mul(dotP, p_light.colour); // diffuse light striking surface
diffuseTerm = mul(diffuseTerm, Diffuse);
specularTerm = (float4)0;

attenuation = 1 / (p_light.attenuation1 * pow(distance, 2) + p_light.attenuation2 * distance + p_light.attenuation3);

float4 tempColour = mul(diffuseTerm, attenuation);
finalColour = finalColour + tempColour;

}
finalColour = (0.0f, 0.0f, 0.0f, 1.0f);
return finalColour;

}


//--------------------------------------------------------------------------------------
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}


Apart from the code to create the vertex and index buffers for the mesh, they're the only parts that involve the directx device. Before I posted here I thought it might be a blending issue, but as I said, I don't set blending states anywhere at all in the code, so it should just use the default.

Share this post


Link to post
Share on other sites
Hmm, here's something interesting:

This is the asm code of the shader from PIX:


// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
//
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// ---------------- ----- ------ -------- -------- ------ ------
// SV_POSITION 0 xyzw 0 POS float
// COLOR 0 xyzw 1 NONE float
// TEXCOORD 0 xyz 2 NONE float
// TEXCOORD 1 xyz 3 NONE float
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// ---------------- ----- ------ -------- -------- ------ ------
// SV_Target 0 xyzw 0 NONE float xyzw
//
ps_4_0
dcl_output o0.xyzw
mov o0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
ret
// Approximately 2 instruction slots used



Note the colour being output here, it's not the same as in the source which, as I posted before, is currently


finalColour = (0.0f, 0.0f, 0.0f, 1.0f);
return finalColour;

Share this post


Link to post
Share on other sites
If you comment out the entire shader and just do return float4(1.0f, 0.0f, 0.0f, 1.0f) does it still get white?


I've used PIX to debug the shader. The colour that gets written just seems to be different to the colour returned by the pixel shader - running through the shader in PIX's debugger shows everything in the shader working fine.[/quote]

Did you right-click a pixel in the render view and select debug pixel so you get a list of every write to the pixel?
Is there anything other than Initial frambuffer value and a Draw call that outputs the color?
Is the color there also white, or just on the screen?

Share this post


Link to post
Share on other sites
Usually in PIX the SysValue for SV_Target is TARGET, not NONE as in your case..
Check all the warnings that you get from compiling your shader, and definitely try replacing the entire shader with return single color, and not leaving the whole thing in there. Perhaps compilation fails.

Share this post


Link to post
Share on other sites
That comma thing helped, thanks, 'return float4(1.0f, 0.0f, 0.0f,1.0f)' displays red pixels, so that's working at least.

I'm not sure where in my original shader code that's happening though.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!