Vector4 Shading(const Vector3 &pos, const Vector3 &normal, const Material &mat, const Light &light) { // 光线方向,由物体指向光源 Vector3 L = light.position - pos; // 光源距离 float dist = L.Magnitude(); L.SetNormalize(); // 光强,按点光源计算 float I = 1.0f / (light.attenuation0 + light.attenuation1 * dist + light.attenuation2 * dist * dist); // 环境光 Vector4 amb_color = light.ambient * mat.ambient * I; amb_color = clamp(amb_color, 0.0f, 1.0f); Vector3 N = normal; N.SetNormalize(); // 顶点法线 float light_angle = DotProduct(L, N); light_angle = max_t(light_angle, 0.0f); // 漫反射 Vector4 diff_color = light.diffuse * mat.diffuse * light_angle * I; diff_color = clamp(diff_color, 0.0f, 1.0f); // 观察方向(相机空间) Vector3 V = -pos; V.SetNormalize(); // 半角向量 Vector3 H = L + V; H.SetNormalize(); // 镜面反射 float view_angle = DotProduct(H, N); view_angle = max_t(view_angle, 0.0f); Vector4 spec_color = light.specular * mat.specular * powf(view_angle, mat.specular.w) * I; spec_color = clamp(spec_color, 0.0f, 1.0f); Vector4 ret = amb_color + diff_color + spec_color; return ret; }
void Renderer::Lighting(void) { if (shading_mode_ == kFrame || shading_mode_ == kNoLightingEffect) { return; } else if (shading_mode_ == kFlat) { assert(light_); if (!light_) return; for (int i = 2; i < rend_primitive_.size; i += 3) { // 假设为三角形 if ((i + 1) % 3 != 0) continue; Vector3 p0 = rend_primitive_.vertexs[i - 2].position.GetVector3(); Vector3 p1 = rend_primitive_.vertexs[i - 1].position.GetVector3(); Vector3 p2 = rend_primitive_.vertexs[i].position.GetVector3(); Vector3 pos = (p0 + p1 + p2) * (1.0f / 3.0f); Vector3 e0 = p1 - p0; Vector3 e1 = p2 - p1; Vector3 normal = CrossProduct(e0, e1); normal.SetNormalize(); Vector4 color = Shading(pos, normal, *mat_, *light_); rend_primitive_.vertexs[i - 2].color = color; rend_primitive_.vertexs[i - 1].color = color; rend_primitive_.vertexs[i].color = color; } } else if (shading_mode_ == kGouraud) { assert(light_); if (!light_) return; for (int i = 0; i < rend_primitive_.size; ++i) { // 顶点位置 const Vector3 pos = rend_primitive_.vertexs[i].position.GetVector3(); const Vector3 &normal = rend_primitive_.vertexs[i].normal; Vector4 color = Shading(pos, normal, *mat_, *light_); rend_primitive_.vertexs[i].color = color; } } else if (shading_mode_ == kPhong) { for (int i = 0; i < rend_primitive_.size; ++i) { // 记录物体原来的位置 rend_primitive_.vertexs[i].global_pos = rend_primitive_.vertexs[i].position.GetVector3(); } return; } }
/* v0 /\ / \ / \ / \ / \ v2 ------------ v1 */ void Renderer::DiffTriangleUp(const RendVertex &v0, const RendVertex &v1, const RendVertex &v2) { float dy = v1.position.y - v0.position.y; float dx_left = (v2.position.x - v0.position.x) / dy; float dx_right = (v1.position.x - v0.position.x) / dy; float done_over_z_left = (1.0f / v2.position.w - 1.0f / v0.position.w) / dy; float done_over_z_right = (1.0f / v1.position.w - 1.0f / v0.position.w) / dy; Vector4 dc_left = (v2.color - v0.color) / dy; Vector4 dc_right = (v1.color - v0.color) / dy; // 透视差值uv Vector2 uv_over_z_top = v0.uv / v0.position.w; Vector2 uv_over_z_left = v2.uv / v2.position.w; Vector2 uv_over_z_right = v1.uv / v1.position.w; Vector2 duv_over_z_left = (uv_over_z_left - uv_over_z_top) / dy; Vector2 duv_over_z_right = (uv_over_z_right - uv_over_z_top) / dy; // 仿射映射差值uv Vector2 duv_left = (v2.uv - v0.uv) / dy; Vector2 duv_right = (v1.uv - v0.uv) / dy; // 对法线差值 Vector3 dnormal_left = (v2.normal - v0.normal) / dy; Vector3 dnormal_right = (v1.normal - v0.normal) / dy; // 对物体原来位置做差值 Vector3 dpos_left = (v2.global_pos - v0.global_pos) / dy; Vector3 dpos_right = (v1.global_pos - v0.global_pos) / dy; float x_begin = v0.position.x; float x_end = v0.position.x; float one_over_z_begin = 1.0f / v0.position.w; float one_over_z_end = 1.0f / v0.position.w; Vector4 color_begin = v0.color; Vector4 color_end = v0.color; Vector2 uv_over_z_begin = uv_over_z_top; Vector2 uv_over_z_end = uv_over_z_top; Vector2 uv_begin = v0.uv; Vector2 uv_end = v0.uv; Vector3 normal_begin = v0.normal; Vector3 normal_end = v0.normal; Vector3 pos_begin = v0.global_pos; Vector3 pos_end = v0.global_pos; int y = (int)v0.position.y; if (y < 0) { float d = -v0.position.y; x_begin += dx_left * d; x_end += dx_right * d; one_over_z_begin += done_over_z_left * d; one_over_z_end += done_over_z_right * d; color_begin += dc_left * d; color_end += dc_right * d; uv_over_z_begin += duv_over_z_left * d; uv_over_z_end += duv_over_z_right * d; uv_begin += duv_left * d; uv_end += duv_right * d; normal_begin += dnormal_left * d; normal_end += dnormal_right * d; pos_begin += dpos_left * d; pos_end += dpos_right * d; y = 0; } int bumpmap_width = 0; int bumpmap_height = 0; float s1 = v1.uv.u - v0.uv.u; float s2 = v2.uv.u - v0.uv.u; float t1 = v1.uv.v - v0.uv.v; float t2 = v2.uv.v - v0.uv.v; float div = s1 * t2 - s2 * t1; Vector3 Q1 = v1.position.GetVector3() - v0.position.GetVector3(); Vector3 Q2 = v2.position.GetVector3() - v0.position.GetVector3(); Vector3 B = (s2 * Q1 - s1 * Q2) / div; B.SetNormalize(); Vector3 T = (t2 * Q1 - t1 * Q2) / div; T.SetNormalize(); if (bumpmap_ && shading_mode_ == kPhong) { bumpmap_width = bumpmap_->get_width(); bumpmap_height = bumpmap_->get_height(); } // floor v1.position.y for (; y < min_t((int)v1.position.y, height_); ++y) { int x = (int)x_begin; float done_over_z = (one_over_z_begin - one_over_z_end) / (x_begin - x_end); float one_over_z = one_over_z_begin; Vector4 dc = (color_begin - color_end) / (x_begin - x_end); Vector4 c = color_begin; Vector2 duv_over_z = (uv_over_z_begin - uv_over_z_end) / (x_begin - x_end); Vector2 uv_over_z = uv_over_z_begin; Vector2 duv = (uv_begin - uv_end) / (x_begin - x_end); Vector2 uv = uv_begin; Vector3 dnormal = (normal_begin - normal_end) / (x_begin - x_end); Vector3 normal = normal_begin; Vector3 dpos = (pos_begin - pos_end) / (x_begin - x_end); Vector3 pos = pos_begin; if (x_begin < 0) { one_over_z += done_over_z * (-x_begin); c += dc * (-x_begin); uv_over_z += duv_over_z * (-x_begin); uv += duv * (-x_begin); normal += dnormal * (-x_begin); pos += dpos * (-x_begin); x = 0; } // floor x_end for (; x < min_t((int)(x_end), width_); ++x, one_over_z += done_over_z, c += dc, uv += duv, uv_over_z += duv_over_z, normal += dnormal, pos += dpos) { // 1/z buffer float prev_one_over_z = get_one_over_z_buffer(x, y); if (one_over_z < prev_one_over_z) continue; set_one_over_z_buffer(x, y, one_over_z); if (shading_mode_ == kPhong) { if (bumpmap_) { int x = uv.x * (bumpmap_width - 3) + 1; int y = uv.y * (bumpmap_height - 3) + 1; // uint8 off_x = bumpmap_->GetDumpData(x + 1, y) - bumpmap_->GetDumpData(x - 1, y); // uint8 off_y = bumpmap_->GetDumpData(x, y + 1) - bumpmap_->GetDumpData(y, y - 1); // normal += (off_x / 255.0f) * B + (off_y / 255.0f) * T; } // Phong着色时,c每次重新计算 c = Shading(pos, normal, *mat_, *light_); } Vector4 cvtex(1.0f, 1.0f, 1.0f, 1.0f); if (texture_) { Vector2 uv_ = uv; if (diff_perspective) { uv_ = uv_over_z / one_over_z; } uv_.u = clamp(uv_.u, 0.0f, 1.0f); uv_.v = clamp(uv_.v, 0.0f, 1.0f); cvtex = texture_->GetDataUV(uv_.u, uv_.v); } uint32 cl = vector4_to_ARGB32(clamp(c * cvtex, 0.0f, 1.0f)); set_pixel(x, y, cl); } x_begin += dx_left; x_end += dx_right; one_over_z_begin += done_over_z_left; one_over_z_end += done_over_z_right; color_begin += dc_left; color_end += dc_right; uv_over_z_begin += duv_over_z_left; uv_over_z_end += duv_over_z_right; uv_begin += duv_left; uv_end += duv_right; normal_begin += dnormal_left; normal_end += dnormal_right; pos_begin += dpos_left; pos_end += dpos_right; } }
// rend_primitive 相机空间 void Renderer::ModelViewTransform(const Matrix44 &model_view) { Matrix33 normal_trans = model_view.GetMatrix33(); normal_trans.SetInverse(); normal_trans.SetTranspose(); // 转换灯光位置 if (light_) { Vector4 pl; pl.SetVector3(light_->position); pl.w = 1.0f; pl = pl * model_view; light_pos_ = pl.GetVector3(); } #if 0 for (int i = 0; i < rend_primitive_.size; ++i) { if (((i + 1) % 3) == 0) { Vector3 p0 = rend_primitive_.vertexs[i - 2].position.GetVector3(); Vector3 p1 = rend_primitive_.vertexs[i - 1].position.GetVector3(); Vector3 p2 = rend_primitive_.vertexs[i].position.GetVector3(); Vector3 e0 = p0 - p1; Vector3 e1 = p1 - p2; Vector3 n = rend_primitive_.vertexs[i-1].normal; float dot = DotProduct(e0, n); // Logger::GtLogInfo("before:0\t%f", dot); assert(equalf(dot, 0, 0.001)); dot = DotProduct(e1, n); // Logger::GtLogInfo("before:1\t%f", dot); assert(equalf(dot, 0, 0.001)); } } #endif for (int i = 0; i < rend_primitive_.size; ++i) { Vector4 &position = rend_primitive_.vertexs[i].position; position = position * model_view; Vector3 &normal = rend_primitive_.vertexs[i].normal; normal = normal * normal_trans; normal.SetNormalize(); } #if 0 for (int i = 0; i < rend_primitive_.size; ++i) { if (((i + 1) % 3) == 0) { Vector4 p0 = rend_primitive_.vertexs[i - 2].position; Vector4 p1 = rend_primitive_.vertexs[i - 1].position; Vector4 p2 = rend_primitive_.vertexs[i].position; Vector3 e0 = (p0 - p1).GetVector3(); Vector3 e1 = (p1 - p2).GetVector3(); Vector3 N = CrossProduct(e0, e1); N.SetNormalize(); float dot = DotProduct(N, e0); Logger::GtLogInfo("dot e0 \t%f", dot); dot = DotProduct(N, e1); Logger::GtLogInfo("dot e1 \t%f", dot); Vector3 n0 = rend_primitive_.vertexs[i - 2].normal; Vector3 n1 = rend_primitive_.vertexs[i - 1].normal; Vector3 n2 = rend_primitive_.vertexs[i].normal; Vector3 zero = CrossProduct(N, n1); zero.Display(); dot = DotProduct(e0, n0); Logger::GtLogInfo("after:0\t%f", dot); dot = DotProduct(e1, n0); Logger::GtLogInfo("after:1\t%f", dot); } } #endif }