Mad*_*ist 9 opengl-es glsl webgl fragment-shader
我正在使用本教程中的以下代码对WebGL中的片段着色器中的浮点纹理执行线性过滤:
float fHeight = 512.0;
float fWidth = 1024.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
Run Code Online (Sandbox Code Playgroud)
在Nvidia GPU上看起来很不错,但在其他两台采用Intel集成GPU的计算机上,它看起来像这样:
出现较浅或较暗的线条,不应该出现在那里.如果放大,它们会变得可见,并且缩放得越多,它们就越频繁.当非常接近地放大时,它们出现在我正在过滤的纹理的每个纹素的边缘.我尝试更改片段着色器中的精度语句,但这并没有解决它.
内置线性过滤适用于两个GPU,但我仍然需要手动过滤作为不支持使用WebGL对浮点纹理进行线性过滤的GPU的后备.
英特尔GPU来自台式机Core i5-4460和配备Intel HD 5500 GPU的笔记本电脑.对于浮点值的所有精度,我得到一个rangeMin和rangeMax为127,精度为23 getShaderPrecisionFormat
.
有什么原因导致这些文物以及我如何解决它?
编辑:
通过多尝试一下,我发现在片段着色器中减少纹素大小变量会删除这些伪像:
float texelSizeX = 1.0/fWidth*0.998;
float texelSizeY = 1.0/fHeight*0.998;
Run Code Online (Sandbox Code Playgroud)
乘以0.999是不够的,但将纹素大小乘以0.998会消除伪影.
这显然不是一个令人满意的解决方案,我仍然不知道是什么导致它,我现在可能在其他GPU或驱动程序上造成了伪影.所以我仍然有兴趣弄清楚实际问题在这里.
我不清楚代码想要做什么。它不会再现 GPU 的双线性,因为这将使用以纹理坐标为中心的像素。
换句话说,按照实施
vec4 c = tex2DBiLinear(someSampler, someTexcoord);
Run Code Online (Sandbox Code Playgroud)
不等于LINEAR
vec4 c = texture2D(someSampler, someTexcoord);
Run Code Online (Sandbox Code Playgroud)
texture2D
查看像素someTexcoord +/- texelSize * .5
,而 as 则tex2DBiLinear
查看像素someTexcoord
,并且someTexcoord + texelSize
您没有提供足够的代码来重新发布您的问题。我猜测源纹理的大小是 512x1024,但由于您没有发布该代码,我不知道您的源纹理是否与定义的大小匹配。您也没有发布您的目标大小。您发布的最上面的图像是 471x488。这是您的目标尺寸吗?您也没有发布您正在使用的纹理坐标的代码以及操作它们的代码。
猜测您的源是 512x1024,您的目标是 471x488 我无法重现您的问题。
vec4 c = tex2DBiLinear(someSampler, someTexcoord);
Run Code Online (Sandbox Code Playgroud)
vec4 c = texture2D(someSampler, someTexcoord);
Run Code Online (Sandbox Code Playgroud)
如果您认为问题与浮点纹理有关,我也无法在那里回购
const fs = `
precision highp float;
uniform sampler2D tex;
varying vec2 v_texcoord;
float tex2DBiLinear( sampler2D textureSampler_i, vec2 texCoord_i )
{
float fHeight = 1024.0;
float fWidth = 512.0;
float texelSizeX = 1.0/fWidth;
float texelSizeY = 1.0/fHeight;
float p0q0 = texture2D(textureSampler_i, texCoord_i)[0];
float p1q0 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX, 0))[0];
float p0q1 = texture2D(textureSampler_i, texCoord_i + vec2(0, texelSizeY))[0];
float p1q1 = texture2D(textureSampler_i, texCoord_i + vec2(texelSizeX , texelSizeY))[0];
float a = fract( texCoord_i.x * fWidth ); // Get Interpolation factor for X direction.
// Fraction near to valid data.
float pInterp_q0 = mix( p0q0, p1q0, a ); // Interpolates top row in X direction.
float pInterp_q1 = mix( p0q1, p1q1, a ); // Interpolates bottom row in X direction.
float b = fract( texCoord_i.y * fHeight );// Get Interpolation factor for Y direction.
return mix( pInterp_q0, pInterp_q1, b ); // Interpolate in Y direction.
}
void main() {
gl_FragColor = vec4(tex2DBiLinear(tex, v_texcoord), 0, 0, 1);
}
`;
const vs = `
attribute vec4 position;
attribute vec2 texcoord;
varying vec2 v_texcoord;
void main() {
gl_Position = position;
v_texcoord = texcoord;
}
`;
const gl = document.querySelector('canvas').getContext('webgl');
// compile shaders, link programs, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: {
numComponents: 2,
data: [
-1, -1,
1, -1,
-1, 1,
1, 1,
],
},
texcoord: [
0, 0,
1, 0,
0, 1,
1, 1,
],
indices: [
0, 1, 2,
2, 1, 3,
],
});
const ctx = document.createElement('canvas').getContext('2d');
ctx.canvas.width = 512;
ctx.canvas.height = 1024;
const gradient = ctx.createRadialGradient(256, 512, 0, 256, 512, 700);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'cyan');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 512, 1024);
const tex = twgl.createTexture(gl, {
src: ctx.canvas,
minMag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
auto: false,
});
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.drawArrays or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo);
Run Code Online (Sandbox Code Playgroud)
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas width="471" height="488"></canvas>
Run Code Online (Sandbox Code Playgroud)
如果任何值关闭。如果您的源纹理大小不匹配fWidth
,fHeigth
或者您的纹理坐标不同或以某种方式进行调整,那么我当然可以回购。如果其中任何一个不同,那么我可以想象问题。
在 Intel Iris Pro 和 Intel HD Graphics 630 中进行了测试。还在 iPhone6+ 上进行了测试。请注意,您需要确保片段着色器正在运行precision highp float
,但该设置可能只会影响移动 GPU。
归档时间: |
|
查看次数: |
650 次 |
最近记录: |