opengl - GPU着色器的像素缩放算法问题

标签 opengl glsl shader cg

所以我正在为像 super 任天堂这样的老式模拟器开发一些像素着色器。您拥有 HQnx、2xSaI 等经典算法,它们绝对是为在 CPU 上运行而编写的,并且在 block 传输到屏幕之前可以精确缩放到两倍大小。

转到 GPU 片段着色器,这些算法基本上可以免费完成。我正在使用 OpenGL 和 Cg/GLSL,但这个问题也应该适用于 Direct3D/HLSL 编码器。

主要问题是这些算法使用某种算法来决定颜色,从而与相邻像素混合。然而,我发现这个概念对于着色器语言来说相当困难。通常使用片段着色器,您可以获得浮点纹理坐标,您可以使用它来进行纹理查找,通常将 GL_LINEAR 用作纹理过滤器。大多数像素着色器使用 GL_NEAREST,并自行进行平滑处理。

如果我想找到确切的相邻像素,就会出现问题。我见过一些实现,但它们偶尔会在屏幕上产生伪影。可能是由于发生 float 不准确。我发现大多数伪像在使用两倍大小的纹理时都会消失,这进一步强化了我的信念,即 float 不准确。这是 Cg 中显示问题的示例片段着色器:

struct output
{
   float4 color : COLOR;
};

struct input
{
  float2 video_size;
  float2 texture_size;
  float2 output_size;
};

struct deltas
{
   float2 UL, UR, DL, DR;
};


output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s_p : TEXUNIT0)
{
   float2 texsize = IN.texture_size;
   float dx = pow(texsize.x, -1.0) * 0.25;
   float dy = pow(texsize.y, -1.0) * 0.25;
   float3 dt = float3(1.0, 1.0, 1.0);

   deltas VAR = { 
      tex + float2(-dx, -dy),
      tex + float2(dx, -dy),
      tex + float2(-dx, dy),
      tex + float2(dx, dy)
   };

   float3 c00 = tex2D(s_p, VAR.UL).xyz;
   float3 c20 = tex2D(s_p, VAR.UR).xyz;
   float3 c02 = tex2D(s_p, VAR.DL).xyz;
   float3 c22 = tex2D(s_p, VAR.DR).xyz;

   float m1=dot(abs(c00-c22),dt)+0.001;
   float m2=dot(abs(c02-c20),dt)+0.001;

   output OUT;
   OUT.color = float4((m1*(c02+c20)+m2*(c22+c00))/(2.0*(m1+m2)),1.0);
   return OUT;
}

有没有什么方法可以确保我们可以从我们期望的像素而不是其他像素中获取颜色数据?我相信会出现此问题,因为我们可能会从恰好位于两个像素之间的坐标查询像素(如果这有意义的话)。希望我忽略的这些着色器语言中有一些内置函数。

最佳答案

当然,在 OpenGL 中有几种方法:

  • 在着色器中,使用 texelFetch 函数进行纹理提取,它使用整数非标准化坐标。在 GL_EXT_gpu_shader4 扩展或 OpenGL 3.0 中可用。
  • 使用纹理矩形(GL_ARB_texture_rectangle,OpenGL 3.2),此纹理目标使用非标准化坐标,但不允许 mipmap 并限制某些环绕模式。

非标准化坐标就是你想要的,它们在[0, 0] x [w, h]范围内/

关于opengl - GPU着色器的像素缩放算法问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5010248/

相关文章:

opengl - 最简单照明模型中的光方向及其变换

c++ - 曲面 segmentation 着色器没有输出?

three.js - 基于世界空间的 GLSL 片段着色器 UV 置换

opengl - 法线贴图问题

opengl - 着色器变量归一化职责

C++ 表示我的最高着色器模型是 3

c++ - GLSL - 尝试添加多盏灯?

c++ - OpenGL 绑定(bind)纹理到顶点缓冲对象(使用 CG 着色器)

ubuntu - 错误 : Library "libGL" was not found

windows - 编译和运行 GLSL 程序需要什么?