precise srgb->linear conversion experiment; color gradients experiment
parent
4aa71a8e0f
commit
7c4ca1dc6e
|
@ -1,5 +1,21 @@
|
|||
#include <Windows.h>
|
||||
|
||||
////////////////////////////////
|
||||
//- Experiment Configuration
|
||||
|
||||
// When this is 0 colors in vertex attributes and uniforms
|
||||
// that are converted (sRGB -> Linear) are converted using
|
||||
// the approximate (sRGB -> Linear) (f(x)=x^2.2); When this
|
||||
// is 1 those colors are converted using an accurate
|
||||
// (sRGB -> Linear) conversion.
|
||||
// This has no effect on colors sampled from sRGB textures
|
||||
// which are not converted by shader code, but by the OpenGL
|
||||
// implementation itself. By default this is zero to show the
|
||||
// difference between the approximate and accurate
|
||||
// conversions in test #3.
|
||||
#define USE_ACCURATE_CONVERSIONS_IN_SHADER 0
|
||||
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
//- Mini-Base
|
||||
|
@ -53,6 +69,8 @@ static void wgl_helper_end_render(void);
|
|||
typedef struct Vertex{
|
||||
F32 px;
|
||||
F32 py;
|
||||
F32 uvx;
|
||||
F32 uvy;
|
||||
F32 cr;
|
||||
F32 cg;
|
||||
F32 cb;
|
||||
|
@ -62,7 +80,9 @@ typedef struct Vertex{
|
|||
|
||||
static void opengl_render_init(void);
|
||||
|
||||
static void opengl_draw_test_geometry(Vertex *v, U64 count);
|
||||
static void opengl_draw_basic_geometry(Vertex *v, U64 count);
|
||||
static void opengl_draw_srgb_in_geometry(Vertex *v, U64 count);
|
||||
static void opengl_draw_texture_geometry(Vertex *v, U64 count, U32 texture);
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
|
@ -88,10 +108,30 @@ typedef unsigned char GLboolean;
|
|||
|
||||
#define GL_TRIANGLES 0x0004
|
||||
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
|
||||
#define GL_UNSIGNED_BYTE 0x1401
|
||||
#define GL_FLOAT 0x1406
|
||||
|
||||
#define GL_DEPTH_COMPONENT 0x1902
|
||||
#define GL_RED 0x1903
|
||||
#define GL_RGB 0x1907
|
||||
#define GL_RGBA 0x1908
|
||||
|
||||
#define GL_NEAREST 0x2600
|
||||
#define GL_LINEAR 0x2601
|
||||
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
|
||||
#define GL_MULTISAMPLE 0x809D
|
||||
|
||||
#define GL_CLAMP_TO_EDGE 0x812F
|
||||
|
||||
#define GL_TEXTURE0 0x84C0
|
||||
|
||||
#define GL_STREAM_DRAW 0x88E0
|
||||
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
|
@ -104,6 +144,17 @@ typedef unsigned char GLboolean;
|
|||
#define GL_INFO_LOG_LENGTH 0x8B84
|
||||
|
||||
#define GL_SRGB 0x8C40
|
||||
#define GL_SRGB8 0x8C41
|
||||
|
||||
#define GL_READ_FRAMEBUFFER 0x8CA8
|
||||
#define GL_DRAW_FRAMEBUFFER 0x8CA9
|
||||
|
||||
#define GL_COLOR_ATTACHMENT0 0x8CE0
|
||||
|
||||
#define GL_FRAMEBUFFER 0x8D40
|
||||
#define GL_FRAMEBUFFER_SRGB 0x8DB9
|
||||
|
||||
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
|
||||
|
||||
//- gl func x-list
|
||||
|
||||
|
@ -132,6 +183,7 @@ X(glGenVertexArrays, void, (GLsizei n, GLuint *arrays)) \
|
|||
X(glDeleteVertexArrays, void, (GLsizei n, const GLuint *arrays)) \
|
||||
X(glBindVertexArray, void, (GLuint array)) \
|
||||
/* textures */ \
|
||||
X(glGenTextures, void, (GLsizei n, GLuint *textures)) \
|
||||
X(glActiveTexture, void, (GLenum texture)) \
|
||||
X(glDeleteTextures, void, (GLsizei n, const GLuint *textures)) \
|
||||
X(glBindTexture, void, (GLenum target, GLuint texture)) \
|
||||
|
@ -213,7 +265,7 @@ static GLuint opengl_helper_make_program(GLuint *shaders, U32 count);
|
|||
////////////////////////////////
|
||||
//- OpenGL Render
|
||||
|
||||
static char test_vshader[] =
|
||||
static char basic_vshader[] =
|
||||
"#version 330\n"
|
||||
"uniform vec2 u_view_xform;\n"
|
||||
"layout (location = 0) in vec2 v_p;\n"
|
||||
|
@ -226,52 +278,210 @@ static char test_vshader[] =
|
|||
"}\n"
|
||||
;
|
||||
|
||||
static char test_fshader[] =
|
||||
static char basic_fshader[] =
|
||||
"#version 330\n"
|
||||
"in vec4 f_c;\n"
|
||||
"out vec4 out_color;\n"
|
||||
"void main(){\n"
|
||||
"out_color = f_c;\n"
|
||||
"}\n"
|
||||
"";
|
||||
;
|
||||
|
||||
GLuint test_program = 0;
|
||||
GLint test_u_view_xform = -1;
|
||||
static GLuint basic_program = 0;
|
||||
static GLint basic_u_view_xform = -1;
|
||||
|
||||
|
||||
|
||||
static char srgb_in_vshader[] =
|
||||
"#version 330\n"
|
||||
"\n"
|
||||
|
||||
#if USE_ACCURATE_CONVERSIONS_IN_SHADER
|
||||
"float lin_from_srgb(float x){\n"
|
||||
"float r = 0;\n"
|
||||
"if (x <= 0.04045) r = x/12.92;\n"
|
||||
"else r = pow(((x + 0.055)/1.055), 2.4);\n"
|
||||
"return(r);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"float srgb_from_lin(float x){\n"
|
||||
"float r = 0;\n"
|
||||
"if (x <= 0.0031308) r = x*12.92;\n"
|
||||
"else r = pow(x, 1/2.4)*1.055 - 0.055;\n"
|
||||
"return(r);\n"
|
||||
"}\n"
|
||||
#endif
|
||||
|
||||
"\n"
|
||||
"uniform vec2 u_view_xform;\n"
|
||||
"layout (location = 0) in vec2 v_p;\n"
|
||||
"layout (location = 1) in vec4 v_c;\n"
|
||||
"out vec4 f_c;\n"
|
||||
"void main(){\n"
|
||||
"vec2 norm_pos = v_p*u_view_xform + vec2(-1.0, -1.0);\n"
|
||||
|
||||
#if USE_ACCURATE_CONVERSIONS_IN_SHADER
|
||||
"float lin_r = lin_from_srgb(v_c.r);\n"
|
||||
"float lin_g = lin_from_srgb(v_c.g);\n"
|
||||
"float lin_b = lin_from_srgb(v_c.b);\n"
|
||||
#else
|
||||
"float lin_r = pow(v_c.r, 2.2);\n"
|
||||
"float lin_g = pow(v_c.g, 2.2);\n"
|
||||
"float lin_b = pow(v_c.b, 2.2);\n"
|
||||
#endif
|
||||
|
||||
|
||||
"gl_Position = vec4(norm_pos, 0.0, 1.0);\n"
|
||||
"f_c = vec4(lin_r, lin_g, lin_b, v_c.a);\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
static char srgb_in_fshader[] =
|
||||
"#version 330\n"
|
||||
"in vec4 f_c;\n"
|
||||
"out vec4 out_color;\n"
|
||||
"void main(){\n"
|
||||
"out_color = f_c;\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
static GLuint srgb_in_program = 0;
|
||||
static GLint srgb_in_u_view_xform = -1;
|
||||
|
||||
|
||||
|
||||
static char texture_vshader[] =
|
||||
"#version 330\n"
|
||||
"uniform vec2 u_view_xform;\n"
|
||||
"layout (location = 0) in vec2 v_p;\n"
|
||||
"layout (location = 1) in vec2 v_uv;\n"
|
||||
"out vec2 f_uv;\n"
|
||||
"void main(){\n"
|
||||
"vec2 norm_pos = v_p*u_view_xform + vec2(-1.0, -1.0);\n"
|
||||
"gl_Position = vec4(norm_pos, 0.0, 1.0);\n"
|
||||
"f_uv = v_uv;\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
static char texture_fshader[] =
|
||||
"#version 330\n"
|
||||
"uniform sampler2D u_texture;\n"
|
||||
"in vec2 f_uv;\n"
|
||||
"out vec4 out_color;\n"
|
||||
"void main(){\n"
|
||||
"out_color = vec4(texture(u_texture, f_uv).rgb, 1);\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
static GLuint texture_program = 0;
|
||||
static GLint texture_u_view_xform = -1;
|
||||
static GLint texture_u_texture = -1;
|
||||
|
||||
|
||||
|
||||
static GLuint canvas_texture = 0;
|
||||
static GLuint canvas_framebuffer = 0;
|
||||
|
||||
static GLuint test3_texture = 0;
|
||||
|
||||
static void
|
||||
opengl_render_init(void){
|
||||
//- setup test shader program
|
||||
//- setup basic shader program
|
||||
{
|
||||
GLuint shaders[2] = {0};
|
||||
shaders[0] = opengl_helper_make_shader(test_vshader, GL_VERTEX_SHADER);
|
||||
shaders[1] = opengl_helper_make_shader(test_fshader, GL_FRAGMENT_SHADER);
|
||||
test_program = opengl_helper_make_program(shaders, 2);
|
||||
test_u_view_xform = glGetUniformLocation(test_program, "u_view_xform");
|
||||
shaders[0] = opengl_helper_make_shader(basic_vshader, GL_VERTEX_SHADER);
|
||||
shaders[1] = opengl_helper_make_shader(basic_fshader, GL_FRAGMENT_SHADER);
|
||||
basic_program = opengl_helper_make_program(shaders, 2);
|
||||
basic_u_view_xform = glGetUniformLocation(basic_program, "u_view_xform");
|
||||
}
|
||||
|
||||
//- setup "srgb in" shader program
|
||||
{
|
||||
GLuint shaders[2] = {0};
|
||||
shaders[0] = opengl_helper_make_shader(srgb_in_vshader, GL_VERTEX_SHADER);
|
||||
shaders[1] = opengl_helper_make_shader(srgb_in_fshader, GL_FRAGMENT_SHADER);
|
||||
srgb_in_program = opengl_helper_make_program(shaders, 2);
|
||||
srgb_in_u_view_xform = glGetUniformLocation(basic_program, "u_view_xform");
|
||||
}
|
||||
|
||||
//- setup texture shader program
|
||||
{
|
||||
GLuint shaders[2] = {0};
|
||||
shaders[0] = opengl_helper_make_shader(texture_vshader, GL_VERTEX_SHADER);
|
||||
shaders[1] = opengl_helper_make_shader(texture_fshader, GL_FRAGMENT_SHADER);
|
||||
texture_program = opengl_helper_make_program(shaders, 2);
|
||||
texture_u_view_xform = glGetUniformLocation(texture_program, "u_view_xform");
|
||||
texture_u_texture = glGetUniformLocation(texture_program, "u_texture");
|
||||
}
|
||||
|
||||
//- vertex array object
|
||||
{
|
||||
GLuint vao = 0;
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
//- vertex array buffer
|
||||
{
|
||||
GLuint vertex_buffer = 0;
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
}
|
||||
|
||||
//- canvas texture
|
||||
{
|
||||
glGenTextures(1, &canvas_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, canvas_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2048, 2048, 0,
|
||||
GL_RGB, GL_FLOAT, 0);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
//- canvas framebuffer
|
||||
{
|
||||
glGenFramebuffers(1, &canvas_framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, canvas_framebuffer);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
canvas_texture, 0);
|
||||
}
|
||||
|
||||
//- test3 texture
|
||||
{
|
||||
U8 test3_img[16*3] = {0};
|
||||
for (U32 i = 0; i < 16; i += 1){
|
||||
U32 i3 = 3*i;
|
||||
for (U32 j = 0; j < 3; j += 1){
|
||||
test3_img[i3 + j] = 0x08 + 0x10*i;
|
||||
}
|
||||
}
|
||||
|
||||
glGenTextures(1, &test3_texture);
|
||||
glBindTexture(GL_TEXTURE_2D, test3_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8, 16, 1, 0,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, test3_img);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
//- check for setup errors
|
||||
if (glGetError() != 0){
|
||||
error_message("error in opengl renderer initialization");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
opengl_draw_test_geometry(Vertex *v, U64 count){
|
||||
opengl_draw_basic_geometry(Vertex *v, U64 count){
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(*v)*count, v, GL_STREAM_DRAW);
|
||||
|
||||
glUseProgram(test_program);
|
||||
glUniform2f(test_u_view_xform, 2.f/graphics_w, 2.f/graphics_h);
|
||||
glUseProgram(basic_program);
|
||||
glUniform2f(basic_u_view_xform, 2.f/graphics_w, 2.f/graphics_h);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, 0,
|
||||
|
@ -284,6 +494,46 @@ opengl_draw_test_geometry(Vertex *v, U64 count){
|
|||
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||
}
|
||||
|
||||
static void
|
||||
opengl_draw_srgb_in_geometry(Vertex *v, U64 count){
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(*v)*count, v, GL_STREAM_DRAW);
|
||||
|
||||
glUseProgram(srgb_in_program);
|
||||
glUniform2f(srgb_in_u_view_xform, 2.f/graphics_w, 2.f/graphics_h);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, 0,
|
||||
sizeof(Vertex), PtrOffsetOf(Vertex, px));
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 4, GL_FLOAT, 0,
|
||||
sizeof(Vertex), PtrOffsetOf(Vertex, cr));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||
}
|
||||
|
||||
static void
|
||||
opengl_draw_texture_geometry(Vertex *v, U64 count, U32 texture){
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(*v)*count, v, GL_STREAM_DRAW);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glUseProgram(texture_program);
|
||||
glUniform2f(texture_u_view_xform, 2.f/graphics_w, 2.f/graphics_h);
|
||||
glUniform1i(texture_u_texture, 0);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, 0,
|
||||
sizeof(Vertex), PtrOffsetOf(Vertex, px));
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, 0,
|
||||
sizeof(Vertex), PtrOffsetOf(Vertex, uvx));
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
|
@ -315,14 +565,24 @@ WinMain(HINSTANCE hInstance,
|
|||
}
|
||||
|
||||
// screen layout
|
||||
F32 margin = 10.f;
|
||||
F32 center_x = graphics_w*0.5f;
|
||||
F32 divider_half_w = 3.f;
|
||||
F32 divider_min_x = (F32)(S32)(center_x - divider_half_w);
|
||||
F32 divider_max_x = divider_min_x + 2.f*divider_half_w;
|
||||
|
||||
// render
|
||||
F32 lside_grad_x0 = 352.f;
|
||||
F32 lside_grad_x1 = lside_grad_x0 + 256.f;
|
||||
F32 rside_grad_x0 = 1312.f;
|
||||
F32 rside_grad_x1 = rside_grad_x0 + 256.f;
|
||||
|
||||
F32 test1_y = graphics_h - 10.f;
|
||||
F32 test2_y = graphics_h - 60.f;
|
||||
F32 test3_y = graphics_h - 110.f;
|
||||
F32 test4_y = graphics_h - 160.f;
|
||||
|
||||
// render to canvas frame buffer
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, canvas_framebuffer);
|
||||
glViewport(0, 0, (S32)graphics_w, (S32)graphics_h);
|
||||
|
||||
// black background everywhere
|
||||
|
@ -345,9 +605,228 @@ WinMain(HINSTANCE hInstance,
|
|||
v[i].ca = 1.f;
|
||||
}
|
||||
|
||||
opengl_draw_test_geometry(v, 6);
|
||||
opengl_draw_basic_geometry(v, 6);
|
||||
}
|
||||
|
||||
// two sided test
|
||||
for (U32 test_idx = 0; test_idx < 2; test_idx += 1){
|
||||
F32 grad_x0 = lside_grad_x0;
|
||||
F32 grad_x1 = lside_grad_x1;
|
||||
if (test_idx == 1){
|
||||
grad_x0 = rside_grad_x0;
|
||||
grad_x1 = rside_grad_x1;
|
||||
}
|
||||
|
||||
// 1: draw gradient
|
||||
{
|
||||
F32 grad_y1 = test1_y;
|
||||
F32 grad_y0 = test1_y - 40.f;
|
||||
|
||||
Vertex v[6];
|
||||
v[0].px = grad_x0; v[0].py = grad_y0;
|
||||
v[1].px = grad_x0; v[1].py = grad_y1;
|
||||
v[2].px = grad_x1; v[2].py = grad_y0;
|
||||
v[3].px = v[1].px; v[3].py = v[1].py;
|
||||
v[4].px = v[2].px; v[4].py = v[2].py;
|
||||
v[5].px = grad_x1; v[5].py = grad_y1;
|
||||
for (U32 i = 0; i < 6; i += 1){
|
||||
if (v[i].px == grad_x0){
|
||||
v[i].cr = 1.f; v[i].cg = 1.f; v[i].cb = 1.f; v[i].ca = 1.f;
|
||||
}
|
||||
else{
|
||||
v[i].cr = 0.f; v[i].cg = 0.f; v[i].cb = 0.f; v[i].ca = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
opengl_draw_basic_geometry(v, 6);
|
||||
}
|
||||
|
||||
// 2: draw extremes and midpoint
|
||||
{
|
||||
F32 box_x[4] = {0};
|
||||
box_x[0] = grad_x0;
|
||||
box_x[1] = (F32)(S32)((grad_x0*2.f + grad_x1)/3.f);
|
||||
box_x[2] = (F32)(S32)((grad_x0 + grad_x1*2.f)/3.f);
|
||||
box_x[3] = grad_x1;
|
||||
|
||||
F32 val[3] = { 1.f, 0.5f, 0.f };
|
||||
|
||||
F32 grad_y1 = test2_y;
|
||||
F32 grad_y0 = test2_y - 40.f;
|
||||
|
||||
for (U32 j = 0; j < 3; j += 1){
|
||||
F32 box_x0 = box_x[j];
|
||||
F32 box_x1 = box_x[j + 1];
|
||||
|
||||
F32 valj = val[j];
|
||||
|
||||
Vertex v[6];
|
||||
v[0].px = box_x0; v[0].py = grad_y0;
|
||||
v[1].px = box_x0; v[1].py = grad_y1;
|
||||
v[2].px = box_x1; v[2].py = grad_y0;
|
||||
v[3].px = v[1].px; v[3].py = v[1].py;
|
||||
v[4].px = v[2].px; v[4].py = v[2].py;
|
||||
v[5].px = box_x1; v[5].py = grad_y1;
|
||||
for (U32 i = 0; i < 6; i += 1){
|
||||
v[i].cr = valj; v[i].cg = valj; v[i].cb = valj; v[i].ca = 1.f;
|
||||
}
|
||||
|
||||
opengl_draw_basic_geometry(v, 6);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 3: compare x^2.2 with texture sampling for (sRGB -> Linear)
|
||||
if (test_idx == 1){
|
||||
F32 grad_y2 = test3_y;
|
||||
F32 grad_y1 = test3_y - 20.f;
|
||||
F32 grad_y0 = test3_y - 40.f;
|
||||
|
||||
// convert (sRGB -> Linear) by texture sampling
|
||||
{
|
||||
Vertex v[6];
|
||||
v[0].px = grad_x0; v[0].py = grad_y1;
|
||||
v[0].uvx = 0.f; v[0].uvy = 1.f;
|
||||
v[1].px = grad_x0; v[1].py = grad_y2;
|
||||
v[1].uvx = 0.f; v[1].uvy = 0.f;
|
||||
v[2].px = grad_x1; v[2].py = grad_y1;
|
||||
v[2].uvx = 1.f; v[2].uvy = 1.f;
|
||||
v[5].px = grad_x1; v[5].py = grad_y2;
|
||||
v[5].uvx = 1.f; v[5].uvy = 0.f;
|
||||
|
||||
v[3] = v[1];
|
||||
v[4] = v[2];
|
||||
|
||||
opengl_draw_texture_geometry(v, 6, test3_texture);
|
||||
}
|
||||
|
||||
// convert (sRGB -> Linear) by pow(x, 2.2) in shader
|
||||
{
|
||||
F32 delta_x = (grad_x1 - grad_x0)/16.f;
|
||||
|
||||
for (U32 i = 0; i < 16; i += 1){
|
||||
F32 l = (F32)(S32)(grad_x0 + i*delta_x);
|
||||
F32 r = (F32)(S32)(l + delta_x);
|
||||
|
||||
Vertex v[6];
|
||||
v[0].px = l; v[0].py = grad_y0;
|
||||
v[1].px = l; v[1].py = grad_y1;
|
||||
v[2].px = r; v[2].py = grad_y0;
|
||||
v[5].px = r; v[5].py = grad_y1;
|
||||
v[3] = v[1];
|
||||
v[4] = v[2];
|
||||
|
||||
F32 val = (F32)(0x08 + 0x10*i)/255.f;
|
||||
for (U32 j = 0; j < 6; j += 1){
|
||||
v[j].cr = val;
|
||||
v[j].cg = val;
|
||||
v[j].cb = val;
|
||||
v[j].ca = 1.f;
|
||||
}
|
||||
|
||||
opengl_draw_srgb_in_geometry(v, 6);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 4: color gradient
|
||||
{
|
||||
F32 color_pairs[12][3] = {
|
||||
{1.f, 0.f, 0.f}, {1.f, 1.f, 0.f},
|
||||
{1.f, 1.f, 0.f}, {0.f, 1.f, 0.f},
|
||||
{0.f, 1.f, 0.f}, {0.f, 1.f, 1.f},
|
||||
{0.f, 1.f, 1.f}, {0.f, 0.f, 1.f},
|
||||
{0.f, 0.f, 1.f}, {1.f, 0.f, 1.f},
|
||||
{1.f, 0.f, 1.f}, {1.f, 0.f, 0.f},
|
||||
};
|
||||
|
||||
F32 cursor_y = test4_y;
|
||||
|
||||
for (U32 j = 0; j < 12; j += 2){
|
||||
F32 grad_y1 = cursor_y;
|
||||
F32 grad_y0 = cursor_y - 20.f;
|
||||
cursor_y -= 30.f;
|
||||
|
||||
F32 *col[2] = {0};
|
||||
col[0] = color_pairs[j];
|
||||
col[1] = color_pairs[j + 1];
|
||||
|
||||
Vertex v[6];
|
||||
v[0].px = grad_x0; v[0].py = grad_y0;
|
||||
v[1].px = grad_x0; v[1].py = grad_y1;
|
||||
v[2].px = grad_x1; v[2].py = grad_y0;
|
||||
v[3].px = v[1].px; v[3].py = v[1].py;
|
||||
v[4].px = v[2].px; v[4].py = v[2].py;
|
||||
v[5].px = grad_x1; v[5].py = grad_y1;
|
||||
for (U32 i = 0; i < 6; i += 1){
|
||||
U32 k = 0;
|
||||
if (v[i].px == grad_x1){
|
||||
k = 1;
|
||||
}
|
||||
v[i].cr = col[k][0];
|
||||
v[i].cg = col[k][1];
|
||||
v[i].cb = col[k][2];
|
||||
v[i].ca = 1.f;
|
||||
}
|
||||
|
||||
if (test_idx == 0){
|
||||
opengl_draw_basic_geometry(v, 6);
|
||||
}
|
||||
else{
|
||||
opengl_draw_srgb_in_geometry(v, 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// resolve canvas to screen
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, canvas_framebuffer);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
S32 w = (S32)graphics_w;
|
||||
S32 h = (S32)graphics_h;
|
||||
|
||||
// left side resolve *without* GL_FRAMEBUFFER_SRGB
|
||||
glBlitFramebuffer(0, 0, w/2, h,
|
||||
0, 0, w/2, h,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
// right side resolve *with* GL_FRAMEBUFFER_SRGB
|
||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
glBlitFramebuffer(w/2, 0, w, h,
|
||||
w/2, 0, w, h,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
// after render numerical value checks
|
||||
{
|
||||
// 1: each value differs from it's neighbors by exactly 1
|
||||
// (w/ 4-byte stride; alpha channel not included)
|
||||
U8 buf[256*4] = {0};
|
||||
glReadPixels((S32)lside_grad_x0, (S32)test1_y - 5, 256, 1,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
||||
for (U32 i = 1; i < 256; i += 1){
|
||||
Assert(buf[(i - 1)*4] - 1 == buf[i*4]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// check for gl errors from this frame
|
||||
if (glGetError() != 0){
|
||||
error_message("error in opengl frame render");
|
||||
}
|
||||
|
||||
// end render
|
||||
|
@ -519,7 +998,7 @@ w32_graphics_window_proc(HWND wnd,
|
|||
w32_wglMakeCurrent(dc, graphics_context);
|
||||
|
||||
// render
|
||||
glClearColor(1.f, 0.f, 1.f, 1.f);
|
||||
glClearColor(0.f, 0.f, 0.f, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// end render
|
||||
|
|
Loading…
Reference in New Issue