This is my texture
This is how it is showing up
I am only getting this distorted result when using array textures.
Do I need to create mipmaps?
I am using the wrong image type?
bmp's might bot be an idea for images but I am using for the time being for their simplicity.
Code
#include <iostream>
using namespace std;
#include <cstdlib>
#include <stdio.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
GLFWwindow* window;
#define WINDOW_HEIGHT 768
#define WINDOW_WIDTH 1024
#include "common/shaders.h"
#include "common/texture.h"
#include "common/controls.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
static void error_callback(int error, const char* description);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
int main(void)
{
if (!glfwInit()) {
fprintf( stderr, "Failed to initialize GLFW\n" );
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE , GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Ortho", NULL, NULL);
if (!window) {
fprintf(stderr, "Failed to create window\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glfwSetErrorCallback(error_callback);
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
glfwSetCursorPos(window, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
fprintf(stderr, "Failed to initialize GLEW\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
if (GL_EXT_texture_array){
fprintf(stderr, "GL_EXT_texture_array\n");
}
glClearColor(0.0f, 0.0f, 255.0f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
GLuint vai; // vertex array id
glGenVertexArrays(1, &vai);
glBindVertexArray(vai);
char vert[] = "shaders/triangles.vert";
char frag[] = "shaders/triangles.frag";
GLuint program = load_shaders(vert,frag);
GLuint matrix_id = glGetUniformLocation(program, "MVP");
GLuint texture_id = glGetUniformLocation(program, "material");
GLsizei width = 16;
GLsizei height = 16;
GLsizei layerCount = 2;
GLsizei mipLevelCount = 1;
unsigned char* data = bmp_data("tiles.bmp");
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D_ARRAY, texture_id);
//GLubyte texels[32] =
//{
////Texels for first image.
//0, 0, 0, 255,
//255, 0, 0, 255,
//0, 255, 0, 255,
//0, 0, 255, 255,
////Texels for second image.
//255, 255, 255, 255,
//255, 255, 0, 255,
//0, 255, 255, 255,
//255, 0, 255, 255,
//};
//glTexStorage3D(GL_TEXTURE_2D_ARRAY, mipLevelCount, GL_RGBA8, width, height, layerCount);
//glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGBA, GL_UNSIGNED_BYTE, texels);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 16);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGB8, width, height, layerCount);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, layerCount, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
delete [] data;
GLuint vbo;
GLuint uvbo;
glGenBuffers(1, &vbo);
glGenBuffers(1, &uvbo);
// prep tile
GLfloat vertex[] = {
0, 1, 0,
1, 1, 0,
1, 0, 0,
0, 1, 0,
0, 0, 0,
1, 0, 0,
};
GLfloat uv[] = {
0.0f , 16.0f,
16.0f, 16.0f,
16.0f, 0.0f ,
0.0f , 16.0f,
0.0f , 0.0f ,
16.0f, 0.0f ,
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, uvbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);
glUseProgram(program);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
glUniformMatrix4fv(matrix_id, 1, GL_FALSE, &MVP[0][0]);
glUniform1i(texture_id, 0);
// render tile
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glBindBuffer(GL_ARRAY_BUFFER, uvbo);
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,0,(void*)0);
glDrawArrays(GL_TRIANGLES, 0, 2*3);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glDeleteProgram(program);
glDeleteVertexArrays(2, &vai);
glfwTerminate();
exit(EXIT_SUCCESS);
}
static void error_callback(int error, const char* description){
fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods){
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
}
fragment shader
#version 400 core
in vec2 uv; // Interpolated values from the vertex shaders
out vec3 color; // Ouput data
uniform sampler2DArray material; // Values that stay constant for the whole mesh.
void main(){
color = texture(material,vec3(uv,0)).rgb;
}
vert shader
#version 400 core
layout(location = 0) in vec3 vertex_pos;
layout(location = 1) in vec2 vertex_uv;
out vec2 uv;
uniform mat4 MVP;
void main(){
gl_Position = MVP * vec4(vertex_pos,1);
uv = vertex_uv;
}
I ended up paying to get someone to solve this problem for me.
I needed to update my texture vertex's. Also I didn't need to call glPixelStorei so I remove that.
GLfloat vertex[] = {
0, 1, 0,
1, 1, 0,
1, 0, 0,
0, 1, 0,
0, 0, 0,
1, 0, 0,
};
A texture files boundaries (uv coordinates) are from 0.0 to 1.0 on the x and y axis. If you want to map the whole texture to a quad you set the four corners to the quad's four corners. The following image is a good example:
http://www.c-jump.com/bcc/common/Talk3/OpenGL/Wk07_texture/const_images/textureMap.png
Related
I get a seemingly random color when I try to load a 16x16 png as Texture instad of the texture.
The Colors are alomst always something like light blue, dark blue, red, pink.
Here is the texture if it helps
DirtTexture
here is the code of the Texture class
TextureClass::TextureClass(const std::string& path)
{
int w, h, bpp;
stbi_set_flip_vertically_on_load(1);
unsigned char* data = stbi_load(path.c_str(), &w, &h, &bpp, 0);
glGenTextures(1, &ID);
glBindTexture(GL_TEXTURE_2D, ID);
glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, &data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
if (data)
{
stbi_image_free(data);
}
}
void TextureClass::Bind(unsigned int slot) const
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, ID);
}
void TextureClass::Delete()
{
glDeleteTextures(1, &ID);
}
here is the code of my vertex and fragment shader
#shader vertex
#version 330 core
layout (location = 0) in vec2 aPosition;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
out vec3 color;
void main()
{
gl_Position = vec4(aPosition.x, aPosition.y, 1.0, 1.0);
texCoord = aTexCoord;
color = vec3(1.0, 0.0, 1.0);
};
#shader fragment
#version 330 core
out vec4 FragColor;
in vec2 texCoord;
uniform sampler2D tex0;
void main()
{
FragColor = texture(tex0, texCoord);
}
Here is my main part
#include<glad/glad.h>
#include<GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#include "VAO.h"
#include "VBO.h"
#include "IBO.h"
#include "ShaderClass.h"
#include "Texture.h"
struct ShaderProgramSource
{
std::string VertexSource;
std::string FragmentSource;
};
static ShaderProgramSource ParseShader(const std::string& filepath)
{
std::ifstream stream(filepath);
enum class ShaderType
{
NONE = -1, VERTEX = 0, FRAGMENT = 1
};
std::string line;
std::stringstream ss[2];
ShaderType type = ShaderType::NONE;
while (getline(stream, line))
{
if (line.find("#shader") != std::string::npos)
{
if (line.find("vertex") != std::string::npos)
type = ShaderType::VERTEX;
else if (line.find("fragment") != std::string::npos)
type = ShaderType::FRAGMENT;
}
else
{
ss[(int)type] << line << '\n';
}
}
return{ ss[0].str(), ss[1].str() };
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 800, "pp", NULL, NULL);
if (window == NULL)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGL();
glViewport(0, 0, 800, 800);
GLfloat vertices[] =
{
-0.5f, -0.5f, 0.0f, 0.0f,//unten Links
0.5f, -0.5f, 1.0f, 0.0f,//untenRechts
0.5f, 0.5f, 1.0f, 1.0f,//open Rechts
-0.5f, 0.5f, 0.0f, 1.0f,//open links
};
unsigned int indices[] =
{
0,1,2,
2,3,0,
};
ShaderProgramSource source = ParseShader("Basic.shader");
const char* vertexShader = source.VertexSource.c_str();
const char* fragmentShader = source.FragmentSource.c_str();
Shader ShaderProgramm(vertexShader, fragmentShader);
TextureClass DirtTexture("Dirt.png");
DirtTexture.Bind(0);
int Loc1 = ShaderProgramm.GetUniformId("tex0");
glUniform1i(Loc1, 0);
VAO vao;
VBO vbo(vertices, sizeof(vertices));
IBO ibo(indices, sizeof(indices));
vbo.Bind();
vao.Bind();
ibo.Bind();
glEnableVertexAttribArray(0);
vao.LinkAttrib(vbo, 0, 2, GL_FLOAT, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
vao.LinkAttrib(vbo, 1, 2, GL_FLOAT, 4 * sizeof(float), (void*)1);
//Main Loop
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glUniform1i(Loc1, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
DirtTexture.Delete();
ShaderProgramm.Delete();
vbo.Delete();
vao.Delete();
ibo.Delete();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
And here is my VAO class
#pragma once
#include<glad/glad.h>
#include "VAO.h"
VAO::VAO()
{
glGenVertexArrays(1, &ID);
glBindVertexArray(ID);
}
void VAO::enable()
{
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
}
void VAO::LinkAttrib(VBO& VBO, GLuint layout, GLuint numComponents, GLenum type, GLsizeiptr stride, void* offset)
{
VBO.Bind();
glVertexAttribPointer(layout, numComponents, type, GL_FALSE, stride, offset);
glEnableVertexAttribArray(layout);
VBO.Unbind();
}
void VAO::Bind()
{
glBindVertexArray(ID);
}
void VAO::Delete()
{
glDeleteVertexArrays(1, &ID);
}
It's not clear how your VAO class works internally, but this looks really broken:
vao.LinkAttrib(vbo, 1, 2, GL_FLOAT, 4 * sizeof(float), (void*)1);
glVertexAttribPointer uses the offset in bytes, so the correct offset matching your vertex data is 2*sizeof(GLfloat), not 1.
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);
I'm using GLFW, OpenGL 4.6 with VSCode, and MinGW64 g++. I'm trying to render a transparent texture using glEnable(GL_BLEND); and glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);. Whilst the texture does render on my window, it seems like the glClearColor() affects the blend significantly. I'm still very new to graphics, so I'm not sure how I can render the texture properly regardless of what the clear color is set to. Also, do I need to enable Depth for 2D games? (shader.cpp and texture.cpp is taken from The Cherno's OpenGL tutorial series)
Without blend
With blend
With blend and black clear color (Desired blend)
main.cpp:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "GeometryUtil.h"
#include "Shader.h"
#include "Texture.h"
#include "Object.h"
#include <iostream>
#include <vector>
using namespace std;
int main() {
if (!glfwInit()) { // Initialise GLFW
cerr << "Failed to initialize GLFW" << endl;
return -1;
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window {glfwCreateWindow(1280, 720, "2D GAME", NULL, NULL)};
if (window == NULL) {
cerr << "Failed to open GLFW window." << endl;
glfwTerminate();
return -1;
}
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
glfwMakeContextCurrent(window);
glewExperimental = true;
if (glewInit() != GLEW_OK) {
cerr << "Failed to initialize GLEW" << endl;
glfwTerminate();
return -1;
}
cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
Object object {608, 392};
vector<float> vectorData;
createQuad(object.getX(), object.getY(), vectorData);
static const GLfloat texCoords[8] {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
GLuint VBOs[2];
glGenBuffers(2, VBOs);
glBindBuffer(GL_ARRAY_BUFFER, VBOs[0]);
glBufferData(GL_ARRAY_BUFFER, vectorData.size() * sizeof(vectorData), &vectorData.front(), GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) 0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat)));
glBindBuffer(GL_ARRAY_BUFFER, VBOs[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
static const GLuint texIndex[6] {
0, 1, 2,
1, 2, 3
};
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(texIndex), texIndex, GL_STATIC_DRAW);
glm::mat4 Projection {glm::ortho(0.0f, 1280.0f, 0.0f, 720.0f, 0.0f, 1.0f)};
glm::mat4 View {glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, 0))};
glm::vec3 translationA {glm::vec3(0, 0, 0)};
glm::mat4 Model = glm::translate(glm::mat4(1.0f), translationA); // Model Matrix (Using Identity Matrix - Origin)
glm::mat4 mvp = Projection * View * Model;
Shader shader {"shader/vertexShader.vert", "shader/fragmentShader.frag"};
shader.bind();
shader.setUniformMat4f("MVP", mvp);
int sampler[] {0, 1};
shader.setUniform1iv("v_Textures", sampler, 2);
Texture texture {"resources/sprites/test.png"};
texture.bind();
while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose(window) == 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
texture.cpp:
#define STB_IMAGE_IMPLEMENTATION
#include <GL/glew.h>
#include "Texture.h"
#include "stb_image.h"
#include <iostream>
Texture::Texture(const std::string &path)
: rendererID{0}, filePath{path}, localBuffer{nullptr}, width{0}, height{0}, bPP{0} {
// stbi_set_flip_vertically_on_load(1);
localBuffer = stbi_load(path.c_str(), &width, &height, &bPP, 4);
if (localBuffer == nullptr)
std::cout << "Unable to load texture file: " << path << std::endl;
glGenTextures(1, &rendererID);
glBindTexture(GL_TEXTURE_2D, rendererID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer);
unbind();
if (localBuffer)
stbi_image_free(localBuffer);
}
Texture::~Texture() {
glDeleteTextures(1, &rendererID);
}
void Texture::bind(GLuint slot) const {;
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, rendererID);
}
void Texture::unbind() const {
glBindTexture(GL_TEXTURE_2D, 0);
}
vertex shader:
#version 460 core
layout(location = 0) in vec3 vertexCoords;
layout(location = 1) in vec2 textureCoords;
layout(location = 2) in float textureIndex;
out vec2 v_TexCoords;
out float v_TexIndex;
uniform mat4 MVP;
void main() {
gl_Position = MVP * vec4(vertexCoords, 1.0);
v_TexCoords = textureCoords;
v_TexIndex = textureIndex;
}
fragment shader:
#version 460 core
in vec2 v_TexCoords;
in float v_TexIndex;
uniform sampler2D v_Textures[2];
void main() {
gl_FragColor = texture2D(v_Textures[int(v_TexIndex)], v_TexCoords);
}
Everthing is correct codewise on the first look, and yes, the Background will affect the Blending in the case of GL_SRC_ALPHA as first pararmeter.
The issue is the second parameter which should be GL_ONE_MINUS_SRC_ALPHA instead of GL_ONE_MINUS_SRC1_ALPHA. In your case the blend is not normalized and so the values of too much green and a full red add up to that yellowish.
source: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFuncSeparate.xhtml
I'm trying to get the depthmap of a shape using the depth buffer (and ortographic projection), but somehow the y-axis is flipped.
I use an OpenCV Mat to display the depth map.
Here is my code:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
int main(void)
{
GLFWwindow *window;
int screenWidth = 450, screenHeight = 350;
GLfloat color[] =
{
255, 0, 0,
0, 255, 0,
0, 0, 255
};
GLfloat vertices[] =
{
-200.0f, -50.0f, -100.0f,
250.0f, 150.0f, 0.0f,
100.0f, 300.0f, 0.0f
};
if (!glfwInit())
{
return -1;
}
// Create windows
window = glfwCreateWindow(screenWidth, screenHeight, "Test", NULL, NULL);
cv::namedWindow("Depthmap", cv::WindowFlags::WINDOW_AUTOSIZE);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-200.0f, 250.0f, -50.0f, 300.0f, 0, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
while (true)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glColorPointer(3, GL_FLOAT, 0, color);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
//To opencv mat
cv::Mat depth = cv::Mat_<float>(screenHeight, screenWidth);
glReadPixels(0, 0, depth.cols, depth.rows, GL_DEPTH_COMPONENT, GL_FLOAT, depth.data);
cv::imshow("Depthmap", depth);
glfwSwapBuffers(window);
glfwPollEvents();
}
return 0;
}
And here is the result:
The actual depth seems to be correct (the red point is 1.0 and the green and blue points are 0.0) but the y-axis is inverted. Why is this and how can I fix it properly?
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);