Как установить фоновую шкалу серого для многострочных графиков в pyopengl? - PullRequest
1 голос
/ 18 февраля 2020

У меня есть массив 2-D numpy, который я построил в Pyopengl, используя Pyqt. Теперь я хочу установить фон в градациях серого таким образом, чтобы при перемещении линии вверх или вниз ее серый цвет изменял интенсивность фона. Я прилагаю изображения для поведения, которое я хочу. p

, но все, что я могу создать до сих пор, - это белый фон, подобный этому enter image description here

код, который я написал:

import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import sys


VS = '''
#version 450

layout(location = 0) in vec2 position;


uniform float right;
uniform float bottom;
uniform float left;
uniform float top;

void main() {
    const float far = 1.0;
    const float near = -1.0;

    mat4 testmat = mat4(
            vec4(2.0 / (right - left), 0, 0, 0),
            vec4(0, 2.0 / (top - bottom), 0, 0),
            vec4(0, 0, -2.0 / (far - near), 0),
            vec4(-(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1)
    );

    gl_Position = testmat * vec4(position.x, position.y, 0., 1.);

}
'''

FS = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.

uniform vec3 triangleColor;
out vec4 outColor;

void main()
{

    outColor = vec4(triangleColor, 1.0);

}


'''


def compile_vertex_shader(source):
    """Compile a vertex shader from source."""
    vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER)
    gl.glShaderSource(vertex_shader, source)
    gl.glCompileShader(vertex_shader)
    # check compilation error
    result = gl.glGetShaderiv(vertex_shader, gl.GL_COMPILE_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetShaderInfoLog(vertex_shader))
    return vertex_shader


def compile_fragment_shader(source):
    """Compile a fragment shader from source."""
    fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)
    gl.glShaderSource(fragment_shader, source)
    gl.glCompileShader(fragment_shader)

    result = gl.glGetShaderiv(fragment_shader, gl.GL_COMPILE_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetShaderInfoLog(fragment_shader))
    return fragment_shader


def link_shader_program(vertex_shader, fragment_shader):
    """Create a shader program with from compiled shaders."""
    program = gl.glCreateProgram()
    gl.glAttachShader(program, vertex_shader)
    gl.glAttachShader(program, fragment_shader)
    gl.glLinkProgram(program)

    result = gl.glGetProgramiv(program, gl.GL_LINK_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetProgramInfoLog(program))
    return program


class GLPlotWidget(QGLWidget):

    def __init__(self, *args):
        super(GLPlotWidget, self).__init__()
        self.width, self.height = 100, 100
        self.e = np.load('two.npy', mmap_mode='r')
        self.vbo = glvbo.VBO(self.e)
        self.count = self.vbo.shape[1]
        self.right, self.left, self.top, self.bottom = self.e[0, -1, 0].min(), self.e[0, 0, 0].max(), self.e[0, :,
                                                                                                     1].max(), self.e[-1,
                                                                                                               :,
                                                                                                               1].min()

        # self.data = np.zeros((10, 2))


        self.showMaximized()

    def initializeGL(self):

        vs = compile_vertex_shader(VS)
        fs = compile_fragment_shader(FS)
        self.shaders_program = link_shader_program(vs, fs)

    def ortho_view(self):

        right = gl.glGetUniformLocation(self.shaders_program, "right")
        gl.glUniform1f(right, self.right)

        left = gl.glGetUniformLocation(self.shaders_program, "left")
        gl.glUniform1f(left, self.left)

        top = gl.glGetUniformLocation(self.shaders_program, "top")
        gl.glUniform1f(top, self.top)

        bottom = gl.glGetUniformLocation(self.shaders_program, "bottom")
        gl.glUniform1f(bottom, self.bottom)


    def paintGL(self):
        self.resizeGL(self.width, self.height)
        gl.glDisable(gl.GL_LINE_STIPPLE)
        gl.glClearColor(1, 1,1, 0)
        gl.glClear(gl.GL_COLOR_BUFFER_BIT)
        self.vbo.bind()
        gl.glEnableVertexAttribArray(0)
        gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
        gl.glUseProgram(self.shaders_program)
        self.ortho_view()

        uni_color = gl.glGetUniformLocation(self.shaders_program, "triangleColor")

        for i in range(0, self.vbo.data.shape[0]):
            gl.glUniform3f(uni_color, 0, 0, 0)
            # gl.glLineWidth(1.8)
            gl.glDrawArrays(gl.GL_LINE_STRIP, i * self.count, self.count)
        self.vbo.unbind()

    def resizeGL(self, width, height):
        self.width, self.height = width, height
        gl.glViewport(0, 0, width, height)



def main():
    app = QApplication(sys.argv)
    editor = GLPlotWidget()
    editor.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

Может кто-нибудь предложить мне какой-либо метод для решения этой проблемы?

ссылка на файл https://drive.google.com/file/d/1y6w35kuMguR1YczK7yMJpXU86T6qtGSv/view?usp=sharing

edit: - Я пытался увеличить ширину линий точек и установить для них цвет, но результат даже не приблизился к удовлетворительному. enter image description here. и я не могу понять, как передать цвет в треугольниках?

1 Ответ

1 голос
/ 19 февраля 2020

Понял ... Я нарисовал треугольники и установил цвет, чтобы получить желаемый результат ..

import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import sys
import copy


VS = '''
#version 450

