Портирование JavaScript / WebGL на Python / OpenGL - PullRequest
0 голосов
/ 27 ноября 2018

Я портирую некоторый код WebGL в node / javascript на код PyOpenGL в python3.Хотя код Python открывает окно OpenGL, он не отображает прямоугольник с рисунком сетки.Я сократил программу до минимума для устранения неполадок, но не могу найти проблему.Любые идеи / указатели?

Ниже кода Python и ниже исходного кода JavaScript.

Python3:

import OpenGL
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
from OpenGL.GL.shaders import *
from OpenGL.GL.framebufferobjects import *
import numpy

class Viewport:
    base = None
    # Model object
    window=None
    windowsize=(256*3,144*3)

    def buildShader(self,txt, type):
        #print ("buildShader",txt,type)
        s = glCreateShader(type)
        glShaderSource(s, txt)
        glCompileShader(s)

        if (not glGetShaderiv(s, GL_COMPILE_STATUS)):
            raise RuntimeError ("Could not compile shader:" , glGetShaderInfoLog(s))
        return s

    def setUniforms(self,prog,modelvar,names):
        modelvar['uniform'] = {}
        for u in names:
            modelvar['uniform'][u] = glGetUniformLocation(prog, u)
        return modelvar

    def setAttribs(self,prog, modelvar,names):
        modelvar['attrib'] = {}
        for attrib in names:
            modelvar['attrib'][attrib]=glGetAttribLocation(prog,attrib)
        return modelvar

    def makeProgram(self,modelvar,vert, frag, uniforms, attribs):
        v = self.buildShader(vert, GL_VERTEX_SHADER)
        f = self.buildShader(frag, GL_FRAGMENT_SHADER)

        prog = glCreateProgram()
        glAttachShader(prog, v)
        glAttachShader(prog, f)
        glLinkProgram(prog)

        #if (not glGetProgramParameter(prog, GL_LINK_STATUS)):
        if (not glGetProgramiv(prog, GL_LINK_STATUS)):
            raise RuntimeError("Could not link program:" + glGetProgramInfoLog(prog))

        self.setUniforms(prog, modelvar, uniforms)
        self.setAttribs(prog, modelvar, attribs)

        return prog

    def makeBase(self):
        self.base = {}
        self.base['prog'] = self.makeProgram(
            self.base,
            open('base.vert').read(),
            open('base.frag').read(),
            ['view', 'zmin', 'aspect'], ['v'])

        self.base['vert'] = glGenBuffers(1) #createBuffer()
        glBindBuffer(GL_ARRAY_BUFFER, self.base['vert'])
        glBufferData(
            GL_ARRAY_BUFFER,
            numpy.array([-1, -1,
                        -1,  1,
                        1, -1,
                        1,  1],dtype=numpy.float32),
            GL_STATIC_DRAW)

        self.base['frac'] = 0.5
        return self.base

    def drawBase(self,base):
        glUseProgram(self.base['prog'])
        M=numpy.array([ 0.26 , 0.22 , 0.18 , 0, -0.4 , 0.13 , 0.11 , 0, 0 , 0.42 , -0.1 , 0, 0 , 0 , 0 , 1])
        glUniformMatrix4fv(self.base['uniform']['view'], 1, False, M)#self.viewMatrix())
        printer_aspectRatio=1.6
        glUniform1f(self.base['uniform']['aspect'], printer_aspectRatio)

        glBindBuffer(GL_ARRAY_BUFFER, self.base['vert'])
        glEnableVertexAttribArray(self.base['attrib']['v'])
        glVertexAttribPointer(self.base['attrib']['v'], 2, GL_FLOAT, False, 0, 0)

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)


    def draw(self):

        glClearColor(1, 1, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT)
        self.drawBase(self.base)
        glutSwapBuffers()



    def __init__(self):

        glutInit(sys.argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)

        glutInitWindowSize(self.windowsize[0],self.windowsize[1])    
        glutInitWindowPosition(0,0)    
        self.window=glutCreateWindow('hackathon-slicer')
        glutDisplayFunc(self.draw)

        glEnable(GL_DEPTH_TEST)

        self.base=self.makeBase()

        glutMainLoop()
        self.draw()

Файл base.frag:

varying /*mediump*/ vec2 uv;

void main() {
   /*mediump*/ float u = mod(uv.x * 10.0, 1.0);
   /*mediump*/ float v = mod(uv.y * 10.0, 1.0);
   /*mediump*/ float t = (u > 0.1 && u < 0.9 &&
                   v > 0.1 && v < 0.9) ? 0.3 : 0.5;
   gl_FragColor = vec4(t, t, t, 1);
}

