OpenGL/C++: Problem passing multiple textures to one shader - opengl

I followed the tutorial on https://learnopengl.com/Lighting/Lighting-maps and got some weird errors when using multiple textures (one for specular and one for diffuse lighting). When using only one Texture everything works fine but after using two textures, the cube renders either only black or only the specular texture is applied.
I searched through all similar questions on stackoverflow and read through the OpenGL documentation but still can't figure out why the second texture is not working.
This is the render-loop part of my main.cpp that is creating the cube that is supposed to be rendered with the two textures. The shaders and textures all load and compile fine.
// Load textures
Texture groundTexture = Texture("GROUND", TEXTURE_DIR+"png/container2.png");
Texture groundSpecular = Texture("SPECULAR", TEXTURE_DIR+"png/container2_specular.png");
// Load shaders
Shader textureShader = Shader("SIMPLE_TEXTURE", SHADER_DIR+"vertex/texture_lighted.vs", SHADER_DIR+"fragment/texture_lighted.fs");
Shader lampShader = Shader("WHITE", SHADER_DIR+"vertex/basic.vs", SHADER_DIR+"fragment/white.fs");
// projection matrix
glm::mat4 projection = glm::perspective(glm::radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// shader configuration
// --------------------
textureShader.use();
// Get the uniform variables location.
GLuint diffLocation = glGetUniformLocation(textureShader.ID, "material.diffuse");
GLuint specLocation = glGetUniformLocation(textureShader.ID, "material.specular");
Another weird thing is that if I change the 0 and 1 to groundTexture.ID and groundSpecular.ID, at least the specular part renders, even though glUniform1i expects the unit numbers here and not the Texture-IDs.
// Then bind the uniform samplers to texture units:
glUseProgram(textureShader.ID);
glUniform1i(diffLocation, 0);
glUniform1i(specLocation, 1);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// Calc time
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// be sure to activate shader when setting uniforms/drawing objects
textureShader.use();
textureShader.setVec3("light.position", lightPos);
textureShader.setVec3("viewPos", camera.Position);
// light properties
textureShader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
textureShader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
textureShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
// material properties
textureShader.setFloat("material.shininess", 64.0f);
// view/projection transformations
glm::mat4 view = camera.getViewMatrix();
textureShader.setMat4("projection", projection);
textureShader.setMat4("view", view);
// world transformation
glm::mat4 model = glm::mat4(1.0f);
textureShader.setMat4("model", model);
// bind texture-maps
glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
glBindTexture(GL_TEXTURE_2D, groundTexture.ID);
glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1
glBindTexture(GL_TEXTURE_2D, groundSpecular.ID);
glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
// render the cube
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
For completeness sake, here's also my shader-class and texture-class:
#include "shader.h"
#include <stdlib.h>
#include <string.h>
#include <glad/glad.h>
#include <iostream>
#include <glm/ext.hpp>
#include <fstream>
#include <sstream>
/*
* Creates a new Shader.
* name = name of the shader
* vShader = vertex shader
* fShader = fragment shader
*/
Shader::Shader(std::string name, std::string vShaderPath, std::string fShaderPath) {
this->name = name;
this->vShaderPath = vShaderPath;
this->fShaderPath = fShaderPath;
compileAndLink();
}
Shader::Shader(const Shader& s) {
this->name = s.name;
this->vShaderPath = s.vShaderPath;
this->fShaderPath = s.fShaderPath;
compileAndLink();
}
void Shader::compileAndLink() {
std::string vShader, fShader;
std::ifstream v_inFile, f_inFile;
std::stringstream v_strStream, f_strStream;
// Read File for vertexShader
v_inFile.open(vShaderPath);
if (!v_inFile.is_open()) {
std::cout << "ERROR LOADING VERTEX SHADER FILE: " << vShaderPath << std::endl;
} else {
v_strStream << v_inFile.rdbuf();
vShader = v_strStream.str();
}
// Read File for fragmentShader
f_inFile.open(fShaderPath);
if (!f_inFile.is_open()) {
std::cout << "ERROR LOADING FRAGMENT SHADER FILE: " << fShaderPath << std::endl;
} else {
f_strStream << f_inFile.rdbuf();
fShader = f_strStream.str();
}
// Compile and link
const char* vertex_shader = vShader.c_str();
const char* fragment_shader = fShader.c_str();
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertex_shader, 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, &fragment_shader, 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;
}
// store reference in ID
ID = glCreateProgram();
// link shaders
glAttachShader(ID, vertexShader);
glAttachShader(ID, fragmentShader);
glLinkProgram(ID);
// check for linking errors
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
// clean up
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
}
/*
* Tell OpenGL to use this shader-program.
*/
void Shader::use() {
glUseProgram(ID);
}
and
#include <glad/glad.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "../image-loader/stb_image.h"
#include "texture.h"
Texture::Texture(std::string name, std::string path) {
this->name = name;
this->path = path;
createTexture();
}
Texture::Texture(const Texture& t) {
this->name = t.name;
this->path = t.path;
createTexture();
}
void Texture::createTexture() {
unsigned int texture;
glGenTextures(1, &texture); // generate one texture
// Load file
int width, height, nrChannels;
unsigned char *data = stbi_load(this->path.c_str(), &width, &height, &nrChannels, 0);
if (data) {
GLenum format;
if (nrChannels == 1)
format = GL_RED;
else if (nrChannels == 3)
format = GL_RGB;
else if (nrChannels == 4)
format = GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
// Set Texture Parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // x
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // y
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
stbi_image_free(data); // clean up
} else {
std::cout << "Failed to load texture" << std::endl;
}
this->ID = texture;
}
void Texture::use() {
glBindTexture(GL_TEXTURE_2D, this->ID);
}
I am using OpenGL 4.4, initialized like below and glad to load the OpenGL function pointers.
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Thanks in advance.
EDIT:
Here are the two shaders (obviously important):
texture_lighted.vs (vertex shader)
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
FragPos = vec3(model * vec4(aPos, 1.0));
TexCoords = aTexCoords;
// transpose normal vectors with normal matrix of model matrix
Normal = mat3(transpose(inverse(model))) * aNormal;
}
And texture_lighted.fs (fragment shader)
#version 330 core
out vec4 FragColor;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
uniform Light light;
void main()
{
// ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}

After the name (value) of the texture is generated by glGenTexture, the named texture has to be bound to a texturing target by glBindTexture, before the texture image is specified by glTexImage2D.
glTexImage2D defines the texture images for the texture, which is currently bound to the specified target:
glGenTextures(1, &texture);
// [...]
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);

Related

OpenGL Transparent textures overlapping/blending issue

I'm making a simple 2D game using OpenGL 4.6 in C++. I've currently got both depth testing and blending enabled, where I've been able to render my transparent textures properly. However, when I move one texture to the point that it overlaps another texture, the transparent pixels overlap the texture underneath as well. All my vertices have a z depth value of 0.0f. Would it be better to just disable depth testing? If not, how can I resolve this?
Initial:
Overlap:
Main.cpp:
// Initialize application
GLFWwindow *window = init();
if (!window)
return -1;
// Settings
cout << "OpenGL Version: " << glGetString(GL_VERSION) << endl;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
// Entities
GameUI gameUI;
glfwSetWindowUserPointer(window, &gameUI);
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);
glm::mat4 mvp = Projection * View * Model;
Shader shader {"shader/vertex.vert", "shader/fragment.frag"};
shader.bind();
shader.setUniformMat4f("MVP", mvp);
int sampler[] {0, 1, 2};
shader.setUniform1iv("v_Textures", sampler, 3);
// MAIN LOOP //
while (glfwWindowShouldClose(window) == 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// glClear(GL_COLOR_BUFFER_BIT);
gameUI.update();
gameUI.draw();
glfwSwapBuffers(window);
glfwPollEvents();
// cout << glGetError() << endl;
}
Vertex Shader:
#version 460 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
layout(location = 2) in float texIndex;
out vec2 v_TexCoord;
out float v_TexIndex;
uniform mat4 MVP;
void main() {
gl_Position = MVP * vec4(position, 1.0);
v_TexCoord = texCoord;
v_TexIndex = texIndex;
}
Fragment Shader:
#version 460 core
in vec2 v_TexCoord;
in float v_TexIndex;
uniform sampler2D v_Textures[3];
void main() {
gl_FragColor = texture(v_Textures[int(v_TexIndex)], v_TexCoord);
}

imageStore() doesn't work with integer types

