I'm trying out my hand at graphics, following a tutorial at http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_06
Problem: When I try to texture my cube, my sample is black.
Screenshot: http://puu.sh/2JP1H.jpg (note: I set blue = uv.x to test my UVs)
I looked at the threads OpenGL textures appear just black, and
Texture is all black, but it seemed they had different problems.
First I load my texture using SOIL image loading library:
int w, h;
unsigned char* img = SOIL_load_image("resources/images/4x4window.jpg",&w,&h,0,0);
ErrorIf(!img, "%s", SOIL_last_result());
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,img);
My render function where I pass my texture to the shader program:
void onDisplay()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glUniform1i(uniform_myTexture, /*GL_TEXTURE*/0);
glEnableVertexAttribArray(attribute_coord3d); // open shader var
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_verts); // put stuff in buffer
glVertexAttribPointer(attribute_coord3d, 3, GL_FLOAT, GL_FALSE, 0, 0); //send
glEnableVertexAttribArray(attribute_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords);
glVertexAttribPointer(attribute_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements);
int size;
glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(attribute_coord3d);
glDisableVertexAttribArray(attribute_texcoord);
glutSwapBuffers();
}
Vertex Shader:
attribute vec3 coord3d;
attribute vec2 texcoord;
varying vec2 f_texcoord;
uniform mat4 mvp;
void main(void)
{
gl_Position = mvp * vec4(coord3d, 1.0);
f_texcoord = texcoord;
}
Fragment Shader:
varying vec2 f_texcoord;
uniform sampler2D mytexture;
void main(void)
{
vec4 result = texture2D(mytexture, f_texcoord);
result.z = f_texcoord.x;
result.w = 1;
gl_FragColor = result;
}
The line where the the texture is bound is:
glBindTexture(GL_TEXTURE, texture_id);
that should be:
glBindTexture(GL_TEXTURE_2D, texture_id);
Related
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.
I tried to load the same model(modeled in 3Ds max) in opengl, but with different textures. The problem is, that when I try to bind the Texture with glBindTexture after I have acitvated the texture, then it disappears. Before I changed the textures in 3Ds max, it always has show me the model in black color (just in opengl). But I havenĀ“t even assign black color to my model. My image "model-image.png" also contains all textures, that I have assign to my object. So am I missing something?
Thanks for your help in advance.
void initDrawing()
{
glEnable(GL_DEPTH_TEST);
program = glCreateProgram();
std::string shaderV = Utilities::loadFile("shader.vert");
std::string shaderF = Utilities::loadFile("shader.frag");
program = Utilities::compileShader(shaderV, shaderF);
Utilities::loadObj("model.obj", obj);
Utilities::loadPNG("model-image.png", diffuse);
glEnable(GL_TEXTURE_2D);
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glGenBuffers(1, &vPosition);
glBindBuffer(GL_ARRAY_BUFFER, vPosition);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*obj.vertices.size(), &obj.vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vPosition);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
GLuint vCoordinates;
glGenBuffers(1, &vCoordinates);
glBindBuffer(GL_ARRAY_BUFFER, vCoordinates);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*obj.textureCoordinates.size(), &obj.textureCoordinates[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vCoordinates);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glGenTextures(2, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, diffuse.width, diffuse.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
&diffuse.colors[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUseProgram(program);
ModelView = glGetUniformLocation(program, "ModelView");
Projection = glGetUniformLocation(program, "Projection");
Diffuse = glGetUniformLocation(program, "Diffuse");
}
void display()
{
// background color
const GLfloat color[] = { 0.5, 0.5, 0.5, 1 };
glClear(GL_DEPTH_BUFFER_BIT);
glClearBufferfv(GL_COLOR, 0, color);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
modelView = view * model;
glUniformMatrix4fv(ModelView, 1, GL_FALSE, glm::value_ptr(modelView));
glUniformMatrix4fv(Projection, 1, GL_FALSE, glm::value_ptr(projection));
glUniform1i(Diffuse, 0);
glDrawArrays(GL_TRIANGLES, 0, obj.vertices.size());
glutSwapBuffers();
}
My Shader:
fragment shader:
uniform sampler2D Diffuse;
in vec2 fUV;
out vec3 color;
//main for the color
void main(void)
{
color = texture(Diffuse, fUV).rgb;
}
vertex Shader:
layout (location = 0) in vec4 vPosition;
layout (location = 2) in vec2 vCoordinates;
uniform mat4 ModelView;
uniform mat4 Projection;
out vec2 fUV;
void main(void)
{
gl_Position = Projection * ModelView * vPosition;
fUV = vCoordinates;
}
My guess is that when you say
layout(location = 2) in vec2 vCoordinates;
you really mean to say
layout(location = 1) in vec2 vCoordinates;
considering you never enable vertex attribute 2.
Beforehand, sorry for a lot of posted code. I will try to be as straightforward as possible.
My texture is 4x4 texture image in bmp format (if someone interested here it is ->). And as a result of mapping i get color of top leftpixel (0.0, 1.0) (i checked it, it is always color of top left pixel) and my triangle color results in color of that pixel, which is white.
I tried changing GL_NEARESTtoGL_LINEAR in GL_TEXTURE_MAG_FILTER
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
and i get bottom right pixel (1.0, 0.0), which is some kind of green:
I am loading texture using stb_image. So in my Texture.cpp:
Texture::Texture(const std::string& fileName)
{
int width, height, numComponents;
unsigned char* imageData = stbi_load(fileName.c_str(), &width, &height, &numComponents, 4);
if (imageData == NULL)
{
std::cerr << "Error: Texture load failed for texture: " << fileName << std::endl;
}
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
stbi_image_free(imageData);
}
Texture::~Texture(void)
{
glDeleteTextures(1, &_texture);
}
void Texture::Bind(unsigned int unit)
{
assert(unit >= 0 && unit <= 31);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_2D, _texture);
}
In my vertex shader:
#version 150
in vec3 position;
in vec2 texCoord;
out vec2 texCoord0;
void main(void)
{
texCoord0 = texCoord;
gl_Position = vec4(position, 1.0);
}
In my fragment shader:
#version 150
in vec2 textCoord0;
uniform sampler2D texture;
void main(void)
{
gl_FragColor = texture2D(texture, textCoord0);
}
In my main.cpp
#include <iostream>
#include <GL/glew.h>
#include "Display.h"
#include "Shader.h"
#include "Mesh.h"
#include "Texture.h"
int main(int argc, char** argv)
{
Display display(800, 600, " ");
display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
Vertex vertices[] = {
Vertex(glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(0.0f, 0.0f)),
Vertex(glm::vec3( 0.0f, 1.0f, 0.0f), glm::vec2(0.5f, 1.0f)),
Vertex(glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec2(1.0f, 0.0f))
};
Texture texture("./res/a.bmp");
Shader shader("./res/testShader");
Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));
while (display.IsClosed() != true)
{
shader.Bind();
texture.Bind(0);
mesh.Draw();
display.Update();
}
return 0;
}
In Mesh.cpp i am splitting Vertices attributes (glm::vec3 _position and glm::vec2 _texture) into 2 stl vectors and using 2 buffers ("0" - for position of vertex and "1" - for texture) :
Mesh::Mesh(Vertex* vertices, unsigned int numVertices, GLenum usage)
{
_drawCount = numVertices;
glGenVertexArrays(1, &_vertexArrayObject);
glBindVertexArray(_vertexArrayObject);
std::vector<glm::vec3> positions;
std::vector<glm::vec2> texCoords;
positions.reserve(numVertices);
texCoords.reserve(numVertices);
for (unsigned int i = 0; i < numVertices; ++i)
{
positions.push_back(*vertices[i].Position());
texCoords.push_back(*vertices[i].TexCoord());
}
glGenBuffers(NUM_BUFFERS, _vertexArrayBuffers);
glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[POSITION_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions.data(), usage);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[TEXCOORD_VB]);
glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(texCoords[0]), texCoords.data(), usage);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindVertexArray(0);
}
Mesh::~Mesh(void)
{
glDeleteVertexArrays(1, &_vertexArrayObject);
}
void Mesh::Draw(GLenum mode)
{
glBindVertexArray(_vertexArrayObject);
glDrawArrays(mode, 0, _drawCount);
glBindVertexArray(0);
}
In Shader.cpp i binded atributes like this:
glBindAttribLocation(_program, 0, "position");
glBindAttribLocation(_program, 1, "texCoord");
----------------------------EDIT---------------------------------
After changing vertex shader to:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
out vec2 TexCoord;
void main()
{
gl_Position = vec4(position, 1.0f);
TexCoord = texCoord;
}
and fragment shader to:
#version 330 core
in vec2 TexCoord;
out vec4 color;
uniform sampler2D ourTexture;
void main()
{
color = texture(ourTexture, TexCoord);
}
texture is mapped correctly.
But i still want to know why my first solution doesn't work.
But i still want to know why my first solution doesn't work.
Because you're using
#version 330 core
and texture2D is deprecated since version 130
The shader compiler should've warned or errored about that. Check your shader logs via glGetShaderInfoLog and glGetProgramInfoLog.
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.
I have the following setup for basic texture mapping
void init(void) {
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[6][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.1, 0.1 }, // UVs
{ 0.9, 0.1 },
{ 0.1, 0.9 }
};
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint program = LoadShaders( "triangles.vert", "triangles.frag" );
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(1, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(2*3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
GLuint sloc = glGetUniformLocation(program, "mySampler");
glUniform1i(sloc, 0);
int x,y,n;
unsigned char *data = stbi_load("bricks.jpg", &x, &y, &n, 4);
glGenTextures(1, &m_textureId);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexParameterf(m_textureId, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(m_textureId, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}
Vertex Shader:
#version 330 core
layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec2 uv;
out vec2 texCoord;
void
main() {
gl_Position = vPosition;
texCoord = uv;
}
Fragment Shader:
#version 330 core
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D mySampler;
void
main() {
fColor = texture(mySampler, texCoord);
}
However, nothing is displayed on the screen. If I swap out my frag shader with one that just sets a static color, I see the triangle. I have confirmed that I am getting data from the image and printed out a sample set of RGBA data that looks correct (rgb vary, but alpha is constant 0xFF). I've read at least 5 tutorials but can't seem to get it right.
I've also confirmed that if I do:
fColor = vec4(texCoord.x, texCoord.y, 0.0, 1.0);
I get a gradient of colors which I believe tells me I'm getting correctly interpolated values of my UVs coming through.
Apparently these texparams are required for some implementations
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );