c++ - TinyGLTF-loaded GLTF file fails to render? - Stack Overflow

I'm trying to load a GLTF file using TinyGLTF:#include <tiny_gltf.h>#include <GLglew.h

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?

Share Improve this question edited Mar 27 at 13:43 genpfault 52.2k12 gold badges91 silver badges151 bronze badges asked Mar 27 at 13:24 Adem BudakAdem Budak 856 bronze badges 4
  • 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
Add a comment  | 

1 Answer 1

Reset to default 3

You 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.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744085725a4556136.html

相关推荐

  • c++ - TinyGLTF-loaded GLTF file fails to render? - Stack Overflow

    I'm trying to load a GLTF file using TinyGLTF:#include <tiny_gltf.h>#include <GLglew.h

    8天前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信