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

2022-12-24 16:06:36 +08:00
 edis0n0

从游戏中逆向出来的着色器,作用的将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")
2937 次点击
所在节点    Python
2 条回复
edis0n0
2022-12-25 11:34:34 +08:00
不用了,chatgpt 给我写了个能用的版本
noErr
2022-12-26 10:27:04 +08:00
@edis0n0 卧槽?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/904457

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX