https://github.com/ingowald/optix7course
마찬가지로 이전 Example에서 변경된 점만 설명한다.
// main.cpp
/*! main entry point to this example - initially optix, print hello
world, then exit */
extern "C" int main(int ac, char **av)
{
try {
TriangleMesh model;
// 100x100 thin ground plane
model.addCube(vec3f(0.f,-1.5f,0.f),vec3f(10.f,.1f,10.f));
// a unit cube centered on top of that
model.addCube(vec3f(0.f,0.f,0.f),vec3f(2.f,2.f,2.f));
model.color = vec3f(.2f,.8f,.2f);
Camera camera = { /*from*/vec3f(-10.f,2.f,-12.f),
/* at */vec3f(0.f,0.f,0.f),
/* up */vec3f(0.f,1.f,0.f) };
// something approximating the scale of the world, so the
// camera knows how much to move for any given user interaction:
const float worldScale = 10.f;
SampleWindow *window = new SampleWindow("Optix 7 Course Example",
model,camera,worldScale);
window->run();
} catch (std::runtime_error& e) {
std::cout << GDT_TERMINAL_RED << "FATAL ERROR: " << e.what()
<< GDT_TERMINAL_DEFAULT << std::endl;
exit(1);
}
return 0;
}
TriangleMesh에 color가 추가되었다.
// SampleRender.h
struct TriangleMesh {
/*! add a unit cube (subject to given xfm matrix) to the current
triangleMesh */
void addUnitCube(const affine3f &xfm);
//! add aligned cube aith front-lower-left corner and size
void addCube(const vec3f ¢er, const vec3f &size);
std::vector<vec3f> vertex;
std::vector<vec3i> index;
vec3f color;
};
// SampleRenderer.cpp
void SampleRenderer::buildSBT()
{
// ------------------------------------------------------------------
// build raygen records
// ------------------------------------------------------------------
std::vector<RaygenRecord> raygenRecords;
for (int i=0;i<raygenPGs.size();i++) {
RaygenRecord rec;
OPTIX_CHECK(optixSbtRecordPackHeader(raygenPGs[i],&rec));
rec.data = nullptr; /* for now ... */
raygenRecords.push_back(rec);
}
raygenRecordsBuffer.alloc_and_upload(raygenRecords);
sbt.raygenRecord = raygenRecordsBuffer.d_pointer();
// ------------------------------------------------------------------
// build miss records
// ------------------------------------------------------------------
std::vector<MissRecord> missRecords;
for (int i=0;i<missPGs.size();i++) {
MissRecord rec;
OPTIX_CHECK(optixSbtRecordPackHeader(missPGs[i],&rec));
rec.data = nullptr; /* for now ... */
missRecords.push_back(rec);
}
missRecordsBuffer.alloc_and_upload(missRecords);
sbt.missRecordBase = missRecordsBuffer.d_pointer();
sbt.missRecordStrideInBytes = sizeof(MissRecord);
sbt.missRecordCount = (int)missRecords.size();
// ------------------------------------------------------------------
// build hitgroup records
// ------------------------------------------------------------------
int numObjects = 1;
std::vector<HitgroupRecord> hitgroupRecords;
for (int i=0;i<numObjects;i++) {
// we only have a single object type so far
int objectType = 0;
HitgroupRecord rec;
OPTIX_CHECK(optixSbtRecordPackHeader(hitgroupPGs[objectType],&rec));
rec.data.vertex = (vec3f*)vertexBuffer.d_pointer();
rec.data.index = (vec3i*)indexBuffer.d_pointer();
rec.data.color = model.color;
hitgroupRecords.push_back(rec);
}
hitgroupRecordsBuffer.alloc_and_upload(hitgroupRecords);
sbt.hitgroupRecordBase = hitgroupRecordsBuffer.d_pointer();
sbt.hitgroupRecordStrideInBytes = sizeof(HitgroupRecord);
sbt.hitgroupRecordCount = (int)hitgroupRecords.size();
}
ratgenRecords와 missRecords는 동일하고, hit group의 record만 변경되었다.
// SampleRenderer.cpp
/*! SBT record for a hitgroup program */
struct __align__( OPTIX_SBT_RECORD_ALIGNMENT ) HitgroupRecord
{
__align__( OPTIX_SBT_RECORD_ALIGNMENT ) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
TriangleMeshSBTData data;
};
TriangleMeshSBTData를 Record에 저장한다.
// LaunchParams.h
#pragma once
#include "gdt/math/vec.h"
#include "optix7.h"
namespace osc {
using namespace gdt;
struct TriangleMeshSBTData {
vec3f color;
vec3f *vertex;
vec3i *index;
};
...
} // ::osc
rec.data.vertex, rec.data.index의 값인 vertexBuffer, indexBuffer는 buildAccel()함수에서 alloc_and_upload된 값들이다.
color는 main 함수에서 설정한 color이다.
// devicePrograms.cu
extern "C" __global__ void __closesthit__radiance()
{
const TriangleMeshSBTData &sbtData
= *(const TriangleMeshSBTData*)optixGetSbtDataPointer();
// compute normal:
const int primID = optixGetPrimitiveIndex();
const vec3i index = sbtData.index[primID];
const vec3f &A = sbtData.vertex[index.x];
const vec3f &B = sbtData.vertex[index.y];
const vec3f &C = sbtData.vertex[index.z];
const vec3f Ng = normalize(cross(B-A,C-A));
const vec3f rayDir = optixGetWorldRayDirection();
const float cosDN = 0.2f + .8f*fabsf(dot(rayDir,Ng));
vec3f &prd = *(vec3f*)getPRD<vec3f>();
prd = cosDN * sbtData.color;
}
optixGetSbtDataPointer() 함수는 현재 program에 해당하는 현재 활성 SBT record의 (헤더 만큼 stride한) 데이터 영역에 대한 pointer를 반환한다. (CUdeviceptr)
Ng는 해당 삼각형의 법선 벡터이다.
optixGetWorldRayDirection() 함수를 통해서 world space에서의 ray vector를 얻는다.
cosDN에서 0.2f는 ambient color를 의미하고, .8f*fabsf(dot(rayDir,Ng))는 diffuse color를 의미한다.
여기서는 camera 위치가 광원(light)가 된다.