pyopengl绘制时翻转纹理

如何解决pyopengl绘制时翻转纹理

我最近下载了一个使用pyOpenGl和pygame的批处理渲染程序。我想编辑绘制功能,以便在绘制纹理时可以翻转纹理。这是批处理渲染程序的代码。

import numpy
from OpenGL import GL
from OpenGL.GL import shaders
import ctypes

def setup_shaders(vpMatrix):
    global shaderProgram,vshader,fshader
    global texCoordAttribute,positionAttribute
    
    vshader = shaders.compileShader('''#version 440

    layout (location = 0) uniform mat4 vpMatrix;

    layout (location = 0) in vec2 vPosition;
    layout (location = 1) in vec2 vTexCoord0;
    //layout (location = 2) in vec4 vVertColor;

    out vec2 texCoord0;
    //out vec4 vertColor;

    void main(void) {
        gl_Position = vpMatrix * vec4(vPosition,0.0,1.0);
        texCoord0 = vTexCoord0;
    }''',GL.GL_VERTEX_SHADER)

    fshader = shaders.compileShader('''#version 440

    in vec2 texCoord0;
    //in vec4 vertColor;
    layout (location = 1) uniform sampler2D u_texture0;

    void main(void) {
        gl_FragColor = texture2D(u_texture0,texCoord0);
    }''',GL.GL_FRAGMENT_SHADER)

    shaderProgram = shaders.compileProgram(vshader,fshader)

    texCoordAttribute = GL.glGetAttribLocation(shaderProgram,'vTexCoord0')
    positionAttribute = GL.glGetAttribLocation(shaderProgram,'vPosition')
    texUniform = GL.glGetUniformLocation(shaderProgram,'u_texture0')

    GL.glEnableVertexAttribArray(positionAttribute)
    GL.glEnableVertexAttribArray(texCoordAttribute)
    
    GL.glUseProgram(shaderProgram)
    
    GL.glUniformMatrix4fv(
        GL.glGetUniformLocation(shaderProgram,'vpMatrix'),1,False,vpMatrix,)
    GL.glUniform1i(texUniform,0)
    
    # TODO: cleanup (delete shaders)

class GLTexture:
    def __init__(self,textureId,width,height):
        self.texture = textureId
        self.width,self.height = width,height

    def delete(self):
        GL.glDeleteTextures([self.texture])

class GLTextureRegion:
    def __init__(self,glTexture,subX,subY,subWidth,subHeight):
        self.texture = glTexture
        #self.tx,self.ty = subX,subY
        self.tw,self.th = subWidth,subHeight

        self.normalizedCoords = (
            subX / glTexture.width,subY / glTexture.height,(subX + subWidth) / glTexture.width,subX / glTexture.width,(subY + subHeight) / glTexture.height,)

    def write_tex_coords(self,aj):
        nc = self.normalizedCoords
        aj[4 * 0 + 2] = nc[0]
        aj[4 * 0 + 3] = nc[1]
        aj[4 * 1 + 2] = nc[2]
        aj[4 * 1 + 3] = nc[3]
        aj[4 * 2 + 2] = nc[4]
        aj[4 * 2 + 3] = nc[5]
        aj[4 * 3 + 2] = nc[6]
        aj[4 * 3 + 3] = nc[7]

    def write_vertices(self,aj,x,y):
        aj[4 * 0 + 0] = x
        aj[4 * 0 + 1] = y
        aj[4 * 1 + 0] = x + self.tw
        aj[4 * 1 + 1] = y
        aj[4 * 2 + 0] = x
        aj[4 * 2 + 1] = y + self.th
        aj[4 * 3 + 0] = x + self.tw
        aj[4 * 3 + 1] = y + self.th

    def update_array(self,vboData,arrayIndex,y):
        aj = vboData[arrayIndex]
        self.write_vertices(aj,y)
        self.write_tex_coords(aj)

    def delete(self):
        '''deletes the underlying texture'''
        self.texture.delete()

