相同的代码,但在不同平台上产生不同的结果。

huangapple go评论173阅读模式
英文:

Same code but different results from different platform

问题

我明白你的请求,以下是翻译好的代码部分:

# cube.py文件中的一部分
class Cube(object):
    def __init__(self, vert_shader, frag_shader):
        self.vertices = np.array([
            # 在这里指定顶点坐标
            [-0.5, -0.5, -0.5],  # A 0
            [0.5, -0.5, -0.5],  # B 1
            [0.5, -0.5, 0.5],  # C 2
            [-0.5, -0.5, 0.5],  # D 3
            [-0.5, 0.5, -0.5],  # E 4
            [0.5, 0.5, -0.5],  # F 5
            [0.5, 0.5, 0.5],  # G 6
            [-0.5, 0.5, 0.5]  # H 7
        ], dtype=np.float32)

        self.indices = np.array([
            # 在这里指定索引
            4, 7, 5, 6,  # 顶部
            6, 0,
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4,  # 侧面
            5, 1,
            0, 3, 1, 2  # 底部
        ])

        # 在这里使用坐标计算顶点法线
        normals = np.random.normal(0, 1, (self.vertices.shape[0], 3)).astype(np.float32)
        normals[:, 2] = np.abs(normals[:, 2])
        self.normals = normals / np.linalg.norm(normals, axis=1, keepdims=True)

        # 颜色:RGB格式
        self.colors = np.array([
            # 在这里指定顶点颜色
            [0.0, 0.0, 0.0],  # 黑色
            [1.0, 0.0, 0.0],  # 红色
            [1.0, 1.0, 0.0],  # 黄色
            [0.0, 1.0, 0.0],  # 绿色
            [0.0, 0.0, 1.0],  # 蓝色
            [1.0, 0.0, 1.0],  # 洋红色
            [1.0, 1.0, 1.0],  # 白色
            [0.0, 1.0, 1.0]  # 青色
        ], dtype=np.float32)

# libs/buffer.py文件中的一部分
class VAO(object):
    def __init__(self):
        self.vao = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(self.vao)
        GL.glBindVertexArray(0)
        self.vbo = {}
        self.ebo = None

    def add_vbo(self, location, data, ncomponents=3, dtype=GL.GL_FLOAT, normalized=False, stride=0, offset=None):
        self.activate()
        buffer_idx = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, buffer_idx)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, data, GL.GL_STATIC_DRAW)
        GL.glVertexAttribPointer(location, ncomponents, dtype, normalized, stride, offset)
        GL.glEnableVertexAttribArray(location)
        self.vbo[location] = buffer_idx
        self.deactivate()

# viewer.py文件中的一部分
class Viewer:
    def __init__(self, width=800, height=800):
        self.fill_modes = cycle([GL.GL_LINE, GL.GL_POINT, GL.GL_FILL])
        # 窗口创建及其他初始化

    def run(self):
        while not glfw.window_should_close(self.win):
            # 清空绘制缓冲区
            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

            win_size = glfw.get_window_size(self.win)
            view = self.trackball.view_matrix()
            projection = self.trackball.projection_matrix(win_size)

            # 绘制场景对象
            for drawable in self.drawables:
                drawable.draw(projection, view, None)

            # 刷新绘制命令,交换绘制缓冲区
            glfw.swap_buffers(self.win)

            # 处理事件
            glfw.poll_events()

# 主程序和场景设置
def main():
    viewer = Viewer()
    # 放置基本对象的实例

    model = Cube("./gouraud.vert", "./gouraud.frag").setup()
    viewer.add(model)

    viewer.run()

if __name__ == '__main__':
    glfw.init()
    main()
    glfw.terminate()

希望这能帮助你解决冲突。

英文:

I have an exercise to draw a simple cube that teacher asks me to fill in where: <br> "YOUR CODE HERE ...". <br>
I have done it but when coming to see the result, it rendered something weird (Figure 1 ). I have run that code on my friend's laptop and it gave a really good cube (Figure 2). <br>
There are 3 files in used:

  • cube.py:
from libs.buffer import *
import glfw


