Я пытаюсь реализовать метод растеризации в cc +. Я пытаюсь реализовать функцию интерполяции, которая обрабатывает интерполяцию между вершинами x, y и z. Таким образом, я могу сохранить инверсию z в буфере глубины.
На этом этапе я получаю только вершины, нарисованные на визуализированном изображении. Может кто-нибудь увидеть, что не так с моим кодом? Я разместил полный код, чтобы вы могли увидеть всю программу.
Спасибо заранее.
РЕДАКТИРОВАТЬ
Я увидел, что сделал ошибку в vertexshader
написав pixel.zinv = 1 / vPrime.z
вместо p.zinv = 1/ vPrime.z
, Теперь ничего не рендерится, только черный экран.
РЕДАКТИРОВАТЬ 2
Моя проверка, чтобы видеть, должен ли быть нарисован пиксель, был неправильным.
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;
}
}
Последний цикл в последней функции мне кажется неверным. Вы определяете currentx вне цикла. Затем определите локальную переменную внутри цикла с тем же именем и используйте ее позже в цикле. Я бы предложил не использовать одно и то же имя для переменной внутри цикла и вне его, чтобы сделать его более читабельным. Кроме того, использование глобальных переменных также затрудняет чтение кода, поскольку я предпочитаю рассматривать функцию как отдельную сущность для анализа.
Других решений пока нет …