2016-05-03 2 views
1

Я пытаюсь реализовать метод растеризации в cc +. Я пытаюсь реализовать функцию интерполяции, которая обрабатывает интерполяцию между вершинами x, y и z. Таким образом, я могу сохранить инверсию z в ​​буфере глубины. В этот момент я получаю только вершины, нарисованные на визуализированном изображении. Может кто-то увидеть, что не так с моим кодом? Я опубликовал полный код, чтобы вы могли видеть всю программу. Большое спасибо заранее.Реализация растрирования и буфера глубины в C++

EDIT

я увидел, что я сделал ошибку в vertexshader написав pixel.zinv = 1/vPrime.z вместо p.zinv = 1/ vPrime.z. Теперь ничего не отображается, просто черный экран.

EDIT 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; 
    } 
} 
+0

Последний цикл последней функции кажется мне неправильным. Вы определяете currentx вне цикла. Затем определите локальную переменную внутри цикла с тем же именем и используйте ее позже в цикле. Я бы предложил не использовать одно и то же имя для переменной внутри цикла и за ее пределами, чтобы сделать ее более читаемой. Кроме того, использование глобальных переменных затрудняет чтение кода, так как я предпочитаю рассматривать функцию как отдельный объект для анализа. –

+0

Согласен! Я изменил его, но все еще черный экран – Lebowski

+0

Eissa N. Спасибо за помощь. Он работает сейчас! :) Проблема была в том, что вы сказали. Я изменил имя, и оно работает. Ценю вашу помощь. Я уже давно это делаю. Единственная проблема в том, что когда я перемещаю камеру, я думаю, что интерполяция терпит неудачу. – Lebowski

ответ

1

Последний цикл последней функции кажется мне неправильным. Вы определяете currentx вне цикла. Затем определите локальную переменную внутри цикла с тем же именем и используйте ее позже в цикле. Я бы предложил не использовать одно и то же имя для переменной внутри цикла и за ее пределами, чтобы сделать ее более читаемой. Кроме того, использование глобальных переменных затрудняет чтение кода, так как я предпочитаю рассматривать функцию как отдельный объект для анализа.