lundi 12 août 2019

Dynamic Cube Mapping for Reflections in OpenGL reflections doesnt look right

Im trying to implement reflections in OpenGL by rendering the scene 6 times from an object. The code to draw the sides to the cubemap is the following:

glm::mat4 currentCubeMapView = glm::mat4(0.0);

    GLenum cubemapSides[6] = {
        GL_TEXTURE_CUBE_MAP_POSITIVE_X,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
    };

    glm::vec3 targetVectors[6] = {
        glm::vec3(1.0f, 0.0f, 0.0f),
        glm::vec3(-1.0f, 0.0f, 0.0f),
        glm::vec3(0.0f, 1.0f, 0.0f),
        glm::vec3(0.0f, -1.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, 1.0f),
        glm::vec3(0.0f, 0.0f, -1.0f)
    };

    glm::vec3 upVectors[6] = {
        glm::vec3(0.0f, -1.0f, 0.0f),
        glm::vec3(0.0f, -1.0f, 0.0f),
        glm::vec3(0.0f, 0.0f, 1.0f),
        glm::vec3(0.0f, 0.0f, -1.0f),
        glm::vec3(0.0f, -1.0f, 0.0f),
        glm::vec3(0.0f, -1.0f, 0.0f)
    };

    projection = glm::perspective(glm::radians(90.0f), 1.0f, near_plane, far_plane);
    glm::vec3 cm = mcCubes.getCenterMass();

    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    Camera dcCamera = Camera(cm);
    dcCamera.Pitch -= 15;
    dcCamera.updateCameraVectors();
    for (GLuint face = 0; face < 6; ++face)
    {

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemapSides[face], dcmap, 0);
        glClear(GL_DEPTH_BUFFER_BIT);

        glm::vec3 modelOrigin = glm::vec3(0,0,0);

        dcCamera.Position = cm;
        dcCamera.Front = targetVectors[face];
        dcCamera.Up = upVectors[face];

        currentCubeMapView = glm::mat4(1.0);
        currentCubeMapView = dcCamera.lookAt(modelOrigin, modelOrigin + targetVectors[face], upVectors[face]);
        // Render skybox

        glDepthFunc(GL_LEQUAL);  // change depth function so depth test passes when values are equal to depth buffer's content
        skyboxShader.use();
        view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix
        //currentCubeMapView = glm::mat4(glm::mat3(currentCubeMapView));
        //currentCubeMapView2 = glm::mat4(glm::mat3(currentCubeMapView2));
        skyboxShader.setMat4("view", currentCubeMapView);
        skyboxShader.setMat4("projection", projection);
        // skybox cube
        glBindVertexArray(skyboxVAO);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glBindVertexArray(0);
        glDepthFunc(GL_LESS); // set depth function back to default

        shader.use();
        shader.setInt("diffuseTexture", 0);
        shader.setInt("depthMap", 1);
        shader.setInt("skybox", 2);
        shader.setInt("normalMap", 3);

        model_ = glm::mat4(1.0);
        //shader.setVec3("viewPos", lightPos);
        shader.setVec3("samplePoint", centerBBox);
        shader.setVec3("maxBox", bbmax);
        shader.setVec3("minBox", bbmin);
        shader.setMat4("view", currentCubeMapView);
        shader.setMat4("projection", projection);
        shader.setMat4("model", model_);
        //glCullFace(GL_BACK);
        shader.setVec3("samplePoint", modelOrigin );
        shader.setBool("depthRendering", true);
        renderScene(shader,true);
        shader.setBool("depthRendering", false);


    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 

