我正在着色器程序中使用非2的幂次纹理。我正在尝试实现重复的滚动文本。滚动效果很好,但是当我尝试通过顶点着色器中的逻辑使纹理重复时,我突然得到一个四边形,其整个范围内都有一组拉伸像素。我认为这是由于过滤算法导致的。
作为背景,我想在顶点程序中生成纹理坐标,因为我随后在片段程序中对其进行了进一步的变形,并且如果片段程序的输入已经正确以解决滚动问题,则更易于管理。请注意,我在相应的片段着色器中访问textureCoordinateVarying
此方法有效,尽管在文本滚动时没有重复的纹理:
attribute vec4 position;
attribute vec2 texcoord;
uniform mat3 matrixUniform;
uniform float horizontalTextureOffsetUniform;
varying vec2 textureCoordinateVarying;
void main() {
gl_Position = vec4((matrixUniform * vec3(position.x, position.y, 1)).xy, 0, 1);
textureCoordinateVarying = vec2(
//I get a nice scrolling animation by changing the offset here, but the texture doesn't repeat, since it is NPO2 and therefore doesn't have repeating enabled
texcoord.x + horizontalTextureOffsetUniform,
texcoord.y
);
}
另一方面,正如您所看到的,这给了我一张延伸的图像:
attribute vec4 position;
attribute vec2 texcoord;
uniform mat3 matrixUniform;
uniform float horizontalTextureOffsetUniform;
varying vec2 textureCoordinateVarying;
void main() {
gl_Position = vec4((matrixUniform * vec3(position.x, position.y, 1)).xy, 0, 1);
textureCoordinateVarying = vec2(
\\Note how I am using fract here, which should make the texture repeat at the 1.0 texture boundary, but instead renders a blurry stretched texture
fract(texcoord.x + horizontalTextureOffsetUniform),
texcoord.y
);
}
关于如何解决这个问题的任何想法?
谢谢!
答案 0 :(得分:0)
您需要在片段着色器(而不是顶点着色器)中执行重复数学运算。
const gl = document.querySelector('canvas').getContext('webgl');
const vs = `
void main() {
gl_Position = vec4(0,0,0,1);
gl_PointSize = 100.0;
}`;
const fs = `
precision highp float;
uniform sampler2D tex;
uniform vec2 offset;
void main() {
gl_FragColor = texture2D(tex, fract(gl_PointCoord.xy + offset));
}`;
// compile shaders, link program, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
// calls gl.createTexture, gl.texImage2D, gl.texParameteri
const tex = twgl.createTexture(gl, {
src: 'https://i.imgur.com/v38pV.jpg'
});
function render(time) {
time *= 0.001;
gl.useProgram(programInfo.program);
// calls gl.activeTexture, gl.bindTexture, gl.uniform
twgl.setUniformsAndBindTextures(programInfo, {
tex,
offset: [time, time * 0.1],
});
gl.drawArrays(gl.POINTS, 0, 1);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>