2016-05-03 41 views
1

我想在cc +中实现光栅化方法。我试图实现一个插值函数来处理x,y和z顶点之间的插值。这样我就可以将z的逆元素保存在深度缓冲区中。 在这一点上,我只得到渲染图像上绘制的顶点。有人可以看到我的代码有什么问题吗?我已经发布了完整的代码,以便您可以看到整个程序。 非常感谢提前。在C++中实现光栅化和深度缓冲区

编辑

我看到了,我已经写pixel.zinv = 1/vPrime.z代替p.zinv = 1/ vPrime.zvertexshader犯了一个错误。现在什么都没有呈现,只是一个黑屏。

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。然后,在循环内定义一个具有相同名称的局部变量,并稍后在循环中使用它。我建议不要在循环内部使用相同的名称作为变量,并在外部使其更具可读性。而且,使用全局变量也会使代码难以阅读,因为我更喜欢将函数看作是用于分析的独立实体。