0

经过相当长的 Google 会话后,我已经受够了!

我有一个带有一些简单 Quad 的 python/opengl 应用程序,我使用 gluLookAt 在场景中移动。然后我在其中一个 Quad 上只需要 1 个纹理,所以我现在显然为这个单个 Quad 使用了着色器程序。

现在,当我使用 gluLookAt 时,带有纹理的四边形不会移动,我也可以理解。

现在有什么方法可以让 gluLookAt 函数与着色器程序一起工作,获取当前矩阵堆栈,这样我就可以用它来提供着色器程序,或者我必须像他一样重写洞应用程序并重新发明 glulookup 函数(在着色器或 CPU 中)?

EDIT1: 我使用:

EDIT2(我的解决方案):

自从我打开这个帖子以来,有些事情发生了变化,但在您的指导下,我设法获得了一个现代且稳定的解决方案。

我必须绘制 3 个主要组件。一个静态场,一些线(为了更好的可视化)和一些可移动的四边形。

该字段现在一次写入数组中的 VBO。(与单个绘图命令相比有重大改进)

可移动的方块和线条的工作原理相同,但它们是动态的,必须随每一帧重新上传。

Foreach 类型的对象我有一个顶点 + 片段着色器程序。我知道我可以只使用一个大的,但这不是应该的。

每个矩阵(模型、视图、投影)都分配给一个制服,然后在顶点着色器中与来自 VBO 的顶点相乘。

场顶点着色器(示例):

#version 330

uniform mat4 uniform_Model;
uniform mat4 uniform_View;
uniform mat4 uniform_Projection;

in vec3 Quad_Color_Attrib;
in vec3 Quad_Size_Attrib;

out vec3 frag_ColorId;

void main()
{
    // Pass the tex coord straight through to the fragment shader
    frag_ColorId = Quad_Color_Attrib;

    // Remember : inverted !
    gl_Position = uniform_Projection * uniform_View * uniform_Model * vec4(Quad_Size_Attrib,1);
}

我要求的不是正确的方法。(结合新旧 OpenGL)不幸的是,我不能按原样分享孔代码,但我在这里你可以找到所有 opengl 关键代码:

顶点/片段着色器程序加载器:

链接到要点

初始化顶点/片段着色器(在本例中为字段)

def init_field(self, p_VertexShaderPath, p_FragmentShaderPath, p_FieldList, p_FieldCount):
    # ############### Field Shader ###############

    # Shader Program
    self.m_FieldShader = LoadShaders(p_VertexShaderPath, p_FragmentShaderPath)
    glUseProgram(self.m_FieldShader)

    # VAO
    self.m_FieldVAO = glGenVertexArrays(1)
    glBindVertexArray(self.m_FieldVAO)

    # Field Definition        
    self.m_FieldCount = p_FieldCount
    t_Vertices = []

    for t_FieldNr in p_FieldList:
        x = p_FieldList[t_FieldNr].m_XPos
        y = p_FieldList[t_FieldNr].m_YPos
        cr = p_FieldList[t_FieldNr].m_Color[0]/255
        cg = p_FieldList[t_FieldNr].m_Color[1]/255
        cb = p_FieldList[t_FieldNr].m_Color[2]/255

        t_Vertices.extend([
             x - 0.5,  y + 0.5, 0.0,  cr, cg, cb,   #  0----1
             x + 0.5,  y + 0.5, 0.0,  cr, cg, cb,   #  |    |
             x + 0.5,  y - 0.5, 0.0,  cr, cg, cb,   #  |    |
             x - 0.5,  y - 0.5, 0.0,  0, 0, 0    #  3----2
        ])

    t_FieldVerticesBuffer = numpy.array(t_Vertices, dtype = numpy.float32)

    # VBO
    self.m_FieldVBO = glGenBuffers(1)
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)
    glBufferData(GL_ARRAY_BUFFER, t_FieldVerticesBuffer.nbytes, t_FieldVerticesBuffer, GL_STATIC_DRAW)

    # VBO Size Attrib
    self.m_FieldVerticesAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Size_Attrib")
    glEnableVertexAttribArray(self.m_FieldVerticesAttrib)
    glVertexAttribPointer(self.m_FieldVerticesAttrib,
                          3, 
                          GL_FLOAT, 
                          GL_FALSE, 
                          ctypes.sizeof(6*GLfloat), 
                          ctypes.c_void_p(0))

    # VBO Color Attrib                      
    self.m_FieldColorAttrib = glGetAttribLocation(self.m_FieldShader, "Quad_Color_Attrib")
    glEnableVertexAttribArray(self.m_FieldColorAttrib)
    glVertexAttribPointer(self.m_FieldColorAttrib,
                          3, 
                          GL_FLOAT, 
                          GL_FALSE, 
                          ctypes.sizeof(6*GLfloat), 
                          ctypes.c_void_p(12))

    # Uniform Locations
    self.m_Field_ModelMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Model')
    self.m_Field_ViewMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_View')
    self.m_Field_ProjectionMat_Uniform = glGetUniformLocation(self.m_FieldShader, 'uniform_Projection')

    # Detach Shader & VAO
    glBindVertexArray(0)  # unbind the VAO
    glUseProgram(0)  # Disable shader

