vs版本是2019,opencv版本是451
这个问题描述起来很长,首先我先贴出代码,代码是正确的,因为我成功运行了,但是!我重新开启另一个解决方案,代码报错了
cv库链接https://github.com/FaithBook233/RayTracing.git?%ra=link 作者:FaithBook-_- https://www.bilibili.com/read/cv9008428/?from=readlist 出处:bilibili
代码有3部分
这是main
#include <iostream>
#include "Vec3.h"
#include "Ray.h"
using namespace std;
#include <opencv.hpp>
#include <highgui.hpp>
using namespace cv;//添加OPENCV相关的头文件
bool HitSphere(const Vec3& Center, float Radius, const Ray& R)
{
Vec3 OC = R.Origin() - Center;
float A = Dot(R.Direction(), R.Direction());
float B = 2.0 * Dot(OC, R.Direction());
float C = Dot(OC, OC) - Radius * Radius;
float Discriminant = B * B - 4 * A * C;
return (Discriminant > 0);
}
Vec3 Color(const Ray& R)//声明一个color函数,用于计算射线R检测到的颜色,并且返回vec3表示所检测的颜色
{
if (HitSphere(Vec3(0, 0, -1), 0.5, R))
return Vec3(1, 0, 0);
Vec3 UnitDirection = UnitVector(R.Direction());
float T = 0.5 * (UnitDirection.Y() + 1.0);
return (1.0 - T) * Vec3(1.0, 1.0, 1.0) + T * Vec3(0.5, 0.7, 1.0);
}//在color返回值中T的范围是【0,1】,T越接近1,返回的颜色越接近vec(0.5,0.7,1.0)淡蓝色,否则越接近白色
int main()
{
int nx = 200;//图片宽度(单位为像素)
int ny = 200;//图片高度(像素)
//写入文件头
std::cout << "P3" << std::endl << nx << " " << ny << std::endl << "255" << std::endl;//P3表示颜色为ASCII,255是最大颜色
Vec3 LowerLeftCorner(-2.0, -1.0, -1.0);//设置左下角坐标
Vec3 Horizontal(4.0, 0.0, 0.0);//屏幕水平宽度
Vec3 Vertical(0.0, 2.0, 0.0);//屏幕垂直高度
Vec3 Origin(0.0, 0.0, 0.0);//原点(眼睛)位置
//预览窗口
int WidowWidth;//窗口宽度
int WindowHeight;//窗口高度
if (nx > ny)//图片为横板,计算高度与宽度
{
WindowHeight = 1080 - 200;
WidowWidth = (int)((double)WindowHeight * (double)nx / (double)ny);
}
else //图片为竖版
{
WidowWidth = 1920 - 200;
WindowHeight = (int)((double)WidowWidth * (double)ny / (double)nx);
}
Mat RenderingImage(ny, nx, CV_8UC3, Scalar(50, 50, 50));//创建第一张图
namedWindow(" 图像预览(渲染中)", WINDOW_NORMAL);//设置标题
moveWindow(" 图像预览(渲染中)", (int)((1720.0 - WidowWidth) / 2), (int)((1800.0 - WindowHeight) / 2) - 50);//设置窗口位置
resizeWindow(" 图像预览(渲染中)", WidowWidth, WindowHeight);//窗口大小
//为了方便对小数的应用,采用double类型
for (int j = nx - 1; j >= 0; j--)//图片的行信息(即一开始是在199层开始输出然后逐层往下)
{
for (int i = 0; i < nx; i++)//列信息(图片从0列开始往右输出)
{
//Vec3 Col(float(i) / float(nx), float(j) / float(ny), 0.2);//声明一个Col三维向量
float U = float(i) / float(nx);
float V = float(j) / float(ny);
//U,V为当前渲染的像素在屏幕高度中的占比,0为屏幕的最上方,1为最下方
Ray R(Origin, LowerLeftCorner + U * Horizontal + V * Vertical);//R为当前检测线
Vec3 Col = Color(R);//计算R检测线遇到的颜色并由Color函数返回
int ir = int(255.99 * Col[0]);
int ig = int(255.99 * Col[1]);
int ib = int(255.99 * Col[2]);//将像素的三个通道写入文件代替RGB变量
std::cout << ir << " " << ig << " " << ib << std::endl;//将数据写入ppm文件
//实时显示渲染帧数
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[0] = ib;
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[1] = ig;
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[2] = ir;
}
//每行计算填充完后刷新预览窗口
if (!(j % (ny / 100)))
{
imshow(" 图像预览(渲染中)", RenderingImage);
waitKey(1);//等待1毫秒后让窗口刷新出来
}
}
imshow(" 图像预览(渲染中)", RenderingImage);//展示窗口
waitKey(3000);//让窗口停留3000毫秒
destroyAllWindows();//关闭窗口
return 0;
}
这是vec3头文件
#pragma once
#pragma once
/*
Vec3类为空间三维坐标或RGB颜色的抽象类
E[3]数组为向量的具体数值
*/
#include<iostream>
#include<stdlib.h>
#include <Math.h>
class Vec3
{
public:
Vec3() {};
Vec3(double E0, double E1, double E2)
{
E[0] = E0;
E[1] = E1;
E[2] = E2;
}
//返回单个元素的值
//作为位置
inline double X() const { return E[0]; }
inline double Y() const { return E[1]; }
inline double Z() const { return E[2]; }
//作为RGB颜色
inline double R() const { return E[0]; }
inline double G() const { return E[1]; }
inline double B() const { return E[2]; }
//以下为运算符重载
inline const Vec3& operator+() const { return *this; }
inline Vec3 operator-() const { return Vec3(-E[0], -E[1], -E[2]); }
inline double operator[](int i)const { return E[i]; } //根据i获取元素
inline double& operator[](int i) { return E[i]; } //根据下标i获取元素引用
inline Vec3& operator+=(const Vec3& V2);
inline Vec3& operator-=(const Vec3& V2);
inline Vec3& operator*=(const Vec3& V2);
inline Vec3& operator/=(const Vec3& V2);
inline Vec3& operator*=(const double T);
inline Vec3& operator/=(const double T);
//返回向量长度,即模长
inline double Vec3Length() const {
return sqrt(E[0] * E[0] + E[1] * E[1] + E[2] * E[2]);
}
//返回向量的平方
inline double SquaredLength() const {
return E[0] * E[0] + E[1] * E[1] + E[2] * E[2];
}
//获得单位向量
inline void MakeUnitVector();
//以下为Vec3类的友元函数,在类内声明,类外定义,友元函数不属于任何类
friend inline Vec3 UnitVector(Vec3 V);
friend inline std::istream& operator>>(std::istream& IS, Vec3& T);
friend inline std::ostream& operator<<(std::ostream& OS, const Vec3& T);
friend inline Vec3 operator+(const Vec3& V1, const Vec3& V2);
friend inline Vec3 operator-(const Vec3& V1, const Vec3& V2);
friend inline Vec3 operator*(const Vec3& V1, const Vec3& V2);
friend inline Vec3 operator/(const Vec3& V1, const Vec3& V2);
friend inline Vec3 operator*(double T, const Vec3& V);
friend inline Vec3 operator/(const Vec3& V, double T);
friend inline Vec3 operator*(const Vec3& V, double T);
friend inline double Dot(const Vec3& V1, const Vec3& V2);
friend inline Vec3 Cross(const Vec3& V1, const Vec3& V2);
//向量的三个元素
double E[3];
protected:
private:
};
//以下为类的非成员函数
//输入运算符重载 ,用于输出Vec3元素数据
inline std::istream& operator>>(std::istream& IS, Vec3& T)
{
IS >> T.E[0] >> T.E[1] >> T.E[2];
return IS;
}
//输出运算符重载,用于输入Vec3元素数据
inline std::ostream& operator<<(std::ostream& OS, const Vec3& T)
{
OS << T.E[0] << " " << T.E[1] << " " << T.E[2];
return OS;
}
//获取向量的单位向量
inline void Vec3::MakeUnitVector()
{
double k = 1.0 / sqrt(E[0] * E[0] + E[1] * E[1] + E[2] * E[2]);
E[0] *= k;
E[1] *= k;
E[2] *= k;
}
inline Vec3 operator+(const Vec3& V1, const Vec3& V2)
{
return Vec3(V1.E[0] + V2.E[0], V1.E[1] + V2.E[1], V1.E[2] + V2.E[2]);
}
inline Vec3 operator-(const Vec3& V1, const Vec3& V2)
{
return Vec3(V1.E[0] - V2.E[0], V1.E[1] - V2.E[1], V1.E[2] - V2.E[2]);
}
inline Vec3 operator*(const Vec3& V1, const Vec3& V2)
{
return Vec3(V1.E[0] * V2.E[0], V1.E[1] * V2.E[1], V1.E[2] * V2.E[2]);
}
inline Vec3 operator/(const Vec3& V1, const Vec3& V2)
{
return Vec3(V1.E[0] / V2.E[0], V1.E[1] / V2.E[1], V1.E[2] / V2.E[2]);
}
inline Vec3 operator*(double T, const Vec3& V)
{
return Vec3(T * V.E[0], T * V.E[1], T * V.E[2]);
}
inline Vec3 operator/(const Vec3& V, double T)
{
return Vec3(V.E[0] / T, V.E[1] / T, V.E[2] / T);
}
inline Vec3 operator*(const Vec3& V, double T)
{
return Vec3(T * V.E[0], T * V.E[1], T * V.E[2]);
}
//向量的数乘,结果是数字 C = |a|·|b|·cos(a^b); C = a1 * b1 + a2 * b2 + a3 * b3;
inline double Dot(const Vec3& V1, const Vec3& V2)
{
return V1.E[0] * V2.E[0] + V1.E[1] * V2.E[1] + V1.E[2] * V2.E[2];
}
//向量的叉乘,结果是一个垂直于V1和V2所在平面的向量,其模长为 |a×b|=|a|·|b|·sin<a,b
inline Vec3 Cross(const Vec3& V1, const Vec3& V2)
{
return Vec3(
(V1.E[1] * V2.E[2] - V1.E[2] * V2.E[1]),
(-(V1.E[0] * V2.E[2] - V1.E[2] * V2.E[0])),
(V1.E[0] * V2.E[1] - V1.E[1] * V2.E[0])
);
}
inline Vec3& Vec3::operator+=(const Vec3& V)
{
E[0] += V.E[0];
E[1] += V.E[1];
E[2] += V.E[2];
return *this;
}
inline Vec3& Vec3::operator*=(const Vec3& V)
{
E[0] *= V.E[0];
E[1] *= V.E[1];
E[2] *= V.E[2];
return *this;
}
inline Vec3& Vec3::operator-=(const Vec3& V)
{
E[0] -= V.E[0];
E[1] -= V.E[1];
E[2] -= V.E[2];
return *this;
}
inline Vec3& Vec3::operator/=(const Vec3& V)
{
E[0] /= V.E[0];
E[1] /= V.E[1];
E[2] /= V.E[2];
return *this;
}
inline Vec3& Vec3::operator*=(const double T)
{
E[0] *= T;
E[1] *= T;
E[2] *= T;
return *this;
}
inline Vec3& Vec3::operator/=(const double T)
{
double K = 1.0 / T;
E[0] *= K;
E[1] *= K;
E[2] *= K;
return *this;
}
//向量/模长 = 单位方向向量
//这里可能有问题
inline Vec3 UnitVector(Vec3 V)
{
return V / V.Vec3Length();
}
这是ray的头文件
#pragma once
#include "Vec3.h"
class Ray
{
public:
Ray();
Ray(const Vec3& a, const Vec3& b) { A = a, B = b; }//构造函数,初始化原点向量A和方向向量B
Vec3 Origin() const { return A; }//返回值是原点向量A
Vec3 Direction() const { return B; }//返回值设定为方向向量B
Vec3 PointAtParameter(float T) const { return A + T * B; }//返回值设定为函数表达式P(t)=A+t*B,此时t表示一个实数对应光线上不同的点,A表示光线的起点,B表示光线方向
Vec3 A;
Vec3 B;//AB都是成员变量
};
这是正确的运行结果
因为cs是我测试用的解决方案,所以有些设置我现在也忘了,但我尝试过
1、目录是否含有中文
2、是否是空项目还是控制台应用的问题
3(这是我目前怀疑的点,但是无法验证)opencv环境配置的问题,所以我把两个解决方案的配置贴图出来
1.首先我在盘里和解决方案文件是有同样的opencv文件夹的
#include <iostream>
#include "Vec3.h"
using namespace std;
#include <opencv.hpp>
#include <highgui.hpp>
using namespace cv;//添加OPENCV相关的头文件
int main()
{
int nx = 200;//图片宽度(单位为像素)
int ny = 200;//图片高度(像素)
//写入文件头
std::cout << "P3" << std::endl << nx << " " << ny << std::endl << "255" << std::endl;//P3表示颜色为ASCII,255是最大颜色
//预览窗口
int WidowWidth;//窗口宽度
int WindowHeight;//窗口高度
if (nx > ny)//图片为横板,计算高度与宽度
{
WindowHeight = 1080 - 200;
WidowWidth = (int)((double)WindowHeight * (double)nx / (double)ny);
}
else //图片为竖版
{
WidowWidth = 1920 - 200;
WindowHeight = (int)((double)WidowWidth * (double)ny / (double)nx);
}
Mat RenderingImage(ny, nx, CV_8UC3, Scalar(50, 50, 50));//创建第一张图
namedWindow(" 图像预览(渲染中)", WINDOW_NORMAL);//设置标题
moveWindow(" 图像预览(渲染中)", (int)((1720.0 - WidowWidth) / 2), (int)((1800.0 - WindowHeight) / 2) - 50);//设置窗口位置
resizeWindow(" 图像预览(渲染中)", WidowWidth, WindowHeight);//窗口大小
//为了方便对小数的应用,采用double类型
for (int j = nx - 1; j >= 0; j--)//图片的行信息(即一开始是在199层开始输出然后逐层往下)
{
for (int i = 0; i < nx; i++)//列信息(图片从0列开始往右输出)
{
Vec3 Col(float(i) / float(nx), float(j) / float(ny), 0.2);//声明一个Col三维向量
int ir = int(255.99 * Col[0]);
int ig = int(255.99 * Col[1]);
int ib = int(255.99 * Col[2]);//将像素的三个通道写入文件代替RGB变量
std::cout << ir << " " << ig << " " << ib << std::endl;//将数据写入ppm文件
//元素顺序为蓝绿红
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[0] = ib;//蓝
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[1] = ig;//绿
RenderingImage.at<cv::Vec3b>(ny - 1 - j, i)[2] = ir;//红
}
//每行计算填充完后刷新预览窗口
if (!(j % (ny / 100)))
{
imshow(" 图像预览(渲染中)", RenderingImage);
waitKey(1);//等待1毫秒后让窗口刷新出来
}
}
imshow(" 图像预览(渲染中)", RenderingImage);//展示窗口
waitKey(3000);//让窗口停留3000毫秒
destroyAllWindows();//关闭窗口
return 0;
}
2.两个解决方案不同的是
2.1测试(cs)解决方案的opencv配置是在解决方案文件目录下的
结果报错了,无论我怎么改又或者新建解决方案复制cs的步骤,结果都无法重现,都会报错link2019
甚至,我新建方案配置cs的opencv库目录都无法重现结果
PS.
重建新方案中唯一没出现当初cs结果的是我在在使用最后一篇代码时
所以,这个问题应该怎么解决