gpt4 book ai didi

javascript - 矩阵的 WebGl 内存表示法

转载 作者:行者123 更新时间:2023-12-02 14:38:04 26 4
gpt4 key购买 nike

由于 webGL 源自 openGL,坐标系应该是右手坐标系,但当我尝试通过手写旋转矩阵来旋转模型时,视觉输出与我的预期相反。

OpenGL 需要以列主格式编写的矩阵,这就是我围绕 y 轴手写 90° 逆时针旋转矩阵(假设我们使用右手坐标系)的方式:

var rot = new glMatrix.ARRAY_TYPE(16);
//I indexed the array this way to edit those values as if I
were editing rows instead of columns
rot[0] = 0;
rot[4] = 0;
rot[8] = -1;
rot[12] = 0;

rot[1] = 0;
rot[5] = 1;
rot[9] = 0;
rot[13] = 0;

rot[2] = 1;
rot[6] = 0;
rot[10] = 0;
rot[14] = 0;

rot[3] = 0;
rot[7] = 0;
rot[11] = 0;
rot[15] = 1;
gl.uniformMatrix4fv(Program.model, false, rot);

我期望围绕 y 轴进行 90° ccw 旋转,但我得到的是 CW 旋转。转置按预期工作,这意味着数学错误或者我遗漏了其他内容

最佳答案

存储与矩阵的使用方式正交。您可以存储它们的列专业或行专业。它们在乘法中的使用方式与其存储无关。

为了清楚起见,我可以像这样存储矩阵

// storage format 1
[xaxis-x, xaxis-y, xaxis-z, 0,
yaxis-x, yaxis-y, yaxis-z, 0,
zaxis-x, zazis-y, xaxis-z, 0,
trans-x, trans-y, trans-z, 1]

或者我可以像这样存储它

// storage format 2
[xaxis-x, yaxis-x, zaxis-x, trans-x,
xaxis-y, yaxis-y, zaxis-y, trans-y,
xaxis-z, yazis-z, zaxis-z, trans-z,
0, 0, 0, 1]

然后我可以编写所有这些函数

columnMajorMutliplyUsingStorageFormat1(matrix, vector)
columnMajorMutliplyUsingStorageFormat2(matrix, vector)
rowMajorMutliplyUsingStorageFormat1(matrix, vector)
rowMajorMutliplyUsingStorageFormat2(matrix, vector)

你可以想象这些函数将如何编写。要点是存储格式与使用是分开的。

在任何情况下,几乎所有 WebGL 和 OpenGL 程序的矩阵几乎总是采用存储格式 1

// storage format 1
[xaxis-x, xaxis-y, xaxis-z, 0,
yaxis-x, yaxis-y, yaxis-z, 0,
zaxis-x, zazis-y, xaxis-z, 0,
trans-x, trans-y, trans-z, 1]

您可以在 OpenGL 1.0 中验证这一点。

glMatrixMode(GL_MODELVIEW);
glTranslatef(1.0f, 2.0f, 3.0f);
float mat[16];
glGetFloatv(GL_MODELVIEW, &mat[0]);
printf("%f %f %f %f\n", mat[0], mat[1], mat[2], mat[3]);
printf("%f %f %f %f\n", mat[4], mat[5], mat[6], mat[7]);
printf("%f %f %f %f\n", mat[8], mat[9], mat[10], mat[11]);
printf("%f %f %f %f\n", mat[12], mat[13], mat[14], mat[15]);

将打印类似的内容

1 0 0 0
0 1 0 0
0 0 1 0
1 2 3 1

也就是说如果要设置平移设置元素12,13,14。如果要设置xaxis设置元素0,1,2

以下是元素 12、13、14 中翻译的典型示例

典型的用法示例是

gl_Position = worldViewProjectionMatrix * position;

"use strict";
twgl.setDefaults({attribPrefix: "a_"});
var m4 = twgl.m4;
var gl = document.getElementById("c").getContext("webgl")
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 2);

var tex = twgl.createTexture(gl, {
min: gl.NEAREST,
mag: gl.NEAREST,
src: [
255, 255, 255, 255,
192, 192, 192, 255,
192, 192, 192, 255,
255, 255, 255, 255,
],
});

var uniforms = {
u_lightWorldPos: [1, 8, -10],
u_lightColor: [0.4, 0.8, 0.8, 1],
u_ambient: [0, 0, 0, 1],
u_specular: [1, 1, 1, 1],
u_shininess: 50,
u_specularFactor: 1,
u_diffuse: tex,
};

function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 10);
var eye = [1, 4, -6];
var target = [0, 0, 0];
var up = [0, 1, 0];

var camera = m4.lookAt(eye, target, up);
var view = m4.inverse(camera);
var viewProjection = m4.multiply(view, projection);
var world = m4.rotationY(time);

uniforms.u_viewInverse = camera;
uniforms.u_world = world;
uniforms.u_worldInverseTranspose = m4.transpose(m4.inverse(world));
uniforms.u_worldViewProjection = m4.multiply(world, viewProjection);

gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);

requestAnimationFrame(render);
}
requestAnimationFrame(render);
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
  <script id="vs" type="notjs">
uniform mat4 u_worldViewProjection;
uniform vec3 u_lightWorldPos;
uniform mat4 u_world;
uniform mat4 u_viewInverse;
uniform mat4 u_worldInverseTranspose;

attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

void main() {
v_texCoord = a_texcoord;
v_position = (u_worldViewProjection * a_position);
v_normal = (u_worldInverseTranspose * vec4(a_normal, 0)).xyz;
v_surfaceToLight = u_lightWorldPos - (u_world * a_position).xyz;
v_surfaceToView = (u_viewInverse[3] - (u_world * a_position)).xyz;
gl_Position = v_position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

uniform vec4 u_lightColor;
uniform vec4 u_ambient;
uniform sampler2D u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_specularFactor;

vec4 lit(float l ,float h, float m) {
return vec4(1.0,
max(l, 0.0),
(l > 0.0) ? pow(max(0.0, h), m) : 0.0,
1.0);
}

void main() {
vec4 diffuseColor = texture2D(u_diffuse, v_texCoord);
vec3 a_normal = normalize(v_normal);
vec3 surfaceToLight = normalize(v_surfaceToLight);
vec3 surfaceToView = normalize(v_surfaceToView);
vec3 halfVector = normalize(surfaceToLight + surfaceToView);
vec4 litR = lit(dot(a_normal, surfaceToLight),
dot(a_normal, halfVector), u_shininess);
vec4 outColor = vec4((
u_lightColor * (diffuseColor * litR.y + diffuseColor * u_ambient +
u_specular * litR.z * u_specularFactor)).rgb,
diffuseColor.a);
gl_FragColor = outColor;
}
</script>
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<canvas id="c"></canvas>

这是相反的示例,在元素 3、7、11 中进行了翻译

在这种情况下,着色器中的数学已更改为

gl_Position = position * worldViewProjectionMatrix;

"use strict";
twgl.setDefaults({attribPrefix: "a_"});
var m4 = twgl.m4;
var gl = document.getElementById("c").getContext("webgl")
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 2);

var tex = twgl.createTexture(gl, {
min: gl.NEAREST,
mag: gl.NEAREST,
src: [
255, 255, 255, 255,
192, 192, 192, 255,
192, 192, 192, 255,
255, 255, 255, 255,
],
});

var uniforms = {
u_lightWorldPos: [1, 8, -10],
u_lightColor: [0.4, 0.8, 0.8, 1],
u_ambient: [0, 0, 0, 1],
u_specular: [1, 1, 1, 1],
u_shininess: 50,
u_specularFactor: 1,
u_diffuse: tex,
};

function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

var projection = m4.perspective(30 * Math.PI / 180, gl.canvas.clientWidth / gl.canvas.clientHeight, 0.5, 10);
var eye = [1, 4, -6];
var target = [0, 0, 0];
var up = [0, 1, 0];

var camera = m4.lookAt(eye, target, up);
var view = m4.inverse(camera);
var viewProjection = m4.multiply(view, projection);
var world = m4.rotationY(time);

uniforms.u_viewInverse = m4.transpose(camera);
uniforms.u_world = m4.transpose(world);
uniforms.u_worldInverseTranspose = m4.transpose(m4.transpose(m4.inverse(world)));
uniforms.u_worldViewProjection = m4.transpose(m4.multiply(world, viewProjection));

gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);

requestAnimationFrame(render);
}
requestAnimationFrame(render);
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script id="vs" type="notjs">
uniform mat4 u_worldViewProjection;
uniform vec3 u_lightWorldPos;
uniform mat4 u_world;
uniform mat4 u_viewInverse;
uniform mat4 u_worldInverseTranspose;

attribute vec4 a_position;
attribute vec3 a_normal;
attribute vec2 a_texcoord;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

void main() {
v_texCoord = a_texcoord;
v_position = (a_position * u_worldViewProjection);
v_normal = (vec4(a_normal, 0) * u_worldInverseTranspose).xyz;
v_surfaceToLight = u_lightWorldPos - (a_position * u_world).xyz;
v_surfaceToView = (u_viewInverse[3] - (a_position * u_world)).xyz;
gl_Position = v_position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

varying vec4 v_position;
varying vec2 v_texCoord;
varying vec3 v_normal;
varying vec3 v_surfaceToLight;
varying vec3 v_surfaceToView;

uniform vec4 u_lightColor;
uniform vec4 u_ambient;
uniform sampler2D u_diffuse;
uniform vec4 u_specular;
uniform float u_shininess;
uniform float u_specularFactor;

vec4 lit(float l ,float h, float m) {
return vec4(1.0,
max(l, 0.0),
(l > 0.0) ? pow(max(0.0, h), m) : 0.0,
1.0);
}

void main() {
vec4 diffuseColor = texture2D(u_diffuse, v_texCoord);
vec3 a_normal = normalize(v_normal);
vec3 surfaceToLight = normalize(v_surfaceToLight);
vec3 surfaceToView = normalize(v_surfaceToView);
vec3 halfVector = normalize(surfaceToLight + surfaceToView);
vec4 litR = lit(dot(a_normal, surfaceToLight),
dot(a_normal, halfVector), u_shininess);
vec4 outColor = vec4((
u_lightColor * (diffuseColor * litR.y + diffuseColor * u_ambient +
u_specular * litR.z * u_specularFactor)).rgb,
diffuseColor.a);
gl_FragColor = outColor;
}
</script>
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<canvas id="c"></canvas>

关于javascript - 矩阵的 WebGl 内存表示法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37264594/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com