I bind a texture to both a texture unit and a image unit, write to it via imageStore() in the compute shader, and sample it with a sampler2D in the fragment shader.
This works when the pixel format is floating point, but stops working with integers. glGetError() yields nothing.
glew and glm are used; should be irrelevant to the problem though.
main.cpp:
constexpr glm::vec2 TEX_DIM = { 2048.0f, 2048.0f / ASPECT_RATIO };
constexpr int LOCAL_WORKGROUP_SIZE = 32;
// After setting up vbo, etc //////////
// Texture
const unsigned int texSlot = 0;
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0 + texSlot);
glBindTexture(GL_TEXTURE_2D, texId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, int(TEX_DIM.x), int(TEX_DIM.y), 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);
// Binding to image unit
const unsigned int imageSlot = 0;
glBindImageTexture(imageSlot, texId, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8);
// Shaders
unsigned int computeShader;
unsigned int graphicsShader;
// After creating shaders //////////
// Graphics shader
glUseProgram(graphicsShader);
glUniform1i(glGetUniformLocation(graphicsShader, "uTexture"), texSlot);
glUniformMatrix4fv(glGetUniformLocation(graphicsShader, "uMVP"), 1, GL_FALSE, &mvp);
auto mvp = glm::ortho(0.0f, (float)WINDOW_WIDTH, 0.0f, (float)WINDOW_HEIGHT, -1.0f, 1.0f);
// Compute shader
glUseProgram(computeShader);
glUniform1i(glGetUniformLocation(computeShader, "uImage"), imageSlot);
// After validating shaders //////////
while (true)
{
// Compute
glUseProgram(computeShader);
glDispatchCompute(TEX_DIM.x / LOCAL_WORKGROUP_SIZE, TEX_DIM.y / LOCAL_WORKGROUP_SIZE, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
// Draw
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(graphicsShader);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwSwapBuffers(window);
}
Compute Shader:
# version 430 core
layout(local_size_x = 32, local_size_y = 32) in;
layout(r8) uniform image2D uImage;
void main()
{
// Writing all to red, for testing purpose
imageStore(uImage, ivec2(gl_GlobalInvocationID.xy), vec4(1.0, 0.0, 0.0, 0.0));
}
Vertex Shader:
# version 430 core
layout(location = 0) in vec2 position;
layout(location = 1) in vec2 texCoord;
out vec2 vTexCoord;
uniform mat4 uMVP;
void main()
{
gl_Position = uMVP * vec4(position, 0.0, 1.0);
vTexCoord = texCoord;
}
Fragment Shader:
# version 430 core
in vec2 vTexCoord;
out vec4 color;
uniform sampler2D uTexture;
void main()
{
color = vec4(
texture(uTexture, vTexCoord).x,
0.0, 0.0, 1.0
);
}
Below is my attempt to convert the minimal program to be using integers instead; gives me a black screen but no errors otherwize.
main.cpp:
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8UI, int(TEX_DIM.x), int(TEX_DIM.y), 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, nullptr);
glBindImageTexture(imageSlot, texId, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_R8UI);
Compute Shader:
layout(r8ui) uniform uimage2D uImage;
void main()
{
// Writing all to red, for testing purpose
imageStore(uImage, ivec2(gl_GlobalInvocationID.xy), uvec4(255, 0, 0, 0));
}
Fragment Shader:
uniform usampler2D uTexture;
void main()
{
color = vec4(
float(texture(uTexture, vTexCoord).x) / 256.0,
0.0, 0.0, 1.0
);
}
I've thought about GL_R8UI being incompatable but the wiki says both GL_R8 and GL_R8UI are fine to use.

A Point Light in Opengl Deferred lighting is ~ 180 degrees?

