简体   繁体   English

在 C++ 中实现光栅化和深度缓冲区

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

I am trying to implement the rasterization method in cc+.我正在尝试在 cc+ 中实现光栅化方法。 I am trying to implement an interpolation function that handles the interpolation between the x,y and z vertices.我正在尝试实现一个插值函数来处理 x、y 和 z 顶点之间的插值。 That way I can save the inverse of z in a depth buffer.这样我就可以将 z 的倒数保存在深度缓冲区中。 At this point I get only the vertices drawn on the rendered image.在这一点上,我只得到渲染图像上绘制的顶点。 Can someone see what is wrong with my code?有人可以看到我的代码有什么问题吗? I have posted the full code so you can see the whole program.我已经发布了完整的代码,所以你可以看到整个程序。 Many thanks in advance.提前谢谢了。

EDIT编辑

I saw that I had made an error in vertexshader by writing pixel.zinv = 1 / vPrime.z instead of p.zinv = 1/ vPrime.z .我看到了,我已经在做了错误vertexshaderpixel.zinv = 1 / vPrime.z而不是p.zinv = 1/ vPrime.z Now nothing renders, just a black screen.现在没有任何渲染,只有黑屏。

EDIT 2 My check to see if a pixel should be painted was wrong.编辑 2我检查是否应该绘制像素是错误的。

if (depthBuffer[row[i].x][row[i].y] < row[i].zinv)

is correct.是正确的。 Now I get little pieces of color.现在我得到了小块的颜色。

#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;
    }
}

The last loop in the last function seems incorrect to me.最后一个函数中的最后一个循环对我来说似乎不正确。 You define currentx outside the loop.您在循环外定义 currentx 。 Then, define a local variable inside the loop with the same name and use it later in the loop.然后,在循环内定义一个同名的局部变量,并在循环中稍后使用它。 I'd suggest not using the same name for variable inside the loop and outside it to make it more readable.我建议不要对循环内外的变量使用相同的名称,以使其更具可读性。 Also, using global variables make the code difficult to read too, since I prefer to look at a function as a separate entity for analysis.此外,使用全局变量也使代码难以阅读,因为我更喜欢将函数视为单独的实体进行分析。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM