Related
I'm trying to draw a quad in three.js, but three.js keeps complaining that 'tex' is not a 'WebGLTexture' and refuse to run, what's going on here? thank you.
// z= depth, tex is texture
function drawQuad(z, tex)
{
var verts = [
-1.0, 1.0, z, 0.0, 1.0,
-1.0, -1.0, z, 0.0, 0.0,
1.0, 1.0, z, 1.0, 1.0,
1.0, -1.0, z, 1.0, 0.0,
];
const gl = renderer.getContext();
gl.disable(gl.DEPTH_TEST);
gl.useProgram(quadShader);
var vb = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verts), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, vb);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 20, 0);
gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 20, 12);
gl.uniform1i(gl.getUniformLocation(quadShader, 'su_tex'), 0)
gl.activeTexture(gl.TEXTURE0 + 0);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)
gl.enable(gl.DEPTH_TEST);
}
tex is loaded like this
wallTex = loader.load("https://r105.threejsfundamentals.org/threejs/resources/images/wall.jpg");
drawQuad(1.0, wallTex);
Ok, i've figured it out.
Anyway, this may help those who are still confused (c++ opengl pragrammers):
WebGlTexture is the id you created with glGenTextures(1, &texturId), it is for rendering.
THREE.js.Texture is a texture container, it contains texture descriptions and image data downloaded from web or whatever, it has a hidden property __webglTexture which is null if this THREE.js.Texture never been used for rendering. then what if it has been used for rendering? it will create a WebGLTexture (via glGenTextures(1, &textureId) internally i guess) and assign this WebGlTexture id to its __webglTexture, and now you can use it for rendering.
It might be more appropriate to call THREE.js.Texture as THREE.js.TextrureRes IMO, less mis-leading.
I want to make a WebGL 2D game with many sprites
But I only have two triangles to make a square.
And I do not need additional vertices.
The following tutorials will help you understand my purpose
https://webgl2fundamentals.org/webgl/lessons/webgl-drawing-without-data.html
https://webgl2fundamentals.org/webgl/lessons/webgl-instanced-drawing.html
Only one square and lots of matrices to move the square
My Shader
#version 300 es
uniform mat3 u_matrix;
uniform mat3 u_view;
uniform mat3 u_uv;
out vec2 v_texcoord;
const float xp[6] = float[](0.0, 0.0, 1.0, 1.0, 1.0, 0.0);
const float yp[6] = float[](0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
void main() {
float x = xp[gl_VertexID];
float y = yp[gl_VertexID];
gl_Position = vec4(u_view * u_matrix * vec3(x, y, 1),1);
v_texcoord = vec3(u_uv * vec3(x,y,0)).xy;
}
My Code in each frame
gameobgects.forEach(gameobject => {
gl.uniformMatrix3fv(u_uv, false, gameobject.uv);
gl.uniformMatrix3fv(u_matrix, false, gameobject.matrix);
gl.drawArrays(gl.TRIANGLES, 0, 6);
});
I can only change the value u_matrix once in each draw call with this shader
Help me to fix my shader. to connect u_matrix to a buffer and draw all objects in one call.
Forgive me for my bad English
I have an object called Cube. It is set up like this
//Cube object
function Cube(vertices, color, scale)
{
//this.vertices = vertices;
this.setColor(color);
this.setScale(vertices, 1);
}
I commented out //this.vertices = vertices; because im not sure if I have to set vertices here or set them within setScale() function.
I want to set a scale on a matrix. The matrix is:
var verts = [
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
The function i use to set the scale is like this:
Cube.prototype.setScale = function(vertices, scale)
{
var length = vertices.length;
for( var i = 0; i < length; i++)
{
//alert("before "+ vertices[i]+ " i "+ i);
vertices[i] *= scale;
//alert("after "+ vertices[i]);
}
I think that by doing this the for loop should take the matrix length and start a for loop.
Within this for loop I will get the vertice at i and multiply it by the scale.
When I do it like this though the for loop will reiterate. I.e. when i hits 72 the loop does not stop.
I commented out //this.vertices = vertices; because im not sure if I have to set vertices here
You either need to set it there or at the end of the constructor. Your setScale function is nicely decoupled from where the vertices array is stored and I'd keep it that way. But you might consider renaming it scaleVertices() instead.
When I do it like this though the for loop will reiterate. I.e. when i hits 72 the loop does not stop.
Really? That's odd. I must be missing something; the code looks correct.
Don't use alert(), by the way, it will make your life hell to debug anything. You're much better using console.log().
Does WebGL have a zBuffer or depth?
So here's my problem:
The cube is being cropped or not being rendered properly. Setting the 'z' coordinates beside 0 and 1 results to object / geometry being cropped / cut.
Additionaly I've already implemented this on C++ and it works properly just porting it webGL and OpenGL ES.
Here's my persepective view configuration:
mat4.perspective(45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0, pMatrix);
also tried setting the zFar to a much more larger value but the result are the same.
Here's the code that I used for vector translation:
mat4.translate(mvMatrix, mvMatrix, [0.0, 0.0, 2.0]);
and also tried this to check if there's a problem on the mat4.translate function this:
var x = 0.0, y = 0.0, z = 2.0;
var position = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1,
];
mat4.multiply(mvMatrix, mvMatrix, position);
Also check and tried setting the values directly in Vertex Shader:
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition.x, aVertexPosition.y, 2.0, 1.0);
Update:
Also set to enabled the DEPTH_TEST.
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
Finally, I solved it, the cause of the problem is due to invalid argument parameters and outdated tutorials on the internet regarding usage of the gl-matrix.js library.
mat4.perspective(45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0, pMatrix);
whereas of the new gl-matrix parameters should be like this:
mat4.perspective(pMatrix, 45.0, gl.viewportWidth / gl.viewportHeight, 0.1, 1000.0);
After checking the correct documentation of the JS library.
If you apply a projection, you normally look from the origin in the direction of the negative z-axis. So I think you need a translation by a negative value in z-direction to get your geometry in view, while you translate by [0.0, 0.0, 2.0].
You say you're trying to draw a cube, but your vertex shader hardwires all z-coordinates to 2.0. You can't really get any kind of 3-dimensional shape if you're using the same z-coordinate for all vertices. Well, you technically could, but I doubt that this is what you want.
In creating a webgl "hello world" for demonstration to a high school class, I am experiencing an anomalous result.
Using gl-matrix.js version 2.2.0, reversing the order of two transforms does not produce a difference in output.
This code produces the desired result:
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = mat4.create();
var modelview_matrix = mat4.create();
var mvp = mat4.create();
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
mat4.perspective(projection_matrix, D2R(50.0), gl.size[0] / gl.size[1], 1.0, 10.0);
mat4.translate(modelview_matrix, modelview_matrix, [0.0, 0.0, -3.5]);
mat4.rotate(modelview_matrix, modelview_matrix, D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0]);
mat4.multiply(mvp, projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
namely a triangle that spins in place about its Y axis.
Reversing the order of the translate and rotate should spin the triangle around the camera (part of my intended lesson), but instead continues to spin the triangle in place. I sanity checked this in an equivalent legacy OpenGL "hello world" producing exactly the expected results.
The vertex shader simply multiples the vertex position attribute with the mvp uniform. Is there a problem in gl-matrix.js or in this code?
For completeness, here is the render function.
Triangle.prototype.Render = function (gl, shader_index, color, mvp) {
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertex_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].VP, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].VP);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.element_buffer_object);
shaders[shader_index].Use(gl);
gl.uniformMatrix4fv(shaders[shader_index].MVP, false, mvp);
if (shader_index == 0)
gl.uniform4fv(shaders[shader_index].COLOR, color);
else {
gl.bindBuffer(gl.ARRAY_BUFFER, this.color_buffer_object);
gl.vertexAttribPointer(shaders[shader_index].COLOR, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaders[shader_index].COLOR);
}
gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
shaders[shader_index].StopUsing(gl);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
}
Thank you.
I believe there is an error in my use of gl-matrix or gl-matrix itself. Replacing gl-matrix with mjs.js works as expacted.
function DrawScene(gl) {
var time_now = new Date();
var elapsed_time = new Date();
elapsed_time.setDate(time_program_started - time_now);
var projection_matrix = M4x4.I;
var modelview_matrix = M4x4.I;
var mvp = M4x4.I;
gl.viewport(0, 0, gl.size[0], gl.size[1]);
gl.clearColor(0.2, 0.2, 0.2, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
projection_matrix = M4x4.makePerspective(50.0, gl.size[0] / gl.size[1], 1.0, 10.0);
modelview_matrix = M4x4.rotate(D2R(elapsed_time / 1000.0 * 60.0), [0.0, 1.0, 0.0], modelview_matrix);
modelview_matrix = M4x4.translate([0.0, 0.0, -5.5], modelview_matrix);
mvp = M4x4.mul(projection_matrix, modelview_matrix);
triangle.Render(gl, shader_index, [1.0, 1.0, 1.0, 1.0], mvp);
}
Does indeed rotate about the camera. Reversing to translate then rotate spins about the Y axis of the triangle.
I would be very pleased to have my code for gl-matrix corrected. If it cannot, gl-matrix is very broken.