frag_color phong_tangent_space_shader::fragment( const vec3& bary, const mat3& verts, const mat3x2& tex_coords, const mat3& vert_norms) const { auto uv = bary_lerp(tex_coords[0], tex_coords[1], tex_coords[2], bary); auto objspace_norm = bary_lerp(vert_norms[0], vert_norms[1], vert_norms[2], bary); auto ts_normval = normalmap.get_from_ratio(uv[0], uv[1]); auto tanspace_norm = normalize(vec3(ts_normval.r - 127.5, ts_normval.g - 127.5, ts_normval.b - 127.5)); // objspace and texture space verts auto o1 = verts[1] - verts[0]; auto o2 = verts[2] - verts[0]; auto t1 = tex_coords[1] - tex_coords[0]; auto t2 = tex_coords[2] - tex_coords[0]; auto tanspace_mat = mat2(t1.x, t2.x, t1.y, t2.y); auto objspace_mat = mat3x2(o1.x, o2.x, o1.y, o2.y, o1.z, o2.z); // S * t1.x + T * t1.y = o1 // S * t2.x + T * t2.y = o2 // // [t1.x t1.y] * [tan = [o1.x o1.y o1.z] // t2.x t2.y] bitan] o2.x o2.y o2.z] // // tanspace_mat * tan_bitan_mat = objspace_mat // inverse(tanspace_mat) * tanspace_mat * tan_bitan_mat = inverse(tanspace_mat) * objspace_mat // I * tan_bitan_mat = inverse(tansapce_mat) * objspace_mat // tan_bitan_mat = inverse(tanspace_mat) * objspace_mat auto tan_bitan_mat = transpose(inverse(tanspace_mat) * objspace_mat); auto tan_to_objspace = mat3(normalize(tan_bitan_mat[0]), normalize(tan_bitan_mat[1]), normalize(objspace_norm)); auto norm = normalize(tan_to_objspace * tanspace_norm); // ambient color TGAColor ambient(5, 5, 5, 255); // specular color auto spec_val = specular.get_from_ratio(uv[0], uv[1]).raw[0]; auto r = normalize(reflect(light_dir(), norm)); auto spec_intensity = pow(max(0.0f, dot(r, to_cam)), spec_val); // diffuse color float diff_intensity = max(0.0f, dot(to_light(), norm)); auto diff_color = diffuse.get_from_ratio(uv[0], uv[1]); diff_color.scale(diff_intensity + spec_intensity * .6); return frag_color {ambient + diff_color, true}; }
void GuiMeshRender::ProcessEntities(const EntityMap &entities) { if (entities.empty()) { //printf("Warning: GuiMeshRender: Entity list is empty\n"); return; } EntityMap::const_iterator it, ite; GuiMeshPtr mesh; TransformPtr transform; mat4 model, view, projection, model_view, mvp; mat3 normal; // warning: make sure the values here are all floats projection = glm::ortho(0.0f, 800.0f, 600.0f, 0.0f, -1.0f, 1.0f); for (it = entities.begin(), ite = entities.end(); it != ite; ++it) { mesh = gui_mesh_mapper_(it->second); transform = transform_mapper_(it->second); model = transform->world(); model_view = model; // camera does not need to effect this mvp = projection * model_view; normal = inverse(transpose(mat3(model_view))); shared_ptr<BasicMaterial> material = boost::dynamic_pointer_cast<BasicMaterial>(mesh->material); vec4 light_pos = material->light_position_; // hack to have light move with world // todo: implement light as entity material->light_position_ = model_view * light_pos; // do things like setup colors and lights // and attach shader program mesh->material->PreRender(); material->light_position_ = light_pos; // push matrices up mesh->material->PushMatrices(model_view, projection, mvp, normal); // call draw mesh->geometry->Draw(); // let go of shader program mesh->material->PostRender(); } }