小编Hay*_*ach的帖子

主要问题是将平截头体从相机空间转换为光空间以进行阴影贴图

我正在尝试在我的OpenGL/C++渲染器中实现级联阴影贴图.当从任意数字构建正交矩阵并保持在场景的原点时,我已经成功地实现了定向阴影贴图.从我能看到的一切,我遇到的问题是根据视锥体的切片决定正交矩阵的界限.

我找到了两种计算方法,两者都是相关的; 第一种方法使用当前切片的近/远平面创建投影矩阵,然后将其反转.然后我在NDC空间中取一个立方体的角(每个轴的范围从[-1:+1]),将它乘以反转投影矩阵,倒置视图矩阵,然后是光空间矩阵; 然后将整个事物划分为角落的'w'.

vec4 corners[8] =
    {
        // Near plane
        { 1, 1, 1, 1 },
        { -1, 1, 1, 1 },
        { 1, -1, 1, 1 },
        { -1, -1, 1, 1 },
        // Far plane
        { 1, 1, -1, 1 },
        { -1, 1, -1, 1 },
        { 1, -1, -1, 1 },
        { -1, -1, -1, 1 }
    };

    // Create a projection matrix for this cascade.
    // This will transform the corner from camera space …
Run Code Online (Sandbox Code Playgroud)

c++ opengl matrix shadow

13
推荐指数
1
解决办法
485
查看次数

将std :: atomic与对齐的类一起使用

我有一个mat4类,一个使用sse内在函数的4x4矩阵.这个类是使用对齐的_MM_ALIGN16,因为它将矩阵存储为一组__m128.问题是,当我声明一个时atomic<mat4>,我的编译器对我大喊:

f:\program files (x86)\microsoft visual studio 12.0\vc\include\atomic(504): error C2719: '_Val': formal parameter with __declspec(align('16')) won't be aligned
Run Code Online (Sandbox Code Playgroud)

这是当我尝试传递任何与_MM_ALIGN16作为函数的参数对齐的类(不使用const &)时得到的相同错误.

如何声明mat4类的原子版?

c++ sse c++11

12
推荐指数
1
解决办法
1307
查看次数

16位浮点数和GL_HALF_FLOAT

我正在寻找/编写一个16位浮点数的C++实现,用于OpenGL顶点缓冲区(纹理坐标,法线等).这是我目前的要求:

  • 必须是16位(显然).
  • 必须能够使用GL_HALF_FLOAT上传到OpenGL顶点缓冲区.
  • 必须能够表示超过-1.0 - +1.0的数字(否则我只会使用GL_SHORT标准化).
  • 必须能够转换为普通的32位浮点数.
  • 算术运算并不重要 - 我只关心存储.
  • 速度不是主要问题,但正确性是.

这是我到目前为止的接口:

class half
{
public:
    half(void) : data(0) {}
    half(const half& h) : data(h.data) {}
    half(const unsigned short& s) : data(s) {}
    half(const float& f) : data(fromFloat(f)) {}
    half(const double& d) : data(fromDouble(d)) {}

    inline operator const float() { return toFloat(data); }
    inline operator const double() { return toDouble(data); }

    inline const half operator=(const float& rhs) { data = fromFloat(rhs); return *this; }
    inline const half operator=(const double& rhs) …
Run Code Online (Sandbox Code Playgroud)

c++ opengl floating-point

9
推荐指数
1
解决办法
6931
查看次数

多线程控制台I/O.

我在我的多线程应用程序中使用控制台.现在,它只接受输出(printf等),到目前为止我没有任何问题.但是,我希望能够支持控制台输入,这也是我生活变得复杂的地方.

为了预先警告,我对使用控制台输入和输出的更复杂的细微差别非常不熟悉.我在这个主题上的经验并没有比printf/cout,scanf/cin和使用SetConsoleTextAttribute()更改颜色(在窗口上)更进一步.

我宁愿让我的程序尽可能保持交叉兼容,但我不反对必须编写特定于平台的代码,只要我能为其他平台找到可行的替代方案.

从概念上讲,我希望控制台能够运行它自己的线程,这样它就可以在使用cin等待时锁定,而不会冻结整个程序或其他线程.任何线程都可以将控制台输出发送到此线程,该线程将以干净的方式输出(可能使用线程安全队列),并且控制台读取的任何输入都会将命令发送到相应的线程.

我的第一个问题是,当我输入一些输入时,任何输出都会显示在我正在键入的内容中.我想要处理的解决方案是保留控制台的底线以进行输入,并将输出转到第二个最后一行,将输入线向下推.我怎样才能做到这一点?

c++ console multithreading

8
推荐指数
1
解决办法
4922
查看次数

使用四元数进行切线空间法线贴图 - 我遇到的问题

受crytek关于使用四元数在四元数中为较小顶点存储切线空间的介绍的启发,我得出了一个合乎逻辑的结论:如果可以使用四元数来存储切线空间,那么您还可以在顶点之间触发四元数并使用它们直接旋转法线.这将消除重新正交化切线空间矢量或重建其中一个的需要,并且它将切出每个片段的矩阵 - 矢量乘法,用单个四元数向量乘法替换它.

我试图在我的OpenGL应用程序中使用我自制的四元数类实现它,我遇到了一些问题.我知道我的四元数可以用矩阵构造,将四元数乘以向量,得到与矩阵乘以向量相同的结果 - 我已经在cpu方面成功完成了.然而,一旦我开始在GLSL中使用它们,一切都会变得混乱.

值得注意的是,事实上我可以辨别出法线贴图的模式,所以我觉得我走在了正确的轨道上.不幸的是,似乎我的颜色变得混乱.

这是我在glsl中使用的四元数数学:

vec4 multQuat(vec4 q1, vec4 q2)
{
    return vec4(
        (q1.w * q2.y) + (q1.y * q2.w) + (q1.x * q2.z) - (q1.z * q2.x),
        (q1.w * q2.z) + (q1.z * q2.w) + (q1.y * q2.x) - (q1.x * q2.y),
        (q1.w * q2.w) - (q1.x * q2.x) - (q1.y * q2.y) - (q1.z * q2.z),
        (q1.w * q2.x) + (q1.x * q2.w) + (q1.z * q2.y) - (q1.y * q2.z)
        );
}

vec3 rotateVector(vec4 …
Run Code Online (Sandbox Code Playgroud)

c++ opengl glsl quaternions normals

8
推荐指数
1
解决办法
1821
查看次数

对数深度缓冲区OpenGL

我已经设法在OpenGL中实现了一个对数深度缓冲区,主要是来自Outerra的文章(你可以在这里,这里这里阅读).但是,我遇到了一些问题,我不确定这些问题是否是使用对数深度缓冲区所固有的,或者是否有一些我无法想到的解决方法.

刚开始,这就是我在顶点着色器中计算对数深度的方法:

gl_Position = MVP * vec4(inPosition, 1.0);
gl_Position.z = log2(max(ZNEAR, 1.0 + gl_Position.w)) * FCOEF - 1.0;
flogz = 1.0 + gl_Position.w;
Run Code Online (Sandbox Code Playgroud)

这就是我在片段着色器中修复深度值的方法:

gl_FragDepth = log2(flogz) * HALF_FCOEF;
Run Code Online (Sandbox Code Playgroud)

在哪里ZNEAR = 0.0001,ZFAR = 1000000.0FCOEF = 2.0 / log2(ZFAR + 1.0),和HALF_FCOEF = 0.5 * FCOEF. C在我的例子中,是1.0,以简化我的代码并减少计算.

对于初学者来说,我对我获得的精确程度非常满意.使用正常的深度缓冲(znear = 0.1,zfar = 1000.0),我会朝视距的边缘进行相当多的z-fighting.现在,随着我的进一步znear:zfar,我已经将第二个地平面放置在第一个以下0.01个单位,我无法找到任何z-fighting,无论我将相机放大多远(我得到一点z-战斗时只有0.0001(0.1毫米),但是meh).

不过,我确实有一些问题/疑虑.

1)我得到的平面剪裁比我的普通深度缓冲更多,看起来很难看.它发生在逻辑上它确实不应该的情况下.以下是我的意思的几个屏幕截图:

剪掉地面. 剪裁网格.

这两种情况都是我用普通深度缓冲区没有遇到的情况,我宁愿看不到(特别是前者).编辑:问题1通过使用正式解决glEnable(GL_DEPTH_CLAMP).

2)为了使其工作,我需要写入gl_FragDepth.我试过不这样做,但结果是不可接受的.写入gl_FragDepth意味着我的显卡无法进行早期z优化.这将不可避免地让我爬上墙,所以我想尽快解决它.

3)我需要能够检索存储在深度缓冲区中的值(我已经有了帧缓冲区和纹理),然后将其转换为线性视图空间坐标.我真的不知道从哪里开始这个,我之前做过它的方式涉及逆投影矩阵,但我不能在这里真正做到这一点.有什么建议?

c++ opengl 3d depth-buffer

7
推荐指数
1
解决办法
4756
查看次数

为什么我的直接四元数乘法比SSE快?

我已经经历了一些不同的四元数乘法实现,但是我很惊讶地发现参考实现到目前为止是我最快的.这是有问题的实施:

inline static quat multiply(const quat& lhs, const quat& rhs)
{
    return quat((lhs.w * rhs.x) + (lhs.x * rhs.w) + (lhs.y * rhs.z) - (lhs.z * rhs.y),
                (lhs.w * rhs.y) + (lhs.y * rhs.w) + (lhs.z * rhs.x) - (lhs.x * rhs.z),
                (lhs.w * rhs.z) + (lhs.z * rhs.w) + (lhs.x * rhs.y) - (lhs.y * rhs.x),
                (lhs.w * rhs.w) - (lhs.x * rhs.x) - (lhs.y * rhs.y) - (lhs.z * rhs.z));
}
Run Code Online (Sandbox Code Playgroud)

