Assignment1
This commit is contained in:
parent
d3bb49b3f5
commit
57ae058d9a
7 changed files with 444 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
|||
build
|
||||
.cache
|
||||
|
|
|
|||
121
Assignments/Assignment1/Application1.cpp
Normal file
121
Assignments/Assignment1/Application1.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "Application1.h"
|
||||
|
||||
void Application1::initScene() {
|
||||
Data_Constructor(&data, 1, 8);
|
||||
|
||||
/* select scene here */
|
||||
standardScene();
|
||||
// standardScenewithAreaLight();
|
||||
}
|
||||
|
||||
void Application1::standardScene() {
|
||||
FileName file = workingDir + FileName("Framework/scenes/cornell_box.obj");
|
||||
|
||||
/* set default camera */
|
||||
camera.from = Vec3fa(278, 273, -800);
|
||||
camera.to = Vec3fa(278, 273, 0);
|
||||
|
||||
Ref<SceneGraph::GroupNode> sceneGraph = loadOBJ(file, false).cast<SceneGraph::GroupNode>();
|
||||
sceneGraph->add(new SceneGraph::LightNodeImpl<SceneGraph::PointLight>(
|
||||
SceneGraph::PointLight(Vec3fa(213, 300, 227), Vec3fa(100000, 100000, 100000))));
|
||||
|
||||
Ref<SceneGraph::GroupNode> flattened_scene = SceneGraph::flatten(sceneGraph, SceneGraph::INSTANCING_NONE);
|
||||
Scene* scene = new Scene;
|
||||
scene->add(flattened_scene);
|
||||
sceneGraph = nullptr;
|
||||
flattened_scene = nullptr;
|
||||
|
||||
auto renderScene = new RenderScene(g_device, scene);
|
||||
g_render_scene = renderScene;
|
||||
data.scene = renderScene;
|
||||
scene = nullptr;
|
||||
}
|
||||
|
||||
void Application1::standardScenewithAreaLight() {
|
||||
FileName file = workingDir + FileName("Framework/scenes/cornell_box.obj");
|
||||
|
||||
/* set default camera */
|
||||
camera.from = Vec3fa(278, 273, -800);
|
||||
camera.to = Vec3fa(278, 273, 0);
|
||||
|
||||
Ref<SceneGraph::GroupNode> sceneGraph = loadOBJ(file, false).cast<SceneGraph::GroupNode>();
|
||||
sceneGraph->add(new SceneGraph::LightNodeImpl<SceneGraph::QuadLight>(
|
||||
SceneGraph::QuadLight(Vec3fa(343.0, 548.0, 227.0), Vec3fa(343.0, 548.0, 332.0), Vec3fa(213.0, 548.0, 332.0),
|
||||
Vec3fa(213.0, 548.0, 227.0), Vec3fa(100000, 100000, 100000))));
|
||||
|
||||
Ref<SceneGraph::GroupNode> flattened_scene = SceneGraph::flatten(sceneGraph, SceneGraph::INSTANCING_NONE);
|
||||
Scene* scene = new Scene;
|
||||
scene->add(flattened_scene);
|
||||
sceneGraph = nullptr;
|
||||
flattened_scene = nullptr;
|
||||
|
||||
auto renderScene = new RenderScene(g_device, scene);
|
||||
g_render_scene = renderScene;
|
||||
data.scene = renderScene;
|
||||
scene = nullptr;
|
||||
}
|
||||
|
||||
/* task that renders a single screen tile */
|
||||
Vec3fa Application1::renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) {
|
||||
/* radiance accumulator and weight */
|
||||
Vec3fa L = Vec3fa(0.0f);
|
||||
Vec3fa Lw = Vec3fa(1.0f);
|
||||
|
||||
/* initialize ray */
|
||||
Ray ray(Vec3fa(camera.xfm.p), Vec3fa(normalize(x * camera.xfm.l.vx + y * camera.xfm.l.vy + camera.xfm.l.vz)), 0.0f,
|
||||
inf);
|
||||
|
||||
/* intersect ray with scene */
|
||||
RTCIntersectArguments iargs;
|
||||
rtcInitIntersectArguments(&iargs);
|
||||
iargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
||||
rtcIntersect1(data.g_scene, RTCRayHit_(ray), &iargs);
|
||||
RayStats_addRay(stats);
|
||||
|
||||
const Vec3fa wo = neg(ray.dir);
|
||||
|
||||
/* shade pixels */
|
||||
if (ray.geomID != RTC_INVALID_GEOMETRY_ID) {
|
||||
Vec3fa Ns = normalize(ray.Ng);
|
||||
Sample sample;
|
||||
sample.P = ray.org + ray.tfar * ray.dir;
|
||||
sample.Ng = ray.Ng;
|
||||
sample.Ns = Ns;
|
||||
int matId = data.scene->geometries[ray.geomID]->materialID;
|
||||
sample.Ng = face_forward(ray.dir, normalize(sample.Ng));
|
||||
sample.Ns = face_forward(ray.dir, normalize(sample.Ns));
|
||||
|
||||
/* calculate BRDF */
|
||||
BRDF brdf;
|
||||
std::vector<Material *> material_array = data.scene->materials;
|
||||
Material__preprocess(material_array, matId, brdf, wo, sample);
|
||||
|
||||
/* sample BRDF at hit point */
|
||||
Sample3f wi1;
|
||||
Material__sample(material_array, matId, brdf, Lw, wo, sample, wi1, RandomSampler_get2D(sampler));
|
||||
|
||||
const Light* l = data.scene->lights[0];
|
||||
Light_SampleRes ls = Lights_sample(l, sample, RandomSampler_get2D(sampler));
|
||||
Vec3f lightColor = {colorLight[0], colorLight[1], colorLight[2]};
|
||||
|
||||
Vec3fa diffuse = Material__eval(material_array, matId, brdf, wo, sample, ls.dir);
|
||||
L += diffuse;
|
||||
|
||||
/* initialize shadow ray */
|
||||
Ray shadow(sample.P, ls.dir, 0.001f, ls.dist, 0.0f);
|
||||
|
||||
/* trace shadow ray */
|
||||
RTCOccludedArguments sargs;
|
||||
rtcInitOccludedArguments(&sargs);
|
||||
sargs.feature_mask = RTC_FEATURE_FLAG_TRIANGLE;
|
||||
rtcOccluded1(data.g_scene, RTCRay_(shadow), &sargs);
|
||||
RayStats_addShadowRay(stats);
|
||||
|
||||
/* add light contribution if not occluded */
|
||||
if (shadow.tfar >= 0.0f) {
|
||||
L += ls.weight * lightColor * 0.1f;
|
||||
}
|
||||
}
|
||||
|
||||
return L;
|
||||
}
|
||||
24
Assignments/Assignment1/Application1.h
Normal file
24
Assignments/Assignment1/Application1.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "helper.hpp"
|
||||
|
||||
|
||||
class Application1 : public Application {
|
||||
public:
|
||||
Application1(int argc, char** argv) : Application(argc, argv, "Assignment 1") {
|
||||
}
|
||||
|
||||
private:
|
||||
Vec3fa renderPixel(float x, float y, const ISPCCamera& camera, RayStats& stats, RandomSampler& sampler) override;
|
||||
|
||||
void drawGUI() override {
|
||||
ImGui::ColorEdit3("Color", colorLight);
|
||||
}
|
||||
|
||||
void initScene() override;
|
||||
|
||||
void standardScene();
|
||||
|
||||
void standardScenewithAreaLight();
|
||||
|
||||
float colorLight[3] = {1.0f, 1.0f, 1.0f};
|
||||
};
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
|
||||
project(Assignment1)
|
||||
|
||||
add_executable(${PROJECT_NAME} "assignment1.cpp")
|
||||
add_executable(${PROJECT_NAME} "assignment1.cpp"
|
||||
Application1.cpp
|
||||
Application1.h
|
||||
helper.hpp)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC CGI-framework)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include "Application1.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
auto app = new Application1(argc, argv);
|
||||
|
||||
app->run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
288
Assignments/Assignment1/helper.hpp
Normal file
288
Assignments/Assignment1/helper.hpp
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
#pragma once
|
||||
#include <application.h>
|
||||
#include <sampling.hpp>
|
||||
#include <scenegraph/obj_loader.h>
|
||||
#include <sys/filename.h>
|
||||
|
||||
#include <lights/ambient_light.h>
|
||||
#include <lights/directional_light.h>
|
||||
#include <lights/point_light.h>
|
||||
#include <lights/quad_light.h>
|
||||
#include <lights/spot_light.h>
|
||||
|
||||
using namespace embree;
|
||||
|
||||
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f * dot(V, N) * N - V; }
|
||||
|
||||
inline Vec3fa face_forward(const Vec3fa& dir, const Vec3fa& _Ng) {
|
||||
const Vec3fa Ng = _Ng;
|
||||
return dot(dir, Ng) < 0.0f ? Ng : neg(Ng);
|
||||
}
|
||||
|
||||
inline Light_SampleRes Lights_sample(const Light* self,
|
||||
const Sample& sp, /*! point to generate the sample for >*/
|
||||
const Vec2f s) /*! random numbers to generate the sample >*/
|
||||
{
|
||||
LightType ty = self->type;
|
||||
switch (ty) {
|
||||
case LIGHT_AMBIENT: return AmbientLight_sample(self, sp, s);
|
||||
case LIGHT_POINT: return PointLight_sample(self, sp, s);
|
||||
case LIGHT_DIRECTIONAL: return DirectionalLight_sample(self, sp, s);
|
||||
case LIGHT_SPOT: return SpotLight_sample(self, sp, s);
|
||||
case LIGHT_QUAD: return QuadLight_sample(self, sp, s);
|
||||
default: {
|
||||
Light_SampleRes res;
|
||||
res.weight = Vec3fa(0, 0, 0);
|
||||
res.dir = Vec3fa(0, 0, 0);
|
||||
res.dist = 0;
|
||||
res.pdf = inf;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Light_EvalRes Lights_eval(const Light* self,
|
||||
const Sample& sp,
|
||||
const Vec3fa& dir) {
|
||||
LightType ty = self->type;
|
||||
switch (ty) {
|
||||
case LIGHT_AMBIENT: return AmbientLight_eval(self, sp, dir);
|
||||
case LIGHT_POINT: return PointLight_eval(self, sp, dir);
|
||||
case LIGHT_DIRECTIONAL: return DirectionalLight_eval(self, sp, dir);
|
||||
case LIGHT_SPOT: return SpotLight_eval(self, sp, dir);
|
||||
case LIGHT_QUAD: return QuadLight_eval(self, sp, dir);
|
||||
default: {
|
||||
Light_EvalRes res;
|
||||
res.value = Vec3fa(0, 0, 0);
|
||||
res.dist = inf;
|
||||
res.pdf = 0.f;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct BRDF {
|
||||
float Ns; /*< specular exponent */
|
||||
float Ni; /*< optical density for the surface (index of refraction) */
|
||||
Vec3fa Ka; /*< ambient reflectivity */
|
||||
Vec3fa Kd; /*< diffuse reflectivity */
|
||||
Vec3fa Ks; /*< specular reflectivity */
|
||||
Vec3fa Kt; /*< transmission filter */
|
||||
float dummy[30];
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Lambertian BRDF //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Lambertian {
|
||||
Vec3fa R;
|
||||
};
|
||||
|
||||
inline Vec3fa Lambertian__eval(const Lambertian* This,
|
||||
const Vec3fa& wo, const Sample& dg, const Vec3fa& wi) {
|
||||
return This->R * (1.0f / (float) (float(M_PI))) * clamp(dot(wi, dg.Ns));
|
||||
}
|
||||
|
||||
inline Vec3fa Lambertian__sample(const Lambertian* This,
|
||||
const Vec3fa& wo,
|
||||
const Sample& dg,
|
||||
Sample3f& wi,
|
||||
const Vec2f& s) {
|
||||
wi = cosineSampleHemisphere(s.x, s.y, dg.Ns);
|
||||
return Lambertian__eval(This, wo, dg, wi.v);
|
||||
}
|
||||
|
||||
inline void Lambertian__Constructor(Lambertian* This, const Vec3fa& R) {
|
||||
This->R = R;
|
||||
}
|
||||
|
||||
inline Lambertian make_Lambertian(const Vec3fa& R) {
|
||||
Lambertian v;
|
||||
Lambertian__Constructor(&v, R);
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Matte Material //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void MatteMaterial__preprocess(MatteMaterial* material, BRDF& brdf, const Vec3fa& wo, const Sample& sp) {
|
||||
}
|
||||
|
||||
inline Vec3fa MatteMaterial__eval(MatteMaterial* This, const BRDF& brdf, const Vec3fa& wo, const Sample& sp,
|
||||
const Vec3fa& wi) {
|
||||
Lambertian lambertian = make_Lambertian(Vec3fa((Vec3fa) This->reflectance));
|
||||
return Lambertian__eval(&lambertian, wo, sp, wi);
|
||||
}
|
||||
|
||||
inline Vec3fa MatteMaterial__sample(MatteMaterial* This, const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo,
|
||||
const Sample& sp, Sample3f& wi_o, const Vec2f& s) {
|
||||
Lambertian lambertian = make_Lambertian(Vec3fa((Vec3fa) This->reflectance));
|
||||
return Lambertian__sample(&lambertian, wo, sp, wi_o, s);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// OBJ Material //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void OBJMaterial__preprocess(OBJMaterial* material, BRDF& brdf, const Vec3fa& wo, const Sample& sp) {
|
||||
float d = material->d;
|
||||
// if (material->map_d) d *= getTextureTexel1f(material->map_d, dg.u, dg.v);
|
||||
brdf.Ka = Vec3fa(material->Ka);
|
||||
//if (material->map_Ka) { brdf.Ka *= material->map_Ka->get(dg.st); }
|
||||
brdf.Kd = d * Vec3fa(material->Kd);
|
||||
// if (material->map_Kd) brdf.Kd = brdf.Kd * getTextureTexel3f(material->map_Kd, dg.u, dg.v);
|
||||
brdf.Ks = d * Vec3fa(material->Ks);
|
||||
//if (material->map_Ks) brdf.Ks *= material->map_Ks->get(dg.st);
|
||||
brdf.Ns = material->Ns;
|
||||
//if (material->map_Ns) { brdf.Ns *= material->map_Ns.get(dg.st); }
|
||||
brdf.Kt = (1.0f - d) * Vec3fa(material->Kt);
|
||||
brdf.Ni = material->Ni;
|
||||
}
|
||||
|
||||
inline Vec3fa OBJMaterial__eval(OBJMaterial* material, const BRDF& brdf, const Vec3fa& wo, const Sample& sp,
|
||||
const Vec3fa& wi) {
|
||||
Vec3fa R = Vec3fa(0.0f);
|
||||
const float Md = max(max(brdf.Kd.x, brdf.Kd.y), brdf.Kd.z);
|
||||
const float Ms = max(max(brdf.Ks.x, brdf.Ks.y), brdf.Ks.z);
|
||||
const float Mt = max(max(brdf.Kt.x, brdf.Kt.y), brdf.Kt.z);
|
||||
if (Md > 0.0f) {
|
||||
R = R + (1.0f / float(M_PI)) * clamp(dot(wi, sp.Ns)) * brdf.Kd;
|
||||
}
|
||||
if (Ms > 0.0f) {
|
||||
const Sample3f refl = make_Sample3f(reflect(wo, sp.Ns), 1.0f);
|
||||
if (dot(refl.v, wi) > 0.0f) {
|
||||
R = R + (brdf.Ns + 2) * float(one_over_two_pi) * powf(max(1e-10f, dot(refl.v, wi)), brdf.Ns) *
|
||||
clamp(dot(wi, sp.Ns)) * brdf.Ks;
|
||||
}
|
||||
}
|
||||
if (Mt > 0.0f) {
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
inline Vec3fa OBJMaterial__sample(OBJMaterial* material, const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo,
|
||||
const Sample& sp, Sample3f& wi_o, const Vec2f& s) {
|
||||
Vec3fa cd = Vec3fa(0.0f);
|
||||
Sample3f wid = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||
if (max(max(brdf.Kd.x, brdf.Kd.y), brdf.Kd.z) > 0.0f) {
|
||||
wid = cosineSampleHemisphere(s.x, s.y, sp.Ns);
|
||||
cd = float(one_over_pi) * clamp(dot(wid.v, sp.Ns)) * brdf.Kd;
|
||||
}
|
||||
|
||||
Vec3fa cs = Vec3fa(0.0f);
|
||||
Sample3f wis = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||
if (max(max(brdf.Ks.x, brdf.Ks.y), brdf.Ks.z) > 0.0f) {
|
||||
const Sample3f refl = make_Sample3f(reflect(wo, sp.Ns), 1.0f);
|
||||
wis.v = powerCosineSampleHemisphere(brdf.Ns, s);
|
||||
wis.pdf = powerCosineSampleHemispherePDF(wis.v, brdf.Ns);
|
||||
wis.v = frame(refl.v) * wis.v;
|
||||
cs = (brdf.Ns + 2) * float(one_over_two_pi) * powf(max(dot(refl.v, wis.v), 1e-10f), brdf.Ns) *
|
||||
clamp(dot(wis.v, sp.Ns)) * brdf.Ks;
|
||||
}
|
||||
|
||||
Vec3fa ct = Vec3fa(0.0f);
|
||||
Sample3f wit = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||
if (max(max(brdf.Kt.x, brdf.Kt.y), brdf.Kt.z) > 0.0f) {
|
||||
wit = make_Sample3f(neg(wo), 1.0f);
|
||||
ct = brdf.Kt;
|
||||
}
|
||||
|
||||
const Vec3fa md = Lw * cd / wid.pdf;
|
||||
const Vec3fa ms = Lw * cs / wis.pdf;
|
||||
const Vec3fa mt = Lw * ct / wit.pdf;
|
||||
|
||||
const float Cd = wid.pdf == 0.0f ? 0.0f : max(max(md.x, md.y), md.z);
|
||||
const float Cs = wis.pdf == 0.0f ? 0.0f : max(max(ms.x, ms.y), ms.z);
|
||||
const float Ct = wit.pdf == 0.0f ? 0.0f : max(max(mt.x, mt.y), mt.z);
|
||||
const float C = Cd + Cs + Ct;
|
||||
|
||||
if (C == 0.0f) {
|
||||
wi_o = make_Sample3f(Vec3fa(0, 0, 0), 0);
|
||||
return Vec3fa(0, 0, 0);
|
||||
}
|
||||
|
||||
const float CPd = Cd / C;
|
||||
const float CPs = Cs / C;
|
||||
const float CPt = Ct / C;
|
||||
|
||||
if (s.x < CPd) {
|
||||
wi_o = make_Sample3f(wid.v, wid.pdf * CPd);
|
||||
return cd;
|
||||
} else if (s.x < CPd + CPs) {
|
||||
wi_o = make_Sample3f(wis.v, wis.pdf * CPs);
|
||||
return cs;
|
||||
} else {
|
||||
wi_o = make_Sample3f(wit.v, wit.pdf * CPt);
|
||||
return ct;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Material //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void Material__preprocess(std::vector<Material *> materials, unsigned int materialID,
|
||||
BRDF& brdf, const Vec3fa& wo, const Sample& sp) {
|
||||
auto id = materialID; {
|
||||
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||
{
|
||||
Material* material = materials[id];
|
||||
|
||||
switch (material->type) {
|
||||
case MATERIAL_OBJ: OBJMaterial__preprocess((OBJMaterial *) material, brdf, wo, sp);
|
||||
break;
|
||||
case MATERIAL_MATTE: MatteMaterial__preprocess((MatteMaterial *) material, brdf, wo, sp);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline Vec3fa Material__eval(std::vector<Material *> materials, unsigned int materialID,
|
||||
const BRDF& brdf, const Vec3fa& wo, const Sample& sp, const Vec3fa& wi) {
|
||||
Vec3fa c = Vec3fa(0.0f);
|
||||
auto id = materialID; {
|
||||
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||
{
|
||||
Material* material = materials[id];
|
||||
switch (material->type) {
|
||||
case MATERIAL_OBJ: c = OBJMaterial__eval((OBJMaterial *) material, brdf, wo, sp, wi);
|
||||
break;
|
||||
case MATERIAL_MATTE: c = MatteMaterial__eval((MatteMaterial *) material, brdf, wo, sp, wi);
|
||||
break;
|
||||
default:
|
||||
std::cout << "No Material found" << std::endl;
|
||||
c = Vec3fa(0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
inline Vec3fa Material__sample(std::vector<Material *> materials, unsigned int materialID,
|
||||
const BRDF& brdf, const Vec3fa& Lw, const Vec3fa& wo, const Sample& sp, Sample3f& wi_o,
|
||||
const Vec2f& s) {
|
||||
Vec3fa c = Vec3fa(0.0f);
|
||||
auto id = materialID; {
|
||||
if (id < materials.size()) // FIXME: workaround for ISPC bug, location reached with empty execution mask
|
||||
{
|
||||
Material* material = materials[id];
|
||||
switch (material->type) {
|
||||
case MATERIAL_OBJ: c = OBJMaterial__sample((OBJMaterial *) material, brdf, Lw, wo, sp, wi_o, s);
|
||||
break;
|
||||
case MATERIAL_MATTE: c = MatteMaterial__sample((MatteMaterial *) material, brdf, Lw, wo, sp, wi_o,
|
||||
s);
|
||||
break;
|
||||
default: wi_o = make_Sample3f(Vec3fa(0.0f), 0.0f);
|
||||
c = Vec3fa(0.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
|
||||
|
||||
#if !defined(EMBREE_STATIC_LIB)
|
||||
/* #undef EMBREE_STATIC_LIB */
|
||||
#define EMBREE_STATIC_LIB
|
||||
#endif
|
||||
/* #undef EMBREE_API_NAMESPACE */
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue