QuelSolaar/betray_plugin_Hald_Clut.c

252 lines
6.4 KiB
C

#include "betray_plugin_api.h"
#include "relinquish.h"
#include <stdio.h>
#include <math.h>
uint texture_id = 0;
uint hald_clut_id = 0;
uint depth_id = 0;
uint fbo_id = 0;
uint screen_size[2] = {0, 0};
RShader *clut_lookup_shader = NULL;
void *clut_surface_pool = NULL;
char *clut_lookup_vertex =
"attribute vec4 vertex;"
"uniform mat4 ModelViewProjectionMatrix;"
"varying vec2 mapping;"
"void main()"
"{"
" mapping = vertex.ba;"
" gl_Position = ModelViewProjectionMatrix * vec4(vertex.xy, 0.0, 1.0);"
"}";
char *clut_lookup_fragment =
"uniform sampler2D image;"
"uniform sampler3D clut;"
"varying vec2 mapping;"
"void main()"
"{"
" vec4 sample;"
" sample = texture2D(image, mapping);"
" gl_FragColor = texture3D(clut, sample.rgb);"
"}";
void save_targa(char *file_name, uint8 *data, unsigned int x, unsigned int y)
{
FILE *image;
char *foot = "TRUEVISION-XFILES.";
unsigned int i, j;
if((image = fopen(file_name, "wb")) == NULL)
{
printf("Could not create file: %s\n", file_name);
return;
}
fputc(0, image);
fputc(0, image);
fputc(2, image); /* uncompressed */
for(i = 3; i < 12; i++)
fputc(0, image); /* ignore some stuff */
fputc(x % 256, image); /* size */
fputc(x / 256, image);
fputc(y % 256, image);
fputc(y / 256, image);
fputc(24, image); /* 24 bit image */
for(j = 0; j < y; j++)
{
for(i = 0; i < x; i++)
{
fputc(data[((y - j - 1) * x + i) * 3 + 0], image);
fputc(data[((y - j - 1) * x + i) * 3 + 2], image);
fputc(data[((y - j - 1) * x + i) * 3 + 1], image);
}
}
for(i = 0; i < 9; i++)
fputc(0, image);
for(i = 0; foot[i] != 0; i++)
fputc(foot[i], image);
fputc(0, image);
fclose(image);
}
uint8 *load_targa(char *file_name, unsigned int *x, unsigned int *y)
{
FILE *image;
uint8 *draw = NULL;
unsigned int i, j, identfeald, type, x_size, y_size, alpha;
if((image = fopen(file_name, "rb")) == NULL)
{
printf("can not open file: %s\n", file_name);
return NULL;
}
identfeald = fgetc(image);
if(0 != fgetc(image))
{
printf("Error: File %s a non suported palet image\n", file_name);
return NULL;
}
type = fgetc(image);
if(2 != type) /* type must be 2 uncompressed RGB */
{
printf("Error: File %s is not a uncompressed RGB image\n", file_name);
return NULL;
}
for(i = 3; i < 12; i++)
fgetc(image); /* ignore some stuff */
x_size = fgetc(image);
x_size += 256 * fgetc(image);
y_size = fgetc(image);
y_size += 256 * fgetc(image);
alpha = fgetc(image);
if(alpha != 24 && alpha != 32) /* type must be 24 or 32 bits RGB */
{
printf("Error: File %s is not a 24 or 32 bit RGB image\n", file_name);
return NULL;
}
for(i = 0; i < identfeald; i++)
fgetc(image); /* ignore some stuff */
*x = x_size;
*y = y_size;
draw = malloc((sizeof *draw) * x_size * y_size * 3);
for(j = 0; j < y_size * x_size * 3; j++)
draw[j] = 0;
if(alpha == 32)
{
for(j = 0; j < y_size; j++)
{
for(i = 0; i < x_size; i++)
{
fgetc(image); /* ignore alpha */
draw[((y_size - j - 1) * x_size + i) * 3 + 2] = fgetc(image);
draw[((y_size - j - 1) * x_size + i) * 3 + 1] = fgetc(image);
draw[((y_size - j - 1) * x_size + i) * 3 + 0] = fgetc(image);
}
}
}else for(j = 0; j < y_size; j++)
{
for(i = 0; i < x_size; i++)
{
draw[((y_size - j - 1) * x_size + i) * 3 + 0] = fgetc(image);
draw[((y_size - j - 1) * x_size + i) * 3 + 2] = fgetc(image);
draw[((y_size - j - 1) * x_size + i) * 3 + 1] = fgetc(image);
}
}
fclose(image);
return draw;
}
boolean betray_plugin_image_warp(BInputState *input)
{
static uint seed = 0;
RMatrix matrix;
float f;
uint x, y, i;
seed++;
f = betray_plugin_screen_mode_get(&x, &y, NULL);
if(screen_size[0] != x || screen_size[1] != y)
{
float surface[6 * 4] = {-1, -1, 0, 0,
1, -1, 1, 0,
1, 1, 1, 1,
-1, -1, 0, 0,
1, 1, 1, 1,
-1, 1, 0, 1};
for(i = 0; i < 6; i++)
surface[i * 4 + 1] *= f;
screen_size[0] = x;
screen_size[1] = y;
if(texture_id != 0)
r_texture_free(texture_id);
if(depth_id != 0)
r_texture_free(depth_id);
if(fbo_id != 0)
r_framebuffer_free(fbo_id);
texture_id = r_texture_allocate(R_IF_RGB_UINT8, x, y, 1, TRUE, TRUE, NULL);
depth_id = r_texture_allocate(R_IF_DEPTH32, x, y, 1, TRUE, TRUE, NULL);
fbo_id = r_framebuffer_allocate(&texture_id, 1, depth_id, RELINQUISH_TARGET_2D_TEXTURE);
r_array_load_vertex(clut_surface_pool, NULL, surface, 0, 6);
}
betray_plugin_application_draw(fbo_id, x, y, NULL, FALSE, NULL);
r_viewport(0, 0, x, y);
r_matrix_set(&matrix);
r_matrix_identity(&matrix);
r_matrix_frustum(&matrix, -0.01, 0.01, -0.01 * f, 0.01 * f, 0.01, 100.0);
glClearColor(0, 0, 1, 1);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
r_matrix_translate(&matrix, 0, 0, -1.0);
r_shader_set(clut_lookup_shader);
r_shader_texture_set(clut_lookup_shader, 0, texture_id);
r_shader_texture_set(clut_lookup_shader, 1, hald_clut_id);
r_array_section_draw(clut_surface_pool, NULL, GL_TRIANGLES, 0, 6);
return TRUE;
}
void betray_plugin_init(void)
{
char *file_name = "Betray_hald_clut.tga";
unsigned int i, j, k, size, level = 16, x, y;
uint8 *data, *p;
RFormats vertex_format_types = R_FLOAT;
uint vertex_format_size = 4;
betray_plugin_callback_set_image_warp(betray_plugin_image_warp, "Hald Clut CC");
data = load_targa(file_name, &x, &y);
if(data == NULL)
{
level = 8;
size = level * level;
data = p = malloc((sizeof *data) * size * size * size * 3);
for(i = 0; i < size; i++)
{
for(j = 0; j < size; j++)
{
for(k = 0; k < size; k++)
{
*p++ = (uint8)(k * 256 / size);
*p++ = (uint8)(j * 256 / size);
*p++ = (uint8)(i * 256 / size);
}
}
}
save_targa(file_name, data, level * level * level, level * level * level);
printf("Hald CLUT with level %u created, %u by %u pixels size, file name: %s\n", level, size * level, size * level, file_name);
return;
}
if(x != y)
{
printf("Betray Plugin Error: Hald CLUT not sqare\n");
return;
}
for(i = 0; i * i * i < x * y; i++);
if(i * i * i != x * y)
{
printf("Betray Plugin Error: Hald CLUT size error\n");
return;
}
printf("Hald CLUT Loaded\n");
r_init(betray_plugin_gl_proc_address_get());
hald_clut_id = r_texture_allocate(R_IF_RGB_UINT8, i, i, i, TRUE, FALSE, data);
free(data);
clut_lookup_shader = r_shader_create_simple(NULL, 0, clut_lookup_vertex, clut_lookup_fragment, "Clut Lookup shader");
clut_surface_pool = r_array_allocate(6, &vertex_format_types, &vertex_format_size, 1, 0);
}