如何在 C 中正确初始化模型矩阵?
Posted
技术标签:
【中文标题】如何在 C 中正确初始化模型矩阵?【英文标题】:How to properly initialize a model matrix in C? 【发布时间】:2018-04-04 14:42:34 【问题描述】:我尝试转换我通过here 提出的问题的代码。
但是当我尝试运行它时,我遇到了一个异常,它指向 this(CGLM,用于 C 中的 OpenGL 数学因为 GLM 是仅限 C++ 的库)库。
C++ 代码运行良好,运行完美,但为什么在 C 中崩溃。
这是使用'CGLM'的代码的C sn-p(这是崩溃的代码):-
glUseProgram(shaderProgram);
mat4 model =
1.0f, 0.0f, 0.0f, 0.0f ,
0.0f, 1.0f, 0.0f, 0.0f ,
0.0f, 0.0f, 1.0f, 0.0f ,
0.0f, 0.0f, 0.0f, 1.0f ,
;
mat4 projection;
glm_ortho(0.0f, (GLfloat)(WIDTH), (GLfloat)(HEIGHT), 0.0f, -1.0f, 1.0f, projection);
vect2 scale = 2.0f, 2.0f ;
vect2 position = 50.0f, 0.0f ;
vec4 color = 1.0f, 1.0f, 1.0f, 0.5f ;
GLfloat rotation = 0.0f;
glm_translate(model, (vec3) position[0], position[1], 0.0f );
glm_translate(model, (vec3) 0.5f * scale[0], 0.5f * scale[1], 0.0f );
glm_rotate(model, rotation, (vec3) 0.0f, 0.0f, 1.0f ); // Why is this function crashing?
glm_translate(model, (vec3) -0.5f * scale[0], -0.5f * scale[1], 0.0f );
glm_scale(model, (vec3) scale[0] * width, scale[1] * height, 1.0f );
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, (GLfloat *)projection);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, (GLfloat *)model);
glUniform4f(glGetUniformLocation(shaderProgram, "spriteColor"), color[0], color[1], color[2], color[3]);
这里是使用GLM的代码的C++ sn-p:-
glUseProgram(shaderProgram);
glm::mat4 model(1.0f);
glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(WIDTH), static_cast<GLfloat>(HEIGHT), 0.0f, -1.0f, 1.0f);
glm::vec2 scale = glm::vec2(2.0f, 2.0f);
glm::vec2 position = glm::vec2(50.0f, 0.0f);
glm::vec4 color = glm::vec4(1.0f, 1.0f, 1.0f, 0.5f);
GLfloat rotation = 0.0f;
model = glm::translate(model, glm::vec3(position, 0.0f));
model = glm::translate(model, glm::vec3(0.5f * scale.x, 0.5f * scale.y, 0.0f));
model = glm::rotate(model, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
model = glm::translate(model, glm::vec3(-0.5f * scale.x, -0.5f * scale.y, 0.0f));
model = glm::scale(model, glm::vec3(scale * glm::vec2(width, height), 1.0f));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform4f(glGetUniformLocation(shaderProgram, "spriteColor"), color.x, color.y, color.z, color.w);
【问题讨论】:
那么,你得到了什么异常,在你的代码中的哪一点? '在 spritetest.exe 中的 0x010F59C7 处引发异常:0xC0000005:访问冲突读取位置 0xFFFFFFFF' 在我运行后立即由编译器说,指向此处:- github.com/recp/cglm/blob/master/include/cglm/vec4.h#L169 由编译器?当然不是。但实际上,使用调试器并锁定堆栈跟踪 @derhass 我刚刚将链接添加到导致异常的行。 为什么glUniform...
调用会以 cglm 向量加法结束?这没有意义。
【参考方案1】:
见CGLM documentation
根据getting started
需要对齐:vec4 和 mat4 需要 16 字节对齐,因为 vec4 和 mat4 操作由 SIMD 指令向量化 (SSE/AVX)。
所以你需要像这样初始化单位矩阵:
mat4 model;
glm_mat4_identity(model);
....
mat4 projection;
glm_mat4_identity(projection);
glm_ortho(0.0f, (GLfloat)(WIDTH), (GLfloat)(HEIGHT), 0.0f, -1.0f, 1.0f, projection);
【讨论】:
但是为什么还是崩溃呢? 哪个源代码行? 这个就在这里model = glm::translate(model, glm::vec3(-0.5f * scale.x, -0.5f * scale.y, 0.0f));
'C' 没有任何异常。异常是一个 C++ 特性。它崩溃了 - glm 代码,使用程序集编写以加速性能会导致未定义的行为,因为数据未正确初始化(对齐)。 C
不是 C++ 更接近于汇编,所以尽量避免使用 (vec3) .... 之类的技巧,这不是使用 std::initialized_list 的构造函数调用,这与 C++
中的不同。跨度>
它并没有真正计量,汇编代码需要对齐的内存。 (vec3) 0.0f, 0.0f, 1.0f
这是一个堆栈对象数组,编译器跨越了元素。汇编函数期望数组上的内存地址具有精确对齐。简单地不要传递形参数组,使用变量。以上是关于如何在 C 中正确初始化模型矩阵?的主要内容,如果未能解决你的问题,请参考以下文章