I am trying to make a simple deferred lighting scene in OpenGL, but the problem after the implementation of a 1 point light I got a 180 degree lighted surface :
screenshot 1 :
screenshot 2 :
Here is my code :
Material shaderGeometryPass("Shaders/deff_shader.vers", "Shaders/deff_shader.frags");
Material shaderLightingPass("Shaders/deff_light.vers", "Shaders/deff_light.frags");
shaderLightingPass.Use();
shaderLightingPass.setInt("gPosition", 0);
shaderLightingPass.setInt("gNormal", 1);
shaderLightingPass.setInt("gAlbedoSpec", 2);
// configure g-buffer framebuffer
// ------------------------------
unsigned int gBuffer;
glGenFramebuffers(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
unsigned int gPosition, gNormal, gAlbedoSpec;
// position color buffer
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
// normal color buffer
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_weight, SCR_height, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
// color + specular color buffer
glGenTextures(1, &gAlbedoSpec);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_weight, SCR_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedoSpec, 0);
// tell OpenGL which color attachments we'll use (of this framebuffer) for rendering
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
// create and attach depth buffer (renderbuffer)
unsigned int rboDepth;
glGenRenderbuffers(1, &rboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_weight, SCR_height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
// finally check if framebuffer is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "Framebuffer not complete!" << std::endl;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window) == 0)
{
camera.ComputeMatrices();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 1. geometry pass: render scene's geometry/color data into gbuffer
// -----------------------------------------------------------------
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (size_t i = 0; i < mScene.all_children.size(); i++)
{
if (mScene.all_children[i]->Get_component_id(Comp_Mesh) >= 0)
{
bool get_suc = false;
RMesh &get_mesh = meshs.GetMesh(mScene.all_children[i]->Get_component_id(Comp_Mesh), get_suc);
if (get_suc)
{
if (!get_mesh.mesh_available) continue;
get_mesh.UseVertex();
shaderGeometryPass.Use();
glm::mat4 ModelMatrix = glm::scale(translate(mat4(1.0), mScene.all_children[i]->transform.Position), mScene.all_children[i]->transform.Scale);
shaderGeometryPass.SetMat4("projection", camera.GetProjectionMatrix());
shaderGeometryPass.SetMat4("view", camera.GetViewMatrix());
shaderGeometryPass.SetMat4("model", ModelMatrix);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1));
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2));
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(shaderGeometryPass.GetUniform("texture_diffuse"), 0);
glUniform1i(shaderGeometryPass.GetUniform("texture_specular"), 1);
// 1rst attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, get_mesh.normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, get_mesh.elementbuffer);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, get_mesh.indices.size(), GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
get_mesh.EndVertex();
}
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 2. lighting pass: calculate lighting by iterating over a screen filled quad pixel-by-pixel using the gbuffer's content.
// -----------------------------------------------------------------------------------------------------------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderLightingPass.Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
// send light relevant uniforms
for (size_t i = 0; i < mScene.all_children.size(); i++)
{
if (mScene.all_children[i]->Get_component_id(Comp_PointLight) >= 0)
{
int g;
if (Point_lights.GetLight(mScene.all_children[i]->Get_component_id(Comp_PointLight), &g))
{
if (Point_lights.lights[g].light_id == mScene.all_children[i]->Get_component_id(Comp_PointLight))
{
Point_lights.lights[g].Position = mScene.all_children[i]->transform.Position;
}
}
}
if (Point_lights.lights.size() > 0)
{
shaderLightingPass.SetVec3("lights[0].Position", Point_lights.lights[0].Position);
shaderLightingPass.SetVec3("lights[0].Color", Point_lights.lights[0].Color);
// update attenuation parameters and calculate radius
const float constant = 1.0;
const float linear = Point_lights.lights[0].Range;
const float quadratic = 1.8;
shaderLightingPass.SetFloat("lights[0].Linear", linear);
shaderLightingPass.SetFloat("lights[0].Quadratic", quadratic);
// then calculate radius of light volume/sphere
const float maxBrightness = Point_lights.lights[0].Energy; //std::fmaxf(std::fmaxf(Point_lights.lights[0].Color.r, Point_lights.lights[0].Color.g), Point_lights.lights[0].Color.b);
float radius = (-linear + std::sqrt(linear * linear - 4 * quadratic * (constant - (256.0f ) * maxBrightness))) / (2.0f * quadratic);
shaderLightingPass.SetFloat("lights[0].Radius", radius);
}
}
shaderLightingPass.SetVec3("viewPos", camera.transform.Position);
renderQuad();
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
"deff_light.vers" shader :
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos, 1.0);
}
"deff_light.frags" shader :
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;
struct Light {
vec3 Position;
vec3 Color;
float Linear;
float Quadratic;
float Radius;
};
const int NR_LIGHTS = 1;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPos;
void main()
{
// retrieve data from gbuffer
vec3 FragPos = texture(gPosition, TexCoords).rgb;
vec3 Normal = texture(gNormal, TexCoords).rgb;
vec3 Diffuse = texture(gAlbedoSpec, TexCoords).rgb;
float Specular = texture(gAlbedoSpec, TexCoords).a;
// then calculate lighting as usual
vec3 lighting = Diffuse * 0.1; // hard-coded ambient component
vec3 viewDir = normalize(viewPos - FragPos);
for(int i = 0; i < NR_LIGHTS; ++i)
{
// calculate distance between light source and current fragment
float distance = length(lights[i].Position - FragPos);
if(distance < lights[i].Radius)
{
// diffuse
vec3 lightDir = normalize(lights[i].Position - FragPos);
vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Diffuse * lights[i].Color;
// specular
vec3 halfwayDir = normalize(lightDir + viewDir);
float spec = pow(max(dot(Normal, halfwayDir), 0.0), 16.0);
vec3 specular = lights[i].Color * spec * Specular;
// attenuation
float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
diffuse *= attenuation;
specular *= attenuation;
lighting += diffuse + specular;
}
}
FragColor = vec4(lighting, 1.0);
}
"deff_shader.vers" shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec2 TexCoords;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
vec4 worldPos = model * vec4(aPos, 1.0);
FragPos = worldPos.xyz;
TexCoords = aTexCoords;
mat3 normalMatrix = transpose(inverse(mat3(model)));
Normal = normalMatrix * aNormal;
gl_Position = projection * view * worldPos;
}
"deff_shader.frags" shader:
#version 330 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;
in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;
uniform sampler2D texture_diffuse1;
uniform sampler2D texture_specular1;
void main()
{
// store the fragment position vector in the first gbuffer texture
gPosition = FragPos;
// also store the per-fragment normals into the gbuffer
gNormal = normalize(Normal);
// and the diffuse per-fragment color
gAlbedoSpec.rgb = texture(texture_diffuse1, TexCoords).rgb;
// store specular intensity in gAlbedoSpec's alpha component
gAlbedoSpec.a = texture(texture_specular1, TexCoords).r;
}
What I am doing wrong ?
Any help please ?

