OpenGL如何在以.jpg为背景的情况下显示.obj模型?

syqv5f0l  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(171)

我希望使用wood.jpg作为OpenGL程序的背景。我希望此程序也显示模型basketball.obj,如图所示:

我读过几个教程(Youtube频道sentdex、atibyte、The Cherno),也试过网站learnopengl.com、opengl-tutorial.org和codeloop.com,还用过Udemy,但没有一个具体说明如何使用.jpg作为.obj模型的背景。
我可以为主代码中定义的多个模型运行代码。我也可以为多个.obj文件运行代码。但我无法运行可以同时运行这两个文件的代码。
有人能帮我吗?我可以用OpenGL C++和pyOpenGL for Python编写代码。
到目前为止,我在显示图像wood.jpg作为背景方面取得的唯一成功是:


# Code modified from https://codeloop.org/python-modern-opengl-texturing-rectangle/

import glfw
from OpenGL.GL import *
import OpenGL.GL.shaders
import numpy as np
from PIL import Image

def main():
    if not glfw.init():
        return

    window = glfw.create_window(720, 600, "Pyopengl Texturing Rectangle", None, None)

    if not window:
        glfw.terminate()
        return

    glfw.make_context_current(window)

    # positions        colors               texture coords
    rectangle = [-1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
                 1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
                 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
                 -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0]

    # convert to 32bit float

    rectangle = np.array(rectangle, dtype=np.float32)

    indicesRectange = [0, 1, 2,
               2, 3, 0]

    indicesRectange = np.array(indicesRectange, dtype=np.uint32)

    VERTEX_SHADER = """

           #version 330

           in vec3 position;
           in vec3 color;
           in vec2 InTexCoords;

           out vec3 newColor;
           out vec2 OutTexCoords;

           void main() {

            gl_Position = vec4(position, 1.0);
            newColor = color;
            OutTexCoords = InTexCoords;

             }

       """

    FRAGMENT_SHADER = """
        #version 330

         in vec3 newColor;
         in vec2 OutTexCoords;

         out vec4 outColor;
         uniform sampler2D samplerTex;

        void main() {

           outColor = texture(samplerTex, OutTexCoords);

        }

    """

    # Compile The Program and shaders

    shader = OpenGL.GL.shaders.compileProgram(OpenGL.GL.shaders.compileShader(VERTEX_SHADER, GL_VERTEX_SHADER),
                                              OpenGL.GL.shaders.compileShader(FRAGMENT_SHADER, GL_FRAGMENT_SHADER))

    # Create Buffer object in gpu
    VBO = glGenBuffers(1)
    # Bind the buffer
    glBindBuffer(GL_ARRAY_BUFFER, VBO)
    glBufferData(GL_ARRAY_BUFFER, 128, rectangle, GL_STATIC_DRAW)

    # Create EBO
    EBO = glGenBuffers(1)
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesRectange, GL_STATIC_DRAW)

    # get the position from  shader
    #position = glGetAttribLocation(shader, 'position')
    position = 0
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(0))
    glEnableVertexAttribArray(position)

    # get the color from  shader
    #color = glGetAttribLocation(shader, 'color')
    color = 1
    glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(12))
    glEnableVertexAttribArray(color)

    #texCoords = glGetAttribLocation(shader, "InTexCoords")
    texCoords = 2
    glVertexAttribPointer(texCoords, 2, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(24))
    glEnableVertexAttribArray(texCoords)

    glBindAttribLocation(shader, position, 'position' )
    glBindAttribLocation(shader, color, 'color' )
    glBindAttribLocation(shader, texCoords, 'InTexCoords' )

    # Creating Texture
    texture = glGenTextures(1)
    glBindTexture(GL_TEXTURE_2D, texture)
    # texture wrapping params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    # texture filtering params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

    image = Image.open("wood.jpg")
    img_data = np.array(list(image.getdata()), np.uint8)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)

    glUseProgram(shader)

    glClearColor(1.0, 0.0, 0.0, 1.0)

    while not glfw.window_should_close(window):
        glfw.poll_events()

        glClear(GL_COLOR_BUFFER_BIT)

        # Draw Rectangle

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)

        glfw.swap_buffers(window)

    glfw.terminate()

if __name__ == "__main__":
    main()

[UPDATE]这是我尝试的最后一段代码。它结合了纹理教程中的代码和对象加载器教程中的代码:


# Object loading code by AtiBYte - OpenGL in python e15 - loading 3D .obj files. Youtube

# Background Texture loading code modified from CodeLoop.org https://codeloop.org/python-modern-opengl-texturing-rectangle/

