Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I'm trying to build a voxel engine, and to do this I have to create hundreds of thousands of voxels, and I was hoping I could use instanced rendering. However, on rendering, the shape is completely disfigured, and not the expected cube shape:
And with several voxels:
This is what my code looks like:
chunk.hpp
#pragma once
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include "voxel.hpp"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using std::vector;
using glm::mat4;
using glm::vec3;
class Chunk {
vec3 centerPoint;
int voxelNum;
int shaderProgram;
unsigned int VBO, EBO, VAO;
mat4 VP;
public:
Chunk(vec3 center, float radius, int rinv);
void setVP(mat4 vp);
void draw();
};
chunk.cpp
#include "chunk.hpp"
#include <stdlib.h>
Chunk::Chunk(vec3 centerPoint, float radius, int rinv) {
vec3 endPoint(centerPoint.x - radius, centerPoint.y - radius, centerPoint.z - radius);
float distVox = 2 * radius/rinv;
voxelNum = pow(rinv, 3);
mat4* modelMatrices = new mat4[voxelNum];
srand(glfwGetTime()); // initialize random seed
for (int z = 0; z < rinv; z++) {
for (int y = 0; y < rinv; y++) {
for (int x = 0; x < rinv; x++) {
glm::mat4 model = glm::mat4(1.0f);
model = translate(model, vec3(endPoint.x + (x + 0.5) * distVox, endPoint.y + (y + 0.5) * distVox, endPoint.z + (z + 0.5) * distVox));
model = scale(model, vec3(radius));
int index = x + y * rinv + z * pow(rinv, 2);
modelMatrices[index] = model;
}
}
}
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 3) in mat4 aInstanceMatrix;\n"
"uniform mat4 VP;\n"
"void main()\n"
"{\n"
" gl_Position = VP * aInstanceMatrix * vec4(aPos, 1.0);\n"
"}\n\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec3 color;\n"
"void main()\n"
"{\n"
" FragColor = vec4(color, 1.0f);\n"
"}\n\0";
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
vec3 voxCenterPoint(0.0f);
float voxRadius = 1.0f;
vec3 maxV(voxCenterPoint.x + voxRadius, voxCenterPoint.y + voxRadius, voxCenterPoint.z + voxRadius);
vec3 minV(voxCenterPoint.x - voxRadius, voxCenterPoint.y - voxRadius, voxCenterPoint.z - voxRadius);
vec3 vertices[8] = {
vec3(maxV.x, maxV.y, maxV.z),
vec3(maxV.x, maxV.y, minV.z),
vec3(maxV.x, minV.y, minV.z),
vec3(maxV.x, minV.y, maxV.z),
vec3(minV.x, minV.y, maxV.z),
vec3(minV.x, maxV.y, maxV.z),
vec3(minV.x, maxV.y, minV.z),
vec3(minV.x, minV.y, minV.z),
};
unsigned int indices[36] = {
0, 2, 1, // maxV.x
0, 2, 3,
2, 6, 1, // minV.z
2, 6, 7,
2, 4, 3, // minV.y
2, 4, 7,
4, 6, 5, // minV.x
4, 6, 7,
1, 5, 0, // maxV.y
1, 5, 6,
0, 4, 3, // maxV.z
0, 4, 5,
};
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// // set the vertex attribute pointers
// // vertex Positions
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vec3), (void*)0);
// set attribute pointers for matrix (4 times vec4)
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) * 2));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) * 3));
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);
glBufferData(GL_ARRAY_BUFFER, voxelNum * sizeof(mat4), &modelMatrices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Chunk::setVP(mat4 vp) {
VP = vp;
}
void Chunk::draw() {
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "VP"), 1, GL_FALSE, &VP[0][0]);
glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, voxelNum);
glBindVertexArray(0);
}
main.cpp
#include <iostream>
using namespace std;
#include "chunk.hpp"
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
//Global Variables
GLFWwindow* window;
const char* SCR_TITLE = "WORKINGPLANET";
const int SCR_WIDTH = 500, SCR_HEIGHT = 500;
float x_rot = 0.0f;
float y_rot = 0.0f;
float y_rot_clamp = 89.999f;
// timing
float deltaTime = 0.0f; // time between current frame and last frame
float lastFrame = 0.0f;
void mouseCallback(GLFWwindow *window, int button, int action, int mods);
vec3 X_AXIS = vec3(1.0f, 0.0f, 0.0f);
vec3 Y_AXIS = vec3(0.0f, 1.0f, 0.0f);
//Main Program
int main()
{
//Constructor Code
if(!glfwInit())
{
cerr << "Error!!GLFW";
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
if(!(window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, SCR_TITLE, NULL, NULL)))
{
cerr << "Error!!GLFW window";
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cout << "Failed to initialize OpenGL context" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
Chunk chunk(vec3(0.0f), 0.5, 2);
mat4 view = mat4(1.0);
vec3 cameraPos = glm::vec3(0.0f, 0.0f, 4.0f);
view = lookAt(cameraPos, vec3(0,0,0), vec3(0,1,0));
//Loop Events
while(!glfwWindowShouldClose(window))
{
// per-frame time logic
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Tweak these values to change the sensitivity
float scale_x = 7.0f / SCR_WIDTH;
float scale_y = 7.0f / SCR_HEIGHT;
float rotSpeed = 350.0f;
float rot = scale_x * rotSpeed;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
rot = scale_y * rotSpeed;
if (y_rot + rot > y_rot_clamp)
rot = y_rot_clamp - y_rot;
view = rotate(view, (float)radians(rot), X_AXIS);
y_rot += rot;
} if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
rot = scale_y * rotSpeed;
if (y_rot - rot < -y_rot_clamp)
rot = y_rot + y_rot_clamp;
view = rotate(view, (float)radians(-rot), X_AXIS);
y_rot -= rot;
} if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
view = rotate(view, (float)radians(-rot), Y_AXIS);
x_rot -= rot;
} if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
view = rotate(view, (float)radians(rot), Y_AXIS);
x_rot += rot;
} if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
view = lookAt(cameraPos, vec3(0,0,0), vec3(0,1,0));
x_rot = 0.0f;
y_rot = 0.0f;
}
mat4 projection = perspective(radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
//Rendering
chunk.setVP(projection * view);
chunk.draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
At first I thought this could be an indices issue, but trying to modify them only revealed that vertices seemed to be out of order. Trying a vector changed nothing (as expected).
Trying to modify the modelMatrices also resulted in nothing of consequence.
The last time, you used the geometry also as transformation matrices. This time, you use the transformation matrices also as geometry.
Here you fill VBO with the vertex data:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
Now you set up your position pattribute to source the data from this VBO, so far, so good:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vec3), (void*)0);
Now, you set up your instane attributes 3 to 7, to also source the vertex data from your VBO:
// set attribute pointers for matrix (4 times vec4)
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
[...]
This already doesn't make any sense, but it only gets worse:
glBufferData(GL_ARRAY_BUFFER, voxelNum * sizeof(mat4), &modelMatrices[0], GL_STATIC_DRAW);
Now you have completely overwritten your geometry data with the transformation matrices, the actual geometry of your cube is lost. Your position attribute still points into VBO, so it will interpret the matrices as the geometry.
In the scheme you're using, you need two distinct VBOs, one for the geomerty data, and one for the per-oinstance transformation matrices. (You can of course also store both data in one VBO, but than you have to deal yourself with storing both parts without overwriting each other, and with supplying the correct offsets, so let's ignore that option here).
When I wrote (empahsis added by me now):
You need to move the attribute setup for the instanced attribute
out of Voxel::generateElement() and into Chunk::Chunk() so you can
tell it to use that VBO as source for the model matrices.
I meant exactly that. You need to setup up the instanced attributes 3 to 7 - and only these - to source the model matrix VBO, and leave the position attribute to source from the geometry VBO where it initially was.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I try to move my object only on the y-axis. I created an array with 4 Vertex and put the data in my vertexBuffer and bind it. Also I created a vertexArray and an indexBuffer to bind them and draw my quad.
Now I change only the y-coordinate of my quad and want to overwrite the data in my vertexBuffer with glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject); but nothing happens. Only when I fill the data before I bind my indexbuffer it will work. After that I can't change the VertexBuffer.
Here is my code of my main
#include <iostream>
#include "headerData/VertexBuffer.h"
#include "headerData/IndexBuffer.h"
#include "headerData/Shader.h"
#include "headerData/VertexLayout.h"
#include "headerData/VertexArray.h"
#include "headerData/Road.h"
#include "glm.hpp"
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
static struct VertexShader {
std::string defaultShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f)*scale;\n"
"}\0";
std::string yMoveShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"uniform vec4 transform;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y+transform.y, aPos.z, 1.0f)*scale;\n"
"}\0";
};
static struct FragmentShader {
std::string defaultShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 0.5f, 0.5f, 1.0);\n"
"}\n\0";
std::string greenShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 1.0f, 0.5f, 1.0);\n"
"}\n\0";
};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
VertexShader vertexShader;
FragmentShader fragmentShader;
Shader shaderCol(vertexShader.defaultShader, fragmentShader.defaultShader);
Shader shaderMove(vertexShader.yMoveShader, fragmentShader.greenShader);
shaderCol.bind();
//shaderMove.bind();
glm::mat4 scale = glm::ortho(-100.0f, 100.0f, -100.0f, 100.0f, -1.0f, 1.0f);
//glUniformMatrix4fv(glGetUniformLocation(shaderMove.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glUniformMatrix4fv(glGetUniformLocation(shaderCol.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glm::vec3 transform(0.0f, 0.0f, 0.0f);
float moveObject[] = {
20.0f, -50.0f, // top right
20.0f, -90.0f, // bottom right
-20.0f, -90.0f, // bottom left
-20.0f, -50.0f // top left
};
float colObject[] = {
2.0f, 2.0f, //top right
2.0f, -2.0f, //bottom right
-2.0f, 2.0f, //top left
-2.0, -2.0f //bot left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VA, VB, IB;
glGenVertexArrays(1, &VA);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//VertexBuffer vb;
//vb.bind(moveObject, 4 * 2 * sizeof(float));
//VertexBuffer
glGenBuffers(1, &VB);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, 8 * 2 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glBindVertexArray(VA);
//LAyout vom Buffer
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(0));
glEnableVertexAttribArray(0);
//VertexLayout layout;
//layout.layoutPush(3);
//VertexArray va;
//va.addBuffer(vb, layout);
//IndexBuffer ib;
//ib.bind(indices, 6 * sizeof(unsigned int));
glGenBuffers(1, &IB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, IB);
//Parameter
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(0));
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Road road;
// render loop
// -----------
float time = 0;
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//shader.bind();
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//road.render();
//That not work
moveObject[1] += abs(90 * sin(glfwGetTime()));
moveObject[3] += abs(90 * sin(glfwGetTime()));
moveObject[5] += abs(90 * sin(glfwGetTime()));
moveObject[7] += abs(90 * sin(glfwGetTime()));
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject);
//transform.y = 90 * abs(sin(glfwGetTime()));
//glUniform4f(glGetUniformLocation(shaderMove.getShaderID(), "transform"), transform.x, transform.y, 0.0f, 1.0f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//glDeleteBuffers(1, &IB);
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
//glDeleteVertexArrays(1, &test);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
std::cout << "callback" << std::endl;
glViewport(0, 0, width, height);
}
When you execute this line
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject);
the data bound to GL_ARRAY_BUFFER on GPU is updated. But what data is it bound to? Look above
glBindBuffer(GL_ARRAY_BUFFER, IB);
You seem to bind your array of indices, while you probably meant
glBindBuffer(GL_ARRAY_BUFFER, VB);
When I use glm::scale to update the model matrix in my vertex shader, no matter what I do, it will always scale it down. Anyone know what I'm doing wrong? The image will sometimes flip up and down too.
The key == 'w' and key == 's' do the exact same thing despite the code being different, the goal is to make the model grow bigger by pressing W and smaller by pressing S. But right now it just gets smaller with both presses.
The relevant code used to scale according to key press is:
if (key == 'w') {
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 's') {
model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
The whole code is:
#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include <iostream>
#include <SOIL.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "OBJ.h"
const char* vs = "#version 330 core\n"
"layout (location = 0) in vec3 pos;\n"
"layout (location = 1) in vec2 texpos;\n"
"out vec2 texCoords;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(pos, 1);\n"
"texCoords = texpos;\n"
"}\0";
const char* fs = "#version 330 core\n"
"in vec2 texCoords;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex;\n"
"void main()\n"
"{\n"
"fragColor = texture(tex, texCoords);"
"}\0";
float verts[] = {
0, 1, 0, 0.5, 1,
-1, -1, 0, 0, 0,
1, -1, 0, 1, 0
};
unsigned short indices[] = {
0, 1, 2
};
unsigned int vao, vbo, ebo, prog, vert, frag, texid;
glm::mat4 model, view, projection;
void changeViewPort(int w, int h)
{
glViewport(0, 0, w, h);
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glBindTexture(GL_TEXTURE_2D, texid);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void initGL() {
//Context stuff
glViewport(0, 0, 800, 600);
glClearColor(0.5, 0.5, 0.5, 1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Shader stuff
int success;
prog = glCreateProgram();
vert = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert, 1, &vs, NULL);
glCompileShader(vert);
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
std::cout << "Vertex shader " << (success ? "compiled" : "not compiled") << std::endl;
frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag, 1, &fs, NULL);
glCompileShader(frag);
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
std::cout << "Fragment shader " << (success ? "compiled" : "not compiled") << std::endl;
glAttachShader(prog, vert);
glAttachShader(prog, frag);
glLinkProgram(prog);
glUseProgram(prog);
glGetShaderiv(prog, GL_LINK_STATUS, &success);
std::cout << "Program " << (success ? "linked" : "not linked") << std::endl;
glDeleteShader(vert);
glDeleteShader(frag);
//Vertex stuff
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//Texture stuff
int width, height;
unsigned char* texData = SOIL_load_image("brick.png", &width, &height, NULL, SOIL_LOAD_RGBA);
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (texData) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Texture not loaded." << std::endl;
}
glBindTexture(GL_TEXTURE_2D, 0);
SOIL_free_image_data(texData);
//Matrix stuff
//Model matrix
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int modelMatrix = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(modelMatrix, 1, GL_FALSE, glm::value_ptr(model));
//View matrix
view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0, 0, -3));
int viewMatrix = glGetUniformLocation(prog, "view");
glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(view));
//Projection matrix, something is messing up here
projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
int projectionMatrix = glGetUniformLocation(prog, "projection");
glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, glm::value_ptr(projection));
}
void input(unsigned char key, int x, int y) {
if (key == 'a') {
model = glm::translate(model, glm::vec3(-0.5, 0, 0));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'd') {
model = glm::translate(model, glm::vec3(0.5, 0, 0));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'w') {
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 's') {
model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'q') {
model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0, 0, 1));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'e') {
model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(0, 0, 1));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
glutPostRedisplay();
}
int main(int argc, char* argv[]) {
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OBJ Viewer");
glutReshapeFunc(changeViewPort);
glutDisplayFunc(render);
glutKeyboardFunc(input);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW error");
return 1;
}
initGL();
glutMainLoop();
return 0;
}
It's not clear what you mean by half a coordinate, but it's clear that you want to change size by an absolute value, while the scale matrix is relative to the model. In fact, you should also consider what happens when the model is not around the origin - the space between the model and the origin is also scaled!
to get an absolute size change, I'd suggest to calculate the model's bounding box, and the desired size. The ratio of the two will go into the scale function. For example, if the model's bounding box is (20, 10, 5), and you want it to be (19.5, 9.5, 4.5), then you need scale(20/19.5, 10/19.5, 5/4.5).
Calculating a model's bounding box should be done after each rotation change. In the general case, you can do it on the CPU, going over the CPU-transformed vertices and taking the min and max of each coordinate. There may be faster methods depending on your special circumstances.
When you scale your model, you pass the model matrix and scale vector to glm::scale function. When you do model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));, this means multiplying your model size by 0.5, instead of adding. Same with -0.5. That's why your model always scales down.
As far as I understand, you want your model to scale up and down by 50 % when pressing 'w' and 's' respectively. So, simply use model = glm::scale(model, glm::vec3(1.5, 1.5, 1.5)); to scale up and model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5)); to scale down.
I am sorry to carry this here, but I spend around 7 hours maybe for a really easy thing. Maybe some of you identify the problem.
I try to render some pixel coordinates to screen. The code is below.
For a 800x600 screen. Simply trying to calculate the position of the lines, and then to render it to the screen.
For example: Point A(400, 300, 0) and point B(500,300,0) shall be a simple black line from the center of the screen to the right.
As I call this class function in render, I thought I might be creating a separate rendering session. However, when I write something such as glCleanColor, the background changes.
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#include <GL/glew.h>
#include <iostream>
#include <vector>
Vertex shader:
const GLchar *vertex_shader =
"#version 410\n"
"layout (location = 0) in vec3 pos;\n"
"layout (location = 1) in vec4 col;\n"
"uniform mat4 projection;\n"
"out vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" Frag_Color = col;\n"
" gl_Position =projection*vec4(pos.xyz,1);\n"
"}\n";
Fragment Shader:
const GLchar *fragment_shader =
"#version 410\n"
"in vec4 Frag_Color;\n"
"layout (location = 0) out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color;\n"
"}\n";
Vertex structure
struct Vrtx
{
float pos[3];
float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
};
coord axis class:
class CoordinateAxis
{
public:
void coordinate_axis()
{
vertices.resize(6);
for (int i = 0; i < 3; i++)
{
vertices[2 * i].pos[0] = 400;
vertices[2 * i].pos[1] = 300;
vertices[2 * i].pos[2] = 0;
}
vertices[1].pos[0] = 500;
vertices[1].pos[1] = 300;
vertices[1].pos[2] = 0;
vertices[3].pos[0] = 400;
vertices[3].pos[1] = 400;
vertices[3].pos[2] = 0;
vertices[3].pos[0] = 400;
vertices[3].pos[1] = 430;
vertices[3].pos[2] = 100;
setupRender();
glBindVertexArray(VAO);
glDrawElements(GL_LINE, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glUseProgram(0);
}
CoordinateAxis()
{
initShaderProgram();
};
private:
void initShaderProgram()
{
// Vertex shader
GLuint vHandle = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vHandle, 1, &vertex_shader, NULL);
glCompileShader(vHandle);
// Fragment shader
GLuint fHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fHandle, 1, &fragment_shader, NULL);
glCompileShader(fHandle);
// Create Program
handleProgram = glCreateProgram();
glAttachShader(handleProgram, vHandle);
glAttachShader(handleProgram, fHandle);
glLinkProgram(handleProgram);
attribLocationProj = glGetUniformLocation(handleProgram, "projection");
glGenVertexArrays(1, &VAO);
// CreateBuffers
glGenBuffers(1, &vboHandle);
glGenBuffers(1, &iboHandle);
}
void setupRender()
{
GLint last_viewport[4];
glGetIntegerv(GL_VIEWPORT, last_viewport);
float L = last_viewport[0];
float R = L + last_viewport[2];
float B = last_viewport[1];
float T = B + last_viewport[3];
const float ortho_projection[4][4] =
{
{2.0f / (R - L), 0.0f, 0.0f, 0.0f},
{0.0f, 2.0f / (T - B), 0.0f, 0.0f},
{0.0f, 0.0f, -1.0f, 0.0f},
{(R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f},
};
glUseProgram(handleProgram);
glUniformMatrix4fv(attribLocationProj, 1, GL_FALSE, &ortho_projection[0][0]);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboHandle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vrtx), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertices.size() * sizeof(Vrtx), 0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertices.size() * sizeof(Vrtx), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
}
std::vector<Vrtx> vertices;
std::vector<GLuint> indices;
GLuint handleProgram, VAO, vboHandle, iboHandle, attribLocationProj;
};
GL_LINE is not a valid primitive type. GL_LINE is a mode for glPolygonMode.
A valid line primitive type is GL_LINES:
glDrawElements(GL_LINE, 6, GL_UNSIGNED_INT, 0);
glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, 0);
Furthermore there is an issue when you set up the array of vertex attribute data by glVertexAttribPointer. The 5th parameter (strid) is the byte offset between consecutive attribute tuples, rather than the size of the buffer. sizeof(Vrtx) rather than vertices.size() * sizeof(Vrtx):
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vrtx), 0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vrtx), (void *)(3*sizeof(float)));
Note, the array of indices seems to be empty. Either initialize the array of indices:
indices = { 0, 1, 2, 3, 4, 5 };
or use glDrawArrays instead:
glDrawArrays(GL_LINES, 0, 6);
I'm trying to create a Mesh class that can generate a model for me and then calling that model in the createTriangle function. However, whenever I try creating the meshObj1 and meshObj2 and then pushing it to the meshVector, it does not want to render? Why is this happening?
Mesh.h
#ifndef MESH_H
#define MESH_H
#include "GL/glew.h"
class Mesh {
public:
Mesh();
~Mesh();
void createMesh(GLfloat *vertices, unsigned int *indices, unsigned int numOfVertices, unsigned int numOfIndices);
void renderMesh();
void clearMesh();
private:
GLuint VAO, VBO, IBO;
GLsizei indexCount;
};
#endif
Mesh.cpp
#include "Mesh.h"
Mesh::Mesh() {
VAO = 0;
VBO = 0;
IBO = 0;
indexCount = 0;
}
Mesh::~Mesh() {
clearMesh();
}
void Mesh::createMesh(GLfloat* vertices, unsigned int* indices, unsigned int numOfVertices, unsigned int numOfIndices) {
indexCount = numOfIndices;
//Binding
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//Information
//VBO Information
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0] * numOfVertices), vertices, GL_STATIC_DRAW);
//IBO Information
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices[0]) * numOfIndices, indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
//Unbinding
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::renderMesh() {
//Binding
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
//Rendering
glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0);
//Unbinding
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Mesh::clearMesh() {
if (VAO != 0) {
glDeleteVertexArrays(1, &VAO);
VAO = 0;
}
if (VBO != 0) {
glDeleteBuffers(1, &VBO);
VBO = 0;
}
if (IBO != 0) {
glDeleteBuffers(1, &IBO);
IBO = 0;
}
indexCount = 0;
}
Main.cpp
#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "glm/gtc/type_ptr.hpp"
#include <iostream>
#include <vector>
#include <memory>
#include "Mesh.h"
//Window dimensions
const GLint SCREEN_WIDTH = 1280, SCREEN_HEIGHT = 900;
GLuint shader, uniformModel, uniformProjection;
bool isMovingLeft = true;
float triOffset = 0.f;
float triMaxOffset = 0.7;
float triIncrement = 0.005;
std::vector<Mesh*> meshVector;
//Vertex shader
static const char* vShader = " \n\
#version 460 \n\
\n\
layout(location = 0) in vec3 pos; \n\
\n\
out vec4 vColor; \n\
\n\
uniform mat4 model; \n\
uniform mat4 projection; \n\
\n\
void main() { \n\
gl_Position = projection * model * vec4(pos, 1.0); \n\
vColor = vec4(clamp(pos, 0.f, 1.f), 1.f); \n\
}; \n\
";
//Fragment shader
static const char* fShader = " \n\
#version 460 \n\
\n\
in vec4 vColor; \n\
\n\
out vec4 color; \n\
\n\
void main() { \n\
color = vColor; \n\
}; \n\
";
void createTriangle() {
unsigned int indices[] = {
0, 3, 1,
1, 3, 2,
2, 3, 0,
0, 1, 2
};
//Points of the triangle
GLfloat vertices[] = {
-1.f, -1.f, 0.f,
0.f, -1.f, 1.f,
1.f, -1.f, 0.f,
0.f, 1.f, 0.f
};
Mesh* meshObj1 = new Mesh();
meshObj1->createMesh(vertices, indices, 12, 12);
meshVector.push_back(meshObj1);
Mesh* meshObj2 = new Mesh();
meshObj2->createMesh(vertices, indices, 12, 12);
meshVector.push_back(meshObj2);
}
void addShader(GLuint theProgram, const char* shaderCode, GLenum shaderType) {
GLuint theShader = glCreateShader(shaderType);
const GLchar* theCode[1];
theCode[0] = shaderCode;
GLint codeLength[1];
codeLength[0] = strlen(shaderCode);
glShaderSource(theShader, 1, theCode, codeLength);
glCompileShader(theShader);
//Getting error information for linking
GLint result = 0;
GLchar eLog[1024] = { 0 };
glGetShaderiv(theShader, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
glGetShaderInfoLog(theShader, sizeof(eLog), NULL, eLog);
std::cout << "Error compiling the " << shaderType << ' ' << eLog << '\n';
}
glAttachShader(theProgram, theShader);
}
void compileShaders() {
shader = glCreateProgram();
if (shader != GL_TRUE) {
std::cout << "Shader program error!\n";
}
//Adding shaders
addShader(shader, vShader, GL_VERTEX_SHADER);
addShader(shader, fShader, GL_FRAGMENT_SHADER);
//Getting error information for linking
GLint result = 0;
GLchar eLog[1024] = { 0 };
//Linking shader
glLinkProgram(shader);
//Shader linking status
glGetProgramiv(shader, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
glGetProgramInfoLog(shader, sizeof(eLog), NULL, eLog);
std::cout << "Error linking program! " << eLog << '\n';
}
//Gets shader ID and then binds it with the variable inside shader
uniformModel = glGetUniformLocation(shader, "model");
uniformProjection = glGetUniformLocation(shader, "projection");
}
int main() {
//Initialize GLFW
if (glfwInit() != GLFW_TRUE) {
std::cout << "GLFW init failed\n";
glfwTerminate();
}
//Setup GLFW window properties
//OpenGL version
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); //Large version
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4); //Small version
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //Detects any old OpenGL code, this will throw an error
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //Allows forward compatibility (between differnt OS)
//Creating window
GLFWwindow* window;
window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "OpenGL Test Window", NULL, NULL);
glfwSetWindowPos(window, 250, 100);
if (window == NULL) {
std::cout << "GLFW window creation failed!\n";
glfwTerminate();
}
//Get buffer size information
int bufferWidth, bufferHeight;
glfwGetFramebufferSize(window, &bufferWidth, &bufferHeight);
//Set context for GLEW to use (can change between which window)
glfwMakeContextCurrent(window);
//Allow modern extension features
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
std::cout << "Glew init failed!\n";
glfwDestroyWindow(window);
glfwTerminate();
}
glEnable(GL_DEPTH_TEST);
//Setup viewport size
glViewport(0, 0, bufferWidth, bufferHeight);
createTriangle();
compileShaders();
glm::mat4 projection = glm::perspective(45.f, (GLfloat)bufferWidth / (GLfloat)bufferHeight, 0.1f, 100.f);
//Main game loop
while (!glfwWindowShouldClose(window)) {
//Get + Handle user input events
glfwPollEvents();
//Left-Right
if (isMovingLeft) {
triOffset += triIncrement;
}
else {
triOffset -= triIncrement;
}
if (abs(triOffset) >= triMaxOffset) {
isMovingLeft = !isMovingLeft;
}
//Clear window
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader);
//Matrix 4x4
glm::mat4 model(1.f);
model = glm::translate(model, glm::vec3(triOffset, 0.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
meshVector[0]->renderMesh();
model = glm::mat4(1.f);
model = glm::translate(model, glm::vec3(-triOffset, 1.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4, 1.f));
meshVector[1]->renderMesh();
glUseProgram(0);
glfwSwapBuffers(window);
}
}
I expect two pyramids to form with color.
The GL_ELEMENT_ARRAY_BUFFER target binding is stored in the Vertex Array Object. See Index buffers.
This means, that the instruction
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
breaks the former binding of IBO to the vertex array object VAO. Remove this instruction from your code, to solve the issue.
Note, GL_ARRAY_BUFFER and the GL_ELEMENT_ARRAY_BUFFER behave differently. The current GL_ARRAY_BUFFER binding is a global state, but the GL_ELEMENT_ARRAY_BUFFER binding is stated in the current Vertex Array Object.
Also the GL_ARRAY_BUFFER is stated in the state vector of the VAO, but this happens when glVertexAttribPointer is called. When glVertexAttribPointer is called, then the buffer which is currently bound to the target GL_ARRAY_BUFFER is associated to the vertex attribute with the specified index.
That causes the difference in the behavior of GL_ELEMENT_ARRAY_BUFFER and GL_ARRAY_BUFFER. A VAO can only refer to 1 index (element) buffer, but it can refer to multiple array buffers. Each attribute (index) can be associated to a different buffer.
Before you render the 2nd mesh, you've the set the corresponding model matrix to the default uniform block of the installed program:
glUseProgram(shader);
glUniformMatrix4fv(uniformProjection, 1, GL_FALSE, glm::value_ptr(projection));
glm::mat4 model(1.f);
model = glm::translate(model, glm::vec3(triOffset, 0.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4f, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model));
meshVector[0]->renderMesh();
model = glm::mat4(1.f);
model = glm::translate(model, glm::vec3(-triOffset, 1.f, -2.5f));
model = glm::scale(model, glm::vec3(0.4f, 0.4, 1.f));
glUniformMatrix4fv(uniformModel, 1, GL_FALSE, glm::value_ptr(model)); // <---
meshVector[1]->renderMesh();
I am trying to make my first cube using open gl. Unfortunately I stucked in easy rotation. This is how it should look:
Instead I am getting those weird, do not even know how to called it : https://youtu.be/0A5Hi-8bygE
Vertex shader
#version 330 core
layout (location = 0) in vec2 a_position;
layout (location = 1) in vec2 a_uv;
layout (location = 2) in vec4 a_color;
out vec2 v_fragmentPosition;
out vec2 v_fragmentUV;
out vec4 v_fragmentColor;
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
void main()
{
gl_Position = u_projection * u_view * u_model * vec4(a_position, 0.0, 1.0);
v_fragmentPosition = a_position;
v_fragmentUV = vec2(a_uv.x, 1 - a_uv.y);
v_fragmentColor = a_color;
}
Fragment
#version 330 core
out vec4 outColor;
in vec2 v_fragmentPosition;
in vec2 v_fragmentUV;
in vec4 v_fragmentColor;
void main()
{
outColor = v_fragmentColor;
}
Main
#include <glad.h>
#include <glm.hpp>
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
#include <iostream>
#include "Mesh.h"
#include "Shader.h"
int main(int argc,char*args[])
{
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 4);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Window* window = SDL_CreateWindow("fdas", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL);
SDL_GLContext context = SDL_GL_CreateContext(window);
gladLoadGLLoader(SDL_GL_GetProcAddress);
glEnable(GL_DEPTH_TEST);
Shader shader;
std::string vertex = shader.LoadFromFile("vertex.shader");
std::string fragment = shader.LoadFromFile("fragment.shader");
shader.CreateShaderProgram(vertex.c_str(), fragment.c_str());
shader.useProgram();
Mesh mesh;
mesh.CreateVertexArray();
bool quit = false;
SDL_Event event;
while (!quit)
{
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
exit(0);
}
}
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 model;
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 view;
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
glm::mat4 projection;
projection = glm::perspective(glm::radians(45.0f), 1280 / 720.0f, 0.1f, 100.0f);
GLint u_model = shader.GetUniformLocation("u_model");
GLint u_view = shader.GetUniformLocation("u_view");
GLint u_projection = shader.GetUniformLocation("u_projection");
glUniformMatrix4fv(u_model, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(u_view, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(u_projection, 1, GL_FALSE, glm::value_ptr(projection));
Rect destRect = { -0.5f, -0.5f, 1.0f, 1.0f };
Rect uvRect = { 0.0f, 0.0f, 1.0f, 1.0f };
ColorRGBA color = { 255, 255, 128, 255 };
mesh.CreateQuad(destRect, uvRect, color);
mesh.Draw(0);
SDL_GL_SwapWindow(window);
}
return 0;
}
Mesh
void Mesh::CreateVertexArray()
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, uv));
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex), (void*)offsetof(Vertex, color));
glBindVertexArray(0);
}
void Mesh::CreateQuad(Rect destRect, Rect uvRect, ColorRGBA color)
{
vertex[0].color = color; // topleft
vertex[0].setPosition(destRect.x, destRect.y + destRect.h);
vertex[0].setUV(uvRect.x, uvRect.y + uvRect.h);
vertex[1].color = color;
vertex[1].setPosition(destRect.x, destRect.y); // bottom left
vertex[1].setUV(uvRect.x, uvRect.y);
vertex[2].color = color;
vertex[2].setPosition(destRect.x + destRect.w, destRect.y); // bottom right
vertex[2].setUV(uvRect.x + uvRect.w, uvRect.y);
vertex[3].color = color;
vertex[3].setPosition(destRect.x + destRect.w, destRect.y + destRect.h); // top right
vertex[3].setUV(uvRect.x + uvRect.w, uvRect.y + uvRect.h);
GLuint indices[6] = {
0, 1, 2,
2, 3, 0
};
glBindVertexArray(vao);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(vertex), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ARRAY_BUFFER, 0, 6 * sizeof(vertex), vertex);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), NULL, GL_STATIC_DRAW); // orphan the buffer
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, 6 * sizeof(GLuint), indices);
glBindVertexArray(0);
}
void Mesh::Draw(GLuint texture)
{
glBindVertexArray(vao);
// glEnable(GL_CULL_FACE);
// glCullFace(GL_FRONT);
//glFrontFace(GL_CW);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
}
Vertex
struct Rect {
float x, y;
float w, h;
};
struct Position {
float x, y;
};
struct UV {
float u, v;
};
struct ColorRGBA {
GLubyte r, g, b, a;
};
class Vertex
{
public:
Vertex();
~Vertex();
void setPosition(float x, float y);
void setcolor(ColorRGBA color);
void setUV(float u, float v);
UV uv;
ColorRGBA color;
Position position;
};
I will not show shader class, because there is all good with it.
I know it, because I did an experiment.
I created a new uniform in fragment class called u_expColor and set outColor = u_expColor and a quad's color changed.
Also I created uniform vec4 u_expPos in vertex shader and said gl_Position = e_expPos and it created quad with no problems.
Only if I want to create/multiply position by mvp in vertex shader there is a problem like on the you tube video.
How to fix it?
I have fixed it thanks http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/#putting-it-all-together. I saw he had
glm::mat4 model = glm::mat4(1.0f)
and it was all I had to do.