【问题标题】:Error when writing a very simple HLSL pixel shader编写非常简单的 HLSL 像素着色器时出错
【发布时间】:2012-10-04 22:08:05
【问题描述】:

我正在编写我的 SlimDX 应用程序来测试人类视觉系统的颜色对比敏感度阈值。主题呈现一个与背景对比度低的大字母,并要求识别该字母。但是,我需要能够显示更多颜色,然后每个通道颜色深度为简单的 8 位。 (即 RGB 值 0-255)。我计划实现这一点的方法是通过一个简单的“抖动”算法实现为 HLSL 像素着色器。基本上,如果请求 slimDX 将文本渲染到颜色为 Color4( 0.55f, 0.55f, 0.55f ) 的表面,对应于 ( 140.25 , 140.25 , 140.25 ) 的 rgb 值,我希望每个像素的每个颜色通道都有设置为 141 的几率为 25%,设置为 140 的几率为 75%。这应该(在许多像素的限制内)导致字母显示为灰色阴影的 1/4介于 140 和 141 之间。
但是,在尝试使用 fxc 进行编译时,我的原型着色器代码出现错误。我在编译时得到一个非法字符代码,我不知道为什么。此外,如果您是 HLSL 专家,请查看我的代码并制作任何让您印象深刻的 cmets。注意我从这个问题的答案中得到了 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 的 cmets,我借用的随机函数是用 GLSL 而不是 HLSL 编写的。我不得不将 vec2 更改为 float2 并将随机函数放在顶部。除此之外,我还必须编写一个 mod 函数,因为 GLSL mod() != HLSL fmod。并且 GLSL fract() 已更改为 HLSL frac()。我还有一个问题,我的文本文件是用 UTF-8 编码的,我猜这会导致 fxc 出现一些问题。重新编码为 ANSI 后,我能够得到一些更好的错误消息。但是,我仍然遇到一些问题。

我尝试使用fxc /Zi /E DitherByChance DitherByChance.fxfxc /Zi /E DitherByChance /LD DitherByChance.fx 进行编译,因为我的目标是DX9,但两次都出现以下错误:

undeclared indentifier 's0' error 来自这一行 float4 oldColor = tex2D(s0, coords);

我不确定这个 s0 参数到底是什么,我刚刚在另一个着色器示例中看到它。我看到另一个例子,有人声明了一个 Global 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

有什么想法吗?

【问题讨论】:

    标签: directx shader hlsl slimdx pixel-shader


    【解决方案1】:

    首先您需要在随机函数中将 vec2 替换为 float2,因为 vec2 是 glsl 语法。

    那么你的随机函数应该放在你的 PixelShader (c-style)之上。

    您的着色器现在应该可以编译了,如果没有,请发布错误消息。

    从最新位编辑:

    sampler2D Tex0;
    

    是一个采样器单元,你需要将它绑定到你的纹理,因为采样器会告诉如何过滤它(线性/点),并解决它(包裹/夹...)

    http://msdn.microsoft.com/en-us/library/windows/desktop/bb509644(v=vs.85).aspx

    由于您编译的是像素着色器,因此您需要使用 fxc /T ps_3_0,因为您编译为像素着色器,而不是顶点着色器。

    【讨论】:

    • 我的代码仍然有问题。我已经用更多细节编辑了我的问题。
    • 编辑了答案并添加了更多细节。
    • Ok /T ps_2_0 固定允许代码编译。 (我想为 DX9 使用 2_0 对吗?)。另外,如何将采样器单元绑定到纹理?我想我不希望它进行过滤,因为我只是使用 RenderToSurface 类将文本绘制到纹理,然后使用精灵批处理将纹理绘制到屏幕。我没有对任何物体或任何东西进行纹理处理。
    • 您也可以将 3_0 与 DX9 一起使用。您通过绑定到相关的纹理单元来绑定到采样器
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多