# [图形学笔记系列] 实现一个简单的软光栅渲染效果-03

·  阅读 306

## 实践部分

### 这一部分的代码

function barycentric(A, B, C, P) {
let s = []
for(let i = 0; i < 2; i++) {
let tmp = glMatrix.vec3.create()
tmp[0] = C[i]-A[i]
tmp[1] = B[i]-A[i]
tmp[2] = A[i]-P[i]
s.push(tmp)
}

let u = glMatrix.vec3.create()
glMatrix.vec3.cross(u, s[0], s[1])

if ( Math.floor(Math.abs(u[2])) != 0 ) {
let result = glMatrix.vec3.fromValues(1-(u[0]+u[1])/u[2], u[1]/u[2], u[0]/u[2])
return result
}

return glMatrix.vec3.fromValues(-1, -1, -1)

}

function triangle_raster(pts, uvs, normals, light_dir, zBuffer, width, getTexture, fragementShader, drawPixel) {
let bboxmin = [Infinity, Infinity]
let bboxmax = [-Infinity, -Infinity]
for(let i = 0; i < 3; i++) {               //找到三角形面的边框
for(let j = 0; j < 2; j++) {
bboxmin[j] = Math.min(bboxmin[j], pts[i][j])
bboxmax[j] = Math.max(bboxmax[j], pts[i][j])
}
}

let p = glMatrix.vec2.create()

for (p[0] = Math.floor(bboxmin[0]); p[0] <= bboxmax[0]; p[0]++) {
for(p[1] = Math.floor(bboxmin[1]); p[1] <= bboxmax[1]; p[1]++) {
let c = barycentric(pts[0], pts[1], pts[2], p) //由重心坐标得到的权值

let z = pts[0][2]*c[0] + pts[1][2]*c[1] + pts[2][2]*c[2]  //插值出P的深度值

if (c[0] < 0 || c[1] < 0 || c[2] < 0 || zBuffer[Math.floor(p[0]) + Math.floor(p[1])*width] > z)
continue;

zBuffer[Math.floor(p[0]) + Math.floor(p[1])* width] = z;

let uv = glMatrix.vec3.create()           //插值出P的uv坐标
glMatrix.vec3.transformMat3(uv, c, uvs)

let normal = glMatrix.vec3.create()       //插值出P的法线向量
glMatrix.vec3.normalize(normal, normal)
glMatrix.vec3.transformMat3(normal, c, normals)

glMatrix.vec3.normalize(light_dir, light_dir)
drawPixel(p[0], p[1], fragementShader(uv, getTexture, normal, light_dir))
}
}
}

let color = texture(uv)
let intensity = glMatrix.vec3.dot(normal, light_dir)
glMatrix.vec3.scale(color, color, intensity)
return color
}

### 实现一个简单的软光栅渲染效果的源码和数据

github.com/yangla2zhen…

## 参考资料

GAMES101-现代计算机图形学入门-闫令琪

Fundamentals of Computer Graphics, Fourth Edition

Tiny renderer or how OpenGL works: software rendering in 500 lines of code