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.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744085725a4556136.html
评论列表(0条)