PDA

View Full Version : Radiosity with OpenGL



maciekmos
04-01-2012, 01:35 PM
Hi,
Ive been trying to implement instant radiosity with OpenGL. I wont go through details but what ive been trying to do is :

We have many lightsources and we want to get illumination of a scene with them. Ive been using accumulation buffer ( cos in opengl there is max 8 lights in one go ) and gl spot lights.

Problem was that with glLightfv( Lightn, GL_DIFFUSE, LightIntensity); LightIntensity values are clumped to 1.0 and radiosity can be much bigger then one. Ive tried to do the trick LightIntensity /= 1000 and then with for every call of glAccum do glAccum( GL_ACCUM, 1000 ); unfortunetely that isnt possible without extension i believe.

So in order to make it possible ive started using ARB_color_buffer_float extension with glew.

Ive initialised glew and check if extension was available
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));

}
if( glewIsSupported("GL_ARB_color_buffer_float") )
{
printf("COOL\n");
}
It was working fine.
Then before rendering ive used
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
Program is compiling and works but unfortunetely results are still or
black screen or completly white ( depending on parameters )
Ive tried to simulate basic equation of global illumination with spotlights .Something like this :
glLightfv( OpenGlLights[iLightIndeks], GL_DIFFUSE, LightDiffusse);
glLightfv( OpenGlLights[iLightIndeks], GL_POSITION, LightSpotPosition);
glLightfv( OpenGlLights[iLightIndeks], GL_SPOT_DIRECTION, LightSpotNormal );
glLightf( OpenGlLights[iLightIndeks], GL_SPOT_CUTOFF , light0SpotCutoff);
glLightf( OpenGlLights[iLightIndeks], GL_QUADRATIC_ATTENUATION, 1);

I think that something is wrong with colors clamping.
Any ideas ? How can i check it out(debug and stuff )? (besides basic
knowledge of open gl i dont have experience with extension and more advanced stuff.
Any help will be apprecieted.
Thanks,

maciekmos
04-04-2012, 01:55 PM
Hi
Maybe i should rephrase my question.
I would like to have spotlights with high lights intensity.
The problem is that glLightfv( OpenGlLights[iLightIndeks], GL_DIFFUSE, LightDiffusse); clamps LightDiffusse to 1.0. What id like to do then
is get rid of clamping ( i thought that ARB_color_buffer_float extension would be helpful but apparently it doesnt work too well ).

I could also divide LightDiffusse by let say 1000 and after rendering multiply all colors values by 1000. In order it work i would have to increase the color depth on each channel lets say to 32 bit. Does anyone know how to do this ?
thanks in advance.

ZbuffeR
04-04-2012, 02:13 PM
To attain your goals you should use modern OpenGL.

That means, forget about accum buffer and glLightfv, but instead use vertex and fragment shaders with floating point render targets on FBO.

Good tutorials for the general topics around modern GL are here : http://www.arcsynthesis.org/gltut/

Alfonse Reinheart
04-04-2012, 02:48 PM
BTW, what you're talking about, "What id like to do then is get rid of clamping," has nothing to do with radiosity. That's high-dynamic-range rendering/lighting.

maciekmos
04-05-2012, 03:07 AM
I didnt want to get throught all details but one voxels based method gives radiosity on voxels and for final gather i d like to use opengl.
So light intensity would be radiosity in this case i imagine but it needs to be rescaled cos in opengl RGB channels are clumped to 1.

V-man
04-05-2012, 06:05 AM
I didnt want to get throught all details but one voxels based method gives radiosity on voxels and for final gather i d like to use opengl.
So light intensity would be radiosity in this case i imagine but it needs to be rescaled cos in opengl RGB channels are clumped to 1.

It depends on the buffer format. If your buffer is a RGB8 or BGR8 or whatever, the values are from 0 to 255 (represented as 0.0 to 1.0).

If you buffer format is floating point, then the full floating point range can be used, all negative and positive values.

Example: GL_RGB32F, GL_RGBA32F, GL_RGB16F, GL_RGBA32F and the many other formats of GL 3.0

maciekmos
04-12-2012, 01:21 PM
Thanks a lot for showing me right direction. :)
However is still have implementation problems/questions.
Ive started implementing this with FBOs and i imagine it should work in following way:
I have 2 FBOs :
FBO_render - used to get part of image with 8 lights (or less )
FBO_Accum - used to accumumulate image after rendering to FBO_render. So imagine it would work like that:
i=0;
while( i < number of lights )
{
render scene with lights from i to i+ max(7, number of lights -i) to FBO_render
i += max(7, number of lights -i);
FBO_Accum = FBO_Accum + FBO_render;
}
FBO_Accum would be final picture.
The question is if and how i can perform FBO_Accum = FBO_Accum + FBO_render; operation
using shaders ( i havent writen single shader in my life and its not very clear if its possible). '+' in this context means adding colors components of relevant texels.

