float MicrofacetBRDF::evaluatePDFInternal(const BSDFQuery &query, const Vector3D &dir, float* revPDF) const { if (dir.z * query.dir_sn.z <= 0) { if (revPDF) *revPDF = 0.0f; return 0.0f; } bool entering = query.dir_sn.z >= 0.0f; int32_t sign = entering ? 1 : -1; Normal3D m = sign * halfVector(query.dir_sn, dir); float dotHV = dot(query.dir_sn, m); if (dotHV * sign <= 0) { if (revPDF) *revPDF = 0.0f; return 0.0f; } float mPDF = m_D->evaluatePDF(sign * query.dir_sn, m); float commonPDFTerm = 1.0f / (4 * dotHV * sign); float ret = commonPDFTerm * mPDF; SLRAssert(!std::isnan(commonPDFTerm) && !std::isinf(commonPDFTerm) && !std::isnan(mPDF) && !std::isinf(mPDF), "commonPDFTerm: %g, mPDF: %g, wlIdx: %u, qDir: %s, dir: %s", commonPDFTerm, mPDF, query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (revPDF) *revPDF = commonPDFTerm * m_D->evaluatePDF(sign * dir, m); return ret; }
SampledSpectrum MicrofacetBRDF::evaluateInternal(const BSDFQuery &query, const Vector3D &dir, SampledSpectrum* rev_fs) const { if (dir.z * query.dir_sn.z <= 0) { if (rev_fs) *rev_fs = SampledSpectrum::Zero; return SampledSpectrum::Zero; } bool entering = query.dir_sn.z >= 0.0f; int32_t sign = entering ? 1 : -1; Normal3D m = sign * halfVector(query.dir_sn, dir); float dotHV = dot(query.dir_sn, m); float D = m_D->evaluate(m); SampledSpectrum F = m_F.evaluate(dotHV); float G = m_D->evaluateSmithG1(query.dir_sn, m) * m_D->evaluateSmithG1(dir, m); SampledSpectrum fs = F * D * G / (4 * query.dir_sn.z * dir.z); SLRAssert(!fs.hasInf() && !fs.hasNaN(), "fs: %s, F: %s, G, %g, D: %g, wlIdx: %u, qDir: %s, dir: %s", fs.toString().c_str(), F.toString().c_str(), G, D, query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (rev_fs) *rev_fs = fs; return fs; }
void SceneBump::setup_model_height() { static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-height.vert"); static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-height.frag"); static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f); Model model; if(!model.load("asteroid-low")) return; model.calculate_normals(); /* Calculate the half vector */ LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z()); halfVector.normalize(); halfVector += LibMatrix::vec3(0.0, 0.0, 1.0); halfVector.normalize(); std::vector<std::pair<Model::AttribType, int> > attribs; attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypePosition, 3)); attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeNormal, 3)); attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeTexcoord, 2)); attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeTangent, 3)); model.convert_to_mesh(mesh_, attribs); /* Load shaders */ ShaderSource vtx_source(vtx_shader_filename); ShaderSource frg_source(frg_shader_filename); /* Add constants to shaders */ frg_source.add_const("LightSourcePosition", lightPosition); frg_source.add_const("LightSourceHalfVector", halfVector); frg_source.add_const("TextureStepX", 1.0 / 1024.0); frg_source.add_const("TextureStepY", 1.0 / 1024.0); if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { return; } std::vector<GLint> attrib_locations; attrib_locations.push_back(program_["position"].location()); attrib_locations.push_back(program_["normal"].location()); attrib_locations.push_back(program_["texcoord"].location()); attrib_locations.push_back(program_["tangent"].location()); mesh_.set_attrib_locations(attrib_locations); Texture::load(GLMARK_DATA_PATH"/textures/asteroid-height-map.png", &texture_, GL_NEAREST, GL_NEAREST, 0); }
SampledSpectrum MicrofacetBSDF::evaluateInternal(const BSDFQuery &query, const Vector3D &dir, SampledSpectrum* rev_fs) const { bool entering = query.dir_sn.z >= 0.0f; int32_t sign = entering ? 1 : -1; float dotNVdotNL = dir.z * query.dir_sn.z; if (dotNVdotNL > 0 && query.flags.matches(DirectionType::Reflection | DirectionType::AllFreq)) { Normal3D m = sign * halfVector(query.dir_sn, dir); float dotHV = dot(query.dir_sn, m); float D = m_D->evaluate(m); SampledSpectrum F = m_F.evaluate(dotHV); float G = m_D->evaluateSmithG1(query.dir_sn, m) * m_D->evaluateSmithG1(dir, m); SampledSpectrum fs = F * D * G / (4 * dotNVdotNL); SLRAssert(!fs.hasInf() && !fs.hasNaN(), "fs: %s, F: %s, G, %g, D: %g, wlIdx: %u, qDir: %s, dir: %s", fs.toString().c_str(), F.toString().c_str(), G, D, query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (rev_fs) *rev_fs = fs; return fs; } else if (dotNVdotNL < 0 && query.flags.matches(DirectionType::Transmission | DirectionType::AllFreq)) { const SampledSpectrum &eEnter = entering ? m_F.etaExt() : m_F.etaInt(); const SampledSpectrum &eExit = entering ? m_F.etaInt() : m_F.etaExt(); SampledSpectrum ret = SampledSpectrum::Zero; for (int wlIdx = 0; wlIdx < SampledSpectrum::NumComponents; ++wlIdx) { Normal3D m_wl = normalize(-(eEnter[wlIdx] * query.dir_sn + eExit[wlIdx] * dir)); float dotHV_wl = dot(query.dir_sn, m_wl); float dotHL_wl = dot(dir, m_wl); float F_wl = m_F.evaluate(dotHV_wl, wlIdx); float G_wl = m_D->evaluateSmithG1(query.dir_sn, m_wl) * m_D->evaluateSmithG1(dir, m_wl); float D_wl = m_D->evaluate(m_wl); ret[wlIdx] = std::fabs(dotHV_wl * dotHL_wl) * (1 - F_wl) * G_wl * D_wl / std::pow(eEnter[wlIdx] * dotHV_wl + eExit[wlIdx] * dotHL_wl, 2); SLRAssert(!std::isnan(ret[wlIdx]) && !std::isinf(ret[wlIdx]), "fs: %g, F: %g, G, %g, D: %g, wlIdx: %u, qDir: %s, dir: %s", ret[wlIdx], F_wl, G_wl, D_wl, query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); } ret /= std::fabs(dotNVdotNL); ret *= query.adjoint ? (eExit * eExit) : (eEnter * eEnter);// !adjoint: eExit^2 * (eEnter / eExit)^2 SLRAssert(!ret.hasInf() && !ret.hasNaN(), "fs: %s, wlIdx: %u, qDir: %s, dir: %s", ret.toString().c_str(), query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (rev_fs) *rev_fs = ret; return ret; } if (rev_fs) *rev_fs = SampledSpectrum::Zero; return SampledSpectrum::Zero; }
float MicrofacetBSDF::evaluatePDFInternal(const BSDFQuery &query, const Vector3D &dir, float* revPDF) const { bool entering = query.dir_sn.z >= 0.0f; int32_t sign = entering ? 1 : -1; float dotNVdotNL = dir.z * query.dir_sn.z; if (dotNVdotNL == 0) return 0.0f; const SampledSpectrum &eEnter = entering ? m_F.etaExt() : m_F.etaInt(); const SampledSpectrum &eExit = entering ? m_F.etaInt() : m_F.etaExt(); Normal3D m; if (dotNVdotNL > 0) m = sign * halfVector(query.dir_sn, dir); else m = normalize(-(eEnter[query.wlHint] * query.dir_sn + eExit[query.wlHint] * dir)); float dotHV = dot(query.dir_sn, m); if (dotHV * sign <= 0) { if (revPDF) *revPDF = 0.0f; return 0.0f; } float mPDF = m_D->evaluatePDF(sign * query.dir_sn, m); SampledSpectrum F = m_F.evaluate(dotHV); float reflectProb = F.importance(query.wlHint); if (query.flags.isReflection()) reflectProb = 1.0f; if (query.flags.isTransmission()) reflectProb = 0.0f; if (dotNVdotNL > 0) { float commonPDFTerm = reflectProb / (4 * dotHV * sign); SLRAssert(!std::isnan(commonPDFTerm) && !std::isinf(commonPDFTerm) && !std::isnan(mPDF) && !std::isinf(mPDF), "commonPDFTerm: %g, mPDF: %g, F: %s, wlIdx: %u, qDir: %s, dir: %s", commonPDFTerm, mPDF, F.toString().c_str(), query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (revPDF) *revPDF = commonPDFTerm * m_D->evaluatePDF(sign * dir, m); return commonPDFTerm * mPDF; } else { float dotHL = dot(dir, m); float commonPDFTerm = (1 - reflectProb) / std::pow(eEnter[query.wlHint] * dotHV + eExit[query.wlHint] * dotHL, 2); SLRAssert(!std::isnan(commonPDFTerm) && !std::isinf(commonPDFTerm) && !std::isnan(mPDF) && !std::isinf(mPDF), "commonPDFTerm: %g, mPDF: %g, F: %s, wlIdx: %u, qDir: %s, dir: %s", commonPDFTerm, mPDF, F.toString().c_str(), query.wlHint, query.dir_sn.toString().c_str(), dir.toString().c_str()); if (revPDF) *revPDF = commonPDFTerm * m_D->evaluatePDF(-sign * dir, m) * eEnter[query.wlHint] * eEnter[query.wlHint] * std::fabs(dotHV); return commonPDFTerm * mPDF * eExit[query.wlHint] * eExit[query.wlHint] * std::fabs(dotHL); } }
rgbColor newWard::f(const vec3& wo, const vec3& wi) const{ if(wo.y*wi.y < 0.f){ return rgbColor(0.f); } const vec3 wh = halfVector(wo, wi); const float meanX = wh.x / alpha; const float meanZ = wh.z / beta; return Rs * exp( -(meanX*meanX + meanZ*meanZ) / (wh.y*wh.y)) / (4.f * PI * alpha * beta * sqrt(wo.y*wi.y)); }
rgbColor substrate::f(const vec3& wo, const vec3& wi) const{ const rgbColor diffuse = ecTerm * (1.f - pow(1.f - bsdf::cosTheta(wo) * 0.5f, 5)) * (1.f - pow(1.f - bsdf::cosTheta(wi) * 0.5f, 5)); const vec3 wh = halfVector(wo, wi); const float wiDotWh = abs(dot(wi, wh)); const rgbColor specular = (distrib->D(wh) * schlickFresnel(Rs, wiDotWh)) / (8.f * PI * wiDotWh * std::max(bsdf::cosTheta(wo), bsdf::cosTheta(wi))); return diffuse + specular; }
void SceneBump::setup_model_plain(const std::string &type) { static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-poly.vert"); static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-poly.frag"); static const std::string low_poly_filename("asteroid-low"); static const std::string high_poly_filename("asteroid-high"); static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f); Model model; /* Calculate the half vector */ LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z()); halfVector.normalize(); halfVector += LibMatrix::vec3(0.0, 0.0, 1.0); halfVector.normalize(); std::string poly_filename = type == "high-poly" ? high_poly_filename : low_poly_filename; if(!model.load(poly_filename)) return; model.calculate_normals(); /* Tell the converter that we only care about position and normal attributes */ std::vector<std::pair<Model::AttribType, int> > attribs; attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypePosition, 3)); attribs.push_back(std::pair<Model::AttribType, int>(Model::AttribTypeNormal, 3)); model.convert_to_mesh(mesh_, attribs); /* Load shaders */ ShaderSource vtx_source(vtx_shader_filename); ShaderSource frg_source(frg_shader_filename); /* Add constants to shaders */ frg_source.add_const("LightSourcePosition", lightPosition); frg_source.add_const("LightSourceHalfVector", halfVector); if (!Scene::load_shaders_from_strings(program_, vtx_source.str(), frg_source.str())) { return; } std::vector<GLint> attrib_locations; attrib_locations.push_back(program_["position"].location()); attrib_locations.push_back(program_["normal"].location()); mesh_.set_attrib_locations(attrib_locations); }
float beckmann::pdf(const vec3& wo, const vec3& wi) const{ const vec3 wh = halfVector(wo, wi); return D(wh) / (4.f * abs(dot(wo, wh))); }