// ---------------------------------------------------------------------------- // Generates a opacity map from the transfer function specification // ---------------------------------------------------------------------------- void mapOpacity(Image3D<float> & map, std::list<std::shared_ptr<Node>> transfer) { float samples = static_cast<float>(map.width()) - 1; auto buffer = map.data(); memset(buffer, 0, map.size()*sizeof(float)); auto iter = transfer.begin(); auto curr = *iter; iter++; while (iter != transfer.end()) { auto next = *iter; size_t x1 = static_cast<size_t>(curr->density * samples); if (x1 >= map.width()) x1 = map.width()-1; size_t x2 = static_cast<size_t>(next->density * samples); if (x2 >= map.width()) x2 = map.width()-1; float y1 = curr->material->opticalThickness; float y2 = next->material->opticalThickness; for (size_t i = x1; i <= x2; i++) { float px = i / samples - curr->density; float py = next->density - curr->density; float part = low( high(px / py, 0.0f), 1.0f ); buffer[i] = - logf( 1.f - (1.f - part) * y1 - part * y2 ); } curr = next; iter++; } }
// ---------------------------------------------------------------------------- // Generates a diffuse map from the transfer function specification // ---------------------------------------------------------------------------- void mapSpecular(Image3D<Vector<UInt8,4>> & map, std::list<std::shared_ptr<Node>> transfer) { float samples = static_cast<float>(map.width()) - 1; auto buffer = map.data(); memset(buffer, 0, map.size()*sizeof(Vector<UInt8,4>)); auto iter = transfer.begin(); auto curr = *iter; iter++; while (iter != transfer.end()) { auto next = *iter; size_t x1 = static_cast<size_t>(curr->density * samples); if (x1 >= map.width()) x1 = map.width()-1; size_t x2 = static_cast<size_t>(next->density * samples); if (x2 >= map.width()) x2 = map.width()-1; Vector3f s1(curr->material->specular); Vector3f s2(next->material->specular); Vector4f y1(s1[0], s1[1], s1[2], curr->material->glossiness*255.0f); Vector4f y2(s2[0], s2[1], s2[2], next->material->glossiness*255.0f); for (size_t i = x1; i <= x2; i++) { float px = i / samples - curr->density; float py = next->density - curr->density; float part = low( high(px / py, 0.0f), 1.0f ); buffer[i] = static_cast<Vector<UInt8,4>>(y1*(1.f - part) + y2*part); } curr = next; iter++; } }
// ---------------------------------------------------------------------------- // Generates an emissive map from the tranfer specification // ---------------------------------------------------------------------------- void mapEmissive(Image3D<Vector4f> & map, std::list<std::shared_ptr<Node>> transfer) { float samples = static_cast<float>(map.width()) - 1; auto buffer = map.data(); memset(buffer, 0, map.size()*sizeof(Vector4f)); auto iter = transfer.begin(); auto curr = *iter; iter++; while (iter != transfer.end()) { auto next = *iter; size_t x1 = static_cast<size_t>(curr->density * samples); if (x1 >= map.width()) x1 = map.width()-1; size_t x2 = static_cast<size_t>(next->density * samples); if (x2 >= map.width()) x2 = map.width()-1; Vector3f s1 = Vector3f(curr->material->emissive) / 255.0f * curr->material->emissiveStrength; Vector3f s2 = Vector3f(next->material->emissive) / 255.0f * curr->material->emissiveStrength; Vector4f y1(s1[0], s1[1], s1[2], 0.0f); Vector4f y2(s2[0], s2[1], s2[2], 0.0f); for (size_t i = x1; i <= x2; i++) { float px = i / samples - curr->density; float py = next->density - curr->density; float part = low( high(px / py, 0.0f), 1.0f ); buffer[i] = y1*(1.f - part) + y2*part; } curr = next; iter++; } }