Open GL Translucid Sprites - c++

So, my goal is to draw sprites with translucid pixels.
First, I render the sprites with a shader that only renders the opaque pixels. Then, I disable depth buffer writing and render the same sprites with a shader that only renders the translucid (or transparent sprites), as explained here:
https://gamedev.stackexchange.com/questions/51202/how-do-you-display-non-cutout-transparent-2d-textures-with-a-depth-buffer-open
This is the animation sprite sheet I am using as test:
https://i.stack.imgur.com/MMs2W.png
This is my renderer update function:
updateRenderData();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);
glUseProgram(_translucencyPogramID);
render();
_window->SwapBuffers();
And this is my render function (just in case you want to know how I render the sprites):
GLint baseInstance = 0;
GLsizei spriteCount;
for (int i = 0; i < _spriteManager->GetSpriteBatchVector()->size(); i++)
{
_SpriteBatch* spriteBatch = _spriteManager->GetSpriteBatchVector()->at(i);
setTexture(spriteBatch->GetTexture());
spriteCount = (GLsizei)spriteBatch->GetSpriteVector()->size();
glDrawElementsInstancedBaseInstance(_quad.renderMode, _quad.indexCount, _quad.indexDataType, 0, spriteCount, baseInstance);
baseInstance += spriteCount;
}
But when I execute this code, it only renders the translucid pixels:
https://i.stack.imgur.com/f4AY6.png
In fact, nothing renders (black screen) if I remove the second render() call (only the call, I still change the shader and set the depth mask to false), like this:
updateRenderData();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);
glUseProgram(_translucencyPogramID);
_window->SwapBuffers();
But if I don't change the shader nor set glDepthMask to false after the first render, it renders the opaque pixels of my sprites correctly.
Edit:
This is the fragment shader I am using for the second pass:
out layout(location = 0) vec4 outColor;
in vec2 texCoord;
uniform sampler2D tex;
void main()
{
vec4 texel = texture(tex, texCoord);
if(texel.a == 1)
{
discard;
}
outColor = texel;
}
The first pass is just the same, but discarding if alpha < 1.
The vertex shader is standard.
So, my question here is: what is causing this?
Edit 2:
To clarify, this renders correctly (without translucent pixels):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
And this doesn't render at all:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glDepthMask(GL_FALSE);//Just added this line
And this also doesn't render at all:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glUseProgram(_programID);
render();
glUseProgram(_translucencyPogramID);//Just added this line

Assuming _programID is for drawing the opaque part of the bird and _translucencyPogramID is for drawing the translucent part.
Nothing in the code you've supplied shows what the cause could be. However it could be the result of:
You aren't actually calling render() while using _programID.
After the _programID you glClear(GL_COLOR_BUFFER_BIT)
You're using GL_ONE_MINUS_SRC_ALPHA as glBlendFunc()'s sfactor
So given that your _programID's fragment shader consists of:
if (texel.a < 1.0)
discard;
and your _translucencyPogramID's fragment shader consists of:
if (texel.a == 1.0)
discard;
Then granted your draw loop is like this (pseudo-code):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE)
glUseProgram(_programID)
for each sprite
glDrawArrays(....)
glDepthMask(GL_FALSE)
glUseProgram(_translucencyPogramID)
for each sprite
glDrawArrays(....)
glDepthMask(GL_TRUE)
Then while using glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), then that should give the desired result.
Edit
Then reason it breaks when you when you add glDepthMask(GL_FALSE), is because you don't enabled it again after. You can check this by doing:
GLboolean enabled;
glGetBooleanv(GL_DEPTH_WRITEMASK, &enabled);
assert(enabled == GL_TRUE);
Before you glClear(GL_DEPTH_BUFFER_BIT).
This reason it breaks is because if writing to the depth buffer is disabled, then glClear(GL_DEPTH_BUFFER_BIT) won't do anything, and thus leave the depth buffer as is.
As you can see below, on the second picture it sort of smears the silhouette of all the bird's frames. Which is because the depth buffer is never cleared, and this bird is the frontmost bird. If writing to the depth buffer is enabled upon calling glClear(GL_DEPTH_BUFFER_BIT) then it correctly yields the first picture.
Left: Depth writing is enabled on glClear. Right: Depth writing is disabled on glClear.
Note that this relation is true for glClear(...) and any gl*Mask(GL_FALSE).

Related

OpenGL - blend two textures on the same object