class Batch:
    def __init__(self,maxQuads = 10000):
        self.maxQuads = maxQuads

        self.vboIndices = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,self.vboIndices)
        vidA = []
        for i in range(maxQuads):
            vidA.extend([
                4 * i + 0,4 * i + 2,4 * i + 1,4 * i + 3
            ])
        self.vboIndexData = numpy.array(vidA,numpy.ushort)
        del vidA
        GL.glBufferData(
            GL.GL_ELEMENT_ARRAY_BUFFER,self.vboIndexData,GL.GL_STATIC_DRAW,)

        self.vbo = GL.glGenBuffers(1)  # texture coords & vertices
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER,self.vbo)
        self.vboData = numpy.zeros((maxQuads,4 * 4),numpy.float32)
        GL.glBufferData(
            GL.GL_ARRAY_BUFFER,self.vboData,GL.GL_DYNAMIC_DRAW
        )

        self.currentTexture = None
        self.objectIndex = 0

    def begin(self):
        GL.glBindBuffer(
            GL.GL_ARRAY_BUFFER,self.vbo,)
        if self.currentTexture:
            GL.glBindTexture(
                GL.GL_TEXTURE_2D,self.currentTexture.texture,)
        GL.glEnable(GL.GL_TEXTURE_2D)
        GL.glActiveTexture(GL.GL_TEXTURE0)

    def draw(self,textureRegion,y,flip = False):
        
        
        if self.currentTexture != textureRegion.texture:
            self.flush()
            self.currentTexture = textureRegion.texture
            GL.glBindTexture(
                GL.GL_TEXTURE_2D,textureRegion.texture.texture,)
        elif self.objectIndex >= self.maxQuads:
            self.flush()
        
        textureRegion.update_array(
            self.vboData,self.objectIndex,y
        )
        
        self.objectIndex += 1

    def end(self):
        self.flush()

    def flush(self):
        if not self.objectIndex:
            return
        GL.glVertexAttribPointer(
            texCoordAttribute,2,GL.GL_FLOAT,GL.GL_TRUE,4 * self.vboData.itemsize,ctypes.c_void_p(2 * self.vboData.itemsize)
        )
        GL.glVertexAttribPointer(
            positionAttribute,GL.GL_FALSE,ctypes.c_void_p(0)
        )
        GL.glBufferSubData(
            GL.GL_ARRAY_BUFFER,16 * self.objectIndex * self.vboData.itemsize,)
        GL.glDrawElements(
            GL.GL_TRIANGLES,6 * self.objectIndex,GL.GL_UNSIGNED_SHORT,ctypes.c_void_p(0),)
        self.objectIndex = 0

    def delete(self):
        GL.glDeleteBuffers(1,[self.vbo])
        GL.glDeleteBuffers(1,[self.vboIndices])

到目前为止,我已经尝试了一些涉及glscalef的事情(正如我在网上找到的答案所建议的那样),但是我无法使它对纹理产生任何影响。有没有办法在draw函数中使这项工作有效?还是我必须完全尝试另一种方法?

解决方法

您可以在顶点着色器中“翻转”纹理坐标的y分量:

void main(void) {
    // [...]        

    texCoord0 = vec2(vTexCoord0.x,1.0 - vTexCoord0.y);
}

如果要“翻转”单个纹理,则可以翻转纹理坐标属性。将TrueFalse传递给参数flipY

class GLTextureRegion:
    # [...]

    def write_tex_coords(self,aj,flipY):
        nc = self.normalizedCoords
        for i in range(4):
            aj[i*4 + 2] = nc[i*2]
            aj[i*4 + 3] = 1-nc[i*2 + 1] if flipY else nc[i*2 + 1]

    # [...]

    def update_array(self,vboData,arrayIndex,x,y,flipY):
        aj = vboData[arrayIndex]
        self.write_vertices(aj,y)
        self.write_tex_coords(aj,flipY)

或者,您可以在顶点着色器中通过统一缩放纹理坐标。初始化制服

layout (location = 0) uniform mat4 vpMatrix;
layout (location = 1) uniform vec2 uTexCoordScale;

layout (location = 0) in vec2 vPosition;
layout (location = 1) in vec2 vTexCoord0;

out vec2 texCoord0;

void main(void) 
{
    gl_Position = vpMatrix * vec4(vPosition,0.0,1.0);
    texCoord0 = uTexCoordScale * vTexCoord0;
}

如果要“翻转”纹理,请通过(1.0,1.0)初始化统一uTexCoordScale并将其更改为(1.0,-1.0)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-