attribute vec2 position;
attribute vec3 a_Color;

out vec3 g_color;
void main() {

    gl_Position = vec4(position.x, position.y, 0., 1.);
    g_color = a_Color;
}
'''

FS = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.

in vec3 g_color;
out vec4 outColor;

void main()
{

    outColor = vec4(g_color, 1.0);

}


'''

VS1 = '''
#version 450

layout(location = 0) in vec2 position;

void main() {

    gl_Position = vec4(position.x, position.y, 0.0, 1.);

}
'''

FS1 = '''
#version 450
// Output variable of the fragment shader, which is a 4D vector containing the
// RGBA components of the pixel color.

uniform vec3 triangleColor;
out vec4 outColor;

void main()
{   

    outColor = vec4(triangleColor, 1.0);

}


'''


def compile_vertex_shader(source):
    """Compile a vertex shader from source."""
    vertex_shader = gl.glCreateShader(gl.GL_VERTEX_SHADER)
    gl.glShaderSource(vertex_shader, source)
    gl.glCompileShader(vertex_shader)
    # check compilation error
    result = gl.glGetShaderiv(vertex_shader, gl.GL_COMPILE_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetShaderInfoLog(vertex_shader))
    return vertex_shader


def compile_fragment_shader(source):
    """Compile a fragment shader from source."""
    fragment_shader = gl.glCreateShader(gl.GL_FRAGMENT_SHADER)
    gl.glShaderSource(fragment_shader, source)
    gl.glCompileShader(fragment_shader)

    result = gl.glGetShaderiv(fragment_shader, gl.GL_COMPILE_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetShaderInfoLog(fragment_shader))
    return fragment_shader


def link_shader_program(vertex_shader, fragment_shader):
    """Create a shader program with from compiled shaders."""
    program = gl.glCreateProgram()
    gl.glAttachShader(program, vertex_shader)
    gl.glAttachShader(program, fragment_shader)
    gl.glLinkProgram(program)

    result = gl.glGetProgramiv(program, gl.GL_LINK_STATUS)
    if not (result):
        raise RuntimeError(gl.glGetProgramInfoLog(program))
    return program


class GLPlotWidget(QGLWidget):

    def __init__(self, *args):
        super(GLPlotWidget, self).__init__()
        self.width, self.height = 100, 100
        self.we = np.load('two.npy', mmap_mode='r')
        self.e = copy.deepcopy(self.we[:, :, :])

        self.e[:, :, 1] = np.interp(self.e[:, :, 1], (self.e[:, :, 1].min(), self.e[:, :, 1].max()),
                                                                                  (-1, 1))

        self.e[:, :, 0] = np.interp(self.e[:, :, 0], (self.e[:, :, 0].min(), self.e[:, :, 0].max()),
                                                                                  (-1, +1))

        self.vbo = glvbo.VBO(self.e)
        self.count = self.vbo.shape[1]

        self.showMaximized()

    def initializeGL(self):

        self.greyscale_data()
        vs = compile_vertex_shader(VS1)
        fs = compile_fragment_shader(FS1)
        self.shaders_program_plot = link_shader_program(vs, fs)

    def greyscale_data(self):
        self.color = np.zeros((self.e.shape[1]*self.e.shape[0], 3), dtype=np.float32)
        for i in range(0, 24):
            a = self.e[i, :, 1].min()
            b = self.e[i, :, 1].max()
            c = np.interp(self.e[i, :, 1], (a, b), (0.15, 0.5))
            self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 0] = c
            self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 1] = c
            self.color[self.e.shape[1] * i:self.e.shape[1] * (i + 1), 2] = c

        self.elems = []
        b = self.e.shape[1]  # number of points per line
        a = self.e.shape[0]  # total number of arms

        for i in range(0, a - 1):
            for j in range(0, b - 1):
                self.elems += [j + b * i, j + b * i + 1, j + b * (i + 1)]
                self.elems += [j + b * (i + 1), j + b * (i + 1) + 1, j + b * i + 1]

        self.elems = np.array(self.elems, dtype=np.int32)
        # print(self.elems[0:100])
        vs = compile_vertex_shader(VS)
        fs = compile_fragment_shader(FS)
        self.shaders_program = link_shader_program(vs, fs)

        self.vertexbuffer = gl.glGenBuffers(1)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
        gl.glBufferData(gl.GL_ARRAY_BUFFER, self.e, gl.GL_DYNAMIC_DRAW)

        self.elementbuffer = gl.glGenBuffers(1)
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
        gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, self.elems, gl.GL_DYNAMIC_DRAW)

        self.colorbuffer = gl.glGenBuffers(1)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
        gl.glBufferData(gl.GL_ARRAY_BUFFER, self.color, gl.GL_DYNAMIC_DRAW)

    def ortho_view(self, i):

        right = gl.glGetUniformLocation(i, "right")
        gl.glUniform1f(right, self.right)

        left = gl.glGetUniformLocation(i, "left")
        gl.glUniform1f(left, self.left)

        top = gl.glGetUniformLocation(i, "top")
        gl.glUniform1f(top, self.top)

        bottom = gl.glGetUniformLocation(i, "bottom")
        gl.glUniform1f(bottom, self.bottom)

    def greyscale(self):
        gl.glUseProgram(self.shaders_program)

        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)

        stride = 0  # 3*self.e.itemsize
        offset = None  # ctypes.c_void_p(0)
        loc = gl.glGetAttribLocation(self.shaders_program, 'position')
        gl.glEnableVertexAttribArray(loc)
        gl.glVertexAttribPointer(loc, 2, gl.GL_FLOAT, False, stride, offset)

        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)

        loc = gl.glGetAttribLocation(self.shaders_program, 'a_Color')
        gl.glEnableVertexAttribArray(loc)
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.colorbuffer)
        gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
        gl.glDrawElements(gl.GL_TRIANGLE_STRIP, self.elems.size, gl.GL_UNSIGNED_INT, None)

    def paintGL(self):
        self.resizeGL(self.width, self.height)
        gl.glClearColor(1, 1, 1, 0)
        gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
        gl.glEnable(gl.GL_DEPTH_TEST)

        self.vbo.bind()
        gl.glEnableVertexAttribArray(0)
        gl.glVertexAttribPointer(0, 2, gl.GL_FLOAT, gl.GL_FALSE, 0, None)
        gl.glUseProgram(self.shaders_program_plot)

        uni_color = gl.glGetUniformLocation(self.shaders_program_plot, "triangleColor")

        for i in range(0, self.vbo.data.shape[0]):
            gl.glUniform3f(uni_color, 0, 0, 0)
            gl.glLineWidth(1)
            gl.glDrawArrays(gl.GL_LINE_STRIP, i * self.count, self.count)
        self.vbo.unbind()
        self.greyscale()
        gl.glUseProgram(0)

    def resizeGL(self, width, height):
        self.width, self.height = width, height
        gl.glViewport(0, 0, width, height)


def main():
    app = QApplication(sys.argv)
    editor = GLPlotWidget()
    editor.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
...