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

列波夫斯基

我正在尝试在cc +中实现栅格化方法。我正在尝试实现处理x,y和z顶点之间的插值的插值函数。这样,我可以将z的倒数保存在深度缓冲区中。此时,我仅获得绘制在渲染图像上的顶点。有人可以看到我的代码有什么问题吗?我已经发布了完整的代码,因此您可以看到整个程序。提前谢谢了。

编辑

我发现自己vertexshader写了pixel.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;
    }
}
Eissa N.

最后一个函数中的最后一个循环对我来说似乎是不正确的。您可以在循环外部定义currentx。然后,在循环内部用相同的名称定义一个局部变量,并在循环中稍后使用它。我建议不要在循环内部和外部使用相同的变量名称,以使其更具可读性。而且,使用全局变量也使代码也难以阅读,因为我更喜欢将函数视为一个单独的实体进行分析。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

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

来自分类Dev

c + +和DX11中的动态常量缓冲区或动态顶点缓冲区

来自分类Dev

C中的缓冲区互斥量和条件变量

来自分类Dev

了解C中const缓冲区和read()的用法

来自分类Dev

如何在目标C中实现循环缓冲区以实现高性能

来自分类Dev

C ++中的缓冲区大小

来自分类Dev

C ++中的位缓冲区

来自分类Dev

在C ++中解析协议缓冲区

来自分类Dev

C中的缓冲区溢出与获取

来自分类Dev

在C#中同步缓冲区

来自分类Dev

C中自发的缓冲区溢出

来自分类Dev

使用双端队列在C ++中实现循环缓冲区

来自分类Dev

C测试问题中的循环缓冲区实现

来自分类Dev

在C ++中初始化卤化物缓冲区

来自分类Dev

使用 pybind11 从 C++ 反序列化 Python 中的 protobuf 缓冲区

来自分类Dev

在一个函数(OpenGL和C ++)中多次交换缓冲区

来自分类Dev

您将如何限制缓冲区大小并返回c ++中的缓冲区限制?

来自分类Dev

C-printf和scanf缓冲区

来自分类Dev

C ++-缓冲区和流都需要什么?

来自分类Dev

C ++-缓冲区和流都需要什么?

来自分类Dev

C读取文件和打印缓冲区

来自分类Dev

C ++刷新缓冲区

来自分类Dev

C缓冲区指针

来自分类Dev

缓冲区溢出 C

来自分类Dev

C中循环缓冲区中的反向遍历

来自分类Dev

协议缓冲区C ++中的异常处理

来自分类Dev

C ++读取缓冲区中的整个文件

来自分类Dev

缓冲区数组在C中的for循环中溢出

来自分类Dev

在C中的fgets()之后清除输入缓冲区