Second question:
Also i've tried to render to FBO scene with lights with intensity > 1 and and then rendering texture (of this FBO) to the screen. Unfortunetely it doesnt work (ive got black screen). However it works fine with lights intensity <= 1. Here is initialisation of FBO :

void OpenGlRenderer::initFrameBufferDepthBuffer(void)
{

glGenRenderbuffersEXT(1, &amp;iDepthBuffer); // Generate one render buffer and store the ID in iDepthBuffer
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, iDepthBuffer); // Bind the iDepthBuffer render buffer

glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, OPT.m_nWidth, OPT.m_nHeight); // Set the render buffer storage to be a depth component, with a width and height of the window

glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, iDepthBuffer); // Set the render buffer of this buffer to the depth buffer

glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); // Unbind the render buffer
}

void OpenGlRenderer::initFrameBufferTexture(void)
{
glGenTextures(1, &amp;iTextureImg); // Generate one texture
glBindTexture(GL_TEXTURE_2D, iTextureImg); // Bind the texture iTextureImg

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, OPT.m_nWidth, OPT.m_nHeight, 0, GL_RGB, GL_FLOAT, NULL); // Create a standard texture with the width and height of our window

// Setup the basic texture parameters
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// Unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
}

void OpenGlRenderer::initFrameBuffer(void)
{
initFrameBufferDepthBuffer(); // Initialize our frame buffer depth buffer

initFrameBufferTexture(); // Initialize our frame buffer texture

glGenFramebuffersEXT(1, &amp;iFrameBufferAccumulation); // Generate one frame buffer and store the ID in iFrameBufferAccumulation
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, iFrameBufferAccumulation); // Bind our frame buffer
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, iTextureImg, 0); // Attach the texture fbo_texture to the color buffer in our frame buffer

glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, iDepthBuffer); // Attach the depth buffer iDepthBuffer to our frame buffer
checkFramebufferStatus();
}

and for lights initialisation:
for(int i= iIndeksFrom; i< iIndeksFrom+iLightsToUse; ++i )
{
LightDiffusse[0] = xLights[i].Bradio.x /**0.0025*/;
LightDiffusse[1] = xLights[i].Bradio.y /**0.0025*/;
LightDiffusse[2] = xLights[i].Bradio.z /**0.0025*/;
LightDiffusse[3] = 1;
float XR = xLights[i].Bradio.x;
float YR = xLights[i].Bradio.y;
float ZR = xLights[i].Bradio.z;
LightSpotNormal[0] = xLights[i].v_n.x;
LightSpotNormal[1] = xLights[i].v_n.y;
LightSpotNormal[2] = xLights[i].v_n.z;

LightSpotPosition[0] = xLights[i].pos.x;
LightSpotPosition[1] = xLights[i].pos.y;
LightSpotPosition[2] = xLights[i].pos.z;

float XP = xLights[i].pos.x;
float YP = xLights[i].pos.y;
float ZP = xLights[i].pos.z;

glLightfv( OpenGlLights[iLightIndeks], GL_DIFFUSE, LightDiffusse);
glLightfv( OpenGlLights[iLightIndeks], GL_POSITION, LightSpotPosition);
glLightfv( OpenGlLights[iLightIndeks], GL_SPOT_DIRECTION, LightSpotNormal );
glLightf( OpenGlLights[iLightIndeks], GL_SPOT_CUTOFF , 90);
glLightf( OpenGlLights[iLightIndeks], GL_QUADRATIC_ATTENUATION, 1);
iLightIndeks++;
}
Where xLights[i].Bradio.x, xLights[i].Bradio.y, xLights[i].Bradio.z are usually around 400

Can someone help me out?
Thanks in advance.

maciekmos
04-12-2012, 02:34 PM
Ive changed
void OpenGlRenderer::initFrameBufferTexture(void)
{
glGenTextures(1, &amp;iTextureImg); // Generate one texture
glBindTexture(GL_TEXTURE_2D, iTextureImg); // Bind the texture iTextureImg

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, OPT.m_nWidth, OPT.m_nHeight, 0, GL_RGB, GL_FLOAT, NULL); // Create a standard texture with the width and height of our window

// Setup the basic texture parameters
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// Unbind the texture
glBindTexture(GL_TEXTURE_2D, 0);
}
as it was recomended on the site http://gpgpu.org/ to
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, iTextureImg);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_FLOAT_R32_NV, OPT.m_nWidth, OPT.m_nHeight, 0, GL_RGBA, GL_FLOAT, NULL);

and generally GL_TEXTURE_2D to GL_TEXTURE_RECTANGLE_ARB but now i get
only white screen .. ehh.