opencv 软光栅 初步

发布时间 2023-05-21 17:51:17作者: Lunamonna

 

1 Rasterizer.hpp

  

#pragma once

#include"Triangle.hpp"

#include<algorithm>
#include<iostream>
#include<Eigen/Eigen>

enum class BufferType{
    Color = 1,
    Depth = 2
};


inline BufferType operator | (BufferType a,BufferType b){
    return BufferType(int(a) | int(b));
}

inline BufferType operator & (BufferType a,BufferType b){
    return BufferType(int(a) & int(b));
}

class Rasterizer{
    public:
        Rasterizer(int w,int h);

        void setPixel(const Eigen::Vector3f& pt,const Eigen::Vector3f& color);

        void clear(BufferType buffType);

        std::vector<Eigen::Vector3f>& getFrameBuffer(){
            return frameBuffer;
        }

        int getBufferIndex(int x,int y);

    private:
        std::vector<Eigen::Vector3f> frameBuffer;
        std::vector<float> depthBuffer;

        int width;
        int height;

       
};

 

2 Rasterizer.cpp

#include"Rasterizer.hpp"
#include<opencv2/opencv.hpp>
#include<math.h>
#include<stdexcept>

Rasterizer::Rasterizer(int w,int h){
    width = w;
    height = h;
    frameBuffer.resize(w * h);
    depthBuffer.resize(w * h);
}

int Rasterizer::getBufferIndex(int x,int y){
    return x * width + y;
}

void Rasterizer::setPixel(const Eigen::Vector3f& pt,const Eigen::Vector3f& color){
    if(pt.x() < 0 || pt.y() >= width ||
       pt.y() < 0 || pt.y() >= width){
        return;
    }
    int idx = getBufferIndex(pt.x(),pt.y());
    if((size_t)idx >= frameBuffer.size()){
        return;
    }
    frameBuffer[idx] = color;
}

void Rasterizer::clear(BufferType buffType){
    if((buffType & BufferType::Color) == BufferType::Color){
        std::fill(frameBuffer.begin(),frameBuffer.end(),Eigen::Vector3f(0.0f,0.0f,0.0f));
    }

    if((buffType & BufferType::Depth) == BufferType::Depth){
        std::fill(depthBuffer.begin(),depthBuffer.end(),std::numeric_limits<float>::infinity());
    }
}

 

3. main.cpp

#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include"Rasterizer.hpp"

using namespace cv;

const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;

int main()
{
    int key = 0;
    int frameCount = 0;
    Rasterizer rasterizer(SCREEN_WIDTH,SCREEN_HEIGHT);

    rasterizer.clear(BufferType::Color | BufferType::Depth);

    Eigen::Vector3f red(0.0f,0.0f,1.0f);
    
    for(int i = 10;i <= 30;i++){
        for(int j = 20;j <= 40;j++){
            rasterizer.setPixel(Eigen::Vector3f(i,j,0),red);
        }
    }

    
    cv::Mat image(SCREEN_HEIGHT,SCREEN_WIDTH,CV_32FC3,rasterizer.getFrameBuffer().data());

    cv::imshow("image",image);

    key = cv::waitKey();

    return 0;
}

 

效果:

 

坐标系

 

 

所以帧缓存中获取索引是这样

int Rasterizer::getBufferIndex(int x,int y){
    return x * width + y;
}