加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
光栅化.cpp 3.87 KB
一键复制 编辑 原始数据 按行查看 历史
SadLava 提交于 2020-03-15 00:12 . 无纹理版本
#include <graphics.h>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#include <map>
using namespace std;
//判断点v是否在[a,b]中
//C#与JAVa的后遗症,EGEAPP
namespace EA {
using namespace std;
#define ct color_t
//几个全局变量
//屏幕buffer
color_t* wBuffer=nullptr;
//纹理buffer
color_t* tBuffer=nullptr;
//屏幕长宽
int W=0;
int H=0;
inline float F2I(float f) {
return floor(f);
}
//把浮点数位数强定为3位(担心爆精度
inline float F2F3(float f) {
return floor(f*1000.0f)/1000.0f;
}
template<class T>
inline bool IsCovered(T a,T b,T v) {
if(a>b) swap(a,b);
return (a<=v&&v<=b);
}
//数据类型
class Vertex2D {
public:
float x;
float y;
ct c;
inline Vertex2D() {
x=y=0.0f;
c=0;
}
inline Vertex2D(float _x,float _y,ct _c) {
x=_x,y=_y,c=_c;
}
inline void Format() {
x=EA::F2I(x);
y=EA::F2I(y);
}
inline VECTOR3D ToVec3D() {
return VECTOR3D(x,y,0);
}
};
typedef struct Vertex2D Ver2D;
//函数
//初始化绘图环境
void InitGraph(int w,int h) {
initgraph(w,h,0);
ege_enable_aa(1);
W=getwidth(),H=getheight();
wBuffer=getbuffer(NULL);
}
//颜色插值,0<=v<=1
inline ct ColorLerp(ct c1,ct c2,float v);
//2D顶点插值
inline Ver2D V2DLerp(Ver2D v1,Ver2D v2,float t);
//高速画点
inline void PutPixel_f(Ver2D v);
//高速画水平线
//这个会渐变
inline void DrawLine_f(float x1,float x2,float y,ct c1,ct c2);
//绘制简单三角,要求至少两个点y一样
inline void DrawSimpleTrangle(Ver2D v1,Ver2D v2,Ver2D v3);
//绘制复杂三角
inline void DrawTrangle(Ver2D v1,Ver2D v2,Ver2D v3);
#undef ct
}
using EA::Ver2D;
#define ct color_t
//程序入口
int main() {
EA::InitGraph(1000,600);
EA::DrawTrangle(Ver2D(0,EA::H/2,RED),Ver2D(EA::W/4,0,GREEN),Ver2D(EA::W/2,EA::H,BLUE));
delay_fps(60);
getch();
closegraph();
return 0;
}
ct EA::ColorLerp(ct c1,ct c2,float v) {
v=EA::F2F3(v);
int r=EGEGET_R(c1)-EGEGET_R(c2);
int g=EGEGET_G(c1)-EGEGET_G(c2);
int b=EGEGET_B(c1)-EGEGET_B(c2);
r=r*v+EGEGET_R(c2);
g=g*v+EGEGET_G(c2);
b=b*v+EGEGET_B(c2);
return EGERGB(r,g,b);
}
void EA::PutPixel_f(Ver2D v) {
v.Format();
if(EA::IsCovered(0,W,int(v.x))&&EA::IsCovered(0,H,int(v.y))) {
wBuffer[int(v.x+v.y*W)]=v.c;
}
}
void EA::DrawLine_f(float x1,float x2,float y,ct c1,ct c2) {
if(x1>x2) swap(x1,x2);
x1=F2I(x1);
x2=F2I(x2);
y=F2I(y);
for(float i=x1; i<=x2; ++i) {
PutPixel_f(Vertex2D(i,y,ColorLerp(c1,c2,float((i-x1)/(x2-x1)))));
}
}
//v1.y==v2.y
void EA::DrawSimpleTrangle(Ver2D v1,Ver2D v2,Ver2D v3) {
//Format
if(v2.y==v3.y&&v1.y!=v2.y) {
swap(v1,v2);
swap(v2,v3);
} else if(v1.y==v3.y&&v1.y!=v2.y) {
swap(v2,v3);
}
if(v1.x>v2.x) {
swap(v1,v2);
}
//解一次方程
float h=v3.y-v1.y;
float kL=(v3.x-v1.x)/h;
float kR=(v3.x-v2.x)/h;
float xL=0;
float xR=0;
ct c1=0,c2=0;
xL=v1.x;
xR=v2.x;
if(h>0) {
for(float i=v1.y; i<=v3.y; ++i) {
float percent=1.0f-(i-v1.y)/(v3.y-v1.y);
c1=EA::ColorLerp(v1.c,v3.c,percent);
c2=EA::ColorLerp(v2.c,v3.c,percent);
EA::DrawLine_f(xL,xR,i,c1,c2);
xL+=kL;
xR+=kR;
}
} else {
for(float i=v1.y; i>=v3.y; --i) {
float percent=(i-v3.y)/(v1.y-v3.y);
c1=EA::ColorLerp(v1.c,v3.c,percent);
c2=EA::ColorLerp(v2.c,v3.c,percent);
EA::DrawLine_f(xL,xR,i,c1,c2);
xL-=kL;
xR-=kR;
}
}
}
void EA::DrawTrangle(Ver2D v1,Ver2D v2,Ver2D v3) {
if(v1.y==v2.y||v1.y==v3.y||v2.y==v3.y) {
EA::DrawSimpleTrangle(v1,v2,v3);
} else {
//找出y中间的顶点,并放在v3的位置
if(v2.y<v1.y&&v1.y<v3.y) {
swap(v1,v3);
} else if(v1.y<v2.y&&v2.y<v3.y) {
swap(v2,v3);
}
//切成两半
float h=v1.y-v2.y;
float w=v1.x-v2.x;
Ver2D vm((w/h)*(v3.y-v2.y)+v2.x,v3.y,EA::ColorLerp(v2.c,v1.c,(v3.y-v2.y)/h));
swap(vm.c,v3.c);
//画他
DrawSimpleTrangle(v1,vm,v3);
DrawSimpleTrangle(v2,vm,v3);
}
}
#undef ct
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化