我正在编写SlimDX应用程序来测试人类视觉系统的色彩对比敏感度阈值。主题会显示一个与背景形成低对比度的大字母,并要求识别该字母。但是我需要能够显示更多颜色,然后可以使用简单的每通道8位颜色深度。 (即rgb值为0-255)。我计划的方法是通过一个简单的“抖动”算法实现为HLSL像素着色器。基本上,如果请求slimDX将文本渲染到Color4(0.55f,0.55f,0.55f)颜色的表面,该颜色对应于rgb值(140.25,140.25,140.25),我希望每个像素的每个颜色通道都有设置为141的可能性为25%,设置为140的可能性为75%。这应该(在许多像素的限制范围内)导致字母显示为灰色阴影的1/4。介于140和141之间 然而,当我尝试使用fxc编译时,我在原型着色器代码中遇到错误。我编译时得到一个非法的字符代码,我不知道为什么。此外,如果您是HLSL大师,请查看我的代码,并发表任何打击你的评论。注意我从这个问题的答案得到了HLSL随机函数。 Can I generate a random number inside a pixel shader?
下面是我的着色器代码。如果我的第一个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) ) ) );
}
修改 在下面的答案的帮助下,我已经接近一个解决方案,但仍然有一些问题。我收到了catflier的评论,我借用的随机函数是用GLSL而不是HLSL编写的。我不得不将vec2更改为float2并将随机函数放在顶部。除此之外,我还必须编写一个mod函数,因为GLSL mod()!= HLSL fmod。并且GLSL fract()更改为HLSL frac()。我也有一个问题,我的文本文件是用UTF-8编码的,我猜这会引起fxc的一些问题。重新编码到ANSI后,我能够获得更好的错误消息。不过我还有一些问题。
我尝试使用fxc /Zi /E DitherByChance DitherByChance.fx
以及fxc /Zi /E DitherByChance /LD DitherByChance.fx
进行编译,因为我的目标是DX9,但我两次出现以下错误:
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
有什么想法吗?
答案 0 :(得分:1)
首先你需要在随机函数中用float2替换vec2,因为vec2是glsl语法。
然后你的随机函数应该放在你的PixelShader(c风格)之上。
您的着色器现在应该编译,如果没有,请发布错误消息。
从最新位编辑:
sampler2D Tex0;
是一个采样器单元,你需要将它绑定到纹理,因为采样器将告诉如何过滤它(线性/点),并解决它(包裹/钳位......)
http://msdn.microsoft.com/en-us/library/windows/desktop/bb509644(v=vs.85).aspx
由于你编译了一个像素着色器,你需要使用fxc / T ps_3_0,因为你编译为像素着色器,而不是顶点着色器。