小编fen*_*fen的帖子

法线贴图,TBN矩阵计算

我只是想确保我正确理解TBN矩阵计算

在顶点着色器中我们通常使用:

vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * Tangent.xyz);
vec3 b = normalize(gl_NormalMatrix * Bitangent.xyz);
mat3 tbn = mat3(t, b, n);
Run Code Online (Sandbox Code Playgroud)

据我所知,这个tbn矩阵将矢量从Tangent空间转换为Eye space.实际上我们想要反向 - 将一个矢量从眼睛空间变换到切线空间.因此我们需要反转tbn矩阵:

tbn = transpose(tbn); // transpose should be OK here for doing matrix inversion
Run Code Online (Sandbox Code Playgroud)

注意: tbn - 应该只包含旋转,对于这种情况,我们可以使用转置来反转矩阵.

我们可以改变我们的向量:

vec3 lightT  = tbn * light_vector;
...          = tbn * ...
Run Code Online (Sandbox Code Playgroud)

在几个教程中,源代码我发现作者使用了这样的东西:

light.x = dot(light, t);
light.y = dot(light, b);
light.z = dot(light, n);
Run Code Online (Sandbox Code Playgroud)

上面的代码与乘以 …

opengl glsl

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

C ++静态初始化顺序:添加到映射中

我们无法确定静态对象的初始化顺序。

但这在以下示例中是否有问题?

  • 一个静态变量是地图(或其他容器)
  • 从其他静态变量我们填充该地图

代码:

class Factory
{
public:
    static bool Register(name, func);

private:
    static map<string, func> s_map;
};

// in cpp file
map<string, func> Factory::s_map;

bool Factory::Register(name, func)
{
    s_map[name] = func;
}
Run Code Online (Sandbox Code Playgroud)

并在另一个cpp文件中

static bool registered = Factory::Register("myType", MyTypeCreate);
Run Code Online (Sandbox Code Playgroud)

当我注册更多类型时,我并不依赖于容器中的顺序。但是,第一次添加到容器中呢?我可以确定它已初始化为“足够”以容纳第一个元素吗?

还是“静态初始化顺序惨败”的另一个问题?

c++

6
推荐指数
2
解决办法
1204
查看次数

有什么方法可以在std :: visit中跳过变量类型的一些重载组合?

std::visit支持多种输入变体.但是,代码应该处理来自这些变体的所有类型的组合.

有没有办法跳过不"有意义"的组合?

例如:

template<class... Ts> 
struct overloaded : Ts... { using Ts::operator()...; };

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main() {
    std::variant<int, float, char> v1 { 's' };
    std::variant<int, float, char> v2 { 10 };

    std::visit(overloaded{
        [](int a, int b) { },
        [](int a, float b) { },
        [](int a, char b) { },
        [](float a, int b) { },
        [](float a, float b) { },
        [](float a, char b) { },
        [](char a, int b) { },
        [](char …
Run Code Online (Sandbox Code Playgroud)

c++ c++17

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

将std :: unique_ptr传递给辅助函数

这是一种正确的方法吗?

void helperFunc(MyClass *ptr)
{
    // do something with ptr,
}

unique_ptr<MyClass> p(new MyClass());
helperFunc(p.get());
Run Code Online (Sandbox Code Playgroud)

或者我应该使用shared_ptr进行此类操作?

c++ stl smart-pointers unique-ptr c++11

4
推荐指数
2
解决办法
2012
查看次数

如何在WebGL上向顶点着色器发送多个参数?

我正在学习OpenGL教程(因为WebGL教程很少见),它使用以下语法来表示多个参数:

#version 330

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;

smooth out vec4 theColor;

void main()
{
    gl_Position = position;
    theColor = color;
}
Run Code Online (Sandbox Code Playgroud)

layout (location = #)语法不适用于WebGL.这有什么替代品?

javascript opengl-es webgl opengl-es-2.0

4
推荐指数
1
解决办法
2501
查看次数

make_shared"证据"与默认构造

make_shared为对象和引用计数器分配单个块.因此使用这种技术有明显的性能优势.

我在VS2012进行了简单的实验,我正在寻找"证据":

std::shared_ptr<Test> sp2 = std::make_shared<Test>();
std::shared_ptr<Test> sp(new Test());
// Test is a simple class with int 'm_value' member
Run Code Online (Sandbox Code Playgroud)

调试时我在本地查看这样的东西(删除了一些行)

-   sp2 shared_ptr {m_value=0 }  [make_shared] std::shared_ptr<Test>
+   _Ptr    0x01208dec {m_value=0 } Test *
+   _Rep    0x01208de0 make_shared  std::_Ref_count_base *

-   sp  shared_ptr {m_value=0 } [default] std::shared_ptr<Test>
+   _Ptr    0x01203c50 {m_value=0 } Test *
+   _Rep    0x01208d90 default  std::_Ref_count_base *
Run Code Online (Sandbox Code Playgroud)

似乎sp20x01208de0(有一个ref计数器)中分配,然后在0x01208dec中有一个Test对象.地点彼此非常接近.

在第二个版本中,我们有0x01208d90为参考计数器,0x01203c50的对象.那些地方相当遥远.

这是正确的输出吗?我能正确理解吗?

c++ memory-management smart-pointers

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

是否可以使用 C++20 中的starts_with/ends_with 来比较不区分大小写?

使用 C++20 和P0457,string我们获得了和的成员函数string_view,用于检查前缀和后缀:

starts_with(),ends_with()

有没有办法不区分大小写地比较字符串?

例如此检查返回false

const std::string url { "https://isocpp.org" };
    
if (url.starts_with("HTTPS"))
    std::cout << "you're using the correct site!\n";
Run Code Online (Sandbox Code Playgroud)

例如,在 boost 中我们就istarts_with进行了这样的比较。

一种方法是“规范化”要检查的字符串和前缀/后缀(例如全部小写),但这需要对象的额外副本。

c++ string c++20

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