|
1 |
| -#include <limits> |
2 |
| -#include "model.h" |
3 |
| -#include "our_gl.h" |
| 1 | +#include <cmath> |
| 2 | +#include "tgaimage.h" |
4 | 3 |
|
5 |
| -extern mat<4,4> ModelView; // "OpenGL" state matrices |
6 |
| -extern mat<4,4> Projection; |
7 |
| - |
8 |
| -struct Shader : IShader { |
9 |
| - const Model &model; |
10 |
| - vec3 uniform_l; // light direction in view coordinates |
11 |
| - mat<3,2> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader |
12 |
| - mat<3,3> varying_nrm; // normal per vertex to be interpolated by FS |
13 |
| - mat<3,3> view_tri; // triangle in view coordinates |
14 |
| - |
15 |
| - Shader(const vec3 l, const Model &m) : model(m) { |
16 |
| - uniform_l = normalized((ModelView*vec4{l.x, l.y, l.z, 0.}).xyz()); // transform the light vector to view coordinates |
17 |
| - } |
18 |
| - |
19 |
| - virtual void vertex(const int iface, const int nthvert, vec4& gl_Position) { |
20 |
| - vec3 n = model.normal(iface, nthvert); |
21 |
| - vec3 v = model.vert(iface, nthvert); |
22 |
| - gl_Position = ModelView * vec4{v.x, v.y, v.z, 1.}; |
23 |
| - varying_uv[nthvert] = model.uv(iface, nthvert); |
24 |
| - varying_nrm[nthvert] = (ModelView.invert_transpose() * vec4{n.x, n.y, n.z, 0.}).xyz(); |
25 |
| - view_tri[nthvert] = gl_Position.xyz(); |
26 |
| - gl_Position = Projection * gl_Position; |
27 |
| - } |
28 |
| - |
29 |
| - virtual bool fragment(const vec3 bar, TGAColor &gl_FragColor) const { |
30 |
| - vec3 bn = normalized(bar * varying_nrm); // per-vertex normal interpolation |
31 |
| - vec2 uv = bar * varying_uv; // tex coord interpolation |
32 |
| - |
33 |
| - mat<3,3> AI = mat<3,3>{ {view_tri[1] - view_tri[0], view_tri[2] - view_tri[0], bn} }.invert(); // for the math refer to the tangent space normal mapping lecture |
34 |
| - vec3 i = AI * vec3{varying_uv[1].x - varying_uv[0].x, varying_uv[2].x - varying_uv[0].x, 0}; // https://github.com/ssloy/tinyrenderer/wiki/Lesson-6bis-tangent-space-normal-mapping |
35 |
| - vec3 j = AI * vec3{varying_uv[1].y - varying_uv[0].y, varying_uv[2].y - varying_uv[0].y, 0}; |
36 |
| - mat<3,3> B = mat<3,3>{ { normalized(i), normalized(j), bn } }.transpose(); |
37 |
| - |
38 |
| - vec3 n = normalized(B * model.normal(uv)); // transform the normal from the texture to the tangent space |
39 |
| - vec3 r = normalized(n * (n * uniform_l)*2 - uniform_l); // reflected light direction, specular mapping is described here: https://github.com/ssloy/tinyrenderer/wiki/Lesson-6-Shaders-for-the-software-renderer |
40 |
| - double diff = std::max(0., n * uniform_l); // diffuse light intensity |
41 |
| - double spec = std::pow(std::max(-r.z, 0.), 5+sample2D(model.specular(), uv)[0]); // specular intensity, note that the camera lies on the z-axis (in view), therefore simple -r.z |
42 |
| - |
43 |
| - TGAColor c = sample2D(model.diffuse(), uv); |
44 |
| - for (int i : {0,1,2}) |
45 |
| - gl_FragColor[i] = std::min<int>(10 + c[i]*(diff + spec), 255); // (a bit of ambient light, diff + spec), clamp the result |
46 |
| - return false; // do not discard the pixel |
47 |
| - } |
48 |
| -}; |
| 4 | +constexpr TGAColor white = {255, 255, 255, 255}; // attention, BGRA order |
| 5 | +constexpr TGAColor green = { 0, 255, 0, 255}; |
| 6 | +constexpr TGAColor red = { 0, 0, 255, 255}; |
| 7 | +constexpr TGAColor blue = {255, 128, 64, 255}; |
| 8 | +constexpr TGAColor yellow = { 0, 200, 255, 255}; |
49 | 9 |
|
50 | 10 | int main(int argc, char** argv) {
|
51 |
| - if (2>argc) { |
52 |
| - std::cerr << "Usage: " << argv[0] << " obj/model.obj" << std::endl; |
53 |
| - return 1; |
54 |
| - } |
| 11 | + constexpr int width = 64; |
| 12 | + constexpr int height = 64; |
| 13 | + TGAImage framebuffer(width, height, TGAImage::RGB); |
55 | 14 |
|
56 |
| - constexpr int width = 800; // output image size |
57 |
| - constexpr int height = 800; |
58 |
| - constexpr vec3 light_dir{1,1,1}; // light source |
59 |
| - constexpr vec3 eye{1,1,3}; // camera position |
60 |
| - constexpr vec3 center{0,0,0}; // camera direction |
61 |
| - constexpr vec3 up{0,1,0}; // camera up vector |
| 15 | + int ax = 7, ay = 3; |
| 16 | + int bx = 12, by = 37; |
| 17 | + int cx = 62, cy = 53; |
62 | 18 |
|
63 |
| - lookat(eye, center, up); // build the ModelView matrix |
64 |
| - viewport(width/8, height/8, width*3/4, height*3/4); // build the Viewport matrix |
65 |
| - projection(norm(eye-center)); // build the Projection matrix |
66 |
| - std::vector<double> zbuffer(width*height, std::numeric_limits<double>::max()); |
| 19 | + framebuffer.set(ax, ay, white); |
| 20 | + framebuffer.set(bx, by, white); |
| 21 | + framebuffer.set(cx, cy, white); |
67 | 22 |
|
68 |
| - TGAImage framebuffer(width, height, TGAImage::RGB); // the output image |
69 |
| - for (int m=1; m<argc; m++) { // iterate through all input objects |
70 |
| - Model model(argv[m]); |
71 |
| - Shader shader(light_dir, model); |
72 |
| - for (int t=0; t<model.nfaces(); t++) { // for every triangle |
73 |
| - vec4 clip_vert[3]; // triangle coordinates (clip coordinates), written by VS, read by FS |
74 |
| - for (int v : {0,1,2}) |
75 |
| - shader.vertex(t, v, clip_vert[v]); // call the vertex shader for each triangle vertex |
76 |
| - rasterize(clip_vert, shader, framebuffer, zbuffer); // actual rasterization routine call |
77 |
| - } |
78 |
| - } |
79 | 23 | framebuffer.write_tga_file("framebuffer.tga");
|
80 | 24 | return 0;
|
81 | 25 | }
|
|
0 commit comments