class Cube(object):
    def __init__(self, vert_shader, frag_shader):
        self.vertices = np.array([
            # YOUR CODE HERE to specify vertices&#39; coordinates
            [-0.5, -0.5, -0.5],  # A 0
            [0.5, -0.5, -0.5],  # B 1
            [0.5, -0.5, 0.5],  # C 2
            [-0.5, -0.5, 0.5],  # D 3
            [-0.5, 0.5, -0.5],  # E 4
            [0.5, 0.5, -0.5],  # F 5
            [0.5, 0.5, 0.5],  # G 6
            [-0.5, 0.5, 0.5]  # H 7
        ], dtype=np.float32)

        self.indices = np.array([
            # YOUR CODE HERE to specify indices
            4, 7, 5, 6,  # Top
            6, 0,
            0, 4, 1, 5, 2, 6, 3, 7, 0, 4,  # Sides
            5, 1,
            0, 3, 1, 2  # Bottom
        ])

        # YOUR CODE HERE to compute vertices&#39; normals using the coordinates
        normals = np.random.normal(0, 1, (self.vertices.shape[0], 3)).astype(np.float32)
        normals[:, 2] = np.abs(normals[:, 2])
        self.normals = normals / np.linalg.norm(normals, axis=1, keepdims=True)

        # colors: RGB format
        self.colors = np.array([
            # YOUR CODE HERE to specify vertices&#39; color
            [0.0, 0.0, 0.0],  # black
            [1.0, 0.0, 0.0],  # red
            [1.0, 1.0, 0.0],  # yellow
            [0.0, 1.0, 0.0],  # green
            [0.0, 0.0, 1.0],  # blue
            [1.0, 0.0, 1.0],  # magenta
            [1.0, 1.0, 1.0],  # white
            [0.0, 1.0, 1.0]  # cyan
        ], dtype=np.float32)

        self.vao = VAO()

        self.shader = Shader(vert_shader, frag_shader)
        self.uma = UManager(self.shader)
        #

    &quot;&quot;&quot;
    Create object -&gt; call setup -&gt; call draw
    &quot;&quot;&quot;

    def setup(self):
        # setup VAO for drawing cylinder&#39;s side
        self.vao.add_vbo(0, self.vertices, ncomponents=3, stride=0, offset=None)
        self.vao.add_vbo(1, self.colors, ncomponents=3, stride=0, offset=None)

        # setup EBO for drawing cylinder&#39;s side, bottom and top
        self.vao.add_ebo(self.indices)

        return self

    def draw(self, projection, view, model):
        GL.glUseProgram(self.shader.render_idx)
        modelview = view

        self.uma.upload_uniform_matrix4fv(projection, &#39;projection&#39;, True)
        self.uma.upload_uniform_matrix4fv(modelview, &#39;modelview&#39;, True)

        self.vao.activate()
        GL.glDrawElements(GL.GL_TRIANGLE_STRIP, self.indices.shape[0], GL.GL_UNSIGNED_INT, None)

    def key_handler(self, key):
        if key == glfw.KEY_1:
            self.selected_texture = 1
        if key == glfw.KEY_2:
            self.selected_texture = 2

  • libs/buffer.py:
import OpenGL.GL as GL
import cv2


class VAO(object):
    def __init__(self):
        self.vao = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(self.vao)
        GL.glBindVertexArray(0)
        self.vbo = {}
        self.ebo = None

    def add_vbo(self, location, data, ncomponents=3, dtype=GL.GL_FLOAT, normalized=False, stride=0, offset=None):
        self.activate()
        buffer_idx = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, buffer_idx)
        GL.glBufferData(GL.GL_ARRAY_BUFFER, data, GL.GL_STATIC_DRAW)
        # location = GL.glGetAttribLocation(self.shader.render_idx, name)
        GL.glVertexAttribPointer(location, ncomponents, dtype, normalized, stride, offset)
        GL.glEnableVertexAttribArray(location)
        self.vbo[location] = buffer_idx
        self.deactivate()

    def add_ebo(self, indices):
        self.activate()
        self.ebo = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, self.ebo)
        GL.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indices, GL.GL_STATIC_DRAW)
        self.deactivate()

    def __del__(self):
        GL.glDeleteVertexArrays(1, [self.vao])
        GL.glDeleteBuffers(1, list(self.vbo.values()))
        if self.ebo is not None:
            GL.glDeleteBuffers(1, [self.ebo])

    def activate(self):
        GL.glBindVertexArray(self.vao)  # activated

    def deactivate(self):
        GL.glBindVertexArray(0)  # activated


