How to use a color texture to store a depth map for Variance shadow mapping

Hello guys!
I am having trouble implementing Variance Shadow Mapping where the depth map, created during the first pass, is made by storing depth in a two component color texture (GL_RG32F) instead of a single component depth texture (GL_DEPTH_COMPONENT32) as is done in basic Shadow Mapping technique.

When i use said texture in my second pass I get a scene rendered in black ( black ). But if I use a depth texture instead i get a correct result ( notBlack ).

I’m speculating that this problem is not hard to correct, but i’m not really good at opengl so i spent the last two days banging my head over this with no result. Any help would be much appreciated!

Here is my code from main.cpp and two fragment shaders (one for each pass):


        const float color[4] = {1.0f, 0.0f, 0.0f, 0.0f};
	const int SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
	const int WINDOW_WIDTH = 640,  WINDOW_HEIGHT = 480;
	
	GLuint mFramebuffer = 0;
	GLuint colorTexture = 0;
	GLuint depthTexture = 0;

	glGenTextures(1, &colorTexture);
	glBindTexture(GL_TEXTURE_2D, colorTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, SHADOW_WIDTH, SHADOW_HEIGHT, 
        0, GL_RGBA, GL_FLOAT, 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_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);

	glGenTextures(1, &depthTexture);
	glBindTexture(GL_TEXTURE_2D, depthTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_WIDTH, 
        SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 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_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);

	glGenFramebuffers(1, &mFramebuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
        GL_TEXTURE_2D, colorTexture, 0);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 
        GL_TEXTURE_2D, depthTexture, 0);

	if( glCheckFramebufferStatus(GL_FRAMEBUFFER) != 
        GL_FRAMEBUFFER_COMPLETE )
		std::cerr <<"[CHECK_FB_STATUS]: "<< std::endl;

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LESS);

      // I use an orthographic projection to create a depth map,
      // but a perspective projection for rendering the actual scene

    glm::mat4 depthP = glm::ortho<float>(-10,10,-10,10,-10,20);
    glm::mat4 P	 = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
    
    do{
		// First Pass
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
	    glViewport(0,0, SHADOW_WIDTH, SHADOW_HEIGHT);
    	glClear( GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);
    	glUseProgram(firstPassID);

		// Drawing MY CUBE
    	glUniformMatrix4fv(glGetUniformLocation(firstPassID, "depthMVP"), 
                           1,GL_FALSE, &depthMVP[0][0]);
	    glDrawArrays(GL_TRIANGLES, 0, 12*3);

		// Second Pass
	
     	computeMatricesFromInputs(mWindow);	 //I'm using fabien's 
    	P = getProjectionMatrix();		     //functions to move
    	V = getViewMatrix();			     //the camera with wsad and mouse

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glBindFramebuffer(GL_FRAMEBUFFER,0);	
    	glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	glUseProgram(secondPassID);

		// Drawing MY CUBE
	
        glUniform3f(glGetUniformLocation( 
        secondPassID,"pointLights.position"), worldSpace_lightPos.x, 
        worldSpace_lightPos.y, worldSpace_lightPos.z);
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, "model"), 1, 
        GL_FALSE, &M[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, "view"), 1, 
        GL_FALSE, &V[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, 
        "projection"), 1, GL_FALSE, &P[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, 
        "depthBiasMVP"), 1, GL_FALSE, &depthBiasMVP[0][0]);
    		glActiveTexture(GL_TEXTURE0);
    		glBindTexture(GL_TEXTURE_2D, colorTexture);
        // If i bind depthTexture here instead it works
            glUniform1i(glGetUniformLocation(secondPassID, "ShadowMap"), 0);
    	    glDrawArrays(GL_TRIANGLES, 0, 12*3);

		// Drawing MY PLANE
    	glUniform3f(glGetUniformLocation( 
        secondPassID,"pointLights.position"), worldSpace_lightPos.x, 
        worldSpace_lightPos.y, worldSpace_lightPos.z);
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, "model"), 1, 
        GL_FALSE, &M[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, "view"), 1, 
        GL_FALSE, &V[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, 
        "projection"), 1, GL_FALSE, &P[0][0] );
    	glUniformMatrix4fv(glGetUniformLocation(secondPassID, 
        "depthBiasMVP"), 1, GL_FALSE, &depthBiasMVP[0][0]);
		    glActiveTexture(GL_TEXTURE0);
    		glBindTexture(GL_TEXTURE_2D, colorTexture);
        // If i bind depthTexture here instead it works
    		glUniform1i(glGetUniformLocation(secondPassID, "ShadowMap"), 0);
	        glDrawArrays(GL_TRIANGLES, 0, 2*3);

    glfwSwapBuffers(mWindow);
    glfwPollEvents();

    }while(glfwGetKey(mWindow, GLFW_KEY_ESCAPE ) != GLFW_PRESS && 
		glfwWindowShouldClose(mWindow) == 0);

This is my firstPassID’s fragment shader:


    #version 330 core
    in vec4 mvp_pos;	// I pass it as depthMVP * vec4(position,1)

    void main()
    {
	float depth = mvp_pos.z / mvp_pos.w ;
	depth = depth * 0.5 + 0.5;			

	float moment1 = depth;
	float moment2 = depth * depth;

	float dx = dFdx(depth);
	float dy = dFdy(depth);

	moment2 += 0.25*(dx*dx+dy*dy);

	gl_FragColor = vec4( moment1,moment2, 0.0, 0.0 );
    }

My secondPassID’s fragment shader:


    struct pointlight {
    vec3 position;
    
    float constant;
    float linear;
    float quadratic;
	
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    };

    in vec3 eyeSpace_coordinates;
    in vec3 eyeSpace_normals;
    in vec4 lightSpace_coordinates;

    uniform sampler2D ShadowMap;
    uniform pointlight pointLights;

    uniform mat4 view;
    uniform mat4 projection;

    float chebyshevUpperBound( float distance, vec2 myPos)
    {
	vec2 moments = texture2D(ShadowMap, myPos).rg;
	
	if (distance <= moments.x)
		return 1.0f;

	float variance = moments.y - ( moments.x*moments.x );
	variance = max( variance, 0.00002 );

	float d = distance - moments.x;
	float p_max = variance / (variance + d*d);
	p_max = clamp(p_max, 0, 1);

    return p_max;
    }

    vec3 CalcPointLight(pointlight light, vec3 normal, vec3 fragPos)
    {
	vec3 eyeSpace_lightPos = ( view * vec4( light.position, 1.0f )).xyz;

	vec3 lightDir = normalize(eyeSpace_lightPos - fragPos);

	float cosTheta = max(dot(normal, lightDir), 0.0);

	vec3 ambient = light.ambient * vec3(1.0f, 0.0f, 0.0f);
	vec3 diffuse = light.diffuse * cosTheta * vec3(1.0f, 0.0f, 0.0f);

    return (ambient + diffuse);
    }

    void main()
    {
	vec4 ls_Pos = lightSpace_coordinates/ lightSpace_coordinates.w;

	vec3 eyespace_cameraDir = -eyeSpace_coordinates;
	vec3 n = normalize(eyeSpace_normals);

	float shadow = chebyshevUpperBound(ls_Pos.z, ls_Pos.xy);
	vec3 light = CalcPointLight(pointLights, n, eyeSpace_coordinates);

	gl_FragColor = vec4( vec3(shadow), 1.0f ) * vec4(light, 1.0f);
    }

Turns out you have to enable writing to first two components in color texture:
glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_FALSE);

God bless!