admin管理员组文章数量:1395424
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, accessorponentType, 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, acponentType,
(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?
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, accessorponentType, 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, acponentType,
(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?
- 1 There's zero error checking on most of your OpenGL commands? Run this under Renderdoc or apitrace to see if any errors pop up. – Botje Commented Mar 27 at 13:27
- Or at least a debug context. – genpfault Commented Mar 27 at 13:30
- @genpfault i did, but removed it just before the posting the question. – Adem Budak Commented Mar 27 at 13:53
- Is this an issue with your renderer, or with your loader ? (ps You should mainain a way to debug your OpenGL calls during development) – limserhane Commented Mar 27 at 14:31
1 Answer
Reset to default 3You don't set uniforms for transform matrices, so replace
gl_Position = projection * view * transform * vec4(vPosition, 1.0);
by
gl_Position = vec4(vPosition, 1.0);
to draw triangle mesh as the model defines it.
---
Model is stored in one buffer. It consists of vertex positions and indices. BufferView
is used to point concrete kind of data. Data of model need to be copied into GL buffers. Then properties of BufferView
are utilized: pointer to the beginning of buffer, offset to concrete data and its length. After model's data was copied, i.e. vertex positions and indices, you should render using the whole data of these buffers, with no any offsets.
First mistake is in:
glVertexArrayVertexBuffer(vertexArrayID, bindingIndex, arrayBufferID, bv.byteOffset /*<<<*/, accessor.ByteStride(bv));
should be replaced by:
glVertexArrayVertexBuffer(vertexArrayID, bindingIndex, arrayBufferID, 0, accessor.ByteStride(bv));
The second culprit is:
glDrawElements(primitive.mode, ac.count, acponentType,
(const void*)(std::data(buf.data) + bv.byteOffset + ac.byteOffset) /*<<<*/);
replace by:
glDrawElements(primitive.mode, ac.count, acponentType, 0);
by these modifications, data is read from the beginning of buffers, one with vertex positions and the second one with indices. You simply confused the method of accessing model's data with pointing data of GL buffers to be used when rendering.
本文标签: cTinyGLTFloaded GLTF file fails to renderStack Overflow
版权声明:本文标题:c++ - TinyGLTF-loaded GLTF file fails to render? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744085725a2588482.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论