Hey,
I'm currently trying to implement pixel-exact 2d sprite rendering. But now I'm stuck with a strange bug. I will just post first all the information that I think is needed to find the bug and then explain whats wrong (if it's not obvious).
First some screenshots and a PIXrun-file with which you can watch the whole frame:
http://rimproject.dyndns.org/das.png
http://rimproject.dyndns.org/sprite_screenshot2.png
http://rimproject.dyndns.org/sprite_run.pixrun
Source to render a sprite:
float_t zn = 0.1f;
float_t zf = 10000.0f;
Matrix4x4f mat;
mat.ToIdentity();
Rectf r(0, 800, 0, 600);
mat._11 = 2 / (r.right - r.left);//2 / 799.0f;
mat._14 = (r.left + r.right) / (r.left - r.right);//-1.0f - 1.0f/799.0f;
mat._22 = 2 / (r.top - r.bottom);//-2 / 599.0f;
mat._24 = (r.top + r.bottom) / (r.bottom - r.top);//1.0f + 1.0f/599.0f;
mat._33 = 1 / (zf - zn);
mat._34 = zn / (zn - zf);
mat._44 = 1.0f;
vshader_constants_->SetFloatMatrix(constant_mat_orthogonal_, mat);
Vertex* v = vstream_->Lock<Vertex>(0, 0, LockDiscard);
Rectf texrect1 = texrect;
if (texrect1.right == 0) texrect1.right = texture->GetWidth();
if (texrect1.bottom == 0) texrect1.bottom = texture->GetHeight();
v[0].x = (float_t)position.left - 0.5f;
v[0].y = (float_t)position.top - 0.5f;
v[0].z = 0.5f;
v[0].rhw = 1.0f;
v[0].tu = texrect1.left / (float_t)texture->GetWidth();
v[0].tv = texrect1.top / (float_t)texture->GetHeight();
v[1].x = (float_t)position.right - 0.5f;
v[1].y = (float_t)position.top - 0.5f;
v[1].z = 0.5f;
v[1].rhw = 1.0f;
v[1].tu = texrect1.right / (float_t)texture->GetWidth();
v[1].tv = texrect1.top / (float_t)texture->GetHeight();
v[2].x = (float_t)position.left - 0.5f;
v[2].y = (float_t)position.bottom - 0.5f;
v[2].z = 0.5f;
v[2].rhw = 1.0f;
v[2].tu = texrect1.left / (float_t)texture->GetWidth();
v[2].tv = texrect1.bottom / (float_t)texture->GetHeight();
v[3].x = (float_t)position.right - 0.5f;
v[3].y = (float_t)position.bottom - 0.5f;
v[3].z = 0.5f;
v[3].rhw = 1.0f;
v[3].tu = texrect1.right / (float_t)texture->GetWidth();
v[3].tv = texrect1.bottom / (float_t)texture->GetHeight();
vstream_->Unlock();
graphicsdriver_->GetBlendState()->Enable();
graphicsdriver_->GetBlendState()->SetColorBlendOp(AlphablendOpAdd);
graphicsdriver_->GetBlendState()->SetColorSrcBlend(AlphablendSrcAlpha);
graphicsdriver_->GetBlendState()->SetColorDestBlend(AlphablendInvSrcAlpha);
pshader_constants_->SetFloatVector(constant_color_, Vector4f(modulation_color.r, modulation_color.g, modulation_color.b, modulation_color.a));
graphicsdriver_->GetVertexProcessingState()->SetVertexDeclaration(vertex_declaration_);
graphicsdriver_->GetVertexProcessingState()->SetVertexStream(0, vstream_, sizeof(Vertex));
graphicsdriver_->GetVertexProcessingState()->SetVertexShader(vshader_);
graphicsdriver_->GetVertexProcessingState()->SetConstantBuffer(vshader_constants_);
graphicsdriver_->GetPixelProcessingState()->SetPixelShader(pshader_);
graphicsdriver_->GetPixelProcessingState()->SetConstantBuffer(pshader_constants_);
graphicsdriver_->GetSamplerState(0)->SetTexture(texture);
graphicsdriver_->GetSamplerState(0)->SetMinFilter(TexFilterPoint);
graphicsdriver_->GetSamplerState(0)->SetMagFilter(TexFilterPoint);
graphicsdriver_->DrawPrimitive(PrimitiveTriangleStrip, 0, 2);
graphicsdriver_->GetBlendState()->Disable();
Source which calls the sprite-rendering:
sprite_->Render(test_texture_b_, Rect(0, 799, 0, 599), Rectf(0, 0, 0, 0), Colorf::WHITE());
// top left
sprite_->Render(test_texture_v_, Rect(5, 14, 5, 14), Rectf(0, 0, 0, 0), Colorf::WHITE());
sprite_->Render(test_texture_h_, Rect(5, 14, 15, 24), Rectf(0, 0, 0, 0), Colorf::WHITE());
// bottom left
sprite_->Render(test_texture_v_, Rect(5, 14, 575, 584), Rectf(0, 0, 0, 0), Colorf::WHITE());
sprite_->Render(test_texture_h_, Rect(5, 14, 585, 594), Rectf(0, 0, 0, 0), Colorf::WHITE());
// top right
sprite_->Render(test_texture_v_, Rect(785, 794, 5, 14), Rectf(0, 0, 0, 0), Colorf::WHITE());
sprite_->Render(test_texture_h_, Rect(785, 794, 15, 24), Rectf(0, 0, 0, 0), Colorf::WHITE());
// bottom right
sprite_->Render(test_texture_v_, Rect(785, 794, 575, 584), Rectf(0, 0, 0, 0), Colorf::WHITE());
sprite_->Render(test_texture_h_, Rect(785, 794, 585, 594), Rectf(0, 0, 0, 0), Colorf::WHITE());
The HLSL-Source:
sampler texSampler;
void vs_main(
float4 inPosition : POSITION,
float2 inTexCoord : TEXCOORD0,
out float4 outPosition : POSITION,
out float2 outTexCoord : TEXCOORD0,
uniform float4x4 orthogonalProjection
)
{
outPosition = mul(orthogonalProjection, inPosition);
outTexCoord = inTexCoord;
}
void ps_main(
float2 inTexCoord : TEXCOORD0,
out float4 outColor : COLOR,
uniform float4 modulationColor : float4
)
{
outColor =
tex2D(texSampler, inTexCoord) *
modulationColor
;
}
The problem is that it doesn't render the images pixel-exact. As you may see in 'das.png' the colors are wrong. when you look at 'sprite_screenshot2.png' you can see that the row in the middle of the picture is white instead of black (every second row/column is black on the texture).
I'd be very grateful if anyone could point me into a direction to solve the problem!
Thanks,
Chris