I want to apply two textures on the same object (actually just a 2D rectangle) in order to blend them. I thought I would achieve that by simply calling glDrawElements with the first texture, then binding the other texture and calling glDrawElements a second time. Like this:
//create vertex buffer, frame buffer, depth buffer, texture sampler, build and bind model
//...
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
glBlendEquation(GL_FUNC_ADD);
// Clear the screen
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Bind our texture in Texture Unit 0
GLuint textureID;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
//second draw call
GLuint textureID2;
//create or load texture
//...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID2);
// Set our sampler to use Texture Unit 0
glUniform1i(textureSampler, 0);
// Draw the triangles !
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);
Unfortunately, the 2nd texture is not drawn at all and I only see the first texture. If I call glClear between the two draw calls, it correctly draws the 2nd texture.
Any pointers? How can I force OpenGL to draw on the second call?
As an alternative to the approach you followed so far I would like to suggest using two texture samplers within your GLSL shader and perform the blending there. This way, you would be done with just one draw call, thus reducing CPU/GPU interaction. To do so, just define to texture samplers in your shader like
layout(binding = 0) uniform sampler2D texture_0;
layout(binding = 1) uniform sampler2D texture_1;
Alternatively, you can use a sampler array:
layout(binding = 0) uniform sampler2DArray textures;
In your application, setup the textures and samplers using
enum Sampler_Unit{BASE_COLOR_S = GL_TEXTURE0 + 0, NORMAL_S = GL_TEXTURE0 + 2};
glActiveTexture(Sampler_Unit::BASE_COLOR_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer1);
glTexStorage2D( ....)
glActiveTexture(Sampler_Unit::NORMAL_S);
glBindTexture(GL_TEXTURE_2D, textureBuffer2);
glTexStorage2D( ....)
Thanks to #tkausl for the tip.
I had depth testing enabled during the initialization phase.
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
The option needs to be disabled in my case, for the blend operation to work.
//make sure to disable depth test
glDisable(GL_DEPTH_TEST);

OpenGL multiple texture with multiple shader programs

I am trying to do a scene in OpenGL to simulate earth from space. I have two spheres right now, one for earth, and another slightly big for clouds. The earth and the cloud sphere objects have their own shader programs to keep it simple. The earth shader program takes 4 textures (day, night, specmap and normalmap) and the cloud shader program takes 2 textures (cloudmap and normalmap). I have an object class which has a render function, and in that function I use this logic:
//bind the current object's texture
for (GLuint i = 0; i < texIDs.size(); i++){
glActiveTexture(GL_TEXTURE0 + i);
if (cubemap)
glBindTexture(GL_TEXTURE_CUBE_MAP, texIDs[i]);
else
glBindTexture(GL_TEXTURE_2D, texIDs[i]);
}
if (samplers.size()){
for (GLuint i = 0; i < samplers.size(); i++){
glUniform1i(glGetUniformLocation(program, samplers[i]), i);
}
}
It starts from the 0th texture unit, and binds N number of textures to N number of texture units starting from GL_TEXTURE0. Then it binds the the samplers starting from 0 to N in the shader program. The samplers are provided by me while loading the textures:
void Object::loadTexture(const char* filename, const GLchar* sampler){
int texID;
texID = SOIL_load_OGL_texture(filename, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS);
if(texID == 0){
cerr << "SOIL error: " << SOIL_last_result();
}
cout << filename << " Tex ID: " << texID << endl;
texIDs.push_back(texID);
samplers.push_back(sampler);
//glBindTexture(GL_TEXTURE_2D, texID);
}
When I do this, all the textures in the first sphere (earth) gets loaded successfully, but in the seconds sphere I get no textures and I just get a black sphere. My query is, how should I manage multiple textures and samplers if I'm using different shader programs for each object?
From what I see You are binding all textures as separate texture unit
that is wrong
what if you have 100 objects and each has 4 textures ...
I strongly doubt that you have 400 texture units at your disposal
Texture ID (name) is not Texture unit ...
I render space bodies like this:
First pass renders the astro body geometry
I have specific texture units for specific tasks
// texture units:
// 0 - texture0 map 2D rgba (surface)
// 1 - texture1 map 2D rgba (clouds blend)
// 2 - normal map 2D xyz (normal/bump mapping)
// 3 - specular map 2D i (reflection shininess)
// 4 - light map 2D rgb rgb (night lights)
// 5 - enviroment/skybox cube map 3D rgb
see the shader in that link (it was written for the solar system visualization too)...
you bind only the textures for single body before each render of it
(after you bind the shader)
do not change the texture unit meanings (how shader will know which texture is what if you do?)
Second render pass adds atmospheres
no textures used
it is just single transparent quad covering whole screen
here some insights to your tasks
[edit1] example of multitexturing
// init shader once per render all geometries
GLint prog_id; // shader program ID;
GLint txrskybox; // global skybox environment cube map
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr_texture0"); glUniform1i(id,0); //uniform sampler2D txr_texture0;
id=glGetUniformLocation(prog_id,"txr_texture1"); glUniform1i(id,1); //uniform sampler2D txr_texture1;
id=glGetUniformLocation(prog_id,"txr_normal"); glUniform1i(id,2); //uniform sampler2D txr_normal;
id=glGetUniformLocation(prog_id,"txr_specular"); glUniform1i(id,3); //uniform sampler2D txr_specular;
id=glGetUniformLocation(prog_id,"txr_light"); glUniform1i(id,4); //uniform sampler2D txr_light;
id=glGetUniformLocation(prog_id,"txr_skybox"); glUniform1i(id,5); //uniform samplerCube txr_skybox;
// add here all uniforms you need ...
glActiveTexture(GL_TEXTURE0+5); glEnable(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP,txrskybox);
for (i=0;i<all_objects;i++)
{
// add here all uniforms you need ...
// pass textures once per any object render
// obj::(GLint) txr0,txr1,txrnor,txrspec,txrlight; // object local textures
glActiveTexture(GL_TEXTURE0+0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr0);
glActiveTexture(GL_TEXTURE0+1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr1);
glActiveTexture(GL_TEXTURE0+2); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrnor);
glActiveTexture(GL_TEXTURE0+3); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrspec);
glActiveTexture(GL_TEXTURE0+4); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrlight);
// here render the geometry of obj[i]
}
// unbind textures and shaders
glActiveTexture(GL_TEXTURE0+5); glBindTexture(GL_TEXTURE_CUBE_MAP,0); glDisable(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE0+4); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+3); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+2); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+1); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+0); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D); // unit0 at last so it stays active ...
glUseProgram(0);

