I've bee playing around again with Modern OpenGL (4.1) and was everything fine until I stepped into shading realms.
But before I even render something with shading I got some problems with the vertex shader.
The program is really simple, it simply reads an OBJ file and also the texture of the mesh. I put those things in their respective buffers and then draw it. At first it was drawing everything perfectly, but then I added 2 more uniform variable in the vertex shader and BAM! Nothing gets drawn. Funny thing is: as soon as I comment one of the extra uniforms, everything gets rendered again.
I really don't understand what is happening here, I thought I was extrapolating any limit of uniforms, but it is just 3 mat4 uniforms, and from what I googled, I have at least 1024 [source].
Anyway, I'm out of ideas, out of google query, so I come here to your help.
Thanks in advance!!
Ah, I'm using MacOSX El Captain and some information of the environment (got from glGetString):
Version: 4.1 ATI-1.40.16
Renderer: AMD Radeon HD 6750M OpenGL Engine
Some of the code not include is just Context creation and Shader compiling.
Note that if I delete uniform mat4 mM; it works perfectly. Otherwise, it keeps printing "Location -> -1" (saying it cannot find any uniform).
I really don't know what's going on.
P.S.: Also please don't mind for the terrible code, still trying to figure out some stuff code still not good.
vertexShader.gs:
#version 410
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec2 vTex;
out vec2 texCoord;
uniform mat4 mM;
uniform mat4 mV;
uniform mat4 mvp;
void main () {
texCoord = vTex;
gl_Position = mvp * vec4(vPosition, 1.0f);
}
Main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <OpenGl/gl.h>
//#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "picg.h"
#include "shader.h"
#include "tiny_obj_loader.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void matrices(GLfloat xAngle, GLfloat yAngle);
glm::mat4 projection, view, model, rotations;
glm::mat4 mvp;
glm::vec3 light;
GLuint vao, vbo, ibo, tbo;
GLuint texture;
GLuint shaderProgram;
const GLfloat angle = 1.0f;
GLfloat cYAngle;
GLfloat cXAngle;
GLfloat scale = 1.0f;
GLfloat points[] = {
-0.7f, +0.7f, +0.7f,
-0.7f, -0.7f, +0.7f,
+0.7f, -0.7f, +0.7f,
+0.7f, +0.7f, +0.7f
};
GLuint indices[] = {
0, 1, 2, 3, 0, 2
};
int main() {
GLFWwindow * window = create_context("Fish club", 600, 600);
initGL();
GLubyte vertexShader = shaderFromFile("vertexShader.gs", GL_VERTEX_SHADER);
GLubyte fragmentShader = shaderFromFile("fragmentShader.gs", GL_FRAGMENT_SHADER);
projection = glm::perspective(glm::radians(+45.f), 1024.f / 768.f, 0.1f, 600.0f);
view = glm::lookAt(
glm::vec3(+0.0f,+0.0f,+5.0f),
glm::vec3(+0.0f,+0.0f,+0.0f),
glm::vec3(+0.0f,+1.0f,+0.0f)
);
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(90.0f));
mvp = projection * view * model;
light = glm::vec3(0.0f, 1.0f, 1.0f);
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string err;
if (!tinyobj::LoadObj(shapes, materials, err, "res/GOLDFISH.obj")) {
throw std::runtime_error(std::string("Error loading OBJ file:\n") + err);
}
std::cout << "Shapes: " << shapes.size() << std::endl
<< "Materials: " << materials.size() << std::endl
<< "Positions: " << shapes[0].mesh.positions.size() << std::endl
<< "Normals: " << shapes[0].mesh.normals.size() << std::endl
<< "TexCoords: " << shapes[0].mesh.texcoords.size() << std::endl;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
int width, height, numComponents;
unsigned char * imageData = stbi_load("res/GOLDFISH.bmp",
&width, &height, &numComponents, 4);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
imageData);
glBindTexture(GL_TEXTURE_2D, NULL);
stbi_image_free(imageData);
GLsizei vertex_buffer_size = 0;
for (int i = 0 ; i < shapes.size(); ++i) {
vertex_buffer_size += sizeof(float) * shapes[i].mesh.positions.size();
}
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ARRAY_BUFFER, offset,
sizeof(float) * shapes[i].mesh.positions.size(),
&shapes[i].mesh.positions[0]);
offset += sizeof(float) * shapes[i].mesh.positions.size();
}
glBindBuffer(GL_ARRAY_BUFFER, NULL);
GLsizei index_buffer_size = 0;
GLsizei index_size = 0;
for (int i = 0 ; i < shapes.size() ; ++i) {
index_buffer_size += sizeof(float) * shapes[i].mesh.indices.size();
index_size += shapes[i].mesh.indices.size();
}
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset,
sizeof(unsigned int) * shapes[i].mesh.indices.size(),
&shapes[i].mesh.indices[0]);
offset += sizeof(unsigned int) * shapes[i].mesh.indices.size();
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
GLsizei texcoord_buffer_size = 0;
for (int i = 0 ; i < shapes.size() ; ++i) {
texcoord_buffer_size += sizeof(float) * shapes[i].mesh.texcoords.size();
}
glGenBuffers(1, &tbo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glBufferData(GL_ARRAY_BUFFER, texcoord_buffer_size, NULL, GL_STATIC_DRAW);
for (int i = 0, offset = 0 ; i < shapes.size() ; ++i) {
glBufferSubData(GL_ARRAY_BUFFER, offset,
sizeof(float) * shapes[i].mesh.texcoords.size(),
&shapes[i].mesh.texcoords[0]);
offset += sizeof(float) * shapes[i].mesh.texcoords.size();
}
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBindBuffer(GL_ARRAY_BUFFER, tbo);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindVertexArray(NULL);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cYAngle += 0.1f;
matrices(cXAngle, cYAngle);
glUseProgram(shaderProgram);
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mV") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mM") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mvp") << std::endl;
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mvp"),
1, GL_FALSE, &mvp[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mV"),
1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mM"),
1, GL_FALSE, &model[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, index_buffer_size, GL_UNSIGNED_INT, NULL);
glBindVertexArray(NULL);
glUseProgram(NULL);
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return 0;
}
void matrices(GLfloat xAngle, GLfloat yAngle) {
model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(xAngle), glm::vec3(+1.0f, +0.0f, +0.0f));
model = glm::rotate(model, glm::radians(yAngle), glm::vec3(+0.0f, +1.0f, +0.0f));
model = glm::scale(model, glm::vec3(40.0f));
mvp = projection * view * model;
}
edit:
As suggested I tried the following vertex shader:
#version 410
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec2 vTex;
out vec2 texCoord;
uniform mat4 mM;
uniform mat4 mV;
uniform mat4 mP;
void main () {
texCoord = vTex;
gl_Position = mP * mV * mM * vec4(vPosition, 1.0f);
}
And changed the following lines
glUseProgram(shaderProgram);
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mP") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mV") << std::endl;
std::cout << "Location -> " << glGetUniformLocation(shaderProgram, "mM") << std::endl;
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mP"),
1, GL_FALSE, &projection[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mV"),
1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(
glGetUniformLocation(shaderProgram, "mM"),
1, GL_FALSE, &model[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shaderProgram, "textureSampler"), 0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, index_buffer_size, GL_UNSIGNED_INT, NULL);
glBindVertexArray(NULL);
glUseProgram(NULL);
And still, I can see nothing and it only returns "Location -> -1" for every uniform.
mM and mV is not used in your vertex shader code. I believe it will be removed during compilation so when you try to get their location with glGetUniformLocation() this information is not available. Try to do something with mM and mV in your shader code.
Related
I need to crop the image. But in opencv, it will create error because of integer domain. So I want to crop every single unit in float domain to reduce the offset error. Maybe openGL can help me, but I'm not good at it.
The image just like this ( but not this one ):
I want every black and white unit, then save them in cv::Mat.
I guess maybe shader or loop or something else can repeat to crop all block, then save them.
Now I can get one single unit. Like this:
glfwInit();//initalization
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(100, 100, "LearnOpenGL", nullptr, nullptr);
if (window == nullptr)
{
cout << "Failed to create GLFW window" << endl;
glfwTerminate();
return false;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return false;
}
Shader ourShader("vertex.vs.glsl", "fragment.fs.glsl");
float unitWidth = moduleLength / (float)tex.cols;
float startP_x = 100.0f / (float)tex.cols + unitWidth * 2;
float startP_y = 104.0f / (float)tex.rows + unitWidth * 2;
float vertices[] = {
// positions // texture coords (note that we changed them to 'zoom in' on our texture image)
0.5f, 0.5f, 0.0f, startP_x + unitWidth, startP_y, // top right
0.5f, -0.5f, 0.0f, startP_x + unitWidth, startP_y + unitWidth, // bottom right
-0.5f, -0.5f, 0.0f, startP_x, startP_y + unitWidth, // bottom left
-0.5f, 0.5f, 0.0f, startP_x, startP_y // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// texture coord attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture
// ---------
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
//// set the texture wrapping parameters
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLubyte* pixels;
int width = tex.cols;
int height = tex.rows;
int pixellength = width * height*tex.channels();
pixels = new GLubyte[pixellength];
memcpy(pixels, tex.data, pixellength * sizeof(unsigned char));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, pixels);
free(pixels);
while (!glfwWindowShouldClose(window))
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind Texture
glBindTexture(GL_TEXTURE_2D, texture);
// draw our first triangle
ourShader.use();
// create transformations
glm::mat4 model = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix first
glm::mat4 view = glm::mat4(1.0f);
glm::mat4 projection = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(0.0f), glm::vec3(1.0f, 0.0f, 0.0f));
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -1.1f));
projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// retrieve the matrix uniform locations
unsigned int modelLoc = glGetUniformLocation(ourShader.ID, "model");
unsigned int viewLoc = glGetUniformLocation(ourShader.ID, "view");
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, &view[0][0]);
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // set the count to 6 since we're drawing 6 vertices now (2 triangles); not 3!
glfwPollEvents();
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glfwTerminate();
return true;
vetex shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec2 TexCoord;
void main()
{
gl_Position = projection * view * model *vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
fragment shader:
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}
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();
The following code draws a white square to the screen. If I uncomment the line that uses the program, the square disappears.
When I debug the program with GLIntercept, the texture appears in a folder called Images, and the log says that the shaders compiled. However, it also says that the program links, but doesn't validate.
I've been poring over this for hours and I have no idea where to go from here.
// Vertex.vert
#version 150 core
in vec3 in_position;
in vec2 in_texture;
out vec2 Texture;
uniform mat4 in_model;
uniform mat4 in_view;
uniform mat4 in_projection;
void main()
{
gl_Position = in_projection * in_view * in_model * vec4(in_position, 1.0);
Texture = in_texture;
}
// Fragment.frag
#version 150 core
in vec2 Texture;
out vec4 Colour;
uniform sampler2D Sampler2D;
void main()
{
Colour = texture(Sampler2D, Texture);
}
// Source.cpp
#include <cfloat>
#include <iostream>
#include <string>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/transform.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include "Archive.h"
using namespace glm;
using namespace sf;
using namespace std;
struct Camera
{
vec3 Position = { 0.0f, 0.0f, 1.0f };
vec3 Target = { 0.0f, 0.0f, 0.0f };
vec3 Up = { 0.0f, 1.0f, 0.0f };
float Fovy = 74.0f;
float Aspect = 16.0f / 9.0f;
float ZNear = FLT_MIN;
float ZFar = FLT_MAX;
mat4 View;
mat4 Projection;
};
struct Actor
{
vec3 Scale = { 1.0f, 1.0f, 1.0f };
vec3 Rotation = { 0.0f, 0.0f, 0.0f };
vec3 Position = { 0.0f, 0.0f, 0.0f };
vector<GLfloat> Vertices;
vector<GLuint> Elements;
GLuint Texture;
Actor(string fileName)
{
Image image;
if (!image.loadFromFile(fileName + ".png"))
{
cerr << "ERROR: Unable to load texture" << endl;
}
glGenTextures(1, &Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.getSize().x, image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
// Draw a square instead of the actual model
Vertices.push_back(-1.0f); Vertices.push_back(-1.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f);
Vertices.push_back(1.0f); Vertices.push_back(-1.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f);
Vertices.push_back(1.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f); Vertices.push_back(1.0f);
Vertices.push_back(-1.0f); Vertices.push_back(1.0f); Vertices.push_back(0.0f); Vertices.push_back(0.0f); Vertices.push_back(1.0f);
Elements.push_back(0); Elements.push_back(1); Elements.push_back(2);
Elements.push_back(2); Elements.push_back(3); Elements.push_back(0);
}
};
GLuint CreateShader(GLenum shaderType, string fileName, Archive& archive)
{
string source;
archive.open(fileName);
source.resize(archive.getSize());
archive.read(&source[0], archive.getSize());
GLuint shader = glCreateShader(shaderType);
const char* pointer = source.c_str();
glShaderSource(shader, 1, &pointer, nullptr);
glCompileShader(shader);
GLsizei length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
GLchar* infoLog = new GLchar[length];
glGetShaderInfoLog(shader, length, &length, infoLog);
cerr << infoLog << endl;
delete[] infoLog;
}
return shader;
}
GLuint CreateProgram(GLuint vertex, GLuint fragment)
{
GLuint program = glCreateProgram();
glAttachShader(program, vertex);
glAttachShader(program, fragment);
glLinkProgram(program);
GLsizei length;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
if (length > 1)
{
GLchar* infoLog = new GLchar[length];
glGetProgramInfoLog(program, length, &length, infoLog);
cerr << infoLog << endl;
delete[] infoLog;
}
return program;
}
int main(int argc, char* argv[])
{
Window window(VideoMode(1920, 1080), "");
window.setVerticalSyncEnabled(true);
if (!window.setActive(true))
{
cerr << "ERROR: Unable to set the window as the current target for OpenGL rendering" << endl;
return 1;
}
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
cerr << "ERROR: Unable to initialise GLEW" << endl;
return 1;
}
Archive shaders("Shaders.lea");
Archive models("Models.lea");
Actor actor("tree01");
GLuint vertex = CreateShader(GL_VERTEX_SHADER, "Vertex.vert", shaders);
GLuint fragment = CreateShader(GL_FRAGMENT_SHADER, "Fragment.frag", shaders);
GLuint program = CreateProgram(vertex, fragment);
GLuint vertexArray;
GLuint vertexBuffer;
GLuint elementBuffer;
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glGenBuffers(1, &elementBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
// glUseProgram(program);
GLint position = glGetAttribLocation(program, "in_position");
glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, 0);
glEnableVertexAttribArray(position);
GLint texture = glGetAttribLocation(program, "in_texture");
glVertexAttribPointer(texture, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (void*)(sizeof(GLfloat) * 3));
glEnableVertexAttribArray(texture);
GLint projection = glGetUniformLocation(program, "in_projection");
GLint view = glGetUniformLocation(program, "in_view");
GLint model = glGetUniformLocation(program, "in_model");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Camera camera;
while (window.isOpen())
{
// Input handling code omitted
camera.View = lookAt(camera.Position, camera.Target, camera.Up);
camera.Projection = perspective(radians(camera.Fovy), camera.Aspect, camera.ZNear, camera.ZFar);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniformMatrix4fv(projection, 1, GL_FALSE, value_ptr(camera.Projection));
glUniformMatrix4fv(view, 1, GL_FALSE, value_ptr(camera.View));
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * actor.Vertices.size(), &actor.Vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * actor.Elements.size(), &actor.Elements[0], GL_STATIC_DRAW);
mat4 transform = translate(mat4(), actor.Position);
transform *= rotate(transform, actor.Rotation.z, vec3(0.0f, 0.0f, 1.0f));
transform *= rotate(transform, actor.Rotation.y, vec3(0.0f, 1.0f, 0.0f));
transform *= rotate(transform, actor.Rotation.x, vec3(1.0f, 0.0f, 0.0f));
transform *= scale(transform, actor.Scale);
glUniformMatrix4fv(model, 1, GL_FALSE, value_ptr(transform));
glBindTexture(GL_TEXTURE_2D, actor.Texture);
glDrawElements(GL_TRIANGLES, actor.Elements.size(), GL_UNSIGNED_INT, 0);
window.display();
}
glUseProgram(0);
glDisableVertexAttribArray(texture);
glDisableVertexAttribArray(position);
glDeleteBuffers(1, &elementBuffer);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
glDetachShader(program, fragment);
glDetachShader(program, vertex);
glDeleteShader(fragment);
glDeleteShader(vertex);
glDeleteProgram(program);
return 0;
}
It was a combination of two things.
When I last used this code, it was with GLM 0.9.7.6, and mat4() generated an identity matrix. However, at some point between that version of GLM and the one I'm currently using (0.9.9.5), mat4() started generating an empty matrix. Instead, you need mat4(1.0f).
Also, I used bad values for the near and far planes. I did think that the values I had would work, but clearly I don't quite understand what's going on behind the scenes.
I am trying to implement polygon selection through clicking by first drawing triangle IDs to an off-screen framebuffer and then reading back pixel values at clicked positions via glReadPixels. I am passing ID as unsigned integer to each vertex (and I confirmed that the buffer is correct from apitrace) and outputting it as uvec4 in fragment shader. I set up the framebuffer as RGBA8UI texture (also confirmed units to be correct from apitrace). There is no opengl error and also checked that framebuffer is complete.
The problem is that the output image where the IDs should be always has a value of 255. The area covered by the triangles are modified from the glClear value but they are not (id, 0, 0, 0) but always (255, 0, 0, 0). The exception is those with ID of 0. It seems like somewhere in the shader, the ID is converted to 255 if the ID is not 0. Is this the expected behavior from the code below? Am I doing something wrong?
Vertex buffer:
x (float), y (float), z (float), tx (float), ty (float), id (unsigned int)
Vertex shader:
#version 330 core
// Input
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in uint id;
// Output (Varying)
out vec2 v_texCoord;
flat out uint v_id;
// Uniform
uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;
void main()
{
v_texCoord = texCoord;
v_id = id;
gl_Position = u_projection * u_view * u_model * vec4(position, 1.0);
}
Fragment shader:
#version 330 core
// Input (Varying)
in vec2 v_texCoord;
flat in uint v_id;
// Output
layout(location = 0) out uvec4 color;
void main()
{
color = uvec4(v_id, 0, 0, 0);
}
GL_VERSION is 3.3.0 NVIDIA 419.35 and I have updated the driver yesterday.
-- Edit --
I was down-voted for lack of information so I created a separate project that just shows my point above with the rest of the code below:
#include <glad/glad.h> // Must be included before GLFW header
#include <GLFW/glfw3.h>
#include <iostream>
#include <vector>
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;
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);
// glfw window creation
GLFWwindow* window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// glad: load all OpenGL function pointers
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
std::cout << glGetString(GL_VERSION) << std::endl;
// Vertex and fragment shaders
GLuint shader = glCreateProgram();
{
GLint isSuccess = false;
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// Vertex shader
{
const GLchar* vertexShaderSource =
"#version 330 core\n"
"layout(location = 0) in vec2 position;\n"
"layout(location = 1) in uint id;\n"
"flat out uint v_id;\n"
"void main() {v_id = id; gl_Position = vec4(position.x, position.y, 0.0, 1.0);}\n";
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glCompileShader(vertexShader);
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isSuccess);
std::cout << "Vertex shader compile status: " << isSuccess << std::endl;
}
// Fragment shader
{
const GLchar* fragmentShaderSource =
"#version 330 core\n"
"layout(location = 0) out uvec4 color;\n"
"flat in uint v_id;\n"
"void main() {color = uvec4(v_id, 0, 0, 0);}\n";
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isSuccess);
std::cout << "Fragment shader compile status: " << isSuccess << std::endl;
}
glAttachShader(shader, vertexShader);
glAttachShader(shader, fragmentShader);
glLinkProgram(shader);
glGetProgramiv(shader, GL_LINK_STATUS, &isSuccess);
std::cout << "Shader link status: " << isSuccess << std::endl;
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
// Vertex Buffer
GLuint vertexBuffer;
{
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLfloat data[] = {
// x y id
-1.0f, 0.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLuint* data2 = ((GLuint *)data);
data2[2] = 0;
data2[5] = 0;
data2[8] = 0;
data2[11] = 1;
data2[14] = 1;
data2[17] = 1;
std::cout << "Size of GLuint: " << sizeof(GLuint) << std::endl;
std::cout << "Size of GLfloat: " << sizeof(GLfloat) << std::endl;
std::cout << "Size of vertex buffer: " << sizeof(data) << std::endl;
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
// Vertex Array
GLuint vertexArray;
{
glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_UNSIGNED_INT, GL_FALSE, 3 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
// Texture for framebuffer
GLuint texture;
glGenTextures(1, &texture);
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D, 0);
}
// Framebuffer
GLuint framebuffer;
{
GLenum completenessStatus;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
std::cout << "Framebuffer status: " << (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Clear
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GLenum error = glGetError();
std::cout << "No error: " << (error == GL_NO_ERROR) << std::endl;
// Draw
while (!glfwWindowShouldClose(window))
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
{
glDisable(GL_DITHER);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader);
glBindVertexArray(vertexArray);
glActiveTexture(GL_TEXTURE0);
glDrawArrays(GL_TRIANGLES, 0, 6);
glEnable(GL_DITHER);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteProgram(shader);
glDeleteBuffers(1, &vertexBuffer);
glDeleteVertexArrays(1, &vertexArray);
glDeleteFramebuffers(1, &framebuffer);
glDeleteTextures(1, &texture);
return 0;
}
Output:
3.3.0 NVIDIA 419.35
Vertex shader compile status: 1
Fragment shader compile status: 1
Shader link status: 1
Size of GLuint: 4
Size of GLfloat: 4
Size of vertex buffer: 72
Framebuffer status: 1
No error: 1
Framebuffer is RGBA8UI:
Vertices are correct:
Triangle with ID of 0 is colored as (0, 0, 0, 0) as expected:
Area outside triangle is (255, 255, 255, 255) as expected (glClearColor is white):
Triangle with ID of 1 is colored as (255, 0, 0, 0). It should be (1, 0, 0, 0):
The same issue occurs for ID > 1. Why is this the case? How can I make it so that the color is (ID, 0, 0, 0) as shown in the fragment shader?
You have to use glVertexAttribIPointer (focus on I), when defining the array of generic vertex attribute data, for the vertex attribute in uint id;.
When vertex attribute data are defined by glVertexAttribPointer, then they will be converted to floating point values.
See OpenGL 4.6 API Core Profile Specification; 10.2. CURRENT VERTEX ATTRIBUTE VALUES; page 344
The VertexAttribI* commands specify signed or unsigned fixed-point values
that are stored as signed or unsigned integers, respectively. Such values are referred to as pure integers.
...
All other VertexAttrib* commands specify values that are converted directly to the internal floating-point representation.
I try to give a data to uniform variable from c++,but the variable is always 0;
Who can help me. I use shader compiler.There is no error in shader
c++ code vbo and vao in this function,I try to give a matrix,but it got error,so i try to give a point like a GLfloat first. I didn't give create and compile shader code,because i am sure that is correct.
void initVBO()
{
// Create and populate the buffer objects
GLuint vboHandles[4];
glGenBuffers(3, vboHandles);
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
GLuint textureBufferHandle = vboHandles[2];
GLuint mvphandle = vboHandles[3];
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(positionData),
positionData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(colorData),
colorData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof (float),
texCoords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, mvphandle);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data),
g_vertex_buffer_data, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2); //texture
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
glBindBuffer(GL_ARRAY_BUFFER, textureBufferHandle);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
errno_t err;
// Data read from the header of the BMP file
unsigned char header[54];
unsigned int dataPos;
unsigned int imageSize;
//unsigned int width, height;
// Actual RGB data
unsigned char * data;
int width, height, nrChannels;
//data = SOIL_load_image("wall.bmp", &width, &height, 0, SOIL_LOAD_RGB);
FILE * file;
const char imagepath[] = "sample.bmp";
if (err = fopen_s(&file, imagepath, "rb")){ printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); }
if (fread(header, 1, 54, file) != 54){
printf("Not a correct BMP file\n");
}
// A BMP files always begins with "BM"
if (header[0] != 'B' || header[1] != 'M'){
printf("Not a correct BMP file\n");
}
// Make sure this is a 24bpp file
if (*(int*)&(header[0x1E]) != 0) { printf("Not a correct BMP file\n"); }
if (*(int*)&(header[0x1C]) != 24) { printf("Not a correct BMP file\n"); }
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
printf("width : %d hight : %d\n", width, height);
data = new unsigned char[imageSize];
// Read the actual data from the file into the buffer
fread(data, 1, imageSize, file);
// Everything is in memory now, the file wan be closed
fclose(file);
GLuint textureID;
glGenTextures(1, &textureID);
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
// Give the image to OpenGL
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
//glUniform1i(glGetUniformLocation(fShader, "tex"), 0);
// Poor filtering, or ...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// ... nice trilinear filtering.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//GLuint MatrixID = glGetUniformLocation(vShader, "p");
//glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(trans));
//glUniform1f(MatrixID, 1.0);
}
void init()
{
GLenum err = glewInit();
if (GLEW_OK != err)
{
cout << "Error initializing GLEW: " << glewGetErrorString(err) << endl;
}
initShader("vert.txt", "frag.txt");
initVBO();
//glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_SMOOTH);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float)600 / (float)600, 0.0f, 10.0f);
glm::mat4 View = glm::lookAt(
glm::vec3(0, 0, 10), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 0), // and looks at the origin
glm::vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
glm::mat4 Model = glm::mat4(1.0f);
glm::mat4 mvp = Projection * View * Model;
glm::mat4 trans = glm::mat4(1.0f);
trans = glm::rotate(
trans,
glm::radians(180.0f),
glm::vec3(0.0f, 0.0f, 1.0f)
);
glm::mat4 test = glm::mat4(1.0f);
test[0][0] = 1;
test[1][1] = 1;
test[2][2] = 1;
//test[1][3] = 0.5;
test[3][3] = 1;
GLfloat aaa[4][4] = {0.0f};
aaa[0][0] = 1;
aaa[1][1] = 1;
aaa[2][2] = 1;
aaa[3][3] = 1;
cout << "test[2][2] = " << trans[0][0] << endl;
//glGetActiveUniform();
GLuint MatrixID = glGetUniformLocation(vShader, "mvp");
if (MatrixID > 0)cout << "Loacation = "<<MatrixID << endl;
else cout << "fail" << endl;
//glUniform1f(glGetUniformLocation(vShader, "test"), 1.0);
GLfloat a = 1.0f;
GLint asize;
//glGetActiveUniform(vShader, MatrixID, 1, NULL, &asize, NULL, NULL);
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, glm::value_ptr(trans));
MatrixID = glGetUniformLocation(vShader, "p");
glUniform1f(MatrixID, 10);
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glutSwapBuffers();
}
void Reshape(int w, int h)
{
if (h == 0)
h = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float)w / (float)h, 0, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
glDeleteShader(vShader);
glUseProgram(0);
exit(0);
break;
}
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB |GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("GLSL Test : Draw a triangle");
glutReshapeFunc(Reshape);
init();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
fragment code
#version 400
uniform float p;
in vec3 Color;
in vec2 texcoord;
out vec4 FragColor
uniform sampler2D tex;
uniform vec3 bbb;
uniform mat4 mvp;
void main()
{
if(p==0)
FragColor = vec4(1.0,0.0,0.0, 1.0);
else
FragColor = vec4(mvp[0][0],Color.y,Color.z, 1.0);
//texture(tex, vec2(1-texcoord.x,texcoord.y))*
}
version and my uniform location
OpenGL 4.6 API Compatibility Profile Specification; 7.6. UNIFORM VARIABLE; page 134:
To determine the set of active uniform variables used by a program, applications can query the properties and active resources of the UNIFORM interface of a program.
Additionally, several dedicated commands are provided to query properties of
active uniforms.
int GetUniformLocation( uint program, const char *name );
A uniform variable is a program resource. This means the parameter for glGetUniformLocation has to be a successfully linked program object (glCreateProgram) and not a shader object (glCreateShader).
Create a program object:
GLuint prog = glCreateProgram();
Attach the shader objects:
glAttachShader(prog, vShader);
....
Link the program:
glLinkProgram(prog);
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if ( status == GL_FALSE )
..... // error handling
Get the uniform location:
GLuint location_p = glGetUniformLocation(prog, "p");
"Use" the program:
glUseProgram(prog);
Set the uniform:
glUniform1f(location_p, 10);