屏幕绘制周期

这现在只是 psydo 代码:

OpenGLEnv.Clear()
OpenGLEnv.SetCamera()
OpenGLEnv.DrawField()
OpenGLEnv.FlipBuffer()

所以 SetCamera 设置了 ViewMat 和 ProjectionMat。

def SetCamera(self, camera, zoom_distance):
    self.m_ViewMat = lookAt(glm.vec3(-camera[0], -camera[1], zoom_distance),  # Camera is at (x,x,x), in World Space
                            glm.vec3(-camera[0], -camera[1], -100),  # and looks at the origin
                            glm.vec3(0, 1, 0)) #  Head is up (set to 0,-1,0 to look upside-down)
    self.m_ProjectionMat = perspective(45, self.m_AspectRatio, 1, 1000.0)

绘制场例程

使用此函数,我将从 VBO 中绘制顶点。

def DrawField(self):
    glUseProgram(self.m_FieldShader)       # Use shader

    self.m_ModelMat = glm.mat4(1)  # Reset ModelMat
    # ############################
    # 1. Scale          self.ModelMat = scale(self.ModelMat,glm.vec3(10,10,10))
    # 2. Rotation       self.ModelMat = rotate(self.ModelMat, self.test, glm.vec3(0,1,0))
    # 3. Translate      self.ModelMat = translate(self.ModelMat,glm.vec3(0,0,0))
    ####################################

    glUniformMatrix4fv(self.m_Field_ModelMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ModelMat.value)))
    glUniformMatrix4fv(self.m_Field_ViewMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ViewMat.value)))
    glUniformMatrix4fv(self.m_Field_ProjectionMat_Uniform, 1, GL_FALSE, numpy.squeeze(numpy.asarray(self.m_ProjectionMat.value)))

    glBindVertexArray(self.m_FieldVAO)
    glBindBuffer(GL_ARRAY_BUFFER, self.m_FieldVBO)

    # Draw Field
    glDrawArrays(GL_QUADS, 0, 4*self.m_FieldCount)

    # Disable shader and unbind VAO
    glBindVertexArray(0)
    glUseProgram(0)

使用的图书馆:

4

1 回答 1

1

您可以决定:

  1. 您可以使用 OpenGL 2,这使事情变得更容易,并且意味着没有着色器编程但效率较低。

  2. 如果您必须绘制至少 1000 个三角形或想要添加凹凸贴图或其他特殊效果,您可能应该考虑使用着色器。这意味着:

  3. 如果你的目标是高效率,不要使用Python 和 Pyopengl(自己的经验)

    • 我建议你使用 Java 和 jogl(我目前的配置)。然后我可以为你提供我的相机课程。
  4. 我可能还会将我的相机类移植到 Python,但这取决于 jogl Matrix4 类等等,但如果 pyopengl 也提供这个数学辅助类(Matrix4,Quaternion,...)

编辑 :

顶点着色器:

#version 330

uniform mat4 uniform_Transformation;
uniform mat4 uniform_Modelview;
uniform mat4 uniform_Projection;

in vec4 attribute_Position;
in vec4 texcoords;

out vec4 texcoords_pass;

void main(void) 
{ 
  texcoords_pass=texcoords;
  vec4 transformedPoint=attribute_Position*uniform_Transformation;
  vec4 toCamera=transformedPoint*uniform_Modelview;
  gl_Position = vec4(toCamera*uniform_Projection);
}

片段着色器:

#version 330

uniform sampler2D tex;

in vec2 texcoords_pass;

out vec4 mgl_FragColor;

void main (void)
{ 
  vec4 texture_color =  texture(tex,texcoords_pass);
  if (texture_color.w == 0) {
      discard;
  }
  mgl_FragColor=vec4(texture_color.x,texture_color.y,texture_color.z,1.0f);
}

关于矩阵:

  • uniform_Transformation是变换矩阵。它用于旋转、缩放、翻转、镜像和移动模型,在您的情况下是四边形。

  • uniform_Modelview是视图矩阵。基本上就是相机。它定义了相机的旋转方式和位置。

  • uniform_Projection是投影矩阵。这是关于透视投影的。在此处阅读更多信息:http: //www.songho.ca/opengl/gl_projectionmatrix.html

希望能帮助到你 !

于 2017-10-12T20:05:28.743 回答