我只是想确保我正确理解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)
上面的代码与乘以 …
我们无法确定静态对象的初始化顺序。
但这在以下示例中是否有问题?
代码:
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)
当我注册更多类型时,我并不依赖于容器中的顺序。但是,第一次添加到容器中呢?我可以确定它已初始化为“足够”以容纳第一个元素吗?
还是“静态初始化顺序惨败”的另一个问题?
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) 这是一种正确的方法吗?
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进行此类操作?
我正在学习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.这有什么替代品?
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)
似乎sp2在0x01208de0(有一个ref计数器)中分配,然后在0x01208dec中有一个Test对象.地点彼此非常接近.
在第二个版本中,我们有0x01208d90为参考计数器,0x01203c50的对象.那些地方相当遥远.
这是正确的输出吗?我能正确理解吗?
使用 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进行了这样的比较。
一种方法是“规范化”要检查的字符串和前缀/后缀(例如全部小写),但这需要对象的额外副本。