我尝试了一些其他的实现,一些使用SSE,一些不使用.以下是一个这样的SSE实现的示例,基本上是从Bullet Physics使用的库中复制的:

inline static __m128 multiplynew(__m128 lhs, …
Run Code Online (Sandbox Code Playgroud)

c++ optimization sse quaternions

6
推荐指数
1
解决办法
2760
查看次数

寻找对我的线程安全,无锁队列实现的批评

所以,经过一番研究后,我写了一个队列.它使用固定大小的缓冲区,因此它是一个循环队列.它必须是线程安全的,我试图让它无锁.我想知道它有什么问题,因为这些事情我自己很难预测.

这是标题:

template <class T>
class LockFreeQueue
{
public:
    LockFreeQueue(uint buffersize) : buffer(NULL), ifront1(0), ifront2(0), iback1(0), iback2(0), size(buffersize) { buffer = new atomic <T>[buffersize]; }
    ~LockFreeQueue(void) { if (buffer) delete[] buffer; }

    bool pop(T* output);
    bool push(T input);

private:
    uint incr(const uint val)
        {return (val + 1) % size;}

    atomic <T>* buffer;
    atomic <uint> ifront1, ifront2, iback1, iback2;
    uint size;
};
Run Code Online (Sandbox Code Playgroud)

这是实施:

template <class T>
bool LockFreeQueue<T>::pop(T* output)
{
    while (true)
    {
        /* Fetch ifront and store it in i. …
Run Code Online (Sandbox Code Playgroud)

c++ queue multithreading lock-free c++11

5
推荐指数
2
解决办法
863
查看次数

深度 + 模板帧缓冲区问题

我的 OpenGL 应用程序需要一个模板和深度缓冲区。深度缓冲区至少需要通过帧缓冲区对象渲染到纹理,这样我才能做延迟着色和其他后处理效果。我已经设置了这个帧缓冲区(使用 GL_DEPTH24_STENCIL8),但我有一些顾虑和问题。

首先,我想使用 32 位浮点深度缓冲区。GL_DEPTH32F_STENCIL8 选项似乎是最明显的。我想知道的是,这种格式的实际内存占用是多少?从逻辑上讲,它将是 40 位,但知道我对对齐做了什么,如果他们将其填充为 64,我不会感到惊讶,而且许多消息来源说这正是发生的情况。我想知道。

也许将深度和模板缓冲区分开对我来说会更好?我是否必须担心这不受支持?缓存效率如何,因为模板和深度测试经常一起执行?

附注。我没有使用多重采样。

c++ opengl stencil-buffer depth-buffer

3
推荐指数
1
解决办法
2006
查看次数

"汽车"成为错误的类型?

基本上,这是我的代码的样子:

vector<int> myVec; // defined elsewhere, and has stuff in it.
auto it = lower_bound(myVec.front(), myVec.back(), key);
myVec.insert(it, key); // <- compiler error!
Run Code Online (Sandbox Code Playgroud)

编译器错误error: no matching function for call to 'std::vector<int>::insert(int&, int&)',这是意外的,因为它应该是一个" something_something_iterator".

为什么这样做?

我在Windows 7上使用MinGW-W64进行编译.

c++ vector auto c++11

0
推荐指数
1
解决办法
200
查看次数

为什么我不能更改新创建的文件的"上次写入时间"?

首先,我使用Visual Studio 2015实现的文件系统库来自即将推出的基于Boost :: Filesystem的C++ 17标准.

基本上,我要做的是保存文件的时间戳(它是"最后写入时间"),将该文件的内容与所述时间戳一起复制到存档中,然后将该文件提取出来并使用保存的时间戳恢复正确"最后写作时间".

// Get the file's 'last write time' and convert it into a usable integer.
__int64 timestamp = chrono::time_point_cast<chrono::seconds>(fs::last_write_time(src)).time_since_epoch().count();

// ... (do a bunch of stuff in here)

//  Save the file
ofstream destfile(dest, ios::binary | ios::trunc);
destfile.write(ptr, size);

// Correct the file's 'last write time'
fs::last_write_time(dest, chrono::time_point<chrono::system_clock>(chrono::seconds(timestamp)));
Run Code Online (Sandbox Code Playgroud)

问题是新文件总是以一个时间戳等于它创建的时间(现在),因为它根本就没有调用last_write_time()过.

当我尝试将时间戳从一个现有文件复制到另一个文件时,它工作正常.当我从文件中复制时间戳时,然后使用fs::copy创建该文件的新副本,然后立即更改副本的时间戳,它也可以正常工作.以下代码正常工作:

// Get the file's 'last write time' and convert it into a usable integer.
__int64 timestamp = chrono::time_point_cast<chrono::seconds>(fs::last_write_time("test.txt")).time_since_epoch().count();
fs::copy("test.txt", "new.txt"); …
Run Code Online (Sandbox Code Playgroud)

c++ boost-filesystem c++-chrono c++17

0
推荐指数
1
解决办法
478
查看次数