2011-02-15 102 views
3

因此,我正在为超级任天堂等优秀的老模拟器制作一些像素着色器。你有像HQnx,2xSaI等经典算法,它们肯定是写在CPU上运行的,并且在传输到屏幕之前被精确缩放到两倍。移动到GPU片段着色器,这些算法可以基本上免费完成。我正在使用OpenGL和Cg/GLSL,但这个问题也应该适用于Direct3D/HLSL编码器。GPU着色器的像素缩放算法问题

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

如果我想查找确切的邻居像素,就会出现问题。我已经看到了一些实现,但他们偶尔会在屏幕上造成文物。可能是由于发生浮点不准确。我发现当使用两次幂次大小的纹理时,大部分工件都会消失,这进一步加强了我相信存在浮点错误的可能性。这里是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; 
} 

有一些方法,以确保我们能够抓住从我们所期望的像素的颜色数据,而不是一个不同?我相信会发生这个问题,因为我们可能从两个像素之间的坐标查询像素(如果有意义的话)。希望有一些内置的函数能够被我忽略的这些着色语言。

回答

4

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

  • 内的着色器,使用texelFetch功能做了纹理拾取,使用整数非标准化的坐标。可用于GL_EXT_gpu_shader4扩展或OpenGL 3.0。
  • 使用纹理矩形(GL_ARB_texture_rectangle,OpenGL 3.2),此纹理目标使用未标准化的坐标,但不允许使用mipmap并限制某些自动换行模式。

非标准化坐标是你想要的,他们是在[0,0]×[W,H]范围/

+0

我碰到同样的问题迈斯特尔没有,但我工作的OpenGL ES 2.0。任何想法如何在该环境下做到这一点? – 2012-03-10 11:19:48