1
\$\begingroup\$

I am trying to render a scene to a cubemap, so I can later use it as environment map for another object. The object I want to use the environment map with is a surface, I am trying to render water. But I have an issue, when the refraction index is set to 1.0 (air), the skybox is shown correctly, however the other object is not.

The circled area is where the cube made out of air is, in these images:

enter image description here

enter image description here

But when I position my camera so it includes a part of the stone platform, the stone platform appears much more larger than it should be:

enter image description here

I render to cubemap as follows:

glm::mat4 translateInfoMat = x.model - glm::mat4(glm::mat3(x.model));
glm::vec3 position = glm::vec3(translateInfoMat[3][0], translateInfoMat[3][1], translateInfoMat[3][2]);//gets the view position of the cubemap from the object's model matrix.

glm::mat4 _projection = glm::perspective(glm::radians(90.0f), 1.f, 0.1f, 2000.0f);

for(int j = 0; j < 6; j++)// for each face it renders the scene
{
    envMap.bindRenderToFace(j); //sets the current face to draw to.
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glm::mat4 _view = glm::lookAt(position, position + targets[j], ups[j]);


    //renders skybox
    glDepthMask(GL_FALSE);
    if(skybox != NULL)
    {
        skybox->setVP(_projection * glm::mat4(glm::mat3(_view)));
        skybox->draw(&skyboxShader);
    }
    glDepthMask(GL_TRUE);


    for(int i = 0; i < renderQueue.size(); i++)//renders the objects that doesn't need environment map (the stone platform)
    {
        RenderableElement object = renderQueue[i];
        if(!y.renderInfo.m_needsEnvironmentMap)
        {
            lighting.SetMVP(_projection * _view  * y.model);
            lighting.SetModel( object.model);
            lighting.SetViewPos(viewPos);

            lighting.Use();

            object.mesh->Draw(lighting.GetShader());
        }
    }
}

And the shader that does the refraction is:

#version 330 core


in vec3 FragPos; //the position of the current fragment in world space
in vec3 Normal; //normal in world space


out vec4 FragColor;

uniform vec3 viewPos;
uniform samplerCube skybox;


vec3 refraction(vec3 normal, vec3 viewPos, vec3 fragPos, float n1, float n2)
{
    vec3 i = normalize(fragPos - viewPos);
    vec3 r = refract(i, normalize(normal), n1 / n2);

    return texture(skybox, normalize(r)).rgb;
}


void main()
{
    vec3 normal;

    normal = normalize(Normal);

    vec4 refr = vec4(refraction(normal, viewPos, FragPos, 1.0, 1.0), 1.0);

    FragColor = refr;
}

I have verified my code with multiple sources, and they are doing approximately the same way as I have done. The data fed to the shader is correct (normals, vertex position, model matrix, view position, etc.).

\$\endgroup\$
0
\$\begingroup\$

(My answer originally from: Reddit.)

The problem you're having is not caused by your cubemap rendering or setup (didn't go through your code, but seems to work just fine from the images), but a parallax issue.

It is caused when the position where you calculate the reflection/refraction vector doesn't correspond to the position of the camera where you took the image. This works fine for the environment but cause issues for objects that are not very far away.

I've been there (exactly same issue with water reflection/refraction :)) and there are two ways to go:

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.