opengl - Opengl vertex color always leads to a black triangle
问题描述
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()
解决方案
先看OpenGL 4.6 API Compatibility Profile Specification;10.3.9 缓冲区对象中的顶点数组;第 409 页
...当数组来自顶点属性的缓冲区对象时,[...] 为顶点缓冲区设置的偏移量 [...] 用作该缓冲区中第一个元素的基本机器单位的偏移量数据存储。
这意味着 的第 6 个参数glVertexAttribPointer
必须是颜色属性的偏移量,编码为 a pointer
。
当你addr colorDataOffset
在
glVertexAttribPointer(1, COLOR_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
addr colorDataOffset)
然后你创建一个pointer
,但指针的值是地址colorDataOffset
- 参见addr 运算符。
你需要做的是通过转换 colorDataOffset
为指针类型cast[pointer](colorDataOffset)
,指针的值必须是值colorDataOffset
- 请参阅类型转换和类型:
glVertexAttribPointer(1, COLOR_LENGTH, GL_FLOAT, GL_FALSE, 6 * sizeof(OGLfloat),
cast[pointer](colorDataOffset))
推荐阅读
- javascript - 如何在按回车键使用 contenteditable 时多次提交表单
- java - 这段代码的问题在于输出。生产者生产不止一次。为什么以及如何解决它?
- scala - Scala:有没有一种方法可以将类型别名与它们别名的类型区别对待?
- c# - Unity - SendMessage,但用于变量而不是函数/方法
- wpf - Telerik RadMenuItem IsEnabled 没有持续刷新
- f# - 删除 F# 中嵌套列表中的第一个元素?
- python - 如何使用按钮将图像一张一张地添加到网格的每个单元格中
- java - 垂直直方图
- javascript - 如何注册一个 ServiceWorker 回来
- python-3.x - 我无法在我的 Mac 上的 python3 中导入熊猫