Skip to content

Commit

Permalink
diffuse texture homework
Browse files Browse the repository at this point in the history
  • Loading branch information
ssloy committed Jan 22, 2015
1 parent 5ff999c commit d7f1bfb
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 21 deletions.
29 changes: 19 additions & 10 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,32 @@ Model *model = NULL;
int *zbuffer = NULL;
Vec3f light_dir(0,0,-1);

void triangle(Vec3i t0, Vec3i t1, Vec3i t2, TGAImage &image, TGAColor color, int *zbuffer) {
void triangle(Vec3i t0, Vec3i t1, Vec3i t2, Vec2i uv0, Vec2i uv1, Vec2i uv2, TGAImage &image, float intensity, int *zbuffer) {
if (t0.y==t1.y && t0.y==t2.y) return; // i dont care about degenerate triangles
if (t0.y>t1.y) std::swap(t0, t1);
if (t0.y>t2.y) std::swap(t0, t2);
if (t1.y>t2.y) std::swap(t1, t2);
if (t0.y>t1.y) { std::swap(t0, t1); std::swap(uv0, uv1); }
if (t0.y>t2.y) { std::swap(t0, t2); std::swap(uv0, uv2); }
if (t1.y>t2.y) { std::swap(t1, t2); std::swap(uv1, uv2); }

int total_height = t2.y-t0.y;
for (int i=0; i<total_height; i++) {
bool second_half = i>t1.y-t0.y || t1.y==t0.y;
int segment_height = second_half ? t2.y-t1.y : t1.y-t0.y;
float alpha = (float)i/total_height;
float beta = (float)(i-(second_half ? t1.y-t0.y : 0))/segment_height; // be careful: with above conditions no division by zero here
Vec3i A = t0 + Vec3f(t2-t0)*alpha;
Vec3i B = second_half ? t1 + Vec3f(t2-t1)*beta : t0 + Vec3f(t1-t0)*beta;
if (A.x>B.x) std::swap(A, B);
Vec3i A = t0 + Vec3f(t2-t0 )*alpha;
Vec3i B = second_half ? t1 + Vec3f(t2-t1 )*beta : t0 + Vec3f(t1-t0 )*beta;
Vec2i uvA = uv0 + (uv2-uv0)*alpha;
Vec2i uvB = second_half ? uv1 + (uv2-uv1)*beta : uv0 + (uv1-uv0)*beta;
if (A.x>B.x) { std::swap(A, B); std::swap(uvA, uvB); }
for (int j=A.x; j<=B.x; j++) {
float phi = B.x==A.x ? 1. : (float)(j-A.x)/(float)(B.x-A.x);
Vec3i P = Vec3f(A) + Vec3f(B-A)*phi;
Vec3i P = Vec3f(A) + Vec3f(B-A)*phi;
Vec2i uvP = uvA + (uvB-uvA)*phi;
int idx = P.x+P.y*width;
if (zbuffer[idx]<P.z) {
zbuffer[idx] = P.z;
image.set(P.x, P.y, color);
TGAColor color = model->diffuse(uvP);
image.set(P.x, P.y, TGAColor(color.r*intensity, color.g*intensity, color.b*intensity));
}
}
}
Expand Down Expand Up @@ -66,7 +71,11 @@ int main(int argc, char** argv) {
n.normalize();
float intensity = n*light_dir;
if (intensity>0) {
triangle(screen_coords[0], screen_coords[1], screen_coords[2], image, TGAColor(intensity*255, intensity*255, intensity*255, 255), zbuffer);
Vec2i uv[3];
for (int k=0; k<3; k++) {
uv[k] = model->uv(i, k);
}
triangle(screen_coords[0], screen_coords[1], screen_coords[2], uv[0], uv[1], uv[2], image, intensity, zbuffer);
}
}

Expand Down
51 changes: 42 additions & 9 deletions model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <vector>
#include "model.h"

Model::Model(const char *filename) : verts_(), faces_() {
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_() {
std::ifstream in;
in.open (filename, std::ifstream::in);
if (in.fail()) return;
Expand All @@ -19,18 +19,29 @@ Model::Model(const char *filename) : verts_(), faces_() {
Vec3f v;
for (int i=0;i<3;i++) iss >> v[i];
verts_.push_back(v);
} else if (!line.compare(0, 2, "f ")) {
std::vector<int> f;
int itrash, idx;
} else if (!line.compare(0, 3, "vn ")) {
iss >> trash >> trash;
Vec3f n;
for (int i=0;i<3;i++) iss >> n[i];
norms_.push_back(n);
} else if (!line.compare(0, 3, "vt ")) {
iss >> trash >> trash;
Vec2f uv;
for (int i=0;i<2;i++) iss >> uv[i];
uv_.push_back(uv);
} else if (!line.compare(0, 2, "f ")) {
std::vector<Vec3i> f;
Vec3i tmp;
iss >> trash;
while (iss >> idx >> trash >> itrash >> trash >> itrash) {
idx--; // in wavefront obj all indices start at 1, not zero
f.push_back(idx);
while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2]) {
for (int i=0; i<3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero
f.push_back(tmp);
}
faces_.push_back(f);
}
}
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << std::endl;
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
}

Model::~Model() {
Expand All @@ -45,10 +56,32 @@ int Model::nfaces() {
}

std::vector<int> Model::face(int idx) {
return faces_[idx];
std::vector<int> face;
for (int i=0; i<(int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
return face;
}

Vec3f Model::vert(int i) {
return verts_[i];
}

void Model::load_texture(std::string filename, const char *suffix, TGAImage &img) {
std::string texfile(filename);
size_t dot = texfile.find_last_of(".");
if (dot!=std::string::npos) {
texfile = texfile.substr(0,dot) + std::string(suffix);
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
img.flip_vertically();

This comment has been minimized.

Copy link
@ovcharik

ovcharik Feb 2, 2015

Почему изображение переворачивается дважды? По стандарту вроде немного другая логика здесь.

This comment has been minimized.

Copy link
@ssloy

ssloy via email Feb 2, 2015

Author Owner

This comment has been minimized.

Copy link
@ovcharik

ovcharik Feb 2, 2015

Видимо ссылка на почту не пришла
https://github.com/ssloy/tinyrenderer/blob/master/tgaimage.cpp#L84

bool TGAImage::read_tga_file(const char *filename) {
  // ...
  if (!(header.imagedescriptor & 0x20)) { // вот эта строка
    flip_vertically();
  }
  if (header.imagedescriptor & 0x10) {
    flip_horizontally();
  }
  // ...
}

Биты 5 (0x20) и 4 (0x10) определяют порядок передачи пиксельных данных из файла на экран. Бит 4 устанавливается для порядка «слева направо», бит 5 — для порядка «сверху вниз».

Если в кратце, то я написал свой парсер для tga и отрисовываю его на канвасе. Если соблюсти такие же условия как у Вас по ссылке, то изображение рисуется отображенным сверху вниз, хотя другие просмотрщики рисуют правильно (правильно ли?).

И эти переворачивания повсюду:

image.flip_vertically(); // i want to have the origin at the left bottom corner of the image

image.flip_vertically(); // i want to have the origin at the left bottom corner of the image

Не совсем понял ошибка ли это, или я что-то делаю не правильно просто.

This comment has been minimized.

Copy link
@ssloy

ssloy via email Feb 2, 2015

Author Owner
}
}

TGAColor Model::diffuse(Vec2i uv) {
return diffusemap_.get(uv.x, uv.y);
}

Vec2i Model::uv(int iface, int nvert) {
int idx = faces_[iface][nvert][1];
return Vec2i(uv_[idx].x*diffusemap_.get_width(), uv_[idx].y*diffusemap_.get_height());
}


9 changes: 8 additions & 1 deletion model.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@

#include <vector>
#include "geometry.h"
#include "tgaimage.h"

class Model {
private:
std::vector<Vec3f> verts_;
std::vector<std::vector<int> > faces_;
std::vector<std::vector<Vec3i> > faces_; // attention, this Vec3i means vertex/uv/normal
std::vector<Vec3f> norms_;
std::vector<Vec2f> uv_;
TGAImage diffusemap_;
void load_texture(std::string filename, const char *suffix, TGAImage &img);
public:
Model(const char *filename);
~Model();
int nverts();
int nfaces();
Vec3f vert(int i);
Vec2i uv(int iface, int nvert);
TGAColor diffuse(Vec2i uv);
std::vector<int> face(int idx);
};

Expand Down
2 changes: 1 addition & 1 deletion tgaimage.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct TGAColor {
TGAColor() : val(0), bytespp(1) {
}

TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A) : b(B), g(G), r(R), a(A), bytespp(4) {
TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A=255) : b(B), g(G), r(R), a(A), bytespp(4) {
}

TGAColor(int v, int bpp) : val(v), bytespp(bpp) {
Expand Down

0 comments on commit d7f1bfb

Please sign in to comment.