# Rendering Grayscale, RenderState/TextureState

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

## Recommended Posts

I'm trying to render a sprite (or anything really) to be a Grayscale when i want it to be, I REALLY dont want to edit the texture to make it gray, so I wondered If there was any RenderState / Texture State i can apply to make this work? Thank you very much :)

##### Share on other sites
If you're using pixel shaders, it's easy - you just average the red, green, and blue channels, and then set all 3 channels to the same (averaged) value. You could make things more complicated by using the proper luminance values (I don't rmember them, but green is multiplied by 0.3 I think. Red and blue are multipled by different values).

Without pixel shaders, I can't think of any way to do this without modifying the texture, but I'm fairly sure there must be a way. I'd be interested to know too...

##### Share on other sites
Hi there konnichiwa,
How are you doing buddy?

The Problem
Setting renderstate to make a texture grayscale

The Solution
I would say the logical and easiest step is just to modify the texture. Unforunately I don't know of any render states that you might be able to set to get this effect but it surely is possible in shaders and if you want more information on that you can check the Post Process sample in the SDK directory,
Source: (SDK root)\Samples\C++\Direct3D\PostProcess

You could probably also fake a kind of grayscale by rendering to texture and modifying the values of each of the vertices in the texture after rendering and then you have your "greyscale" texture.

I hope this helps buddy.
Take care.

##### Share on other sites
If you're using pixel shaders, you can convert an RGB color to grayscale by the following:

float fLuminance = 0.299f*color.r + 0.587f*color.g + 0.114f*color.b;
return float4( fLuminance, fLuminance, fLuminance, 1.0f );

Use this luminance value as the RGB colors output from the pixel shader and you get proper grayscale images.

As far as I know, there is no way to do this without using shaders.

neneboricua

##### Share on other sites
Quote:
 Original post by neneboricua19If you're using pixel shaders, you can convert an RGB color to grayscale by the following:float fLuminance = 0.299f*color.r + 0.587f*color.g + 0.114f*color.b;return float4( fLuminance, fLuminance, fLuminance, 1.0f );Use this luminance value as the RGB colors output from the pixel shader and you get proper grayscale images.As far as I know, there is no way to do this without using shaders.neneboricua

Couldn't you just use SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3) and set ARG1 to the texture and ARG2 to TFACTOR. Then before you render call SetRenderState( D3DRS_TEXTUREFACTOR, dwTFactor) where dwTFactor is the vector (0.299, 0.587, 0.114) packed into a DWORD. I havn't tried it but it may work.

-SirKnight

##### Share on other sites
I tried out the effect described by SirKnight and it works perfectly, but you have to use inverted weights for the TFactor (don't ask me why :). I initially used the following C# code, following the instructions:

[source lang=C#]device.TextureState[0].ColorOperation = TextureOperation.DotProduct3;device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;device.TextureState[0].ColorArgument2 = TextureArgument.TFactor;device.RenderState.TextureFactor = ( 0xFF << 24 ) | (76 << 16) | (150 << 8) | 29;

This however produced an inverted, but grayscale image in my effect demo. It may be a problem with the renderstates already set by my effects, so I thought I'd post my original result as well. Anyway, here it is:

To fix this inverted color, I simply inverted the TFactor. This gave the correct effect and it also miraculously solved the problem with the articfacts in the shadow volume & billboards in the first picture. So, the code:

[source lang=c#]device.TextureState[0].ColorOperation = TextureOperation.DotProduct3;device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;device.TextureState[0].ColorArgument2 = TextureArgument.TFactor;device.RenderState.TextureFactor = ( 0xFF << 24 ) | ( (255-76) << 16) | ( (255-150) << 8) |(255- 29);

and the final effect:

##### Share on other sites
Quote:
 Original post by SirKnightCouldn't you just use SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3) and set ARG1 to the texture and ARG2 to TFACTOR. Then before you render call SetRenderState( D3DRS_TEXTUREFACTOR, dwTFactor) where dwTFactor is the vector (0.299, 0.587, 0.114) packed into a DWORD. I havn't tried it but it may work.-SirKnight
Ooh, that's a sexy way to do it. I'd never think of that. [smile] Ratings++

##### Share on other sites
Quote:
 Original post by SirKnightCouldn't you just use SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DOTPRODUCT3) and set ARG1 to the texture and ARG2 to TFACTOR. Then before you render call SetRenderState( D3DRS_TEXTUREFACTOR, dwTFactor) where dwTFactor is the vector (0.299, 0.587, 0.114) packed into a DWORD. I havn't tried it but it may work.

Well done, SirKnight. I had forgotten about the TFACTOR thing. Been doing nothing but shaders for the past couple of years so I tend to forget parts of the fixed function pipeline.

neneboricua

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 14
• 46
• 22
• 27
• ### Forum Statistics

• Total Topics
634047
• Total Posts
3015230
×