I'm very new to WebGL, and I'm modifying an existing project that I found online to suit my needs.
My camera is isometric, and I'm rendering two cubes. I'd like to have an infinite grid along the 'ground', like in many 3d editors.
You can see below that the grid isn't infinite (I'm aware that this is because the vertices only go from -1 to 1), and it's not oriented properly. It's been rendered directly on-screen, rather than respecting the transformation matrix sent to the GPU.
As there are three interconnected programs involved (2 shaders, plus JS), I don't know where the fault lies. Here's the code that should be the most relevant; the project is large so let me know if you need to see anything else:
let vertices = [
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0,
1.0, -1.0, 0.0,
-1.0, -1.0, 0.0
];
let bufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
let attribute = shader.position; // getAttribLocation(..., 'position')
gl.bindBuffer(gl.ARRAY_BUFFER, vertices);
gl.enableVertexAttribArray(attribute);
gl.vertexAttribPointer(attribute, 3, gl.FLOAT, false, 0, 0); // size of 3 is the only one that renders the quad
// this rotates the plane to be along the 'ground' - even without this, it stands up, and the grid still doesn't respect the orientation
(new Matrix()).rotateX(90).sendToGpu(gl, shader.model); // getUniformLocation(..., 'model')
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); // 4 vertices
Vertex shader:
attribute vec4 position;
attribute vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
varying vec2 vUv;
void main()
{
vUv = uv;
gl_Position = projection * view * model * position;
}
Fragment shader:
precision mediump float;
uniform float time;
uniform vec2 mouse;
uniform vec2 resolution;
vec2 offset = vec2(0, 0);
vec2 pitch = vec2(32, 32);
void main()
{
float lX = gl_FragCoord.x / resolution.x;
float lY = gl_FragCoord.y / resolution.y;
float scaleFactor = 10000.0;
float offX = (scaleFactor * offset[0]) + gl_FragCoord.x;
float offY = (scaleFactor * offset[1]) + (1.0 - gl_FragCoord.y);
if (int(mod(offX, pitch[0])) == 0 || int(mod(offY, pitch[1])) == 0)
{
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.2);
}
else
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 0.1);
}
}
Could anyone point me in the right direction please?
Generate the grid depending the texture coordinates (vUv
) instead of gl_FragCoord.xy
.
Add a texture coordinate attribute:
let vertices = [
// x y z u v
1.0, 1.0, 0.0, 1.0, 0.0,
-1.0, 1.0, 0.0, 0.0, 0.0,
1.0, -1.0, 0.0, 1.0, 1.0,
-1.0, -1.0, 0.0 0.0, 1.0,
];
let bufferObject = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, bufferObject);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, vertices);
let attribute = shader.position; // getAttribLocation(..., 'position')
gl.enableVertexAttribArray(attribute);
gl.vertexAttribPointer(attribute, 3, gl.FLOAT, false, 5*4, 0);
let attribute_uv = gl.getAttribLocation(..., 'uv')
gl.enableVertexAttribArray(attribute_uv);
gl.vertexAttribPointer(attribute_uv, 2, gl.FLOAT, false, 5*4, 3*4);
Set offX
and offY
by vUV
instead of gl_FragCoord.xy
in the fragment shader:
// [...]
varying vec2 vUv;
void main()
{
// float offX = (scaleFactor * offset[0]) + gl_FragCoord.x;
// float offY = (scaleFactor * offset[1]) + (1.0 - gl_FragCoord.y);
float scaleFactor = 32.0*8.0;
float offX = scaleFactor * vUv.x;
float offY = scaleFactor * vUv.y;
// [...]
}