私は、人間の視覚系の色のコントラスト感度のしきい値をテストするためにISlimDXアプリケーションを作成しています。被写体には、背景とのコントラストが低い大きな文字が表示され、文字を識別するように求められます。ただし、チャネルあたり8ビットの単純な色深度で利用できるよりも多くの色を表示する機能が必要です。(つまり、rgb値は0〜255です)。これを実現するための計画は、HLSLピクセルシェーダーとして実装された単純な「ディザリング」アルゴリズムを使用することです。基本的に、slimDXに、(140.25、140.25、140.25)のrgb値に対応するColor4(0.55f、0.55f、0.55f)の色でテキストを表面にレンダリングするように要求する場合、各ピクセルの各カラーチャネルに25%の確率で141に設定され、75%の確率で140に設定されます。
ただし、fxcでコンパイルしようとすると、プロトタイプシェーダーコードでエラーが発生します。コンパイル時に不正な文字コードが表示されますが、その理由がわかりません。また、HLSLの第一人者である場合は、私のコードを調べて、印象に残っているコメントを入力してください。この質問への回答からHLSLランダム関数を取得したことに注意してください。
ピクセルシェーダー内で乱数を生成できますか?
以下は私のシェーダーコードです。私の最初のHLSLコードとして多くの間違いがあった場合は、ご容赦ください。
float4 DitherByChance(float2 coords : TEXCOORD0) : COLOR0
{
float4 newColor; // The pixel color to return
float4 oldColor = tex2D(s0, coords);
// Note I know that as the code stands now rCutOff = gCutOff = bCutOff I will sort a fix for this out later
float rCutOff = random(coords); // A random float that determines if the red channel will be rounded up or down
float gCutOff = random(coords); // A random float that determines if the green channel will be rounded up or down
float bCutOff = random(coords); // A random float that determines if the blue channel will be rounded up or down
float rPercentChance = frac(oldColor.r * 255); //Chance to round red channel up
float gPercentChance = frac(oldColor.g * 255); //Chance to round green channel up
float bPercentChance = frac(oldColor.b * 255); //Chance to round blue channel up
//In the code below (1/255) is the floating point represntaion of an incress of one on the 0-255 RGB scale
if (rCutOff <= rPercentChance) newColor.r = oldColor.r + ((1 - rPercentChance) / 255); //Bump up one r value
else newColor.r = oldColor.r - rPercentChance * (1 / 255); //Bump down to ensure r is not rounded up
if (gCutOff <= gPercentChance) newColor.g = oldColor.g + ((1 - gPercentChance) / 255); //Bump up one g value
else newColor.b = oldColor.b - bPercentChance * (1 / 255); //Bump down to ensure g is not rounded up
if (bCutOff <= bPercentChance) newColor.b = oldColor.b + ((1 - bPercentChance) / 255); //Bump up one b value
else newColor.b = oldColor.b - bPercentChance * (1 / 255); //Bump down to ensure b is not rounded up
return newColor;
}
// Input: It uses texture coords as the random number seed.
// Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive.
// Author: Michael Pohoreski
// Copyright: Copyleft 2012 :-)
float random( vec2 p )
{
// We need irrationals for pseudo randomness.
// Most (all?) known transcendental numbers will (generally) work.
const vec2 r = vec2(
23.1406926327792690, // e^pi (Gelfond's constant)
2.6651441426902251); // 2^sqrt(2) (Gelfond–Schneider constant)
return fract( cos( mod( 123456789., 1e-7 + 256. * dot(p,r) ) ) );
}
編集: 以下の答えの助けを借りて、私は解決策に少し近づきましたが、まだいくつかの問題があります。私が借りたランダム関数はHLSLではなくGLSLで書かれているというcatflierのコメントを受け取りました。vec2をfloat2に変更し、ランダム関数を一番上に配置する必要がありました。それに加えて、GLSL mod()!= HLSL fmodであるため、mod関数も作成する必要がありました。また、GLSL fract()はHLSL frac()に変更されました。また、テキストファイルがUTF-8でエンコードされているという問題もありました。これにより、fxcでいくつかの問題が発生すると思います。ANSIに再エンコードした後、いくつかのより良いエラーメッセージを受け取ることができました。しかし、私はまだいくつかの問題を抱えています。
fxc /Zi /E DitherByChance DitherByChance.fx
DX9をターゲットにしているので、と同様にコンパイルしようとしましfxc /Zi /E DitherByChance /LD DitherByChance.fx
たが、どちらの場合も次のエラーが発生します。
undeclared indentifier 's0' error
この行からfloat4 oldColor = tex2D(s0, coords);
このs0引数が正確に何であるかはわかりませんが、別のシェーダーの例で見ただけです。誰かがグローバルsampler2D変数を宣言し、s0の代わりにそれを使用した別の例を見たので、これを試しました:
sampler2D Tex0;
...
....
.....
float4 oldColor = tex2D(Tex0, coords);
ただし、実行するfxc /Zi /E DitherByChance /LD DitherByChance.fx
と、次のエラーが発生します。
vs_2_0 target does not support texture lookup
何か案は?