class UManager(object):
    def __init__(self, shader):
        self.shader = shader
        self.textures = {}

    @staticmethod
    def load_texture(filename):
        texture = cv2.cvtColor(cv2.imread(filename, 1), cv2.COLOR_BGR2RGB)
        return texture

    def _get_texture_loc(self):
        if not bool(self.textures):
            return 0
        else:
            locs = list(self.textures.keys())
            locs.sort(reverse=True)
            ret_id = locs[0] + 1
            return ret_id

    &quot;&quot;&quot;
    * first call to setup_texture: activate GL.GL_TEXTURE0
        &gt; use GL.glUniform1i to associate the activated texture to the texture in shading program (see fragment shader)
    * second call to setup_texture: activate GL.GL_TEXTURE1
        &gt; use GL.glUniform1i to associate the activated texture to the texture in shading program (see fragment shader)
    * second call to setup_texture: activate GL.GL_TEXTURE2
        &gt; use GL.glUniform1i to associate the activated texture to the texture in shading program (see fragment shader)
    and so on
    
    &quot;&quot;&quot;

    def setup_texture(self, sampler_name, image_file):
        rgb_image = UManager.load_texture(image_file)

        GL.glUseProgram(self.shader.render_idx)  # must call before calling to GL.glUniform1i
        texture_idx = GL.glGenTextures(1)
        binding_loc = self._get_texture_loc()
        self.textures[binding_loc] = {}
        self.textures[binding_loc][&quot;id&quot;] = texture_idx
        self.textures[binding_loc][&quot;name&quot;] = sampler_name

        GL.glActiveTexture(GL.GL_TEXTURE0 + binding_loc)  # activate texture GL.GL_TEXTURE0, GL.GL_TEXTURE1, ...
        GL.glBindTexture(GL.GL_TEXTURE_2D, texture_idx)
        GL.glUniform1i(GL.glGetUniformLocation(self.shader.render_idx, sampler_name), binding_loc)

        GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB,
                        rgb_image.shape[1], rgb_image.shape[0], 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, rgb_image)
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR)
        GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR)

    def upload_uniform_matrix4fv(self, matrix, name, transpose=True):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniformMatrix4fv(location, 1, transpose, matrix)

    def upload_uniform_matrix3fv(self, matrix, name, transpose=False):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniformMatrix3fv(location, 1, transpose, matrix)

    def upload_uniform_vector4fv(self, vector, name):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniform4fv(location, 1, vector)

    def upload_uniform_vector3fv(self, vector, name):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniform3fv(location, 1, vector)

    def upload_uniform_scalar1f(self, scalar, name):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniform1f(location, scalar)

    def upload_uniform_scalar1i(self, scalar, name):
        GL.glUseProgram(self.shader.render_idx)
        location = GL.glGetUniformLocation(self.shader.render_idx, name)
        GL.glUniform1i(location, scalar)

  • viewer.py (file to run):
