I'm trying to load a GLTF file using TinyGLTF:
#include <tiny_gltf.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GLFW/glfw3.h>
#include <vector>
#include <string>
namespace tn = tinygltf;
void key(GLFWwindow* w, int key, int scancode, int action, int mods) {
switch(action) {
case GLFW_PRESS: {
if(key == GLFW_KEY_ESCAPE)
glfwSetWindowShouldClose(w, GLFW_TRUE);
} break;
case GLFW_RELEASE: break;
default: break;
}
}
const GLchar* vertexShaderSource = R"(
#version 460 core
#extension all: warn
#pragma optimize(off)
#pragma debug(on)
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec2 tPosition;
layout (location = 2) uniform mat4x4 transform;
layout (location = 3) uniform mat4x4 view;
layout (location = 4) uniform mat4x4 projection;
out vec2 textureCoordinate;
void main() {
textureCoordinate = tPosition;
gl_Position = projection * view * transform * vec4(vPosition, 1.0);
}
)";
const GLchar* fragmentShaderSource = R"(
#version 460 core
#extension all: warn
layout (binding = 0) uniform sampler2D s;
in vec2 textureCoordinate;
out vec4 color;
void main() {
// color = texture(s, textureCoordinate);
color = vec4(1.0);
}
)";
void fillArrayBuffers(const tn::Model& model, GLuint programID, GLuint vertexArrayID) {
int defaultSceneIndex = model.defaultScene;
const tn::Scene& defaultScene = model.scenes[defaultSceneIndex];
for(int nodeIndex : defaultScene.nodes) {
for(const tn::Primitive& primitive : model.meshes[model.nodes[nodeIndex].mesh].primitives) {
for(GLuint bindingIndex = -1; const auto& [attrib, attribAccessorIndex] : primitive.attributes) {
if(attrib == "POSITION") {
bindingIndex = glGetAttribLocation(programID, "vPosition");
}
if(attrib.starts_with("TEXCOORD")) {
bindingIndex = glGetAttribLocation(programID, "tPosition");
}
tn::Accessor accessor = model.accessors[attribAccessorIndex];
tn::BufferView bv = model.bufferViews[accessor.bufferView];
tn::Buffer buf = model.buffers[bv.buffer];
GLuint arrayBufferID;
glCreateBuffers(1, &arrayBufferID);
glBindBuffer(bv.target, arrayBufferID);
glBufferStorage(bv.target, bv.byteLength, std::data(buf.data) + bv.byteOffset, GL_MAP_READ_BIT);
glVertexArrayVertexBuffer(vertexArrayID, bindingIndex, arrayBufferID, bv.byteOffset, accessor.ByteStride(bv));
glVertexArrayAttribFormat(vertexArrayID, bindingIndex, accessor.count, accessor.componentType, accessor.normalized,
accessor.byteOffset);
glEnableVertexArrayAttrib(vertexArrayID, bindingIndex);
} // end for
}
}
}
void fillElementBuffers(const tn::Model& model, std::vector<GLuint>& elementBufferIDs) {
int defaultSceneIndex = model.defaultScene;
const tn::Scene& defaultScene = model.scenes[defaultSceneIndex];
for(int nodeIndex : defaultScene.nodes) {
const tn::Node& node = model.nodes[nodeIndex];
int meshIndex = node.mesh;
const tn::Mesh& mesh = model.meshes[meshIndex];
for(const tn::Primitive& primitive : mesh.primitives) {
tn::Accessor accessor = model.accessors[primitive.indices];
tn::BufferView bv = model.bufferViews[accessor.bufferView];
tn::Buffer buf = model.buffers[bv.buffer];
GLuint id;
glCreateBuffers(1, &id);
glBindBuffer(bv.target, id);
elementBufferIDs.push_back(id);
glBufferStorage(bv.target, bv.byteLength, std::data(buf.data) + bv.byteOffset, GL_MAP_READ_BIT);
}
}
}
int main(int argc, const char* argv[]) {
int ret = glfwInit();
assert(ret == GLFW_TRUE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, GLFW_LOSE_CONTEXT_ON_RESET);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
int win_width = 580, win_height = 325;
GLFWwindow* window = glfwCreateWindow(win_width, win_height, "sth", nullptr, nullptr);
glfwMakeContextCurrent(window);
GLenum err = glewInit();
assert(GLEW_OK == err);
glfwSetKeyCallback(window, key);
tn::Model model;
std::string errors;
std::string warnings;
bool ret_ = tn::TinyGLTF{}.LoadASCIIFromFile(&model, &errors, &warnings, "./models/Triangle/glTF/Triangle.gltf");
assert(ret_);
assert(std::empty(errors));
assert(std::empty(warnings));
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShaderID);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShaderID);
GLuint programID = glCreateProgram();
glAttachShader(programID, vertexShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
glUseProgram(programID);
GLuint vertexArrayID;
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
int defaultSceneIndex = model.defaultScene;
const tn::Scene& defaultScene = model.scenes[defaultSceneIndex];
std::vector<GLuint> elementBufferIDs;
fillArrayBuffers(model, programID, vertexArrayID);
fillElementBuffers(model, elementBufferIDs);
assert(glGetError() == GL_NO_ERROR);
constexpr GLfloat value[] = {0.247, 0.45, 0.45, 1.0};
while(!glfwWindowShouldClose(window)) {
glClearBufferfv(GL_COLOR, 0, value);
glUseProgram(programID);
glBindVertexArray(vertexArrayID);
for(const tn::Mesh& m : model.meshes) {
for(const auto& primitive : m.primitives) {
tn::Accessor ac = model.accessors[primitive.indices];
tn::BufferView bv = model.bufferViews[ac.bufferView];
tn::Buffer buf = model.buffers[bv.buffer];
glDrawElements(primitive.mode, ac.count, ac.componentType,
(const void*)(std::data(buf.data) + bv.byteOffset + ac.byteOffset));
}
}
glfwPollEvents();
glfwSwapBuffers(window);
}
}
...but I failed to do so. The glGetError() returns no error but the screen output is just the cleared color. Any pointer?