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.
Related
I'm trying to draw two lines which's vertices are:
glm::vec2(100, 100),
glm::vec2(300, 100),
glm::vec2(100, 100),
glm::vec2(100, 300)
The other line seems to not overlap with the other one like seen in the picture:
Instead the other line starts from the left of this line. How could this be resolved so that it would be overlapping the other line?
Vertex shader (test.vs):
#version 120
attribute vec2 position;
attribute vec4 in_color;
varying vec4 color;
uniform mat4 projection;
uniform mat4 view;
void main() {
color = in_color;
gl_Position = projection * view * vec4(position, 0, 1);
}
Fragment shader (test.fs):
#version 120
varying vec4 color;
void main()
{
gl_FragColor = color;
}
Source code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <glm/gtx/transform.hpp>
void checkCompileErrors(GLuint shader, std::string type)
{
GLint success;
GLchar infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << infoLog << '\n';
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << infoLog << '\n';
}
}
}
int main( void )
{
const glm::vec2 window_size(640, 480);
GLFWwindow *window;
if (!glfwInit())
{
return -1;
}
window = glfwCreateWindow(window_size.x, window_size.y, "window", 0, 0);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
std::cout << "glew not ok" << '\n';
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable( GL_BLEND );
glViewport( 0.0f, 0.0f, window_size.x, window_size.y);
std::ifstream fvertex;
std::ifstream ffragment;
std::stringstream vss, fss;
fvertex.open("test.vs");
ffragment.open("test.fs");
vss << fvertex.rdbuf();
fss << ffragment.rdbuf();
fvertex.close();
ffragment.close();
std::string vs;
std::string fs;
vs = vss.str();
fs = fss.str();
unsigned int vertex, fragment;
const char* vsc = vs.c_str();
const char* fsc = fs.c_str();
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vsc, 0);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fsc, 0);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
uint32_t id = glCreateProgram();
glAttachShader(id, vertex);
glAttachShader(id, fragment);
glLinkProgram(id);
checkCompileErrors(id, "PROGRAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
glm::vec2 vertices[] =
{
glm::vec2(100, 100),
glm::vec2(300, 100),
glm::vec2(100, 100),
glm::vec2(100, 300)
};
glm::vec4 colors[] = {
glm::vec4(1, 0, 0, 0.6),
glm::vec4(1, 0, 0, 0.6),
glm::vec4(0, 1, 0, 0.4),
glm::vec4(0, 1, 0, 0.4)
};
uint32_t vao = 0, position_vbo = 0, color_vbo = 0;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &position_vbo);
glGenBuffers(1, &color_vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, position_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
int location = glGetAttribLocation(id, "position");
glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(location);
glBindBuffer(GL_ARRAY_BUFFER, color_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
location = glGetAttribLocation(id, "in_color");
glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(location);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glm::mat4 projection(1);
projection = glm::ortho(window_size.x * 0.5, window_size.x + window_size.x * 0.5, window_size.y + window_size.y * 0.5, window_size.y * 0.5, 0.1, 1000.0);
glm::mat4 view(1);
view = glm::translate(view, glm::vec3(window_size.x * 0.5, window_size.y * 0.5, -700.0f));
view = view * glm::lookAtLH(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, 1, 0));
glUseProgram(id);
glUniformMatrix4fv(glGetUniformLocation(id, "projection"), 1, GL_FALSE, (float*)&projection[0][0]);
glUniformMatrix4fv(glGetUniformLocation(id, "view"), 1, GL_FALSE, (float*)&view[0][0]);
glBindVertexArray(vao);
glDrawArrays(GL_LINES, 0, 4);
glBindVertexArray(0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I'm trying to use a compute shader to do three-dimensional physical simulations but having trouble storing anything into my 3D texture. My shaders compile successfully but when reading back any value from the 3D texture I get a zero vector. I haven't used compute shaders before either so I'm not sure if I'm even distributing the work load properly in order to achieve what I want.
I've isolated the problem in a small example here. Basically the compute.glsl shader has a uniform image3D and uses imageStore to write a vec4(1,1,0,1) into gl_WorkGroupID. In C++ I create a 100x100x100 3D texture and bind it to the shader's uniform, then I call glDispatchCompute(100,100,100) - to my knowledge, this will create 1,000,000 jobs/shader invocations, one for each coordinate in the texture. In my view.glsl fragment shader I read the value of a random coordinate (in this case (3,5,7)) and output that. I use this shade a cube object.
Everything I've tried results in a black cube being output:
Here's my code (I've been following along with learnopengl.com so it's mostly the same boiler plate stuff except I extended the shader class to handle compute shaders):
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <learnopengl/shader_m.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
struct vaoinfo
{
unsigned int VBO, VAO, EBO;
vaoinfo() : VAO(0), VBO(0), EBO(0)
{}
};
void create_vao(vaoinfo& info)
{
glGenVertexArrays(1, &info.VAO);
glGenBuffers(1, &info.VBO);
glGenBuffers(1, &info.EBO);
}
void init_vao(vaoinfo& info, float* vertices, int num_vertices, int* indices, int num_indices)
{
glGenVertexArrays(1, &info.VAO);
glGenBuffers(1, &info.VBO);
glGenBuffers(1, &info.EBO);
glBindVertexArray(info.VAO);
glBindBuffer(GL_ARRAY_BUFFER, info.VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * num_vertices, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, info.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * num_indices, indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "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);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
vaoinfo cube;
create_vao(cube);
glm::vec3 c(0.5, 0.5, 0.5);
float verts[24] =
{
c.x, -c.y, c.z,
c.x, c.y, c.z,
-c.x, c.y, c.z,
-c.x, -c.y, c.z,
c.x, -c.y, -c.z,
c.x, c.y, -c.z,
-c.x, c.y, -c.z,
-c.x, -c.y, -c.z,
};
int indices[36] =
{
7, 4, 5,
5, 6, 7,
3, 0, 1,
1, 2, 3,
2, 6, 7,
7, 3, 2,
1, 5, 4,
4, 0, 1,
7, 4, 0,
0, 3, 7,
6, 5, 1,
1, 2, 6
};
init_vao(cube, verts, 24, indices, 36);
// Create a 3D texture
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_3D, texId);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8_SNORM, 100, 100, 100, 0, GL_RGBA, GL_FLOAT, nullptr);
// Create shaders
Shader computeShader("compute.glsl");
Shader viewShader("coords.glsl", "view.glsl");
while (!glfwWindowShouldClose(window))
{
processInput(window);
computeShader.use();
computeShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId);
glDispatchCompute(100, 100, 100);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
viewShader.use();
viewShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId);
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, (float)glfwGetTime(), glm::vec3(0.5f, 1.0f, 0.0f));
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
unsigned int modelLoc = glGetUniformLocation(viewShader.ID, "model");
unsigned int viewLoc = glGetUniformLocation(viewShader.ID, "view");
unsigned int projLoc = glGetUniformLocation(viewShader.ID, "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
// render cube
glBindVertexArray(cube.VAO);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
compute.glsl:
#version 430
layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(rgba8_snorm, binding=0) uniform image3D img;
uniform vec3 position;
void main()
{
ivec3 voxel_coord = ivec3(gl_WorkGroupID);
imageStore(img, voxel_coord, vec4(1, 1, 0, 1));
}
coords.glsl (vertex shader):
#version 430 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
view.glsl (fragment shader):
#version 430 core
out vec4 FragColor;
layout(rgba8_snorm, binding=0) uniform image3D img;
void main()
{
FragColor = imageLoad(img, ivec3(3,5,7));
}
It turned out that I was missing a call to glBindImageTexture - I thought that in order to bind my texture to the shader's image variable I needed to set the uniform and call glActiveTexture+glBindTexture but it seems only glBindImageTexture is needed.
I replaced:
computeShader.setInt("img", 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texId)
With:
glBindImageTexture(0, texId, 0, true, 0, GL_WRITE_ONLY, GL_RGBA16);
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.
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);
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.