Pyopengl纹理渲染不正确,对象填充实心灰色

2024-09-27 21:33:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图添加纹理(png图像文件)的矩形,这是正在渲染。但是,不管我使用什么图像,对象都是灰色的。我有一种感觉,我错过了一些与tetxure坐标有关的东西。在顶点缓冲区的每一行中,前2个数字表示x和y坐标,而后2个数字表示纹理坐标。你知道吗

大多数在线答案表明,有一个问题与图像数据被传递到纹理,或是没有被正确绑定。你知道吗

from OpenGL.GL import *
import glfw
import numpy
import sys
from PIL import Image

class Shader:    
    def readshader(self, Title, filepath):
        #reads shader (This works so I have removed it for ease of reading)

    def CreateShader(self, filepath):
        program = glCreateProgram()
        VERT = self.readshader("VERTEX", filepath)
        vertShader = glCreateShader(GL_VERTEX_SHADER)
        self.Compileshader(vertShader, VERT, program, "Vertex")     
        FRAG = self.readshader("FRAGMENT", filepath)
        fragShader = glCreateShader(GL_FRAGMENT_SHADER)
        self.Compileshader(fragShader, FRAG, program, "Fragment")
        glLinkProgram(program)
        glValidateProgram(program)
        glDeleteShader(vertShader)
        glDeleteShader(fragShader)  
        return program

    def Compileshader(self, shader, shaderstring, program, type):
        glShaderSource(shader, shaderstring)
        glCompileShader(shader)
        status = glGetShaderiv(shader, GL_COMPILE_STATUS)
        if not status:
            info = glGetShaderInfoLog(shader)
            print("Error in " + type + " Shader:")
            print(info.decode("utf-8"))
            glDeleteShader(shader)
        else:
            glAttachShader(program, shader)

class Renderer:
    def __init__(self):
        self.vao = glGenVertexArrays(1)
        glBindVertexArray(self.vao)
        self.buffer = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, self.buffer)
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, None)
        self.ibo = glGenBuffers(1)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ibo)

    def AttachTexture(self, NewTexture, Width, Height, Uniform, value):
        glEnable(GL_TEXTURE_2D)
        self.Texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.Texture)

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NewTexture)

        glGenerateMipmap(GL_TEXTURE_2D); ##new

        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 16, None) ##new
        glEnableVertexAttribArray(2)  ##new

        glBindTexture(GL_TEXTURE_2D, self.Texture)  #new

        glActiveTexture(GL_TEXTURE0 + value)
        location = glGetUniformLocation(self.program, Uniform)
        glUniform1i(location, value)

    def AttachShader(self, program):
        self.program = program
        glUseProgram(self.program)

    def GetUniformLocation(self, Uniform, r, g, b):
        location = glGetUniformLocation(self.program, Uniform)
        glUniform4f(location, r, g, b, 1.0)

    def ArrayBufferData(self, positions):
        glBufferData(GL_ARRAY_BUFFER, positions, GL_STATIC_DRAW)

    def IndexBufferData(self, indices):
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW)

    def Unbind(self):
        glBindVertexArray(0)
        glUseProgram(0)
        glBindBuffer(GL_ARRAY_BUFFER, 0)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)

    def Bind(self):
        glBindVertexArray(self.vao)
        glUseProgram(self.program)
        glBindBuffer(GL_ARRAY_BUFFER, self.buffer)
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.ibo)

    def DrawElements(self, length):
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glDrawElements(GL_TRIANGLES, length, GL_UNSIGNED_INT, None)


def main():
    TextureA = Image.open("Textures\Texture Test 2019.08.12 01.58.png").transpose(Image.FLIP_TOP_BOTTOM)
    Texture = numpy.frombuffer(TextureA.tobytes(), numpy.uint8)
    Width, Height = TextureA.size
    name = "OpenGL Testing"
    if not glfw.init():
        return
    window = glfw.create_window(640, 480, "Hello World", None, None)
    if not window:
        glfw.terminate()
    glfw.make_context_current(window)
    glfw.swap_interval(1)

    NewShader = Shader()
    program = NewShader.CreateShader("Shaders\Complete Shader 2019.08.12 02.41.txt")

    NewBuffer = Renderer()
    NewBuffer.AttachShader(program)
    positions = numpy.array([-0.5, -0.5, 0.0, 0.0\
                             ,0.5, -0.5, 1.0, 0.0\
                             ,0.5,  0.5, 1.0, 1.0\
                            ,-0.5,  0.5, 0.0, 1.0]\
                            ,dtype = 'float32')
    indices = numpy.array([0, 1, 2,\
                           2, 3, 0]\
                          ,dtype = 'int32')

    NewBuffer.ArrayBufferData(positions)
    NewBuffer.IndexBufferData(indices)

    red = 0.0
    increment = 0.05

    while not glfw.window_should_close(window):
        NewBuffer.Bind()
        if red > 1.0:
            increment = -0.05
        elif red < 0.0:
            increment = 0.05
        red += increment
        NewBuffer.GetUniformLocation("u_Color", red, 0.3, 0.8)
        NewBuffer.DrawElements(len(indices))
        NewBuffer.AttachTexture(Texture, Width, Height, "u_Texture", 0)

        glfw.swap_buffers(window)
        glfw.poll_events()

    glfw.terminate()

if __name__ == '__main__': main()

#For reference here is the vertex and fragment shader I am using:

"""
@VERTEX
#version 330 core

layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord; 

out vec2 v_TexCoord;

void main()
{
    gl_Position = position;
    v_TexCoord = texCoord;
};
@FRAGMENT
#version 330 core

layout(location = 0) out vec4 color;

in vec2 v_TexCoord;

uniform vec4 u_Color;
uniform sampler2D u_Texture;

void main()
{
    vec4 texColor = texture(u_Texture, v_TexCoord);
    color = texColor;
};
"""

Tags: importselfdefbufferlocationwindowprogramarray
2条回答

我认为需要偏移量8作为第二个glVertexAttribPointer的最后一个参数,这个参数定义了纹理坐标。你知道吗

你使用的是一个交错数组,顶点坐标后跟tex坐标,对吗?因此第一个attrib指针将顶点坐标定义为两个浮点数,相隔16字节(4 x float),从缓冲区的字节0开始。第二个attrib指针将纹理坐标定义为两个浮点数,相隔16个字节,从缓冲区的字节0开始。所以顶点坐标被重新用作纹理坐标。你知道吗

纹理坐标的属性索引为1:

layout(location = 1) in vec2 texCoord;

因此,当指定并启用常规顶点属性数组时,属性索引也必须为1。分别见^{}^{}。你知道吗

绑定命名缓冲区对象时,glVertexAttribPointer的最后一个参数被视为缓冲区对象数据存储的字节偏移量。
缓冲区的内容是顶点坐标,后跟2个纹理坐标:

x0, y0, u0, v0,   x1, y1, u1, v1,   x2, y2, u2, v2, ...

每个分量的大小为4(大小为float),因此步幅为16=4*4。
顶点坐标的偏移为0,偏移纹理坐标为8=2*4。你知道吗

因为^{}的offset(last)参数的类型是const GLvoid *,所以必须将参数强制转换为^{}

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, c_void_p(0))

如果偏移量为0,则可以使用None

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, None)

绑定缓冲区在指定常规顶点属性数据数组之前,请设置适当的属性索引和偏移:

from ctypes import c_void_p
glBindBuffer(GL_ARRAY_BUFFER, self.buffer)

glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 16, None)

glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 16, c_void_p(8))

相关问题 更多 >

    热门问题