Scene is all in shadow

My shadow map seem to be casting shadows everywhere and i don't know why.
Here is where i set up the FBO and depth texture
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
// Depth texture. Slower than a depth buffer, but you can sample it later in your shader
glGenTextures(1, &shadowMap);
glBindTexture(GL_TEXTURE_2D, shadowMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, 800, 600, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMap, 0);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
// Always check that our framebuffer is ok
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
cout << "shadowMap fail" << endl;
Here are my two passes
// clear the screen
glEnable(GL_CULL_FACE);
glClearColor(0.5f,0.5f,0.5f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 projection(1.0);
projection = glm::perspective(float(60.0f*DEG_TO_RADIAN),800.0f/600.0f,1.0f,150.0f);
rt3d::setUniformMatrix4fv(shaderProgram, "projection", glm::value_ptr(projection));
GLfloat scale(1.0f); // just to allow easy scaling of complete scene
glm::mat4 modelview(1.0); // set base position for scene
mvStack.push(modelview);
for (int pass = 0; pass < 2; pass++) {
if (pass == 0) {
glUseProgram(shadowMapProgram);
glm::vec3 lightInvDir = glm::vec3(lightPos.x, lightPos.y, lightPos.z);
oldeye = eye;
eye = lightInvDir;
at = glm::vec3(0, 0, 0);
up = glm::vec3(0, 1, 0);
// Compute the MVP matrix from the light's point of view
glm::mat4 depthViewMatrix = glm::lookAt(eye, at ,up);
depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
uniformIndex = glGetUniformLocation(shadowMapProgram, "depthMVP");
glUniformMatrix4fv(uniformIndex, 1, GL_FALSE, &depthMVP[0][0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMap, 0);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rt3d::setUniformMatrix4fv(shadowMapProgram, "projection", glm::value_ptr(depthProjectionMatrix));
uniformIndex = glGetUniformLocation(shadowMapProgram, "modelMatrix");
glUniformMatrix4fv(uniformIndex, 1, GL_FALSE, glm::value_ptr(depthModelMatrix));
cout << uniformIndex << " DepthModelMatrix" << endl;
}
if (pass == 1) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
eye = oldeye;
at = moveForward(eye, r, 1.0f);
up = glm::vec3(0, 1, 0);
glUseProgram(toonShaderProgram);
glm::mat4 depthBiasMVP = biasMatrix*depthMVP;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
//uniformIndex = glGetUniformLocation(toonShaderProgram, "depthBiasMVP");
// glUniformMatrix4fv(uniformIndex, 1, GL_FALSE, &depthBiasMVP[0][0]);
//cout << uniformIndex << " depthBiasMVP" << endl;
rt3d::setUniformMatrix4fv(toonShaderProgram, "depthBiasMVP", glm::value_ptr(depthBiasMVP));
uniformIndex = glGetUniformLocation(toonShaderProgram, "shadowMap");
glUniform1i(uniformIndex, shadowMap);
//cout << uniformIndex << " shadowMap" << endl;
rt3d::setUniformMatrix4fv(toonShaderProgram, "projection", glm::value_ptr(projection));
uniformIndex = glGetUniformLocation(toonShaderProgram, "modelMatrix");
glUniformMatrix4fv(uniformIndex, 1, GL_FALSE, glm::value_ptr(depthModelMatrix));
cout << uniformIndex << " modelMatrix" << endl;
}
mvStack.top() = glm::lookAt(eye, at, up);
//render scene
My shadow map shaders
.vert
#version 330
// Input vertex data, different for all executions of this shader.
in vec3 in_Position;
// Values that stay constant for the whole mesh.
uniform mat4 depthMVP;
uniform mat4 modelMatrix;
uniform mat4 projection;
void main(){
vec4 vertexPosition = modelMatrix * vec4(in_Position,1.0);
gl_Position = depthMVP * vertexPosition;
}
.frag
#version 330
void main(){
// Not really needed, OpenGL does it anyway
gl_FragColor = vec4(gl_FragCoord.z);
}
and my Phong shaders
.vert
...
out vec4 ShadowCoord;
uniform mat4 modelMatrix;
void main(void) {
...
gl_Position = projection * vertexPosition;
vec4 shadowPos = (modelMatrix * vec4(in_Position,1.0));
ShadowCoord = depthBiasMVP * shadowPos;
ShadowCoord = ShadowCoord/ ShadowCoord.w;
.frag
....
if ((ShadowCoord.x < 0 || ShadowCoord.x > 1 || ShadowCoord.y < 0 || ShadowCoord.y > 1 || ShadowCoord.z < 0 || ShadowCoord.z > 1)){
visibility = 0.5f;
}else{
float shadowDepth = texture(shadowMap, ShadowCoord.xy).r;
if(shadowDepth<ShadowCoord.z-bias)
visibility = 0.0f;
}
// Ambient intensity
vec4 ambientI = light.ambient * material.ambient;
// Diffuse intensity
vec4 diffuseI = light.diffuse * material.diffuse *visibility;
diffuseI = diffuseI * max(dot(normalize(ex_N),normalize(ex_L)),0);
// Specular intensity
// Calculate R - reflection of light
vec3 R = normalize(reflect(normalize(-ex_L),normalize(ex_N)));
vec4 specularI = light.specular * material.specular *visibility;
specularI = specularI * pow(max(dot(R,ex_V),0), material.shininess);
// Fragment colour
out_Color = (ambientI + diffuseI + specularI) * texture(textureUnit0, ex_TexCoord);
I really can't work out what i am doing wrong. All my scene is cast in shadow.
I have tried various things including rendering my shadow map on screen( as shown) and doing the calculations using different matrices but i still can't figure it out.
Does it matter what space I calculate my ShadowCoords in, i've been using modelview, would model be better?
Here is my scene

OpenGL Framebuffer - rendering to texture

I made an application which renders skybox and particles over it. I want to add some effects and i need to use framebuffers to render skybox, particles color, depth and position to separate textures. Then i want to use simple shader to use values from these textures and mix them in a proper way. I wrote helper classes for textures, framebuffers and screen quad (simple rectangle to render) but unfortunately - nothing renders when i try to use it.
When binding framebuffers is commented out, my scene looks like this:
Modifying shader shows that depth and position values are calculated properly. Therefore problem lays in texture and framebuffers way of using. Time for some code:
Framebuffer helper class (only important methods):
void Framebuffer::init(){
// unbind all textures from openGL
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &framebuffer);
}
void Framebuffer::bind(){
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}
void Framebuffer::unbind(){
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void Framebuffer::attachTexture(GLuint texture, GLenum attachmentType){
glBindTexture(GL_TEXTURE_2D, texture);
glFramebufferTexture(GL_FRAMEBUFFER, attachmentType, texture, 0);
}
void Framebuffer::drawBuffers(GLsizei n, const GLenum *buffers){
glDrawBuffers(n, buffers);
}
Texture helper class:
void Texture::init(GLuint windowWidth, GLuint windowHeight, GLint internalFormat, GLenum format, GLenum type){
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D( GL_TEXTURE_2D, 0, internalFormat , windowWidth, windowHeight, 0, format, type, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
void Texture::bind(){
glBindTexture(GL_TEXTURE_2D, texture);
}
void Texture::unbind(){
glBindTexture(GL_TEXTURE_2D, 0);
}
GLuint Texture::getId(){
return texture;
}
ScreenQuad class:
void ScreenQuad::init(void){
vao.createVAO();
vao.bindVAO();
vbo.createVBO();
vbo.addData(vertices, 8*sizeof(GLfloat));
vbo.bindVBO(GL_ARRAY_BUFFER);
vbo.uploadDataToGPU(GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)3, 2, GL_FLOAT, GL_FALSE, 0, NULL);
loadShaders("shaders/basicPostShader.vp", "shaders/basicPostShader.fp");
}
void ScreenQuad::loadShaders(string vsPath, string fsPath){
shaderProgram.createProgram();
shaderProgram.loadVertexShader(vsPath);
shaderProgram.loadFragmentShader(fsPath);
glBindAttribLocation(shaderProgram.getProgramID(), 3, "v_coord");
shaderProgram.linkProgram();
}
void ScreenQuad::draw(GLuint depthTexture, GLuint colorTexture, GLuint positionTexture, GLuint backgroundTexture){
shaderProgram.bindProgram();
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);
shaderProgram.setUniform("u_depthtex", 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorTexture);
shaderProgram.setUniform("u_colortex", 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, positionTexture);
shaderProgram.setUniform("u_positiontex", 2);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
shaderProgram.setUniform("u_backgroundtex", 3);
glEnableVertexAttribArray(3);
vbo.bindVBO();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
vbo.unbindVBO();
glDisableVertexAttribArray(3);
shaderProgram.unbindProgram();
}
and methods for initialization and rendering scene:
void OpenGLContext::setupScene(void) {
glClearColor(0.4f, 0.6f, 0.9f, 1.0f);
//FRAMEBUFFERS:
skyboxFramebuffer.init();
skyboxTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
skyboxFramebuffer.bind();
skyboxFramebuffer.attachTexture(skyboxTexture.getId(), GL_COLOR_ATTACHMENT0);
const GLenum skyboxDrawBuffers[1] = { GL_COLOR_ATTACHMENT0};
skyboxFramebuffer.drawBuffers(1, skyboxDrawBuffers);
skyboxFramebuffer.validate();
skyboxFramebuffer.unbind();
mainFramebuffer.init();
mainColorTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
mainPositionTexture.init(windowWidth, windowHeight, GL_RGBA32F, GL_RGBA, GL_FLOAT);
mainDepthTexture.init(windowWidth, windowHeight, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT);
mainFramebuffer.bind();
mainFramebuffer.attachTexture(mainColorTexture.getId(), GL_COLOR_ATTACHMENT0);
mainFramebuffer.attachTexture(mainPositionTexture.getId(), GL_COLOR_ATTACHMENT1);
mainFramebuffer.attachTexture(mainDepthTexture.getId(), GL_DEPTH_ATTACHMENT);
const GLenum mainDrawBuffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
mainFramebuffer.drawBuffers(2, mainDrawBuffers);
mainFramebuffer.validate();
mainFramebuffer.unbind();
//SKYBOX:
skybox->init("resources/skybox/default/",
"pos_x.tga",
"neg_x.tga",
"pos_y.tga",
"neg_y.tga",
"pos_z.tga",
"neg_z.tga");
//PARTICLES:
particles->init(scene);
//SCREENQUAD:
screenQuad.init();
}
void OpenGLContext::renderScene() {
glfwGetFramebufferSize(window, &windowWidth, &windowHeight);
glViewport(0, 0, windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
fpsCounter->calcFPS(1.0, windowName);
if(mode==INPUT_ENABLED_MODE){
updateInputs();
}
projectionMatrix = controls->getProjectionMatrix();
viewMatrix = controls->getViewMatrix();
modelMatrix = glm::mat4(1.0f);
glm::mat4 mvpMatrix = projectionMatrix*viewMatrix*modelMatrix;
//SKYBOX:
skyboxFramebuffer.bind();
skybox->render(mvpMatrix);
skyboxFramebuffer.unbind();
//PARTICLES:
if(scene->tryLockScene()){
if(scene->isSceneUpdated()){
particles->updateParticlesPosition(scene);
scene->setSceneUpdated(false);
}
scene->unlockScene();
}
mainFramebuffer.bind();
particles->draw(modelMatrix, viewMatrix, projectionMatrix);
mainFramebuffer.unbind();
//SCREENQUAD:
screenQuad.draw(mainDepthTexture.getId(), mainColorTexture.getId(), mainPositionTexture.getId(), skyboxTexture.getId());
glfwSwapBuffers(window);
glfwPollEvents();
}
plus screenQuad shaders:
vertex:
#version 430
layout (location = 3) in vec2 v_coord;
layout (binding = 0) uniform sampler2D u_depthtex;
layout (binding = 1) uniform sampler2D u_colortex;
layout (binding = 2) uniform sampler2D u_positiontex;
layout (binding = 3) uniform sampler2D u_backgroundtex;
out vec2 fs_texcoord;
void main(void) {
gl_Position = vec4(v_coord, 0.0, 1.0);
fs_texcoord = (v_coord + 1.0) / 2.0;
}
and fragment:
#version 430
layout (binding = 0) uniform sampler2D u_depthtex;
layout (binding = 1) uniform sampler2D u_colortex;
layout (binding = 2) uniform sampler2D u_positiontex;
layout (binding = 3) uniform sampler2D u_backgroundtex;
layout (location = 0) out vec4 out_Color;
in vec2 fs_texcoord;
void main(void) {
float exp_depth = texture(u_depthtex,fs_texcoord).r;
if(exp_depth>0.99f){
out_Color = vec4(texture(u_backgroundtex,fs_texcoord).xyz,1.0f);
return;
}
out_Color = vec4(texture(u_colortex,fs_texcoord).xyz, 1.0f);
}
Shader helper classes, vao and vbo helper classes are fine for sure. No errors occurs in logs.
UPDATE:
particles vertex shader:
#version 430
uniform mat4x4 modelViewMatrix;
uniform mat4x4 projectionMatrix;
uniform float pointRadius; // point size in world space
uniform float pointScale; // scale to calculate size in pixels
layout (location = 0) in vec3 in_Position;
layout (location = 1) in vec4 in_Color;
out vec3 fs_PosEye;
out vec4 fs_Position;
out vec4 fs_Color;
void main(void) {
vec3 posEye = (modelViewMatrix * vec4(in_Position.xyz, 1.0f)).xyz;
float dist = length(posEye);
gl_PointSize = pointRadius * (pointScale/dist);
fs_PosEye = posEye;
fs_Position = modelViewMatrix * vec4(in_Position.xyz, 1.0f);
fs_Color = in_Color;
gl_Position = projectionMatrix * modelViewMatrix * vec4(in_Position.xyz, 1.0f);
}
fragment shader:
#version 430
uniform mat4x4 modelViewMatrix;
uniform mat4x4 projectionMatrix;
uniform float pointRadius; // point size in world space
uniform float pointScale; // scale to calculate size in pixels
in vec4 fs_Position;
in vec3 fs_PosEye;
in vec4 fs_Color;
layout (location = 0) out vec4 out_Color;
layout (location = 1) out vec4 out_Position;
void main(void)
{
// calculate normal from texture coordinates
vec3 normal;
normal.xy = gl_PointCoord.xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
float r = dot(normal.xy, normal.xy);
if(r>1.0)
discard;
normal.z = sqrt(1.0-r);
//calculate depth
vec4 pixelPos = vec4(fs_PosEye + normalize(normal)*pointRadius,1.0f);
vec4 clipSpacePos = projectionMatrix * pixelPos;
gl_FragDepth = (clipSpacePos.z / clipSpacePos.w);
out_Color = fs_Color;
out_Position = pixelPos;
}
and Particles.draw() method:
void CParticles::draw(glm::mat4 modelMatrix, glm::mat4 viewMatrix, glm::mat4 projectionMatrix){
shaderProgram.bindProgram();
glm::mat4 modelViewMatrix = viewMatrix*modelMatrix;
shaderProgram.setUniform("projectionMatrix", &projectionMatrix);
shaderProgram.setUniform("modelViewMatrix", &modelViewMatrix);
shaderProgram.setUniform("pointRadius", &pointRadius);
shaderProgram.setUniform("pointScale", &pointScale);
glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
glEnable(GL_POINT_SPRITE);
glEnable(GL_PROGRAM_POINT_SIZE);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_POINTS, 0, n);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisable(GL_PROGRAM_POINT_SIZE);
glDisable(GL_POINT_SPRITE);
shaderProgram.unbindProgram();
}
UPDATE2:
The problem is that textures filled by a particle shader are empty when I try to sample data from them in a screenQuad shader. Each depth, position and color texture samplers return zeros. I use same classes and same methods as with a skybox, but skybox texture works fine.
UPDATE3:
Random code changes showed me that if I comment line with attaching depth texture to framebuffer, particle color is finally passed to a texture and i can see it on a screen quad (but without any depth test. Red particles (drawed last) are always on the front).
I guess there is a problem with connecting particle shader with depth texture. But still I can't find an exact bug. I hope my sugestion will be helpful.
I haven't studied the entire code, but one problem jumps out immediately:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorTexture);
shaderProgram.setUniform("u_colortex", colorTexture);
The value of a uniform for a texture sampler is not the texture id (aka name). It's the texture unit the texture is bound to. So in this case, since you're using texture unit 1 for this texture, it should be:
shaderProgram.setUniform("u_colortex", 1);
The problem was that glDepthMask() was disabled when i invoked glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);.
It needs to be enabled in order to glClear(GL_DEPTH_BUFFER_BIT) took any effect.
Plus I needed to add cleaning framebuffers in a proper way as well.