C++ 在c+中实现光栅化和深度缓冲+;
我试图在cc+中实现光栅化方法。我正在尝试实现一个插值函数,用于处理x、y和z顶点之间的插值。这样我就可以把z的倒数保存在深度缓冲区中。 此时,我只在渲染图像上绘制顶点。有人能看到我的代码有什么问题吗?我已经发布了完整的代码,所以你可以看到整个程序。 非常感谢C++ 在c+中实现光栅化和深度缓冲+;,c++,graphics,3d,render,rasterizing,C++,Graphics,3d,Render,Rasterizing,我试图在cc+中实现光栅化方法。我正在尝试实现一个插值函数,用于处理x、y和z顶点之间的插值。这样我就可以把z的倒数保存在深度缓冲区中。 此时,我只在渲染图像上绘制顶点。有人能看到我的代码有什么问题吗?我已经发布了完整的代码,所以你可以看到整个程序。 非常感谢 if (depthBuffer[row[i].x][row[i].y] < row[i].zinv) 编辑 if (depthBuffer[row[i].x][row[i].y] < row[i].zinv) 我看到我在v
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
编辑
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
我看到我在vertexshader
中犯了一个错误,写的是pixel.zinv=1/vPrime.z
而不是p.zinv=1/vPrime.z
。现在没有渲染,只有一个黑屏
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
编辑2
我检查一个像素是否应该被绘制是错误的
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
if(depthBuffer[row[i].x][row[i].y]|
这是正确的。现在我得到了一些颜色
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
#include <iostream>
#include <glm/glm.hpp>
#include <SDL.h>
#include "SDLauxiliary.h"
#include "TestModel.h"
using namespace std;
using glm::vec2;
using glm::vec3;
using glm::ivec2;
using glm::mat3;
using glm::max;
// ----------------------------------------------------------------------------
// GLOBAL VARIABLES
int cc = 0;
const int SCREEN_WIDTH = 500;
const int SCREEN_HEIGHT = 500;
SDL_Surface* screen;
int t;
vector<Triangle> triangles;
vec3 cameraPos(0, 0, -3.001);
float f = 500;
double yaw = 0;
vec3 c1(cos(yaw), 0, -sin(yaw));
vec3 c2(0, 1, 0);
vec3 c3(sin(yaw), 0, cos(yaw));
glm::mat3 R(c1, c2, c3);
float translation = 0.1; // use this to set translation increment
const float PI = 3.1415927;
vec3 currentColor;
float depthBuffer[SCREEN_HEIGHT][SCREEN_WIDTH];
// ----------------------------------------------------------------------------
// STUCTURES
struct Pixel
{
int x;
int y;
float zinv;
}pixel;
// ----------------------------------------------------------------------------
// FUNCTIONS
void Update();
void Draw();
void VertexShader(const vec3& v, Pixel& p);
void Interpolate(ivec2 a, ivec2 b, vector<ivec2>& result);
void DrawLineSDL(SDL_Surface* surface, ivec2 a, ivec2 b, vec3 color);
void DrawPolygonEdges(const vector<vec3>& vertices);
void ComputePolygonRows(const vector<Pixel>& vertexPixels, vector<Pixel>& leftPixels, vector<Pixel>& rightPixels);
void DrawPolygonRows(const vector<Pixel>& leftPixels, const vector<Pixel>& rightPixels);
void DrawPolygon(const vector<vec3>& vertices);
void Interpolate2(Pixel a, Pixel b, vector<Pixel>& result);
int main(int argc, char* argv[])
{
LoadTestModel(triangles);
screen = InitializeSDL(SCREEN_WIDTH, SCREEN_HEIGHT);
t = SDL_GetTicks(); // Set start value for timer.
while (NoQuitMessageSDL())
{
Draw();
}
//Draw();
//cin.get();
SDL_SaveBMP(screen, "screenshot.bmp");
return 0;
}
void Draw()
{
SDL_FillRect(screen, 0, 0);
if (SDL_MUSTLOCK(screen))
SDL_LockSurface(screen);
for (int y = 0; y<SCREEN_HEIGHT; ++y)
for (int x = 0; x<SCREEN_WIDTH; ++x)
depthBuffer[y][x] = 0;
for (int i = 0; i<triangles.size(); ++i)
{
currentColor = triangles[i].color;
vector<vec3> vertices(3);
int aa = 24;
vertices[0] = triangles[i].v0;
vertices[1] = triangles[i].v1;
vertices[2] = triangles[i].v2;
DrawPolygon(vertices);
}
if (SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);
SDL_UpdateRect(screen, 0, 0, 0, 0);
}
void VertexShader(const vec3& v, Pixel& p)
{
vec3 vPrime = (v - cameraPos)*R;
p.zinv = 1 / vPrime.z;
p.x = f * vPrime.x / vPrime.z + SCREEN_WIDTH / 2;
p.y = f * vPrime.y / vPrime.z + SCREEN_HEIGHT / 2;
//cout << p.x << " this is it " << p.y << endl;
depthBuffer[p.x][p.y] = pixel.zinv;
}
void ComputePolygonRows(const vector<Pixel>& vertexPixels,
vector<Pixel>& leftPixels, vector<Pixel>& rightPixels)
{
// Find y-min,max for the 3 vertices
vec3 vp(vertexPixels[0].y, vertexPixels[1].y, vertexPixels[2].y);
Pixel start; Pixel end; Pixel middle;
int yMin = 1000;
int yMax = -1000;
int w=0; int s=0;
for (int k = 0; k < vertexPixels.size(); ++k)
{
if (vp[k] <= yMin)
{
yMin = vp[k];
end = vertexPixels[k];
w = k;
}
}
for (int k = 0; k < vertexPixels.size(); ++k)
{
if (vp[k] >= yMax)
{
yMax = vp[k];
start = vertexPixels[k];
s = k;
}
}
for (int k = 0; k < vertexPixels.size(); ++k)
{
if (vertexPixels[k].y != start.y
&& vertexPixels[k].y != end.y)
{
middle = vertexPixels[k];
}
if (w!= k && s!= k)
{
middle = vertexPixels[k];
}
}
int ROWS = yMax - yMin + 1;
leftPixels.resize(ROWS);
rightPixels.resize(ROWS);
for (int i = 0; i<ROWS; ++i)
{
leftPixels[i].x = +numeric_limits<int>::max();
rightPixels[i].x = -numeric_limits<int>::max();
}
int pixels1 = glm::abs(start.y - end.y) + 1;
vector<Pixel> line1(pixels1);
Interpolate2(end, start, line1);
int pixels2 = glm::abs(end.y - middle.y) + 1;
vector<Pixel> line2(pixels2);
Interpolate2(end, middle, line2);
int pixels3 = glm::abs(middle.y - start.y) + 1;
vector<Pixel> line3(pixels3);
Interpolate2(middle, start, line3);
vector<Pixel> side1(ROWS);
for (int i = 0; i < line2.size(); ++i)
{
side1[i] = line2[i];
}
for (int i = 0; i < line3.size(); ++i)
{
side1[line2.size()+i-1] = line3[i];
}
for (int i = 0; i < ROWS; ++i)
{
if (line1[i].x < leftPixels[i].x)
{
leftPixels[i] = line1[i];
}
if (line1[i].x > rightPixels[i].x)
{
rightPixels[i] = line1[i];
}
if (side1[i].x < leftPixels[i].x)
{
leftPixels[i] = side1[i];
}
if (side1[i].x > rightPixels[i].x)
{
rightPixels[i] = side1[i];
}
}
}
void DrawPolygonRows(const vector<Pixel>& leftPixels, const vector<Pixel>& rightPixels)
{
//cout << cc++ << endl;
for (int k = 0; k < leftPixels.size(); ++k)
{
int pixels = glm::abs(leftPixels[k].x - rightPixels[k].x) + 1;
vector<Pixel> row(pixels);
Interpolate2(leftPixels[k], rightPixels[k], row);
for (int i = 0; i < pixels; ++i)
{
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)
{
PutPixelSDL(screen, row[i].x, row[i].y, currentColor);
depthBuffer[row[i].x][row[i].y] = row[i].zinv;
}
}
}
}
void DrawPolygon(const vector<vec3>& vertices)
{
int V = vertices.size();
vector<Pixel> vertexPixels(V);
for (int i = 0; i<V; ++i)
VertexShader(vertices[i], vertexPixels[i]);
vector<Pixel> leftPixels;
vector<Pixel> rightPixels;
ComputePolygonRows(vertexPixels, leftPixels, rightPixels);
DrawPolygonRows(leftPixels, rightPixels);
}
void Interpolate2(Pixel a, Pixel b, vector<Pixel>& result)
{
int N = result.size();
float stepx = (b.x - a.x) / float(glm::max(N - 1, 1));
float stepy = (b.y - a.y) / float(glm::max(N - 1, 1));
float stepz = (b.zinv - a.zinv) / float(glm::max(N - 1, 1));
float currentx = a.x;
float currenty = a.y;
float currentz = a.zinv;
for (int i = 0; i<N; ++i)
{
result[i].x = currentx;
result[i].y = currenty;
result[i].zinv = currentz;
currentx = a.x;
currenty = a.y;
currentz = a.zinv;
currentx += stepx;
currenty += stepy;
currentz += stepz;
}
}
#包括
#包括
#包括
#包括“SDLauxiliary.h”
#包括“TestModel.h”
使用名称空间std;
使用glm::vec2;
使用glm::vec3;
使用glm::ivec2;
使用glm::mat3;
使用glm::max;
// ----------------------------------------------------------------------------
//全局变量
int cc=0;
屏幕宽度=500;
屏幕内的常数_高度=500;
SDL_表面*屏幕;
int t;
矢量三角形;
vec3 cameraPos(0,0,-3.001);
浮动f=500;
双偏航=0;
vec3c1(cos(偏航),0,-sin(偏航));
vec3c2(0,1,0);
vec3-c3(sin(偏航),0,cos(偏航));
glm::MAT3R(c1,c2,c3);
浮点转换=0.1;//使用此选项设置平移增量
常数浮点PI=3.1415927;
vec3电流颜色;
浮动深度缓冲器[屏幕高度][屏幕宽度];
// ----------------------------------------------------------------------------
//结构
结构像素
{
int x;
int-y;
浮锌;
}像素;
// ----------------------------------------------------------------------------
//功能
无效更新();
无效抽取();
void VertexShader(const vec3&v、Pixel&p);
无效插值(ivec2 a、ivec2 b、向量和结果);
虚线SDL(SDL_表面*表面,ivec2 a,ivec2 b,vec3颜色);
void DrawPolygonEdges(常量向量和顶点);
void ComputePolygonRows(常量向量和顶点像素、向量和左像素、向量和右像素);
void DrawPolygonRows(常量向量和左像素、常量向量和右像素);
void DrawPolygon(常量向量和顶点);
无效插值2(像素a、像素b、向量和结果);
int main(int argc,char*argv[])
{
LoadTestModel(三角形);
屏幕=初始值DL(屏幕宽度、屏幕高度);
t=SDL_GetTicks();//设置计时器的启动值。
while(NoQuitMessageSDL())
{
Draw();
}
//Draw();
//cin.get();
SDL_SaveBMP(屏幕,“screenshot.bmp”);
返回0;
}
作废提款()
{
SDL_FillRect(屏幕,0,0);
如果(SDL_必须锁定(屏幕))
SDL_锁面(屏幕);
对于(int y=0;y最后一个函数中的最后一个循环对我来说似乎不正确。你在循环外定义currentx。然后,在循环内定义一个同名的局部变量,稍后在循环中使用它。我建议不要在循环内和循环外使用相同的名称,以使其更可读。此外,使用全局变量使e代码也很难阅读,因为我更喜欢将函数视为单独的实体进行分析。最后一个函数中的最后一个循环对我来说似乎不正确。您在循环外部定义currentx。然后,在循环内部定义一个同名的局部变量,稍后在循环中使用它。我建议不要对变量insi使用相同的名称对循环进行反循环和外部处理,使其更具可读性。此外,使用全局变量也会使代码更难阅读,因为我更喜欢将函数视为单独的实体进行分析。我同意!我已经更改了它,但仍然是一个黑屏。感谢您的帮助。它现在可以工作了!:)问题在于你所说的。我更改了名称,效果很好。感谢你的帮助。我已经做了一段时间了。现在唯一的问题是,当我移动相机时,我认为插值失败。我将它移动到了“答案”中,以便你可以接受它作为记录。我很高兴我可以提供帮助:)
if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)