Color Scene::shade(Intersection isect, Ray r, int level) { if (!isect.hits()) { return bgColor; } real eps; if (r.in()) { eps = 0.00001; } else { eps = -0.00001; } Texture *txt = isect.object()->getTexture(); Point isectPt = r.pointOn(isect.t()); Color curColor(0.0,0.0,0.0); Color specular(0,0,0); Color diffuse(0,0,0); Color shadowAmt(1,1,1); for (LightList::iterator lt_iter = lights.begin(); lt_iter != lights.end(); ++lt_iter) { Vector specL((*lt_iter)->location()-isectPt); Vector specV(cam.getLocation()-isectPt); Vector specHj((specL+specV)*(1.0/((specL+specV).length()))); Ray shade_ray = (*lt_iter)->getRayTo(r.pointOn(isect.t()+ eps)); ++shadow_rays_cast; Intersection tempI = rtrace(shade_ray, true, isect.object()); if (tempI.hits()) { if (level>0) { shadowAmt -= shade(tempI, shade_ray, level-1); } else { shadowAmt = Color(0.0,0.0,0.0); } } specular += (*lt_iter)->intensity()*std::pow(specHj.dot(isect.normal()), txt->n()); diffuse += (*lt_iter)->intensity()*shade_ray.getDir().dot(isect.normal()); } shadowAmt *= 1.0/real(lights.size()); Color reflective(0.0,0.0,0.0,0.0); if ((level>0) && (txt->kr().intensity()>0.01)) { ++reflective_rays_cast; Ray tempRay(r.pointOn(isect.t()+eps), r.getDir() - 2.0 * (r.getDir().dot(isect.normal())) * isect.normal()); reflective = shade(rtrace(tempRay), tempRay, level-1); } Color refractive(0.0,0.0,0.0); if ((level>0) && (txt->kt().intensity()>0.01)) { real eta; if (r.in()) { eta = 1.0/txt->ior(); } else { eta = txt->ior(); } real ci; if (r.in()) { ci = (r.getDir().dot(-1.0*isect.normal())); } else { ci = (r.getDir().dot(isect.normal())); } real costt = 1.0 - (eta*eta) * (1.0-ci*ci); if (costt<0.0) { refractive = Color(0,0,0); } else { ++refractive_rays_cast; Ray tempRay(r.pointOn(isect.t()+eps), ((eta*ci-std::sqrt(costt))*((r.in()?-1.0:1.0)*isect.normal()) - (eta*r.getDir())), !r.in()); refractive = shade(rtrace(tempRay, isect.object()), tempRay, level-1); } } curColor += txt->ka() + (txt->kd()*diffuse + txt->ks()*specular + txt->kr()*reflective + txt->kt()*refractive) * shadowAmt; return curColor.clamp(); }
static bool load(std::shared_ptr<CookingTask> cookingTask) { if (!cookingTask->dataSet->loadMaterials) return true; auto tid = Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PushTask("MaterialLoader : loading " + cookingTask->dataSet->filePath.getShortFileName()); if (!cookingTask->assimpScene->HasMaterials()) { Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); return true; } if (cookingTask->assimpScene->mNumMaterials <= 1) { return true; } for (unsigned int materialIndex = 1; materialIndex < cookingTask->assimpScene->mNumMaterials; ++materialIndex) { auto &aiMat = cookingTask->assimpScene->mMaterials[materialIndex]; aiColor4D diffuse(1.0f,1.0f,1.0f,1.0f); aiColor4D ambient(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D emissive(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D reflective(1.0f, 1.0f, 1.0f, 1.0f); aiColor4D specular(1.0f, 1.0f, 1.0f, 1.0f); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_DIFFUSE, &diffuse); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_AMBIENT, &ambient); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_EMISSIVE, &emissive); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_REFLECTIVE, &reflective); aiGetMaterialColor(aiMat, AI_MATKEY_COLOR_SPECULAR, &specular); aiString diffuseTexPath; aiString ambientTexPath; aiString emissiveTexPath; aiString reflexionTexPath; aiString specularTexPath; aiString normalTexPath; aiString bumpTexPath; aiMat->GetTexture(aiTextureType_DIFFUSE, 0, &diffuseTexPath); aiMat->GetTexture(aiTextureType_AMBIENT, 0, &ambientTexPath); aiMat->GetTexture(aiTextureType_EMISSIVE, 0, &emissiveTexPath); aiMat->GetTexture(aiTextureType_REFLECTION, 0, &reflexionTexPath); aiMat->GetTexture(aiTextureType_SPECULAR, 0, &specularTexPath); aiMat->GetTexture(aiTextureType_NORMALS, 0, &normalTexPath); aiMat->Get(AI_MATKEY_TEXTURE_HEIGHT(0), bumpTexPath); auto material = std::make_shared<MaterialData>(); material->diffuse = AssimpLoader::aiColorToGlm(diffuse); material->ambient = AssimpLoader::aiColorToGlm(ambient); material->emissive = AssimpLoader::aiColorToGlm(emissive); material->reflective = AssimpLoader::aiColorToGlm(reflective); material->specular = AssimpLoader::aiColorToGlm(specular); material->diffuseTexPath = diffuseTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(diffuseTexPath) : ""; material->ambientTexPath = ambientTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(ambientTexPath) : ""; material->emissiveTexPath = emissiveTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(emissiveTexPath) : ""; material->reflectiveTexPath = reflexionTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(reflexionTexPath) : ""; material->specularTexPath = specularTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(specularTexPath) : ""; material->normalTexPath = normalTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(normalTexPath) : ""; material->bumpTexPath = bumpTexPath.length > 0 ? cookingTask->dataSet->filePath.getFolder() + "/" + AssimpLoader::aiStringToStd(bumpTexPath) : ""; cookingTask->texturesPath.insert(material->diffuseTexPath); cookingTask->texturesPath.insert(material->ambientTexPath); cookingTask->texturesPath.insert(material->emissiveTexPath); cookingTask->texturesPath.insert(material->reflectiveTexPath); cookingTask->texturesPath.insert(material->specularTexPath); cookingTask->texturesPath.insert(material->normalTexPath); cookingTask->texturesPath.insert(material->bumpTexPath); AssimpLoader::replaceExtension(material->diffuseTexPath, ".dds"); AssimpLoader::replaceExtension(material->ambientTexPath, ".dds"); AssimpLoader::replaceExtension(material->emissiveTexPath, ".dds"); AssimpLoader::replaceExtension(material->reflectiveTexPath, ".dds"); AssimpLoader::replaceExtension(material->specularTexPath, ".dds"); AssimpLoader::replaceExtension(material->normalTexPath, ".dds"); AssimpLoader::replaceExtension(material->bumpTexPath, ".dds"); cookingTask->materials.push_back(material); } if (cookingTask->materials.size() == 0) { Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); std::cerr << "MaterialLoader : Materials has not been loaded" << std::endl; return false; } Singleton<AGE::AE::ConvertorStatusManager>::getInstance()->PopTask(tid); return true; }