Render cubemap to another cubemap with transparancy?

I wish to have shadows with multiple lights.

Each light’s shadow rendered to a depth cubemap.

How do I render each cubemap onto a single cubemap with transparency so have a cubemap with all the shadows?

This is how I’m setting up the cubemaps: code based on tutorial Learn OpenGL, extensive tutorial resource for learning Modern OpenGL

const GLuint SHADOW_WIDTH = 1024, SHADOW_HEIGHT = 1024;
    const int totalLights = 4;
    GLuint depthMapFBO[totalLights];
    GLuint depthCubemap[totalLights];

for (GLuint light = 0; light < totalLights; ++light)
    {
        glGenFramebuffers(1, &depthMapFBO[light]);
        // Create depth cubemap texture
        glGenTextures(1, &depthCubemap[light]);
        glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap[light]);
        for (GLuint i = 0; i < 6; ++i)
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
        // Attach cubemap as depth map FBO's color buffer
        glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO[light]);
        glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap[light], 0);
        glDrawBuffer(GL_NONE);
        glReadBuffer(GL_NONE);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            std::cout << "Framebuffer not complete!" << std::endl;
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

And this is the code to render a single cubemap:

// 1. Render scene to depth cubemap
            glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
            glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO[0]);
            glClear(GL_DEPTH_BUFFER_BIT);

            // Set texture samples
            simpleDepthShader.Use();

            // 0. Create depth cubemap transformation matrices
            GLfloat aspect = (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT;

            glm::mat4 shadowProj = glm::perspective(90.0f, aspect, fNear, fFaar);
            std::vector<glm::mat4> shadowTransforms;
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
            shadowTransforms.push_back(shadowProj * glm::lookAt(lightPositions[light], lightPositions[light] + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));

            for (GLuint i = 0; i < 6; ++i)
                glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, ("shadowTransforms[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(shadowTransforms[i]));
            glUniform1f(glGetUniformLocation(simpleDepthShader.Program, "far_plane"), fFaar);
            glUniform3fv(glGetUniformLocation(simpleDepthShader.Program, "lightPos"), 1, &lightPositions[light][0]);
            RenderScene(simpleDepthShader);
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
 

I really need help with this…It’s essential to my project.
I have created a new type of portal implementation called CACP. Can have lighting and shadow come in and out the portal, hence need multiple lighting and shadows.

All help very much appreciated. Thank you.

I’m wondering if it would be easier to create 6 individual renderbuffers rather than use a cubemap? Rendering individual textures to a full screen quad seems an easier option to do the combining?

Any tutorials available?

Unless someone can prove me wrong?

You can either bind an individual face of a cube map to the framebuffer with glFramebufferTextureLayer(), or you can bind the entire cube map with glFramebufferTexture(). In the latter case, the framebuffer will be layered, so you’ll need to have a geometry shader select the desired face by assigning to gl_Layer.

Processing each face separately is probably simpler; processing the entire cube map with a single draw call may be more efficient.

[QUOTE=GClements;1285250]You can either bind an individual face of a cube map to the framebuffer with glFramebufferTextureLayer(), or you can bind the entire cube map with glFramebufferTexture(). In the latter case, the framebuffer will be layered, so you’ll need to have a geometry shader select the desired face by assigning to gl_Layer.

Processing each face separately is probably simpler; processing the entire cube map with a single draw call may be more efficient.[/QUOTE]

I like the geometry shader approach.

So heres a shader:

#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;

uniform mat4 transform;

in int face;
out vec4 FragPos;

void main()
{
	gl_Layer = face; 
	for(int i = 0; i < 3; ++i) // for each triangle's vertices
	{
		FragPos = gl_in[i].gl_Position;
		gl_Position = transform * FragPos;
		EmitVertex();
	}    
	EndPrimitive();
}  

So I create a uniform specifying which face.

Now the vertex shader, am stuck!

#version 330 core
layout (location = 0) in vec3 position;

void main()
{
    gl_Position = ???
}

And the fragment shader:

#version 330 core

in vec3 TexCoords;
out vec4 FragColor;
uniform samplerCube depthMap;

void main()
{
	FragColor = textureCube(depthMap, TexCoords);  //need to change this and more..
} 

Heres what I just put together for rendering to a cubemap:

		for (GLuint light = 0; light < totalLights; ++light)
		{
			glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO[combineCubemapBuffer]);
			glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			shaderCombineShadows.Use();
			
			for (int face = 0; face < 6; face++)
			{
				glActiveTexture(GL_TEXTURE0);
				glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap[light]);
				glUniform3i(glGetUniformLocation(shaderMultipassShadows.Program, "face"), 1, face);
				glUniform1i(glGetUniformLocation(shaderMultipassShadows.Program, "depthMap"), 0);
				RenderQuad();
				glBindFramebuffer(GL_FRAMEBUFFER, 0);
			}
		}

I’m guessing I send all the cubemaps to the renderer simultaneously.

All help appreciated.
Ill release a demo for people on github.

Am wondering how many lights do you think an average grahics card can handle?
1024 * 1024 * 24 bits = 3.14 meg bytes per framebuffer.
Multiply that by 6 buffers per cubemap = 18.84 meg bytes.
So 50 lights = 942 meg bytes.
Think a card can handle that amount?

