Skip to content

Commit

Permalink
first shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
ssloy committed Jan 26, 2015
1 parent a23d224 commit 1cb0834
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 57 deletions.
5 changes: 2 additions & 3 deletions geometry.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "geometry.h"

template <> template <> vec<3,int> ::vec(const vec<3,float> &v) : x(int(v.x+.5)),y(int(v.y+.5)),z(int(v.z+.5)) {}
template <> template <> vec<3,int> ::vec(const vec<3,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)),z(int(v.z+.5f)) {}
template <> template <> vec<3,float>::vec(const vec<3,int> &v) : x(v.x),y(v.y),z(v.z) {}
template <> template <> vec<2,int> ::vec(const vec<2,float> &v) : x(int(v.x+.5)),y(int(v.y+.5)) {}
template <> template <> vec<2,int> ::vec(const vec<2,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)) {}
template <> template <> vec<2,float>::vec(const vec<2,int> &v) : x(v.x),y(v.y) {}

34 changes: 22 additions & 12 deletions geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
template<size_t DimCols,size_t DimRows,typename T> class mat;

template <size_t DIM, typename T> struct vec {
vec() { for (size_t i=DIM; i--; data_[i] = T(0)); }
vec() { for (size_t i=DIM; i--; data_[i] = T()); }
T& operator[](const size_t i) { assert(i<DIM); return data_[i]; }
const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; }
private:
Expand All @@ -19,7 +19,7 @@ template <size_t DIM, typename T> struct vec {
/////////////////////////////////////////////////////////////////////////////////

template <typename T> struct vec<2,T> {
vec() : x(0), y(0) {}
vec() : x(T()), y(T()) {}
vec(T X, T Y) : x(X), y(Y) {}
template <class U> vec<2,T>(const vec<2,U> &v);
T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; }
Expand All @@ -31,7 +31,7 @@ template <typename T> struct vec<2,T> {
/////////////////////////////////////////////////////////////////////////////////

template <typename T> struct vec<3,T> {
vec() : x(0), y(0), z(0) {}
vec() : x(T()), y(T()), z(T()) {}
vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
template <class U> vec<3,T>(const vec<3,U> &v);
T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
Expand Down Expand Up @@ -67,7 +67,7 @@ template<size_t DIM,typename T,typename U> vec<DIM,T> operator*(vec<DIM,T> lhs,
}

template<size_t DIM,typename T,typename U> vec<DIM,T> operator/(vec<DIM,T> lhs, const U& rhs) {
for (size_t i=DIM; i--; lhs[i]*=rhs);
for (size_t i=DIM; i--; lhs[i]/=rhs);
return lhs;
}

Expand Down Expand Up @@ -99,7 +99,7 @@ template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, ve
template<size_t DIM,typename T> struct dt {
static T det(const mat<DIM,DIM,T>& src) {
T ret=0;
for (size_t i=DIM; i--; ret += src[0][i]*src.algAdd(0,i));
for (size_t i=DIM; i--; ret += src[0][i]*src.cofactor(0,i));
return ret;
}
};
Expand Down Expand Up @@ -127,13 +127,18 @@ template<size_t DimRows,size_t DimCols,typename T> class mat {
return rows[idx];
}

vec<DimRows,T> col(const size_t idx) {
vec<DimRows,T> col(const size_t idx) const {
assert(idx<DimCols);
vec<DimRows,T> ret;
for (size_t i=DimRows; i--; ret[i]=rows[i][idx]);
return ret;
}

void set_col(size_t idx, vec<DimRows,T> v) {
assert(idx<DimCols);
for (size_t i=DimRows; i--; rows[i][idx]=v[i]);
}

static mat<DimRows,DimCols,T> identity() {
mat<DimRows,DimCols,T> ret;
for (size_t i=DimRows; i--; )
Expand All @@ -145,21 +150,21 @@ template<size_t DimRows,size_t DimCols,typename T> class mat {
return dt<DimCols,T>::det(*this);
}

mat<DimRows-1,DimCols-1,T> minor(size_t row, size_t col) const {
mat<DimRows-1,DimCols-1,T> get_minor(size_t row, size_t col) const {
mat<DimRows-1,DimCols-1,T> ret;
for (size_t i=DimRows-1; i--; )
for (size_t j=DimCols-1;j--; ret[i][j]=rows[i<row?i:i+1][j<col?j:j+1]);
return ret;
}

T algAdd(size_t row, size_t col) const {
return minor(row,col).det()*((row+col)%2 ? -1 : 1);
T cofactor(size_t row, size_t col) const {
return get_minor(row,col).det()*((row+col)%2 ? -1 : 1);
}

mat<DimRows,DimCols,T> adjugate() const {
mat<DimRows,DimCols,T> ret;
for (size_t i=DimRows; i--; )
for (size_t j=DimCols; j--; ret[i][j]=algAdd(i,j));
for (size_t j=DimCols; j--; ret[i][j]=cofactor(i,j));
return ret;
}

Expand All @@ -178,13 +183,18 @@ template<size_t DimRows,size_t DimCols,typename T> vec<DimRows,T> operator*(cons
return ret;
}

template<size_t R1,size_t C1,size_t C2,typename T>mat<R1,C2,T> operator*(const mat<R1,C1,T>& lhs, const mat<C1,C2,T>& rhs) {
mat<R1,C2,T> result;
for (size_t i=R1; i--; )
for (size_t j=C2; j--; result[i][j]=lhs[i]*rhs.col(j));
return result;
}

template<size_t DimRows,size_t DimCols,typename T>mat<DimCols,DimRows,T> operator/(mat<DimRows,DimCols,T> lhs, const T& rhs) {
for (size_t i=DimRows; i--; lhs[i]=lhs[i]/rhs);
return lhs;
}


template <size_t DimRows,size_t DimCols,class T> std::ostream& operator<<(std::ostream& out, mat<DimRows,DimCols,T>& m) {
for (size_t i=0; i<DimRows; i++) out << m[i] << std::endl;
return out;
Expand All @@ -196,7 +206,7 @@ typedef vec<2, float> Vec2f;
typedef vec<2, int> Vec2i;
typedef vec<3, float> Vec3f;
typedef vec<3, int> Vec3i;
typedef vec<4, float> Vec4f;
typedef mat<4,4,float> Matrix;

#endif //__GEOMETRY_H__

48 changes: 24 additions & 24 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,39 @@ Model *model = NULL;
const int width = 800;
const int height = 800;


Vec3f light_dir(1,1,1);
Vec3f eye(1,1,3);
Vec3f center(0,0,0);
Vec3f up(0,1,0);

struct Shader : public IShader {
mat<3,3,float> varying_tri;
mat<2,3,float> varying_uv;

virtual ~Shader() {}
Vec2i varying_uv[3];
float varying_inty[3];

virtual Vec3i vertex(int iface, int nthvert) {
varying_inty[nthvert] = model->normal(iface, nthvert)*Vec3f(light_dir);
varying_uv[nthvert] = model->uv(iface, nthvert);
Vec3f gl_Vertex = model->vert(iface, nthvert);
vec<4,float> p = (Viewport*(Projection*(ModelView*embed<4>(gl_Vertex))));
Vec3f gl_Position = proj<3>(p*(1.f/p[3]));
return Vec3i(gl_Position);
Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert));
gl_Vertex = Projection*ModelView*gl_Vertex;
varying_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3]));

varying_uv.set_col(nthvert, model->uv(iface, nthvert));

gl_Vertex = Viewport*gl_Vertex;
return proj<3>(gl_Vertex/gl_Vertex[3]);
}

virtual bool fragment(Vec3f bar, TGAColor &color) {
Vec2i uv;
for (size_t i=3;i--;) {
uv = uv + (varying_uv[i])*bar[i];
}

// float inty = varying_inty[0]*bar.x + varying_inty[1]*bar.y + varying_inty[2]*bar.z;
// inty = std::max(0.f, std::min(1.f, inty));
// color = model->diffuse(uv)*inty;
Vec2i uv = varying_uv*bar;
Vec3f n = model->normal(uv);
Vec3f reflected_light = n*(n*light_dir*2.f) - light_dir;
float diffuse_ity = std::max(n*light_dir, 0.f);
float ambient_ity = .1f;
float specular_ity = pow(std::max(reflected_light.z/reflected_light.norm(), 0.0f), model->specular(uv));

Matrix itm = Matrix::identity();//ModelView.invert_transpose();
vec<4,float> n = itm*embed<4>(model->normal(uv), 0.f);
Vec3f n2 = proj<3>(n).normalize();
float inty = n2*light_dir;
color = model->diffuse(uv)*inty;
float ity = CLAMP(.1f+n*light_dir, 0.f, 1.f);
TGAColor diff = model->diffuse(uv)*ity;
for (int c=0; c<3; c++) color[c] = std::min(5 + diff[c]*(diffuse_ity + .6f*specular_ity), 255.f);

return false;
}
Expand All @@ -56,13 +54,15 @@ int main(int argc, char** argv) {
} else {
model = new Model("obj/african_head.obj");
}

lookat(eye, center, up);
viewport(width/8, height/8, width*3/4, height*3/4);
projection(-1.f/(eye-center).norm());
light_dir.normalize();

TGAImage image (width, height, TGAImage::RGB);
TGAImage zbuffer(width, height, TGAImage::GRAYSCALE);

Shader shader;
for (int i=0; i<model->nfaces(); i++) {
Vec3i screen_coords[3];
Expand All @@ -71,10 +71,10 @@ int main(int argc, char** argv) {
}
triangle(screen_coords, shader, image, zbuffer);
}
image.flip_vertically();
image.write_tga_file("output.tga");

image. flip_vertically(); // to place the origin in the bottom left corner of the image
zbuffer.flip_vertically();
image. write_tga_file("output.tga");
zbuffer.write_tga_file("zbuffer.tga");

delete model;
Expand Down
8 changes: 6 additions & 2 deletions model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <sstream>
#include "model.h"

Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_() {
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() {
std::ifstream in;
in.open (filename, std::ifstream::in);
if (in.fail()) return;
Expand Down Expand Up @@ -41,6 +41,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.tga", normalmap_);
load_texture(filename, "_spec.tga", specularmap_);
}

Model::~Model() {}
Expand Down Expand Up @@ -94,8 +95,11 @@ Vec2i Model::uv(int iface, int nthvert) {
return Vec2i(uv_[idx][0]*diffusemap_.get_width(), uv_[idx][1]*diffusemap_.get_height());
}

float Model::specular(Vec2i uv) {
return specularmap_.get(uv.x, uv.y)[0]/1.f;
}

Vec3f Model::normal(int iface, int nthvert) {
int idx = faces_[iface][nthvert][2];
return norms_[idx].normalize();
}

2 changes: 2 additions & 0 deletions model.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Model {
std::vector<Vec2f> uv_;
TGAImage diffusemap_;
TGAImage normalmap_;
TGAImage specularmap_;
void load_texture(std::string filename, const char *suffix, TGAImage &img);
public:
Model(const char *filename);
Expand All @@ -26,6 +27,7 @@ class Model {
Vec3f vert(int iface, int nthvert);
Vec2i uv(int iface, int nthvert);
TGAColor diffuse(Vec2i uv);
float specular(Vec2i uv);
std::vector<int> face(int idx);
};

Expand Down
21 changes: 5 additions & 16 deletions our_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,6 @@ void lookat(Vec3f eye, Vec3f center, Vec3f up) {
}
}


Vec3f barycentric(Vec3i A, Vec3i B, Vec3i C, Vec3i P) {
Vec3f u = cross(Vec3f(C[0]-A[0], B[0]-A[0], A[0]-P[0]),Vec3f(C[1]-A[1], B[1]-A[1], A[1]-P[1]));
return std::abs(u[2])>.5 ? Vec3f(1.f-(u[0]+u[1])/u[2], u[1]/u[2], u[0]/u[2]) : Vec3f(-1,1,1); // dont forget that u[2] is an integer. If it is zero then triangle ABC is degenerate
}

/*
Vec3f barycentric(Vec3i A, Vec3i B, Vec3i C, Vec3i P) {
Vec3i s[2];
for (int i=2; i--; ) {
Expand All @@ -50,13 +42,10 @@ Vec3f barycentric(Vec3i A, Vec3i B, Vec3i C, Vec3i P) {
s[i][2] = A[i]-P[i];
}
Vec3f u = cross(s[0], s[1]);
if (std::abs(u[2])>1e-2) {
u = u*(1./u.z);
return u;
}
return Vec3f(-1,1,1);
if (std::abs(u[2])>1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate
return Vec3f(1.f-(u.x+u.y)/u.z, u.y/u.z, u.x/u.z);
return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator
}
*/

void triangle(Vec3i *pts, IShader &shader, TGAImage &image, TGAImage &zbuffer) {
Vec2i bboxmin( std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
Expand All @@ -68,12 +57,12 @@ void triangle(Vec3i *pts, IShader &shader, TGAImage &image, TGAImage &zbuffer) {
}
}
Vec3i P;
TGAColor color;
for (P[0]=bboxmin[0]; P[0]<=bboxmax[0]; P[0]++) {
for (P[1]=bboxmin[1]; P[1]<=bboxmax[1]; P[1]++) {
Vec3f c = barycentric(pts[0], pts[1], pts[2], P);
P[2] = std::max(0, std::min(255, int(pts[0][2]*c[0] + pts[1][2]*c[1] + pts[2][2]*c[2] + .5))); // clamping to 0-255 since it is stored in unsigned char
P[2] = std::max(0, std::min(255, int(pts[0].z*c[0] + pts[1].z*c[1] + pts[2].z*c[2] + .5))); // clamping to 0-255 since it is stored in unsigned char
if (c[0]<0 || c[1]<0 || c[2]<0 || zbuffer.get(P[0], P[1])[0]>P[2]) continue;
TGAColor color;
bool discard = shader.fragment(c, color);
if (!discard) {
zbuffer.set(P[0], P[1], TGAColor(P[2]));
Expand Down
3 changes: 3 additions & 0 deletions our_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,8 @@ struct IShader {
};

void triangle(Vec3i *pts, IShader &shader, TGAImage &image, TGAImage &zbuffer);
template <typename T> T CLAMP(const T& value, const T& low, const T& high) {
return value < low ? low : (value > high ? high : value);
}

#endif //__OUR_GL_H__
74 changes: 74 additions & 0 deletions shaders.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
struct FlatShader : public IShader {
mat<3,3,float> varying_tri;

virtual ~FlatShader() {}

virtual Vec3i vertex(int iface, int nthvert) {
Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert));
gl_Vertex = Projection*ModelView*gl_Vertex;
varying_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3]));
gl_Vertex = Viewport*gl_Vertex;
return proj<3>(gl_Vertex/gl_Vertex[3]);
}

virtual bool fragment(Vec3f bar, TGAColor &color) {
Vec3f n = cross(varying_tri.col(1)-varying_tri.col(0),varying_tri.col(2)-varying_tri.col(0)).normalize();
float intensity = CLAMP(n*light_dir, 0.f, 1.f);
color = TGAColor(255, 255, 255)*intensity;
return false;
}
};

struct GouraudShader : public IShader {
mat<3,3,float> varying_tri;
Vec3f varying_ity;

virtual ~GouraudShader() {}

virtual Vec3i vertex(int iface, int nthvert) {
Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert));
gl_Vertex = Projection*ModelView*gl_Vertex;
varying_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3]));

varying_ity[nthvert] = CLAMP(model->normal(iface, nthvert)*light_dir, 0.f, 1.f);

gl_Vertex = Viewport*gl_Vertex;
return proj<3>(gl_Vertex/gl_Vertex[3]);
}

virtual bool fragment(Vec3f bar, TGAColor &color) {
float intensity = varying_ity*bar;
color = TGAColor(255, 255, 255)*intensity;
return false;
}
};


struct ToonShader : public IShader {
mat<3,3,float> varying_tri;
Vec3f varying_ity;

virtual ~ToonShader() {}

virtual Vec3i vertex(int iface, int nthvert) {
Vec4f gl_Vertex = embed<4>(model->vert(iface, nthvert));
gl_Vertex = Projection*ModelView*gl_Vertex;
varying_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3]));

varying_ity[nthvert] = CLAMP(model->normal(iface, nthvert)*light_dir, 0.f, 1.f);

gl_Vertex = Viewport*gl_Vertex;
return proj<3>(gl_Vertex/gl_Vertex[3]);
}

virtual bool fragment(Vec3f bar, TGAColor &color) {
float intensity = varying_ity*bar;
if (intensity>.85) intensity = 1;
else if (intensity>.60) intensity = .80;
else if (intensity>.45) intensity = .60;
else if (intensity>.30) intensity = .45;
else if (intensity>.15) intensity = .30;
color = TGAColor(255, 155, 0)*intensity;
return false;
}
};

0 comments on commit 1cb0834

Please sign in to comment.