import OpenGL.GL as GL              # standard Python OpenGL wrapper
import glfw                         # lean windows system wrapper for OpenGL
import numpy as np                  # all matrix manipulations &amp; OpenGL args
from itertools import cycle   # cyclic iterator to easily toggle polygon rendering modes
from libs.transform import Trackball
from cube import *
# ------------  Viewer class &amp; windows management ------------------------------
class Viewer:
    &quot;&quot;&quot; GLFW viewer windows, with classic initialization &amp; graphics loop &quot;&quot;&quot;
    def __init__(self, width=800, height=800):
        self.fill_modes = cycle([GL.GL_LINE, GL.GL_POINT, GL.GL_FILL])
        
        # version hints: create GL windows with &gt;= OpenGL 3.3 and core profile
        glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
        glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
        glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, GL.GL_TRUE)
        glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
        glfw.window_hint(glfw.RESIZABLE, False)
        glfw.window_hint(glfw.DEPTH_BITS, 16)
        glfw.window_hint(glfw.DOUBLEBUFFER, True)
        self.win = glfw.create_window(width, height, &#39;Viewer&#39;, None, None)

        # make win&#39;s OpenGL context current; no OpenGL calls can happen before
        glfw.make_context_current(self.win)

        # initialize trackball
        self.trackball = Trackball()
        self.mouse = (0, 0)

        # register event handlers
        glfw.set_key_callback(self.win, self.on_key)
        glfw.set_cursor_pos_callback(self.win, self.on_mouse_move)
        glfw.set_scroll_callback(self.win, self.on_scroll)

        # useful message to check OpenGL renderer characteristics
        print(&#39;OpenGL&#39;, GL.glGetString(GL.GL_VERSION).decode() + &#39;, GLSL&#39;,
              GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION).decode() +
              &#39;, Renderer&#39;, GL.glGetString(GL.GL_RENDERER).decode())

        # initialize GL by setting viewport and default render characteristics
        GL.glClearColor(0.5, 0.5, 0.5, 0.1)
        #GL.glEnable(GL.GL_CULL_FACE)   # enable backface culling (Exercise 1)
        #GL.glFrontFace(GL.GL_CCW) # GL_CCW: default

        GL.glEnable(GL.GL_DEPTH_TEST)  # enable depth test (Exercise 1)
        GL.glDepthFunc(GL.GL_LESS)   # GL_LESS: default


        # initially empty list of object to draw
        self.drawables = []

    def run(self):
        &quot;&quot;&quot; Main render loop for this OpenGL windows &quot;&quot;&quot;
        while not glfw.window_should_close(self.win):
            # clear draw buffer
            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

            win_size = glfw.get_window_size(self.win)
            view = self.trackball.view_matrix()
            projection = self.trackball.projection_matrix(win_size)

            # draw our scene objects
            for drawable in self.drawables:
                drawable.draw(projection, view, None)

            # flush render commands, and swap draw buffers
            glfw.swap_buffers(self.win)

            # Poll for and process events
            glfw.poll_events()

    def add(self, *drawables):
        &quot;&quot;&quot; add objects to draw in this windows &quot;&quot;&quot;
        self.drawables.extend(drawables)

    def on_key(self, _win, key, _scancode, action, _mods):
        &quot;&quot;&quot; &#39;Q&#39; or &#39;Escape&#39; quits &quot;&quot;&quot;
        if action == glfw.PRESS or action == glfw.REPEAT:
            if key == glfw.KEY_ESCAPE or key == glfw.KEY_Q:
                glfw.set_window_should_close(self.win, True)

            if key == glfw.KEY_W:
                GL.glPolygonMode(GL.GL_FRONT_AND_BACK, next(self.fill_modes))

            for drawable in self.drawables:
                if hasattr(drawable, &#39;key_handler&#39;):
                    drawable.key_handler(key)

    def on_mouse_move(self, win, xpos, ypos):
        &quot;&quot;&quot; Rotate on left-click &amp; drag, pan on right-click &amp; drag &quot;&quot;&quot;
        old = self.mouse
        self.mouse = (xpos, glfw.get_window_size(win)[1] - ypos)
        if glfw.get_mouse_button(win, glfw.MOUSE_BUTTON_LEFT):
            self.trackball.drag(old, self.mouse, glfw.get_window_size(win))
        if glfw.get_mouse_button(win, glfw.MOUSE_BUTTON_RIGHT):
            self.trackball.pan(old, self.mouse)

    def on_scroll(self, win, _deltax, deltay):
        &quot;&quot;&quot; Scroll controls the camera distance to trackball center &quot;&quot;&quot;
        self.trackball.zoom(deltay, glfw.get_window_size(win)[1])



# -------------- main program and scene setup --------------------------------
def main():

    &quot;&quot;&quot; create windows, add shaders &amp; scene objects, then run rendering loop &quot;&quot;&quot;
    viewer = Viewer()
    # place instances of our basic objects

    model = Cube(&quot;./gouraud.vert&quot;, &quot;./gouraud.frag&quot;).setup()
    viewer.add(model)

    # start rendering loop
    viewer.run()


if __name__ == &#39;__main__&#39;:
    glfw.init()                # initialize windows system glfw
    main()                     # main function keeps variables locally scoped
    glfw.terminate()           # destroy all glfw windows and GL contexts

Hope someone can help me solve this conflict. <br>
P/s: I use MacOS whereas my friend uses Window.

答案1

得分: 0

问题在于<b>cube.py</b>中索引数组的数据类型。为了在各种操作系统上顺利运行,我们需要指定一个特定的数据类型。例如:self.indices = np.array([...], dtype=np.uint32)

英文:

The problem is the data type of index array in <b>cube.py</b>. We need to specify a specific type in order to run smoothly through various OSs. <br>
For example: self.indices = np.array([...], dtype=np.uint32).

huangapple
  • 本文由 发表于 2023年2月23日 20:41:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544989.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定