GAMES 202 作业2 Part2

第七步 实时球谐光照计算

歪打正着

function getRotationPrecomputeL(precompute_L, rotationMatrix){
	result = [];
	for(xx = 0;xx < 3;xx++)
	{
		result[xx] = [];
		rr = [];
		for(yy =0;yy < 9;yy ++)
		{
			result[xx][yy] = precompute_L[yy][xx];
			rr[yy] = rotationMatrix[(yy - (yy % 3)) / 3 * 4 + (yy % 3)];
			// console.log(rotationMatrix[(yy - (yy % 3)) / 3 * 4 + (yy % 3)]);
			// console.log(rotationMatrix);
		}
		console.log("result[xx]" + result[xx]);
		console.log("rr" + rr);
		// result[xx] = mat3.create(result[xx]).reshape(3,3);
		// rr = mat3.create(rr).reshape(3,3);
		console.log(math.multiply([1,0,0,0,1,1,0,0,1] ,[1,0,0,0,1,0,0,0,1]));
	}
	return result;
}

我这时候正在打印,突然能用了

发现传入的数据其实是一个 9维的向量
我之前把他打包成3x3的矩阵是有问题的

let precomputeL_RGBMat3 = getRotationPrecomputeL(precomputeL[guiParams.envmapId], cameraModelMatrix);
if (k == 'uPrecomputeLR') {
    gl.uniformMatrix3fv(
        this.meshes[i].shader.program.uniforms[k],
        false,
        precomputeL_RGBMat3[0]);
}
if (k == 'uPrecomputeLG') {
    gl.uniformMatrix3fv(
        this.meshes[i].shader.program.uniforms[k],
        false,
        precomputeL_RGBMat3[1]);
}
if (k == 'uPrecomputeLB') {
    gl.uniformMatrix3fv(
        this.meshes[i].shader.program.uniforms[k],
        false,
        precomputeL_RGBMat3[2]);
}

实际上 gl.uniformMatrix3fv函数
已经帮我把9维的向量打包成 Mat3了

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第八步 环境光球谐旋转 (bonus)

现在 我拿到了SH 9个系数 ,和3x3旋转矩阵,怎么旋转呢?

首先precomputeL是SH函数,拿到9个系数就相当于拿到了原始图片。
precomputeL存储的其实是环境光球谐系数下的 RGB 值;
那么对环境光旋转的问题就转化为对SH函数进行旋转

第一个性质

球谐函数具有旋转不变形性,
在这里插入图片描述

第二个性质

对每层 band 上的 SH coefficient,可以分别在上面进行旋转,并且这个旋转是线性变化。
band就是阶数

公式1

性质推 存在mat4 M 使得公式成立
其中

  • M是三维空间旋转矩阵 mat4
  • R是旋转函数
  • n是三维空间法线向量 vec3
  • P是获取该bind上的球谐投影系数的函数
    在这里插入图片描述
    在这里插入图片描述
    此处假设A是可逆矩阵,实际上要判断A是否可逆,要看A的行列式不等于0;
    在这里插入图片描述

如何选取2l + 1个法向量

computeSquareMatrix_3by3
computeSquareMatrix_5by5
这两个预设函数里已经给了,我还在傻乎乎的想!!

二阶情况下 3x3

在这里插入图片描述

let n1 = [1, 0, 0, 0]; let n2 = [0, 0, 1, 0]; let n3 = [0, 1, 0, 0];
let p1 = sh.SHEval3(n1[0],n1[1],n1[2]);
let p2 = sh.SHEval3(n2[0],n2[1],n2[2]);
let p3 = sh.SHEval3(n3[0],n3[1],n3[2]);
let A_mat = math.matrix([[p1[1],p1[2],p1[3]],
	[p2[1],p2[2],p2[3]],
	[p3[1],p3[2],p3[3]]]
);
let A_inverse_mat = math.inv(A_mat);

在这里插入图片描述

let n1_rot = vec4.create();
let n2_rot = vec4.create();
let n3_rot = vec4.create();
vec4.transformMat4(n1_rot, n1, rotationMatrix);
vec4.transformMat4(n2_rot, n2, rotationMatrix);
vec4.transformMat4(n3_rot, n3, rotationMatrix);

let p1_rot = sh.SHEval3(n1_rot[0],n1_rot[1],n1_rot[2]);
let p2_rot = sh.SHEval3(n2_rot[0],n2_rot[1],n2_rot[2]);
let p3_rot = sh.SHEval3(n3_rot[0],n3_rot[1],n3_rot[2]);
let S_mat = math.matrix([[p1_rot[1],p1_rot[2],p1_rot[3]],
	[p2_rot[1],p2_rot[2],p2_rot[3]],
	[p3_rot[1],p3_rot[2],p3_rot[3]]]
);

vec4.transformMat4(n3_rot, n3, rotationMatrix);
其实就是对 n3 右乘 rotationMatrix 得到 n3_rot
在这里插入图片描述