Deferred Rendering Skybox OpenGL

I've just implemented deferred rendering and am having trouble getting my skybox working. I try rendering my skybox at the very end of my rendering loop and all I get is a black screen. Here's the rendering loop:
//binds the fbo
gBuffer.Bind();
//the shader that writes info to gbuffer
geometryPass.Bind();
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
//draw geometry
geometryPass.SetUniform("model", transform.GetModel());
geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform.GetModel());
mesh3.Draw();
geometryPass.SetUniform("model", transform2.GetModel());
geometryPass.SetUniform("mvp", camera.GetViewProjection() * transform2.GetModel());
sphere.Draw();
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
//shader that calculates lighting
pointLightPass.Bind();
pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());
for (int i = 0; i < 2; i++)
{
pointLightPass.SetUniformPointLight("light", pointLights[i]);
pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
//skybox.GetCubeMap()->Bind(9);
quad.Draw();
}
//draw skybox
glEnable(GL_DEPTH_TEST);
skybox.Render(camera);
window.Update();
window.SwapBuffers();
The following is the skybox's render function
glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);
m_transform.SetPosition(camera.GetTransform().GetPosition());
m_shader->Bind();
m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
m_shader->SetUniform("cubeMap", 0);
m_cubeMap->Bind(0);
m_cubeMesh->Draw();
glDepthFunc(GL_LESS);
glCullFace(GL_BACK);
And here is the skybox's vertex shader:
layout (location = 0) in vec3 position;
out vec3 TexCoord;
uniform mat4 mvp;
void main()
{
vec4 pos = mvp * vec4(position, 1.0);
gl_Position = pos.xyww;
TexCoord = position;
}
The skybox's fragment shader just sets the output color to texture(cubeMap, TexCoord).
As you can see from the vertex shader, I'm setting the position's z component to be w so that it will always have a depth of 1. I am also setting the depth function to be GL_LEQUAL so that it will fail the depth test. Should this not only draw the skybox in places where other objects weren't already drawn? Why does it result in a black screen?
I know I have set up the skybox correctly because if I just draw the skybox by itself it shows up just fine.
I can briefly see for a split second the geometry that should be drawn before the skybox is drawn on top of everything.
Since you're using double buffering, seeing different things must be due to a different frame being drawn. The depth buffer in the default framebuffer isn't being cleared, which I believe is the cause of the temporal instability at least.
In your case, you want the default depth buffer to be the same as the GBuffer when you draw the skybox. A quick way to achieve this is with glBlitFramebuffer, also avoiding the need to clear it:
glBindFramebuffer(GL_READ_FRAMEBUFFER, gbuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(..., GL_DEPTH_BUFFER_BIT, ...);
Now to explain the black screen when the skybox fills the screen. Without the depth test, of course the skybox just draws. With the depth test, the skybox still draws on the first frame, but shortly after the second frame clears only the colour buffer. The depth buffer still contains stale skybox values so it does not get re-draw for this frame and you're left with black...
However your geometry pass draws without depth testing enabled, so this should still be visible even if the skybox isn't. Also this would only happen with GL_LESS and you have GL_LEQUAL. And you have glDepthMask false, which means nothing should write to the default depth buffer in your code. This points to the depth buffer containing other values, perhaps uninitialized, but in my experience it's initially zero. Also this still happens when the skybox doesn't fill the screen, drawn as a cube away from the camera, which blows away that argument. Now, perhaps if the geometry failed to draw in the second frame that would explain it. For that matter blatant driver bugs would too, but I'm not seeing any problems in the given code.
TLDR: Many unexplained things, so **I tried it myself and can't reproduce your problem...
Here's a quick example based on your code and it works fine for me...
(green sphere is the geometry, red cube is the skybox)
gl_Position = pos:
Note the yellow from additive blending even if the skybox is drawn over the top. I would have thought you'd be seeing this too.
gl_Position = pos.xyww:
Now for the code...
//I haven't enabled back face culling, but that shouldn't affect anything
//binds the fbo
fbo.bind();
//the shader that writes info to gbuffer
//geometryPass.Bind(); //fixed pipeline for now
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glColor3f(0,1,0);
fly.uploadCamera(); //glLoadMatrixf
sphere.draw();
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_ONE, GL_ONE);
fbo.unbind(); //glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
//shader that calculates lighting
drawtex.use();
//pointLightPass.SetUniform("cameraPos", camera.GetTransform().GetPosition());
drawtex.set("tex", *(Texture2D*)fbo.colour[0]);
for (int i = 0; i < 2; i++)
{
//pointLightPass.SetUniformPointLight("light", pointLights[i]);
//pointLightPass.SetUniform("mvp", glm::mat4(1.0f));
//skybox.GetCubeMap()->Bind(9);
drawtex.set("modelviewMat", mat44::identity());
quad.draw();
}
drawtex.unuse();
//draw skybox
glEnable(GL_DEPTH_TEST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, fbo.size.x, fbo.size.y, 0, 0, fbo.size.x, fbo.size.y, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glCullFace(GL_FRONT);
glDepthFunc(GL_LEQUAL);
//m_transform.SetPosition(camera.GetTransform().GetPosition());
skybox.use();
skybox.set("mvp", fly.camera.getProjection() * fly.camera.getInverse() * mat44::translate(1,0,0));
//m_shader->SetUniform("mvp", camera.GetViewProjection() * m_transform.GetModel());
//m_shader->SetUniform("cubeMap", 0);
//m_cubeMap->Bind(0);
cube.draw();
skybox.unuse();
glDepthFunc(GL_LESS);
//glCullFace(GL_BACK);
//window.Update();
//window.SwapBuffers();

offscreen rendering opengl 4.5 multisample FBO

I'm referencing OpenGL Superbible 6 in my code.
First I simply wanted to implement object picking in my 3d scene. Eventually I've decided to use framebuffer objects and I have succeeded and then I understood the problem with the need to solve the problem of polygon edge aliasing, so, i've rewritten my code again to make use of GL_TEXTURE_2D_MULTISAMPLE
Here is the initialization code for framebuffer
void window_glview::init_framebuffer()
{
//CREATE FRAMEBUFFER OBJECT
GLenum gl_error=glGetError();
glGenTextures(1,&texture_id_framebuffer_color);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,texture_id_framebuffer_color);
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,ANTIALIASING_SAMPLES,GL_RGBA8,client_area.right,client_area.bottom,GL_TRUE);
glGenTextures(1,&texture_id_framebuffer_objectid);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,texture_id_framebuffer_objectid);
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,ANTIALIASING_SAMPLES,GL_RGBA8,client_area.right,client_area.bottom,GL_TRUE);
glGenTextures(1,&texture_id_framebuffer_depth);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,texture_id_framebuffer_depth);
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE,ANTIALIASING_SAMPLES,GL_DEPTH_COMPONENT32,client_area.right,client_area.bottom,GL_TRUE);
gl_error=glGetError();
glGenFramebuffers(1,&buffer_id_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER,buffer_id_framebuffer);
gl_error=glGetError();
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture_id_framebuffer_color,0);
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture_id_framebuffer_objectid,0);
glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,texture_id_framebuffer_depth,0);
GLenum draw_buffers[] =
{
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1
};
glDrawBuffers(2,draw_buffers);
GLenum status=glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status!=GL_FRAMEBUFFER_COMPLETE)
MessageBox(0,L"Failed to create framebuffer object",0,0);
glBindFramebuffer(GL_FRAMEBUFFER,0);
}
It's pretty common to most of the internet listings on the same topic.
Now here is my drawing code
void window_glview::paint()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//DRAW TO CUSTOM FRAMEBUFFER
glBindFramebuffer(GL_FRAMEBUFFER,buffer_id_framebuffer);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLineWidth(1.0);
draw_viewport();
viewport_object_count=0;
draw_lights();
glLineWidth(1.5);
for (unsigned short i=0;i<mesh_count;i++)
{
draw_mesh(mesh_table[i],GL_TRIANGLES,false);
}
//DRAW TO DEFAULT
glBindFramebuffer(GL_FRAMEBUFFER,0);
//USE TEXTURE FROM FRAMEBUFFER COLOR_ATTACHMENT0
glUseProgram(program_id_screen_render);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE,texture_id_framebuffer_color);
//HERE IS A QUAD DRAWING PROCESS
glBindBuffer(GL_ARRAY_BUFFER,buffer_id_screen_quad);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,24,0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_QUADS,0,4);
SwapBuffers(hDC);
}
vertex shader is simple
#version 450
layout(location=0) in vec4 _pos;
void main(void)
{
gl_Position=_pos;
}
fragment shader is written with the purpose of iterpreting multisamples
#version 450
uniform sampler2DMS screen_texture;
layout(location=0) out vec4 out_color;
void main(void)
{
ivec2 coord=ivec2(gl_FragCoord.xy);
vec4 result=vec4(0.0);
int i;
for (i=0;i<4;i++)
{
result=max(result,texelFetch(screen_texture,coord,i));
}
out_color=result;
}
I end up with a black screen. If i change out_color to something lice out_color=vec4(1.0,0.0,0.0,1.0) i get red screen.
What could go wrong?
In my initializer function for framebuffer when i pass GL_DEPTH_COMPONENT to glTexStorage2DMultisample, then i get error. I decided to pass GL_DEPTH_COMPONENT16 and it works. Why is that?
Should I better use RENDERBUFFER for some perpose and if yes, how can i read it to texture?
The texture with id texture_id_framebuffer_color, which is the texture you use for your final rendering, is not attached to the FBO while you render to the FBO:
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture_id_framebuffer_color,0);
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture_id_framebuffer_objectid,0);
Only one texture can be attached to a given attachment point at a time. So when you specify a second texture to be attached to COLOR_ATTACHMENT0, the first one automatically gets un-attached.
If you want to have two attachments, they will need to use different attachment points:
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,texture_id_framebuffer_color,0);
glFramebufferTexture(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,texture_id_framebuffer_objectid,0);

