Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render inverted scene to framebuffer

I need some help with rendering inverted scene to framebuffer. I want to make a mirror effect. What i have in result: My result Initializing frame buffer:

GLuint FramebufferName = 0;
glGenFramebuffers(1, &FramebufferName);
glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);

GLuint renderedTexture;
glGenTextures(1, &renderedTexture);
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCREEN_WIDTH, SCREEN_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderedTexture, 0);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_NONE);

Draw scene to frame buffer:

    mView = camera.getViewMatrix();
    mProjection = perspective(45.0f, 4.0f / 3.0f, 0.1f, 300.0f) * scale(mat4(1.0f), vec3(1.0f, -1.0f, 1.0f)); 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FramebufferName);
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glCullFace(GL_FRONT);
    glEnable(GL_CULL_FACE);
    mWorld = rotate(mWorld, -15.0f, vec3(1, 0, 0));
    mWorld = rotate(mWorld, -30.0f, vec3(0, 1, 0));
    cubemap.Draw(mView, mProjection, mWorld);
    glDisable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glUseProgram(program);
    mWorld = translate(mat4(1.0f), vec3(0, -10, 0));
    glUniformMatrix4fv(mvp_object, 1, GL_FALSE, value_ptr(mProjection * mView * mWorld * scale(mat4(1.0f), vec3(10.0f))));
    cannon.Draw(program);

    mWorld = mat4(1.0f);
    mWorld = translate(mat4(1.0f), vec3(50, -10, 0));
    mWorld = rotate(mWorld, 90.0f, vec3(0, 1, 0));
    glUniformMatrix4fv(mvp_object, 1, GL_FALSE, value_ptr(mProjection * mView * mWorld * scale(mat4(1.0f), vec3(10.0f))));
    cannon.Draw(program);

    mWorld = mat4(1.0f);
    mWorld = translate(mat4(1.0f), vec3(0, -10, 50));
    mWorld = rotate(mWorld, 140.0f, vec3(0, 1, 0));
    glUniformMatrix4fv(mvp_object, 1, GL_FALSE, value_ptr(mProjection * mView * mWorld * scale(mat4(1.0f), vec3(10.0f))));
    cannon.Draw(program);

    glDisable(GL_DEPTH_TEST);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

I saw some tutorials where used glScalef(1.0, -1.0, 1.0) to invert scene. glScalef was used in old versions of opengl. How can i invert scene in new versions of opengl? I've multiplied projection matrix on scale(mat4(1.0f), vec3(1.0, -1.0, 1.0)) for this effect. Is it right?

like image 299
Vertigo Avatar asked Nov 10 '22 02:11

Vertigo


1 Answers

Here is the vertex shader written in GLSL.

void main(void)
{
   // Clean up inaccuracies
   vec2 Pos = sign(gl_Vertex.xy);

   gl_Position = vec4(Pos.xy, 0.0, 1.0);
   // Image-space
   gl_TexCoord[0].xy = vec2(-Pos.x, Pos.y) * 0.5 + 0.5; // x texture coord is inverted       
}

Pos refers to screen aligned quad for framebuffer output.

Fragment shader

uniform sampler2D framebufferSampler;

void main(void)
{
   gl_FragColor = texture2D(framebufferSampler, gl_TexCoord[0].xy);
}

Screen aligned quad can be drawn

glBegin(GL_QUADS)
{
    glVertex2f(-1.0f, -1.0f);
    glVertex2f(1.0f, -1.0f);
    glVertex2f(1.0f, 1.0f);
    glVertex2f(-1.0f, 1.0f);
}
glEnd();

or using vertex arrays.

GLfloat vertices[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    1.0f, 1.0f,
    -1.0f, 1.0f
};

glEnableClientState(GL_VERTEX_ARRAY);

glVertexPointer(2, GL_FLOAT, 0, (void*)vertices);

glDrawArrays(GL_QUADS, 0, 4);

glDisableClientState(GL_VERTEX_ARRAY);

texture that is used to be wraped to the quad, is the framebuffer info with previous rendered content (multipass shader technique).

You can also do so with others 2D texture coords or images instead of framebuffer and screen align quads.

Original image.

enter image description here

Inverted image.

enter image description here

More info can be found in Learn OpenGL.

like image 124
Mykola Avatar answered Nov 14 '22 21:11

Mykola