How do i make cubemapping

Started by
2 comments, last by agleed 9 years ago

I recently read whole bunch of articles i failed to make my cubemap reflections.

So basically in my opinion the idea is like that:

-generate a cubemap texture

-set all cubemap sides (put pictures in it)

-get cubemap color at (reflectionvector(vertexpos - camerapos, vertex_normal); within fragment shader

noreflection.png

that black color was supposed to be a water with cubemap reflection of a skydome.

so i initialize a cubemap texture wtih:


void InitCubeMapTextures()
{
	glActiveTexture(GL_TEXTURE3);
glGenTextures(1, &CUBEMAP_TEXTURE);
glBindTexture(GL_TEXTURE_CUBE_MAP, CUBEMAP_TEXTURE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glActiveTexture(GL_TEXTURE0);
}

then to update the cubemap i use (hold on for a moment its a long piece of code dont mind i use glReadPixels - i was trying framebuffers (rendering to texture), glcopyteximage etc. since with glreadpixels i could write a simple tga file and see if anything is drawn ( and yes cube map textures shoudl be updated - at least pixels are valid)




void AquireCubemap()
{
	
	gluPerspectiveA(ACTUAL_PROJECTION, 90.0f, 1.0f, 1000.0f, 1000.0f * 1000.0f * 1000.0f);

	glActiveTexture(GL_TEXTURE3);

	glDepthMask(GL_FALSE);
    glDisable(GL_DEPTH_TEST);
    glViewport(0, 0, 128, 128);

    glBindTexture(GL_TEXTURE_CUBE_MAP, CUBEMAP_TEXTURE);

    glClear(GL_COLOR_BUFFER_BIT);
    glClear(GL_DEPTH_BUFFER_BIT);

    TSpecCamera * cube_cam = new TSpecCamera();
    cube_cam->SetCamera(t3dpoint<float>(0.0,0.0,0.0),t3dpoint<float>(100.0,0.0,0.0),t3dpoint<float>(0.0,0.0,100.0),t3dpoint<float>(0.0,1.0,0.0));
    cube_cam->lookatpoint = true;
    cube_cam->pos = t3dpoint<float>(0.0f, 0.0f, 0.0f);

    unsigned char * pdata = new unsigned char[viewport_size*viewport_size*4];
    //X cubemap
    cube_cam->lap = t3dpoint<float>(100.0f, 0.0f, 0.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);

glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);

glClear(GL_COLOR_BUFFER_BIT);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



//    unsigned char * pdata = new unsigned char[viewport_size * viewport_size * 4];
//AnsiString fname = appdir+"shaders\cubemap_X_plus.tga";
//	glReadPixels(0,0,viewport_size,viewport_size,GL_RGBA,GL_UNSIGNED_BYTE,pdata);
//	WriteTga(fname.c_str(), viewport_size, viewport_size, 32, pdata);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //-X cubemap
    cube_cam->lap = t3dpoint<float>(-100.0f, 0.0f, 0.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);
    glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);

    glClear(GL_COLOR_BUFFER_BIT);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //Y cubemap
    cube_cam->lap = t3dpoint<float>(0.0f, 100.0f, 0.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);
    glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
 
    glClear(GL_COLOR_BUFFER_BIT);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //-Y cubemap
    cube_cam->lap = t3dpoint<float>(0.0f, -100.0f, 0.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);
    glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
  
    glClear(GL_COLOR_BUFFER_BIT);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //Z cubemap
    cube_cam->lap = t3dpoint<float>(0.0f, 0.0f, 100.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);
    glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
   
    glClear(GL_COLOR_BUFFER_BIT);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //-Z cubemap
    cube_cam->lap = t3dpoint<float>(0.0f, 0.0f, -100.0f);
    cube_cam->SetView();
    SkyDome->Draw(cube_cam);
    glReadPixels(0, 0, viewport_size, viewport_size, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, viewport_size, viewport_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pdata);
 
    glClear(GL_COLOR_BUFFER_BIT);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glActiveTexture(GL_TEXTURE0);
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    delete cube_cam;
   
}
//----------------------------------------------------------------------------------------------

as maybe you can see i use cubemap texture in GL_TEXTURE3

procedure draws skydome and fetches the image to the texture

then i call actuall drawing code


glUseProgram(program);

glUniform1i(glGetUniformLocation(program, "cubemap"), 3);

draw_water();

glUseProgram(0);

every uniform has valid location and i pass all data (Including normals to the buffer) - thats for sure because i checked that in different shader

now shaders:

VP


attribute vec3 Vpos;
attribute vec2 Vtexcoord;
attribute vec3 Vnormal;
attribute vec4 Vcolor;
attribute float Vheight;

uniform vec4 MVP1;
uniform vec4 MVP2;
uniform vec4 MVP3;
uniform vec4 MVP4;
uniform vec3 u_cameraPosition;

vec4 vertexClip;
varying vec3 u_normalMap;
varying vec3 vertex_position;
varying vec3 REFLECTED_VEC;

float dp43(vec4 matrow, vec3 p)
{
return ( (matrow.x*p.x) + (matrow.y*p.y) + (matrow.z*p.z) + matrow.w );
}

vec3 Reflect_vec(vec3 incoming, vec3 normal)
{
return incoming - 2.0*dot(incoming, normal)*normal;
}
 
void main()
{
vec3 new_pos = Vpos + vec3(0.0,Vheight,0.0);
vertexClip.x = dp43(MVP1, new_pos);
vertexClip.y = dp43(MVP2, new_pos);
vertexClip.z = dp43(MVP3, new_pos);
vertexClip.w = dp43(MVP4, new_pos);



vec3 Incidence = new_pos - u_cameraPosition;
REFLECTED_VEC = Reflect_vec(Incidence, Vnormal); //if normalzied returns same thing



gl_Position = vertexClip;


}

FP



varying vec3 REFLECTED_VEC;

uniform samplerCube cubemap;



void main()
{
vec3 cube_col = textureCube(cubemap, REFLECTED_VEC).rgb;
gl_FragColor = vec4(cube_col, 1.0);
}

Yo!

Advertisement

I can't find any obvious errors, although just looking through strangers code it's hard to find random bugs without being able to actually debug the code. You should conquer this step by step to find out what's going wrong.

- check that your method of uploading the cubemap faces actually works. If you can't use a debugging tool like Renderdoc (since you're not using GL 3+) or gDebugger for that, you can check the contents of the cube map faces using glGetTexImage

