diff --git a/Primitives.cpp b/Primitives.cpp new file mode 100644 index 0000000..fd64646 --- /dev/null +++ b/Primitives.cpp @@ -0,0 +1 @@ +#include "Primitives.h" \ No newline at end of file diff --git a/Primitives.h b/Primitives.h index 0ad9322..734d69f 100644 --- a/Primitives.h +++ b/Primitives.h @@ -1,9 +1,4 @@ #pragma once -#ifndef STB_IMAGE_IMPLEMENTATION -#define STBI_MSC_SECURE_CRT -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#endif #include #include #include "Types.h" @@ -29,7 +24,9 @@ class Primitive { std::vector vertex_colors; std::vector triangle_verts; - void (*surface_shade)(VertexShaderPayload& pi) = nullptr; + void (*geometric_shader)(GeometricShaderPayload& p) = nullptr; + void (*surface_shader)(FragmentShaderPayload& p) = nullptr; + std::shared_ptr texture; void setup_vectors(int l) { world_points.resize(l); @@ -79,7 +76,7 @@ class Primitive { virtual void get_bounding_cube() = 0; - virtual Eigen::Vector4f get_3D_coordinates(float u_n, float v_n) = 0; + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& pos, Eigen::Vector4f& norm) = 0; int get_dice_factor(int width, int height) { @@ -109,6 +106,15 @@ class Primitive { bb_top_y = screen_y; } + // clamp to left edge + bb_left_x = std::max(bb_left_x, 0.0f); + //clamp to right edge + bb_right_x = std::min(bb_right_x, (float)width); + //clamp to bottom edge + bb_bottom_y = std::max(bb_bottom_y, 0.0f); + //clamp to top edge + bb_top_y = std::min(bb_top_y, (float)height); + //if it will be on the screen, how many pixels will it take up? int xFactor = (bb_right_x - bb_left_x) * MICROPOLYGONS_PER_PIXEL; int yFactor = (bb_top_y - bb_bottom_y) * MICROPOLYGONS_PER_PIXEL; @@ -130,11 +136,10 @@ class Primitive { float u_n = (float)u / ((float)grid_width - 1); float v_n = (float)v / ((float)grid_height - 1); - Eigen::Vector4f position = get_3D_coordinates(u_n, v_n); - position.w() = 0.0f; - Eigen::Vector4f normal = position.normalized(); - normal.w() = 1.0f; - position.w() = 1.0f; + Eigen::Vector4f position; + Eigen::Vector4f normal; + + get_3D_coordinates(u_n, v_n, position, normal); points[i] = position; normals[i] = normal; @@ -183,51 +188,21 @@ class Primitive { } - void shade() { - //texture_map(); - //apply_checker_shade(); - for (int i = 0; i < points.size(); ++i) { - UVTuple tup = get_uv(i); - auto u = (float)tup.u / (float)(dice_factor - 1); - auto v = (float)tup.v / (float)(dice_factor - 1); - - /*Point p; - p.u = u; - p.v = v; - p.c = vertex_colors[i]; - - surface_shade(p); - vertex_colors[i] = p.c;*/ - } - } - - - void texture_map() { - int x, y, n; - unsigned char* data = stbi_load("textures\\earth_2.jpg", &x, &y, &n, 0); - - for (int i = 0; i < points.size(); ++i) { - UVTuple p = get_uv(i); - auto u = (float)p.u / (float)(dice_factor - 1); - auto v = (float)p.v / (float)(dice_factor - 1); - - int img_x = u * (x); - int img_y = v * (y); - - img_x = img_x % x; - img_y = img_y % y; + void sh() { + if (geometric_shader == nullptr) + return; - // we want image processing to start from top left corner - // instead of bottom left corner. So flipping x and y in index value - int id = (img_y * x + img_x)*3; - uint8_t r = data[id]; - uint8_t g = data[id + 1]; - uint8_t b = data[id + 2]; + GeometricShaderPayload p; + p.dice_factor = dice_factor; + p.normals = normals; + p.points = points; + p.triangle_verts = triangle_verts; - vertex_colors[i] = Color(r, g, b); - } + geometric_shader(p); - stbi_image_free(data); + normals = p.normals; + points = p.points; + triangle_verts = p.triangle_verts; } @@ -263,8 +238,7 @@ class Sphere : public Primitive { b_cube_vertices[7] = Eigen::Vector4f(-1 * radius, radius, -1 * radius, 1.0f); } - virtual Eigen::Vector4f get_3D_coordinates(float u_n, float v_n) { - Eigen::Vector4f position; + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& position, Eigen::Vector4f& normal) { float phi = phimin + v_n * (phimax - phimin); float theta = u_n * thetamax; @@ -272,9 +246,10 @@ class Sphere : public Primitive { position.x() = radius * std::cos(theta) * std::cos(phi); position.y() = radius * std::sin(theta) * std::cos(phi); position.z() = radius * std::sin(phi); - position.w() = 1.0f; - return position; + position.w() = 0.0f; + normal = position.normalized(); + position.w() = 1.0f; } }; @@ -304,15 +279,19 @@ class Cylinder : public Primitive { b_cube_vertices[7] = Eigen::Vector4f(radius, -1 * radius, zmax, 1.0f); } - virtual Eigen::Vector4f get_3D_coordinates(float u_n, float v_n) { - Eigen::Vector4f position; + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& position, Eigen::Vector4f& normal) { + float theta = u_n * thetamax; position.x() = radius * cos(theta); position.y() = radius * sin(theta); position.z() = zmin + v_n * (zmax - zmin); position.w() = 1.0f; - return position; + normal.x() = position.x(); + normal.y() = position.y(); + normal.z() = 0.0f; + normal.w() = 0.0f; + normal.normalize(); } }; @@ -349,8 +328,7 @@ class Torus : public Primitive { } - virtual Eigen::Vector4f get_3D_coordinates(float u_n, float v_n) { - Eigen::Vector4f position; + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& position, Eigen::Vector4f& normal) { float phi = phi_min + v_n * (phi_max - phi_min); float theta = u_n * theta_max; @@ -361,53 +339,68 @@ class Torus : public Primitive { position.z() = minor_r * std::sin(phi); position.w() = 1.0f; - return position; + Eigen::Vector4f t(major_r * std::cos(theta), major_r * std::sin(theta), 0.0f, 0.0f); + normal = (position - t).normalized(); } }; -class Patch : public Primitive { +class Cone : public Primitive { public: - std::vector control_points; + float height, radius; + float thetamax; - - Patch(std::vector cp, float scale) { - this->control_points = cp; - for (int i = 0; i < control_points.size(); ++i) - control_points[i] *= scale; + Cone(float height, float radius, float tmax) { + this->radius = radius; + this->height = height; + this->thetamax = tmax * PI / 180.0f; + } + + virtual void get_bounding_cube() { + b_cube_vertices[0] = Eigen::Vector4f(radius, radius, 0.0f, 1.0f); + b_cube_vertices[1] = Eigen::Vector4f(-1 * radius, radius, 0.0f, 1.0f); + b_cube_vertices[2] = Eigen::Vector4f(-1 * radius, -1 * radius, 0.0f, 1.0f); + b_cube_vertices[3] = Eigen::Vector4f(radius, -1 * radius, 0.0f, 1.0f); + + b_cube_vertices[4] = Eigen::Vector4f(radius, radius, height, 1.0f); + b_cube_vertices[5] = Eigen::Vector4f(-1 * radius, radius, height, 1.0f); + b_cube_vertices[6] = Eigen::Vector4f(-1 * radius, -1 * radius, height, 1.0f); + b_cube_vertices[7] = Eigen::Vector4f(radius, -1 * radius, height, 1.0f); } - Eigen::Vector3f eval_curve(Eigen::Vector3f cp[4], float t) { + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& position, Eigen::Vector4f& normal) { - Eigen::Vector3f P01 = (1 - t) * cp[0] + t * cp[1]; - Eigen::Vector3f P12 = (1 - t) * cp[1] + t * cp[2]; - Eigen::Vector3f P23 = (1 - t) * cp[2] + t * cp[3]; + float theta = u_n * thetamax; - Eigen::Vector3f a = (1 - t) * P01 + t * P12; - Eigen::Vector3f b = (1 - t) * P12 + t * P23; + position.x() = radius * (1 - v_n) * std::cos(theta); + position.y() = radius * (1 - v_n) * std::sin(theta); + position.z() = v_n * height; + position.w() = 1.0f; - return ((1 - t) * a) + (t * b); + //vector from center to position + Eigen::Vector4f V(position.x(), position.y(), 0.0f, 1.0f); + V.normalize(); + normal.x() = V.x() * height / radius; + normal.y() = V.y() * height / radius; + normal.z() = radius / height; + normal.w() = 0.0f; + normal.normalize(); } +}; - Eigen::Vector3f eval_surface(float u, float v) { - Eigen::Vector3f ucurve_cp[4]; - for (int i = 0; i < 4; ++i) { - // select 4 points for a curve - Eigen::Vector3f curve[4]; - int k = i * 4; - curve[0] = control_points[k]; - curve[1] = control_points[k + 1]; - curve[2] = control_points[k + 2]; - curve[3] = control_points[k + 3]; - ucurve_cp[i] = eval_curve(curve, u); - } +class Patch : public Primitive { +public: + std::vector control_points; - auto z = eval_curve(ucurve_cp, v); - return z; + + Patch(std::vector cp, float scale) { + this->control_points = cp; + for (int i = 0; i < control_points.size(); ++i) + control_points[i] *= scale; } virtual void get_bounding_cube() { @@ -419,7 +412,7 @@ class Patch : public Primitive { for (int i = 0; i < 16; ++i) { auto p = control_points[i]; - + if (p.x() < l.x()) l.x() = p.x(); @@ -459,8 +452,96 @@ class Patch : public Primitive { b_cube_vertices[7] = Eigen::Vector4f(h.x(), h.y(), h.z(), 1.0f); } - virtual Eigen::Vector4f get_3D_coordinates(float u_n, float v_n) { + inline Eigen::Vector3f eval_curve(Eigen::Vector3f cp[4], float t) { + + Eigen::Vector3f P01 = (1 - t) * cp[0] + t * cp[1]; + Eigen::Vector3f P12 = (1 - t) * cp[1] + t * cp[2]; + Eigen::Vector3f P23 = (1 - t) * cp[2] + t * cp[3]; + + Eigen::Vector3f a = (1 - t) * P01 + t * P12; + Eigen::Vector3f b = (1 - t) * P12 + t * P23; + + return ((1 - t) * a) + (t * b); + + } + + Eigen::Vector3f eval_surface(float u, float v) { + + Eigen::Vector3f ucurve_cp[4]; + for (int i = 0; i < 4; ++i) { + // select 4 points for a curve + Eigen::Vector3f curve[4]; + int k = i * 4; + curve[0] = control_points[k]; + curve[1] = control_points[k + 1]; + curve[2] = control_points[k + 2]; + curve[3] = control_points[k + 3]; + ucurve_cp[i] = eval_curve(curve, u); + } + + auto z = eval_curve(ucurve_cp, v); + return z; + } + + Eigen::Vector3f dU(float u, float v) { + + Eigen::Vector3f P[4]; + Eigen::Vector3f v_curve[4]; + for (int i = 0; i < 4; ++i) { + P[0] = control_points[i]; + P[1] = control_points[4 + i]; + P[2] = control_points[8 + i]; + P[3] = control_points[12 + i]; + v_curve[i] = eval_curve(P, v); + } + + return -3 * (1 - u) * (1 - u) * v_curve[0] + + (3 * (1 - u) * (1 - u) - 6 * u * (1 - u)) * v_curve[1] + + (6 * u * (1 - u) - 3 * u * u) * v_curve[2] + + 3 * u * u * v_curve[3]; + } + + Eigen::Vector3f dV(float u, float v) + { + Eigen::Vector3f u_curve[4]; + for (int i = 0; i < 4; ++i) { + + Eigen::Vector3f curve[4]; + int k = i * 4; + curve[0] = control_points[k]; + curve[1] = control_points[k + 1]; + curve[2] = control_points[k + 2]; + curve[3] = control_points[k + 3]; + u_curve[i] = eval_curve(curve, u); + + } + + return -3 * (1 - v) * (1 - v) * u_curve[0] + + (3 * (1 - v) * (1 - v) - 6 * v * (1 - v)) * u_curve[1] + + (6 * v * (1 - v) - 3 * v * v) * u_curve[2] + + 3 * v * v * u_curve[3]; + } + + virtual void get_3D_coordinates(float u_n, float v_n, Eigen::Vector4f& position, Eigen::Vector4f& normal) { Eigen::Vector3f p = eval_surface(u_n, v_n); - return Eigen::Vector4f(p.x(), p.y(), p.z(), 1.0f); + position.x() = p.x(); + position.y() = p.y(); + position.z() = p.z(); + position.w() = 1.0f; + + Eigen::Vector3f dU_vec = dU(u_n, v_n); + Eigen::Vector3f dV_vec = dV(u_n, v_n); + Eigen::Vector3f n = dU_vec.cross(dV_vec); + normal.x() = n.x(); + normal.y() = n.y(); + normal.z() = n.z(); + normal.w() = 0.0f; + + + /*normal.x() = p.x(); + normal.y() = p.y(); + normal.z() = p.z(); + normal.w() = 0.0f; + normal.normalize();*/ } }; diff --git a/Renderer.cpp b/Renderer.cpp new file mode 100644 index 0000000..00aa2fd --- /dev/null +++ b/Renderer.cpp @@ -0,0 +1,310 @@ +#pragma once +#define STBI_MSC_SECURE_CRT +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" +#include + +#include "Types.h" +#include "Primitives.h" +#include "States.h" +#include "Buffers.h" +#include "Shaders.h" +#include "Renderer.h" + +std::shared_ptr fb_ptr; +std::shared_ptr zb_ptr; + +inline +float edge_function(const Eigen::Vector4f& a, const Eigen::Vector4f& b, const Eigen::Vector4f& c) +{ + return ((c.x() - a.x()) * (b.y() - a.y()) - (c.y() - a.y()) * (b.x() - a.x())); +} + +inline UVTuple interpolate_uv(float w0, float w1, float w2, UVTuple uv[3]) { + auto u = (w0 * uv[0].u + w1 * uv[1].u + w2 * uv[2].u); + auto v = (w0 * uv[0].v + w1 * uv[1].v + w2 * uv[2].v); + + UVTuple r; + r.u = u; + r.v = v; + return r; +} + +inline Eigen::Vector4f interpolate_vector(float w0, float w1, float w2, Eigen::Vector4f normals[3]) { + auto interpolated = w0 * normals[0] + w1 * normals[1] + w2 * normals[2]; + return interpolated; +} + +inline +void sample(int x, int y, int xsamples, int ysamples, FrameBuffer& fb, ZBuffer& zb, + Triangle t, void (*surface_shader)(FragmentShaderPayload& p), + std::shared_ptr texture) { + + // default background color + Eigen::Vector3f pixel_color(0, 0, 0); + for (float m = 0; m < xsamples; ++m) { + for (float n = 0; n < ysamples; ++n) { + + float mMin = (float)m / xsamples + (0.5f / xsamples); + float nMin = (float)n / ysamples + (0.5f / ysamples); + float mMax = (float)(m + 1) / xsamples; + float nMax = (float)(n + 1) / ysamples; + + //using random sampling values makes stuff noisy + //float x_delta = ((float)rand() / RAND_MAX) * (mMax - mMin) + mMin; + //float y_delta = ((float)rand() / RAND_MAX) * (nMax - nMin) + nMin; + + float sample_x = x + mMin; + float sample_y = y + nMin; + + Eigen::Vector4f sample(sample_x, sample_y, 0.0, 0.0); + auto v0 = t.screen_coordinates[0]; + auto v1 = t.screen_coordinates[1]; + auto v2 = t.screen_coordinates[2]; + + float area = edge_function(v0, v1, v2); + float w0 = edge_function(v1, v2, sample); + float w1 = edge_function(v2, v0, sample); + float w2 = edge_function(v0, v1, sample); + + // The second or condition prevents back face culling, helping us + // render inside surfaces of primitives + bool is_inside = (w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 < 0 && w1 < 0 && w2 < 0); + + if (is_inside) { + // compute barycentriic coordinates + w0 /= area; + w1 /= area; + w2 /= area; + + /*--------------------------*/ + float w_reciprocal = 1.0 / (w0 / v0.w() + w1 / v1.w() + w2 / v2.w()); + float z_interpolated = w0 * v0.z() / v0.w() + w1 * v1.z() / v1.w() + w2 * v2.z() / v2.w(); + z_interpolated *= w_reciprocal; + float z = z_interpolated; + + // linearly interpolate sample depth + //float oneOverZ = v0.z() * w0 + v1.z() * w1 + v2.z() * w2; + //float z = 1 / oneOverZ; + + if (z < zb(x, y, m, n).front()) { + zb(x, y, m, n).push_front(z); + + auto c = t.colors; + + Color c0 = w0 * c[0]; + Color c1 = w1 * c[1]; + Color c2 = w2 * c[2]; + Color c_interpolated = c0 + c1 + c2; + + UVTuple uv = interpolate_uv(w0, w1, w2, t.uv_tups); + auto interpolated_xyz = interpolate_vector(w0, w1, w2, t.world_coordinates); + auto interpolated_normal = interpolate_vector(w0, w1, w2, t.normals); + + FragmentShaderPayload p; + p.u = uv.u; + p.v = uv.v; + p.texture = texture; + p.pos = interpolated_xyz; + p.normal = interpolated_normal; + p.c = c_interpolated; + + if(surface_shader != nullptr) + surface_shader(p); + + phong(p); + c_interpolated = p.c; + fb(x, y, m, n) = c_interpolated; + + } + } + + } + } + +} + + +void pimage(FrameBuffer& frame_buffer, const char* filename) { + //const char* f = "D:\\stbjpg3.jpg"; + const int CHANNEL_NUM = 3; + + int width = frame_buffer.w; + int height = frame_buffer.h; + + //grey background + uint8_t* out_buffer = new uint8_t[width * height * CHANNEL_NUM](); + + // Set background color + // For the following framebuffer, (0,0) pixel is at the top left + int index = 0; + for (int x = 0; x < width; ++x) + { + for (int y = 0; y < height; ++y) + { + index = (y * width * 3) + x * 3; + Color pix_color = frame_buffer.collapse(x, y); + out_buffer[index++] = pix_color.ir(); + out_buffer[index++] = pix_color.ig(); + out_buffer[index++] = pix_color.ib(); + } + } + + stbi_write_jpg(filename, width, height, 3, out_buffer, 100); + delete[] out_buffer; +} + +void setup_buffers(int w, int h, int xs, int ys) { + + bool is_empty = !(fb_ptr && zb_ptr); + if (is_empty) { + fb_ptr = std::make_shared(w, h, xs, ys); + zb_ptr = std::make_shared(w, h, xs, ys); + return; + } + + + bool change = (w != fb_ptr->w || h != fb_ptr->h || xs != fb_ptr->xsamples || ys != fb_ptr->ysamples); + if (change) { + fb_ptr = std::make_shared(w, h, xs, ys); + zb_ptr = std::make_shared(w, h, xs, ys); + } + + else { + for (int x = 0; x < w; ++x) { + for (int y = 0; y < h; ++y) { + for (int m = 0; m < xs; ++m) { + for (int n = 0; n < ys; ++n) { + fb_ptr->operator()(x, y, m, n) = Color(); + zb_ptr->operator()(x, y, m, n).clear(); + } + } + } + } + } +} + +void render_frame(WorldState& world_state, RenderState& render_state, ImageState& image_state) { + const int xsamples = render_state.xsamples; + const int ysamples = render_state.ysamples; + const int width = image_state.x_resolution; + const int height = image_state.y_resolution; + + std::shared_ptr texture; + void (*surface_shader)(FragmentShaderPayload & p) = nullptr; + //void (*geometric_shader)(GeometricShaderPayload & p) = checker_explode; + + setup_buffers(width, height, xsamples, ysamples); + + std::vector>& world_obj_ptrs = world_state.object_ptrs; + + for (int i = 0; i < world_obj_ptrs.size(); ++i) { + + std::unique_ptr objPtr = std::move(world_obj_ptrs[i]); + objPtr->build(width, height); + objPtr->sh(); + surface_shader = objPtr->surface_shader; + texture = objPtr->texture; + + auto& points = objPtr->points; + for (int j = 0; j < points.size(); ++j) { + auto p = objPtr->points[j]; + + Eigen::Vector4f sp = objPtr->mvp * p; + // For some reason x axis and y axis are flipped, so multiplying by -1 + sp.x() = sp.x() / sp.w() * 1; + sp.y() = sp.y() / sp.w() * 1; + sp.z() = sp.z() / sp.w(); + + Eigen::Vector4f wp = objPtr->m * p; + //wp.x() = wp.x() * 1; + //wp.y() = wp.y() * 1; + + Eigen::Vector4f pixel_coordinate_space; + float screen_x = (sp.x() + 1.0f) * 0.5f * width; + float screen_y = (1.0 - (sp.y() + 1.0f) * 0.5f) * height; + sp.x() = screen_x; + sp.y() = screen_y; + + points[j] = sp; + //objPtr->normals[j] = wp.normalized(); + objPtr->world_points[j] = wp; + + Eigen::Vector4f n = objPtr->normals[j]; + auto m_n = objPtr->m.inverse().transpose(); + n = m_n * n; + //n.normalize(); + objPtr->normals[j] = n; + } + + + // Sample triangles + std::vector triangle_vert_groups = objPtr->triangle_verts; + for (int j = 0; j < triangle_vert_groups.size(); ++j) { + + auto triangle_vert_ids = triangle_vert_groups[j].ids; + + std::vector v({ + points[triangle_vert_ids[0]], + points[triangle_vert_ids[1]], + points[triangle_vert_ids[2]] + }); + + float bb_left_x = width, bb_right_x = 0, bb_top_y = 0, bb_bottom_y = height; + for (int vertex_no = 0; vertex_no < 3; vertex_no++) + { + Eigen::Vector4f triangle_vertex = v[vertex_no]; + //std::cout << "\n" << triangle_vertex << "\n"; + if (triangle_vertex.x() < bb_left_x) + bb_left_x = triangle_vertex.x(); + if (triangle_vertex.x() > bb_right_x) + bb_right_x = triangle_vertex.x(); + if (triangle_vertex.y() < bb_bottom_y) + bb_bottom_y = triangle_vertex.y(); + if (triangle_vertex.y() > bb_top_y) + bb_top_y = triangle_vertex.y(); + } + + // clamp to left edge + bb_left_x = std::max(bb_left_x, 0.0f); + //clamp to right edge + bb_right_x = std::min(bb_right_x, (float)width); + //clamp to bottom edge + bb_bottom_y = std::max(bb_bottom_y, 0.0f); + //clamp to top edge + bb_top_y = std::min(bb_top_y, (float)height); + + + for (int x = bb_left_x; x < bb_right_x; x++) + { + for (int y = bb_bottom_y; y < bb_top_y; y++) + { + + Triangle tri; + for (int k = 0; k < 3; ++k) { + tri.screen_coordinates[k] = v[k]; + tri.world_coordinates[k] = objPtr->world_points[triangle_vert_ids[k]]; + tri.colors[k] = objPtr->vertex_colors[triangle_vert_ids[k]]; + tri.uv_tups[k] = objPtr->get_uv(triangle_vert_ids[k]); + tri.normals[k] = objPtr->normals[triangle_vert_ids[k]]; + } + + sample( + x, y, xsamples, ysamples, + *fb_ptr, *zb_ptr, + tri, surface_shader, texture + ); + } + } + + + + } + + + } + + + pimage(*fb_ptr, image_state.filename.c_str()); + +} \ No newline at end of file diff --git a/Renderer.h b/Renderer.h index f8f39c1..942a958 100644 --- a/Renderer.h +++ b/Renderer.h @@ -1,16 +1,10 @@ #pragma once -#define STBI_MSC_SECURE_CRT -#define STB_IMAGE_WRITE_IMPLEMENTATION -#include "stb_image_write.h" + #include "Types.h" -#include "Primitives.h" #include "States.h" #include -#include -#include #include "Buffers.h" -#include -#include "Shaders.h" + //#define _USE_MATH_DEFINES //#include //#include @@ -18,263 +12,17 @@ inline -float edge_function(const Eigen::Vector4f& a, const Eigen::Vector4f& b, const Eigen::Vector4f& c) -{ - return ((c.x() - a.x()) * (b.y() - a.y()) - (c.y() - a.y()) * (b.x() - a.x())); -} - -inline UVTuple interpolate_uv(float w0, float w1, float w2, UVTuple uv[3]) { - auto u = (w0 * uv[0].u + w1 * uv[1].u + w2 * uv[2].u); - auto v = (w0 * uv[0].v + w1 * uv[1].v + w2 * uv[2].v); - - UVTuple r; - r.u = u; - r.v = v; - return r; -} +float edge_function(const Eigen::Vector4f& a, const Eigen::Vector4f& b, const Eigen::Vector4f& c); -inline Eigen::Vector4f interpolate_vector(float w0, float w1, float w2, Eigen::Vector4f normals[3]) { - auto interpolated = w0 * normals[0] + w1 * normals[1] + w2 * normals[2]; - return interpolated; -} +inline UVTuple interpolate_uv(float w0, float w1, float w2, UVTuple uv[3]); +inline Eigen::Vector4f interpolate_vector(float w0, float w1, float w2, Eigen::Vector4f normals[3]); inline void sample(int x, int y, int xsamples, int ysamples, FrameBuffer& fb, ZBuffer& zb, - Triangle t, void (*surface_shader)(FragmentShaderPayload& p), - std::shared_ptr texture) { - - // default background color - Eigen::Vector3f pixel_color(0, 0, 0); - for (float m = 0; m < xsamples; ++m) { - for (float n = 0; n < ysamples; ++n) { - - float mMin = (float)m / xsamples + (0.5f / xsamples); - float nMin = (float)n / ysamples + (0.5f / ysamples); - float mMax = (float)(m + 1) / xsamples; - float nMax = (float)(n + 1) / ysamples; - - //using random sampling values makes stuff noisy - //float x_delta = ((float)rand() / RAND_MAX) * (mMax - mMin) + mMin; - //float y_delta = ((float)rand() / RAND_MAX) * (nMax - nMin) + nMin; - - float sample_x = x + mMin; - float sample_y = y + nMin; - - Eigen::Vector4f sample(sample_x, sample_y, 0.0, 0.0); - auto v0 = t.screen_coordinates[0]; - auto v1 = t.screen_coordinates[1]; - auto v2 = t.screen_coordinates[2]; - - float area = edge_function(v0, v1, v2); - float w0 = edge_function(v1, v2, sample); - float w1 = edge_function(v2, v0, sample); - float w2 = edge_function(v0, v1, sample); - - bool is_inside = (w0 >= 0 && w1 >= 0 && w2 >= 0); - - if (is_inside) { - // compute barycentriic coordinates - w0 /= area; - w1 /= area; - w2 /= area; - - /*--------------------------*/ - float w_reciprocal = 1.0 / (w0 / v0.w() + w1 / v1.w() + w2 / v2.w()); - float z_interpolated = w0 * v0.z() / v0.w() + w1 * v1.z() / v1.w() + w2 * v2.z() / v2.w(); - z_interpolated *= w_reciprocal; - float z = z_interpolated; - - // linearly interpolate sample depth - //float oneOverZ = v0.z() * w0 + v1.z() * w1 + v2.z() * w2; - //float z = 1 / oneOverZ; - - if (z < zb(x, y, m, n).front()) { - zb(x, y, m, n).push_front(z); - - auto c = t.colors; - - Color c0 = w0 * c[0]; - Color c1 = w1 * c[1]; - Color c2 = w2 * c[2]; - Color c_interpolated = c0 + c1 + c2; - - UVTuple uv = interpolate_uv(w0, w1, w2, t.uv_tups); - auto interpolated_xyz = interpolate_vector(w0, w1, w2, t.world_coordinates); - auto interpolated_normal = interpolate_vector(w0, w1, w2, t.normals); - - FragmentShaderPayload p; - p.u = uv.u; - p.v = uv.v; - p.texture = texture; - p.pos = interpolated_xyz; - p.normal = interpolated_normal; - p.c = c_interpolated; - - - //surface_shader(p); - light(p); - c_interpolated = p.c; - fb(x, y, m, n) = c_interpolated; - - } - } - - } - } - -} - - -void pimage(FrameBuffer frame_buffer, const char* filename) { - const char* f = "D:\\stbjpg3.jpg"; - const int CHANNEL_NUM = 3; - - int width = frame_buffer.w; - int height = frame_buffer.h; - - //grey background - uint8_t* out_buffer = new uint8_t[width * height * CHANNEL_NUM](); - - // Set background color - // For the following framebuffer, (0,0) pixel is at the top left - int index = 0; - for (int x = 0; x < width; ++x) - { - for (int y = 0; y < height; ++y) - { - index = (y * width * 3) + x * 3; - Color pix_color = frame_buffer.collapse(x, y); - out_buffer[index++] = pix_color.ir(); - out_buffer[index++] = pix_color.ig(); - out_buffer[index++] = pix_color.ib(); - } - } - - stbi_write_jpg(f, width, height, 3, out_buffer, 100); - delete[] out_buffer; -} - -void render_frame(WorldState& world_state, RenderState& render_state, ImageState& image_state) { - const int xsamples = render_state.xsamples; - const int ysamples = render_state.ysamples; - const int width = image_state.x_resolution; - const int height = image_state.y_resolution; - - std::shared_ptr texture = std::make_shared(); - void (*surface_shader)(FragmentShaderPayload& p) = earth; - - FrameBuffer frame_buffer(width, height, xsamples, ysamples); - ZBuffer z_buffer(width, height, xsamples, ysamples); - - std::vector>& world_obj_ptrs = world_state.object_ptrs; - - for (int i = 0; i < world_obj_ptrs.size(); ++i) { - - std::unique_ptr objPtr = std::move(world_obj_ptrs[i]); - objPtr->build(width, height); - - auto& points = objPtr->points; - for (int j = 0; j < points.size(); ++j) { - auto p = objPtr->points[j]; - - Eigen::Vector4f sp = objPtr -> mvp * p; - // For some reason x axis and y axis are flipped, so multiplying by -1 - sp.x() = sp.x() / sp.w() * -1; - sp.y() = sp.y() / sp.w() * -1; - sp.z() = sp.z() / sp.w(); - - Eigen::Vector4f wp = objPtr -> m * p; - wp.x() = wp.x() * -1; - wp.y() = wp.y() * -1; - - Eigen::Vector4f pixel_coordinate_space; - - float screen_x = (sp.x() + 1.0f) * 0.5f * width; - float screen_y = (1.0 - (sp.y() + 1.0f) * 0.5f) * height; - sp.x() = screen_x; - sp.y() = screen_y; - - points[j] = sp; - objPtr->world_points[j] = wp; - } - - - // Sample triangles - std::vector triangle_vert_groups = objPtr->triangle_verts; - for (int j = 0; j < triangle_vert_groups.size(); ++j){ - - auto triangle_vert_ids = triangle_vert_groups[j].ids; - - std::vector v({ - points[triangle_vert_ids[0]], - points[triangle_vert_ids[1]], - points[triangle_vert_ids[2]] - }); - - float bb_left_x = width, bb_right_x = 0, bb_top_y = 0, bb_bottom_y = height; - for (int vertex_no = 0; vertex_no < 3; vertex_no++) - { - Eigen::Vector4f triangle_vertex = v[vertex_no]; - //std::cout << "\n" << triangle_vertex << "\n"; - if (triangle_vertex.x() < bb_left_x) - bb_left_x = triangle_vertex.x(); - if (triangle_vertex.x() > bb_right_x) - bb_right_x = triangle_vertex.x(); - if (triangle_vertex.y() < bb_bottom_y) - bb_bottom_y = triangle_vertex.y(); - if (triangle_vertex.y() > bb_top_y) - bb_top_y = triangle_vertex.y(); - } - - // clamp to left edge - bb_left_x = std::max(bb_left_x, 0.0f); - //clamp to right edge - bb_right_x = std::min(bb_right_x, (float)width); - //clamp to bottom edge - bb_bottom_y = std::max(bb_bottom_y, 0.0f); - //clamp to top edge - bb_top_y = std::min(bb_top_y, (float)height); - - - for (int x = bb_left_x; x < bb_right_x; x++) - { - for (int y = bb_bottom_y; y < bb_top_y; y++) - { - - - Triangle tri; - for (int k = 0; k < 3; ++k) { - tri.screen_coordinates[k] = v[k]; - tri.world_coordinates[k] = objPtr->world_points[triangle_vert_ids[k]]; - tri.colors[k] = objPtr->vertex_colors[triangle_vert_ids[k]]; - tri.uv_tups[k] = objPtr->get_uv(triangle_vert_ids[k]); - tri.normals[k] = objPtr->normals[triangle_vert_ids[k]]; - } - - //tri.screen_coordinates[0] = v[0]; - //tri.screen_coordinates[1] = v[1]; - //tri.screen_coordinates[2] = v[2]; - - //tri.colors[0] = objPtr->vertex_colors[triangle_vert_ids[0]]; - //tri.colors[1] = objPtr->vertex_colors[triangle_vert_ids[1]]; - //tri.colors[2] = objPtr->vertex_colors[triangle_vert_ids[2]]; - - sample( - x, y, xsamples, ysamples, - frame_buffer, z_buffer, - tri, surface_shader, texture - ); - } - } - - + Triangle t, void (*surface_shader)(FragmentShaderPayload& p), + std::shared_ptr texture); - } - - - } +void pimage(FrameBuffer& frame_buffer, const char* filename); - pimage(frame_buffer, image_state.filename); - -} \ No newline at end of file +void render_frame(WorldState& world_state, RenderState& render_state, ImageState& image_state); \ No newline at end of file diff --git a/Ri.cpp b/Ri.cpp index eb1d25a..94591e3 100644 --- a/Ri.cpp +++ b/Ri.cpp @@ -1,9 +1,7 @@ #include "Ri.h" -#include "Types.h" #include "Primitives.h" #include "States.h" #include "Renderer.h" -#include "Shaders.h" #include #define PI 3.141592653589793238462643383279502884197 @@ -14,6 +12,9 @@ RenderState render_state; TransformationState transformation_state; WorldState world_state; +RtToken RI_PERSPECTIVE = "perspective"; +RtToken RI_ORTHOGRAPHIC = "orthgraphic"; + Eigen::Matrix4f get_ortho_projection_matrix(float width, float height, float zFar, float zNear) { Eigen::Matrix4f ortho_projection = Eigen::Matrix4f::Identity(); @@ -61,16 +62,21 @@ void RiBegin(RtToken token) { // TODO add reyes defaults render_state = RenderState(); camera_state = CameraState(); + world_state = WorldState(); } void RiEnd() { } +void RiDisplay(char* fname, RtToken type, RtToken mode, ...) { + image_state.filename = std::string(fname); +} + void RiFormat(int x_resolution, int y_resolution, float pixelaspectratio) { image_state.x_resolution = x_resolution; image_state.y_resolution = y_resolution; - image_state.pixelaspectratio = pixelaspectratio; + image_state.pixel_aspect_ratio = pixelaspectratio; //set default frame aspect ratio as image aspect ratio render_state.frame_aspect_ratio = (x_resolution * pixelaspectratio) / y_resolution; @@ -108,12 +114,32 @@ void RiFrameAspectRatio(float aspect_ratio) { render_state.frame_aspect_ratio = aspect_ratio; } -/* -template -void RiProjection(T projetion_type, Args... args) { +//void RiProjection(RtToken name) { +// auto aspect_ratio = image_state.pixel_aspect_ratio; +// auto width = image_state.x_resolution; +// auto height = image_state.y_resolution; +// if (name == RI_PERSPECTIVE) { +// float aspect = aspect_ratio * (float)width / height; +// auto projection_matrix = get_perspective_projection_matrix(45.0f, aspect, 1, 100); +// render_state.view_to_frame_transformation = projection_matrix; +// } +// else if (name == RI_ORTHOGRAPHIC) { +// auto projection_matrix = get_ortho_projection_matrix(50, 50, 1, 100); +// render_state.view_to_frame_transformation = projection_matrix; +// } +//} + +void RiProjection(RtToken projection_type, RtToken fov_t, float fov, RtToken m) { //https://renderman.pixar.com/resources/RenderMan_20/options.html#riprojection + + //auto aspect_ratio = image_state.pixel_aspect_ratio; + auto width = image_state.x_resolution; + auto height = image_state.y_resolution; + float aspect = 1.0f * (float)width / (float)height; + + auto projection_matrix = get_perspective_projection_matrix(fov, aspect, 0.001, 100); + render_state.view_to_frame_transformation = projection_matrix; } -*/ void RiWorldBegin() { @@ -129,6 +155,8 @@ void RiWorldEnd() { void RiFrameEnd() { render_frame(world_state, render_state, image_state); + world_state.object_ptrs.clear(); + render_state.reset(); } @@ -154,10 +182,10 @@ void RiTranslate(RtFloat dx, RtFloat dy, RtFloat dz) { 0, 0, 0, 1; if (transformation_state.is_in_transform_block) { - transformation_state.current_transformation = model * transformation_state.current_transformation; + transformation_state.current_transformation = transformation_state.current_transformation * model; } else { - render_state.transformation = model * render_state.transformation; + render_state.world_to_view_transformation = render_state.world_to_view_transformation * model; } } @@ -183,81 +211,136 @@ void RiRotate(float rotation_angle, float dx, float dy, float dz) { model(3, 3) = 1.0f; if (transformation_state.is_in_transform_block) { - transformation_state.current_transformation = model * transformation_state.current_transformation; + transformation_state.current_transformation = transformation_state.current_transformation * model; } else { - render_state.transformation = model * render_state.transformation; + render_state.world_to_view_transformation = render_state.world_to_view_transformation * model; } } +//void Ri_GeometricShader(void (*geometric_shade)(GeometricShaderPayload& p)) { +// transformation_state.geometric_shade = geometric_shade; +//} - -void RiSphere(float radius, float zmin, float zmax, float tmax) { - auto model_to_world_matrix = transformation_state.current_transformation; - auto world_to_view_transformation = render_state.transformation; - //auto view_to_frame_transformation = get_perspective_projection_matrix(45.0, 1.0, 1, 100); - auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); - - std::unique_ptr ptr = std::make_unique(radius, -1* radius, radius, 360.0f); - ptr->primitive_color = render_state.current_color; - ptr->m = model_to_world_matrix; - ptr->v = world_to_view_transformation; - ptr->p = view_to_frame_transformation; - ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; - //ptr->surface_shade = checkboard; - world_state.object_ptrs.push_back(std::move(ptr)); - +void RiSurface(void (*surface_shader)(FragmentShaderPayload& p)) { + render_state.surface_shader = surface_shader; } +void RiMakeTexture(std::string filepath, int id) { + std::shared_ptr texture = std::make_shared(filepath); + render_state.texture = texture; +} -void RiCylinder(float radius, float zmin, float zmax, float tmax) { - auto model_to_world_matrix = transformation_state.current_transformation; - auto world_to_view_transformation = render_state.transformation; - auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); - //auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); - std::unique_ptr ptr = std::make_unique(radius, zmin, zmax, tmax); +template +void _generate(Args ... args) { + auto model_to_world_transformation = transformation_state.current_transformation; + auto world_to_view_transformation = render_state.world_to_view_transformation; + auto view_to_frame_transformation = render_state.view_to_frame_transformation; + //auto view_to_frame_transformation = get_perspective_projection_matrix(45.0f, 1.0f, 1, 100); + //auto view_to_frame_transformation = get_ortho_projection_matrix(50,50, 0, 100); + + std::unique_ptr ptr = std::make_unique(std::forward(args)...); ptr->primitive_color = render_state.current_color; - ptr->m = model_to_world_matrix; + ptr->m = model_to_world_transformation; ptr->v = world_to_view_transformation; ptr->p = view_to_frame_transformation; - ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; + ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_transformation; + //ptr->geometric_shader = transformation_state.geometric_shade; + ptr->surface_shader = render_state.surface_shader; + ptr->texture = render_state.texture; //ptr->surface_shade = checkboard; world_state.object_ptrs.push_back(std::move(ptr)); } +void RiSphere(float radius, float zmin, float zmax, float tmax, RtToken mode) { + _generate(radius, zmin, zmax, tmax); +} -void RiTorus(float majorRadius, float minorRadius, float phimin, float phimax, float tmax) { - auto model_to_world_matrix = transformation_state.current_transformation; - auto world_to_view_transformation = render_state.transformation; - auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); - //auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); - - std::unique_ptr ptr = std::make_unique(majorRadius, minorRadius, phimin, phimax, tmax); - ptr->primitive_color = render_state.current_color; - ptr->m = model_to_world_matrix; - ptr->v = world_to_view_transformation; - ptr->p = view_to_frame_transformation; - ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; - //ptr->surface_shade = checkboard; - world_state.object_ptrs.push_back(std::move(ptr)); +void RiCylinder(float radius, float zmin, float zmax, float tmax, RtToken mode) { + _generate(radius, zmin, zmax, tmax); } +void RiTorus(float majorRadius, float minorRadius, float phimin, float phimax, float tmax, RtToken mode) { + _generate(majorRadius, minorRadius, phimin, phimax, tmax); +} -void Ri_Patch(std::vector cp) { - auto model_to_world_matrix = transformation_state.current_transformation; - auto world_to_view_transformation = render_state.transformation; - //auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); - auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 0.01, 100); +void RiCone(float height, float radius, float tmax, RtToken mode) { + _generate(height, radius, tmax); +} - std::unique_ptr ptr = std::make_unique(cp, 5.0f); - ptr->primitive_color = render_state.current_color; - ptr->m = model_to_world_matrix; - ptr->v = world_to_view_transformation; - ptr->p = view_to_frame_transformation; - ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; - //ptr->surface_shade = checkboard; - world_state.object_ptrs.push_back(std::move(ptr)); +void Ri_Patch(std::vector cp, RtToken mode) { + _generate(cp, 1.0f); } +//void RiSphere(float radius, float zmin, float zmax, float tmax) { +// auto model_to_world_matrix = transformation_state.current_transformation; +// auto world_to_view_transformation = render_state.transformation; +// auto view_to_frame_transformation = get_perspective_projection_matrix(45.0, 1.0, 1, 100); +// //auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); +// +// std::unique_ptr ptr = std::make_unique(radius, -1* radius, radius, 360.0f); +// ptr->primitive_color = render_state.current_color; +// ptr->m = model_to_world_matrix; +// ptr->v = world_to_view_transformation; +// ptr->p = view_to_frame_transformation; +// ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; +// ptr->geometric_shader = transformation_state.geometric_shade; +// //ptr->surface_shade = checkboard; +// world_state.object_ptrs.push_back(std::move(ptr)); +// +//} +// +// +//void RiCylinder(float radius, float zmin, float zmax, float tmax) { +// auto model_to_world_matrix = transformation_state.current_transformation; +// auto world_to_view_transformation = render_state.transformation; +// auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); +// //auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); +// +// std::unique_ptr ptr = std::make_unique(radius, zmin, zmax, tmax); +// ptr->primitive_color = render_state.current_color; +// ptr->m = model_to_world_matrix; +// ptr->v = world_to_view_transformation; +// ptr->p = view_to_frame_transformation; +// ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; +// ptr->geometric_shader = transformation_state.geometric_shade; +// //ptr->surface_shade = checkboard; +// world_state.object_ptrs.push_back(std::move(ptr)); +//} +// +// +//void RiTorus(float majorRadius, float minorRadius, float phimin, float phimax, float tmax) { +// auto model_to_world_matrix = transformation_state.current_transformation; +// auto world_to_view_transformation = render_state.transformation; +// auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); +// //auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 1, 100); +// +// std::unique_ptr ptr = std::make_unique(majorRadius, minorRadius, phimin, phimax, tmax); +// ptr->primitive_color = render_state.current_color; +// ptr->m = model_to_world_matrix; +// ptr->v = world_to_view_transformation; +// ptr->p = view_to_frame_transformation; +// ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; +// ptr->geometric_shader = transformation_state.geometric_shade; +// //ptr->surface_shade = checkboard; +// world_state.object_ptrs.push_back(std::move(ptr)); +//} +// +// +//void Ri_Patch(std::vector cp) { +// auto model_to_world_matrix = transformation_state.current_transformation; +// auto world_to_view_transformation = render_state.transformation; +// //auto view_to_frame_transformation = get_perspective_projection_matrix(90.0f, 1.0, 1, 100); +// auto view_to_frame_transformation = get_ortho_projection_matrix(50, 50, 0.01, 100); +// +// std::unique_ptr ptr = std::make_unique(cp, 5.0f); +// ptr->primitive_color = render_state.current_color; +// ptr->m = model_to_world_matrix; +// ptr->v = world_to_view_transformation; +// ptr->p = view_to_frame_transformation; +// ptr->mvp = view_to_frame_transformation * world_to_view_transformation * model_to_world_matrix; +// ptr->geometric_shader = transformation_state.geometric_shade; +// world_state.object_ptrs.push_back(std::move(ptr)); +//} diff --git a/Ri.h b/Ri.h index fba6c1c..b741ad3 100644 --- a/Ri.h +++ b/Ri.h @@ -4,7 +4,8 @@ * (for ANSI Standard C) */ /* Definitions of Abstract Types used in RI */ -#include "Eigen/Eigen" +#include +#include "Types.h" typedef short RtBoolean; typedef int RtInt; @@ -105,7 +106,8 @@ RiFormat(RtInt xres, RtInt yres, RtFloat aspect), RiFrameAspectRatio(RtFloat aspect), RiScreenWindow(RtFloat left, RtFloat right, RtFloat bot, RtFloat top), RiCropWindow(RtFloat xmin, RtFloat xmax, RtFloat ymin, RtFloat ymax), -RiProjection(RtToken name, ...), +//RiProjection(RtToken name, ...), +RiProjection(RtToken projection_type, RtToken fov_t, float fov, RtToken m), RiProjectionV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]), RiClipping(RtFloat hither, RtFloat yon), RiClippingPlane(RtFloat x, RtFloat y, RtFloat z, @@ -144,7 +146,8 @@ RiAreaLightSourceV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]); extern RtVoid RiIlluminate(RtLightHandle light, RtBoolean onoff), -RiSurface(RtToken name, ...), +//RiSurface(RtToken name, ...), +RiSurface(void (*surface_shader)(FragmentShaderPayload& p)), RiSurfaceV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]), RiAtmosphere(RtToken name, ...), RiAtmosphereV(RtToken name, RtInt n, RtToken tokens[], RtPointer parms[]), @@ -217,13 +220,13 @@ RiGeneralPolygonV(RtInt nloops, RtInt nverts[], RtFloat knot[], RtFloat min[], RtFloat max[], RtInt n[], RtFloat u[], RtFloat v[], RtFloat w[]); extern RtVoid -RiSphere(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax), +RiSphere(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, RtToken m), RiSphereV(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, RtInt n, RtToken tokens[], RtPointer parms[]), - RiCone(RtFloat height, RtFloat radius, RtFloat tmax, ...), + RiCone(RtFloat height, RtFloat radius, RtFloat tmax, RtToken m), RiConeV(RtFloat height, RtFloat radius, RtFloat tmax, RtInt n, RtToken tokens[], RtPointer parms[]), - RiCylinder(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax), + RiCylinder(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, RtToken m), RiCylinderV(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, RtInt n, RtToken tokens[], RtPointer parms[]), RiHyperboloid(RtPoint point1, RtPoint point2, RtFloat tmax, ...), @@ -236,7 +239,7 @@ RiSphereV(RtFloat radius, RtFloat zmin, RtFloat zmax, RtFloat tmax, RiDiskV(RtFloat height, RtFloat radius, RtFloat tmax, RtInt n, RtToken tokens[], RtPointer parms[]), RiTorus(RtFloat majrad, RtFloat minrad, RtFloat phimin, - RtFloat phimax, RtFloat tmax), + RtFloat phimax, RtFloat tmax, RtToken m), RiTorusV(RtFloat majrad, RtFloat minrad, RtFloat phimin, RtFloat phimax, RtFloat tmax, RtInt n, RtToken tokens[], RtPointer parms[]); @@ -315,7 +318,12 @@ RiReadArchiveV(RtToken name, RtArchiveCallback callback, RtInt n, RtToken tokens[], RtPointer parms[]); extern RtVoid RiErrorHandler(RtErrorHandler handler); -void Ri_Patch(std::vector cp); +void Ri_Patch(std::vector cp, RtToken m); +void Ri_GeometricShader(void (*geometric_shade)(GeometricShaderPayload& p)); +void Ri_Texture(void (*surface_shader)(FragmentShaderPayload& p)); +template +void _generate(Args...args); +void RiMakeTexture(std::string filepath, int id); /* Error Codes 1 - 10 System and File Errors diff --git a/SamepleScene.cpp b/SamepleScene.cpp index a8aa97c..7509b3c 100644 --- a/SamepleScene.cpp +++ b/SamepleScene.cpp @@ -6,10 +6,11 @@ //#include "Reyes_Impl.h" #include #include +#include "Shaders.h"; inline void parse_teapot_patches() { - std::ifstream input("a.txt"); + std::ifstream input("teapot_points.txt"); std::string line; int num_patch; @@ -28,10 +29,111 @@ inline void parse_teapot_patches() { cp[j] = Eigen::Vector3f(x, y, z); } - Ri_Patch(cp); + Ri_Patch(cp, RI_NULL); } } +void Tunnel() +{ + RiBegin(RI_NULL); + //RiFormat(960, 720, 1.0); + RiFormat(400, 300, 1.0); + RiDisplay("D:\\a\\Tunnel.png", "", ""); + RiPixelSamples(2,2); + + RiFrameBegin(0); + /* set the perspective transformation */ + float fov = 45.0; + RiProjection(RI_PERSPECTIVE, "fov", fov, RI_NULL); + //RiProjection(RI_ORTHOGRAPHIC); + + RiWorldBegin(); + RiTransformBegin(); + RtColor color = {1,0,0}; + RiColor(color); + RiTranslate(0, 0.5, 7.0); + RiRotate(60, 1, 0, 0); + RiTorus(1, .25, 0, 360, 360, RI_NULL); + RiTransformEnd(); + RiTransformBegin(); + color[0] = 0; color[1] = 1; + RiColor(color); + RiTranslate(0, 0, 8.0); + RiRotate(60, 1, 0, 0); + RiRotate(30, 0, 1, 0); + RiCylinder(1, -1, 1, 360, RI_NULL); + RiTransformEnd(); + RiTransformBegin(); + color[1] = 0; color[2] = 1; + RiColor(color); + RiTranslate(0, 1, 9.0); + RiRotate(60, 1, 0, 0); + RiSphere(1.0, -1.0, 1.0, 360, RI_NULL); + RiTransformEnd(); + RiTransformBegin(); + color[0] = 1; color[1] = .4; color[2] = .4; + RiColor(color); + CHECK_SIZE_X = 40; + CHECK_SIZE_Y = 40; + RiSurface(CHECKERBOARD); + RiTranslate(0, -1, 8.5); + RiRotate(-160, 1, 0, 0); + RiRotate(30, 0, 1, 0); + RiCone(2, 1, 360, RI_NULL); + RiTransformEnd(); + RiTransformBegin(); + CHECK_SIZE_X = 40; + CHECK_SIZE_Y = 40; + RiTranslate(0, 0, 7.0); + RiCylinder(3, 0, 10, 360, RI_NULL); + RiTransformEnd(); + RiWorldEnd(); + + RiFrameEnd(); + + RiEnd(); +} + +void Earth() +{ + RiBegin(RI_NULL); + //RiFormat(960, 720, 1.0); + RiFormat(400, 300, 1.0); + //RiFormat(200, 150, 1.0); + RiDisplay("D:\\a\\Earth.png", "", ""); + RiPixelSamples(2,2); + + RiFrameBegin(0); + /* set the perspective transformation */ + float fov = 45.0; + RiProjection(RI_PERSPECTIVE, "fov", fov, RI_NULL); + //RiProjection(RI_ORTHOGRAPHIC); + + RiWorldBegin(); + RiTransformBegin(); + RiMakeTexture("textures\\earth_2.jpg", 0); + //void (*earthShader)(void) = TextureMap0; + RiSurface(texture_shader); + RtColor blue = { 0, 0, 1 }; + RtColor opacity = { .9, .9, .9 }; + RiColor(blue); + /*RiOpacity(opacity); + BUMP_AMPLITUDE = .02; + BUMP_MIN_FREQ_EXP = 14; + BUMP_MAX_FREQ_EXP = 16; + RiDisplacement(BUMPY);*/ + RiTranslate(0, 0, 5.0); + RiRotate(-175, 0, 1, 0); + RiRotate(110, 1, 0, 0); + RiSphere(1, -1, 1, 360, RI_NULL); + RiTransformEnd(); + RiWorldEnd(); + + RiFrameEnd(); + + RiEnd(); +} + void SampleScene1(void) { int i; int nf; @@ -60,108 +162,86 @@ void SampleScene1(void) { slopez = (p2[2] - p1[2]) / nf; RiBegin(RI_NULL); - - RiFormat(500, 500, 1); + RiFormat(320, 240, 1); RiPixelSamples(2, 2); RiShutter(0, 1); - /* new code*/ - RiFrameBegin(1); - RiTranslate(0, 0, -50); + /* loop through all the frames */ + for (i = 1; i <= nf; i++) { + RiFrameBegin(i); + sprintf_s(name, "D:\\a\\image_%02d.tif", i - 1); + RiDisplay(name, "file", "rgb", RI_NULL); + + RiProjection(RI_PERSPECTIVE, "fov", fov, RI_NULL); + RiTranslate(0, -5, 60); + RiRotate(-120, 1, 0, 0); + RiRotate(25, 0, 0, 1); + + RiWorldBegin(); + RiColor(blue); + RiTransformBegin(); + RiCylinder(1, 0, 20, 360, RI_NULL); + RiTranslate(0, 0, 20); + RiCone(2, 2, 360, RI_NULL); + RiTransformEnd(); + + RiColor(green); + RiTransformBegin(); + RiRotate(-90, 1, 0, 0); + RiCylinder(1, 0, 20, 360, RI_NULL); + RiTranslate(0, 0, 20); + RiCone(2, 2, 360, RI_NULL); + RiTransformEnd(); + + RiColor(red); + RiTransformBegin(); + RiRotate(90, 0, 1, 0); + RiCylinder(1, 0, 20, 360, RI_NULL); + RiTranslate(0, 0, 20); + RiCone(2, 2, 360, RI_NULL); + RiTransformEnd(); + + + RiColor(white); + RiTransformBegin(); + RiTranslate(p1[0] + slopex * (i - 1), p1[1] + slopey * (i - 1), p1[2] + slopez * (i - 1)); + RiSphere(5, -5, 5, 360, RI_NULL); + RiTransformEnd(); + RiWorldEnd(); + + /* when you hit this command you should output the final image for this frame */ + RiFrameEnd(); + } + RiEnd(); +}; - RiWorldBegin(); - RiTransformBegin(); +void Teapot() { + RiBegin(RI_NULL); + //RiFormat(960, 720, 1.0); + RiFormat(400, 300, 1.0); + //RiFormat(200, 150, 1.0); + RiDisplay("D:\\a\\Teapot.png", "", ""); + RiPixelSamples(2, 2); + RiFrameBegin(0); + /* set the perspective transformation */ + float fov = 45.0; + RiProjection(RI_PERSPECTIVE, "fov", fov, RI_NULL); RiTranslate(0, 0, -10); - RiColor(red); - RiSphere(15, 0, 0, 0); - RiTransformEnd(); - + RiWorldBegin(); RiTransformBegin(); - RiTranslate(10, 0, 10); - RiColor(blue); - RiSphere(5, 0, 0, 0); - - - //RiTorus(40, 20, 0, 0, 0); + RtColor color = { 1,0,0 }; + RiColor(color); + RiRotate(90, 1.0, 0.0, 0.0); + parse_teapot_patches(); RiTransformEnd(); RiWorldEnd(); RiFrameEnd(); RiEnd(); - - } -// /* loop through all the frames */ -// for (i = 1; i <= nf; i++) { -// RiFrameBegin(i); -// //sprintf(name, "image_%02d.tif", i - 1); -// //RiDisplay(name, "file", "rgb", RI_NULL); -// -// //RiProjection("perspective", "fov", &fov, RI_NULL); -// RiTranslate(0, -5, 60); -// RiRotate(-120, 1, 0, 0); -// RiRotate(25, 0, 0, 1); -// -// RiWorldBegin(); -// RiColor(blue); -// RiTransformBegin(); -// RiCylinder(1, 0, 20, 360, RI_NULL); -// RiTranslate(0, 0, 20); -// RiCone(2, 2, 360, RI_NULL); -// RiTransformEnd(); -// -// RiColor(green); -// RiTransformBegin(); -// RiRotate(-90, 1, 0, 0); -// RiCylinder(1, 0, 20, 360, RI_NULL); -// RiTranslate(0, 0, 20); -// RiCone(2, 2, 360, RI_NULL); -// RiTransformEnd(); -// -// RiColor(red); -// RiTransformBegin(); -// RiRotate(90, 0, 1, 0); -// RiCylinder(1, 0, 20, 360, RI_NULL); -// RiTranslate(0, 0, 20); -// RiCone(2, 2, 360, RI_NULL); -// RiTransformEnd(); -// -// -// RiColor(white); -// RiTransformBegin(); -// RiTranslate(p1[0] + slopex * (i - 1), p1[1] + slopey * (i - 1), p1[2] + slopez * (i - 1)); -// RiSphere(5, -5, 5, 360, RI_NULL); -// RiTransformEnd(); -// RiWorldEnd(); -// -// /* when you hit this command you should output the final image for this frame */ -// RiFrameEnd(); -// } -// RiEnd(); -//}; - int main(void) { // select which scene to render - SampleScene1(); - - //Eigen::Vector4f p[3]; - //p[0] << -0.9, 0.9, 0, 1; - //p[1] << -0.9, -0.9, 0, 1; - ////p[2] << 20, 2, 0, 1; - - - //std::vector points; - //for (int i = 0; i < 2; ++i) { - // float screen_x = (p[i].x() + 1.0f) * 0.5f * 100; - // float screen_y = (1 - (p[i].y() + 1) * 0.5) * 100; - - // std::cout << screen_x << "," << screen_y << "\n"; - // points.push_back(Eigen::Vector4f(screen_x, screen_y, p[i].z(), p[i].w())); - //} - - // - //pimage(points); - //render_perspective_projection(); + Teapot(); } \ No newline at end of file diff --git a/Shaders.cpp b/Shaders.cpp new file mode 100644 index 0000000..a028e3e --- /dev/null +++ b/Shaders.cpp @@ -0,0 +1,197 @@ +#include +#include "Types.h" +#include "Shaders.h" +#include +#include + +float CHECK_SIZE_X; +float CHECK_SIZE_Y; +void CHECKERBOARD(FragmentShaderPayload& pi) { + + float u = pi.u; + float v = pi.v; + if ((int)(floor(u * CHECK_SIZE_X) + floor(v * CHECK_SIZE_Y)) % 2 == 0) { + pi.c.set(255.0f, 255.0f, 255.0f); + } + else { + pi.c.set(0.0f, 0.0f, 0.0f); + } + +} + + +inline UVTuple get_uv(int id, int dice_factor) { + int u = id / dice_factor; + int v = id - (u * dice_factor); + + int grid_width = dice_factor; + int grid_height = dice_factor; + + float u_n = (float)u / ((float)grid_width - 1); + float v_n = (float)v / ((float)grid_height - 1); + + UVTuple p; + p.u = u_n; + p.v = v_n; + return p; +} + +//void checker_explode(GeometricShaderPayload& p) { +// float CHECK_SIZE_X = 60.0f; +// float CHECK_SIZE_Y = 60.0f; +// +// int dice_factor = p.dice_factor; +// auto& points = p.points; +// auto& normals = p.normals; +// auto& triangles = p.triangle_verts; +// std::vector n_triangles; +// +// for (int i = 0; i < triangles.size(); ++i) { +// auto verts = triangles[i].ids; +// bool all_in = true; +// std::set type; +// +// for (int j = 0; j < 3; ++j) { +// int v_id = verts[j]; +// UVTuple tup = get_uv(v_id, dice_factor); +// float u = tup.u; +// float v = tup.v; +// bool t = (int)(floor(u * CHECK_SIZE_X) + floor(v * CHECK_SIZE_Y)) % 2 == 0; +// float p = (int)floor(u * CHECK_SIZE_X) % 3; +// float q = (int)floor(v * CHECK_SIZE_Y) % 3; +// bool x = (p == 1) && (q == 1); +// type.emplace(x && t); +// } +// +// if (type.size() == 1) { +// bool f = *type.begin(); +// if (f) +// n_triangles.push_back(triangles[i]); +// +// } +// } +// +// p.triangle_verts = n_triangles; +//} + +void texture_shader(FragmentShaderPayload& p) { + float u = p.u; + float v = p.v; + std::shared_ptr t = p.texture; + + Color c = t->get_at(u, v); + p.c = c; +} + +void blinn_phong(FragmentShaderPayload& p) { + + Eigen::Vector3f ka(0.01, 0.01, 0.01); + Eigen::Vector3f kd(p.c.r(), p.c.g(), p.c.b()); + Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937); + + Eigen::Vector3f amb_light_intensity{ 10, 10, 10 }; + Eigen::Vector3f ambient = amb_light_intensity.cwiseProduct(ka); + + + Eigen::Vector3f light_pos(0, 5, 0); + Eigen::Vector3f light_intensity(600.0f, 600.0f, 600.0f); + + Eigen::Vector3f vert_pos(p.pos.x(), p.pos.y(), p.pos.z()); + Eigen::Vector3f normal(p.normal.x(), p.normal.y(), p.normal.z()); + Eigen::Vector3f light_dir = light_pos - vert_pos; + float distance = light_dir.norm(); + distance = distance * distance; + //light_dir.normalize(); + float lambertian = std::max(normal.dot(light_dir.normalized()), 0.0f); + Eigen::Vector3f diffuse = kd.cwiseProduct((light_intensity / distance) * lambertian); + + + Eigen::Vector3f view_dir = vert_pos * -1; + view_dir.normalize(); + Eigen::Vector3f half_vec = (light_dir + view_dir) / ((light_dir + view_dir).norm()); + //half_vec.normalize(); + float _p = 150; + float spec_lambertian = pow(std::max(normal.dot(half_vec), 0.0f), _p); + Eigen::Vector3f specular = ks.cwiseProduct((light_intensity / distance) * spec_lambertian); + + + Eigen::Vector3f result_color(0.0f, 0.0f, 0.0f); + result_color += ambient + diffuse + specular; + + p.c.set(result_color[0], result_color[1], result_color[2]); +} + +void blinn_phong_modded(FragmentShaderPayload& p) { + + Eigen::Vector3f ka(0.01, 0.01, 0.01); + Eigen::Vector3f kd(p.c.r(), p.c.g(), p.c.b()); + Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937); + + Eigen::Vector3f amb_light_intensity{ 15, 15, 15 }; + Eigen::Vector3f ambient = amb_light_intensity.cwiseProduct(kd / 45); + + + Eigen::Vector3f light_pos(-10.0, 0.0, 0.0); + Eigen::Vector3f light_intensity(600.0f, 600.0f, 600.0f); + + Eigen::Vector3f vert_pos(p.pos.x(), p.pos.y(), p.pos.z()); + Eigen::Vector3f normal(p.normal.x(), p.normal.y(), p.normal.z()); + Eigen::Vector3f light_dir = light_pos - vert_pos; + float distance = light_dir.norm(); + distance = distance * distance; + //light_dir.normalize(); + float lambertian = std::max(normal.dot(light_dir.normalized()), 0.0f); + Eigen::Vector3f diffuse = kd.cwiseProduct((light_intensity / distance) * lambertian); + + + Eigen::Vector3f view_dir = vert_pos * -1; + view_dir.normalize(); + Eigen::Vector3f half_vec = (light_dir + view_dir) / ((light_dir + view_dir).norm()); + //half_vec.normalize(); + float _p = 150; + float spec_lambertian = pow(std::max(normal.dot(half_vec), 0.0f), _p); + Eigen::Vector3f specular = ks.cwiseProduct((light_intensity / distance) * spec_lambertian); + + + Eigen::Vector3f result_color(0.0f, 0.0f, 0.0f); + result_color += ambient + diffuse + specular; + + p.c.set(result_color[0], result_color[1], result_color[2]); +} + + +//Phong lighting +float LIGHTING_REFLECTIVITY = 15; +float LIGHTING_SPEC_ATTEN = 1.0f; +void phong(FragmentShaderPayload& p) { + //All positions are in eye space + Eigen::Vector3f fragPos(p.pos.x(), p.pos.y(), p.pos.z()); + Eigen::Vector3f lightPos(0, 5, 0); + Eigen::Vector3f normal(p.normal.x(), p.normal.y(), p.normal.z()); + normal.normalize(); + Eigen::Vector3f eyeDir = -1 * fragPos.normalized(); + + //make normal frontfacing + if (eyeDir.dot(normal) < 0) + normal = -normal; + Eigen::Vector3f lightDir = (lightPos - fragPos).normalized(); + + //diffuse lighting factor + float diffuse = std::max(lightDir.dot(normal), 0.0f); + + + /*Vector4 reflect(Vector4 & normal) { + return *this - normal * 2 * this->dot3(normal); + }*/ + + + //specular lighting factor + Eigen::Vector3f reflectDir = (-1 * lightDir) - normal * 2 * (-1 * lightDir).dot(normal); + float specular = pow(std::max(eyeDir.dot(reflectDir), 0.0f), LIGHTING_REFLECTIVITY) * LIGHTING_SPEC_ATTEN; + + float r = std::min((diffuse + 0.2f) * p.c.r() + specular * 1.0f, 1.0f); + float g = std::min((diffuse + 0.2f) * p.c.g() + specular * 1.0f, 1.0f); + float b = std::min((diffuse + 0.2f) * p.c.b() + specular * 1.0f, 1.0f); + + p.c.set(r, g, b); +} diff --git a/Shaders.h b/Shaders.h index 1077f9d..76eb845 100644 --- a/Shaders.h +++ b/Shaders.h @@ -1,72 +1,13 @@ #pragma once -#include #include "Types.h" -#include -//extern Eigen::Vector4f __sh_P; -//extern Color __sh_C; -//extern float __sh_u; -//extern float __sh_v; -void checkboard(VertexShaderPayload& pi) { - float CHECK_SIZE_X = 10.0f; - float CHECK_SIZE_Y = 10.0f; +extern float CHECK_SIZE_X; +extern float CHECK_SIZE_Y; - float u = pi.u; - float v = pi.v; - if ((int)(floor(u * CHECK_SIZE_X) + floor(v * CHECK_SIZE_Y)) % 2 == 0) { - pi.c.set(255.0f, 255.0f, 255.0f); - } - else { - pi.c.set(0.0f, 0.0f, 0.0f); - } - -} - -void earth(FragmentShaderPayload& p) { - float u = p.u; - float v = p.v; - std::shared_ptr t= p.texture; - - Color c = t->get_at(u, v); - p.c = c; -} - -void light(FragmentShaderPayload& p) { - - Eigen::Vector3f ka(0.01, 0.01, 0.01); - Eigen::Vector3f kd(p.c.r(), p.c.g(), p.c.b()); - Eigen::Vector3f ks = Eigen::Vector3f(0.7937, 0.7937, 0.7937); - - Eigen::Vector3f amb_light_intensity{ 10, 10, 10 }; - Eigen::Vector3f ambient = amb_light_intensity.cwiseProduct(ka); - - - Eigen::Vector3f light_pos(0.0, 10.0, 0.0); - light_pos.x() *= -1; - light_pos.y() *= -1; - Eigen::Vector3f light_intensity(500.0f, 500.0f, 500.0f); - - Eigen::Vector3f vert_pos(p.pos.x(), p.pos.y(), p.pos.z()); - Eigen::Vector3f normal(p.normal.x(), p.normal.y(), p.normal.z()); - Eigen::Vector3f light_dir = light_pos - vert_pos; - float distance = light_dir.norm(); - distance = distance * distance; - light_dir.normalize(); - float lambertian = std::max(normal.dot(light_dir), 0.0f); - Eigen::Vector3f diffuse = kd.cwiseProduct( (light_intensity / distance) * lambertian); - - - Eigen::Vector3f view_dir = vert_pos * -1; - view_dir.normalize(); - Eigen::Vector3f half_vec = (light_dir + view_dir) / ((light_dir + view_dir).norm()); - half_vec.normalize(); - float _p = 150; - float spec_lambertian = pow(std::max(normal.dot(half_vec), 0.0f), _p); - Eigen::Vector3f specular = ks.cwiseProduct((light_intensity / distance) * spec_lambertian); - - - Eigen::Vector3f result_color(0.0f, 0.0f, 0.0f); - result_color += ambient + diffuse + specular; - - p.c.set(result_color[0], result_color[1], result_color[2]); -} +void CHECKERBOARD(FragmentShaderPayload& p); +inline UVTuple get_uv(int id, int dice_factor); +void checker_explode(GeometricShaderPayload& p); +void texture_shader(FragmentShaderPayload& p); +void blinn_phong(FragmentShaderPayload& p); +void blinn_phong_modded(FragmentShaderPayload& p); +void phong(FragmentShaderPayload& p); diff --git a/States.h b/States.h index d26935a..d0b015c 100644 --- a/States.h +++ b/States.h @@ -6,11 +6,11 @@ class ImageState { public: int x_resolution, y_resolution; - float pixelaspectratio; - const char* filename; + float pixel_aspect_ratio; + std::string filename; ImageState() { - filename = nullptr; + filename = "default.jpg"; } }; @@ -61,18 +61,42 @@ class RenderState { // https://renderman.pixar.com/resources/RenderMan_20/graphicsState.html#ribegin int f_no; - int is_in_world_block; + bool is_in_world_block; - // This matrix represent world-to-camera and camera-to-screen projection combined - Eigen::Matrix4f transformation; + // world-to-camera + Eigen::Matrix4f world_to_view_transformation; + // camera - to - screen projection + Eigen::Matrix4f view_to_frame_transformation; - void (*surface_shade)(FragmentShaderPayload p); + void (*surface_shader)(FragmentShaderPayload& p); std::shared_ptr texture; RenderState() { //projection_type = RI_ORTHOGRAPHIC; zNear = 0.0; zFar = 100.0; - transformation = Eigen::Matrix4f::Identity(); + xsamples = 2, ysamples = 2; + + f_no = 0; + is_in_world_block = false; + + current_color = Color(0.0f, 0.0f, 0.0f); + world_to_view_transformation = Eigen::Matrix4f::Identity(); + view_to_frame_transformation = Eigen::Matrix4f::Identity(); + surface_shader = nullptr; + } + + void reset() { + zNear = 0.0; + zFar = 100.0; + xsamples = 2, ysamples = 2; + + f_no = 0; + is_in_world_block = false; + + current_color = Color(0.0f, 0.0f, 0.0f); + world_to_view_transformation = Eigen::Matrix4f::Identity(); + view_to_frame_transformation = Eigen::Matrix4f::Identity(); + surface_shader = nullptr; } }; \ No newline at end of file diff --git a/Tunnel.png b/Tunnel.png new file mode 100644 index 0000000..87414b6 Binary files /dev/null and b/Tunnel.png differ diff --git a/Types.cpp b/Types.cpp new file mode 100644 index 0000000..6aae73e --- /dev/null +++ b/Types.cpp @@ -0,0 +1,10 @@ +#define STBI_MSC_SECURE_CRT +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#include "Types.h" + +Texture::Texture(std::string filepath) { + unsigned char* raw_data = stbi_load(filepath.c_str(), &w, &h, &n, 0); + std::shared_ptr data(raw_data); + this->data = data; +} \ No newline at end of file diff --git a/Types.h b/Types.h index 8d23566..3adef18 100644 --- a/Types.h +++ b/Types.h @@ -1,13 +1,8 @@ #pragma once -#ifndef STB_IMAGE_IMPLEMENTATION -#define STBI_MSC_SECURE_CRT -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" -#endif #include -inline float clamp(float v, float min=0.0f, float max=1.0f) { +inline float clamp(float v, float min = 0.0f, float max = 1.0f) { return std::max(min, std::min(v, max)); } @@ -116,11 +111,7 @@ class Texture { std::shared_ptr data; int w, h, n; - Texture() { - unsigned char* raw_data = stbi_load("textures\\earth_2.jpg", &w, &h, &n, 0); - std::shared_ptr data(raw_data); - this->data = data; - } + Texture(std::string filepath); Color get_at(float u, float v) { @@ -156,4 +147,11 @@ struct FragmentShaderPayload { Color c; std::shared_ptr texture; +}; + +struct GeometricShaderPayload { + int dice_factor; + std::vector points; + std::vector normals; + std::vector triangle_verts; }; \ No newline at end of file diff --git a/a.txt b/teapot_points.txt similarity index 100% rename from a.txt rename to teapot_points.txt