Rasterization 学习笔记

======================Barycentric interpolation======================================

<1>2d/3d Check point in triangle test

float areas(vector p1;vector p2;vector p3)
{
return length(cross(p1-p2,p3-p2)) * 0.5f;
} int ptInTri(vector inpt;vector p1;vector p2; vector p3)
{
float s = areas(p1,p2,p3);
float s1 = areas(inpt,p2,p3) / s;
float s2 = areas(inpt,p3,p1) / s;
float s3 = areas(inpt,p1,p2) / s;
if(s1<0.0f || s1>1.0f)
{
return false;
}
if(s2 < 0.0f || s2 >)
{
return false;
}
if(s3 < 0.0f || s3 >)
{
return false;
}
float all = s1 + s2 + s3;
if (all-1.0f<0.000001f)
return true;
else
return false;
}

<2>2d check can use :

<test 3d in houdini found problem>

int ptInTri2(vector P;vector A;vector B; vector C)
{
vector u = B - A;
vector v = C - A;
vector w = P - A; vector vCrossW = cross(v, w);
vector vCrossU = cross(v, u); if (dot(vCrossW, vCrossU) < )
return false; vector uCrossW = cross(u, w);
vector uCrossV = cross(u, v); // Test sign of t
if (dot(uCrossW, uCrossV) < )
return false; float denom = length(uCrossV);
float r = length(vCrossW) / denom;
float t = length(uCrossW) / denom; return (r + t <= );
}

<3> Color Interpolation:

Rasterization 学习笔记

float areas(vector p1;vector p2;vector p3)
{
return length(cross(p1-p2,p3-p2)) * 0.5f;
} vector P = getInputP();
float s = areas(p1,p2,p3);
float s1 = areas(P,p2,p3) / s;
float s2 = areas(P,p3,p1) / s;
float s3 = areas(P,p1,p2) / s; vector PColor = p1.color * s1 + p2.color*s2 + p3.color*s3;

<4>we can use this method to getPointAt uv like maya function or houdini primuv();

Rasterization 学习笔记

float areas(vector p1;vector p2;vector p3)
{
return length(cross(p1-p2,p3-p2)) * 0.5f;
} vector getPointAtUV(float u;float v)
{
clamp(u,,);
clamp(v,,); // get current gdp's points
vector gdpPtsPos[];
for(int i=;i<;i++)
{
vector curl = point(,"P",i);
//printf("%f ,%f , %f \n",curl[0],curl[1],curl[2]);
append(gdpPtsPos,curl);
} vector p1 = gdpPtsPos[];
vector p2 = gdpPtsPos[];
vector p3 = gdpPtsPos[]; // tri area
float s = areas(p1,p2,p3);
// reverse to get base on u value float uArea = u * 0.5 / s; // reverse to get base on v value
float vArea = v * 0.5 / s ; // the w value
float wArea =;
if( - uArea - vArea < )
{
wArea = ;
}
else
{
wArea =( - u - v )*0.5 / s;
} //https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates //P=uA+vB+wC. vector retP = p1 * uArea + p2*vArea + p3*wArea;
return retP; } #define maxscatter 100000 for(int i=;i<maxscatter;i++)
{
float u = rand(i);
float v = rand(i*);
vector retPos = getPointAtUV(u,v);
addpoint(geoself(),retPos);
}

<4>Color Define:

(1)ARGB:uint32_t,也就是单位为uint8_t ,共4个,a ,r ,g ,b    0xFF FF FF FF (255,255,255,255)

//  uint32_t c;

A:(uint8_t)   ( (c & 0xFF   ) >>)
R:(uint8_t) ( (c & 0x00 FF ) >>)
G:(uint8_t) ( (c & 0x00 FF ) >>)
B:(uint8_t) ( (c & 0x00 FF) >>)

(2)从uint8_t r,g,b,a转换到uint32_t,用位和求回去

((uint32_t)a<<) | ((uint32_t)r<<) | ((uint32_t)g<<) | ((uint32_t)b<<)

(2)float color:sixteen bytes:

struct color{float a, float r,float g,float b}

转换成ARGB(uint32_t)颜色也简单.

color fc = {1.0f,0.5f,0.0f,1.0f};
uint8_t r = (uint8_t) (floorf(fc.r*255.0f))
uint8_t g = (uint8_t) (floorf(fc.g*255.0f))
uint8_t b = (uint8_t) (floorf(fc.b*255.0f))
uint8_t a = (uint8_t) (floorf(fc.a*255.0f))

=========================Rasterization==================================================

<1>Line:

画斜线没用到斜率方程,直接用的线性差值。

Rasterization 学习笔记

DrawApi.h

