2017-10-12 131 views
0

經過一段相當長的Google Session後,我有足夠的空間!是否可以將gluLookAt與Vertex Shader結合使用?

我有一個python/opengl應用程序,用一些簡單的Quad,我用gluLookAt在場景中移動。然後我只需要一個Quad的紋理,所以我現在明顯使用這個Quad的着色器程序。

現在,當我使用gluLookAt時,帶有紋理的Quad不會移動,我也能理解。

現在有什麼辦法可以讓gluLookAt函數與着色器程序一起工作,獲得當前矩陣堆棧,以便我可以爲它提供着色器程序,或者必須重寫孔應用程序並重新創建glulookup函數like he did(在着色器中還是在CPU上)?

EDIT1: 我使用:

EDIT2(我的解決方案):

自從我開了這個線程,一些事情發生了變化,但與你的guideance我得到了一個現代&穩定的解決方案。

有3個主要部件,我必須畫。一個靜態字段,一些行(爲了更好的可視化)和一些可移動的四邊形。

該字段現在被寫入一個數組中的VBO。 (與單個繪圖命令相比有重大改進)

可移動的正方形和線條以相同的原理工作,但是它們是動態的並且必須隨每個框架重新上傳。

Foreach類型的對象我有一個頂點+片段着色器程序。我知道我可以使用一個大的,但這不是它應該的。

將每個矩陣(模型,視圖,投影)分配給一個統一體,然後與頂點着色器中的VBO的頂點相乘。

場的Vertex Shader(例):

#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鍵碼:

頂點/片斷着色器程序裝載機:

Link to a gist

初始化頂點/片段着色器(在這種情況下爲場)

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

我建議使用數學庫而不是試圖擺弄矩陣堆棧。 [glm](https://glm.g-truc.net/0.9.8/index.html)可能是一個不錯的選擇,同時也提供了一個lookat功能。對於您的其餘問題:這取決於您使用的是哪個版本和配置文件。 – BDL

+0

對不起沒有提及它,我使用Python工作^^ 好吧,你會去手動計算矩陣...感謝您的建議。 – noscript

+1

還有glm的python版本。請參閱以下鏈接 https://github.com/mackst/glm。它不像glm那樣功能齊全,但有你需要的功能。 –

回答

1

你可以去cider:

  1. 你可能會使用OpenGL 2,它使得事情變得更容易,並且意味着沒有着色器編程,但效率更低。

  2. 如果您必須繪製至少1000個三角形或想要添加bumpmapping或其他特殊效果,則應該考慮着色器。 這意味着:

  3. 不要使用 Python的& Pyopengl,如果你的目標是在高效率(親身經歷)

    • 編號建議你Java和JOGL(目前我的配置)。然後我可以爲你提供我的相機課程。
  4. 我會也許還口我的相機類Python,但它取決於JOGL Matrix4類等,但很容易,如果pyopengl也提供了同樣的數學輔助類(Matrix4,四元數,...)

編輯:

頂點着色器:

#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

希望它有幫助!

+1

「OpenGL 2 ...表示無着色器」OpenGL 2.0和2.1都有着色器。 – genpfault

+0

我必須使用此解決方案繪製大約800至1000個四邊形。事實上,它是2D環境,但我必須能夠移動,縮放等等。 它背後有一個更大的腳本,這部分只是圖形界面部分,所以改變是痛苦的^^如果我從一開始就知道這將是C++。我想你們都知道這個改變目標的東西... 它看起來並不大有希望後,pyopengl會提供這個,但也許一些其他的lib。 現在我必須決定我將採取哪種方式。 – noscript

+0

@genpfault是的,我知道,但對於GL 2,你有默認着色器,你不能自己做。 – user7185318

相關問題