简体   繁体   中英

Implementing rasterization and depth buffer in c++

I am trying to implement the rasterization method in cc+. I am trying to implement an interpolation function that handles the interpolation between the x,y and z vertices. That way I can save the inverse of z in a depth buffer. 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 . Now nothing renders, just a black screen.

EDIT 2 My check to see if a pixel should be painted was wrong.

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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