#ifndef DRAWAPI_H
#define DRAWAPI_H #include <QImage>
#include "LineSegment.h"
#include <glm/glm.hpp>
#include <iostream>
#include "MathUtility.h"
using namespace TopVertex;
class DrawApi
{
public:
template <typename T = glm::vec3>
static void drawLine(QImage &image ,LineSegment<T> &line,const glm::vec3 &color)
{ auto &sp = line.startPoint();
auto &ep = line.endPoint();
float m = line.getSlope(); if(line.getType() == LineSegment<T>::HORIZON)
{
std::cout << "write horizon line\n";
auto y = sp[];
for(int x=sp[] ; x <= ep[]; x++)
{
image.setPixel(x,y,qRgb(color[],color[],color[]));
}
return;
}
if(line.getType() == LineSegment<T>::VERTICAL)
{
std::cout << "write verticle line\n";
auto x = sp[];
auto y0 = sp[];
auto y1 = ep[];
if(y0 < y1)
{
for(int y=y0;y<=y1;y++)
{
image.setPixel(x,y,qRgb(color[],color[],color[]));
}
}
else
{
for(int y=y1;y<=y0;y++)
{
image.setPixel(x,y,qRgb(color[],color[],color[]));
}
}
return;
}
if(line.getType() == LineSegment<T>::NORMAL)
{
std::cout << "write normal line\n";
int startRow = ;
int endRow = ; if(sp[] < ep[])
{
startRow = sp[];
endRow = ep[];
}
else
{
startRow = ep[];
endRow = sp[];
}
for(int r = startRow;r<=endRow;r++)
{
auto bias = GLY_MATH::fit<float>(r,startRow,endRow,0.1f,1.0f);
auto pos = GLY_MATH::linearInterpolation(sp,ep,bias);
image.setPixel(pos[],pos[],qRgb(color[],color[],color[]));
}
return;
} }
}; #endif // DRAWAPI_H

LineSegment.h

#ifndef LINESEGMENT_H
#define LINESEGMENT_H
#include <algorithm>
#include <cmath>
#include <string>
#include <iostream>
#include <glm/glm.hpp>
template <typename T>
class LineSegment
{
public:
typedef T value_type;
enum TYPE{VERTICAL,HORIZON,NORMAL};
LineSegment(T startPoint,T endPoint):
mStartPoint(startPoint),mEndPoint(endPoint)
{
// LINE PROPERTY
evalLineProperty();
// LINE PROPERTY
}
LineSegment()=default;
void setPoints(const T &startPoint , const T &endPoint)
{
mStartPoint = startPoint;
mEndPoint = endPoint;
evalLineProperty();
}
inline T & operator[](int i)
{
if(i == )
{
return mStartPoint;
}
else if(i == )
{
return mEndPoint;
}
else
{
throw std::string("Can't get point over 2\n").c_str();
} }
TYPE getType();
T &startPoint();
T &endPoint();
T startPoint()const;
T endPoint()const;
float getSlope()const; template <typename T2,typename T3>
inline T2 intersect(const LineSegment<T3> &Line)
{
auto st_y = Line.startPoint()[]; // get line y value
auto it_x = (st_y - startPoint()[] + startPoint()[]*getSlope())/getSlope(); // y slope function get x pos
return T2(it_x,st_y);
} private:
void evalLineProperty()
{ auto x0 = mStartPoint[];
auto x1 = mEndPoint[]; if(x0 > x1)
{
swap(mStartPoint,mEndPoint);
} x0 = mStartPoint[];
x1 = mEndPoint[];
auto y0 = mStartPoint[];
auto y1 = mEndPoint[]; if(fabs(y1-y0) <= 0.0000001f) // horizon line slope = 0
{
mSlope = 0.0f;
mLineType = HORIZON;
}
else if(fabs(x1-x0) <= 0.000001f) // verticle line slope = 0
{
mSlope = 0.0f;
mLineType = VERTICAL;
}
else // slope !=0
{
mSlope = (y1 - y0) / (x1-x0);
mLineType = NORMAL;
}
} T mStartPoint;
T mEndPoint;
TYPE mLineType;
float mSlope;
}; template<typename T>
typename LineSegment<T>::TYPE LineSegment<T>::getType()
{
return mLineType;
} template<typename T>
float LineSegment<T>::getSlope() const
{
return mSlope;
} template<typename T>
T &LineSegment<T>::startPoint()
{
return mStartPoint;
} template<typename T>
T &LineSegment<T>::endPoint()
{
return mEndPoint;
} template<typename T>
T LineSegment<T>::startPoint()const
{
return mStartPoint;
} template<typename T>
T LineSegment<T>::endPoint()const
{
return mEndPoint;
} // ostream
inline std::ostream& operator<<(std::ostream &os,LineSegment<glm::vec3> line)
{
os << "Line start points:" << line.startPoint()[] << " " <<line.startPoint()[] << " "<<line.startPoint()[]
<< " | "
<< "end:" << line.endPoint()[]<< " "<< line.endPoint()[] << " "<< line.endPoint()[] ;
return os;
} inline std::ostream& operator<<(std::ostream &os,LineSegment<glm::vec2> line)
{
os << "Line start points:" << line.startPoint()[] << " " <<line.startPoint()[] << "|"
<< "end:" << line.endPoint()[]<< " "<< line.endPoint()[] ;
return os;
} #endif // LINESEGMENT_H

