Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the irradiance Vector3 irradiance = (pLight->color() * pLight->wattage()) * std::max(0.0f, dot(hit.N, l)) / (4.0 * PI * falloff); L += irradiance * (m_kd / PI); } return L; }
Vector3 SpecularRefractionShading::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= m_kd; L += std::max(0.0f, nDotL / falloff * pLight->wattage() / PI) * result; Vector3 r = (-l + 2 * dot(l, hit.N) * hit.N).normalized(); float eDotR = dot(viewDir, r); eDotR = 0.0f > eDotR ? 0.0f : 1.0f < eDotR ? 1.0f : eDotR; // clamp it to [0..1] eDotR = pow(eDotR, 3); L += std::max(0.0f, eDotR * falloff * pLight->wattage()); } // add the ambient component L += m_ka; return L; }
Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene, int bounce) { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const PointLights *lightlist = scene.lights(); // loop over all of the lights PointLights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= m_kd; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * result; } // add the ambient component L += m_ka; return L; }
Vector3 Lambert::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); // reflectance if (m_ks != 0 && ray.times <3) { Vector3 Wr = -2 * dot(ray.d, hit.N) * hit.N + ray.d; Wr.normalize(); Ray r(hit.P + (EPSILON * Wr), Wr); HitInfo hi; r.times = ray.times + 1; if(scene.trace(hi, r)) L += m_spec * m_ks * hi.material->shade(r, hi, scene); } // cellular noise texture if(m_noisiness > 0) { float at[3] = { hit.P.x, hit.P.y, hit.P.z }; const long mO = 3; float F[mO]; float delta[mO][3]; unsigned long *ID = new unsigned long(); WorleyNoise::noise3D(at, mO, F, delta, ID); L += m_noisiness * (0.5f * (F[2] - F[1]));// + PerlinNoise::noise(at[0], at[1], at[2])); } // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Vector3 l = pLight->position() - hit.P; // the inverse-squared falloff float falloff = l.length2(); // normalize the light direction l /= sqrt(falloff); // get the diffuse component float nDotL = dot(hit.N, l); Vector3 result = pLight->color(); result *= f_diff * m_kd; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * result; // highlights //if (m_ks != 0) L += m_spec * pLight->color() * m_ks * max(0.f, pow(dot(viewDir, l), SPECULAR_CONST)); // / dot(hit.N, l); } // refraction if (m_trans != 0 && ray.times <3) { float n = (ray.times % 2 == 0) ? (ENV_INDEX / m_refInd) : (m_refInd / ENV_INDEX); float wn = dot(viewDir, hit.N); if (wn < 0) wn = -wn; Vector3 Wt = -1 * n * (viewDir - wn * hit.N) - sqrtf(1 - (n * n) * (1 - wn * wn)) * hit.N; Wt.normalize(); Ray r(hit.P + (EPSILON * Wt), Wt); r.times = ray.times + 1; HitInfo hi; if (scene.trace(hi, r)) L += m_trans * m_kt * hi.material->shade(r, hi, scene); } // add the ambient component L += m_ka; if(DO_BOUNCE && ray.times < BOUNCES) { float v = rand() / (float)RAND_MAX; float u = rand() / (float)RAND_MAX; Vector3 coord = hemisphereSample_cos(u,v); Vector3 unv = Vector3(rand() / (float)RAND_MAX, rand() / (float)RAND_MAX, rand() / (float)RAND_MAX); Vector3 v1 = cross(hit.N, unv); Vector3 v2 = cross(v1, hit.N); Vector3 dir = coord.x * v1 + coord.z * hit.N + coord.y * v2; dir.normalize(); Ray r(hit.P, dir); r.times = ray.times + 1; HitInfo hi; if(scene.trace(hi, r)) L+= m_kd * dot(r.d, hit.N) * hit.material->shade(r, hi, scene); } return L; }
Vector3 RefractiveInterface::shade(const Ray& ray, const HitInfo& hit, const Scene& scene, const bool& isFront) const { Ray rayLight; HitInfo hitLight; Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const PointLights *plightlist = scene.pointLights(); // loop over all of the POINT lights PointLights::const_iterator plightIter; for (plightIter = plightlist->begin(); plightIter != plightlist->end(); plightIter++) { PointLight* pLight = *plightIter; Vector3 l = pLight->position() - hit.P; rayLight.o = hit.P; rayLight.d = l.normalized(); Vector3 brdf = BRDF(rayLight.d, hit.N, -ray.d, isFront); if (brdf == 0) continue; if (scene.trace(hitLight, rayLight, 0.0001, l.length())) continue; // the inverse-squared falloff float falloff = l.length2(); float nDotL = fabs(dot(hit.N, l)); Vector3 result = pLight->color(); L += nDotL / falloff * pLight->wattage() *brdf * result; } const AreaLights *alightlist = scene.areaLights(); // loop over all of the lights AreaLights::const_iterator alightIter; for (alightIter = alightlist->begin(); alightIter != alightlist->end(); alightIter++) { AreaLight* aLight = *alightIter; vec3pdf vp = aLight->randPt(); Vector3 l = vp.v - hit.P; // shoot a shadow ray to a random point on the area light rayLight.o = hit.P; rayLight.d = l.normalized(); Vector3 brdf = BRDF(rayLight.d, hit.N, -ray.d, isFront); if (brdf == 0) continue; // if the shadow ray hits the "backside of the light" continue to the next area light if (!aLight->intersect(hitLight, rayLight)){ continue; } // if the shadow ray is occluded by another (hence the "skip") object continue the next light if (scene.trace(hitLight, rayLight, aLight, 0.0001, l.length())){ continue; } // the inverse-squared falloff float falloff = l.length2(); float nDotL = fabs(dot(hit.N, l)); Vector3 result = aLight->color(); L += std::max(0.0f, dot(hitLight.N, -l))* 0.0f, nDotL / falloff* aLight->wattage() / aLight->area() *brdf * result / (vp.p); } // add the ambient component L += m_ka; return L; }
//Blinn-Phong shading model Vector3 Specular::shade(Ray& ray, const HitInfo& hit, const Scene& scene) const { Vector3 reflected = Vector3(0.0f, 0.0f, 0.0f); Vector3 L = Vector3(0.0f, 0.0f, 0.0f); //scale down intensity of light in proportion to num of ray bounces Vector3 attenuation = k_s * ( 1 / (ray.numBounces+1)); const Lights *lightlist = scene.lights(); // loop over all of the lights Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { //find reflected vector, given normal and incident light direction PointLight* pLight = *lightIter; //light vector points from hit point to light Vector3 l = pLight->position() - hit.P; //why did we use ray.d here instead of l? Would just need to change calculation a bit //to use l reflected = ray.d - 2.0f * (dot(hit.N, ray.d)) * hit.N; if (ray.numBounces < maxBounces) { //trace from reflected vector now Ray reflect(ray.numBounces + 1); reflect.o = hit.P; reflect.d = reflected; HitInfo hitReflect; if (scene.trace(hitReflect, reflect, 0.008f)) { //get color from object hit //printf("Bounced reflected ray hit something!\n"); L += attenuation * hitReflect.material->shade(reflect, hitReflect, scene); } else { //get color from background L += Vector3(0,0,0.5f);//bgColor; } } //Get halfway vector Vector3 h = (L + -1 * ray.d).normalize(); Ray shadow_ray(0); HitInfo hi; shadow_ray.o = hit.P; shadow_ray.d = l; //std::cout<<"M = "<<M<< " hit.N = "<<hit.N<<std::endl; if (scene.trace(hi, shadow_ray, 0.001f, sqrt(l.length2()))) { // We are in shadow } else { //get color of light Vector3 color = pLight->color(); //flip vector from eye so points from hit point back to eye //L += k_s * color * pow(std::max(0.0f, dot(h, hit.N)), shinyExp); //L += attenuation * color * pow(std::max(0.0f, dot(reflected, -ray.d)), shinyExp); //Specular Highlights //This is separate from the reflection calculation because it //needs to be dependent on just the shinyExp //https://en.wikipedia.org/wiki/Specular_highlight //Specular calculation for ABSORBED light L += attenuation * pow(std::max(0.0f, dot(h, hit.N)), 50* shinyExp); //check entering or exiting and change n1/n2 n2/n1 //dot product ray.dot.normal //Specular Refraction //L += attenuation * color * pow(std::max(0.0f, dot(wt, -ray.d)), shinyExp); //std::cout<<"Final Refraction vector = "<<(k_s * color * pow(std::max(0.0f, //dot(wt,ray.d)), shinyExp))<<std::endl; } } return L; }
Vector3 Phong::shade(const Ray& ray, const HitInfo& rhit, const Scene& scene) const { Vector3 L = Vector3(0.0f, 0.0f, 0.0f); Vector3 randvect(randone(g_rng), randone(g_rng), randone(g_rng)); const Lights *lightlist = scene.lights(); HitInfo bm_hit = bumpHit(rhit); // loop over all of the lights Lights::const_iterator lightIter; Vector3 diffcolor = m_kd * m_texture_kd->shade(ray, bm_hit, scene); Vector3 speccolor = m_ks * m_texture_ks->shade(ray, bm_hit, scene); // float irrad[3]; // g_global_illum_map->irradiance_estimate(irrad, bm_hit.P.array(), bm_hit.N.array(), 1.f, 100); // L += Vector3(irrad) * diffcolor; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; float shadow_mul = 0.f; Vector3 tolight = pLight->position() - bm_hit.P; tolight.normalize(); Vector3 xaxis = randvect.cross(tolight); xaxis.normalize(); Vector3 yaxis = xaxis.cross(tolight); yaxis.normalize(); float xdisk, ydisk; do { xdisk = 1 - 2*randone(g_rng); ydisk = 1 - 2*randone(g_rng); } while (xdisk*xdisk + ydisk*ydisk > 1); Vector3 posinlight = pLight->position() + xdisk*pLight->sphere()*xaxis + ydisk*pLight->sphere()*yaxis; Ray lightray; lightray.d = (posinlight - bm_hit.P); float raylength = lightray.d.length(); float remaininglength = raylength; lightray.d /= raylength; lightray.o = bm_hit.P; while (true) { HitInfo lighthit; if (!scene.trace(lighthit, lightray, EPSILON, remaininglength)) { shadow_mul = 1; break; } if (lighthit.material->castShadow()) break; remaininglength -= lighthit.t; lightray.o = lighthit.P; } if (shadow_mul < EPSILON) continue; // Diffuse Vector3 result = pLight->color()*shadow_mul; // the inverse-squared falloff float falloff = raylength*raylength; // normalize the light direction float nDotL = dot(bm_hit.N, lightray.d); if (m_kd.max() > EPSILON) { L += std::max(0.0f, nDotL/falloff * pLight->wattage() / (4*PI)) * result * diffcolor; } if (m_ks.max() > EPSILON && nDotL > 0) { Vector3 refl = -lightray.d + 2*nDotL*bm_hit.N; L += std::max(0.f, powf((-ray.d).dot(refl), m_phong)) * result * speccolor * (1 - m_tp); //Vector3 half = -ray.d + hit.N; //half.normalize(); //L += std::max(0.f, powf(half.dot(hit.N), 1000)) * result * speccolor * m_sp; } } float caustic[3] = {0, 0, 0}; g_caustics_map->irradiance_estimate(caustic, bm_hit.P.array(), bm_hit.N.array(), 3.0f, 200); // TODO: customize these parameters Vector3 caustic_color(caustic); L += caustic_color; // Indirect diffuse sampling (method 2) if (m_indirect && m_kd.max() > EPSILON && ray.iter < MAX_RAY_ITER) { float theta = asinf((randone(g_rng))); float phi = 2 * PI * randone(g_rng); Vector3 const &yaxis = bm_hit.N; Vector3 xaxis = yaxis.cross(randvect); xaxis.normalize(); Vector3 zaxis = yaxis.cross(xaxis); zaxis.normalize(); Ray diffuse_ray; diffuse_ray.refractionIndex = ray.refractionIndex; diffuse_ray.refractionStack = ray.refractionStack; diffuse_ray.iter = ray.iter + 1; diffuse_ray.o = bm_hit.P; diffuse_ray.d = 0; diffuse_ray.d += sinf(theta) * cosf(phi) * xaxis; diffuse_ray.d += sinf(theta) * sinf(phi) * zaxis; diffuse_ray.d += cosf(theta) * yaxis; diffuse_ray.d.normalize(); HitInfo diff_hit; Vector3 diff_res; if (scene.trace(diff_hit, diffuse_ray, EPSILON)) { float irrad[3]; g_global_illum_map->irradiance_estimate(irrad, diff_hit.P.array(), diff_hit.N.array(), 100.f, 50); // TODO: customize these parameters diff_res = Vector3(irrad); } // diff_res = diff_hit.material->shade(diffuse_ray, diff_hit, scene); else diff_res = scene.bgColor(); L += (diffcolor * diff_res) / PI; } float roulette = randone(g_rng); if (roulette > m_tp && (1 - m_tp) * m_ks.max() > EPSILON && ray.iter < MAX_RAY_ITER) { Ray newray; newray.iter = ray.iter + 1; newray.refractionIndex = ray.refractionIndex; newray.refractionStack = ray.refractionStack; newray.o = bm_hit.P; if (m_is_glossy) { Vector3 R = ray.d - 2 * ray.d.dot(bm_hit.N) * bm_hit.N; Vector3 u = R.cross(randvect); u.normalize(); Vector3 v = R.cross(u); v.normalize(); float theta = acos(powf(1.0f - randone(g_rng), (1.0f / (m_phong + 1)))); float phi = 2.0f * PI * randone(g_rng); newray.d = 0; newray.d += sinf(theta) * cosf(phi) * u; newray.d += sinf(theta) * sinf(phi) * v; newray.d += cosf(theta) * R; } else newray.d = ray.d - 2 * ray.d.dot(bm_hit.N) * bm_hit.N; newray.d.normalize(); HitInfo minHit; if (scene.trace(minHit, newray, EPSILON)) { L += minHit.material->shade(newray, minHit, scene) * speccolor; } else { L += scene.bgColor() * speccolor; } } if (roulette < m_tp && m_tp * m_ks.max() > EPSILON && ray.iter < MAX_RAY_ITER) { Ray newray; newray.refractionStack = ray.refractionStack; newray.refractionIndex = ray.refractionIndex; float ratio = 1.0; if ((*ray.refractionStack)[ray.refractionIndex] == m_refr && m_refr != 1.0) { newray.refractionIndex = ray.refractionIndex - 1; ratio = m_refr / (*newray.refractionStack)[newray.refractionIndex]; } else if ((*ray.refractionStack)[ray.refractionIndex] != m_refr) { newray.refractionIndex = ray.refractionIndex + 1; newray.refractionStack->push_back(m_refr); ratio = (*ray.refractionStack)[ray.refractionIndex] / m_refr; } newray.o = bm_hit.P; Vector3 w = -ray.d; float dDotN = w.dot(bm_hit.N); if (dDotN < 0) dDotN = -dDotN; if (1 - ratio*ratio*(1 - dDotN*dDotN) >= 0) { newray.d = -ratio * (w - dDotN*bm_hit.N) - sqrtf(1 - ratio*ratio*(1 - dDotN*dDotN)) * bm_hit.N; newray.d.normalize(); newray.iter = ray.iter + 1; HitInfo minHit; if (scene.trace(minHit, newray, EPSILON)) { L += minHit.material->shade(newray, minHit, scene) * speccolor; } else { L += scene.bgColor() * m_tp * speccolor; } } } L += m_ka * m_texture_ka->shade(ray, bm_hit, scene); return L; }
Vector3 Specular::shade(const Ray& ray, const HitInfo& hit, const Scene& scene) const { printf("Shading specular\n"); Vector3 L = Vector3(0.0f, 0.0f, 0.0f); const Vector3 viewDir = -ray.d; // d is a unit vector const Lights *lightlist = scene.lights(); Vector3 color = Vector3(m_kd); if (hit.material->hasTexture()) { Vector3 c = Vector3(hit.P); color = m_texture->getColor(c); } // loop over all of the lights HitInfo lightHitReflect = HitInfo(hit); HitInfo lightHitRefract = HitInfo(hit); lightHitReflect.hitNum = hit.hitNum; lightHitRefract.hitNum = hit.hitNum; Lights::const_iterator lightIter; for (lightIter = lightlist->begin(); lightIter != lightlist->end(); lightIter++) { PointLight* pLight = *lightIter; Ray lightRay; Vector3 l = pLight->position() - hit.P; float falloff = l.length2(); l /= sqrt(falloff); /* Calculate the diffuse component - From Labertian Shading Model */ float nDotL = dot(hit.N, l); Vector3 diffuseResult = pLight->color(); diffuseResult *= color; L += std::max(0.0f, nDotL/falloff * pLight->wattage() / PI) * diffuseResult; /* Calculate the specular highlight - From Phong Shading Model */ Vector3 h = (viewDir + l).normalize(); float nDotH = dot(hit.N, h); Vector3 specResult = pLight->color(); specResult *= m_ks; L += pow(std::max(0.0f, nDotH/falloff * pLight->wattage() / PI), m_p) * specResult; /* Calculate the specular reflectance */ if(lightHitReflect.hitNum < 1){ Vector3 r = reflect(hit.N, ray.d); lightRay.d = r.normalize(); lightRay.o = hit.P; if(scene.trace(lightHitReflect, lightRay, 0.0001, r.length())){ lightHitReflect.hitNum = lightHitReflect.hitNum+1; L += lightHitReflect.material->shade(lightRay, lightHitReflect, scene)*m_rl; } } /* Calculate the specular refractance */ // Vector3 incident = viewDir - hit.P; if(lightHitRefract.hitNum < 1 && m_rf > 0.0f ){ Vector3 t = refract(hit.N, ray.d, hit.material->n(), m_n); if(t != Vector3(0.0f)) lightRay.d = t.normalize(); else lightRay.d = t; lightRay.o = hit.P; if(scene.trace(lightHitRefract, lightRay, 0.0001, t.length())){ lightHitRefract.hitNum = lightHitRefract.hitNum+1; L+=lightHitRefract.material->shade(lightRay, lightHitRefract, scene)*m_rf; } else { L+=scene.getBGColor()*m_rf; } } } return L; }
void PointLightnigRenderPass::perform() { if (!m_initialized) { return; } m_pPointLightsSelector->select(Object::Type_PointLight); const std::vector<Object*> &lights = m_pPointLightsSelector->selectedObjects(); if (lights.size() == 0) { // No lights selected return; } glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glViewport(0, 0, m_pRenderer->width(), m_pRenderer->height()); // clear frame buffer glClearDepth(1.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLenum buffers[] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, buffers); m_pShaderProgram->use(); Camera *pCamera = m_pScene->activeCamera(); glm::mat4 cameraWorldMatrix = pCamera->worldMatrix(); glm::vec3 cameraPosition = cameraWorldMatrix[3].xyz(); (*m_pShaderProgram)["CameraPosition"] = cameraPosition; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, *m_pColorTexureHandle); (*m_pShaderProgram)["ColorTexture"] = 0; glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, *m_pPositionTextureHandle); (*m_pShaderProgram)["PositionTexture"] = 1; glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, *m_pNormalTextureHandle); (*m_pShaderProgram)["NormalTexture"] = 2; glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); DS_CHECK_GL_ERROR glViewport(0, 0, m_pRenderer->width(), m_pRenderer->height()); glBindVertexArray(m_vertexArray); for (int i = 0; i < lights.size(); i++) { PointLight *pLight = dynamic_cast<PointLight*>(lights[i]); if (pLight != nullptr) { (*m_pShaderProgram)["LightPosition"] = pLight->worldMatrix()[3].xyz(); (*m_pShaderProgram)["LightColor"] = pLight->color(); } glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } glBindVertexArray(0); glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, 0); }