import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import pyrr
from TextureLoader import load_texture
from ObjLoader import ObjLoader

# imports for background texture

import numpy as np
from PIL import Image

############## Background Texture ######################

# positions        colors               texture coords

rectangle = [-1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0,
             1.0, -1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0,
             1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
             -1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0]

# convert to 32bit float

rectangle = np.array(rectangle, dtype=np.float32)

indicesBackground = [0, 1, 2,
                     2, 3, 0]

indicesBackground = np.array(indicesBackground, dtype=np.uint32)

VERTEX_SHADER = """

       #version 330

       in vec3 position;
       in vec3 color;
       in vec2 InTexCoords;

       out vec3 newColor;
       out vec2 OutTexCoords;

       void main() {

        gl_Position = vec4(position, 1.0);
        newColor = color;
        OutTexCoords = InTexCoords;

         }

   """

FRAGMENT_SHADER = """
    #version 330

     in vec3 newColor;
     in vec2 OutTexCoords;

     out vec4 outColor;
     uniform sampler2D samplerTex;

    void main() {

       outColor = texture(samplerTex, OutTexCoords);

    }

"""

######################################################## 

vertex_src = """

# version 330

layout(location = 0) in vec3 a_position;
layout(location = 1) in vec2 a_texture;
layout(location = 2) in vec3 a_normal;

uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;

out vec2 v_texture;

void main()
{
    gl_Position = projection * view * model * vec4(a_position, 1.0);
    v_texture = a_texture;
}
"""

fragment_src = """

# version 330

in vec2 v_texture;

out vec4 out_color;

uniform sampler2D s_texture;

void main()
{
    out_color = texture(s_texture, v_texture);
}
"""

# glfw callback functions

def window_resize(window, width, height):
    glViewport(0, 0, width, height)
    projection = pyrr.matrix44.create_perspective_projection_matrix(45, width / height, 0.1, 100)
    glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)

# initializing glfw library

if not glfw.init():
    raise Exception("glfw can not be initialized!")

# creating the window

window = glfw.create_window(1280, 720, "My OpenGL window", None, None)

# check if window was created

if not window:
    glfw.terminate()
    raise Exception("glfw window can not be created!")

# set window's position

glfw.set_window_pos(window, 400, 200)

# set the callback function for window resize

glfw.set_window_size_callback(window, window_resize)

# make the context current

glfw.make_context_current(window)

# load here the 3d meshes

chibi_indices, chibi_buffer = ObjLoader.load_model("meshes/chibi.obj")
monkey_indices, monkey_buffer = ObjLoader.load_model("meshes/monkey.obj")

shaderObj = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))

# VAO and VBO

VAO = glGenVertexArrays(2)
VBO = glGenBuffers(3) #edited from 2 to 3 for background texture

# EBO = glGenBuffers(1)

# Chibi VAO

glBindVertexArray(VAO[0])

# Chibi Vertex Buffer Object

glBindBuffer(GL_ARRAY_BUFFER, VBO[0])
glBufferData(GL_ARRAY_BUFFER, chibi_buffer.nbytes, chibi_buffer, GL_STATIC_DRAW)

# glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)

# glBufferData(GL_ELEMENT_ARRAY_BUFFER, chibi_indices.nbytes, chibi_indices, GL_STATIC_DRAW)

# chibi vertices

glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, chibi_buffer.itemsize * 8, ctypes.c_void_p(0))

# chibi textures

glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, chibi_buffer.itemsize * 8, ctypes.c_void_p(12))

# chibi normals

glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, chibi_buffer.itemsize * 8, ctypes.c_void_p(20))
glEnableVertexAttribArray(2)

# Monkey VAO

glBindVertexArray(VAO[1])

# Monkey Vertex Buffer Object

glBindBuffer(GL_ARRAY_BUFFER, VBO[1])
glBufferData(GL_ARRAY_BUFFER, monkey_buffer.nbytes, monkey_buffer, GL_STATIC_DRAW)

# monkey vertices

glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, monkey_buffer.itemsize * 8, ctypes.c_void_p(0))

# monkey textures

glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, monkey_buffer.itemsize * 8, ctypes.c_void_p(12))

# monkey normals

glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, monkey_buffer.itemsize * 8, ctypes.c_void_p(20))
glEnableVertexAttribArray(2)

############### Background Texture #################################

# Bind the buffer

glBindBuffer(GL_ARRAY_BUFFER, VBO[2])
glBufferData(GL_ARRAY_BUFFER, 128, rectangle, GL_STATIC_DRAW)