3D model looks transparent-like

Trying to draw wavefront obj files using OpenGL but it seems there is a depth-buffer problem.
Source:
// Default constructor
Engine::Engine()
{
initialize();
loadModel();
start();
}
// Initialize OpenGL
void Engine::initialize()
{
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Enable depth write
glDepthMask(GL_TRUE);
}
void Engine::start()
{
// Main loop
while(isOpen())
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw 3D model to screen
draw();
}
}
Things to check:
Make sure depth test is enabled glEnable(GL_DEPTH_TEST)
Make sure depth write is enabled glDepthMask(true)
Make sure your context has a depth buffer Assert(glGetIntegerv(GL_DEPTH_BITS) != 0))
Did you activated the depth test?
glEnable(GL_DEPTH_TEST);
Request a GL context with a depth buffer and glEnable(GL_DEPTH_TEST).
Try this:
mainWindow.create
(
sf::VideoMode
(
settings.getWidth(),
settings.getHeight()
),
"",
sf::Style::Resize,
sf::ContextSettings( 16, 0, 0, 2, 0 )
);
Are you using vertex shaders? This thing would happen if at the exit of vertex shader gl_Position.z is accidentally set to 0. Or to any value between -1 and 1 I believe.
It would also happen if all vertices had equal z value before the input stage, albeit there must be something wrong with your transformation matrices in this case. Or simply you may be doing something very exotic with your transformation matrices, and the model is fine. Have you set up both MODELVIEW and PROJECTION, and multiplied them accordingly? Either in the vertex shader or in the FFP?