PyOpenGL texture rendering black - python-3.x

I have been following an online tutorial on OpenGL lately to test integration of PyOpenGL into a PyQt5 application with QOpenGLWidget. I was able to follow every episode with no issues until the textures episode; I cannot get the texture to render at all.
My code is as follows (wrappers removed to make the code simpler, but I have tested it to make sure it is the same):
def FirstFrame():
positions = [
-0.5, -0.5, 0.0, 0.0,
+0.5, -0.5, 1.0, 0.0,
+0.5, +0.5, 1.0, 1.0,
-0.5, +0.5, 0.0, 1.0
]
indices = [
0, 1, 2,
2, 3, 0,
]
global g_vao
vao = g_vao = glGenVertexArrays(1)
glBindVertexArray(vao)
global g_posBuffer
posBuffer = g_posBuffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, posBuffer)
glBufferData(GL_ARRAY_BUFFER, (GLfloat * len(positions))(*positions), GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), c_void_p(0))
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), c_void_p(8))
global g_idxBuffer
idxBuffer = g_idxBuffer = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxBuffer)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLuint * len(indices))(*indices), GL_STATIC_DRAW)
vertexShader = """
#version 330 core
layout(location = 0) in vec4 position;
layout(location = 1) in vec2 texCoord;
out vec2 v_TexCoord;
void main()
{
gl_Position = position;
v_TexCoord = texCoord;
}
"""
fragmentShader = """
#version 330 core
layout(location = 0) out vec4 color;
layout(location = 1) out vec4 colorTemp;
in vec2 v_TexCoord;
uniform sampler2D u_Texture;
void main()
{
vec4 texColor = texture(u_Texture, v_TexCoord);
color = texColor;
}
"""
global g_shader
shader = g_shader = compileProgram(compileShader(vertexShader, GL_VERTEX_SHADER),
compileShader(fragmentShader, GL_FRAGMENT_SHADER))
glUseProgram(shader)
global g_data
g_data, width, height = ParseRGBA8DDS("ChernoLogo.dds") # Parses input DDS file and returns bytearray of flipped texture
localBuffer = (GLubyte * len(g_data)).from_buffer(g_data) # Making a copy instead of using from_buffer does not work either
global g_tex
tex = g_tex = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, tex)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer) # Passing g_data directly does not work either
glBindTexture(GL_TEXTURE_2D, 0)
glActiveTexture(GL_TEXTURE0 + 0)
glBindTexture(GL_TEXTURE_2D, tex)
global g_tex_loc
tex_loc = g_tex_loc = glGetUniformLocation(shader, "u_Texture")
assert tex_loc != -1
glUniform1i(tex_loc, 0)
def MainLoopIteration():
glClear(GL_COLOR_BUFFER_BIT)
global g_shader, g_r, g_vao, g_idxBuffer
glUseProgram(g_shader)
glBindVertexArray(g_vao)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_idxBuffer)
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, c_void_p(0))
I have tried color = vec4(v_TexCoord, 0.0, 1.0) and color = vec4(u_Texture, 0.0, 0.0, 1.0) (and binding to slot 1) in the fragment shader to make sure these variables are set correctly and indeed they are.
In fact, I have checked texColor and it looks to be (0.0, 0.0, 0.0, 1.0) for all pixels.
I have also verified the output of ParseRGBA8DDS() by hand and it looks to be correct.

I found the issue. This is something the tutorial does not mention, but I needed to rebind and reactivate the texture on each frame. Althought I'm not sure why it still works for the person giving the tutorial.

Related

How to set background greyscale of multiple line plots in pyopengl?

I have a 2-D numpy array that I have plotted in Pyopengl using Pyqt. Now I want to set The background of the plot greyscale such that when the line moves up or down, its background grey color changes intensity. I am attaching images for the behaviour I want.
but all I am able to create till now is with white background like this
the code that I have written is
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()
Can anyone suggest me any method to solve this problem?
file link https://drive.google.com/file/d/1y6w35kuMguR1YczK7yMJpXU86T6qtGSv/view?usp=sharing
edit:- I tried to increase linewidth of points and set color to them but the result is not even close to satisfactory.. and I am unable to understand how to pass color in triangles?
Got it...I have rendered triangles and set color to get the desired result..
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()

Implementing Ambient Occlusion in simple Voxel Renderer

I am currently trying to implement Ambient Occlusion in a simple Voxel Renderer, each block is rendered (unless not visible) with 24 vertices and 12 triangles, so no meshing of any kind.
I followed this tutorial on how ambient occlusion for minecraft-like worlds could work, but it didn't explain how to actually implement that in shaders / graphics programming, so what I've done so far are only my uneducated best guesses.
The basic idea is, for each vertex to generate a value from the surrounding blocks about how "dark" the ambient occlusion should be. (Nevermind my values being completely wrong currently). These are from 0 (no surroundings) to 3 (vertex completely surrounded) The picture in the tutorial I linked helps to explain that.
So I tried that, but it seems to not darken the area around a vertex, but instead the whole triangle, the vertex is in... How do I make it not do that? I am a total beginner in shaders and graphics programming, so any help is appreciated :D
Here is my vertex shader, the inputs are
position of vertex
normal of vertex
tex_coord in texture atlas
tile_uv: position on block (0 or 1 for left/right bottom/top)
the ambient_occlusion value
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 tex_coord;
layout(location = 3) in vec2 tile_uv;
layout(location = 4) in uint ambient_occlusion;
layout(location = 0) out vec3 v_position;
layout(location = 1) out vec3 v_normal;
layout(location = 2) out vec2 v_tex_coord;
layout(location = 3) out vec2 v_tile_uv;
layout(location = 4) out uint v_ambient_occlusion;
layout(set = 0, binding = 0) uniform Data {
mat4 world;
mat4 view;
mat4 proj;
vec2 tile_size;
} uniforms;
void main() {
mat4 worldview = uniforms.view * uniforms.world;
v_normal = mat3(transpose(inverse(uniforms.world))) * normal;
v_tex_coord = tex_coord;
v_tile_uv = tile_uv;
v_position = vec3(uniforms.world * vec4(position, 1.0));
v_ambient_occlusion = ambient_occlusion;
gl_Position = uniforms.proj * worldview * vec4(position.x, position.y, position.z, 1.0);
}
And here is my fragment shader:
#version 450
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec3 v_normal;
layout(location = 2) in vec2 v_tex_coord;
layout(location = 3) in vec2 v_tile_uv;
layout(location = 4) in flat uint v_ambient_occlusion;
layout(location = 0) out vec4 f_color;
layout(set = 0, binding = 1) uniform sampler2D block_texture;
void main() {
vec3 ao_color;
switch (v_ambient_occlusion) {
case 0: ao_color = vec3(1.0, 0.0, 0.0); break;
case 1: ao_color = vec3(0.0, 1.0, 0.0); break;
case 2: ao_color = vec3(0.0, 0.0, 1.0); break;
case 3: ao_color = vec3(1.0, 1.0, 1.0); break;
}
f_color = texture(block_texture, v_tex_coord);
f_color.rgb = mix(f_color.rgb, vec3(0.05, 0.05, 0.05), 0.3 * v_ambient_occlusion * distance(v_tile_uv, vec2(0.5)));
}
The "flat" part of this ...
layout(location = 4) in flat uint v_ambient_occlusion;
... means that the same value is used for the whole triangle (taken from the provoking vertex). If you want interpolation between the 3 per-vertex values then just remove the flat qualifier.
Note that currently this is an integer attribute value, which must be flat shaded, so you'll need to convert the input into a float too.

How to create surface from 3-D numpy array in Pyopengl?

I have created a 3-d numpy array consisting of X, Y, and Z axis coordinates. Now I am trying to create a surface using these points in opengl but all I have got success is in creating wire model something like this below . Can anyone suggest changes in my code to form actual 3-D surface from data?
Data file used link https://drive.google.com/open?id=1PWbNIt3xbchtQ9HIIS96k7ZjblzPO_wO
Code:-
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
import Backend_algo as Sb
import sys
import ctypes
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
VS = '''
attribute vec3 position;
uniform float right;
uniform float bottom;
uniform float left;
uniform float top;
uniform float far;
uniform float near;
void main() {
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, 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);
}
'''
class GLPlotWidget3D(QGLWidget):
def __init__(self, *args):
# QGLWidget.__init__(self)
super(GLPlotWidget3D, self).__init__()
# self.parent = args[0]
self.width, self.height = 100, 100
self.right, self.left, self.top, self.bottom = 21000, -21000, 10, -10
self.data = np.zeros((3, 10, 2))
self.vbo = glvbo.VBO(self.data)
self.showMaximized()
def initializeGL(self):
vs = Sb.compile_vertex_shader(VS)
fs = Sb.compile_fragment_shader(FS)
self.shaders_program = link_shader_program(vs, fs)
self.e = np.load(('three.npy'), mmap_mode='r')
self.e = np.array(self.e, dtype=np.float32)
self.right, self.left, self.top, self.bottom, self.far, self.near = self.e[:, :, 1].min(), self.e[:, : , 1].max(), self.e[:, : , 0].min(), self.e[:, : , 0].max(), self.e[:, : , 2].max(), self.e[:, : , 2].min()
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)
far = gl.glGetUniformLocation(self.shaders_program, "far")
gl.glUniform1f(far, self.far)
near = gl.glGetUniformLocation(self.shaders_program, "near")
gl.glUniform1f(near, self.near)
def paintGL(self):
self.resizeGL(self.width, self.height)
gl.glClearColor(0.2, 0.2, 0.2, 0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glUseProgram(self.shaders_program)
buffer = gl.glGenBuffers(1)
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, buffer)
stride = self.e.strides[0]
offset = ctypes.c_void_p(1)
loc = gl.glGetAttribLocation(self.shaders_program, "position")
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
gl.glBufferData(gl.GL_ARRAY_BUFFER, self.e.nbytes, self.e, gl.GL_DYNAMIC_DRAW)
gl.glDrawArrays(gl.GL_LINE_LOOP, 0, self.e.shape[0])
self.ortho_view()
uni_color = gl.glGetUniformLocation(self.shaders_program, "triangleColor")
gl.glUniform3f(uni_color, 0.9, 0.9, 0.9)
def resizeGL(self, width, height):
self.width, self.height = width, height
gl.glViewport(0, 0, width, height)
def main():
app = QApplication(sys.argv)
editor = GLPlotWidget3D()
editor.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
'three.npy' contains a 3 dimensional array (7782 x 24 x3) with the vertex coordinates of a tube. The 3rd dimension with a size of 3 contains the x, y and z coordinates of the vertices. The vertices are organized in 7782 rings with 24 point around the circumference.
Read the vertex coordinates to a flatten buffer (the numpy array is flatten automatically by glBufferData).
Generate an array of indices (indices of the vertex buffer). The indices describe GL_TRIANGLE_STRIP primitives which stack up 7781 rings. Each ring consisting of 24 quads around the circumference.
self.e = np.load(('three.npy'), mmap_mode='r')
self.e = np.array(self.e, dtype=np.float32)
self.elems = []
ring_c = self.e.shape[1]
slice_c = self.e.shape[0]
for si in range(slice_c-1):
self.elems += [si*ring_c, si*ring_c]
for ri in range(ring_c+1):
ie = ri % ring_c
self.elems += [ie+si*ring_c, ie+(si+1)*ring_c]
self.elems = np.array(self.elems, dtype=np.int32)
The x and y component of the vertices are in range [-10, 10], but the z component is in range [3, 29724672].
x min x max y min y max z min z max
-10.589109 10.517833 -10.464569 10.594374 29724672.0 3.1618009
I recommend to define a scale for the z coordinate:
self.scaleZ = 0.000001
Create a Vertex Buffer Object (GL_ARRAY_BUFFER) for the vertices and an Index buffer Object (GL_ELEMENT_ARRAY_BUFFER) for the indices:
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)
Specif the array of vertex coordinates. See Vertex Specification.
The stride and offset parameter of glVertexAttribPointer have to be 0.
stride specifies the byte offset between consecutive generic vertex attributes it has to be either 3*self.e.itemsize (12) or 0. 0 has a special meaning and and interprets the attributes as to be tightly packed. If stride is 0 it is computed by the size and type parameter.
offset hast to be ctypes.c_void_p(0) or None, because the offset of the 1 attribute in the array is 0.
In any case the unit of stride and offset is bytes.
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, self.vertexbuffer)
stride = 0 # 3*self.e.itemsize
offset = None # ctypes.c_void_p(0)
loc = self.attrib['position']
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
The primitive type is GL_TRIANGLE_STRIP and the index buffer has to be bound before the elements are drawn by glDrawElements:
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
self.perspective_view()
gl.glUniform3f(self.uniform['triangleColor'], 1, 1, 1)
gl.glDrawElements(gl.GL_TRIANGLE_STRIP, self.elems.size, gl.GL_UNSIGNED_INT, None)
Instead of specifying an Orthographic projection matrix in the vertex shader, I recommend to use matrix Uniform variable for the projection, respectively model and view transformation.
The projection matrix defines the projection of the 3 dimensional viewing volume to the 2 dimensional viewport. The view matrix defines the viewing position of view and viewing direction onto the scene. The model matrix defines the scale and animation of the mode.
attribute vec3 position;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main() {
gl_Position = u_proj * u_view * u_model * vec4(position, 1.0);
}
Get the attribute index and uniform locations after the shader program is linked:
vs = compile_vertex_shader(VS)
fs = compile_fragment_shader(FS)
self.shaders_program = link_shader_program(vs, fs)
self.attrib = { a : gl.glGetAttribLocation (self.shaders_program, a) for a in ['position'] }
print(self.attrib)
self.uniform = { u : gl.glGetUniformLocation (self.shaders_program, u) for u in ['u_model', 'u_view', 'u_proj', "triangleColor"] }
print(self.uniform)
For a 3D look, I recommend to use Perspective projection rather than Orthographic projection.
Use numpy.array or numpy.matrix to set the matrices.
# projection matrix
aspect, ta, near, far = self.width/self.height, np.tan(np.radians(90.0) / 2), 0.1, 50
proj = np.matrix(((1/ta/aspect, 0, 0, 0), (0, 1/ta, 0, 0), (0, 0, -(far+near)/(far-near), -1), (0, 0, -2*far*near/(far-near), 0)), np.float32)
# view matrix
view = np.matrix(((1, 0, 0, 0), (0, 0, -1, 0), (0, 1, 0, 0), (0, 0, -30, 1)), np.float32)
# model matrix
c, s = math.cos(self.angle), math.sin(self.angle)
model = scale
gl.glUniformMatrix4fv(self.uniform['u_proj'], 1, gl.GL_FALSE, proj)
gl.glUniformMatrix4fv(self.uniform['u_view'], 1, gl.GL_FALSE, view)
gl.glUniformMatrix4fv(self.uniform['u_model'], 1, gl.GL_FALSE, model)
Full example:
(The fragment shader tints the fragments dependent on their depth)
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvbo
from PyQt5.Qt import *
import numpy as np
#import Backend_algo as Sb
import sys
import ctypes
import os
import math
sourceFileDir = os.path.dirname(os.path.abspath(__file__))
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
VS = '''
attribute vec3 position;
uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;
void main() {
gl_Position = u_proj * u_view * u_model * vec4(position, 1.0);
}
'''
FS = '''
#version 450
out vec4 outColor;
uniform vec3 triangleColor;
void main()
{
float d = 1.0 - gl_FragCoord.z;
outColor = vec4(triangleColor * d, 1.0);
}
'''
class GLPlotWidget3D(QGLWidget):
def __init__(self, *args):
# QGLWidget.__init__(self)
super(GLPlotWidget3D, self).__init__()
# self.parent = args[0]
self.width, self.height = 100, 100
self.right, self.left, self.top, self.bottom = 21000, -21000, 10, -10
self.data = np.zeros((3, 10, 2))
self.vbo = glvbo.VBO(self.data)
self.showMaximized()
def initializeGL(self):
vs = compile_vertex_shader(VS)
fs = compile_fragment_shader(FS)
self.shaders_program = link_shader_program(vs, fs)
self.attrib = { a : gl.glGetAttribLocation (self.shaders_program, a) for a in ['position'] }
print(self.attrib)
self.uniform = { u : gl.glGetUniformLocation (self.shaders_program, u) for u in ['u_model', 'u_view', 'u_proj', "triangleColor"] }
print(self.uniform)
self.e = np.load((os.path.join(sourceFileDir,'three.npy')), mmap_mode='r')
self.e = np.array(self.e, dtype=np.float32)
print(self.e.shape)
self.elems = []
ring_c = self.e.shape[1]
slice_c = self.e.shape[0]
for si in range(slice_c-1):
self.elems += [si*ring_c, si*ring_c]
for ri in range(ring_c+1):
ie = ri % ring_c
self.elems += [ie+si*ring_c, ie+(si+1)*ring_c]
self.elems = np.array(self.elems, dtype=np.int32)
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.scaleZ = 0.000001
self.right, self.left, self.top, self.bottom, self.far, self.near = self.e[:, :, 1].min(), self.e[:, : , 1].max(), self.e[:, : , 0].min(), self.e[:, : , 0].max(), self.e[:, : , 2].max(), self.e[:, : , 2].min()
print(self.right, self.left, self.top, self.bottom, self.far, self.near)
self.far *= self.scaleZ
self.near *= self.scaleZ
self.angle = 0.0
self.GLtimer = QTimer()
self.GLtimer.setInterval(10)
self.GLtimer.timeout.connect(self.redraw)
self.GLtimer.start()
def redraw(self):
self.angle += 0.01
self.update()
def perspective_view(self):
# projection matrix
aspect, ta, near, far = self.width/self.height, np.tan(np.radians(90.0) / 2), 10, 50
proj = np.matrix(((1/ta/aspect, 0, 0, 0), (0, 1/ta, 0, 0), (0, 0, -(far+near)/(far-near), -1), (0, 0, -2*far*near/(far-near), 0)), np.float32)
# view matrix
view = np.matrix(((1, 0, 0, 0), (0, 0, -1, 0), (0, 1, 0, 0), (0, 0, -30, 1)), np.float32)
# model matrix
c, s = math.cos(self.angle), math.sin(self.angle)
scale = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, self.scaleZ, 0), (0, 0, 0, 1)), np.float32)
rotZ = np.array(((c, s, 0, 0), (-s, c, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)), np.float32)
rotY = np.matrix(((0, 0, 1, 0), (0, 1, 0, 0), (-1, 0, 0, 0), (0, 0, 0, 1)), np.float32)
trans = np.matrix(((1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, (self.near - self.far)/2, 1)), np.float32)
model = scale * trans * rotY * rotZ
gl.glUniformMatrix4fv(self.uniform['u_proj'], 1, gl.GL_FALSE, proj)
gl.glUniformMatrix4fv(self.uniform['u_view'], 1, gl.GL_FALSE, view)
gl.glUniformMatrix4fv(self.uniform['u_model'], 1, gl.GL_FALSE, model)
def paintGL(self):
self.resizeGL(self.width, self.height)
gl.glClearColor(0.2, 0.2, 0.2, 0)
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
gl.glEnable(gl.GL_DEPTH_TEST)
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 = self.attrib['position']
gl.glEnableVertexAttribArray(loc)
gl.glVertexAttribPointer(loc, 3, gl.GL_FLOAT, False, stride, offset)
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, self.elementbuffer)
self.perspective_view()
gl.glUniform3f(self.uniform['triangleColor'], 1, 1, 1)
#gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE)
gl.glDrawElements(gl.GL_TRIANGLE_STRIP, self.elems.size, gl.GL_UNSIGNED_INT, None)
def resizeGL(self, width, height):
self.width, self.height = width, height
gl.glViewport(0, 0, width, height)
def main():
app = QApplication(sys.argv)
editor = GLPlotWidget3D()
editor.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Inputs and Outputs of the Geometry Shader

I was wondering if anyone would be so kind as to pin-point the problem with my program. I am certain the setback has something to do with the way in which data is passed through the GS. If, for instance, the geometry shader is taken out of the code (modifying the other two stages to accommodate for the change as well), I end up with a operational pipeline. And if I modify the data input of the GS to accept PS_INPUT instead of VS_DATA, the program does not crash, but outputs a blank blue screen. My intent here is to create a collection of squares on a two-dimensional plane, so blank blue screens are not exactly what I am going for.
Texture2D txDiffuse[26] : register(t0);
SamplerState samLinear : register(s0); //For Texturing
#define AWR_MAX_SHADE_LAY 1024
cbuffer ConstantBuffer : register(b0)
{
float4 Matrix_Array[30];
matrix Screen;
float GM;
float GA;
float GD;
float epsilon;
}
// Includes Layer Data
cbuffer CBLayer : register(b1)
{
float4 Array_Fill_Color[AWR_MAX_SHADE_LAY];
float4 Array_Line_Color[AWR_MAX_SHADE_LAY];
float Array_Width[AWR_MAX_SHADE_LAY];
float Array_Line_Pattern[AWR_MAX_SHADE_LAY];
float Array_Z[AWR_MAX_SHADE_LAY];
float Array_Thickness[AWR_MAX_SHADE_LAY];
}
//Input for Vertex Shader
struct VS_DATA
{
float4 Pos : POSITION;
int M2W_index : M2W_INDEX;
int Layer_index : LAYER_INDEX;
};
//Input for Pixel Shader
struct PS_INPUT{
float4 Pos : SV_POSITION;
float4 Color : COLOR;
int Layer_index : LAYER_INDEX;
};
//Vertex Shader
VS_DATA VS(VS_DATA input)// Vertex Shader
{
VS_DATA output = (VS_DATA)0;
//Model to World Transform
float xm = input.Pos.x, yw = input.Pos.y, zm = input.Pos.z, ww = input.Pos.w, xw, zw;
float4 transformation = Matrix_Array[input.M2W_index];
xw = ((xm)*transformation.y - (zm)*transformation.x) + transformation.z;
zw = ((xm)*transformation.x + (zm)*transformation.y) + transformation.w;
//set color
int valid_index = input.Layer_index;
output.Color = Array_Fill_Color[valid_index];
output.Color.a = 0.0;
//output.Vertex_index = input.Vertex_index;
//output.Next_Vertex_index = input.Next_Vertex_index;
//Snapping process
float sgn_x = (xw >= 0) ? 1.0 : -1.0;
float sgn_z = (zw >= 0) ? 1.0 : -1.0;
int floored_x = (int)((xw + (sgn_x*GA) + epsilon)*GD);
int floored_z = (int)((zw + (sgn_z*GA) + epsilon)*GD);
output.Pos.x = ((float)floored_x)*GM;
output.Pos.y = yw;
output.Pos.z = ((float)floored_z)*GM;
output.Pos.w = ww;
int another_valid_index = input.Layer_index;
output.Layer_index = another_valid_index;
// Transform to Screen Space
output.Pos = mul(output.Pos, Screen);
return output;
}
[maxvertexcount(6)]
void GS_Line(line VS_DATA points[2], inout TriangleStream<PS_INPUT> output)
{
float4 p0 = points[0].Pos;
float4 p1 = points[1].Pos;
float w0 = p0.w;
float w1 = p1.w;
p0.xyz /= p0.w;
p1.xyz /= p1.w;
float3 line01 = p1 - p0;
float3 dir = normalize(line01);
float3 ratio = float3(700.0, 0.0, 700.0);
ratio = normalize(ratio);
float3 unit_z = normalize(float3(0.0, -1.0, 0.0));
float3 normal = normalize(cross(unit_z, dir) * ratio);
float width = 0.01;
PS_INPUT v[4];
float3 dir_offset = dir * ratio * width;
float3 normal_scaled = normal * ratio * width;
float3 p0_ex = p0 - dir_offset;
float3 p1_ex = p1 + dir_offset;
v[0].Pos = float4(p0_ex - normal_scaled, 1) * w0;
v[0].Color = float4(1.0, 1.0, 1.0, 1.0);
v[0].Layer_index = 1;
v[1].Pos = float4(p0_ex + normal_scaled, 1) * w0;
v[1].Color = float4(1.0, 1.0, 1.0, 1.0);
v[1].Layer_index = 1;
v[2].Pos = float4(p1_ex + normal_scaled, 1) * w1;
v[2].Color = float4(1.0, 1.0, 1.0, 1.0);
v[2].Layer_index = 1;
v[3].Pos = float4(p1_ex - normal_scaled, 1) * w1;
v[3].Color = float4(1.0, 1.0, 1.0, 1.0);
v[3].Layer_index = 1;
output.Append(v[2]);
output.Append(v[1]);
output.Append(v[0]);
output.RestartStrip();
output.Append(v[3]);
output.Append(v[2]);
output.Append(v[0]);
output.RestartStrip();
}
//Pixel Shader
float4 PS(PS_INPUT input) : SV_Target{
float2 Tex = float2(input.Pos.x / (8.0), input.Pos.y / (8.0));
int the_index = input.Layer_index;
float4 tex0 = txDiffuse[25].Sample(samLinear, Tex);
if (tex0.r > 0.0)
tex0 = float4(1.0, 1.0, 1.0, 1.0);
else
tex0 = float4(0.0, 0.0, 0.0, 0.0);
if (tex0.r == 0.0)
discard;
tex0 *= input.Color;
return tex0;
}
If you compile your vertex shader as it is, you will have the following error :
(line 53) : invalid subscript 'Color'
output.Color = Array_Fill_Color[valid_index];
output is of type VS_DATA which does not contain color.
If you change your VS definition as :
PS_INPUT VS(VS_DATA input)// Vertex Shader
{
PS_INPUT output = (PS_INPUT)0;
//rest of the code here
Then your vs will compile, but then you will have a mismatched layout with GS (GS still expects a line of VS_DATA as input, and now you provide PS_INPUT to it)
This will not give you any error until you draw (and generally runtime will silently fail, you would have a mismatch message in case debug layer is on)
So you also need to modify your GS to accept PS_INPUT as input eg:
[maxvertexcount(6)]
void GS_Line(line PS_INPUT points[2], inout TriangleStream<PS_INPUT> output)

Problem when trying to use simple Shaders + VBOs

Hello I'm trying to convert the following functions to a VBO based function for learning purposes, it displays a static texture on screen. I'm using OpenGL ES 2.0 with shaders on the iPhone (should be almost the same than regular OpenGL in this case), this is what I got working:
//Works!
- (void) drawAtPoint:(CGPoint)point depth:(CGFloat)depth
{
GLfloat coordinates[] = {
0, 1,
1, 1,
0, 0,
1, 0
};
GLfloat width = (GLfloat)_width * _maxS,
height = (GLfloat)_height * _maxT;
GLfloat vertices[] = {
-width / 2 + point.x, -height / 2 + point.y,
width / 2 + point.x, -height / 2 + point.y,
-width / 2 + point.x, height / 2 + point.y,
width / 2 + point.x, height / 2 + point.y,
};
glBindTexture(GL_TEXTURE_2D, _name);
//Attrib position and attrib_tex coord are handles for the shader attributes
glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(ATTRIB_POSITION);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, coordinates);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
I tried to do this to convert to a VBO however I don't see anything displaying on-screen with this version:
//Doesn't display anything
- (void) drawAtPoint:(CGPoint)point depth:(CGFloat)depth
{
GLfloat width = (GLfloat)_width * _maxS,
height = (GLfloat)_height * _maxT;
GLfloat position[] = {
-width / 2 + point.x, -height / 2 + point.y,
width / 2 + point.x, -height / 2 + point.y,
-width / 2 + point.x, height / 2 + point.y,
width / 2 + point.x, height / 2 + point.y,
}; //Texture on-screen position ( each vertex is x,y in on-screen coords )
GLfloat coordinates[] = {
0, 1,
1, 1,
0, 0,
1, 0
}; // Texture coords from 0 to 1
glBindVertexArrayOES(vao);
glGenVertexArraysOES(1, &vao);
glGenBuffers(2, vbo);
//Buffer 1
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), position, GL_STATIC_DRAW);
glEnableVertexAttribArray(ATTRIB_POSITION);
glVertexAttribPointer(ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, position);
//Buffer 2
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), coordinates, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(ATTRIB_TEXCOORD);
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, coordinates);
//Draw
glBindVertexArrayOES(vao);
glBindTexture(GL_TEXTURE_2D, _name);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
In both cases I'm using this simple Vertex Shader
//Vertex Shader
attribute vec2 position;//Bound to ATTRIB_POSITION
attribute vec4 color;
attribute vec2 texcoord;//Bound to ATTRIB_TEXCOORD
varying vec2 texcoordVarying;
uniform mat4 mvp;
void main()
{
//You CAN'T use transpose before in glUniformMatrix4fv so... here it goes.
gl_Position = mvp * vec4(position.x, position.y, 0.0, 1.0);
texcoordVarying = texcoord;
}
The gl_Position is equal to product of mvp * vec4 because I'm simulating glOrthof in 2D with that mvp
And this Fragment Shader
//Fragment Shader
uniform sampler2D sampler;
varying mediump vec2 texcoordVarying;
void main()
{
gl_FragColor = texture2D(sampler, texcoordVarying);
}
I really need help with this, maybe my shaders are wrong for the second case ?
thanks in advance.
Everything is right, except the glVertexAttribPointer call.
When you have a VBO bound, the last parameter o glVertexAttribPointer is used as an offset into the VBO, as a pointer (the pointer value is the offset). So, your data is at the start of the VBO, so the last parameter should be 0 (NULL) for both calls.

Resources