diff --git a/OpenWindow/OpenWindow.vcxproj b/OpenWindow/OpenWindow.vcxproj
index f617bbd..d97a814 100644
--- a/OpenWindow/OpenWindow.vcxproj
+++ b/OpenWindow/OpenWindow.vcxproj
@@ -121,6 +121,7 @@
+
@@ -129,6 +130,7 @@
+
diff --git a/OpenWindow/OpenWindow.vcxproj.filters b/OpenWindow/OpenWindow.vcxproj.filters
index 89db46c..a9845d1 100644
--- a/OpenWindow/OpenWindow.vcxproj.filters
+++ b/OpenWindow/OpenWindow.vcxproj.filters
@@ -36,6 +36,9 @@
Source Files
+
+ Source Files
+
@@ -56,5 +59,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/OpenWindow/african_head_spec.tga b/OpenWindow/african_head_spec.tga
new file mode 100644
index 0000000..12e02ce
Binary files /dev/null and b/OpenWindow/african_head_spec.tga differ
diff --git a/OpenWindow/camera.cpp b/OpenWindow/camera.cpp
index 91c8729..b434b70 100644
--- a/OpenWindow/camera.cpp
+++ b/OpenWindow/camera.cpp
@@ -79,27 +79,31 @@ void Camera::move_camera_forward() {
void Camera::move_camera_backward() {
position = position - forward * movement_speed;
}
+void Camera::rise() {
+ position = position + Vec3f(0, movement_speed, 0);
+}
+void Camera::fall() {
+ position = position - Vec3f(0, movement_speed, 0);
+}
void Camera::SetMovementSpeed(float speed) {
movement_speed = speed;
}
void Camera::ApplyChanges() {
- forward = Vec3f(sin(rotation.y * DEG2RAD), -sin(rotation.x * DEG2RAD), -cosf(rotation.y*DEG2RAD) * cosf(rotation.x*DEG2RAD));
- right = Vec3f(cos(rotation.y*DEG2RAD), 0, sin(rotation.y * DEG2RAD));
- up = cross(right, forward);
+ forward = Vec3f(sin(rotation.y * DEG2RAD), -sin(rotation.x * DEG2RAD), -cosf(rotation.y*DEG2RAD) * cosf(rotation.x*DEG2RAD)).normalize();
+ right = Vec3f(cos(rotation.y*DEG2RAD), 0, sin(rotation.y * DEG2RAD)).normalize();
+ up = cross(right, forward).normalize();
}
Matrix Camera::GetModelViewMatrix() {
Vec3f center = position + forward;
- Vec3f z = (position - center).normalize();
- Vec3f x = cross(up, z).normalize();
- Vec3f y = cross(z, x).normalize();
+ Vec3f z = forward * -1;
Matrix Minv = Matrix::identity();
Matrix Tr = Matrix::identity();
for (int i = 0; i < 3; i++) {
- Minv[0][i] = x[i];
- Minv[1][i] = y[i];
+ Minv[0][i] = right[i];
+ Minv[1][i] = up[i];
Minv[2][i] = z[i];
Tr[i][3] = -center[i];
}
diff --git a/OpenWindow/camera.h b/OpenWindow/camera.h
index c3c3746..b1c4e14 100644
--- a/OpenWindow/camera.h
+++ b/OpenWindow/camera.h
@@ -40,6 +40,8 @@ public:
void move_camera_right();
void move_camera_forward();
void move_camera_backward();
+ void rise();
+ void fall();
void ApplyChanges();
Matrix GetModelViewMatrix();
diff --git a/OpenWindow/main.cpp b/OpenWindow/main.cpp
index da1378c..5d5e7dc 100644
--- a/OpenWindow/main.cpp
+++ b/OpenWindow/main.cpp
@@ -11,6 +11,8 @@ const int screen_height = 1000;
int prev_mouse_x = screen_width/2;
int prev_mouse_y = screen_height/2;
+float TIME = 0;
+
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
@@ -52,11 +54,16 @@ bool HandleButtonPressed() {
camera.move_camera_right();
if (GetAsyncKeyState(VK_LEFT) & 0x8000)
camera.move_camera_left();
+ if (GetAsyncKeyState(VK_SPACE) & 0x8000)
+ camera.rise();
+ if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
+ camera.fall();
return true;
}
void CALLBACK FixedUpdate(HWND hwnd, UINT message, UINT uInt, DWORD dWord)
{
+ TIME += 0.167;
HandleButtonPressed();
camera.ApplyChanges();
render();
diff --git a/OpenWindow/model.cpp b/OpenWindow/model.cpp
index d712c83..8ddf0cc 100644
--- a/OpenWindow/model.cpp
+++ b/OpenWindow/model.cpp
@@ -48,7 +48,7 @@ Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffus
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
- //load_texture(filename, "_spec.tga", specularmap_);
+ load_texture(filename, "_spec.tga", specularmap_);
}
Model::~Model() {}
diff --git a/OpenWindow/renderer.cpp b/OpenWindow/renderer.cpp
index f6bfc10..e7e87e3 100644
--- a/OpenWindow/renderer.cpp
+++ b/OpenWindow/renderer.cpp
@@ -8,192 +8,33 @@
#include "util_window.h"
#include
#include "camera.h"
+#include "util_renderer.h"
-#define HORIZONTAL_CAMERA_SPEED 0.1
-#define VERTICAL_CAMERA_SPEED 0.1
+#define HORIZONTAL_CAMERA_SPEED 0.1
+#define VERTICAL_CAMERA_SPEED 0.1
#define VERTICAL_CAMERA_CLAMP_UP 90
#define VERTICAL_CAMERA_CLAMP_DOWN -90
#define NEAR_CLIP_PLANE 0
-#define FAR_CLIP_PLANE 15
+#define FAR_CLIP_PLANE 10
#define FOV 30
-#define DEFAULT_CAMERA_POS Vec3f(0, 0, 5)
-#define DEFAULT_CAMERA_ROT Vec3f(0, 0, 0)
-#define CAMERA_MOVEMENT_SPEED 1.f
+#define CAMERA_MOVEMENT_SPEED 0.05f
+#define DEFAULT_CAMERA_POS Vec3f(0, 0, 5)
+#define DEFAULT_CAMERA_ROT Vec3f(0, 0, 0)
+#define LIGHT_INTENSITY 1
const TGAColor white = TGAColor(255, 255, 255, 255);
const TGAColor red = TGAColor(255, 0, 0, 255);
const TGAColor green = TGAColor(0, 255, 0, 255);
const TGAColor blue = TGAColor(0, 0, 255, 255);
-bool wireframe = false;
-
+Matrix ViewPort = Matrix::identity();
+Matrix ModelView = Matrix::identity();
+Matrix Projection = Matrix::identity();
Model* model = new Model("african_head.obj");
Camera camera;
-float* z_buffer = new float[screen_width * screen_height];
-Vec3f light_dir = Vec3f(0, 0, 1).normalize();
-
-Matrix viewport(int x, int y, int w, int h) {
- Matrix m = Matrix::identity();
- m[0][3] = x + w / 2.f;
- m[1][3] = y + h / 2.f;
- m[2][3] = (FAR_CLIP_PLANE-NEAR_CLIP_PLANE) / 2.f;
-
- m[0][0] = w / 2.f;
- m[1][1] = h / 2.f;
- m[2][2] = (FAR_CLIP_PLANE+NEAR_CLIP_PLANE) / 2.f;
- return m;
-}
-
-void line(Vec3f p0, Vec3f p1, TGAColor color)
-{
- bool steep = false;
-
- if (std::abs(p0[0] - p1[0]) < std::abs(p0[1] - p1[1])) {
- std::swap(p0[0], p0[1]);
- std::swap(p1[0], p1[1]);
- steep = true;
-
- }
-
- if (p0[0] > p1[0]) {
- std::swap(p0[0], p1[0]);
- std::swap(p0[1], p1[1]);
- }
-
- int dx = p1[0] - p0[0];
- int dy = p1[1] - p0[1];
- int derror2 = std::abs(dy) * 2;
- int error2 = 0;
- int y = p0[1];
- int y_step = p1[1] > p0[1] ? 1 : -1;
- int dx_2 = 2 * dx;
-
- for (int x = p0[0]; x <= p1[0]; x++) {
- if (steep) {
- set_pixel(y, x, color_to_int(color));
- }
- else {
- set_pixel(x, y, color_to_int(color));
- }
- error2 += derror2;
- if (error2 > dx) {
- y += (y_step);
- error2 -= dx_2;
- }
- }
-}
-
-Vec3f barycentric(Vec3f* pts, Vec3f P)
-{
- Vec3f u = cross(
- Vec3f(pts[2][0] - pts[0][0], pts[1][0] - pts[0][0], pts[0][0] - P[0]), // AC_x, AB_x, distance_x
- Vec3f(pts[2][1] - pts[0][1], pts[1][1] - pts[0][1], pts[0][1] - P[1]) // AC_y, AB_y, distance_y
- );
-
- if (std::abs(u[2]) < 1) return Vec3f(-1, 1, 1);
- return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
-}
-
-
-void triangle(
- Vec3f* pts, // Needed
- Vec2f* diff_pts, // Should be removed
- Model* model,
- float* intensities)
-{
-
- if (pts[0].y == pts[1].y && pts[0].y == pts[2].y) return; // i dont care about degenerate triangles
- if (pts[0].y > pts[1].y) {
- std::swap(pts[0], pts[1]);
- if(diff_pts)
- std::swap(diff_pts[0], diff_pts[1]);
- if(intensities)
- std::swap(intensities[0], intensities[1]);
- }
- if (pts[0].y > pts[2].y) {
- std::swap(pts[0], pts[2]);
- if(diff_pts)
- std::swap(diff_pts[0], diff_pts[2]);
- if(intensities)
- std::swap(intensities[0], intensities[2]);
- }
- if (pts[1].y > pts[2].y) {
- std::swap(pts[1], pts[2]);
- if(diff_pts)
- std::swap(diff_pts[1], diff_pts[2]);
- if(intensities)
- std::swap(intensities[1], intensities[2]);
- }
-
- if (wireframe)
- {
- line(pts[0], pts[1], white);
- line(pts[1], pts[2], white);
- line(pts[2], pts[0], white);
- return;
- }
-
- Vec2i bounding_box_min(screen_width - 1, screen_height - 1);
- Vec2i bounding_box_max(0, 0);
- Vec2i clamp(screen_width - 1, screen_height - 1);
- TGAColor color = white;
-
- #pragma omp parallel for
- for (int i = 0; i < 3; i++) {
- for (int j = 0; j < 2; j++) {
- bounding_box_min[j] = std::fmax(0, std::fmin(bounding_box_min[j], (int)pts[i][j]));
- bounding_box_max[j] = std::fmin(clamp[j], std::fmax(bounding_box_max[j], (int)pts[i][j]));
- }
- }
-
- Vec3f P;
- #pragma omp parallel for
- for (P.x = bounding_box_min.x; P.x <= bounding_box_max.x; P.x++) {
- for (P.y = bounding_box_min.y; P.y <= bounding_box_max.y; P.y++) {
- Vec3f bc_coord = barycentric(pts, P);
- if (bc_coord.x < 0 || bc_coord.y < 0 || bc_coord.z < 0) continue;
-
-
- float intensity =
- intensities[0]
- + (intensities[1] - intensities[0]) * bc_coord[1]
- + (intensities[2] - intensities[0]) * bc_coord[2];
-
-
- // Interpolating Z using the barycentric coordinates
- P.z = 0;
- for (int i = 0; i < 3; i++) P.z += pts[i][2] * bc_coord[i];
-
- // Coloring according to the Z-Buffer
- if (P.z > z_buffer[(int)(P.x + P.y * screen_width)] && P.z > 0)
- {
- z_buffer[(int)(P.x + P.y * screen_width)] = P.z;
-
- // If diff_pts (Diffusemap Points) were passed, then find the
- // color of the current pixel
- if (diff_pts) {
- Vec2f diff_pt =
- diff_pts[0]
- + (diff_pts[1] - diff_pts[0]) * bc_coord[1]
- + (diff_pts[2] - diff_pts[0]) * bc_coord[2];
-
- color = model->diffuse(diff_pt);
- }
- color = color * intensity;
- set_pixel(P.x, P.y, color_to_int(color));
- //char debugStr[200];
- //sprintf_s(debugStr, "%f\n", P.z);
- //OutputDebugString(debugStr);
- }
- }
- }
-}
-
-int color_to_int(TGAColor col) {
- return (col[2] << 16) | (col[1] << 8) | col[0];
-}
+Vec3f light_dir = Vec3f(1, 1, 1).normalize();
void init_camera() {
camera.SetPosition(DEFAULT_CAMERA_POS);
@@ -215,49 +56,62 @@ void clear_zbuffer()
z_buffer[i] = INT_MIN;
}
-Matrix ViewPort = Matrix::identity();
-Matrix Projection = Matrix::identity();
-Matrix ModelView = Matrix::identity();
+
+struct TextureShader : public IShader {
+ mat<2, 3, float> varying_uv_coords;
+ Matrix uniform_mit;
+ Matrix uniform_m;
+
+ virtual Vec4f vertex(int iface, int nthvert) {
+ varying_uv_coords.set_col(nthvert, model->uv(iface, nthvert));
+ Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert)); // read the vertex from .obj file
+ return ViewPort * Projection * ModelView * gl_Vertex; // transform it to screen coordinates
+ }
+
+ virtual bool fragment(Vec3f bar, TGAColor &color) {
+ Vec2f uv = varying_uv_coords * bar;
+ Vec3f normal = Vec3f(uniform_mit * Vec4f(model->normal(uv))).normalize();
+ Vec3f light = Vec3f(uniform_m * Vec4f(light_dir)).normalize();
+ float intensity = std::fmax(0.f, (normal*light*LIGHT_INTENSITY));
+ color = model->diffuse(uv) * intensity * (cos(TIME * 10 * uv.x) + sin(TIME * 10 * uv.y));
+ return false;
+ }
+};
+
void render()
{
- light_dir = camera.GetForward() * -1;
- ViewPort = viewport(0, 0, screen_width, screen_height);
- Projection = camera.GetProjectionMatrix();
- ModelView = camera.GetModelViewMatrix();
+ {
+ light_dir = camera.GetForward().normalize() * -1;
+ }
- Matrix z = ViewPort * Projection * ModelView * model->Transform;
+ {
+ viewport(0, 0, screen_width, screen_height, FAR_CLIP_PLANE, NEAR_CLIP_PLANE);
+ Projection = camera.GetProjectionMatrix();
+ ModelView = camera.GetModelViewMatrix();
+ }
+
+
+ //Matrix z = ViewPort * Projection * ModelView * model->Transform;
clear_zbuffer();
+ TextureShader shader;
+ shader.uniform_m = (Projection);
+ shader.uniform_mit = (Projection).invert_transpose();
+
#pragma omp parallel for
- for (int i = 0; i < model->nfaces(); i++)
- {
- std::vector face = model->face(i);
- Vec3f screen_coords[3];
- Vec3f world_coords[3];
- Vec2f diffuse_coords[3];
- float intensities[3];
+ for (int i = 0; i < model->nfaces(); i++) {
+ Vec4f screen_coords[3];
bool out = true;
+ #pragma omp parallel for
+ for (int j = 0; j < 3; j++) {
+ screen_coords[j] = shader.vertex(i, j);
+ Vec3f screen3(screen_coords[j]);
- for (int j = 0; j < 3; j++)
- {
- Vec3f v = model->vert(face[j]);
- Vec4f v4(v);
- Vec3f coord(z * v4);
-
- if (coord.x > 0 && coord.x < screen_width
- && coord.y > 0 && coord.y < screen_height)
- out = false;
-
- screen_coords[j] = coord;
- world_coords[j] = v;
- diffuse_coords[j] = model->uv(i, j);
- intensities[j] = model->normal(i, j) * light_dir;
+ if (screen3.x > 0 && screen3.x < screen_width && screen3.y > 0 && screen3.y < screen_height) out = false;
}
-
- if (out) continue;
-
- triangle(screen_coords, diffuse_coords, model, intensities);
+ if(!out)
+ triangle(screen_coords, shader);
}
}
diff --git a/OpenWindow/renderer.h b/OpenWindow/renderer.h
index 9aef4a6..ae4152d 100644
--- a/OpenWindow/renderer.h
+++ b/OpenWindow/renderer.h
@@ -6,6 +6,7 @@
extern float* z_buffer;
extern Camera camera;
+extern float TIME;
void init_camera();
void render();
diff --git a/OpenWindow/util_renderer.cpp b/OpenWindow/util_renderer.cpp
new file mode 100644
index 0000000..669799b
--- /dev/null
+++ b/OpenWindow/util_renderer.cpp
@@ -0,0 +1,73 @@
+#include "util_renderer.h"
+#include "util_window.h"
+
+IShader::~IShader() {}
+
+float* z_buffer = new float[screen_width * screen_height];
+
+void viewport(int x, int y, int w, int h, int far_plane, int near_plane) {
+ ViewPort[0][3] = x + w / 2.f;
+ ViewPort[1][3] = y + h / 2.f;
+ ViewPort[2][3] = (far_plane-near_plane) / 2.f;
+
+ ViewPort[0][0] = w / 2.f;
+ ViewPort[1][1] = h / 2.f;
+ ViewPort[2][2] = (far_plane+near_plane) / 2.f;
+}
+
+int color_to_int(TGAColor col) {
+ return (col[2] << 16) | (col[1] << 8) | col[0];
+}
+
+Vec3f barycentric(Vec3f* pts, Vec3f P)
+{
+ Vec3f u = cross(
+ Vec3f(pts[2][0] - pts[0][0], pts[1][0] - pts[0][0], pts[0][0] - P[0]), // AC_x, AB_x, distance_x
+ Vec3f(pts[2][1] - pts[0][1], pts[1][1] - pts[0][1], pts[0][1] - P[1]) // AC_y, AB_y, distance_y
+ );
+
+ if (std::abs(u[2]) < 1) return Vec3f(-1, 1, 1);
+ return Vec3f(1.f - (u.x + u.y) / u.z, u.y / u.z, u.x / u.z);
+}
+
+void triangle( Vec4f* pts, IShader &shader)
+{
+ Vec3f pts3[3];
+ for (int i = 0; i < 3; i++)
+ pts3[i] = Vec3f(pts[i]);
+
+ if (pts3[0].y == pts3[1].y && pts3[0].y == pts3[2].y) return; // i dont care about degenerate triangles
+ //if (pts3[0].y > pts3[1].y) { std::swap(pts3[0], pts3[1]); }
+ //if (pts3[0].y > pts3[2].y) { std::swap(pts3[0], pts3[2]); }
+ //if (pts3[1].y > pts3[2].y) { std::swap(pts3[1], pts3[2]); }
+
+ Vec2i bounding_box_min(screen_width - 1, screen_height - 1);
+ Vec2i bounding_box_max(0, 0);
+ Vec2i clamp(screen_width - 1, screen_height - 1);
+
+ #pragma omp parallel for
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 2; j++) {
+ bounding_box_min[j] = std::fmax(0, std::fmin(bounding_box_min[j], (int)pts3[i][j]));
+ bounding_box_max[j] = std::fmin(clamp[j], std::fmax(bounding_box_max[j], (int)pts3[i][j]));
+ }
+
+
+ Vec3i P;
+ #pragma omp parallel for
+ for (P.x = bounding_box_min.x; P.x <= bounding_box_max.x; P.x++) {
+ for (P.y = bounding_box_min.y; P.y <= bounding_box_max.y; P.y++) {
+ Vec3f bc_coord = barycentric(pts3, P);
+ float frag_depth = 0;
+ for (int i = 0; i < 3; i++)
+ frag_depth += pts3[i][2] * bc_coord[i];
+ if (bc_coord.x < 0 || bc_coord.y < 0 || bc_coord.z < 0 || z_buffer[ P.x + P.y * screen_width ]>frag_depth || frag_depth < 0) continue;
+ TGAColor color;
+ bool discard = shader.fragment(bc_coord, color);
+ if (!discard) {
+ z_buffer[P.x + P.y * screen_width] = frag_depth;
+ set_pixel(P.x, P.y, color_to_int(color));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/OpenWindow/util_renderer.h b/OpenWindow/util_renderer.h
new file mode 100644
index 0000000..ff846fc
--- /dev/null
+++ b/OpenWindow/util_renderer.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "tgaimage.h"
+#include "model.h"
+#include "geometry.h"
+
+extern Matrix ModelView;
+extern Matrix ViewPort;
+extern Matrix Projection;
+
+void viewport(int x, int y, int w, int h, int far, int near);
+
+struct IShader {
+ virtual ~IShader();
+ virtual Vec4f vertex(int iface, int nthvert) = 0;
+ virtual bool fragment(Vec3f bar, TGAColor &color) = 0;
+};
+
+//void triangle(Vec4f *pts, IShader &shader, TGAImage &image, TGAImage &zbuffer);
+
+//void triangle( Vec3f* pts, Vec2f* diff_pts, Model* model, float* intensities)
+
+void triangle(Vec4f* pts, IShader &shader);