MathUtility.h

#ifndef MATHUTILITY_H
#define MATHUTILITY_H #include <string>
#include <vector>
#include <iostream>
#include <sstream>
using namespace std; namespace TopVertex
{
class GLY_MATH
{
public: template<typename T>
static T linearInterpolation(T val1 , T val2,float bias)
{
return val1*(-bias) + val2*bias;
} template<typename T>
static T min(T a, T b) {
if (a > b) {
return b;
} else {
return a;
}
} template<typename T>
static T max(T a, T b) {
if (a > b) {
return a;
} else {
return b;
}
} template<typename T>
static bool zero_compare(T a, double tol = 0.00001) {
return a >= -tol && a <= tol;
} // DO NOT USE THIS FIT TO FIT VECTOR VALUE
template<typename T>
static T fit(T var, T omin, T omax, T nmin, T nmax) {
T d = omax - omin;
if (zero_compare(d)) {
return (nmin + nmax) * 0.5;
}
if (omin < omax) {
if (var < omin) return nmin;
if (var > omax) return nmax;
} else {
if (var < omax) return nmax;
if (var > omin) return nmin;
}
return nmin + (nmax - nmin) * (var - omin) / d;
} //return -1 to 1
template<typename T>
static T fit_negate(T var, T omin, T omax) {
return fit(var, omin, omax, -1.0, 1.0);
} //string split
static std::vector<std::string> split_string(std::string &inputString, char &split_char) {
std::stringstream ss(inputString);
std::string sub_str;
std::vector<std::string> sp_strPath;
sp_strPath.clear();
while (getline(ss, sub_str, split_char)) {
sp_strPath.push_back(sub_str);
}
return sp_strPath;
} //value to string
template<typename T>
// T must be a value int/float/double
static std::string value_to_str(T &value) {
std::ostringstream os;
os << value;
return os.str();
} static int wang_inthash(int key) {
// From http://www.concentric.net/~Ttwang/tech/inthash.htm
key += ~(key << );
key ^= (key >> );
key += (key << );
key ^= (key >> );
key += ~(key << );
key ^= (key >> );
return key;
} static int fastRandomInt(int seed) {
int nseed = seed * +0XFFFFFFF;
return wang_inthash(nseed);
} static float fastRandom01(int seed)
{
return float(fastRandomInt(seed) % ) / 1000000.0f;
} };
} #endif // MATHUTILITY_H

Renderer.h

#ifndef RENDERER_H
#define RENDERER_H #include <QImage>
#include <iostream>
#include <glm/glm.hpp> using namespace std; class Renderer
{
public:
Renderer();
void render();
}; #endif // RENDERER_H

Renderer.cpp

#include "Renderer.h"
#include "DrawApi.h" Renderer::Renderer()
{ } void Renderer::render()
{ QImage image(,,QImage::Format_RGB32);
image.fill(Qt::gray);
glm::vec3 p0(,,);
glm::vec3 p1(,,);
glm::vec3 p2(,,); // write horizon line
glm::vec3 p3(,,);
glm::vec3 p4(,,);
auto hline1 = LineSegment<glm::vec3>(p3,p4);
DrawApi::drawLine(image,hline1,glm::vec3(,,)); // write verticle line
glm::vec3 p5(,,);
glm::vec3 p6(,,);
auto hline2 = LineSegment<glm::vec3>(p5,p6);
DrawApi::drawLine(image,hline2,glm::vec3(,,)); // write normal line
glm::vec3 p7(,,);
glm::vec3 p8(,,);
auto hline3 = LineSegment<glm::vec3>(p8,p7);
DrawApi::drawLine(image,hline3,glm::vec3(,,)); image.save("c:/Raster.jpg",,);
return ;
}

main.cpp

auto render =  Renderer();
render.render();

Rasterization 学习笔记

Rasterization 学习笔记

以上的方法不过还是垃圾,因为还是循环像素row。对于以上的方法如果不考虑计算成本,直接暴力法循环row,

然后判断pixelPos是不是在triangle里面。是就给他画出来。

最好的方法:

Rasterization 学习笔记

线求交:

Rasterization 学习笔记

2,矩阵大法:

计算 :

Rasterization 学习笔记

rotate:

Rasterization 学习笔记

Rasterization 学习笔记

Scale:

Rasterization 学习笔记

Rasterization 学习笔记

translate:

Rasterization 学习笔记

Rasterization 学习笔记

得到的XF = 1*x + 0*y + 1*tx = x + tx;

得到的YF = 0*x + 1*y + 1*ty = y + ty;

总体带x,y,w

Rasterization 学习笔记

3d:

Rasterization 学习笔记

Rasterization 学习笔记

Orthographic Matrix:

Rasterization 学习笔记

Perspective Matrix

Rasterization 学习笔记

Viewport Transform:

Rasterization 学习笔记

Raster Pipeline:

Rasterization 学习笔记

Rasterization 学习笔记

..

上一篇:使用POI读取excel文件内容


下一篇:python Unittest+excel+ddt数据驱动测试