- check the various things you're computing in the vertex and fragment shader by "debug output"-ing them on the screen. For example, output the normal value, output view direction value, output some hardcoded values from the cubemap, and check if what you're seeing matches up with what you expect. For example, output textureCube(cubemap,vec3(1,0,0)) and draw a little pink dot at the middle of your POSITIVE_x cubemap face and see if it shows up.

- etc.

since i cant use glgetteximage (i am using opengl es 2.0) for that i am wondering if the cubemap calculations is bad i diint check everything from the list, but how does that cube map look liek i mean

how this determine that it has to get the color from upper front left corner of the cubemap is it something like infinite big cube and then it extends the ray to that plane and checks for it or what

because when i am using 128x128 (per cube side) it needs somehow to be stretched to match the enviroment i totally dont get that

Yes, cubemap sampling works as if you would shoot a ray (the vec3 you hand to textureCube) from the center of a cube (doesn't matter if it's infinitely big or 1x1x1, the result would be the same) and look where the ray hits it.

Regarding your calculations of the cubemap sample coords: They look fine superficially, but even if they aren't, it's unusual that you would just get a completely black output. Even if the calcuations were off somewhere, you'd expect some kind of colored output, assuming your cubemap itself is not completely black e.g. in the bottom half. That's why I was suggesting looking at the contents of the cubemap, or the contents of all the elements that go into your calculations in the vertex shader. Unfortunately I can't help you with GL ES specifics, I haven't ever used that API.

This topic is closed to new replies.

Advertisement