This cubemap is to show the reflections of the result of the marching cubes mesh (skybox and sphere) Similarly, the code for the reflections of a sphere (skybox and cube):

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glViewport(0, 0, cubemapSize, cubemapSize);
    glBindFramebuffer(GL_FRAMEBUFFER, noSphereFrameBuffer);

    Camera noSphereCamera = Camera(collObjects[0].getPos());
    noSphereCamera.updateCameraVectors();
    for (GLuint face = 0; face < 6; ++face)
    {

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubemapSides[face], noSphereMap, 0);
        glClear(GL_DEPTH_BUFFER_BIT);

        glm::vec3 modelOrigin = glm::vec3(0, 0, 0);// +collObjects[0].getPos();

        currentCubeMapView = glm::mat4(1.0);

        noSphereCamera.Position = collObjects[0].getPos();
        noSphereCamera.Front = targetVectors[face];
        noSphereCamera.Up = upVectors[face];
        currentCubeMapView = noSphereCamera.lookAt(modelOrigin, modelOrigin + targetVectors[face], upVectors[face]);
        shader.use();
        shader.setInt("diffuseTexture", 0);
        shader.setInt("depthMap", 1);
        shader.setInt("skybox", 2);
        shader.setInt("normalMap", 3);
        shader.setMat4("view", currentCubeMapView);
        shader.setMat4("projection", projection);
        shader.setVec3("view_right", noSphereCamera.Right);
        shader.setVec3("view_up", noSphereCamera.Up);
        shader.setVec3("view_forward", noSphereCamera.Front);
        //collObjects[1].pos = Vector3(camera.Position.x, camera.Position.y, camera.Position.z);
        renderCollisionObjectAt(shader, 1, noSphereCamera);

        // Render skybox

        //glCullFace(GL_FRONT);
        glDepthFunc(GL_LEQUAL);  // change depth function so depth test passes when values are equal to depth buffer's content

        skyboxShader.use();
        view = glm::mat4(glm::mat3(camera.GetViewMatrix())); // remove translation from the view matrix

        skyboxShader.setMat4("view", currentCubeMapView);
        skyboxShader.setMat4("projection", projection);

        // skybox cube
        glBindVertexArray(skyboxVAO);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        glBindVertexArray(0);
        glDepthFunc(GL_LESS); // set depth function back to default


    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

Then i use the vertex shader to calculate the reflected vector:

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
layout (location = 3) in vec3 aOffset;
layout (location = 4) in vec3 aTangent;
layout (location = 5) in vec3 aBitangent;

out vec2 TexCoords;

out VS_OUT {
    vec3 FragPos;
    vec3 Normal;
    vec2 TexCoords;

    vec3 TangentLightPos;
    vec3 TangentViewPos;
    vec3 TangentFragPos;

    vec3 reflectedVector;
    vec3 refractedVector;
} vs_out;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

uniform bool isParticle;

uniform bool reverse_normals;

uniform vec4 plane;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 camPos;

uniform samplerCube depthMap;

uniform vec3 view_right;
uniform vec3 view_up;
uniform vec3 view_forward;

void main()
{

    vec4 pos = vec4(aPos,1.0);



    if(isParticle)pos = vec4(aPos+aOffset,1.0);

    vec4 worldPosition = model*pos; 


    vs_out.FragPos = vec3(model * pos);

    //gl_ClipDistance[0] = dot(worldPosition,plane);

    if(reverse_normals) // a slight hack to make sure the outer large cube displays lighting from the 'inside' instead of the default 'outside'.
        vs_out.Normal = transpose(inverse(mat3(model))) * (-1.0 * aNormal);
    else
        vs_out.Normal = transpose(inverse(mat3(model))) * aNormal;
    vs_out.TexCoords = aTexCoords;

    mat3 normalMatrix = transpose(inverse(mat3(model)));
    vec3 T = normalize(normalMatrix * aTangent);
    vec3 N = normalize(normalMatrix * aNormal);
    T = normalize(T - dot(T, N) * N);
    vec3 B = cross(N, T);

    mat3 TBN = transpose(mat3(T, B, N));    
    vs_out.TangentLightPos = TBN * lightPos;
    vs_out.TangentViewPos  = TBN * viewPos;
    vs_out.TangentFragPos  = TBN * vs_out.FragPos;

    gl_Position = projection * view * model * pos;

    //vs_out.FragPos = vec3(gl_Position);

    float waterRatio = 1./1.333;

    vec3 vNormal = (transpose(inverse(model))*vec4(aNormal, 0.0)).xyz;
    vec3 viewVector = normalize(worldPosition.xyz-camPos);
    vs_out.reflectedVector = reflect(viewVector,normalize(vNormal)); 
    vs_out.refractedVector = refract(viewVector,normalize(vNormal), waterRatio);



}

Then in the fragment shader i simply do:

vec4 reflectedColour = reflect(textureCube, reflectedVector);

The results i get are not correct as you can see: https://imgur.com/b6Uk784 https://imgur.com/0QfQ45F

I believe it has to do with the way im writing the framebuffer to the cubemap. What is wrong with my code? Any help appreciated!





Aucun commentaire:

Enregistrer un commentaire