V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
edis0n0
V2EX  ›  Python

有懂 OpenGL 的 V 友能帮忙看看为什么我的着色器渲染出来是黑屏么?研究了一天还没解决。

  •  
  •   edis0n0 · 2022-12-24 16:06:36 +08:00 · 2938 次点击
    这是一个创建于 699 天前的主题,其中的信息可能已经有所发展或是发生改变。

    从游戏中逆向出来的着色器,作用的将256*1像素颜色查找表的颜色还原到灰度贴图上。

    调用的 Python 代码是:

    import numpy as np
    from PIL import Image
    from OpenGL.GL import *
    from OpenGL.GLU import *
    from OpenGL.GLUT import *
    
    # Load the two input images
    main_tex = Image.open("main_tex.png")
    clut = Image.open("clut.png")
    
    # Convert the images to numpy arrays and flip the y-axis
    main_tex_data = np.flip(np.array(main_tex), 0)
    clut_data = np.flip(np.array(clut), 0)
    
    # Create the output image
    output_image = Image.new("RGB", main_tex.size)
    output_data = np.array(output_image)
    
    # Create the OpenGL window and set up the viewport
    glutInit(sys.argv)
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
    glutInitWindowSize(main_tex.size[0], main_tex.size[1])
    glutCreateWindow(b"Shader")
    glutReshapeFunc(lambda w, h: glViewport(0, 0, w, h))
    
    # Create the texture objects for the input images
    main_tex_id = glGenTextures(1)
    clut_id = glGenTextures(1)
    
    # Set up the main texture
    glBindTexture(GL_TEXTURE_2D, main_tex_id)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, main_tex.size[0], main_tex.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, main_tex_data)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    
    # Set up the CLUT texture
    glBindTexture(GL_TEXTURE_2D, clut_id)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, clut.size[0], clut.size[1], 0, GL_RGB, GL_UNSIGNED_BYTE, clut_data)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
    
    # Create the shader program
    program_id = glCreateProgram()
    
    # Compile the vertex shader
    vertex_shader = """
    #version 100
    					
    					uniform 	vec4 hlslcc_mtx4x4unity_ObjectToWorld[4];
    					uniform 	vec4 hlslcc_mtx4x4unity_MatrixVP[4];
    					uniform 	vec4 _MainTex_ST;
    					uniform 	vec4 _MainTex_TexelSize;
    					attribute highp vec4 in_POSITION0;
    					attribute highp vec4 in_TEXCOORD0;
    					varying mediump vec2 vs_TEXCOORD0;
    					varying mediump vec2 vs_TEXCOORD1;
    					varying mediump vec2 vs_TEXCOORD2;
    					varying mediump vec2 vs_TEXCOORD3;
    					varying highp vec2 vs_TEXCOORD4;
    					vec4 u_xlat0;
    					vec4 u_xlat1;
    					vec2 u_xlat4;
    					void main()
    					{
    					    u_xlat0 = in_POSITION0.yyyy * hlslcc_mtx4x4unity_ObjectToWorld[1];
    					    u_xlat0 = hlslcc_mtx4x4unity_ObjectToWorld[0] * in_POSITION0.xxxx + u_xlat0;
    					    u_xlat0 = hlslcc_mtx4x4unity_ObjectToWorld[2] * in_POSITION0.zzzz + u_xlat0;
    					    u_xlat0 = u_xlat0 + hlslcc_mtx4x4unity_ObjectToWorld[3];
    					    u_xlat1 = u_xlat0.yyyy * hlslcc_mtx4x4unity_MatrixVP[1];
    					    u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[0] * u_xlat0.xxxx + u_xlat1;
    					    u_xlat1 = hlslcc_mtx4x4unity_MatrixVP[2] * u_xlat0.zzzz + u_xlat1;
    					    gl_Position = hlslcc_mtx4x4unity_MatrixVP[3] * u_xlat0.wwww + u_xlat1;
    					    u_xlat4.x = 0.0;
    					    u_xlat4.y = _MainTex_TexelSize.y;
    					    u_xlat0.xy = in_TEXCOORD0.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    					    u_xlat0.xy = (-_MainTex_TexelSize.xy) * vec2(0.5, 0.5) + u_xlat0.xy;
    					    vs_TEXCOORD1.xy = u_xlat4.xy + u_xlat0.xy;
    					    vs_TEXCOORD0.xy = u_xlat0.xy;
    					    u_xlat1.x = _MainTex_TexelSize.x;
    					    u_xlat1.y = 0.0;
    					    vs_TEXCOORD2.xy = u_xlat0.xy + u_xlat1.xy;
    					    vs_TEXCOORD3.xy = u_xlat0.xy + _MainTex_TexelSize.xy;
    					    vs_TEXCOORD4.xy = u_xlat0.xy * _MainTex_TexelSize.zw;
    
    					    return;
    					}
    """
    vertex_shader_id = glCreateShader(GL_VERTEX_SHADER)
    glShaderSource(vertex_shader_id, vertex_shader)
    glCompileShader(vertex_shader_id)
    
    # Compile the fragment shader
    fragment_shader = """
    #version 100
    					
    					#ifdef GL_FRAGMENT_PRECISION_HIGH
    					    precision highp float;
    					#else
    					    precision mediump float;
    					#endif
    					precision highp int;
    					uniform 	vec4 _CLUT_TexelSize;
    					uniform lowp sampler2D _MainTex;
    					uniform lowp sampler2D _CLUT;
    					varying mediump vec2 vs_TEXCOORD0;
    					varying mediump vec2 vs_TEXCOORD1;
    					varying mediump vec2 vs_TEXCOORD2;
    					varying mediump vec2 vs_TEXCOORD3;
    					varying highp vec2 vs_TEXCOORD4;
    					#define SV_Target0 gl_FragData[0]
    					vec4 u_xlat0;
    					lowp float u_xlat10_0;
    					vec4 u_xlat1;
    					mediump vec4 u_xlat16_1;
    					lowp vec4 u_xlat10_1;
    					vec4 u_xlat2;
    					mediump vec4 u_xlat16_2;
    					lowp vec4 u_xlat10_2;
    					float u_xlat3;
    					lowp vec4 u_xlat10_3;
    					vec2 u_xlat8;
    					vec2 u_xlat10;
    					void main()
    					{
    					    u_xlat10_0 = texture2D(_MainTex, vs_TEXCOORD3.xy).w;
    					    u_xlat0.x = u_xlat10_0 * _CLUT_TexelSize.z + (-_CLUT_TexelSize.x);
    					    u_xlat0.x = u_xlat0.x / _CLUT_TexelSize.z;
    					    u_xlat0.y = float(0.0);
    					    u_xlat8.y = float(0.0);
    					    u_xlat10_1 = texture2D(_CLUT, u_xlat0.xy);
    					    u_xlat10_0 = texture2D(_MainTex, vs_TEXCOORD1.xy).w;
    					    u_xlat0.x = u_xlat10_0 * _CLUT_TexelSize.z + (-_CLUT_TexelSize.x);
    					    u_xlat2.x = u_xlat0.x / _CLUT_TexelSize.z;
    					    u_xlat2.y = float(0.0);
    					    u_xlat10.y = float(0.0);
    					    u_xlat10_3 = texture2D(_CLUT, u_xlat2.xy);
    					    u_xlat16_1 = u_xlat10_1 + (-u_xlat10_3);
    					    u_xlat0.xy = fract(vs_TEXCOORD4.xy);
    					    u_xlat1 = u_xlat0.xxxx * u_xlat16_1 + u_xlat10_3;
    					    u_xlat10_2.x = texture2D(_MainTex, vs_TEXCOORD2.xy).w;
    					    u_xlat2.x = u_xlat10_2.x * _CLUT_TexelSize.z + (-_CLUT_TexelSize.x);
    					    u_xlat10.x = u_xlat2.x / _CLUT_TexelSize.z;
    					    u_xlat10_2 = texture2D(_CLUT, u_xlat10.xy);
    					    u_xlat10_3.x = texture2D(_MainTex, vs_TEXCOORD0.xy).w;
    					    u_xlat3 = u_xlat10_3.x * _CLUT_TexelSize.z + (-_CLUT_TexelSize.x);
    					    u_xlat8.x = u_xlat3 / _CLUT_TexelSize.z;
    					    u_xlat10_3 = texture2D(_CLUT, u_xlat8.xy);
    					    u_xlat16_2 = u_xlat10_2 + (-u_xlat10_3);
    					    u_xlat2 = u_xlat0.xxxx * u_xlat16_2 + u_xlat10_3;
    					    u_xlat1 = u_xlat1 + (-u_xlat2);
    					    u_xlat0 = u_xlat0.yyyy * u_xlat1 + u_xlat2;
    					    SV_Target0.w = ceil(u_xlat0.w);
    					    SV_Target0.xyz = u_xlat0.xyz;
    					    return;
    					}
    					
    """
    fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
    glShaderSource(fragment_shader_id, fragment_shader)
    glCompileShader(fragment_shader_id)
    
    if vertex_shader_id == 0:
            print("Error creating vertex shader object")
    else:
        # Set the vertex shader source code
        glShaderSource(vertex_shader_id, vertex_shader)
    
        # Compile the vertex shader
        glCompileShader(vertex_shader_id)
    
        # Check if the vertex shader was successfully compiled
        vertex_compile_status = glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS)
    
        if vertex_compile_status != GL_TRUE:
            # Print the compile log if the vertex shader failed to compile
            vertex_compile_log = glGetShaderInfoLog(vertex_shader_id)
            print("Error compiling vertex shader:")
            print(vertex_compile_log)
        else:
            # Create the fragment shader object
            fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER)
    
            # Check if the fragment shader object is valid
            if fragment_shader_id == 0:
                print("Error creating fragment shader object")
            else:
                # Set the fragment shader source code
                glShaderSource(fragment_shader_id, fragment_shader)
    
                # Compile the fragment shader
                glCompileShader(fragment_shader_id)
    
                # Check if the fragment shader was successfully compiled
                fragment_compile_status = glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS)
    
                if fragment_compile_status != GL_TRUE:
                    # Print the compile log if the fragment shader failed to compile
                    fragment_compile_log = glGetShaderInfoLog(fragment_shader_id)
                    print("Error compiling fragment shader:")
                    print(fragment_compile_log)
                # else:
                #     # Attach the shaders to the program
                #     glAttachShader(program_id, vertex_shader_id)
                #     glAttachShader(program_id, fragment_shader_id)
    
    
    # Link the program
    glLinkProgram(program_id)
    
    # Create the vertex data
    vertices = np.array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0], np.float32)
    tex_coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0], np.float32)
    
    # Create the vertex buffer object
    vbo = glGenBuffers(1)
    
    # Bind the VBO and upload the vertex data
    glBindBuffer(GL_ARRAY_BUFFER, vbo)
    glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
    
    # Create the texture coordinate buffer object
    tex_coord_vbo = glGenBuffers(1)
    
    # Bind the tex coord VBO and upload the texture coordinate data
    glBindBuffer(GL_ARRAY_BUFFER, tex_coord_vbo)
    glBufferData(GL_ARRAY_BUFFER, tex_coords.nbytes, tex_coords, GL_STATIC_DRAW)
    
    # Set up the vertex attribute pointers
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, None)
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, None)
    
    # Enable the vertex attribute arrays
    glEnableVertexAttribArray(0)
    glEnableVertexAttribArray(1)
    
    # Bind the main texture to texture unit 0
    glActiveTexture(GL_TEXTURE0)
    glBindTexture(GL_TEXTURE_2D, main_tex_id)
    
    # Bind the CLUT texture to texture unit 1
    glActiveTexture(GL_TEXTURE1)
    glBindTexture(GL_TEXTURE_2D, clut_id)
    
    # # Set the CLUT texel size uniform
    # clut_texel_size = np.array([1.0 / clut.size[0], 1.0 / clut.size[1], 1.0 / clut.size[0], 1.0 / clut.size[1]], np.float32)
    # glUniform4fv(glGetUniformLocation(program_id, "_CLUT_TexelSize"), 1, clut_texel_size)
    
    # Compile the shaders
    glCompileShader(vertex_shader_id)
    glCompileShader(fragment_shader_id)
    
    # Check if the shaders were successfully compiled
    vertex_compile_status = glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS)
    fragment_compile_status = glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS)
    
    if vertex_compile_status != GL_TRUE or fragment_compile_status != GL_TRUE:
        # Print the compile logs if the shaders failed to compile
        vertex_compile_log = glGetShaderInfoLog(vertex_shader_id)
        fragment_compile_log = glGetShaderInfoLog(fragment_shader_id)
        print("Error compiling shaders:")
        print(vertex_compile_log)
        print(fragment_compile_log)
    else:
        # Attach the shaders to the program
        glAttachShader(program_id, vertex_shader_id)
        glAttachShader(program_id, fragment_shader_id)
        
        # Link the program
        glLinkProgram(program_id)
        
        # Check if the program was successfully linked
        link_status = glGetProgramiv(program_id, GL_LINK_STATUS)
    
        if link_status != GL_TRUE:
            # Print the link log if the program failed to link
            link_log = glGetProgramInfoLog(program_id)
            print("Error linking program:")
            print(link_log)
        else:
            # Activate the program
            glUseProgram(program_id)
    
    # Set the CLUT texel size uniform
    clut_texel_size = np.array([1.0 / clut.size[0], 1.0 / clut.size[1], 1.0 / clut.size[0], 1.0 / clut.size[1]], np.float32)
    
    # Get the uniform location
    clut_texel_size_loc = glGetUniformLocation(program_id, "_CLUT_TexelSize")
    
    # Set the uniform value
    glUniform4fv(clut_texel_size_loc, 1, clut_texel_size)
    
    # Draw the quad
    glClearColor(0.0, 0.0, 0.0, 1.0)
    glClear(GL_COLOR_BUFFER_BIT)
    glUseProgram(program_id)
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
    
    # Read back the framebuffer data
    width = main_tex.width
    height = main_tex.height
    
    # Set the format and type of the pixel data
    format = GL_RGBA
    type = GL_UNSIGNED_BYTE
    
    # Allocate a buffer to store the pixel data
    pixels = ctypes.create_string_buffer(width * height * 4)
    
    # Read the pixels from the framebuffer
    glReadPixels(0, 0, width, height, format, type, pixels)
    
    # Convert the pixel data to a Python bytearray
    output_data = bytearray(pixels)
    
    # Convert the bytearray to a NumPy array
    output_data = np.frombuffer(output_data, np.uint8)
    
    # Reshape the array to the desired dimensions
    output_data = output_data.reshape((height, width, 4))
    
    # Create the output image from the NumPy array
    output_image = Image.fromarray(output_data)
    
    # Save the output image as a PNG file
    output_image.save("output.png")
    
    2 条回复    2022-12-26 10:27:04 +08:00
    edis0n0
        1
    edis0n0  
    OP
       2022-12-25 11:34:34 +08:00
    不用了,chatgpt 给我写了个能用的版本
    noErr
        2
    noErr  
       2022-12-26 10:27:04 +08:00
    @edis0n0 卧槽?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2820 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:00 · PVG 12:00 · LAX 20:00 · JFK 23:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.