// ======================================================================== // // Copyright 2009-2013 Intel Corporation // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // // ======================================================================== // #pragma once /*! \file shapesampler.isph Implements sampling functions for different * geometric shapes. */ //inline float cos2sin(const float f) { return sqrt(max(0.f,1.f-f*f)); } //inline float sin2cos(const float f) { return sqrt(max(0.f,1.f-f*f)); } /*! Cosine weighted hemisphere sampling. Up direction is the z direction. */ inline Sample3f cosineSampleHemisphere(const float u, const float v) { const float phi = 2.0f * (M_PI) * u; const float cosTheta = sqrt(v); const float sinTheta = sqrt(1.0f - v); return make_Sample3f(make_Vec3f(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta), cosTheta*(1.f/(M_PI))); } /*! Cosine weighted hemisphere sampling. Up direction is provided as argument. */ inline Sample3f cosineSampleHemisphere(const float u, const float v, const Vec3f& N) { Sample3f s = cosineSampleHemisphere(u,v); return make_Sample3f(frame(N)*s.v,s.pdf); } /*! Samples hemisphere with power cosine distribution. Up direction * is the z direction. */ inline Sample3f powerCosineSampleHemisphere(const float u, const float v, const float _exp) { const float phi = 2.0f * (M_PI) * u; const float cosTheta = pow(v,1.0f/(_exp+1.0f)); const float sinTheta = cos2sin(cosTheta); return make_Sample3f(make_Vec3f(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta), (_exp+1.0f)*pow(cosTheta,_exp)*0.5f/(M_PI)); } /*! Computes the probability density for the power cosine sampling of the hemisphere. */ inline float powerCosineSampleHemispherePDF(const Vec3f& s, const float _exp) { if (s.z < 0.f) return 0.f; return (_exp+1.0f)*pow(s.z,_exp)*0.5f/M_PI; } /*! Samples hemisphere with power cosine distribution. Up direction * is provided as argument. */ inline Sample3f powerCosineSampleHemisphere(const float u, const float v, const Vec3f& N, const float _exp) { Sample3f s = powerCosineSampleHemisphere(u,v,_exp); return make_Sample3f(frame(N)*s.v,s.pdf); } //////////////////////////////////////////////////////////////////////////////// /// Sampling of Spherical Cone //////////////////////////////////////////////////////////////////////////////// /*! Uniform sampling of spherical cone. Cone direction is the z * direction. */ inline Sample3f UniformSampleCone(const float u, const float v, const float angle) { const float phi = (float)(2.0f * M_PI) * u; const float cosTheta = 1.0f - v*(1.0f - cos(angle)); const float sinTheta = cos2sin(cosTheta); return make_Sample3f(make_Vec3f(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta), 1.0f/((float)(4.0f*M_PI)*sqr(sin(0.5f*angle)))); } /*! Computes the probability density of uniform spherical cone sampling. */ inline float UniformSampleConePDF(const Vec3f &s, const float angle) { return select(s.z < cos(angle), 0.0f, 1.0f/((float)(4.0f*M_PI)*sqr(sin(0.5f*angle)))); } /*! Uniform sampling of spherical cone. Cone direction is provided as argument. */ inline Sample3f UniformSampleCone(const float u, const float v, const float angle, const Vec3f& N) { Sample3f s = UniformSampleCone(u,v,angle); return make_Sample3f(frame(N)*s.v,s.pdf); } /*! Computes the probability density of uniform spherical cone sampling. */ inline float UniformSampleConePDF(const Vec3f &s, const float angle, const Vec3f &N) { // return make_select(dot(s,N) < cos(angle), 0.0f, 1.0f/((float)(4.0f*M_PI)*sqr(sin(0.5f*angle)))); if (dot(s,N) < cos(angle)) return 0.f; else return 1.0f/((float)(4.0f*M_PI)*sqr(sin(0.5f*angle))); } //////////////////////////////////////////////////////////////////////////////// /// Sampling of Triangle //////////////////////////////////////////////////////////////////////////////// /*! Uniform sampling of triangle. */ inline Vec3f UniformSampleTriangle(const float u, const float v, const Vec3f& A, const Vec3f& B, const Vec3f& C) { const float su = sqrt(u); return C + (1.0f-su)*(A-C) + (v*su)*(B-C); } //////////////////////////////////////////////////////////////////////////////// /// Sampling of Disk //////////////////////////////////////////////////////////////////////////////// /*! Uniform sampling of disk. */ inline Vec2f UniformSampleDisk(const Vec2f &sample, const float radius) { const float r = sqrt(sample.x); const float theta = (2.f*M_PI) * sample.y; return make_Vec2f(radius*r*cos(theta), radius*r*sin(theta)); }