Файл base.vert:

attribute vec2 v; // Vertex position

uniform mat4 view; // Model transform matrix
uniform /*mediump*/ float zmin; // Z position of plane
uniform /*mediump*/ float aspect; // Aspect ratio

varying /*mediump*/ vec2 uv;

void main() {
   gl_Position = view * vec4(v.x * aspect, v.y, zmin - 0.01, 1);
   gl_Position.w = (gl_Position.z + 1.0);
   uv = (vec2(v.x * aspect, v.y) + 1.0) / 2.0;
}

Код javascript использует те же файлы base.frag и vert, однако промежуточные слова не закомментированы.

Оригинальный код JavaScript:

'use strict';

let _ = require('underscore');
let glslify = require('glslify');

let ui = require('./ui.js');
let printer = require('./printer.js');

let canvas = document.getElementById("canvas");
let gl = canvas.getContext("experimental-webgl");

let base = makeBase();

function buildShader(txt, type){
    let s = gl.createShader(type);
    gl.shaderSource(s, txt);
    gl.compileShader(s);
    return s;
}

function setUniforms(prog, u){
    prog.uniform = {};
    _.each(u, function(u){ prog.uniform[u] = gl.getUniformLocation(prog, u); });
}

function setAttribs(prog, a){
    prog.attrib = {};
    _.each(a, function(a){ prog.attrib[a] = gl.getAttribLocation(prog, a); });
}

function makeProgram(vert, frag, uniforms, attribs){
    let v = buildShader(vert, gl.VERTEX_SHADER);
    let f = buildShader(frag, gl.FRAGMENT_SHADER);

    let prog = gl.createProgram();
    gl.attachShader(prog, v);
    gl.attachShader(prog, f);
    gl.linkProgram(prog);

    setUniforms(prog, uniforms);
    setAttribs(prog, attribs);

    return prog;
}

function makeBase(){
    let base = {};
    base.prog = makeProgram(
        glslify(__dirname + '/../shaders/base.vert'),
        glslify(__dirname + '/../shaders/base.frag'),
        ['view', 'zmin', 'aspect'], ['v']);

    base.vert = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, base.vert);
    gl.bufferData(
        gl.ARRAY_BUFFER,
        new Float32Array([-1, -1,
                          -1,  1,
                           1, -1,
                           1,  1]),
        gl.STATIC_DRAW);

    base.frac = 0.5;
    return base;
}


function drawBase(base){
    gl.useProgram(base.prog);
    let M=[ 0.26 , 0.22 , 0.18 , 0, -0.4 , 0.13 , 0.11 , 0, 0 , 0.42 , -0.1 , 0, 0 , 0 , 0 , 1];
    gl.uniformMatrix4fv(base.prog.uniform.view, false, M);
    gl.uniform1f(base.prog.uniform.aspect, printer.aspectRatio());

    gl.bindBuffer(gl.ARRAY_BUFFER, base.vert);
    gl.enableVertexAttribArray(base.prog.attrib.v);
    gl.vertexAttribPointer(base.prog.attrib.v, 2, gl.FLOAT, false, 0, 0);

    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}


function draw(){
    gl.clearColor(1, 1, 1, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    drawBase(base);
}

function init(){
    gl.enable(gl.DEPTH_TEST);
    draw();
}

module.exports = {'init': init};

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

Я обнаружил, что мне нужно закомментировать glEnable(GL_DEPTH_TEST) в init .Я не понимаю почему, но это работает: -)

0 голосов
/ 27 ноября 2018

Если буфер массива связан, то 6-й параметр glVertexAttribPointer обрабатывается как смещение байта в хранилище данных объекта буфера.Но тип параметра должен быть указателем.

В вашем случае смещение равно 0. Это означает, что вы должны использовать встроенную константу None

glVertexAttribPointer(self.base['attrib']['v'], 2, GL_FLOAT, False, 0, None)

или вы должны использовать ctypes.cast, который приводит 0 к типу ctypes.c_void_p:

glVertexAttribPointer(self.base['attrib']['v'], 2, GL_FLOAT, False, 0,
    ctypes.cast(0, ctypes.c_void_p))

Поскольку проверка глубинывключается

glEnable(GL_DEPTH_TEST)

Вы также должны очищать буфер глубины, в начале каждого кадра:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
...