簡體   English   中英

在 C++ 中實現光柵化和深度緩沖區

[英]Implementing rasterization and depth buffer in c++

我正在嘗試在 cc+ 中實現光柵化方法。 我正在嘗試實現一個插值函數來處理 x、y 和 z 頂點之間的插值。 這樣我就可以將 z 的倒數保存在深度緩沖區中。 在這一點上,我只得到渲染圖像上繪制的頂點。 有人可以看到我的代碼有什么問題嗎? 我已經發布了完整的代碼,所以你可以看到整個程序。 提前謝謝了。

編輯

我看到了,我已經在做了錯誤vertexshaderpixel.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 。 然后,在循環內定義一個同名的局部變量,並在循環中稍后使用它。 我建議不要對循環內外的變量使用相同的名稱,以使其更具可讀性。 此外,使用全局變量也使代碼難以閱讀,因為我更喜歡將函數視為單獨的實體進行分析。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM