My first triangle works well if the color is specified in the fragment shader. When I add a vertex color to the buffer the triangle is always black.
A minimal code with the issue:
type
OGLfloat = float32
OGLuint = uint32
OGLint = int32
const
GLFW_CONTEXT_VERSION_MAJOR = 0x00022002
GLFW_CONTEXT_VERSION_MINOR = 0x00022003
GLFW_OPENGL_PROFILE = 0x00022008
GLFW_OPENGL_CORE_PROFILE = 0x00032001
const
GL_COLOR_BUFFER_BIT = 0x00004000
GL_DEPTH_BUFFER_BIT = 0x00000100
GL_ACCUM_BUFFER_BIT = 0x00000200
GL_STENCIL_BUFFER_BIT = 0x00000400
GL_ARRAY_BUFFER = 0x8892
GL_ELEMENT_ARRAY_BUFFER = 0x8893
GL_FALSE = 0.char
GL_STATIC_DRAW = 0x88E4
GL_FLOAT = 0x1406
GL_VERTEX_SHADER = 0x8B31
GL_COMPILE_STATUS = 0x8B81
GL_INFO_LOG_LENGTH = 0x8B84
GL_FRAGMENT_SHADER = 0x8B30
GL_LINK_STATUS = 0x8B82
GL_TRIANGLES = 0x0004
GL_UNSIGNED_INT= 0x1405
GL_VERSION = 0x1F02
const
POSITION_LENGTH = 3
COLOR_LENGTH = 3
const
WINDOW_W = 640
WINDOW_H = 480
var
colorDataOffset = 3 * sizeof(OGLfloat)
vertices = @[OGLfloat(0.0), 0.5, 0, 1, 1, 1,
0.5, -0.5, 0, 0, 0, 0,
-0.5, -0.5, 0, 0, 0, 0]
indices = @[OGLuint(0), 1 , 2]
# initialisation using glfw and glew
var glfwErr = glfwInit()
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3)
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3)
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)
var winHandle = glfwCreateWindow(WINDOW_W, WINDOW_H)
glfwMakeContextCurrent(winHandle)
var glewErr = glewInit()
# shaders sources
var
shadID:OGLuint
vertSrc:cstring = """
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out vec3 inColor;
void main()
{
gl_Position = vec4(aPos, 1.0f);
inColor = aColor;
}
"""
fragSrc:cstring = """
#version 330 core
out vec4 FragColor;
in vec3 inColor;
void main()
{
FragColor = vec4(inColor, 1.0f);
}
"""
# create the shader program
proc send_src(vert:var cstring, frag:var cstring):OGLuint =
var success:OGLint
# vertex
var vertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertexShader, 1, addr vert, nil)
glCompileShader(vertexShader)
# Check compilation errors.
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, addr success)
if bool(success) == false:
echo(" vertex shader compilation failed (send_src)")
else:
echo("vertexShader compiled (send_src)")
# fragment
var fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragmentShader, 1, addr frag, nil)
glCompileShader(fragmentShader)
# Check compilation errors.
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, addr success)
if bool(success) == false:
echo("fragment shader compilation failed (send_src)"
else:
echo("fragmentShader compiled (send_src)")
# Shader program
result = glCreateProgram()
glAttachShader(result, vertexShader)
glAttachShader(result, fragmentShader)
glLinkProgram(result)
# Check for linkage errors.
glGetProgramiv(result, GL_LINK_STATUS, addr success)
if success == 0:
echo ("program linking failed (send_src)")
else:
echo ("shader linked (send_src)")
glDeleteShader(vertexShader)
glDeleteShader(fragmentShader)
glViewport(0, 0, WINDOW_W, WINDOW_H)
shadID = send_src(vertSrc, fragSrc)
var VAO, VBO, EBO:OGLuint
glGenVertexArrays(1, addr VAO)
glGenBuffers(1, addr VBO)
glGenBuffers(1, addr EBO)
glBindVertexArray(VAO)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, vertices.len * sizeof(OGLfloat),
addr vertices[0], GL_STATIC_DRAW)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.len * sizeof(OGLuint),
addr indices[0], GL_STATIC_DRAW)
# Position layout
glVertexAttribPointer(0, POSITION_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
nil)
glEnableVertexAttribArray(0)
# Color layout
glVertexAttribPointer(1, COLOR_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
addr colorDataOffset)
glEnableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
glUseProgram(shadID)
while bool(glfwWindowShouldClose(winHandle)) == false:
glClearColor(0.2, 0.3, 0.3, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
glBindVertexArray(VAO)
glDrawElements(GL_TRIANGLES, OGLint(indices.len), GL_UNSIGNED_INT, nil)
glfwSwapBuffers(winHandle)
glfwPollEvents()
glDeleteVertexArrays(1, addr VAO)
glDeleteBuffers(1, addr VBO)
glDeleteBuffers(1, addr EBO)
glfwDestroyWindow(winHandle)
glfwTerminate()
First see OpenGL 4.6 API Compatibility Profile Specification; 10.3.9 Vertex Arrays in Buffer Objects; page 409
... When an array is sourced from a buffer object for a vertex attribute, [...] the offset set for the vertex buffer [...] is used as the offset in basic machine units of the first element in that buffer’s data store.
This means that the 6th parameter of glVertexAttribPointer
has to be the offset of the color attribute, encoded to a pointer
.
When you do addr colorDataOffset
in
glVertexAttribPointer(1, COLOR_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
addr colorDataOffset)
then you create a pointer
, but the value of the pointer is the address of colorDataOffset
- see The addr operator.
What you have to do is to cast colorDataOffset
to an pointer type by cast[pointer](colorDataOffset)
, the value of the pointer has to be the value of colorDataOffset
- see Type casts and Types:
glVertexAttribPointer(1, COLOR_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
cast[pointer](colorDataOffset))
User contributions licensed under CC BY-SA 3.0