Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit 475cc37

Browse files
committed
added image textures
1 parent 453c439 commit 475cc37

File tree

15 files changed

+145
-25
lines changed

15 files changed

+145
-25
lines changed

OptiX-Path-Tracer/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cuda_compile_and_embed( embedded_constant_texture_programs programs/textures/con
2828
cuda_compile_and_embed( embedded_aarect_programs programs/hitables/aarect.cu )
2929
cuda_compile_and_embed( embedded_checker_texture_programs programs/textures/checkered_texture.cu )
3030
cuda_compile_and_embed( embedded_noise_texture_programs programs/textures/noise_texture.cu )
31+
cuda_compile_and_embed( embedded_image_texture_programs programs/textures/image_texture.cu )
3132

3233
# this is doing the same using OptiX
3334
add_executable(OptiX-Path-Tracer
@@ -54,6 +55,7 @@ add_executable(OptiX-Path-Tracer
5455
${embedded_aarect_programs}
5556
${embedded_checker_texture_programs}
5657
${embedded_noise_texture_programs}
58+
${embedded_image_texture_programs}
5759
)
5860

5961
target_link_libraries(OptiX-Path-Tracer

OptiX-Path-Tracer/host_includes/scenes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ optix::GeometryGroup InOneWeekend(optix::Context &g_context, Camera &camera, int
3737
}
3838
}
3939
d_list.push_back(createSphere(vec3f(-4.f, 1.f, 0.f), 1.f, Dielectric(1.5f), g_context));
40-
d_list.push_back(createSphere(vec3f(4.f, 1.f, 0.f), 1.f, Lambertian(new Noise_Texture(4.f)), g_context));
40+
d_list.push_back(createSphere(vec3f(4.f, 1.f, 0.f), 1.f, Lambertian(new Image_Texture("assets/map.jpg")), g_context));
4141
d_list.push_back(createSphere(vec3f(0.f, 1.f, 0.f), 1.f, Metal(new Constant_Texture(vec3f(0.7f, 0.6f, 0.5f)), 0.0f), g_context));
4242
//createBox(vec3f(0.3f, 0.5f, 0.6f), vec3f(3.55f, 3.f, 3.2f), Lambertian(new Constant_Texture(vec3f(rnd()*rnd(), rnd()*rnd(), rnd()*rnd()))), g_context, d_list);
4343

OptiX-Path-Tracer/host_includes/textures.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77

88
#include "../programs/vec.h"
99

10+
// Image I/O - disregard lib warnings
11+
#pragma warning(push, 0)
12+
#define STBI_MSC_SECURE_CRT
13+
#define STB_IMAGE_IMPLEMENTATION
14+
#include "../lib/stb_image.h"
15+
#define STB_IMAGE_WRITE_IMPLEMENTATION
16+
#include "../lib/stb_image_write.h"
17+
#pragma warning(pop)
18+
1019
float rnd() {
1120
// static std::random_device rd; //Will be used to obtain a seed for the random number engine
1221
static std::mt19937 gen(0); //Standard mersenne_twister_engine seeded with rd()
@@ -22,6 +31,7 @@ float rnd() {
2231
extern "C" const char embedded_constant_texture_programs[];
2332
extern "C" const char embedded_checker_texture_programs[];
2433
extern "C" const char embedded_noise_texture_programs[];
34+
extern "C" const char embedded_image_texture_programs[];
2535

2636
struct Texture {
2737
virtual optix::Program assignTo(optix::GeometryInstance gi, optix::Context &g_context) const = 0;
@@ -123,4 +133,59 @@ struct Noise_Texture : public Texture{
123133
const float scale;
124134
};
125135

136+
struct Image_Texture : public Texture{
137+
Image_Texture(const std::string f) : fileName(f) {}
138+
139+
optix::TextureSampler loadTexture(optix::Context context, const std::string fileName) const {
140+
int nx, ny, nn;
141+
unsigned char *tex_data = stbi_load((char*)fileName.c_str(), &nx, &ny, &nn, 0);
142+
143+
optix::TextureSampler sampler = context->createTextureSampler();
144+
sampler->setWrapMode(0, RT_WRAP_REPEAT);
145+
sampler->setWrapMode(1, RT_WRAP_REPEAT);
146+
sampler->setWrapMode(2, RT_WRAP_REPEAT);
147+
sampler->setIndexingMode(RT_TEXTURE_INDEX_NORMALIZED_COORDINATES);
148+
sampler->setReadMode(RT_TEXTURE_READ_NORMALIZED_FLOAT);
149+
sampler->setMaxAnisotropy(1.0f);
150+
sampler->setMipLevelCount(1u);
151+
sampler->setArraySize(1u);
152+
153+
optix::Buffer buffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_BYTE4, nx, ny);
154+
unsigned char * data = static_cast<unsigned char *>(buffer->map());
155+
156+
for (int i = 0; i < nx; ++i) {
157+
for (int j = 0; j < ny; ++j) {
158+
int bindex = (j * nx + i) * 4;
159+
int iindex = ((ny - j - 1) * nx + i) * nn;
160+
161+
data[bindex + 0] = tex_data[iindex + 0];
162+
data[bindex + 1] = tex_data[iindex + 1];
163+
data[bindex + 2] = tex_data[iindex + 2];
164+
165+
if(nn == 4)
166+
data[bindex + 3] = tex_data[iindex + 3];
167+
else//3-channel images
168+
data[bindex + 3] = (unsigned char)255;
169+
}
170+
}
171+
172+
buffer->unmap();
173+
sampler->setBuffer(buffer);
174+
sampler->setFilteringModes(RT_FILTER_LINEAR, RT_FILTER_LINEAR, RT_FILTER_NONE);
175+
return sampler;
176+
}
177+
178+
virtual optix::Program assignTo(optix::GeometryInstance gi, optix::Context &g_context) const override {
179+
optix::Program textProg = g_context->createProgramFromPTXString(embedded_image_texture_programs, "sample_texture");
180+
181+
textProg["data"]->setTextureSampler(loadTexture(g_context, fileName));
182+
183+
gi["sample_texture"]->setProgramId(textProg);
184+
185+
return textProg;
186+
}
187+
188+
const std::string fileName;
189+
};
190+
126191
#endif

OptiX-Path-Tracer/main.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@
2525
// that we can use host functions as usual in these headers.
2626
#include "host_includes/scenes.h"
2727

28-
// Image I/O - disregard lib warnings
29-
#pragma warning(push, 0)
30-
#define STBI_MSC_SECURE_CRT
31-
#define STB_IMAGE_IMPLEMENTATION
32-
#include "lib/stb_image.h"
33-
#define STB_IMAGE_WRITE_IMPLEMENTATION
34-
#include "lib/stb_image_write.h"
35-
#pragma warning(pop)
36-
3728
optix::Context g_context;
3829

3930
/*! the precompiled programs/raygen.cu code (in ptx) that our
@@ -182,7 +173,7 @@ int main(int ac, char **av) {
182173
arr[pixel_index + 2] = int(255.99 * clamp(col.z));
183174
}
184175

185-
std::string output = "output/perlin_1000.png";
176+
std::string output = "output/image_1000.png";
186177
stbi_write_png((char*)output.c_str(), Nx, Ny, 3, arr, 0);
187178
fb->unmap();
188179

OptiX-Path-Tracer/programs/hitables/aarect.cu

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
1515
/*! the attributes we use to communicate between intersection programs and hit program */
1616
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
1717
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
18+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
19+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
1820

1921
/*! the per ray data we operate on */
2022
rtDeclareVariable(PerRayData, prd, rtPayload, );
@@ -38,6 +40,8 @@ RT_PROGRAM void hit_rect_X(int pid) {
3840
if (rtPotentialIntersection(t)) {
3941
hit_rec_p = ray.origin + t * ray.direction;
4042
hit_rec_normal = normal;
43+
hit_rec_u = (a - a0) / (a1 - a0);
44+
hit_rec_v = (b - b0) / (b1 - b0);
4145
rtReportIntersection(0);
4246
}
4347
}
@@ -60,6 +64,8 @@ RT_PROGRAM void hit_rect_Y(int pid) {
6064
if (rtPotentialIntersection(t)) {
6165
hit_rec_p = ray.origin + t * ray.direction;
6266
hit_rec_normal = normal;
67+
hit_rec_u = (a - a0) / (a1 - a0);
68+
hit_rec_v = (b - b0) / (b1 - b0);
6369
rtReportIntersection(0);
6470
}
6571
}
@@ -78,6 +84,8 @@ RT_PROGRAM void hit_rect_Z(int pid) {
7884
if (rtPotentialIntersection(t)) {
7985
hit_rec_p = ray.origin + t * ray.direction;
8086
hit_rec_normal = normal;
87+
hit_rec_u = (a - a0) / (a1 - a0);
88+
hit_rec_v = (b - b0) / (b1 - b0);
8189
rtReportIntersection(0);
8290
}
8391
}

OptiX-Path-Tracer/programs/hitables/moving_sphere.cu

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,20 @@ rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
3030
/*! the attributes we use to communicate between intersection programs and hit program */
3131
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
3232
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
33+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
34+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
3335

3436
/*! the per ray data we operate on */
3537
rtDeclareVariable(PerRayData, prd, rtPayload, );
3638

39+
inline __device__ void get_sphere_uv(const vec3f& p) {
40+
float phi = atan2(p.z, p.x);
41+
float theta = asin(p.y);
42+
43+
hit_rec_u = 1 - (phi + CUDART_PI_F) / (2 * CUDART_PI_F);
44+
hit_rec_v = (theta + CUDART_PI_F / 2) / CUDART_PI_F;
45+
}
46+
3747
__device__ float3 center(float time) {
3848
return center0 + ((time - time0) / (time1 - time0)) * (center1 - center0);
3949
}
@@ -71,6 +81,7 @@ RT_PROGRAM void hit_sphere(int pid) {
7181
if (rtPotentialIntersection(temp)) {
7282
hit_rec_p = ray.origin + temp * ray.direction;
7383
hit_rec_normal = (hit_rec_p - center(prd.in.time)) / radius;
84+
get_sphere_uv((hit_rec_p - center(prd.in.time)) / radius);
7485
rtReportIntersection(0);
7586
}
7687
}
@@ -81,6 +92,7 @@ RT_PROGRAM void hit_sphere(int pid) {
8192
if (rtPotentialIntersection(temp)) {
8293
hit_rec_p = ray.origin + temp * ray.direction;
8394
hit_rec_normal = (hit_rec_p - center(prd.in.time)) / radius;
95+
get_sphere_uv((hit_rec_p - center(prd.in.time)) / radius);
8496
rtReportIntersection(0);
8597
}
8698
}

OptiX-Path-Tracer/programs/hitables/sphere.cu

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,20 @@ rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
2727
/*! the attributes we use to communicate between intersection programs and hit program */
2828
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
2929
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
30+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
31+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
3032

3133
/*! the per ray data we operate on */
3234
rtDeclareVariable(PerRayData, prd, rtPayload, );
3335

36+
inline __device__ void get_sphere_uv(const vec3f& p) {
37+
float phi = atan2(p.z, p.x);
38+
float theta = asin(p.y);
39+
40+
hit_rec_u = 1 - (phi + CUDART_PI_F) / (2 * CUDART_PI_F);
41+
hit_rec_v = (theta + CUDART_PI_F / 2) / CUDART_PI_F;
42+
}
43+
3444

3545
// Program that performs the ray-sphere intersection
3646
//
@@ -65,6 +75,7 @@ RT_PROGRAM void hit_sphere(int pid) {
6575
if (rtPotentialIntersection(temp)) {
6676
hit_rec_p = ray.origin + temp * ray.direction;
6777
hit_rec_normal = (hit_rec_p - center) / radius;
78+
get_sphere_uv((hit_rec_p - center) / radius);
6879
rtReportIntersection(0);
6980
}
7081
}
@@ -75,6 +86,7 @@ RT_PROGRAM void hit_sphere(int pid) {
7586
if (rtPotentialIntersection(temp)) {
7687
hit_rec_p = ray.origin + temp * ray.direction;
7788
hit_rec_normal = (hit_rec_p - center) / radius;
89+
get_sphere_uv((hit_rec_p - center) / radius);
7890
rtReportIntersection(0);
7991
}
8092
}

OptiX-Path-Tracer/programs/materials/dielectric.cu

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ rtDeclareVariable(rtObject, world, , );
2626
/*! the attributes we use to communicate between intersection programs and hit program */
2727
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
2828
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
29+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
30+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
2931

3032
/*! and finally - that particular material's parameters */
3133
rtDeclareVariable(float, ref_idx, , );
@@ -75,7 +77,12 @@ inline __device__ bool scatter(const optix::Ray &ray_in,
7577
return true;
7678
}
7779

80+
inline __device__ float3 emitted(){
81+
return make_float3(0.f, 0.f, 0.f);
82+
}
83+
7884
RT_PROGRAM void closest_hit() {
85+
prd.out.emitted = emitted();
7986
prd.out.scatterEvent
8087
= scatter(ray,
8188
*prd.in.randState,

OptiX-Path-Tracer/programs/materials/lambertian.cu

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ rtDeclareVariable(rtObject, world, , );
2626
/*! the attributes we use to communicate between intersection programs and hit program */
2727
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
2828
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
29+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
30+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
2931

3032
// TODO: eventually UV parameters will be needed in the materials.
3133
// These should be defined in the intersection/hitable programs.
@@ -47,13 +49,18 @@ inline __device__ bool scatter(const optix::Ray &ray_in,
4749
// return scattering event
4850
scattered_origin = hit_rec_p;
4951
scattered_direction = (target - hit_rec_p);
50-
float3 color = sample_texture(0.f, 0.f, hit_rec_p);
52+
float3 color = sample_texture(hit_rec_u, hit_rec_v, hit_rec_p);
5153
attenuation = vec3f(color);
5254
return true;
5355
}
5456

57+
inline __device__ float3 emitted(){
58+
return make_float3(0.f, 0.f, 0.f);
59+
}
60+
5561
RT_PROGRAM void closest_hit() {
56-
prd.out.scatterEvent
62+
prd.out.emitted = emitted();
63+
prd.out.scatterEvent
5764
= scatter(ray,
5865
*prd.in.randState,
5966
prd.out.scattered_origin,

OptiX-Path-Tracer/programs/materials/metal.cu

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,16 @@ rtDeclareVariable(PerRayData, prd, rtPayload, );
2323
rtDeclareVariable(rtObject, world, , );
2424

2525

26-
2726
/*! the attributes we use to communicate between intersection programs and hit program */
2827
rtDeclareVariable(float3, hit_rec_normal, attribute hit_rec_normal, );
2928
rtDeclareVariable(float3, hit_rec_p, attribute hit_rec_p, );
30-
29+
rtDeclareVariable(float, hit_rec_u, attribute hit_rec_u, );
30+
rtDeclareVariable(float, hit_rec_v, attribute hit_rec_v, );
3131

3232
/*! and finally - that particular material's parameters */
3333
rtDeclareVariable(rtCallableProgramId<float3(float, float, float3)>, sample_texture, , );
3434
rtDeclareVariable(float, fuzz, , );
3535

36-
3736
/*! the actual scatter function - in Pete's reference code, that's a
3837
virtual function, but since we have a different function per program
3938
we do not need this here */
@@ -46,12 +45,16 @@ inline __device__ bool scatter(const optix::Ray &ray_in,
4645
vec3f reflected = reflect(unit_vector(ray_in.direction),hit_rec_normal);
4746
scattered_origin = hit_rec_p;
4847
scattered_direction = (reflected+fuzz*random_in_unit_sphere(rndState));
49-
attenuation = sample_texture(0.f, 0.f, hit_rec_p);
48+
attenuation = sample_texture(hit_rec_u, hit_rec_v, hit_rec_p);
5049
return (dot(scattered_direction, hrn) > 0.f);
5150
}
5251

53-
RT_PROGRAM void closest_hit()
54-
{
52+
inline __device__ float3 emitted(){
53+
return make_float3(0.f, 0.f, 0.f);
54+
}
55+
56+
RT_PROGRAM void closest_hit() {
57+
prd.out.emitted = emitted();
5558
prd.out.scatterEvent
5659
= scatter(ray,
5760
*prd.in.randState,

0 commit comments

Comments
 (0)