【问题标题】:Translate two objects in the same 3D space in different ways?以不同的方式平移同一 3D 空间中的两个对象?
【发布时间】:2026-01-03 03:50:01
【问题描述】:

我正在尝试以不同的方式在我的 3D 世界中移动对象,但我无法在不影响整个场景的情况下移动一个对象。我尝试使用具有不同统一名称的第二个着色器,但得到了一些非常奇怪的结果,例如对象消失和其他烦人的东西。

我尝试链接和取消链接程序,但是当我将不同的矩阵应用于不同的着色器以希望看到它们以不同的方式移动时,所有内容似乎都可以一起转换。

TRANSLATE 矩阵只是一个旋转 * 缩放 * 平移矩阵。

编辑 - 这是我的制服的设置方法:

   //All of my mat4's
// Sorry for not initialising any of the vec3 or mat4's don't want the code to be too lengthy

perspectiveproj = glm::perspective(glm::radians(95.0f), static_cast<float>(width)/height , 0.01f,  150.0f);

views = glm::lookAt(position, position + viewdirection, UP);

trans1 = glm::rotate(trans1, 0.0f, glm::vec3(0.0f, 1.0f, 0.0f));
trans1 = glm::scale(trans1, glm::vec3(0.0f, 0.0f, 0.0f));
trans1 = glm::translate(trans1, glm::vec3(1.0f, 0.0f, 1.0f));



 //These are the uniforms for my perspective matrix per shader

int persp = glGetUniformLocation(shader_one, "perspective");
glUniformMatrix4fv(persp, 1, GL_FALSE, glm::value_ptr(perspectiveproj));
int persp2 = glGetUniformLocation(shader_two, "perspective");
glUniformMatrix4fv(persp2, 1, GL_FALSE, glm::value_ptr(perspectiveproj));  

//These are the uniforms for my lookAt matrix per shader

int Look = glGetUniformLocation(shader_one, "lookAt");
glUniformMatrix4fv(Look, 1, GL_FALSE, glm::value_ptr(views));
int Look2 = glGetUniformLocation(shader_two, "perspective");
glUniformMatrix4fv(Look2, 1, GL_FALSE, glm::value_ptr(views));    

 //This is the one uniform for my Translation to one shader object matrix 
moving Shader two       
//objects differently than shader one

int Moveoneshader = glGetUniformLocation(shader_two, "TRANSLATE");
glUniformMatrix4fv(Moveoneshader, 1, GL_FALSE, glm::value_ptr(trans1)) 

着色器一:

gl_Positions = perspective * lookAt * vec4(position.x, position.y, position.z, 1.0);

着色器二:

 gl_Positions = perspective * lookAt * TRANSLATE * vec4(position.x, position.y, position.z,      1.0);

链接和绘图:

glUseProgram(shader_one);
glBindVertexArray(vao_one);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

glDeleteProgram(shader_one);

glUseProgram(shader_two);
glBindVertexArray(vao_two);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);  

glDeleteProgram(shader_two);

【问题讨论】:

  • 通常,您只需为每个对象使用一个模型矩阵。另外:为什么在使用后删除着色器程序?
  • @derhass我就是这么想的。现在我知道不会了,谢谢。
  • @derhass 我整晚都在尝试这个,但我继续黑屏??!!有什么想法吗?
  • 问题不是由着色器程序引起的。该问题是由制服的初始化引起的。您必须显示设置统一变量 TRANSLATE 的代码。
  • "我已经尝试了一整晚" 好吧:什么你试过了吗?如果你不展示你的所作所为,就不可能发现任何错误。

标签: c++ opengl glsl glm-math


【解决方案1】:

您似乎无法理解使用shader 背后的机制。 shader 应该是一组可以在多个输入上运行的指令,例如对象。

让我们首先调用TRANSLATE 矩阵model 矩阵,因为它包含所有直接影响我们模型的转换。 model 矩阵对于不同的对象可以有不同的值。因此,您可以使用一个通用的shader,而不是使用不同的shaders,它会计算:

gl_Position = perspective * view * model * vec4(position, 1.0);

其中view 等于lookAt。我已经交换了您的矩阵名称以遵循命名约定。我建议您使用这些名称,以便在研究过程中找到更多信息。

创建model 矩阵时,还必须注意矩阵乘法的顺序。在大多数情况下,您希望您的 model 矩阵像这样组成

model = translate * rotate * scale

避免你的对象扭曲。

为了能够使用各自的model 矩阵渲染多个对象,您必须在绘制对象之前遍历所有对象并更新着色器中的矩阵值。一个简化的例子是:

std::string name = "model";
for (Object obj : objects)
{
    glUniformMatrix4fv(glGetUniformLocation(shaderID, name.c_str()), 1,
        GL_FALSE, glm::value_ptr(model));

    // draw object
}

您可以在此处https://learnopengl.com/Getting-started/Coordinate-Systems 阅读更多相关信息。


与您的问题有关,如果您使用多个着色器绘制对象,它们可能会消失。这与着色器如何将其数据写入屏幕有关。默认情况下,活动着色器会写入屏幕的所有像素。这意味着当使用第一个着色器绘制后切换着色器以使用第二个着色器进行绘制时,第一个着色器的结果将被覆盖。

要组合多个图像,您可以使用帧缓冲区。您可以先使用它们写入图像,而不是直接在屏幕上书写。之后,这些图像可以在第三个着色器中组合。

但是,这会消耗太多内存,并且计算效率太低,无法考虑您的方案。这些技术通常在渲染后处理效果时应用。

【讨论】:

    最近更新 更多