opengl - GL_FRAMEBUFFER_SRGB_EXT banding problems (gamma correction) -
consider following code. imagedataf float*. in fact, code shows consist of float4 values created ray tracer. of course, color values in linear space , need them gamma corrected output on screen. can simple loop gamma correction of 2.2 (see loop). also, can use gl_framebuffer_srgb_ext, works correclty has "banding" problems.
left using gl_framebuffer_srgb_ext, right manual gamma correction. right picture looks perfect. there may difficulties spot on monitors. have clue how fix problem? gamma correction "free" cpu version makes gui bit laggy. note actual ray tracing done in thread using gpu(optix) in fact fast in rendering performance.
glboolean srgb = gl_false; glgetbooleanv( gl_framebuffer_srgb_capable_ext, &srgb ); if (srgb) { //glenable(gl_framebuffer_srgb_ext); } for(int = 0; < 768*768*4; i++) { imagedataf[i] = (float)powf(imagedataf[i], 1.0f/2.2f); } glpixelstorei(gl_unpack_alignment, 8); gldrawpixels( static_cast<glsizei>( buffer_width ), static_cast<glsizei>( buffer_height ), gl_rgba, gl_float, (glvoid*)imagedataf); //gldisable(gl_framebuffer_srgb_ext);
when gl_framebuffer_srgb
enabled, means opengl assume colors fragment in linear colorspace. therefore, when writes them srgb-format image, convert them internally linear srgb. except... pixels not linear. converted them non-linear colorspace.
however, i'll assume forgot if
statement in there. i'll assume if framebuffer srgb capable, skip loop , upload data directly. instead, i'll explain why you're getting banding.
you're getting banding because opengl operation asked following. each color specify:
- clamp floats [0, 1] range.
- convert floats unsigned, normalized, 8-bit integers.
- generate fragment unsigned, normalized, 8-bit color.
- convert unsigned, normalized, 8-bit fragment color linear rgb space srgb space , store it.
steps 1-3 come use of gldrawpixels
. problem step 2. want keep floating-point values floats. yet insist on using fixed-function pipeline (ie: gldrawpixels
), forces conversion float unsigned normalized integers.
if uploaded data float texture , used proper fragment shader render texture (even simple gl_fragcolor = texture(tex, texcoord);
shader), you'd fine. shader pipeline uses floating-point math, not integer math. no such conversion occur.
in short: stop using gldrawpixels
.
Comments
Post a Comment