Sign in to follow this  
RuneLancer

SetTextureStageState / pixel shader question...

Recommended Posts

I am attempting to "tint" a texture (for use in rendering an ID3DXSprite) the following way: - If the diffuse component is 0x80, nothing unusual happens. - If the diffuse component is less than 0x80, the final color/alpha is darkened (with 0x00 shutting it off completely). - If the diffuse component is greater than 0x80, the final color/alpha is brightened (with 0xFF maxing it out). I found D3DTOP_ADDSIGNED, which works like I'd want (when using it with the texture and diffuse components) it but I can't get the full range of values (it's only give or take 0x80). Then I found D3DTOP_ADDSIGNED2X, which sounds like it'd do exactly what I want. Orange Rect: Diffuse A 0x20 RGB 0xC08060 Background: Diffuse A 0x80 RGB 0x808080 The left image is with ADDSIGNED2X, the right is ADDSIGNED. The right image is fine (though that's not quite what I want). The orange rect's alpha is Texture - (0x80 - Diffuse) = 0xFF - (0x80 - 0x20) = 0x9F. The left image, on the other hand, seems to do (Texture - (0x80 - Diffuse)) x 2 = (0xFF - (0x80 - 0x20)) x 2 = 0xFF. The same happens with the background image. I would want to have Texture - ((0x80 - Diffuse) x 2) = 0xFF - ((0x80 - 0x20) x 2) = 0x3F. So ADDSIGNED2X isn't quite what I want... Any suggestions as to how I could achieve this? I haven't had much luck with the other texture operators either... :/ [Edited by - RuneLancer on July 23, 2009 12:26:30 PM]

Share this post


Link to post
Share on other sites
Why not blend the textures in a pixel shader using a render target, then use the result from that for your sprite.

Or am I misunderstanding what you're trying to do?

Share this post


Link to post
Share on other sites
I'm highly unexperienced with pixel shaders. Currently I wouldn't be able to pull this off.

Basically I'm trying to get my destination color/alpha in a way similare to what D3DTOP_ADDSIGNED2X does ((Arg1 + (signed)Arg2) << 1). What I want, rather, is (Arg1 + ((signed)Arg2 << 1)). In other words, rather than shifting the result, I want Arg2 to be shifted before being added to Arg1. (And I understand enough about shaders to know I could probably do juuuust that with one...)

If it's impossible to achieve this just by messing with the texture stage, are there any good resources for learning to do this with a pixel shader? Tinting/fading is not a show-stopper but I don't want to spend a few weeks learning how pixel shaders work just for this (my vacation ends next monday ;) If I can learn how to do this in a day or two of reading and experimenting, that'd be perfect.)

Thanks!

Share this post


Link to post
Share on other sites
I've managed to get started with pixel shaders and everything seems to be working fine - seems I'll be using that as a solution after all. :) I'm unable to get my code to work, though.

ps_2_0

; Stage 0 sampler
dcl_2d s0

; Texture coordinates
dcl t0.xy

; Diffuse component
dcl v0.rgba

; Sample texture 0 at t0 into r1.
texld r1, t0, s0

; Add the diffuse component.
add r2, r1, v0

; Output the color.
mov oC0, r2


What I'm trying to do, for now, is take the diffuse color and just add it to the texture color (eventually I'll apply a different formula to this and I'll have the effect I'm shooting for). Doesn't seem to be working though. The shader compiles and loads up fine (the return value is D3D_OK) but my output seems unaffected. Wether I use the shader or not, it doesn't seem to change anything.


resAssemble = D3DXAssembleShader(shaderCode.c_str(), shaderCode.length(), NULL, NULL, 0, &pCode, &pErrorMsgs);
if(resAssemble == D3D_OK)
{
resCreate = m_d3dDevice->CreatePixelShader((DWORD*)pCode->GetBufferPointer(), &shader);
if(resCreate == D3D_OK)
{
resSet = m_d3dDevice->SetPixelShader(shader);
shader->Release();

DEBUG_LOG("Shader set!");
}
}


This is how I load it (shaderCode is a string containing the pixel shader). This occures during the "setup" phase of my code. Also, currently, I render everything through ID3DXSprite, though I doubt that matters...

Share this post


Link to post
Share on other sites
Are you forced to use D3D 8.0, or why do you torture yourself by using asm shaders? ;)

In D3D9 and later, you can use HLSL (which is a C-style language) to compile shaders. Also, you can use the Effect framework which handles the compiling as well as state changes for you.

Also, when you use custom states with the sprite class, you need to put your own state changes inside the begin/end pair. The begin method applies the internal states of the sprite to the device so if you set your shader prior to that, it won't be in effect inside the sprite begin/end block. Alternatively, you can use the D3DXSPRITE_DONOTMODIFY_RENDERSTATE flag (at least in D3D9) to tell the sprite class not to modify your current states, but then you need to manually set all the states that the sprite needs.

One more thing: you shouldn't release the shader immediately after creation.

Share this post


Link to post
Share on other sites
Ah! That did it! I should've known about setting the state after calling Begin - I had the same problem using SetTextureStageState. The shader is actively being used.

I suppose with a little bit of tweaking, I'll be able to achieve the effect I wanted now. Thanks for the help!

Edit: And wham! Just like that, I got it to work like I wanted. :) Can't say I expected to learn how to use pixel shaders today when I woke up this morning...

Share this post


Link to post
Share on other sites
Pixel shaders are actually easier than the fixed-function combiner, once you know the shader syntax :)

Learning shaders has the additional advantage: When you move to D3D11 or later at some point, you need to use shaders as the API doesn't support fixed-function T/L or combiner, beginning with D3D10.

Share this post


Link to post
Share on other sites
Well, all I can add is that I'm now Master of the Pixel. It obeys my every whim without question. :o

Honestly, after just a few hours of even knowing how to set up a pixel shader, I've already started getting very comfortable with it. And that's just with some of the more basic commands! I'm thinking of adding custom pixel shader support in my graphics engine in fact - I can really see potential future uses for this once I'll be more comfortable with it.

Thanks for showing me the Right Way. :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this