result = S_mat * A_inverse_mat;

三阶情况下 5x5

function computeSquareMatrix_5by5(rotationMatrix){ // 计算方阵SA(-1) 5*5
	
	// 1、pick ni - {ni}
	let k = 1 / math.sqrt(2);
	let n1 = [1, 0, 0, 0]; let n2 = [0, 0, 1, 0]; let n3 = [k, k, 0, 0]; 
	let n4 = [k, 0, k, 0]; let n5 = [0, k, k, 0];
	let p1 = sh.SHEval3(n1[0],n1[1],n1[2]);
	let p2 = sh.SHEval3(n2[0],n2[1],n2[2]);
	let p3 = sh.SHEval3(n3[0],n3[1],n3[2]);
	let p4 = sh.SHEval3(n4[0],n4[1],n4[2]);
	let p5 = sh.SHEval3(n5[0],n5[1],n5[2]);
	let A_mat = math.matrix([[p1[4],p1[5],p1[6],p1[7],p1[8]],
		[p2[4],p2[5],p2[6],p2[7],p2[8]],
		[p3[4],p3[5],p3[6],p3[7],p3[8]],
		[p4[4],p4[5],p4[6],p4[7],p4[8]],
		[p5[4],p5[5],p5[6],p5[7],p5[8]]]
	);

	// 2、{P(ni)} - A  A_inverse
	let A_inverse_mat = math.inv(A_mat);

	// 3、用 R 旋转 ni - {R(ni)}
	let n1_rot = vec4.create();
	let n2_rot = vec4.create();
	let n3_rot = vec4.create();
	let n4_rot = vec4.create();
	let n5_rot = vec4.create();
	vec4.transformMat4(n1_rot, n1, rotationMatrix);
	vec4.transformMat4(n2_rot, n2, rotationMatrix);
	vec4.transformMat4(n3_rot, n3, rotationMatrix);
	vec4.transformMat4(n4_rot, n4, rotationMatrix);
	vec4.transformMat4(n5_rot, n5, rotationMatrix);

	// 4、R(ni) SH投影 - S
	let p1_rot = sh.SHEval3(n1_rot[0],n1_rot[1],n1_rot[2]);
	let p2_rot = sh.SHEval3(n2_rot[0],n2_rot[1],n2_rot[2]);
	let p3_rot = sh.SHEval3(n3_rot[0],n3_rot[1],n3_rot[2]);
	let p4_rot = sh.SHEval3(n4_rot[0],n4_rot[1],n4_rot[2]);
	let p5_rot = sh.SHEval3(n5_rot[0],n5_rot[1],n5_rot[2]);
	let S_mat = math.matrix([[p1_rot[4],p1_rot[5],p1_rot[6],p1_rot[7],p1_rot[8]],
		[p2_rot[4],p2_rot[5],p2_rot[6],p2_rot[7],p2_rot[8]],
		[p3_rot[4],p3_rot[5],p3_rot[6],p3_rot[7],p3_rot[8]],
		[p4_rot[4],p4_rot[5],p4_rot[6],p4_rot[7],p4_rot[8]],
		[p5_rot[4],p5_rot[5],p5_rot[6],p5_rot[7],p5_rot[8]],
	]
	);

	// 5、S*A_inverse
	result = math.multiply(S_mat,A_inverse_mat);
	return result;
}

在这里插入图片描述

function getRotationPrecomputeL(precompute_L, rotationMatrix){
	let rotMatBand1 = computeSquareMatrix_3by3(rotationMatrix);
	let rotMatBand2 = computeSquareMatrix_5by5(rotationMatrix);
	let result = [];
	for(let i = 0;i < 3;i++)
	{
		let rotSHBand1 = math.multiply(rotMatBand1, [precompute_L[i][1], precompute_L[i][2], precompute_L[i][3]]);
		let rotSHBand2 = math.multiply(rotMatBand2, [precompute_L[i][4], precompute_L[i][5], precompute_L[i][6],
			precompute_L[i][7], precompute_L[i][8]]);
		
		result[i] = mat3.fromValues(precompute_L[i][0], rotSHBand1._data[0], rotSHBand1._data[1],
			rotSHBand1._data[2], rotSHBand2._data[0], rotSHBand2._data[1], 
			rotSHBand2._data[2], rotSHBand2._data[3], rotSHBand2._data[4]); 
	}
	return result;
}

在这里插入图片描述

在这里插入图片描述
已经有环境光照了。

let RGBMat3 = getMat3ValueFromRGB(precomputeL[guiParams.envmapId]);

// Bonus - Fast Spherical Harmonic Rotation
let precomputeL_RGBMat3 = getRotationPrecomputeL(RGBMat3, cameraModelMatrix);

这里在WebGLRenderer里对输入环境光格式做一下处理

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值