# Create EBO

EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBackground, GL_STATIC_DRAW)

# get the position from  shader

position = glGetAttribLocation(shaderObj, 'position')
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(0))
glEnableVertexAttribArray(position)

# get the color from  shader

# color = glGetAttribLocation(shader, 'color')

color = 1
glVertexAttribPointer(color, 3, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(12))
glEnableVertexAttribArray(color)

# texCoords = glGetAttribLocation(shader, "InTexCoords")

texCoords = 2
glVertexAttribPointer(texCoords, 2, GL_FLOAT, GL_FALSE, 32, ctypes.c_void_p(24))
glEnableVertexAttribArray(texCoords)

glBindAttribLocation(shaderObj, position, 'position')
glBindAttribLocation(shaderObj, color, 'color')
glBindAttribLocation(shaderObj, texCoords, 'InTexCoords')

# Creating Texture

texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)

# texture wrapping params

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)

# texture filtering params

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

image = Image.open("wood.jpg")
img_data = np.array(list(image.getdata()), np.uint8)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data)

##################################################################### 

textures = glGenTextures(2)
load_texture("meshes/chibi.png", textures[0])
load_texture("meshes/monkey.jpg", textures[1])

glUseProgram(shaderObj)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

projection = pyrr.matrix44.create_perspective_projection_matrix(45, 1280 / 720, 0.1, 100)
chibi_pos = pyrr.matrix44.create_from_translation(pyrr.Vector3([0, -5, -10]))
monkey_pos = pyrr.matrix44.create_from_translation(pyrr.Vector3([-4, 0, 0]))

# eye, target, up

view = pyrr.matrix44.create_look_at(pyrr.Vector3([0, 0, 8]), pyrr.Vector3([0, 0, 0]), pyrr.Vector3([0, 1, 0]))

model_loc = glGetUniformLocation(shaderObj, "model")
proj_loc = glGetUniformLocation(shaderObj, "projection")
view_loc = glGetUniformLocation(shaderObj, "view")

glUniformMatrix4fv(proj_loc, 1, GL_FALSE, projection)
glUniformMatrix4fv(view_loc, 1, GL_FALSE, view)

# the main application loop

while not glfw.window_should_close(window):
    glfw.poll_events()

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    rot_y = pyrr.Matrix44.from_y_rotation(0.8 * glfw.get_time())
    model = pyrr.matrix44.multiply(rot_y, chibi_pos)

    # draw the chibi character
    glBindVertexArray(VAO[0])
    glBindTexture(GL_TEXTURE_2D, textures[0])
    glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
    glDrawArrays(GL_TRIANGLES, 0, len(chibi_indices))

    rot_y = pyrr.Matrix44.from_y_rotation(-0.8 * glfw.get_time())
    model = pyrr.matrix44.multiply(rot_y, monkey_pos)

    # draw the monkey head
    glBindVertexArray(VAO[1])
    glBindTexture(GL_TEXTURE_2D, textures[1])
    glUniformMatrix4fv(model_loc, 1, GL_FALSE, model)
    glDrawArrays(GL_TRIANGLES, 0, len(monkey_indices))

    # Draw Background Texture
    glDrawElements(GL_TRIANGLES, len(chibi_indices), GL_UNSIGNED_INT, None)

    glfw.swap_buffers(window)

# terminate glfw, free up allocated resources

glfw.terminate()
bnl4lu3b

bnl4lu3b1#

您有2个着色器程序,因此必须编译这两个着色器程序,并且必须在通过glUseProgram绘制几何体之前安装着色器程序:
第一个
确保背景纹理始终位于所有其他几何体的后面。
可以通过在VERTEX_SHADER顶点着色器中将z坐标设置为接近1.0的值来实现此目的:
gl_Position = vec4(position, 1.0);

gl_Position = vec4(position.xy, 0.999, 1.0);

或者,您可以在绘制背景纹理时将深度测试函数更改为GL_LEQUAL

glDepthFunc(GL_LEQUAL)

并将裁剪空间的z坐标设置为等于w分量。例如:

gl_Position = vec4(position, 1.0);
gl_Position.z = gl_Position.w;
vu8f3i0k

vu8f3i0k2#

下面的修改对我来说也是同样的问题。但是,我想知道它下面在做什么....它不是在逐层渲染上工作,而是在做类似针孔相机模型的实际透视变换吗?
背景前glDepthFunc(GL_LEQUAL)
以及着色器中的下方

gl_Position = vec4(position, 1.0);
gl_Position.z = gl_Position.w;

免责声明!!!非常新的opengl

相关问题