Probably be able to do the shadows portal by portal. Each portal having it’s own combiner cubemap, then combine all the combiners.
I think a max of 25 lights per portal would be pretty good.

You know, I’m not positive this portal+lights+shadows will work. It’s a bit like creating the portal my new way, wasn’t positive CACP would work at any camera angle. But it works beautifully.:slight_smile:

Combining CACP, LACP and SACP will be beautiful, I’m 98% sure of it! :smiley:
May be I should try for a job at opengl? I’m good for ideas but need experience though.
If I had the money I would patent these 3 4 letters abbreviations. :smiley: Want to do a deal opengl?
Still got copyright though! :slight_smile:

CACP, LACP, SACP copyright 2017 Paul G Griffiths.

This is what I have so far;

Geometry shader:

#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;
 
uniform mat4 transform;
uniform int face;
out vec3 TexCoords;

void main()
{
	gl_Layer = face; 
	for(int i = 0; i < 3; ++i) // for each triangle's vertices
	{
		gl_Position = transform * gl_in[i].gl_Position;
		TexCoords = gl_in[i].gl_Position.xyz; 
		EmitVertex();
	}    
	EndPrimitive();
}

I think for my shadows the vertex shader should be this?
Is this correct?

#version 330 core
layout (location = 0) in vec3 position;

void main()
{
    gl_Position =   vec4(position, 1.0); 
} 

And Ifor the fragment shader.

#version 330 core

in vec3 TexCoords;
out vec4 FragColor;
uniform samplerCube depthMap;

void main()
{
	FragColor = texture(depthMap, TexCoords);
}

And this so far for the render code(1 cubemap);

			glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO[combineCubemapBuffer]);
			glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			shaderCombineShadows.Use();
			// 0. Create depth cubemap transformation matrices
			GLfloat aspect = (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT;
			glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f);
			glm::mat4 shadowProj = glm::perspective(90.0f, aspect, fNear, fFaar);
			glm::mat4 shadowTransform;

			for (int face = 0; face < 6; face++)
			{
				switch (face)
				{
				case 0:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
					break;

				case 1:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
					break;

				case 2:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
					break;

				case 3:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
					break;

				case 4:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
					break;

				case 5:
					shadowTransform = glm::mat4(shadowProj * glm::lookAt(position, position + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));
					break;
				}

				glActiveTexture(GL_TEXTURE0);
				glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap[0]);
				glUniform1i(glGetUniformLocation(shaderCombineShadows.Program, "face"), face);
				glUniformMatrix4fv(glGetUniformLocation(simpleDepthShader.Program, "transform"), 1, GL_FALSE, glm::value_ptr(shadowTransform));
				glUniform1i(glGetUniformLocation(shaderCombineShadows.Program, "depthMap"), 0);
				RenderQuad();
				glBindFramebuffer(GL_FRAMEBUFFER, 0);
			}

render quad function:

	
// RenderQuad() Renders a 1x1 quad in NDC, best used for framebuffer color targets
// and post-processing effects.
GLuint quadVAO = 0;
GLuint quadVBO;
void RenderQuad()
{
	if (quadVAO == 0)
	{
		GLfloat quadVertices[] = {
			// Positions        // Texture Coords
			-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
			-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
			1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
			1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
		};
		// Setup plane VAO
		glGenVertexArrays(1, &quadVAO);
		glGenBuffers(1, &quadVBO);
		glBindVertexArray(quadVAO);
		glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
		glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
	}
	glBindVertexArray(quadVAO);
	glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	glBindVertexArray(0);
}

Not copying the texture though , whats wrong?

I’m getting this all wrong. Even if could combine cubemaps there all at different positions due to lighting at different positions.

Wasting my time with this one :frowning:

Any way shadows by cubemap with multiple lights glsl core 330 or upto 4.0?

Any advice appreciated.

I need lighting and shadows on all walls and objects regardless of position or scene. Is this even possible?

It is possible: https://www.youtube.com/watch?v=BACNDyDZs4w

Can anyone explain how it is done?

[EDIT:] Please don’t start multiple threads on the same topic in different forums. I just noticed that this relates to your other 2 recent threads here and to some extent here. I’ll combine this with the first thread.

You probably need to provide more information about your use case for folks to provide much useful input.

How many lights sources?
What types of light sources (e.g. point, directional, etc.)?
Are the light sources dynamic?
How many objects?
Are the objects dynamic?

<other requirements/desires>

[QUOTE=Dark Photon;1285270]You probably need to provide more information about your use case for folks to provide much useful input.

How many lights sources?
What types of light sources (e.g. point, directional, etc.)?
Are the light sources dynamic?
How many objects?
Are the objects dynamic?

<other requirements/desires>[/QUOTE]

About 100 lights, point and directional, static and non static lights and objects, lots of them.
Game size ideas. All of the above.

Found a book opengl insights but it’s glsl 4.5, I’m only 4.0 so got to get a new pc.

Am thinking of using cubemap arrays for my multiple shadows but can you dynamically set uniform array lengths in glsl 4.0?

No. The only situation where the size of an array needn’t be fixed at shader compilation time is the last element of a SSBO, and those only exist in 4.3 and later.

Also, array textures have nothing to do with GLSL arrays; they are accessed via a single sampler uniform.