I want to render a texture to a plane using custom shaders. This texture has an 'offset' property set, that works correctly when I use a standard threejs material. However, I cannot figure out how to access these offsets in my custom fragment shader. It simply renders the whole texture over the whole plane:
shaders:
<script id="vertex_shader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position,1.0);
}
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
uniform sampler2D texture1;
varying vec2 vUv;
void main()
{
gl_FragColor = texture2D(texture1, vUv);
}
</script>
if I could somehow say something like:
gl_FragColor = texture2D(texture1, vUv + texture1.offset);
? Maybe that would work. But obviously that throws an error.
UPDATE: so I sent the texture offset in as a uniform and that works. Dont know why I didn't think of that.
If I understand your question correctly, then the answer should be to add and use the uniform mat3 uvTransform;
uniform to your fragment shader.
THREE will look for and populate that uniform with the texture transformation (which includes texture1.offset
), when rendering the texture onto your geometry.
You should be able to access and extract the data supplied to texture1.offset
to offset your texture sampling as follows:
<script id="vertex_shader" type="x-shader/x-vertex">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>
<script id="fragment_shader" type="x-shader/x-fragment">
// [UPDATE] The uv offset uniform we defined below
uniform vec2 uvOffset;
// [UPDATE] The texture uniform we defined below
uniform sampler2D texture;
varying vec2 vUv;
void main()
{
// [UPDATE] Apply offset to texture lookup
gl_FragColor = texture2D(texture, vUv + uvOffset);
}
</script>
You would then accompany the vertex and fragment shaders above, with the following THREE.ShaderMaterial
:
<script>
var material = new THREE.ShaderMaterial({
uniforms: THREE.UniformsUtils.merge([
{
//Declare texture uniform in shader
texture: { type: 't', value: null },
//Declare texture offset in shader
uvOffset : { type : 'v', value : new THREE.Vector2(0,0) }
}
]),
vertexShader:
document.getElementById('vertexshader').textContent,
fragmentShader:
document.getElementById('fragmentshader').textContent
});
// Shader uniforms can be updated like so
material.uniforms.map.value = yourTexture;
material.uniforms.uvOffset.value = yourTextureOffsetVector2;
</script>